node-formidable / formidable

The most used, flexible, fast and streaming parser for multipart form data. Supports uploading to serverless environments, AWS S3, Azure, GCP or the filesystem. Used in production.
MIT License
7k stars 680 forks source link

TypeError when testing with Jest #886

Closed Sethlans closed 1 year ago

Sethlans commented 1 year ago

Context

What are you trying to achieve or the steps to reproduce?

I have created an express middleware to parse the raw data incoming from a multipart request. The middleware itself is working properly and doing its job. The issue is when I test my endpoint with jest. I get the error

TypeError: Cannot set property domain of [object process] which has only a getter

when calling form.parse() It looks like Jest put some limitations to the process object. The issue seems to be caused by the dependency asap requestFlush (/node_modules/asap/raw.js:83:40)

import formidable from 'formidable'
import { AppRequest } from '../../app-types'
import { NextFunction, Response } from 'express-async-router'
export const formMiddleWare = async (req: AppRequest, res: Response, next: NextFunction) => {
  const myPromise = new Promise<void>((resolve, reject) => {
    const form = formidable({
      keepExtensions: true,
      multiples: true,
    })

    const incomingPayload = {} as any
    form.onPart = (part) => {
      part.on('data', (buffer: Buffer) => {
        if (part.originalFilename && part.mimetype) {
          if (!incomingPayload.files) {
            incomingPayload.files = []
          }
          let currentFile = incomingPayload.files.find((obj: any) => {
            return obj.originalname === part.originalFilename && obj.mimetype === part.mimetype
          })
          if (!currentFile) {
            currentFile = {
              originalname: part.originalFilename,
              mimetype: part.mimetype,
              buffer: buffer,
            }
            incomingPayload.files.push(currentFile)
          } else {
            currentFile.buffer = Buffer.concat([currentFile.buffer, buffer])
          }
        } else {
          if (incomingPayload[part.name]) {
            incomingPayload[part.name] = Buffer.concat([incomingPayload[part.name], buffer])
          } else {
            incomingPayload[part.name] = buffer
          }
        }
      })
    }
    form.parse(req, async (err, fields, files) => {
      if (err) {
        console.log(err)
        req.logger.error('Could not parse incoming form', {
          payload: { ...req.body },
        })
        next(err)
        reject(err)
        return
      }
      req.body = incomingPayload
      next()
      resolve(null)
    })
  })

  return myPromise
}

What was the result you got?

Test failing due to an issue with a dependency

What result did you expect?

Test running correctly like when the service runs

tunnckoCore commented 1 year ago

Hey @Sethlans, sorry for the delay.

Sounds like some jest environment problem. No idea. We are using Jest for its tests too and don't have problems.

Maybe it could be because of the onPart override. But I don't think we have anything that does anything with process.

ziogas commented 1 year ago

For anyone looking, downgrading to Jest@26 fixed for me the TypeError: Cannot set property domain of [object process] which has only a getter error.

The error comes from the asap package: domain.active = process.domain = null; line.

It must be something with Jest@27 breaking changes. However, couldn't pinpoint what exactly.