Pesquisa de site

typescript - Jest não irá transformar o módulo - SyntaxError: Cannot use import statement outside a module


Não consegui me livrar deste erro SyntaxError: Cannot use import statement outside a module não importa o que eu tenha tentado e isso ficou tão frustrante. Alguém aqui já resolveu esse problema? Eu li um milhão de tópicos no Stack Overflow e issues no GitHub. Nenhuma solução clara.

Este é um projeto React, Typescript, Webpack. Estou tentando testar um módulo. Mas o Jest não irá transformar o módulo em javascript puro de alguma forma.

O erro que recebo é

/Users/me/dev/Project/project/node_modules/variables/src/variables.js:12
    import './main.js';
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      17 | 
      18 | */
    > 19 | import { GlobalVars } from 'variables'
         | ^
      20 | 
      21 | export const Vars = new GlobalVars()
      22 | 

O que eu tentei para resolver isso (e não funcionou):

  • Usando a configuração env em babel.config: env.test.preset: ['@babel/plugin-transform-modules-commonjs']

  • modificando a configuração transform no Jest como '^.+\\.jsx?$': 'babel-jest', '^.+\\.tsx?$': 'ts-jest' e todas as outras possibilidades relacionadas a isso.

  • Na configuração do Jest, testPathIgnorePatterns, transformIgnorePatterns

  • Usando .babel.config.js em vez de .babelrc.js

...e mais.

Eu tenho esta configuração:

package.json

  "jest": {
    "preset": "ts-jest",
    "testEnvironment": "node"
  }

.babelrc.js

module.exports = {
  presets: [
    ['@babel/preset-env', { targets: { node: 'current' } }],
    '@babel/preset-react',
    '@babel/preset-typescript',
  ],
  plugins: [
    '@babel/plugin-transform-runtime',
    '@babel/proposal-class-properties',
    '@babel/transform-regenerator',
    '@babel/plugin-transform-template-literals',
    'react-hot-loader/babel',
  ],
}

variables.ts

import { GlobalVars } from 'variables'

export const Vars = new GlobalVars()

variables.spec.ts

import { Vars } from './variables.ts'

describe('Test The Package', () => {
  it('Should accept new variables', () => {
    Vars.newVariable = 'new variable'
    expect(Vars.newVariable).toEqual('new variable')
  })
})

Alguma ideia de como resolver esse problema?

Resposta #1

Embora eu os tenha testado separadamente, ainda não os testei juntos (transform e transformIgnorePatterns). Então, esta configuração do jest resolveu meu problema:

  "jest": {
    "preset": "ts-jest",
    "testEnvironment": "node",
    "transform": {
      "node_modules/variables/.+\\.(j|t)sx?$": "ts-jest"
    },
    "transformIgnorePatterns": [
      "node_modules/(?!variables/.*)"
    ]
  },

Meus erros foram:

  1. Não usar transform e transformIgnorePatterns juntos.
  2. E definir babel-jest como o transformador em vez de ts-jest (eu acho que isso é um problema quando o preset do jest é definido como ts-jest. Porque se eu mudar para babel-jest ele lança o mesmo erro novamente.):
--- "node_modules/variables/.+\\.(j|t)sx?$": "babel-jest"
+++ "node_modules/variables/.+\\.(j|t)sx?$": "ts-jest"

Resposta #2

Use Vitest.

Eu tentei a maioria das sugestões feitas aqui. Achei o Jest bastante doloroso de instalar corretamente, enquanto o Vitest funciona imediatamente sem nenhuma configuração. Esta é a minha experiência pessoal. Demorei dias para fazer o Jest funcionar mais ou menos. Eu tinha o Vitest funcionando imediatamente após a instalação.

Eu não quero falar mal do Jest, na verdade eu acho que é uma ferramenta de testes maravilhosa e intuitiva. Mas, no final das contas, o Vitest "Simplesmente Funciona" (tm), e você pode usar a mesma API de estilo Jest simples que todos nós aprendemos a amar.

Passos (eu uso pnpm, mas claro que você poderia fazer o mesmo com yarn ou npm):

pnpm remove jest ts-jest @types/jest
pnpm add -D vite vitest

Exclua jest.config.js e crie vite.config.ts:

/// <reference types="vitest" />

import { defineConfig } from 'vite'

export default defineConfig({
  test: {
    /* for example, use global to avoid globals imports (describe, test, expect): */
    // globals: true,
  },
})

Adicione aos seus testes:

import { assert, expect, test } from 'vitest'

Atualize seu package.json:

"test": "vitest",

Resposta #3

Meu problema era diferente de uma forma que o jest encontraria dificuldades em arquivos .js de uma das dependências no node_modules com SyntaxError: Cannot use import statement outside a module.

Eu tive que ter certeza de que ts-jest não iria ignorar (ao transformar) arquivos .js em uma dependência problemática.

Depois de ler atentamente sobre os presets, percebi que ele os deixa 'como estão' com preset: 'ts-jest'. Eu mudei para preset: 'ts-jest/presets/js-with-ts' e defini "allowJs": true em tsconfig.json.

Para não bagunçar o tsconfig.json do meu projeto, eu tenho um separado para o jest.

No final, meu jest.config.js se parece principalmente com isto:

module.exports = {
    preset: 'ts-jest/presets/js-with-ts',
    testEnvironment: "node",
    globals: {
        'ts-jest': {
            tsconfig: '<rootDir>/test/tsconfig.json',
        },
    },
    transformIgnorePatterns: [
        "node_modules/(?!troublesome-dependency/.*)",
    ],
}

P.S. Eu não precisei de um campo transform, já que o preset já está nele.

P.P.S. Eu não precisei configurar nenhum babel

Resposta #4

Como o Jest não está funcionando bem com esmodules, você precisa adicionar essas configurações em jest.config.js para dizer ao Jest para usar builds commonJS em vez disso

moduleNameMapper: {
  '^variables$': 'variables/dist/cjs',
  '^[NAME OF MODULE YOU WANT TO IMPORT]$': '[NAME OF MODULE YOU WANT TO IMPORT]/dist/cjs'
}

Artigos relacionados