Jest can't run test with methods in .tsx file - reactjs

Usually I only test files that ends with .ts, but in this case I have a file with utility methods that returns a react element. So in this case my file has a .tsx extension and returns some components from material ui and other libraries.
I was getting an error saying SyntaxError: Cannot use import statement outside a module but I solved it by adding "^.+\\.(ts|js)x?$": "ts-jest" to the transform property of my jest.config.js.
But after that I got another error:
● 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:
C:\projetos\COM.FLOU.FrontEnd\node_modules\overlayscrollbars\css\OverlayScrollbars.css:19
html.os-html > .os-host {
^
SyntaxError: Unexpected token '.'
jest.config.ts
import { pathsToModuleNameMapper } from "ts-jest/utils";
import { compilerOptions } from "./tsconfig.paths.json";
export default {
coverageDirectory: "coverage/jest",
testEnvironment: "jsdom",
testMatch: ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[tj]s?(x)"],
testPathIgnorePatterns: ["\\\\node_modules\\\\", "<rootDir>/cypress/"],
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: "<rootDir>/" }),
transform: {
"^.+\\.jsx?$": "babel-jest",
"^.+\\.(ts|js)x?$": "ts-jest",
".+\\.(css|styl|less|sass|scss)$": "jest-css-modules-transform",
},
};
babel.config.js
// babel.config.js
module.exports = {
presets: [
["#babel/preset-env", { targets: { node: "current" } }],
"#babel/preset-react",
"#babel/preset-typescript",
],
plugins: [
[
"#babel/plugin-transform-runtime",
{
regenerator: true,
},
],
],
};
tsconfig.json
{
"compilerOptions": {
"noImplicitAny": true,
"target": "es5",
"module": "esnext",
"jsx": "react-jsx",
"types": [
"jest"
],
"lib": [
"es6",
"DOM"
],
"outDir": "./dist/",
"rootDir": "./src/",
"sourceMap": true,
"removeComments": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"allowJs": true,
"allowSyntheticDefaultImports": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
},
"extends": "./tsconfig.paths.json",
"include": [
"src/**/*"
],
"exclude": [
"jest.config.ts"
]
}
Am I missing any specific configuration?

I solved it by adding an empty styleMock.ts file and adding it to moduleNameMapper on my jest.config.ts file.
styleMock.ts
export default {};
jest.config.ts
import { pathsToModuleNameMapper } from "ts-jest/utils";
import { compilerOptions } from "./tsconfig.paths.json";
export default {
coverageDirectory: "coverage/jest",
testEnvironment: "jsdom",
testMatch: ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[tj]s?(x)"],
testPathIgnorePatterns: ["\\\\node_modules\\\\", "<rootDir>/cypress/"],
moduleNameMapper: {
...pathsToModuleNameMapper(compilerOptions.paths, { prefix: "<rootDir>/" }),
"\\.(css)$": "<rootDir>/styleMock.ts",
},
transform: {
"^.+\\.(ts|js)x?$": "ts-jest",
},
};

Related

Jest fails to run .tsx files

I implemented typescript to my create-react-app project and I can't run jest test files with .jsx suffix to test .tsx files
for example I want to test ConsentContainer.tsx file with ConsentContainer.spec.jsx and I got this error
test/unit/containers/ConsentContainer.spec.jsx
● Test suite failed to run
Jest encountered an unexpected token
.
.
.
Details:
C:\src\containers\ConsentContainer.tsx:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { useEffect, useState }
from 'react';
^^^^^^
SyntaxError: Cannot use import statement outside a module
1 | import React from 'react';
2 | import configureStore from 'redux-mock-store';
> 3 | import ConsentContainer from '../../../src/containers/ConsentContainer';
when the files had .jsx suffix jest tests worked properly
but I don't know how to make the configuration
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": [
"es6",
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"noImplicitAny": false,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"noUnusedParameters": true,
"noUnusedLocals": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"noFallthroughCasesInSwitch": true
},
"include": [
"src"
]
}
jest.config.json
module.exports = {
verbose: true,
testEnvironment: 'jsdom',
setupFiles: ['raf/polyfill'],
setupFilesAfterEnv: ['./test/jest.test-setup.js'],
moduleFileExtensions: ['js', 'jsx', 'tsx'],
moduleNameMapper: {
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'identity-obj-proxy'
},
testPathIgnorePatterns: ['/node_modules/', '/cypress/', '/.cache/Cypress/3.1.0/Cypress/'],
snapshotSerializers: ['enzyme-to-json/serializer'],
transform: {
'^.+\\.jsx?$': 'babel-jest',
'.+\\.(css|css!|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$':
'jest-transform-stub',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/test/assetsTransformer.js'
},
transformIgnorePatterns: [
'/node_modules/(?!(p-retry)/)',
'/dist/'
]
};
babel.config.json
{
"presets": ["#babel/preset-react", "#babel/preset-env", "#babel/preset-typescript"],
"plugins": [
"react-hot-loader/babel",
"transform-object-rest-spread",
["#babel/plugin-transform-runtime", {
"regenerator": true
}],
[
"#babel/plugin-proposal-decorators",
{
"legacy": true
}
],
["#babel/plugin-proposal-private-property-in-object", { "loose": true }],
["#babel/plugin-proposal-private-methods", { "loose": true }],
["#babel/plugin-proposal-class-properties", { "loose": true }]
]
}
when I install ts-jest package all my tests are failing not only ones connected with .tsx files

