Jest - cannot find module - javascript

I have the following test:
jest.mock('#my-company/my-package/dist/browser');
import { broadcast } from '#my-company/my-package/dist/browser';
...
The file it is importing looks something like this within the node_modules folder:
import someFunction from '#my-company/some-other-package';
...
This is throwing the following error message when I run the test:
Cannot find module '#my-company/some-other-package' from 'browser.js'
Why would I be getting this error?
I have been going through my jest config file and can't spot anything that might be wrong. Here is the config file:
module.exports = {
testPathIgnorePatterns: [
'/node_modules/',
'/bower_components/',
'/cypress/',
'/test/', // test directory contains mocha and chai tests for now
],
transform: {
'.(js|jsx)': '#sucrase/jest-plugin',
},
transformIgnorePatterns: [`node_modules/(?!#my-company/my-package)`],
resolver: '#my-company/jest-bower-resolver',
setupFilesAfterEnv: ['<rootDir>/test/setup-tests.js'],
moduleDirectories: ['node_modules', 'bower_components', "<rootDir>"],
collectCoverageFrom: [
'**/*.{js,jsx}',
'!**/*.spec.js',
'!**/test/**',
'!**/test-jest/**',
'!**/cypress/**',
'!**/coverage/**',
'!**/node_modules/**',
'!**/bower_components/**',
'!**/public/**',
],
coverageDirectory: '<rootDir>/coverage/',
};
It is important to note that the package #my-company/my-package must be added to transformIgnorePatterns part of the config otherwise it won't be transpiled
Thanks

Related

Eslint doesn't respect jsconfig paths

I have my express.js project in monorepo. I want to add custom path alias to it.
The directory structure is:
./
server/
----> jsconfig.json
----> .eslintrc.js
----> src/
--------> index.js
--------> modules/auth
-------------> auth.controller.js
jsconfig.json
{
"compilerOptions": {
"module": "ES6",
"baseUrl": "./",
"paths": {
"#modules/*": [
"src/modules/*"
]
}
},
"exclude": ["node_modules"]
}
.eslintrc.js
module.exports = {
env: {
es2021: true,
node: true,
},
extends: [
'airbnb-base',
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
},
rules: {
'no-console': 'error',
'no-debugger': 'error',
},
settings: {
'import/resolver': {
alias: {
map: [
['#modules/*', 'src/modules/*'],
],
extensions: ['.js', '.json'],
},
},
},
};
Simply, I just tried to import auth controller in my index.js file.
import authRoutes from '#modules/auth/auth.routes';
but I get the following error: Unable to resolve path to module '#modules/auth/auth.controller' .eslint import/no-unresolved
please, don't suggest to turn off the rule.
I've alreadyy tried eslint-import-resolver-jsconfig, but I got Cannot resolve jsConfig, SyntaxError } on 150.
Because I used monorepo, there was a problem for ESLint or even lint-staged.
So now I have only one project per repository and:
Added custom paths in jsconfig.json:
"paths": {
"#modules/*": [
"./src/modules/*"
]
}
Installed eslint-import-resolver-jsconfig and added the following configuration to the eslint.json:
"extends": [
"airbnb-base",
"eslint:recommended"
],
"plugins": ["import"],
"settings": {
"import/resolver": {
"jsconfig": {
"config": "jsconfig.json"
}
}
}
Installed the Babel plugin babel-plugin-module-resolver and added the following settings to the .babelrc:
"plugins": [
[
"module-resolver",
{
"alias": {
"#modules": "./src/modules"
}
}
]
]
But, again: This only works if you have one project per repository and all your configuration files (.*rc, package.json, etc) are in the root level.
To achieve the above I use the module-alias package.
After installing it as a normal dependency, npm i --save module-alias, add the following to your package.json:
"_moduleAliases": {
"#modules": "./src/modules"
}
That will basically define the mappings for all the aliases you want to define.
To make it work, you will now need to import the following on top of your application under index.js:
require("module-alias/register"); // If using commonJS
// or
import "module-alias/register"; // If transpiling es6
You are now all set and should be able to import your files with absolute paths looking as:
const authRoutes = require("#modules/auth/auth.routes")
// or
import authRoutes from "#modules/auth/auth.routes";
In case eslint still flags the unresolved path, you may need to update your jsconfig.json or tsconfig.json to contain the below:
"paths": {
"#modules/*": ["src/modules/*"]
}
You can find the package documentation and read more about its usage here.

ts-jest cannot resolve tsconfig aliases

