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

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

Related

Typescript request-body types validation always pass for invalid body schema

export interface UpdateRule {
rule_name : string,
weightage ?: number,
description ?: string,
dependency ?: object | null,
conditions ?: object,
facts ?: object,
status ?: string
}
Request Body
{
"rule": 1,
"weightage": "3"
}
Handler Function
export const updateRule = async (req, res) => {
const body: UpdateRule = req.body;
res.send("success");
}
Typescript never gives me error for any request body schema. It always gives success response.
tsconfig.json
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"noImplicitAny": false,
"outDir": "build",
"strict": true,
"baseUrl": "./",
"removeComments": false,
"sourceMap": true,
"typeRoots": [
"node_modules/#types"
],
"types": [
"node",
"express"
],
"esModuleInterop": true,
"resolveJsonModule": true,
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts",
".vscode",
]
}
Please help me to rectify the issue. So that typescript gives me error for incorrect body schema.

I have this error : ERROR: Cannot use import statement outside a module

I need to execute seed file and when I execute the file this error appears. How can I solve it?
ERROR: Cannot use import statement outside a module
This is my tsconfig.js:
{
"compilerOptions": {
"module": "commonjs",
"target": "es2019",
"lib": [
"dom",
"es2019"
],
// "baseUrl": "./src",
"moduleResolution": "node",
"outDir": "dist",
"sourceMap": true,
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"typeRoots": [
"./types",
"./node_modules/#types"
],
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
".vscode"
]
}
And this is my seeds:
'use strict';
import { Player } from "../../app/models/player";
module.exports = {
up: async (queryInterface, Sequelize) => {
return Player.bulkCreate(
[
{ name: "Inbal", email: "inbal#test.co.il",phone: "1111" },
{ name: "Tal", email: "tal#test.co.il",phone: "2222" },
{ name: "Sivan", email: "sivan#test.co.il" ,phone: "3333"}
],
{ hooks: true, individualHooks: true, validate: true }
);
},
down: async (queryInterface, Sequelize) => {
await queryInterface.bulkDelete("players", null, {});
}
};
When I run npx sequelize-cli-ts db:seed:all the error appears.
Either use require instead of import in your seed file or you could also try to set
"type": "module"
in your package.json

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?

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

Is there anyway to extend a jest configuration file?

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

Resources