Using jsx-react includes React into the bundle

I'm trying to make React UI component libraries. In my tsconfig, if I set {..., "jsx": "react-jsx"}, I see in the bundle index.esm.js that React code is included.
But if I use the old jsx {"jsx": "react"}, React code is not included in the bundle.
I am using rollup to bundle. This is rollup.config.ts
export default {
input: "./index.ts",
output: [
{
file: pkg.main,
format: "cjs",
},
{
file: pkg.module,
format: "es",
},
],
external: ["react", "react-dom", "#emotion", "#mui/material", "#mui/style"],
plugins: [
resolve(),
external(),
commonjs(),
typescript({
useTsconfigDeclarationDir: true,
}),
terser(),
],
};
This is tsconfig
{
"compilerOptions": {
"declaration": true,
"declarationDir": "lib/types",
"esModuleInterop": true,
"moduleResolution": "Node",
"jsx": "react-jsx",
"resolveJsonModule": true,
"strict": true,
"target": "ESNext"
},
"include": ["./**/*"],
"exclude": ["./**/*.stories.tsx", "./lib", "./node_modules"]
}
How can I use the react-jsx and not include the React code in the bundle. I tried setting sideEffects:false in package.json but it did not work.

Can't import const enums in webpack with babel project

I am working on a react project which was built using create-react-app and later we ejected and modified the webpack config a lot. Right now I am having a hard time importing const enums from external libraries. I don't have control over that external package. It has the const enums defined in its d.ts files.
I have tried with babel-plugin-use-const-enum babel plugin and preset. It doesn't help me either.
My webpack config:
.....
.....
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: [paths.appSrc],
loader: require.resolve("babel-loader"),
options: {
customize: require.resolve("babel-preset-react-app/webpack-overrides"),
plugins: [
[require.resolve("babel-plugin-const-enum"), { transform: "constObject" }],
[require.resolve("#babel/plugin-transform-typescript"), { isTSX: true, optimizeConstEnums: true }],
[require.resolve("#babel/plugin-transform-react-jsx")],
[require.resolve("#babel/plugin-proposal-class-properties"), { loose: true }],
[require.resolve("#babel/plugin-proposal-nullish-coalescing-operator")],
[require.resolve("#babel/plugin-proposal-optional-chaining"), { isTSX: true }],
[require.resolve("#babel/plugin-transform-arrow-functions")],
[require.resolve("#babel/plugin-proposal-private-methods"), { loose: true }],
[
require.resolve("babel-plugin-named-asset-import"),
{
loaderMap: {
svg: {
ReactComponent: "#svgr/webpack?-svgo,+titleProp,+ref![path]",
},
},
},
],
],
presets: ["#babel/preset-env"],
},
},
.....
.....
My tsconfig:
{
"compilerOptions": {
"typeRoots": ["./typings", "node_modules/#types"],
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"noEmit": true,
"jsx": "react",
"downlevelIteration": true
},
"exclude": ["dist/**/*"],
}
The problem is that the build is successful but I am facing the runtime issue with all the const enums import like below
Uncaught TypeError: Cannot read properties of undefined (reading '<ConstEnumName>').
Package versions:
"#babel/core": "^7.11.6",
"babel-loader": "^8.1.0",
"typescript": "^3.9.7",
"webpack": "^4.44.2",
According to this thread, where the plugin's creator is involved, babel does not transpile .d.ts files, making it impossible to get enums from there. The only option seems to be migrating your config to use ts-loader and include the .d.ts files that have the enum declarations
tsconfig
{
...
"exclude": ["dist/**/*"],
"include": ["node_modules/[external_library]/**/*.d.ts"],
}

