Vite with Jest: cannot find module start with alias '#' - jestjs

I'm using Jest in Vite. It works until I import a module from node_module.
import { defineComponent } from 'vue'
import { useCookies } from '#vueuse/integrations/useCookies'
I got this error.
FAIL src/components/MyComponent/index.test.ts
● Test suite failed to run
Cannot find module '#vueuse/integrations/useCookies' from 'src/components/MyComponent/index.vue'
Require stack:
src/components/MyComponent/index.vue
src/components/MyComponent/index.test.ts
16 | <script lang="ts">
17 | import { defineComponent } from 'vue'
> 18 | import { useCookies } from '#vueuse/integrations/useCookies'
| ^
19 |
20 | export default defineComponent({
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:306:11)
I guess somehow Jest cannot resolve the module starts with '#'. Maybe I should write a moduleNameMapper? I also tried to install vite-jest, but somehow my app just crash, maybe I mess up something.
Anyway, thanks for your time, and if you need more information like my jest.config.js or vite.config.ts, please let me know.
Thank you.

Use moduleNameMapper in your jest.config.js file like following:
module.exports = {
//...
moduleNameMapper: {
"^#/(.*)$": "<rootDir>/src/$1",
},
};
Also, if you are using TypeScript, you should add the following to your tsconfig.json file as well:
{
"compilerOptions": {
"paths": {
"#/*": ["./src"]
}
}
}

Related

React: Absolute Paths from Root Folder using ViteJS with TypeScript

So, in React, using vite, I'm trying to do the following structure, but seems I can't get it to work because I'm missing a concept or something, so the structure is as follows:
src/utils
src/routes
src/index.tsx
src/main.tsx
And on the index.tsx, I want to import utils and routes, and then call them at any root level as following: import {Routes, Utils} from "#", but the way I did is not working.
Meanwhile, this is how I configured it with vite:
resolve: {
alias: {
"#": path.resolve(__dirname, "src"),
},
},
Make sure index.tsx exports everything from src/utils and src/routes:
// src/index.tsx
export * from './routes'
export * from './utils'
And configure TypeScript with a path alias for #:
// tsconfig.json
{
"compilerOptions": {
"paths": {
"#": ["./src"], // 👈 needed for barrel imports from '#'
"#/*": ["./src/*"]
}
}
}
demo

Jest test gives me "Cannot find module" when running tests, but the code compiles fine outside of tests. Whats up?

I am writing my first test for a large application using NestJS and TypeScript. I want to import an entity which imports an interface from a module in another folder. This is proving challenging.
The project has a structure like
apps
..apis
--..web-api
----..src
----..package.json
----..jest.config.js
------..app
--------..profiles
----------.._entities
------------..profile.entity.spec.ts <--- the test
------------..profile.entity.ts
libs
--app-interfaces
----src
------lib
--------profile
----------index.ts <--- the files the test is trying to import and test
----------gender.enum.ts
----------profile.interface.ts
In profile.entity.spec.ts I have:
import { ProfileEntity } from "./profile.entity";
import { GenderEnum, ProfileTypeEnum } from '../../../../../../../libs/app-interfaces/src/lib/profile';
// all that ../../ is what I have to do to get to the import and have it recognized in this .spec file
// it doesn't recognize the # symbol taking us to the root of the project
describe('Profile class', () => {
it('should make a profile with no fields', () => {
const profile = new ProfileEntity();
expect(profile).toBeTruthy();
});
});
and in profile.entity.ts:
import { Column, CreateDateColumn, DeleteDateColumn, Entity, PrimaryColumn, UpdateDateColumn } from 'typeorm';
import { GenderEnum, IProfile, ProfileTypeEnum } from '#ourProject/app-interfaces';
#Entity({ name: 'profile' })
export class ProfileEntity implements IProfile {
#PrimaryColumn({ nullable: false, unique: true })
id: string;
The profile.entity.ts file works fine when the app is compiled by Docker. However when I run my profile.entity.spec.ts file in Jest, I get:
Cannot find module '#ourProject/app-interfaces' from 'src/app/profiles/_entities/profile.entity.ts' // <--- this is a big clue
Require stack:
src/app/profiles/_entities/profile.entity.ts
src/app/profiles/_entities/profile.entity.spec.ts
1 | import { Column, CreateDateColumn, DeleteDateColumn, Entity, PrimaryColumn, UpdateDateColumn } from 'typeorm';
> 2 | import { GenderEnum, IProfile, ProfileTypeEnum } from '#ourProject/app-interfaces';
| ^
3 |
4 |
5 | #Entity({ name: 'profile' })
at Resolver.resolveModule (node_modules/jest-resolve/build/resolver.js:324:11)
at Object.<anonymous> (src/app/profiles/_entities/profile.entity.ts:2:1)
Is there some special configuration I need to use in jest.config.js to give jest testing access to files outside of the top lvl of the package.json?
here is jest.config.js
module.exports = {
displayName: 'web-api',
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json',
},
},
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/apps/web-api',
roots: ['../../'],
};
The line Cannot find module '#ourProject/app-interfaces' from 'src/app/profiles/_entities/profile.entity.ts' does not occur when the file runs normally.
Let's say your tsconfig.json alias configuration looks like this:
"paths": {
"#ourProject/*": ["./libs/*"],
}
Then you would need to add a moduleNameMapper line in jest.config.js:
{
moduleNameMapper: {
'^#ourProject/(.*)$': ['<rootDir>/libs/$1'],
},
}
I didn't have an issue with aliased imports being in a different folder, but jest didn't recognize aliases defined in tsconfig.json.

