【发布时间】:2022-10-17 21:10:23
【问题描述】:
在使用 Jest 进行单元测试时获取 SyntaxError: Cannot use import statement outside a module。错误来自node-fetch 包,即required 包jsdom-worker。这可能是node-fetch 包的问题,但不完全确定。
我在jest.config.js 中忽略了节点模块,为什么这是个问题?
jest.config.js 文件:
const ignores = ['/node_modules/', '/__fixtures__/', '/fixtures/', '/__tests__/helpers/', '/__tests__/utils/', '__mocks__'];
module.exports = {
preset: 'ts-jest',
roots: ['<rootDir>'],
modulePaths: [
"<rootDir>/src"
],
moduleDirectories: [
"node_modules"
],
transformIgnorePatterns: [...ignores],
transform: {
'^.+\\.(ts|tsx|js|jsx)?$': 'ts-jest',
'^.+\\.(gif|svg|ico)$': '<rootDir>/svgTransform.js',
},
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.js?$',
moduleFileExtensions: ['tsx', 'js', 'json', 'node', 'ts'],
moduleNameMapper: {
"\\.(css|less|scss|sass)$": "identity-obj-proxy"
},
clearMocks: true,
// collectCoverage: true, // todo
// coverageDirectory: "coverage", // todo
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect', 'jsdom-worker'],
}
// }
更新:将node-fetch 降级到 2.4 版后,那错误消失了,但现在与另一个包有相同的语法问题,为什么会继续发生这种情况?
babel.config.js
// Need to convert modules to commonjs format so Jest can undertstand them.
const isTest = String(process.env.NODE_ENV) === 'test'
const isProd = String(process.env.NODE_ENV) === 'production'
module.exports = {
// For transformation of TSX and other react related bable plugins
presets: [
// Allows smart transpilation according to target environments
['@babel/preset-env', { modules: isTest ? 'commonjs' : false }],
// Enabling Babel to understand TypeScript
'@babel/preset-typescript',
],
}
也试过this来自 kcd-scripts 的 babel 配置:
"use strict";
const browserslist = require('browserslist');
const semver = require('semver');
const {
ifDep,
ifAnyDep,
ifTypescript,
parseEnv,
appDirectory,
pkg
} = require('../utils');
const {
BABEL_ENV,
NODE_ENV,
BUILD_FORMAT
} = process.env;
const isTest = (BABEL_ENV || NODE_ENV) === 'test';
const isPreact = parseEnv('BUILD_PREACT', false);
const isRollup = parseEnv('BUILD_ROLLUP', false);
const isUMD = BUILD_FORMAT === 'umd';
const isCJS = BUILD_FORMAT === 'cjs';
const isWebpack = parseEnv('BUILD_WEBPACK', false);
const isMinify = parseEnv('BUILD_MINIFY', false);
const treeshake = parseEnv('BUILD_TREESHAKE', isRollup || isWebpack);
const alias = parseEnv('BUILD_ALIAS', isPreact ? {
react: 'preact'
} : null);
const hasBabelRuntimeDep = Boolean(pkg.dependencies && pkg.dependencies['@babel/runtime']);
const RUNTIME_HELPERS_WARN = 'You should add @babel/runtime as dependency to your package. It will allow reusing "babel helpers" from node_modules rather than bundling their copies into your files.';
if (!treeshake && !hasBabelRuntimeDep && !isTest) {
throw new Error(RUNTIME_HELPERS_WARN);
} else if (treeshake && !isUMD && !hasBabelRuntimeDep) {
console.warn(RUNTIME_HELPERS_WARN);
}
/**
* use the strategy declared by browserslist to load browsers configuration.
* fallback to the default if don't found custom configuration
* @see https://github.com/browserslist/browserslist/blob/master/node.js#L139
*/
const browsersConfig = browserslist.loadConfig({
path: appDirectory
}) || ['defaults'];
const envTargets = isTest ? {
node: 'current'
} : isWebpack || isRollup ? {
browsers: browsersConfig
} : {
node: getNodeVersion(pkg)
};
const envOptions = {
modules: false,
loose: true,
targets: envTargets
};
module.exports = () => ({
presets: [[require.resolve('@babel/preset-env'), envOptions], ifAnyDep(['react', 'preact'], [require.resolve('@babel/preset-react'), {
pragma: isPreact ? ifDep('react', 'React.h', 'h') : undefined
}]), ifTypescript([require.resolve('@babel/preset-typescript')])].filter(Boolean),
plugins: [[require.resolve('@babel/plugin-transform-runtime'), {
useESModules: treeshake && !isCJS
}], require.resolve('babel-plugin-macros'), alias ? [require.resolve('babel-plugin-module-resolver'), {
root: ['./src'],
alias
}] : null, ifAnyDep(['react', 'preact'], [require.resolve('babel-plugin-transform-react-remove-prop-types'), isPreact ? {
removeImport: true
} : {
mode: 'unsafe-wrap'
}]), isUMD ? require.resolve('babel-plugin-transform-inline-environment-variables') : null, [require.resolve('@babel/plugin-proposal-class-properties'), {
loose: true
}], isMinify ? require.resolve('babel-plugin-minify-dead-code-elimination') : null, treeshake ? null : require.resolve('@babel/plugin-transform-modules-commonjs')].filter(Boolean)
});
function getNodeVersion({
engines: {
node: nodeVersion = '10.13'
} = {}
}) {
const oldestVersion = semver.validRange(nodeVersion).replace(/[>=<|]/g, ' ').split(' ').filter(Boolean).sort(semver.compare)[0];
if (!oldestVersion) {
throw new Error(`Unable to determine the oldest version in the range in your package.json at engines.node: "${nodeVersion}". Please attempt to make it less ambiguous.`);
}
return oldestVersion;
}
【问题讨论】:
-
你能发布你的打字稿和/或 babel 配置吗?问题可能就在那里。
-
刚刚发布@Derek
-
第二张图片显示了正在使用的浏览器构建 (
index.browser.js)。用于浏览器的 JS 包不需要遵守 Node 的文件命名约定,因此它可以在非.js包中的.js文件中使用import。但是,这在 Node.js 中不起作用。您需要确保 Jest 不使用浏览器捆绑包,因为它们可能不遵守 Node 的 ESM 约定。 -
写了github.com/juanelas/bigint-conversion/issues/10,尽管这可能只会在补丁发布后解决您的直接问题。
-
@rschristian 是的。我通过将我正在使用的 nanoid 包降级到下一个较低版本并修复了它来解决了我遇到的下一个语法错误.. 不断收到类似的奇怪东西
标签: reactjs unit-testing testing jestjs es6-modules