testing-library / dom-testing-library

🐙 Simple and complete DOM testing utilities that encourage good testing practices.
https://testing-library.com/dom
MIT License
3.26k stars 466 forks source link

ReferenceError: process is not defined when using with karma, webpack, and jasmine #1180

Open jattasNI opened 1 year ago

jattasNI commented 1 year ago

Relevant code or config:

In a Jasmine test:

import screen from '@testing-library/dom';

What you did:

Execute the test suite in Chromium using karma:

karma start karma.conf.js --browsers=ChromeHeadlessOpt --single-run

The karma.conf.js uses karma-webpack to bundle the tests.

What happened:

When evaluating the @testing-library/dom import, some code that @testing-library/dom imports assumes that it is running in a Node environment and tries to access the process variable. It's not defined since the test is running in a browser environment, so we get this error:

An error was thrown in afterAll
  Uncaught ReferenceError: process is not defined
  ReferenceError: process is not defined
      at Object.push.b (/var/folders/3h/v_p6s_s50s39ydrwn9r7r4300000gn/T/_karma_webpack_545704/webpack:/node_modules/react-is/index.js:3:1)
      at __webpack_require__ (http://localhost:9876/webpack:/@ni/nimble-components/webpack/bootstrap:19:1)
      at Object.<anonymous> (/var/folders/3h/v_p6s_s50s39ydrwn9r7r4300000gn/T/_karma_webpack_545704/webpack:/node_modules/@testing-library/dom/node_modules/pretty-format/build/plugins/ReactElement.js:8:39)
      at __webpack_require__ (http://localhost:9876/webpack:/@ni/nimble-components/webpack/bootstrap:19:1)
      at Object.<anonymous> (/var/folders/3h/v_p6s_s50s39ydrwn9r7r4300000gn/T/_karma_webpack_545704/webpack:/node_modules/@testing-library/dom/node_modules/pretty-format/build/index.js:26:44)
      at __webpack_require__ (http://localhost:9876/webpack:/@ni/nimble-components/webpack/bootstrap:19:1)
      at Object.push.__webpack_unused_export__.value (/var/folders/3h/v_p6s_s50s39ydrwn9r7r4300000gn/T/_karma_webpack_545704/commons.js:18062:13)
      at __webpack_require__ (http://localhost:9876/webpack:/@ni/nimble-components/webpack/bootstrap:19:1)
      at Object.push.__webpack_require__.d.ListOption (/var/folders/3h/v_p6s_s50s39ydrwn9r7r4300000gn/T/_karma_webpack_545704/commons.js:13638:15)
      at __webpack_require__ (http://localhost:9876/webpack:/@ni/nimble-components/webpack/bootstrap:19:1)

Reproduction:

I have a reproduction in my project repo which I could share or try to pare down if needed, but I wanted to start the discussion first to ensure this seems like something that maintainers think should and could be fixed in this repo.

Problem description:

The code that tries to access process is in react-isindex.js.

That code is pulled in because @testing-library/dom is importing everything from pretty-format which includes its React support.

My project doesn't use React at all so it would be nice if the React code could be tree shaken away.

Suggested solution:

This is similar to https://github.com/testing-library/angular-testing-library/issues/244 in angular-testing-library which I believe was fixed by guarding against accessing the process variable. However since the code that's accessing process is not part of testing-library, that fix doesn't seem feasible here. If we can't come up with a fix in testing-library then we could consider filing a bug to pretty-format or react-is asking them to do this.

I'd hope testing-library could sever this dependency chain somewhere when a test suite isn't using React but I'm not sure what the right place to do this would be.

Workaround

Define process globally so that the code that accesses it doesn't fail. Once the react-is code gets past the place that it tries to access process, it isn't needed so using a stubbed process is ok.

In setup.ts which is part of the files array in karma.conf.js, add code like:

window.process = {
    env: {
        NODE_ENV: 'production'
    }
};
juanca commented 1 year ago

Is it possible to use https://webpack.js.org/plugins/environment-plugin/ ?

jattasNI commented 1 year ago

Thanks for the idea @juanca! I verified that I can use environment plugin in our karma-webpack config and it has a similar effect as the workaround I listed in the description (and I like it better because it's using an official webpack API rather than messing with the global scope).

// karma.conf.js
const webpackEnvironmentPlugin = new webpack.EnvironmentPlugin({ NODE_ENV: 'production' });
module.exports = config => {
    const options = {
        webpack: {
            plugins: [ webpackEnvironmentPlugin ]
        }
    }
}

However for my use case I think I'd still call it a workaround. I'm a library developer trying to leverage testing-library to provide better testing utilities for my library's clients. I'd like to avoid having to tell my clients that they need to configure their build in a particular way in order to use my library's testing utilities. It would be cleaner if testing-library didn't pull in a dependency that required that. (I acknowledge that the dependency presumably provides value and it wouldn't be trivial to remove it, just speaking as someone trying to build a library that clients can treat as a "black box").