I have a typescript project and I setup aliases in ts.config.json
{
"compilerOptions": {
"paths": {
"#pkg/*": ["./packages/*"],
},
}
}
in my ts files I can shorten my import paths
// example.ts
import {someThing} from '#pkg/mypackage'
it works fine with tsc and vscode can recognize the alias path correctly.
but when I run npm t whitch runs jest it fails
Cannot find module '#pkg/mypackage' from 'example.ts'
jest.config.js
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
transform: {
"^.+\\.tsx?$": "ts-jest",
},
};
I added this to my package.json file
"jest": {
"moduleNameMapper": {
"#pkg/(.*)": "<rootDir>/packages/$1"
}
}
I managed to use pathsToModuleNameMapper, but I had this issue
https://github.com/kulshekhar/ts-jest/issues/2709
I had the same problem, but managed to get it working by using a couple of plugins. I also have some extra matchers at the end for some additional test types.
My Jest-base.config.js has the tsconfig-paths-jest plugin installed and running. This plugin solved my tsconfig path issues.
I use a common base file for common configuration between unit tests and end to end tests, both of which I run via Jest currently.
jest-base.config.ts
const tsconfig = require('./tsconfig.json');
const moduleNameMapper = require('tsconfig-paths-jest')(tsconfig);
module.exports = {
moduleNameMapper,
preset: 'ts-jest',
testEnvironment: 'node',
rootDir: './',
collectCoverage: true,
collectCoverageFrom: [
'<rootDir>/**/*.ts',
'!<rootDir>/**/*.interface.ts',
'!<rootDir>/**/*.mock.ts',
'!<rootDir>/**/*.module.ts',
'!<rootDir>/**/__mock__/*',
'!<rootDir>/src/main.ts'
],
coverageProvider: 'v8',
coverageReporters: [
'clover',
'json',
'lcov',
'text',
'text-summary'
],
resetModules: true,
setupFiles: [
'dotenv/config'
],
// Add the community jest-extended matchers
setupFilesAfterEnv: [
'jest-extended'
],
verbose: false
};
My jest.config.js (for unit tests) will extend my jest-base.config.js to add unit test specific code such as coverage requirements, where to store output for coverage etc.
jest.config.js
const JestBaseConfiguration = require('./jest-base.config');
module.exports = Object.assign(JestBaseConfiguration, {
moduleFileExtensions: ['js', 'json', 'ts'],
testRegex: '.e2e-spec.ts$',
transform: {
'^.+\\.(t|j)s$': 'ts-jest'
},
...

Babel module resolver not working with react-native

My babel module resolver is not working with React-Native (neither does intellij in VScode)
Here, Is my babel config
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module-resolver',
{
root: ['./'],
alias: {
'#assets': './src/assets',
'#modules': './src/modules',
'#config': './src/config',
'#utils': './src/utils',
},
},
],
],
};
And jsconfig.json
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"#assets": ["./assets"],
"#modules": ["./modules"],
"#config": ["./config"],
"#utils": ["./utils"]
}
}
}
I changed import for one of my files and this is the error I get when I executed the build command from Xcode
Error: Error loading assets JSON from Metro. Ensure you've followed
all expo-updates installation steps correctly. Unable to resolve
module ../../modules/store/components/Filters from
src/utils/Router.js:
None of these files exist:
Where I imported the file like this
import Filters from '#modules/store/components/Filters';
I had the same problem, I just removed the '#' from my aliases and it seems working fine now.
Here is my babel.config.js
module.exports = function (api) { ■ File is a CommonJS module; it may be converted to an ES6 module.
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: [
[
require.resolve("babel-plugin-module-resolver"),
{
root: ["./src/"],
alias: {
// define aliases to shorten the import paths
components: "./src/components",
containers: "./src/containers",
contexts: "./src/contexts",
interfaces: "./src/interfaces",
organizer: "./src/screens/organizer",
screens: "./src/screens",
},
extensions: [".js", ".jsx", ".tsx", ".ios.js", ".android.js"],
},
],
],
};
};
Try resetting the cache, if above suggested answers don't work
react-native start --reset-cache
This worked for me. For more info see here
Change your module-resolver's root to ['./src/']:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module-resolver',
{
root: ['./src/'], // <-- here ✅
alias: {
'#assets': './src/assets',
'#modules': './src/modules',
'#config': './src/config',
'#utils': './src/utils',
},
},
],
],
};

Jest - No output of test results

