Jest + @testing-library/react 在来自 [dom-accessibility-api] 库的 .mjs 文件上抛出错误
Jest + @testing-library/react throws error on a .mjs file from [dom-accessibility-api] library
我刚开始使用 Jest + @testing-library/react,在我第一次尝试时,我得到了第三方库错误(可能被 react-testing-library 使用),我不确定如何修复。
这是我对主要 React App.js 组件的测试。基本上我尝试用 Redux 存储来渲染它,然后验证 DOM 组件是否存在。非常简单:
import React from 'react';
import '@testing-library/jest-dom/extend-expect';
import { render } from '@testing-library/react';
import { App } from '../../../src/features/root/App';
import { Provider } from "react-redux";
import { createStore } from "redux";
import { initialState } from '../../../src/features/root/redux/initialState';
import { reducer } from '../../../src/features/root/redux/reducer';
const renderWithProviders = (ui, { reduxState } = {}) => {
const store = createStore(reducer, reduxState || initialState);
return render(<Provider store={store}>{ui}</Provider>);
}
describe('root/App', () => {
it('renders node with correct class name', () => {
const { getByTestId } = renderWithProviders(<App />, { });
const mainDiv = getByTestId('id-of-the-div');
expect(mainDiv).toBeDefined();
});
});
然而,当 运行 测试时,Jest 抛出以下错误:
Test suite failed to run
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
• 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/en/configuration.html
Details:
/sandbox/node_modules/dom-accessibility-api/dist/accessible-description.mjs:7
import { computeTextAlternative } from "./accessible-name-and-description.mjs";
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14)
at Object.<anonymous> (node_modules/dom-accessibility-api/sources/index.ts:1:1)
所以这里的重点是:
/sandbox/node_modules/dom-accessibility-api/dist/accessible-description.mjs:7
import { computeTextAlternative } from "./accessible-name-and-description.mjs";
^^^^^^
SyntaxError: Cannot use import statement outside a module
看起来那个特定的 .mjs 文件来自那个库 dom-accessibility-api 不能被 Jest 解析。但为什么会这样?在任何使用 react-testing-library 和 Jest 进行 React 测试的教程中,似乎都没有关于此的问题或提及。这是一个我一无所知的第三方库
有谁知道如何解决这个问题?
我的主要配置文件:
babel.config.js:
const presets = [
'react-app'
];
module.exports = { presets };
jest.config.js:(我尝试了很多选项和简化,但无济于事)
module.exports = {
reporters: [
"default",
"jest-junit"
],
coverageReporters: [
"lcov",
"text",
"cobertura"
],
collectCoverageFrom: [
"src/**/*.{js,jsx}"
],
setupFiles: [
"<rootDir>/tests/setup.js",
"jest-localstorage-mock",
"jest-canvas-mock"
],
snapshotSerializers: [
"enzyme-to-json/serializer"
],
testMatch: [
"<rootDir>/tests/**/*.test.js"
],
testEnvironment: "jsdom",
testURL: "http://localhost",
transform: {
"^.+\.(js|jsx)$": "babel-jest",
"^.+\.(ts|tsx|mjs)$": "ts-jest",
"^.+\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\.(js|jsx|mjs|css|json|ts)$)": "<rootDir>/config/jest/fileTransform.js"
},
transformIgnorePatterns: [
"[/\\]node_modules[/\\].+\.(js|jsx|mjs|ts|tsx)$"
],
testPathIgnorePatterns: ["<rootDir>/build/", "<rootDir>/node_modules/"],
moduleNameMapper: {
"^react-native$": "react-native-web"
},
moduleFileExtensions: [
"web.js",
"mjs",
"js",
"ts",
"json",
"web.jsx",
"jsx",
"node"
]
}
/tests/setup.js:(只是为了初始化 Enzyme 用于其他类型的测试)
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter(), disableLifecycleMethods: true });
/config/jest/fileTransform.js:
'use strict';
const path = require('path');
// This is a custom Jest transformer turning file imports into filenames.
// http://facebook.github.io/jest/docs/en/webpack.html
module.exports = {
process(src, filename) {
return `module.exports = ${JSON.stringify(path.basename(filename))};`;
},
};
package.json:(仅显示 devDependencies)
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"@babel/preset-typescript": "^7.12.7",
"@testing-library/jest-dom": "^5.11.9",
"@testing-library/react": "^11.2.3",
"axios-mock-adapter": "^1.15.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"babel-loader": "^8.2.2",
"babel-preset-react-app": "^10.0.0",
"babel-runtime": "^6.26.0",
"browser-refresh-taglib": "^1",
"case-sensitive-paths-webpack-plugin": "2.1.1",
"cross-env": "^5.2.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
"enzyme-to-json": "^3.6.1",
"eslint": "^7.17.0",
"eslint-config-react-app": "^6.0.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-flowtype": "^5.2.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"extract-text-webpack-plugin": "3.0.2",
"html-webpack-plugin": "2.29.0",
"jest": "^26.6.3",
"jest-canvas-mock": "^2.2.0",
"jest-junit": "^5.2.0",
"jest-localstorage-mock": "^2.3.0",
"jest-when": "^2.7.0",
"nock": "^9.2.3",
"optimizer-plugin-inc": "^4",
"query-string": "5.1.1",
"react-dev-utils": "^5.0.0",
"redux-mock-store": "^1.5.4",
"redux-thunk": "^2.3.0",
"sw-precache-webpack-plugin": "0.11.4",
"ts-jest": "^26.4.4",
"webpack": "3.8.1",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-dev-server": "2.9.4",
"webpack-hot-middleware": "^2.22.2",
"webpack-manifest-plugin": "1.3.2"
};
看来我找到了解决办法。
基于这个例子:react-redux
我更新并简化了我的 jest.config.js 如下:
const path = require('path')
module.exports = {
roots: [path.resolve(__dirname, './tests')],
reporters: [
"default",
"jest-junit"
],
coverageReporters: [
"lcov",
"text",
"cobertura"
],
collectCoverageFrom: [
"src/**/*.{js,jsx}"
],
setupFiles: [
path.resolve(__dirname, "./tests/setup.js"),
"jest-localstorage-mock",
"jest-canvas-mock"
],
setupFilesAfterEnv: [path.resolve(__dirname, './tests/setupAfterEnv.js')],
testMatch: [
"**/tests/**/*.test.js"
],
testURL: "http://localhost"
}
并添加了一个 setupAfterEnv.js 文件,只有这一行:
import '@testing-library/jest-dom/extend-expect'
到目前为止,测试现在可以通过了...
老实说,我仍然不确定为什么之前会出现该错误,我认为变化不大...
看来真正的解决方法是 remove/disable 代码转换。
关注 Jest 27.4 文档(当前版本):https://jestjs.io/docs/ecmascript-modules,
#1:确保您通过传递 transform: {}
来禁用代码转换,或者将您的转换器配置为发出 ESM 而不是默认的 CommonJS (CJS)。
这正是您在 jest.config.js 文件中所做的。
希望这有助于更好地理解问题!
我刚开始使用 Jest + @testing-library/react,在我第一次尝试时,我得到了第三方库错误(可能被 react-testing-library 使用),我不确定如何修复。
这是我对主要 React App.js 组件的测试。基本上我尝试用 Redux 存储来渲染它,然后验证 DOM 组件是否存在。非常简单:
import React from 'react';
import '@testing-library/jest-dom/extend-expect';
import { render } from '@testing-library/react';
import { App } from '../../../src/features/root/App';
import { Provider } from "react-redux";
import { createStore } from "redux";
import { initialState } from '../../../src/features/root/redux/initialState';
import { reducer } from '../../../src/features/root/redux/reducer';
const renderWithProviders = (ui, { reduxState } = {}) => {
const store = createStore(reducer, reduxState || initialState);
return render(<Provider store={store}>{ui}</Provider>);
}
describe('root/App', () => {
it('renders node with correct class name', () => {
const { getByTestId } = renderWithProviders(<App />, { });
const mainDiv = getByTestId('id-of-the-div');
expect(mainDiv).toBeDefined();
});
});
然而,当 运行 测试时,Jest 抛出以下错误:
Test suite failed to run
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
• 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/en/configuration.html
Details:
/sandbox/node_modules/dom-accessibility-api/dist/accessible-description.mjs:7
import { computeTextAlternative } from "./accessible-name-and-description.mjs";
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14)
at Object.<anonymous> (node_modules/dom-accessibility-api/sources/index.ts:1:1)
所以这里的重点是:
/sandbox/node_modules/dom-accessibility-api/dist/accessible-description.mjs:7
import { computeTextAlternative } from "./accessible-name-and-description.mjs";
^^^^^^
SyntaxError: Cannot use import statement outside a module
看起来那个特定的 .mjs 文件来自那个库 dom-accessibility-api 不能被 Jest 解析。但为什么会这样?在任何使用 react-testing-library 和 Jest 进行 React 测试的教程中,似乎都没有关于此的问题或提及。这是一个我一无所知的第三方库
有谁知道如何解决这个问题? 我的主要配置文件:
babel.config.js:
const presets = [
'react-app'
];
module.exports = { presets };
jest.config.js:(我尝试了很多选项和简化,但无济于事)
module.exports = {
reporters: [
"default",
"jest-junit"
],
coverageReporters: [
"lcov",
"text",
"cobertura"
],
collectCoverageFrom: [
"src/**/*.{js,jsx}"
],
setupFiles: [
"<rootDir>/tests/setup.js",
"jest-localstorage-mock",
"jest-canvas-mock"
],
snapshotSerializers: [
"enzyme-to-json/serializer"
],
testMatch: [
"<rootDir>/tests/**/*.test.js"
],
testEnvironment: "jsdom",
testURL: "http://localhost",
transform: {
"^.+\.(js|jsx)$": "babel-jest",
"^.+\.(ts|tsx|mjs)$": "ts-jest",
"^.+\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\.(js|jsx|mjs|css|json|ts)$)": "<rootDir>/config/jest/fileTransform.js"
},
transformIgnorePatterns: [
"[/\\]node_modules[/\\].+\.(js|jsx|mjs|ts|tsx)$"
],
testPathIgnorePatterns: ["<rootDir>/build/", "<rootDir>/node_modules/"],
moduleNameMapper: {
"^react-native$": "react-native-web"
},
moduleFileExtensions: [
"web.js",
"mjs",
"js",
"ts",
"json",
"web.jsx",
"jsx",
"node"
]
}
/tests/setup.js:(只是为了初始化 Enzyme 用于其他类型的测试)
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter(), disableLifecycleMethods: true });
/config/jest/fileTransform.js:
'use strict';
const path = require('path');
// This is a custom Jest transformer turning file imports into filenames.
// http://facebook.github.io/jest/docs/en/webpack.html
module.exports = {
process(src, filename) {
return `module.exports = ${JSON.stringify(path.basename(filename))};`;
},
};
package.json:(仅显示 devDependencies)
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"@babel/preset-typescript": "^7.12.7",
"@testing-library/jest-dom": "^5.11.9",
"@testing-library/react": "^11.2.3",
"axios-mock-adapter": "^1.15.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"babel-loader": "^8.2.2",
"babel-preset-react-app": "^10.0.0",
"babel-runtime": "^6.26.0",
"browser-refresh-taglib": "^1",
"case-sensitive-paths-webpack-plugin": "2.1.1",
"cross-env": "^5.2.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
"enzyme-to-json": "^3.6.1",
"eslint": "^7.17.0",
"eslint-config-react-app": "^6.0.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-flowtype": "^5.2.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"extract-text-webpack-plugin": "3.0.2",
"html-webpack-plugin": "2.29.0",
"jest": "^26.6.3",
"jest-canvas-mock": "^2.2.0",
"jest-junit": "^5.2.0",
"jest-localstorage-mock": "^2.3.0",
"jest-when": "^2.7.0",
"nock": "^9.2.3",
"optimizer-plugin-inc": "^4",
"query-string": "5.1.1",
"react-dev-utils": "^5.0.0",
"redux-mock-store": "^1.5.4",
"redux-thunk": "^2.3.0",
"sw-precache-webpack-plugin": "0.11.4",
"ts-jest": "^26.4.4",
"webpack": "3.8.1",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-dev-server": "2.9.4",
"webpack-hot-middleware": "^2.22.2",
"webpack-manifest-plugin": "1.3.2"
};
看来我找到了解决办法。 基于这个例子:react-redux
我更新并简化了我的 jest.config.js 如下:
const path = require('path')
module.exports = {
roots: [path.resolve(__dirname, './tests')],
reporters: [
"default",
"jest-junit"
],
coverageReporters: [
"lcov",
"text",
"cobertura"
],
collectCoverageFrom: [
"src/**/*.{js,jsx}"
],
setupFiles: [
path.resolve(__dirname, "./tests/setup.js"),
"jest-localstorage-mock",
"jest-canvas-mock"
],
setupFilesAfterEnv: [path.resolve(__dirname, './tests/setupAfterEnv.js')],
testMatch: [
"**/tests/**/*.test.js"
],
testURL: "http://localhost"
}
并添加了一个 setupAfterEnv.js 文件,只有这一行:
import '@testing-library/jest-dom/extend-expect'
到目前为止,测试现在可以通过了...
老实说,我仍然不确定为什么之前会出现该错误,我认为变化不大...
看来真正的解决方法是 remove/disable 代码转换。
关注 Jest 27.4 文档(当前版本):https://jestjs.io/docs/ecmascript-modules,
#1:确保您通过传递 transform: {}
来禁用代码转换,或者将您的转换器配置为发出 ESM 而不是默认的 CommonJS (CJS)。
这正是您在 jest.config.js 文件中所做的。
希望这有助于更好地理解问题!