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;
},
},
});
Related
I have noticed that Storybook can't process Typescript files if they are from another project (monorepo), but it is doing okay with TS files that are within its project.
How do I configure Storybook to handle TS files outside the project?
Structure of the monorepo:
package1
.storybook
main.ts
preview.ts
component.tsx (this component imports file.ts)
component.stories.tsx
package2
file.ts <- (Storybook can't process this file: ModuleParseError: Module parse failed: Unexpected token)
Here is the main.ts config file:
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const path = require('path');
const toPath = (filePath) => path.join(process.cwd(), filePath);
module.exports = {
"stories": [
"../src/**/*.stories.#(mdx|js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials",
"#storybook/addon-interactions",
"#storybook/addon-knobs/register",
"#storybook/preset-create-react-app",
"#storybook/addon-a11y",
'storybook-addon-styled-component-theme/dist/preset',
'storybook-addon-themes',
"storybook-dark-mode",
],
"framework": "#storybook/react",
"core": {
"builder": "#storybook/builder-webpack5",
"disableTelemetry": true,
},
features: {
emotionAlias: false,
},
typescript: { reactDocgen: false },
webpackFinal: async (config, { configType }) => {
return {
...config,
resolve: {
...config.resolve,
alias: {
...config.resolve.alias,
'#emotion/core': toPath('node_modules/#emotion/react'),
'emotion-theming': toPath('node_modules/#emotion/react'),
},
plugins: [new TsconfigPathsPlugin()]
},
}
}
}
Here is the error:
ModuleParseError: Module parse failed: Unexpected token (7:11)
File was processed with these loaders:
* ../../node_modules/#pmmmwh/react-refresh-webpack-plugin/loader/index.js
You may need an additional loader to handle the result of these loaders.
| import { Palette as palette } from '../Palette';
|
> const Paper: any = [
| {
If I import the same TS file, but manually precompiled into regular JS - Storybook works.
I have no idea what to try to solve this :(
Add this to .storybook/main.js
webpackFinal: async (config, { configType }) => {
// `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
// You can change the configuration based on that.
// 'PRODUCTION' is used when building the static version of storybook.
// Storybook uses its own webpack config, so we need to merge our config with it
// See https://storybook.js.org/docs/configurations/custom-webpack-config/
// Add typescript loader to process TS-files from other packages
config.module.rules.push({
test: /\.(ts|tsx)$/,
use: [
{
loader: require.resolve("ts-loader"),
options: {
reportFiles: [
"../**/src/**/*.{ts,tsx}"
]
}
},
]
});
config.resolve.extensions.push(".ts", ".tsx");
return config;
}
I am building a project using Vite + React + Antd.
My project has lodash library, when i build with vite build command then get an error like below:
Running on environment production
vite v2.9.9 building for production...
transforming (2741) node_modules\.pnpm\lodash#4.17.21\node_modules\lodash\isLength.jsUnexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:
(commonjs) load "\u0000cross-fetch?commonjs-proxy"
error during build:
Error: Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:
(commonjs) load "\u0000cross-fetch?commonjs-proxy"
In my vite.config.js file, I added #rollup/plugin-commonjs,
import commonjs from '#rollup/plugin-commonjs';
import react from '#vitejs/plugin-react';
import { defineConfig, loadEnv } from 'vite';
export default ({ mode }) => {
const env = loadEnv(mode, 'env');
const htmlPlugin = () => {
return {
name: 'html-transform',
// Replace %VITE_X% env variables in index.html.
transformIndexHtml(html: string) {
return html.replace(/%(.*?)%/g, function match(_match, p1) {
return env[p1];
});
},
};
};
return defineConfig({
resolve: {
alias: [
{ find: /^~/, replacement: '' },
{ find: 'react/jsx-runtime', replacement: 'react/jsx-runtime.js' },
],
},
define: {
'process.env': process.env,
},
build: {
outDir: './build',
rollupOptions: {
plugins: [commonjs()],
},
commonjsOptions: {
exclude: [/./],
},
},
publicDir: './public',
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true,
},
},
},
optimizeDeps: {
include: ['#ant-design/icons'],
},
plugins: [
htmlPlugin(),
react({
babel: {
plugins: [['#babel/plugin-transform-react-jsx', { runtime: 'automatic' }]],
},
}),
],
});
};
I tried to change lodash into lodash-es, but in my node_modules has a couple of libraries use it.
Please help me. Thank all
I couldn't find any information on how to make #emotion/react work in Storybook when using Vite as a bundler in a React application.
I'm getting errors like Invalid value for prop 'css' in <div> tag in almost every story.
Even though, #emotion/react is working fine for the webapp itself.
Here's my vite.config.js configuration:
import { defineConfig } from 'vite';
import react from '#vitejs/plugin-react';
export default defineConfig({
esbuild: {
jsxFactory: 'jsx',
jsxInject: `import { jsx } from '#emotion/react'`,
},
plugins: [
react({
jsxImportSource: '#emotion/react',
babel: {
plugins: ['#emotion/babel-plugin'],
},
}),
],
});
And here's my main.js for Storybook:
const svgrPlugin = require('vite-plugin-svgr');
module.exports = {
core: {
builder: 'storybook-builder-vite',
},
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.#(js|jsx|ts|tsx)'],
addons: ['#storybook/addon-links', '#storybook/addon-essentials'],
viteFinal: (config, { configType }) => {
config.define = {
'window.process': {
env: {
NODE_ENV: configType.toLowerCase(),
},
},
};
return {
...config,
plugins: [
...config.plugins,
svgrPlugin({
svgrOptions: {
icon: true,
},
}),
],
};
},
};
The solution was found in storybook-builder-vite's github page here.
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
I'm having issues with jest on typescript.
//myprovider.tsx
class MyProvider{
constructor(){}
giveMeFive(): int{ return 5; }
}
export { MyProvider }
// myprovider.test.js
import { MyProvider } from './myprovider';
test('give me five!', () => {
const myprovider = new MyProvider();
/// assert
})
I get the following error
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".
import { MyProvider } from './myprovider';
^
I'm not sure what I'm missing, I have this on my package
//package.json
"jest": {
"transform": {
".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"testRegex": "(/tests/.*|\\.(test|spec))\\.(ts|tsx|js)$",
"moduleFileExtensions": ["ts", "tsx", "js"]
},
// .babelrc
{
"presets": [
"#babel/preset-typescript"
]
}
//jest.config.js
module.exports = {
preset: 'ts-jest',
transform: {
'^.+\\.tsx?$': 'babel-jest',
},
}
Make sure to install these packages:
babel-jest #babel/core #babel/preset-env
Your babel config should look like this:
presets: [
[
"#babel/preset-env",
{
targets: {
node: "current",
},
},
],
"#babel/preset-typescript",
]