I've been having difficulties with Jest ever since I tried to begin using it. No tests I try to run and with what options I try to pass Jest, I never get the 'Pass' / 'Fail' output results in the console.
Jest always just outputs 'Done'
Using the 'Nuxt CLI' there is a default test written as:
import { mount } from '#vue/test-utils'
import Logo from '#/components/Logo.vue'
describe('Logo', () => {
test('is a Vue instance', () => {
const wrapper = mount(Logo)
expect(wrapper.isVueInstance()).toBeTruthy()
})
})
So far I have tried:
yarn test
yarn test --verbose
yarn test --watch
yarn test --watchAll
yarn test --no-watchmen
Every single time, the result is as follows:
yarn run v1.21.1
$ jest
Done in 0.72s.
Current jest.config.js:
module.exports = {
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/$1',
'^~/(.*)$': '<rootDir>/$1',
'^vue$': 'vue/dist/vue.common.js'
},
moduleFileExtensions: ['js', 'vue', 'json'],
transform: {
'^.+\\.js$': 'babel-jest',
'.*\\.(vue)$': 'vue-jest'
},
collectCoverage: true,
collectCoverageFrom: [
'<rootDir>/components/**/*.vue',
'<rootDir>/pages/**/*.vue'
]
}
This seems to be the default config for Nuxt.
Any help would be appreciated
So I figured it out (kind-of).
My tests run fine with the following:
yarn test --no-watchman
I can't figure out why watchman is causing me so many issues but this does seem to help.
More Info:
https://github.com/facebook/jest/issues/2219
Jest looks for files ending with .spec.js or .test.js file formats. Try putting your test in a file ending with .spec.js or .test.js file. Also you can configure jest, using jest.config.js file.
One such example of using jest.config.js file is
const path = require('path')
module.exports = {
rootDir: path.resolve(__dirname),
moduleFileExtensions: [
'js',
'json',
'vue',
'ts'
],
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1'
},
transform: {
".*\\.(vue)$": "<rootDir>/node_modules/vue-jest",
"^.+\\.(js|jsx)?$": "<rootDir>/node_modules/babel-jest",
"^.+\\.ts$": "<rootDir>/node_modules/ts-jest"
},
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
snapshotSerializers: [
"jest-serializer-vue"
],
testEnvironment: "jsdom",
setupFiles: [
"<rootDir>/globals.js"
]
}

Using jquery in a shared webpack module, which is outside the webpack root

I have multiple layouts, which depend on some shared typescript files, thats why I want to share this files with multiple layouts which are using webpack.
I'm trying to include jquery in my ajax.ts and get this error:
ERROR in ../_shared/ajax.ts
Module not found: Error: Can't resolve 'jquery' in '{...}/layouts/_shared'
_shared/ajax.ts:
import * as $ from 'jquery';
export class AjaxListener {
constructor(){
// use jquery with $
}
}
layoutA/app.ts:
import { AjaxListener } from "../_shared/ajax";
import { App } from "../_shared/app";
let app = new App();
let ajaxListener = new AjaxListener();
My Folder Structure looks like this:
/layouts
/_shared
/ajax.ts
/app.ts
/layoutA
/app.ts
/webpack.config.js
/package.json (contains "#types/jquery": "^2.0.47" and "jquery": "^3.2.1")
/tsconfig.json
tsconfig.json:
{
"compilerOptions": {
"module": "es6",
"target": "es6",
"sourceMap": true
},
"exclude": [
"node_modules",
"typings/browser",
"typings/browser.d.ts",
"typings/main",
"typings/main.d.ts"
]
}
webpack.config.js:
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var path = require("path");
var distPath = path.join(__dirname, "dist");
module.exports = [
{
entry: {
app: ['./app.sass', './app.ts']
},
resolve: {
extensions: [".tsx", ".js", ".ts", ".sass"]
},
cache: false,
output: {
path: distPath,
filename: "[name]_scripts.js"
},
module: {
rules : [
{
enforce: 'pre',
// "test" is commonly used to match the file extension
test: /\.js$/,
loader: "source-map-loader"
},
{
// "test" is commonly used to match the file extension
test: /\.tsx?$/,
exclude: [/node_modules/],
use: [ 'babel-loader', 'ts-loader' ]
},
{
test: /\.sass$/,
use: [
{
loader: "style-loader" // creates style nodes from JS strings
},{
loader: "css-loader", options: { sourceMap: true } // translates CSS into CommonJS
},{
loader: "sass-loader", options: { sourceMap: true } // compiles Sass to CSS
}
]
}
]
},
devtool: "eval"
}
]
If I try to import jquery inside layoutA/app.ts file (webpack root), it works fine. Since the ajax.ts lives outside this folder, which is the best way to import libraries like jquery, lodash etc. in these files?
The following points must be observed for the best way to load js libraries in your context:
Install every js library (e.g. jquery) with a package manager like npm
To each library it needs a TypeScript definitions file (e.g. #types/jquery, to find under npmjs.com)
Install this TypeScript definition file also with npm
Note every TypeScript definition in the tsconfig.json under "files" like
"files":[
"node_modules/#types/jquery/index.d.ts",
"node_modules/#types/requirejs/index.d.ts",
]
Do this compellingly (point 1-4) with the library requirejs. This is a js file and module loader.
Now you are ready to load the js library in the TypeScript main file like:
require(["jquery", "urijs"], function($, uri) {
// your code
});
Other notes:
In the index.html file: reference under the script tags only the js bundle files, builded by e.g. webpack.
Webpack needs a TypeScript loader.
Reference exported TypeScript classes in the tsconfig.json file under 'files' and also in the TypeScript file like:
import {Car} from "./classes/Car";
Hope it helps you, to get a proper structur!
Supplement:
Try the following: reference a js library in your ayax.ts like:
private example = require("./[path to npm library]/node_modules/test/src/test.js");
If you call the library name like 'test' in the require command, then its not possible to resolve 'test'. It try to resolve over the package.json and can not find it because its outside of the root.

Categories