Why IDE shows me error when I import SVG file to use as React component?

I am try to using SVG Icon as React component with svgr
everything works well. I can imoport SVG and svgr convert it to ReactComponents perfectly.
but, My IDE webstorm still shows me error when I import svg like below
I am using typescript and nextjs as well.
what is real problem? is it only caused by IDE? or Should I setup additional options?
here is my config files
tsconfig.json
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"baseUrl": "src/"
},
"exclude": [
"node_modules"
],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
"**/*.svg"
]
}
next.config.js
module.exports = {
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
// Note: we provide webpack above so you should not `require` it
// Perform customizations to webpack config
// Important: return the modified config
config.plugins.push(new webpack.IgnorePlugin(/\/__tests__\//))
config.module.rules.push({
test: /\.svg$/,
use: [{
loader: '#svgr/webpack',
options: {
svgoConfig: {
plugins: {
removeViewBox: false
}
}
}
}],
})
return config
},
webpackDevMiddleware: (config) => {
// Perform customizations to webpack dev middleware config
// Important: return the modified config
return config
},
}
and no babelrc because I am using default babel setting given by nextjs.
Thanks in advance
I find by my self. It is caused by typescript. i had to declare type for .svg
I made typing.d.ts file on the root
declare module '*.svg' {
import * as React from 'react';
export const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
const src: string;
export default src;
}
The IDE does not show error any more

Rollup and typescript bundle is without editor code completion and jump to declaration

Very new to bundling. My team is used to code completion and being able to jump to the type declaration file of a corresponding component using command + click in their editor (VSCode).
However the bundle generated does not come with this behaviour... I don't know how to go form here, or what I am missing. These feature are very important to my team. Any help is appreciated 🙏
Versions
typescript: 3.7.5
rollup: 1.31.0
rollup-plugin-typescript2: 0.26.0
rollup.config.js
import babel from 'rollup-plugin-babel';
import commonjs from '#rollup/plugin-commonjs';
import resolve from '#rollup/plugin-node-resolve';
import typescript from 'rollup-plugin-typescript2';
import svgr from '#svgr/rollup';
import url from '#rollup/plugin-url';
import json from '#rollup/plugin-json';
import external from 'rollup-plugin-peer-deps-external';
import includePaths from 'rollup-plugin-includepaths';
const pkg = require('./package.json');
export default {
cache: false,
input: 'src/index.ts',
output: { file: pkg.module, format: 'esm' },
plugins: [
external({
preferBuiltins: false,
}),
babel({
exclude: /node_modules/,
plugins: ['external-helpers'],
externalHelpers: true,
}),
json(),
resolve(),
svgr({
ref: true,
svgo: false,
}),
typescript({
clean: true,
typescript: require('typescript'),
}),
url(),
includePaths({
paths: ['src'],
}),
commonjs({
namedExports: {
'prop-types': [
'oneOfType',
'func',
'shape',
'any',
'number',
'object',
'bool',
'string',
],
},
}),
],
};
tsconfig.json
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"baseUrl": "src",
"declaration": true,
"declarationMap": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"jsx": "react",
"lib": ["dom", "dom.iterable", "esnext"],
"module": "es6",
"moduleResolution": "node",
"noEmit": true,
"noErrorTruncation": true,
"outDir": "./dist",
"skipLibCheck": true,
"strict": true,
"target": "es5",
"rootDir": "src"
},
"include": ["src"],
"exclude": ["storybook", "dist"]
}
package.json
Relevant bits only 👇
{
"main": "dist/index.js",
"module": "dist/index.js",
"typings": "dist/index.d.ts",
}
Found the issue - it was because I was using absolute paths. Changing import paths to relative imports or using a plugin to convert absolute to relative import paths when building fixes this issue.

Resources