javascriptjestjsbabel-jest

Babel and Jest configuration: SyntaxError: Cannot use import statement outside a module


I'm working on a Ruby on Rails 7 app with a few JS web components written using lit element. I'm trying to add Jest to the project so we can unit test our web components.

Not using Typescript, just vanilla JS. I'm running node v18.12.1, npm v9.2.0.

I followed the initial Jest getting started steps from their site:

npm install --save-dev jest

Then added "scripts": { "test": "jest" } to package.json.

I created a simple test to try it out and it passed without error.

However, once I added a test for one of my custom web components that imports lit (import {LitElement} from 'lit';), I got the following error:

Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    /home/app/service/app/javascript/test/utils/validators.test.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { IsNumber } from '../../utils/validators.js';
                                                                                      ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1495:14)

Reading the error (and checking here and with Dr Google) it sounded like using Babel was the way to go. So, I went to the Babel installation page for jest and followed their instructions:

npm install --save-dev babel-jest

Then added to package.json:

  "jest": {
    "transform": {
      "^.+\\.[t|j]sx?$": "babel-jest"
    }
  },
}

Then installed babel preset env:

npm install @babel/preset-env --save-dev

And add babel.config.json:

{
  "presets": ["@babel/preset-env"]
}

I continue to get the same error.

My package.json:

{
  "scripts": {
    "test": "jest"
  },
  "jest": {
    "transform": {
      "^.+\\.[t|j]sx?$": "babel-jest"
    }
  },
  "devDependencies": {
    "@babel/preset-env": "^7.20.2",
    "babel-jest": "^29.4.3",
    "jest": "^29.4.3",
    "lit": "^2.6.1"
  }
}

My babel.config.json:

{
  "presets": ["@babel/preset-env"]
}

Failing test:

import {SomeFunction} from '/a-valid-path/my-custom.js';

describe('some tests', () => {
  test('a test', () => {
    expect(SomeFunction(some-value)).toBe(true);
  });
});

There are other posts on this issue here on stack overflow. The solutions provided all seem to indicate I need to add some transform and transformIgnorePatterns settings to my jest configuration in package.json (or jest.config.js for those with a separate jest config file) in order to get the transpilation right.

For example here the recommended solution was:

"transform": {
      "node_modules/variables/.+\\.(j|t)sx?$": "ts-jest" //I swapped in 'babel-jest' here
    },
    "transformIgnorePatterns": [
      "node_modules/(?!variables/.*)"
    ]

And here it was

  transform: {
    "^.+\\.(js|ts)$": "ts-jest",
  },
  transformIgnorePatterns: [
    "node_modules/(?!lit-html)",
  ],

Here the solution was to add "type": "module" to package.json.

None of these or other solutions I've found here or on other sites have worked. I keep getting the same error.

Does anyone out there know what I'm missing?


Solution

  • It took some more trial and error, but I eventually resolved it by setting: "transformIgnorePatterns": [] in package.json.

    It appears that setting has to be present even though I'm not giving it a value. Removing transformIgnorePatterns entirely results in the same error.

    Final working configuration:

    Package.json:

    {
      "scripts": {
        "test": "jest"
      },
      "jest": {
        "transform": {
          "^.+\\.(js|ts)$": "babel-jest"
        },
        "transformIgnorePatterns": []
      },
      "devDependencies": {
        "@babel/preset-env": "^7.20.2",
        "babel-jest": "^29.4.3",
        "jest": "^29.4.3",
        "lit": "^2.6.1"
      }
    }
    

    Babel.config.json:

    {
      "presets": ["@babel/preset-env"]
    }