Jest react SyntaxError: Cannot use import statement outside a module - reactjs

I'm trying to run a simple test taken from jest official site in jest but I'm getting this error:
I don't understand why he complains about an import statement since there are not in the test file:
sum.test.ts:
test('two plus two is four', () => {
expect(2 + 2).toBe(4);
});
export {};
Any suggestions?
Following more configurations files about jest and typescript in case are needed for a better view of my situation..
jest.config.js:
// recusrsively replaces the string from / to in the object structure.
function replacePackageJsonSpecific(structure, from, to) {
for (const property in structure) {
if (typeof structure[property] === 'object') {
replacePackageJsonSpecific(structure[property], from, to);
} else if (typeof structure[property] === 'string') {
if (structure[property].includes(from)) {
structure[property] = structure[property].replace(from, to);
}
}
}
}
// replaces properties from left to right, concatenates arrays from left and right
function merge(left, right) {
const merged = {...left, ...right};
for (const property in right) {
if (Array.isArray(right[property]) && Array.isArray(left[property])) {
merged[property] = left[property].concat(right[property]);
}
}
return merged;
}
const path = require('path');
let directory = path.join(process.cwd(), '/');
let reporters = ['default', 'jest-junit'];
process.argv.forEach(function (val) {
if (val.includes('cwd')) {
const cwd = val.split('=')[1];
directory = path.join(directory, cwd.substring(0, cwd.search('test')));
reporters = reporters.slice(0, 1);
}
});
const packageJson = require(directory + 'package.json');
replacePackageJsonSpecific(packageJson.jest, '<rootDir>', directory);
packageJson.jest.rootDir = directory;
const isCI = () => process.env['CI'] === 'true';
module.exports = merge(
{
cacheDirectory: './node_modules/.cache/jest-cache',
reporters: reporters,
roots: [path.join(directory, '/test/unit/')],
setupFilesAfterEnv: [directory + 'test/setupTests.ts'],
snapshotSerializers: ['enzyme-to-json/serializer'],
collectCoverage: process.env['COVERAGE_REPORT'] === 'true' || isCI(),
coverageDirectory: 'generated/coverage',
testEnvironment: 'enzyme',
testEnvironmentOptions: {
enzymeAdapter: 'react16',
},
testMatch: ['**/?(*.)(spec|test).(j|t)s?(x)'],
testURL: 'http://localhost',
preset: 'ts-jest',
transform: {
'^.+\\.(ts|tsx)?$': 'ts-jest',
'^.+\\.(js|jsx|mjs|ts|tsx)$': './node_modules/react-scripts/config/jest/babelTransform.js',
'^.+\\.(js|jsx|mjs)$': './node_modules/babel-jest',
'^.+\\.css$': './node_modules/react-scripts/config/jest/cssTransform.js',
'^(?!.*\\.(js|jsx|mjs|css|json)$)': './node_modules/react-scripts/config/jest/fileTransform.js',
},
transformIgnorePatterns: ['<rootDir>/node_modules/(?!#uwr/icons)'],
coverageReporters: ['html', 'lcov', 'text'],
globals: {
'ts-jest': {
tsConfigFile: 'tsconfig.test.json',
},
},
moduleDirectories: ['node_modules'],
moduleFileExtensions: ['mjs', 'web.ts', 'ts', 'web.tsx', 'tsx', 'web.js', 'js', 'web.jsx', 'jsx', 'json', 'node'],
},
packageJson.jest,
);
babel.config.js:
module.exports = {
presets: [
['#babel/preset-env', {targets: {node: 'current'}}],
'#babel/preset-typescript',
],
};
package.json:
"scripts": {
"test": "react-app-rewired test --no-watchman --watchAll=false",
}
folders structure:

Related

Reacr Single SPA Micro frontend executes old scripts after a fresh deployment

We are migrating a standalone React.js application into micro frontend architecture using the library react-single-spa https://single-spa.js.org/docs/ecosystem-react/
We noticed a problem that after a new deployment to any micro-frontend app, the Single SPA was still loading the old code. I assume it is because, the browser caches the scrips . Is there's a way to make sure latest version of the code is being used ? Or is there a sample on how to implement this?
Below is my current webpack configs.
root-config
const { merge } = require("webpack-merge");
const singleSpaDefaults = require("webpack-config-single-spa");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = (webpackConfigEnv, argv) => {
const orgName = "my-org";
const defaultConfig = singleSpaDefaults({
orgName,
projectName: "root-config",
webpackConfigEnv,
argv,
disableHtmlGeneration: true,
});
return merge(defaultConfig, {
plugins: [
new HtmlWebpackPlugin({
inject: false,
template: "src/index.ejs",
templateParameters: {
isLocal: webpackConfigEnv && webpackConfigEnv.isLocal,
orgName,
},
}),
],
});
};
app-config
const { merge } = require("webpack-merge");
const singleSpaDefaults = require("webpack-config-single-spa-react");
const path = require("path");
module.exports = (webpackConfigEnv, argv) => {
const defaultConfig = singleSpaDefaults({
orgName: "my-org",
projectName: "my-app",
webpackConfigEnv,
argv,
});
return merge(defaultConfig, {
resolve: {
fallback: {
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify")
},
extensions: ['.ts', '.js', 'mjs', '.tsx'],
alias: {
src: path.resolve(__dirname, 'src'),
}
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
"style-loader",
// Translates CSS into CommonJS
"css-loader",
// Compiles Sass to CSS
"sass-loader",
],
},
{
test: /\.(woff|woff2|ttf|eot)$/,
use: 'file-loader?name=fonts/[name].[ext]!static'
}
]
}
});
};
Appreciate any help. Thank you !

