Search code examples
node.jsexpressjestjssupertestformidable

Files not being sent in a multipart form when testing endpoint using Jest Supertest Formidable


I'm trying to test an endpoint that should receive a multipart/form-data. I'm sending a collection of images, which i want to process and save on the server or CDN. I'm using Jest, Express and Formidable.

Endpoint

router.post("/videos", async (req, res) => {

  new formidable.IncomingForm().parse(req, (err, fields, files) => {
    console.log('PARSE FORM');
    if (err) {
      console.error('Error', err);
      throw err
    }
    console.log('Fields', fields);
    console.log('Files', files);
    for (const file of Object.entries(files)) {
      console.log('FILE', file)
    }
  });

  res.status(200).send('Created Video');
});

Test

describe("Video Endpoints", () => {
  it('should create a new timelapse video', done => {
    request
      .post('/api/videos')
      .field('file', 'some random value')
      .attach('image', `${__dirname}/__mocks__/image.png`)
      .then(res => {
        console.log('THEN');
        done();
      })
  });
});

When running the test it doesn't reach the formidable parse method.

If change my my attach method to this...

.attach('image', fs.readFileSync(`${__dirname}/__mocks__/xdebugcurlaccessingwpapi.png`))

It will reach the parse method but it sees the it as field and not a file.

If i make the same request but from my react app using fetch, it works perfectly fine.

What am i doing wrong? Been on this for a few days now lol.

Any help would be great.

Thanks.


Solution

  • I'm not entirely sure why but if you add

    .set({connection: 'keep-alive'})
    

    Then it works.

    Final solution

    request
      .post('/api/videos')
      .set({connection: 'keep-alive'})
      .field('name', 'Richard')
      .attach('image', mockImage)
      .then(res => {
        console.log('THEN');
        done();
      });
    });
    

    Would be good if someone has an understanding to why this is the case.

    I think it might close the stream to image but can't be sure.