Within a node app where I'm using Jest to test client side code (testEnvironment: 'jsdom') and server side code (testEnvironment:'node') as well collecting code coverage for both client and server side.
Currently I'm using 4 Jest config files with lots of redundant configuration to accomplish this.
client
{
"bail": true,
"verbose": true,
"notify": true,
"scriptPreprocessor": "./node_modules/babel-jest",
"testPathIgnorePatterns": [
"./node_modules",
"./coverage",
"./dist",
"./build"
],
"testRegex": "\\.test\\.js"
}
client coverage
{
"bail": true,
"verbose": true,
"notify": true,
"scriptPreprocessor": "./node_modules/babel-jest",
"testPathIgnorePatterns": [
"./node_modules",
"./coverage",
"./dist",
"./build"
],
"testRegex": "\\.test\\.js",
"collectCoverageFrom": ["**/*.js", "!**/node_modules/**"],
"collectCoverage": true,
"coverageDirectory": "./coverage",
"coveragePathIgnorePatterns": [
"./node_modules",
"./coverage",
"./dist",
"./build",
"./test"
],
"coverageThreshold": {
"global": {
"branches": 100,
"functions": 100,
"lines": 100,
"statements": 100
}
}
}
server
{
"bail": true,
"verbose": true,
"notify": true,
"scriptPreprocessor": "./node_modules/babel-jest",
"testPathIgnorePatterns": [
"./node_modules",
"./coverage",
"./dist",
"./build"
],
"testRegex": "\\.test\\.js",
"testEnvironment": "node"
}
server coverage
{
"bail": true,
"verbose": true,
"notify": true,
"scriptPreprocessor": "./node_modules/babel-jest",
"testPathIgnorePatterns": [
"./node_modules",
"./coverage",
"./dist",
"./build"
],
"testRegex": "\\.test\\.js",
"testEnvironment": "node",
"collectCoverageFrom": ["**/*.js", "!**/node_modules/**"],
"collectCoverage": true,
"coverageDirectory": "./coverage",
"coveragePathIgnorePatterns": [
"./node_modules",
"./coverage",
"./dist",
"./build",
"./test"
],
"coverageThreshold": {
"global": {
"branches": 100,
"functions": 100,
"lines": 100,
"statements": 100
}
}
}
How can I achieve this without repeating my configuration 4 times? I've looked at the preset configuration option. Using that I have to create a separate package for each configuration. Is that the recommended way?
Yes, you could define shared jest.config.js
and reuse it in your specific configs:
It's nice to use <rootDir> in all paths in your shared config, so those could be reused too.
client/jest.config.js
const sharedConfig = require('../jest.config.js');
module.exports = {
...sharedConfig,
'rootDir': './',
}
server/jest.config.js
const sharedConfig = require('../jest.config.js');
module.exports = {
...sharedConfig,
'rootDir': './',
"testEnvironment": "node"
}
You could also reuse jest defaults if needed: Jest Documentation - Configuring Jest
Yes, since Jest v20 you can define config as a JS file and use it to share common parts of the similar configs. Docs on configuring Jest.
By default Jest looks up for:
jest.config.js
"jest" entry in package.json
...and treats the parent directory as a rootDir.
Also be sure to check out the projects option, which makes it easier to run Jest inside monorepos (e.g. client + server code in one codebase). See this answer for reference: Testing two environments with jest
Related
I'm trying to use absolute path import form my custom modules and VSCode has no prob recognising them. The problem is that when I run firebase deploy which runs first eslint I get errors.
3:24 error Unable to resolve path to module '#src/stripe/lib/secret-key' import/no-unresolved
I have tried to set this
"import/resolver": {
"typescript": {}
}
in the eslintrc.js but I just get more and more errors. I have also tried to install some plugins but no luck.
Here is the line which throws the error.
import { stripe } from '#src/stripe/lib/secret-key'
tsconfig
{
"compilerOptions": {
"module": "commonjs",
"noImplicitReturns": true,
"noUnusedLocals": true,
"outDir": "lib",
"sourceMap": true,
"strict": true,
"target": "es2017",
"allowSyntheticDefaultImports": true,
"baseUrl": "./",
"paths": {
"#src/*": [
"./src/*"
]
}
},
"compileOnSave": true,
"include": [
"src"
]
}
eslintrc.js
module.exports = {
env: {
browser: true,
es6: true,
node: true,
},
extends: [
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript",
],
parser: "#typescript-eslint/parser",
parserOptions: {
project: "tsconfig.json",
sourceType: "module",
},
plugins: [
"#typescript-eslint",
"import",
],
rules: {
"#typescript-eslint/adjacent-overload-signatures": "error",
"#typescript-eslint/no-empty-function": "error",
"#typescript-eslint/no-empty-interface": "warn",
"#typescript-eslint/no-floating-promises": "error",
"#typescript-eslint/no-namespace": "error",
"#typescript-eslint/no-unnecessary-type-assertion": "error",
"#typescript-eslint/prefer-for-of": "warn",
"#typescript-eslint/triple-slash-reference": "error",
"#typescript-eslint/unified-signatures": "warn",
"constructor-super": "error",
eqeqeq: ["warn", "always"],
"import/no-deprecated": "warn",
"import/no-extraneous-dependencies": "error",
"import/no-unassigned-import": "warn",
"no-cond-assign": "error",
"no-duplicate-case": "error",
"no-duplicate-imports": "error",
"no-empty": [
"error",
{
allowEmptyCatch: true,
},
],
"no-invalid-this": "error",
"no-new-wrappers": "error",
"no-param-reassign": "error",
"no-redeclare": "error",
"no-sequences": "error",
"no-shadow": [
"error",
{
hoist: "all",
},
],
"no-throw-literal": "error",
"no-unsafe-finally": "error",
"no-unused-labels": "error",
"no-var": "warn",
"no-void": "error",
"prefer-const": "warn",
},
settings: {
jsdoc: {
tagNamePreference: {
returns: "return",
},
},
},
};
Any idea how to make this work?
I have two projects:
App
A library (to share code)
On my app, I have one test using directly the source of my npm package library
import { mockAddress } from '#xxx/library/src/entities/address';
Issue
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:
• 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.
What I tried
I tried to add the folder of my library to transformIgnorePatterns
transformIgnorePatterns: [
'<roodDir>/node_modules/(?!vee-validate/dist/rules)',
'<roodDir>/node_modules/(?!#xxx/library/src)',
],
I tried to add transform
'\\.(ts|js)x?$': 'ts-jest'
EDIT 1
transform: {
'vee-validate/dist/rules': 'babel-jest',
'\\.(ts|tsx)?$': 'ts-jest',
},
transformIgnorePatterns: [
'node_modules/(?!vee-validate/dist/rules|#xxx/lib/)',
],
jest.config
module.exports = {
globals: {
'ts-jest': {
isolatedModules: true,
},
},
verbose: true,
preset: '#vue/cli-plugin-unit-jest/presets/typescript-and-babel',
collectCoverage: false,
collectCoverageFrom: [
'**/entities/**/*.ts',
'**/services/**/*.ts',
'**/store/**/*.ts',
'**/ui/components/**/*.{js,vue}',
'**/ui/views/**/**.{js,vue}',
'!src/main.ts', // No need to cover bootstrap file
'!**/store.ts',
'!**/*.mock.ts',
'!**/*.types.ts',
'!**/index.ts',
],
transform: {
'vee-validate/dist/rules': 'babel-jest',
'^.+\\.tsx?$': 'ts-jest',
},
transformIgnorePatterns: [
'<roodDir>/node_modules/(?!vee-validate/dist/rules)',
],
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1',
},
testMatch: [
'**/*.(spec|test).(js|jsx|ts|tsx)',
],
roots: [
'<rootDir>/src',
],
testEnvironmentOptions: {
// Allow test environment to fire onload event
// See https://github.com/jsdom/jsdom/issues/1816#issuecomment-355188615
resources: 'usable',
},
reporters: [
'default',
[
'jest-trx-results-processor',
{
outputFile: './coverage/test-results.trx',
defaultUserName: 'user name to use if automatic detection fails',
},
],
],
};
tsconfig.json
{
"compilerOptions": {
"strictNullChecks": false,
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env",
"jest",
"vuetify",
"vue-meta"
],
"paths": {
"#/*": [
"src/*"
]
},
"lib": [
"es6",
"es2017",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx",
],
"exclude": [
"node_modules"
]
}
I have a CLI node app that I am trying to debug with VSCode. It works pretty well, however when hitting a breakpoint, VSCode opens a new code view from the source map file instead of the actual TS file located in my "src" folder. This is kind of annoying. When I run some JS code in a browser using VSCode as a debugger, VSCode opens the actual TS file as expected. How do I get this behavior also with node?
launch.json:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-node",
"request": "launch",
"name": "Node",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/bin/js/index.js",
"console": "integratedTerminal",
"cwd": "${workspaceFolder}/bin/js",
"args": [
"authorize"
]
}
]
}
tsconfig.json:
{
"compilerOptions": {
"baseUrl": "./src",
"moduleResolution": "node",
"module": "ES2020",
"target": "ES2018",
"allowSyntheticDefaultImports": true,
"jsx": "react",
"strict": true,
"strictPropertyInitialization": true,
"noEmitOnError": true,
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"outDir": "./bin",
"sourceMap": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
webpack.config.json:
const path = require("path");
const webpack = require("webpack");
const { merge } = require('webpack-merge');
const commonConfig = {
target: 'node',
entry: "./src/Startup.ts",
module: {
rules: [
{
test: /\.tsx?$/,
use: [{
loader: "ts-loader"
}]
}
]
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx"],
modules: ["./src", "node_modules"]
},
output: {
path: path.resolve(__dirname, "./bin/js/"),
filename: "index.js",
},
plugins: [
new webpack.DefinePlugin({ "global.GENTLY": false })
],
externals: {
'cliui': 'commonjs2 cliui',
'y18n': 'commonjs2 y18n',
'yargs-parser': 'commonjs2 yargs-parser',
}
}
const developmentConfig = {
mode: 'development',
devtool: 'source-map',
stats: {
warnings: false
}
}
const productionConfig = {
mode: 'production'
}
module.exports = (env, argv) => {
switch(argv.mode) {
case 'development':
return merge(commonConfig, developmentConfig);
case 'production':
return merge(commonConfig, productionConfig);
default:
throw new Error(`Configuration '${argv.mode}' does not exists.`);
}
}
The TS file paths generated by Webpack in the source map files are using the webpack protocol that VSCode did not understand. I solved it by adding this parameter in my webpack.config.js so the source map contains absolute paths to the TypeScript files instead:
const commonConfig = {
output: {
devtoolModuleFilenameTemplate: "[absolute-resource-path]",
},
}
I have jest tests in my angular project.
I have a package.json file specifying the version of jest I would like to use to run the test. The file includes:
"#types/jest": "^24.0.18",
"jest": "^24.9.0",
"jest-preset-angular": "^7.1.1",
The jest config also includes:
"setupFilesAfterEnv": [
"<rootDir>/setup-jest.ts"
],
This is where the issue occurs. When trying to run jest, I get the following message:
● Validation Warning:
Unknown option "setupFilesAfterEnv" with value ["<rootDir>/setup-jest.ts"] was found.
This is probably a typing mistake. Fixing it will remove this message.
Configuration Documentation:
https://jestjs.io/docs/configuration.html
I had a look at jest -h and found a flag which gives me the setup of the jest environment.
jest --showConfig
This however shows that I am running jest on version
"version": "23.6.0"
So my question lies here. How come after I do an npm i, the jest version trying to run the tests is different / old.
I tried installing jest-cli with the -g flag and the save-dev flag.
Also trying to run tests in VS Code, if thats any help.
Please help.
Thank you in advance.
Full log of npx jest --showConfig
● Validation Warning:
Unknown option "setupFilesAfterEnv" with value ["<rootDir>/setup-jest.ts"] was found.
This is probably a typing mistake. Fixing it will remove this message.
Configuration Documentation:
https://jestjs.io/docs/configuration.html
{
"configs": [
{
"automock": false,
"browser": false,
"cache": true,
"cacheDirectory": "/var/folders/bs/wrvrgl6132df8l5ndxv40m3m0000gn/T/jest_dx",
"clearMocks": false,
"coveragePathIgnorePatterns": [
"/node_modules/",
"setup-jest.ts"
],
"detectLeaks": false,
"detectOpenHandles": false,
"errorOnDeprecated": false,
"filter": null,
"forceCoverageMatch": [],
"globals": {
"ts-jest": {
"tsConfig": "<rootDir>/tsconfig.spec.json",
"stringifyContentPathRegex": "\\.html$",
"astTransformers": [
"jest-preset-angular/InlineHtmlStripStylesTransformer"
]
}
},
"haste": {
"providesModuleNodeModules": []
},
"moduleDirectories": [
"node_modules"
],
"moduleFileExtensions": [
"ts",
"html",
"js",
"json"
],
"moduleNameMapper": [
[
"#app/(.*)",
"/Users/name/Projects/project/src/app/$1"
],
...
],
"modulePathIgnorePatterns": [],
"name": "6caa4...",
"prettierPath": "/Users/name/Projects/project/node_modules/prettier/index.js",
"resetMocks": false,
"resetModules": false,
"resolver": null,
"restoreMocks": false,
"rootDir": "/Users/name/Projects/project",
"roots": [
"/Users/name/Projects/project"
],
"runner": "jest-runner",
"setupFiles": [],
"setupTestFrameworkScriptFile": null,
"skipFilter": false,
"snapshotSerializers": [],
"testEnvironment": "/Users/name/Projects/project/node_modules/jest-environment-jsdom-thirteen/build/index.js",
"testEnvironmentOptions": {},
"testLocationInResults": false,
"testMatch": [
"**/__tests__/**/*.js?(x)",
"**/?(*.)+(spec|test).js?(x)"
],
"testRegex": "",
"testRunner": "/Users/name/node_modules/jest-jasmine2/build/index.js",
"testURL": "http://localhost",
"timers": "real",
"transform": [
[
"^.+\\.(ts|js|html)$",
"/Users/name/Projects/project/node_modules/ts-jest/dist/index.js"
]
],
"watchPathIgnorePatterns": []
}
],
"globalConfig": {
"bail": false,
"changedFilesWithAncestor": false,
"collectCoverage": true,
"collectCoverageFrom": null,
"coverageDirectory": "/Users/name/Projects/project/coverage",
"coverageReporters": [
"json",
"text",
"lcov",
"clover"
],
"coverageThreshold": null,
"detectLeaks": false,
"detectOpenHandles": false,
"errorOnDeprecated": false,
"expand": false,
"filter": null,
"globalSetup": null,
"globalTeardown": null,
"listTests": false,
"maxWorkers": 7,
"noStackTrace": false,
"nonFlagArgs": [],
"notify": false,
"notifyMode": "always",
"passWithNoTests": false,
"projects": null,
"rootDir": "/Users/name/Projects/project",
"runTestsByPath": false,
"skipFilter": false,
"testFailureExitCode": 1,
"testPathPattern": "",
"testResultsProcessor": null,
"updateSnapshot": "new",
"useStderr": false,
"verbose": null,
"watch": false,
"watchman": true
},
"version": "23.6.0"
}
Showing npm config get log here too:
; cli configs
metrics-registry = "http://.../.../npm-group/"
scope = ""
user-agent = "npm/6.9.0 node/v10.15.3 darwin x64"
; project config /Users/user/Projects/project/.npmrc
registry = "http://.../.../npm-group/"
; node bin location = /Users/user/.nvm/versions/node/v10.15.3/bin/node
; cwd = /Users/user/Projects/project
; HOME = /Users/user
; "npm config ls -l" to show all defaults.
I had the same issue, after a long search I've tried this:
type jest
Which gave me the location:
/usr/local/bin/jest
Renaming this file (or deleting it), solved the problem (note that now running jest will give command not found).
I have Jest tests in my React project, and I don't have coverage on all files yet. However, I am getting these errors:
Failed to collect coverage from /home/user/Development/VideoManager/VideoManagerClient/src/components/AppContent/VideoListLayout/VideoListLayout.js
ERROR: Cannot read property 'coverageData' of null
STACK: TypeError: Cannot read property 'coverageData' of null
The file being mentioned here does not yet have unit tests created for it. I want it to simply be tracked as lacking coverage and thus bring my whole coverage stats down, rather than throwing an error.
In addition, when I run individual tests in my IDE, my logs get filled with even more of these errors because it's not running the other tests.
How can I fix this?
PS. Here is my Jest configuration:
"jest": {
"collectCoverage": true,
"coverageReporters": [
"html"
],
"coverageThreshold": {
"global": {
"branches": 80,
"functions": 80,
"lines": 80,
"statements": 80
}
},
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
"!src/**/*.d.ts",
"!src/serviceWorker.js"
],
"resolver": "jest-pnp-resolver",
"setupFiles": [
"react-app-polyfill/jsdom"
],
"setupFilesAfterEnv": [
"<rootDir>/test/setupTests.js"
],
"testMatch": [
"<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
"<rootDir>/src/**/?(*.)(spec|test).{js,jsx,ts,tsx}",
"<rootDir>/test/**/*.{js,jsx,ts,tsx}"
],
"testPathIgnorePatterns": [
"<rootDir>/test/setupTests.js",
"<rootDir>/test/mock/.*",
"<rootDir>/test/exclude/.*"
],
"testEnvironment": "jsdom",
"testURL": "http://localhost",
"transform": {
"^.+\\.(js|jsx|ts|tsx)$": "<rootDir>/node_modules/babel-jest",
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
},
"transformIgnorePatterns": [
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx)$",
"^.+\\.module\\.(css|sass|scss)$"
],
"moduleNameMapper": {
"^react-native$": "react-native-web",
"^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy",
"\\.(css|sass|scss)$": "identity-obj-proxy"
},
"moduleFileExtensions": [
"web.js",
"js",
"web.ts",
"ts",
"web.tsx",
"tsx",
"json",
"web.jsx",
"jsx",
"node"
]
}
I had the exact same issue while using jest version 24.1.0 and babel-jest version 23.6.0.
Solved it by updating babel-jest version to 24.0.0.