CRA + Yarn 2 + jsconfig.json = Can't run unit tests

I have the following configuration in my jsconfig.json file:
{
"compilerOptions": {
"baseUrl": "./src"
},
"include": ["src"]
}
Which lets me do this:
import { App } from 'components'
import * as actions from 'actions/app.actions'
Instead of this:
import { App } from '../components'
import * as actions from '../actions/app.actions'
To get started with unit testing, I've created a simple App.test.jsx in src/components/tests
import { render } from '#testing-library/react'
import { App } from 'components'
it('renders without crashing', () => {
render(<App />)
})
However, when I run yarn test (which is sugar for react-scripts test), it throws with this ugly error:
FAIL src/components/tests/App.test.jsx
● Test suite failed to run
Your application tried to access components, but it isn't declared in your dependencies;
this makes the require call ambiguous and unsound.
Required package: components (via "components")
Required by: C:\Users\Summer\Code\sandbox\src\components\tests\
23714 | enumerable: false
23715 | };
> 23716 | return Object.defineProperties(new Error(message), {
| ^
23717 | code: { ...propertySpec,
23718 | value: code
23719 | },
at internalTools_makeError (.pnp.js:23716:34)
at resolveToUnqualified (.pnp.js:24670:23)
at resolveRequest (.pnp.js:24768:29)
at Object.resolveRequest (.pnp.js:24846:26)
It seems like Jest (or Yarn?) thinks components is a node package, because it's not aware of the absolute imports setting in my jsconfig.json. Is there a way to make it aware? Or do I have to choose between 0% coverage and relative imports?
I've tried entering "moduleNameMapper" under "jest" in my package.json like the documentation explains, but it didn't help. I got the same error + one more after it.
I've also tried changing components in the test file to ../components but then it complains about actions/app.actions which is inside the <App /> component.
Module name mapper config:
/* package.json */
{
/* ... */
"jest": {
"moduleNameMapper": {
"actions(.*)$": "<rootDir>/src/actions$1",
"assets(.*)$": "<rootDir>/src/assets$1",
"components(.*)$": "<rootDir>/src/components$1",
"mocks(.*)$": "<rootDir>/src/mocks$1",
"pages(.*)$": "<rootDir>/src/pages$1",
"reducers(.*)$": "<rootDir>/src/reducers$1",
"scss(.*)$": "<rootDir>/src/scss$1",
"store(.*)$": "<rootDir>/src/store$1",
"themes(.*)$": "<rootDir>/src/themes$1",
"api": "<rootDir>/src/api.js",
}
}
}
This is because Yarn takes control of the resolution pipeline, and thus isn't aware of resolution directives coming from third-party configuration (like moduleNameMapper).
This isn't to say you have no options, though - specifically, the fix here is to avoid moduleNameMapper, and instead leverage the builtin link: dependency protocol. This has other advantages, such as being compatible with all tools (TS, Jest, ESLint, ...) without need to port your aliases to each configuration format.
See also: Why is the link: protocol recommended over aliases for path mapping?

Jest return error when using "import * as .."

I have problems to run my test suite when I used import * as './filename.js' with Jest.
All the others imports run without problems so I don't think is a problem with babel configuration.
I use Nextjs 10(so react17), Jest, Typescript and babel-jest.
Here is my babel.config.js
{
"env": {
"development": {
"presets": ["next/babel"]
},
"production": {
"presets": ["next/babel"]
},
"test": {
"presets": [
[
"next/babel",
{
"preset-env": {
"modules": "commonjs"
}
}
]
]
}
}
}
And here an example of the test that gives the error:
import React, { FC, useEffect } from 'react'
import Head from 'next/head'
import Header from '../Header/Header'
import HeaderHome from '../HeaderHome/HeaderHome'
import Footer from '../Footer/Footer'
import styles from './Layout.module.css'
import * as settingsHelper from '../../helpers/_settingsHelper'
// .... normal react component here.
And inside the _seetingsHelper.js I call my cookieHelper like so:
import * as cookieHelper from './_cookies'
function initialise () {
// body of function here
}
error:
.../helpers/_settingsHelper.js:2
import * as cookieHelper from './_cookies'
^^^^^^
SyntaxError: Cannot use import statement outside a module
6 | import styles from './Layout.module.css'
7 |
> 8 | import * as settingsHelper from '../../helpers/_settingsHelper'
| ^
9 |
10 | // prettier-ignore
11 | interface LayoutProps {
Someone already encountered this issue?

Cannot test jest with monaco editor - unexpected token

Running jest on the application fails with:
Details:
/home/**/node_modules/monaco-editor/esm/vs/editor/editor.api.js:5
import { EDITOR_DEFAULTS } from './common/config/editorOptions.js';
^
SyntaxError: Unexpected token {
> 1 | import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";
| ^
2 |
3 | /**
4 | * Get create function for the editor.
at ScriptTransformer._transformAndBuildScript (node_modules/#jest/transform/build/ScriptTransformer.js:537:17)
at ScriptTransformer.transform (node_modules/#jest/transform/build/ScriptTransformer.js:579:25)
at Object.<anonymous> (src/utils/editor-actions.js:1:1)
Application has installed packages for jest and babel-jest.
Babel config:
const presets = [
[
"#babel/env",
{
targets: {
edge: "17",
firefox: "60",
chrome: "67",
safari: "11.1"
},
useBuiltIns: "usage",
corejs: 3,
}
],
"#babel/preset-react"
];
const plugins = [
"#babel/plugin-proposal-object-rest-spread",
"#babel/plugin-proposal-class-properties",
"babel-plugin-styled-components"
];
module.exports = { presets, plugins };
The import statement as suggested in the docs for lazy loading modules from monaco leads to the esm folder, which jest is not familiar with.
import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";
By default, babel-jest would not transform node_modules and hence anything referencing the monaco-editor would error out. A possible solution is to include monaco-editor package into the compilation step by transformIgnorePatterns as mentioned in the docs
Add these to the jest config:
{
"transformIgnorePatterns": [
"node_modules\/(?!(monaco-editor)\/)"
]
}
PS: If you are using jest-dom, it might start complaining on not implmenting certain features from monaco-editor, you can mock it out with:
jest.mock("monaco-editor/esm/vs/editor/editor.api.js");
The only workaround that helped me in that issue (from here):
In folder __mocks__ create file react-monaco-editor.js with content:
import * as React from 'react';
export default function MonacoEditor() {
return <div />;
}
I have the same issue with Jest and Monaco and to make the tests pass I had to:
Add a moduleNameMapper for monaco-editor: #133 (comment)
Configure a setupTests.js like explained here: stackOverflow
I'm using:
"jest": "^24.9.0"
"babel-jest": "24.9",
"monaco-editor": "^0.20.0"
"react-monaco-editor": "0.33.0",
"monaco-editor-webpack-plugin": "^1.8.2",

Resources