Storyshots Runner does not get called

I am using Storybook with the Storyshots addon and whenever I run the tests, the output is the following.
What is causing the storyshots.test.ts file to not get picked up here?
In [filepath...]
1487 files checked.
testMatch: !**/__utils__/**, /Users/root/dev/repo/storyshots.test.ts - 0 matches
testPathIgnorePatterns: /node_modules/ - 1487 matches
testRegex: - 0 matches
Pattern: - 0 matches
It appears the init file for Storyshots is not getting picked up by the jest.config.
// jest.config.js
module.exports = {
setupFilesAfterEnv: ['./jest.setup.js'],
roots: ['<rootDir>/src/'],
modulePathIgnorePatterns: ['<rootDir>/src/.*/__mocks__'],
globalSetup: './jest.global-setup.js',
testMatch: [
'**/__tests__/**/*.[jt]s?(x)',
'**/?(*.)+(spec|test).[tj]s?(x)',
'!**/__utils__/**',
'<rootDir>/storyshots.test.ts'
]
}
// .storybook/main.js
const custom = require("../webpack.common.js");
module.exports = {
stories: [
"../src/**/*.stories.mdx",
"../src/**/*.stories.#(ts|tsx)",
],
addons: [
{
name: "#storybook/addon-docs",
options: {
configureJSX: true,
}
},
{
name: "#storybook/addon-essentials",
options: {
/* This panel is disabled due to how we write stories */
actions: false,
},
}
],
webpackFinal: (config) => {
return {
...config,
resolve: {
...config.resolve,
alias: { ...config.resolve.alias, ...custom.resolve.alias },
},
};
},
};
// storyshots.test.ts
import initStoryshots from '#storybook/addon-storyshots'
initStoryshots()

Next js jest coverage

I am using in my next js application Cypress and Jest. Running jest --coverage i get an error:
STACK: Error: Duplicate plugin / preset detected.
If you 'd like to use two separate instances of a plugin,
they need separate names, e.g.
plugins: [
['some-plugin', {}],
['some-plugin', {}, 'some unique name'],
]
This is my .babelrc file:
{
"presets": ["next/babel"],
"plugins": ["istanbul"]
}
Who faced with the same issue and how to solve it to get the coverage?
I found the solution that helped to solve the problem.
I had to add the env variable to the .babelrc
{
"env": {
"component": {
"plugins": [
"istanbul"
]
}
}
}
Then add it to cypress.config.js
const { defineConfig } = require('cypress');
const { devServer } = require('#cypress/webpack-dev-server');
const webpackConfig = require('./config/cypress.webpack.config.js');
const codeCoverageTask = require('#cypress/code-coverage/task');
module.exports = defineConfig({
viewportWidth: 1000,
viewportHeight: 660,
video: false,
env: {
BABEL_ENV: 'component',
},
component: {
devServer(devServerConfig) {
return devServer({
...devServerConfig,
framework: 'react',
webpackConfig,
});
},
specPattern: 'src/**/*.cy.{js,ts,jsx,tsx}',
setupNodeEvents(on, config) {
codeCoverageTask(on, config);
return config;
},
},
});

SyntaxError: pragma and pragmaFrag cannot be set when runtime is automatic

I'm migrating a project from Next 9 to Next 11 which uses webpack5 by default. After fixing the loader issue as shown in the next.config.js file, I get this error:
SyntaxError: pragma and pragmaFrag cannot be set when runtime is automatic
I've tried debugging with these solutions, and I still trigger the same error.
My code:
next.config.js
const withImages = require("next-images");
const { PHASE_DEVELOPMENT_SERVER } = require("next/constants");
const withYaml = require("next-plugin-yaml");
const babel = require('babel-plugin-import-glob-array');
module.exports = (phase) =>
withYaml(
withImages(
({
target: "serverless",
env: {
isDev: phase === PHASE_DEVELOPMENT_SERVER,
},
webpack5: true,
webpack: (config, options) => {
config.module.rules.push({
test: /\.mdx/,
use: [
options.defaultLoaders.babel,
{
loader: '#mdx-js/loader',
options: babel.options,
},
],
});
config.module.rules.unshift({
test: /\.svg$/,
use: ["#svgr/webpack"]
});
console.log(options.webpack.version); // 5.18.0
// eslint-disable-next-line no-param-reassign
config.experiments = {};
return config;
},
})
)
);
babel.config.json
{
"presets": ["next/babel", "#emotion/babel-preset-css-prop"],
"plugins": ["import-glob-array", "emotion"]
}
.tsx files
/** #jsx jsx */
import { css, jsx } from "#emotion/core";

