Is there anyway to extend a jest configuration file? - jestjs

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

Node JS 14 unable to use absolute path import (Cloud Functions)

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?

Jest config to be able to run tests using node modules source

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"
]
}

How to make VSCode open original TS file of "src" when hitting a breakpoint in node app

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]",
},
}

Incorrect version of jest trying to run jest

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).

Jest Testing Coverage - Errors When Files Don't Have Tests

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.

Resources