Web Worker - Jest - Cannot use 'import.meta' outside a module

I'm working on a nextjs 10.1.3 built-in web application. We implemented a web worker to boost up the performance in one of the pages and the plan is to continue adding more workers; also, all the code is properly unit tested, and using the worker-loader in previous webpack versions (4th and below) we were able to test it.
With the new webpack 5 version, the worker-loader plugin is not needed anymore; instead, the way to load a web worker using the new version is new Worker(new URL("#/workers/task.worker.js", import.meta.url));.
Doing it this way, my code is working as expected with npm build && npm start; however, when I try to add the respective unit tests I got the following error: Cannot use 'import.meta' outside a module and everything happens because of the import.meta.url used to add the location of the worker in the browser.
I read many posts on the web regarding babel but I want to get away from that option. Is there any other option to mock the import.meta.url with jest?
Any help will be very welcome. This is the current configuration.
package.json
{
...
"#babel/core": "^7.8.6",
"next": "^10.1.3",
"react": "^16.13.0",
"webpack": "^5.37.1"
"devDependencies": {
...
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"jest": "^24.9.0",
"jest-cli": "^25.1.0",
...
}
...
}
next.config.js
const {
...
} = process.env;
const basePath = "";
const COMMIT_SHA = [];
const { parsed: localEnv } = require("dotenv").config();
const webpack = require("webpack");
const withBundleAnalyzer = require("#next/bundle-analyzer")({
enabled: process.env.ANALYZE === "true",
});
const nextConfig = {
env: {
NEXT_PUBLIC_COMMIT_SHA: COMMIT_SHA,
},
images: {
domains: [
"...",
],
},
future: {
webpack5: true,
},
productionBrowserSourceMaps: true,
trailingSlash: true,
reactStrictMode: true,
webpack: (config, options) => {
if (localEnv) {
config.plugins.push(new webpack.EnvironmentPlugin(localEnv));
} else {
config.plugins.push(new webpack.EnvironmentPlugin(process.env));
}
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: "url-loader",
options: {
limit: 100000,
name: "[name].[ext]",
},
},
});
config.output = {
...config.output,
chunkFilename: options.isServer
? `${options.dev ? "[name]" : "[name].[fullhash]"}.js`
: `static/chunks/${options.dev ? "[name]" : "[name].[fullhash]"}.js`,
publicPath: `/_next/`,
globalObject: `(typeof self !== 'undefined' ? self : this)`,
};
config.plugins.push(new webpack.IgnorePlugin(/pages.*\/__tests__.*/));
config.plugins.push(
new options.webpack.DefinePlugin({
"process.env.NEXT_IS_SERVER": JSON.stringify(
options.isServer.toString()
),
})
);
return config;
},
};
module.exports = withBundleAnalyzer(nextConfig);
The useEffect worker
useEffect(() => {
if (pageData.data?.length) {
workerRef.current = new Worker(new URL("#/workers/task.worker.js", import.meta.url));
workerRef.current.addEventListener("message", result => {
if (result.error) {
setWorkerError();
} else {
updateData(result.data);
}
});
const ids = pageData.data.map(store => store.id);
workerRef.current.postMessage(ids);
} else {
setNoDataFound();
}
return () => {
workerRef.current && workerRef.current.terminate();
};
}, []);
jest.config.js
module.exports = {
moduleDirectories: ["node_modules", "src", "static", "store"],
modulePathIgnorePatterns: [
"<rootDir>/node_modules/prismjs/plugins/line-numbers",
],
testPathIgnorePatterns: [
"<rootDir>/src/components/component-library",
"<rootDir>/.next",
"jest.config.js",
"next.config.js",
],
collectCoverageFrom: [
"**/src/**",
"**/store/**",
"**/pages/**",
"!**/__tests__/**",
"!**/node_modules/**",
"!**/component-library/**",
],
testEnvironment: "node",
collectCoverage: true,
verbose: false,
automock: false,
setupFiles: ["./setupTests.js"],
moduleNameMapper: {
"#/components/(.*)$": "<rootDir>/src/components/$1",
"#/functions/(.*)$": "<rootDir>/src/components/functions/$1",
"#/services/(.*)$": "<rootDir>/src/components/services/$1",
"#/workers/(.*)$": "<rootDir>/src/components/workers/$1",
"#/scripts(.*)$": "<rootDir>/src/scripts/$1",
"#/src(.*)$": "<rootDir>/src/$1",
"#/__mocks__(.*)$": "<rootDir>/__mocks__/$1",
"#/pages(.*)$": "<rootDir>/pages/$1",
"#/store(.*)$": "<rootDir>/store/$1",
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
},
coveragePathIgnorePatterns: ["/node_modules/"],
coverageThreshold: {
global: {
branches: 67,
functions: 66,
lines: 73,
statements: 72,
},
},
runner: "groups",
extraGlobals: [],
testTimeout: 10000,
};
In my setup (typescript + ts-jest) I prepended the following node option to make it work:
NODE_OPTIONS=--experimental-vm-modules
Reference can be found here: https://jestjs.io/docs/ecmascript-modules

Resources