eslint + jsconfig + nextjs module path aliases (absolue path import - #) - reactjs

I am trying to import the files using custom aliases following the nextjs documentation.
My current approach is
from
import Header from '../../../components/Header';
to
import Header from '#components/Header';
I am getting the expected result. But eslint throws the following error:
unable to resolve path to module (eslint - import/no unresolved)
And I have tried adding the following line in my eslintrc file to resolve the error
settings: {
'import/resolver': {
node: {
paths: ['src'],
},
},
},
But still the eslint throws the same error.
What is the correct approach to resolve this one?
Thanks in advance...
Note: I don't want to remove eslint and I need #components import aliases

Finally after digging into lots of GitHub answers and etc...
Inside your eslintrc file... add the following aliases
settings: {
'import/resolver': {
alias: {
map: [
['#components', '../../../components/'],
['#images', '../../../assets/images/'],
],
extensions: ['.js', '.jsx'],
},
},
},
and also to fix flow error
inside your flowconfig file add the name_mapper
module.name_mapper='^#components' ->'<PROJECT_ROOT>/../../../components'
module.name_mapper='^#images' ->'<PROJECT_ROOT>/../../../assets/images'

You need to also install npm i -D eslint-import-resolver-typescript and then add below to eslint config file:
"settings": {
"import/resolver": {
"typescript": {} // this loads <rootdir>/tsconfig.json to eslint
},
}
Reference: https://gourav.io/blog/nextjs-cheatsheet

You can try adding your custom paths in tsconfig.json/jsconfig.json, like so:
Add a baseUrl in your compilerOptions (in my case it's "baseUrl": ".")
Add your paths in a paths object:
"paths": {
"components": ["components/*"],
}

Related

TS Config nested alias for absolute path not working

I'm trying to set up path aliases in my tsconfig.json for a React app bundled with Vite. Here is the relevant part of my tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
...
"paths": {
"*": ["src/*", "node_modules/*"],
"components/*": ["src/components/*"],
"containers/*": ["src/containers/*"],
"pages/*": ["src/constants/*"],
"store/*": ["src/store/*"],
"types/*": ["src/types/*"],
"NestedFolder/*": [
"src/components/NestedFolder/*"
],
}
},
"include": ["src/**/*", "*"]
}
The only issue is with the NestedFolder. When I import this way, everything works:
import { ComponentName } from "components/NestedFolder/types";
However, the nested alias fails:
import { ComponentName } from "NestedFolder/types";
// error
EslintPluginImportResolveError: typescript with invalid interface loaded as resolver
Occurred while linting .../src/components/NestedFolder/canvas/index.ts:1
Rule: "import/namespace"
// error on hover in VS Code
Unable to resolve path to module 'NestedFolder/types'.eslintimport/no-unresolved
I would like to do nested components because I have several folders that are nested 3-4 levels and it would be nice to have a cleaner view of my imports. Is there a way to do this?
You need to install the vite-tsconfig-paths plugin to set up path aliases using TypeScript and Vite.
If nothing changes and you are using VSCode make sure to restart the TypeScript server by pressing Ctrl+Shift+P or Cmd+Shift+P, typing restart, and then selecting the command: TypeScript: Restart TS server
The accepted answer did not work for me. I found that I had to install the following packages:
npm i eslint-plugin-import eslint-import-resolver-alias eslint-import-resolver-typescript
And then add the following configurations, with the important ingredient being strongly-defined alias paths:
const path = require('path');
module.exports = {
root: true, // important to ensure nested eslint scoping in monorepos
plugins: ['#typescript-eslint', 'import'],
extends: [
'airbnb-typescript-prettier',
'plugin:import/typescript'
],
parser: '#typescript-eslint/parser',
parserOptions: {
project: path.join(__dirname, './tsconfig.json'),
tsconfigRootDir: './src',
},
settings: {
"import/parsers": { // add this definition
"#typescript-eslint/parser": [".ts", ".tsx"],
},
'import/resolver': {
alias: {
map: [
// define each alias here
['components', path.join(__dirname, './src/components')],
],
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json']
},
typescript: {
project: path.join(__dirname, './tsconfig.json'),
},
},
},
}
I think this could be improved on by harmonizing the aliases between the .eslintrc and vite.config so aliases only need to be defined once, using a tactic like the one defined here: https://stackoverflow.com/a/68908814/14198287
if vite-tsconfig-paths is not working for you. Make sure you didn't install v4.0.0. That version has a bug.
v4.0.1 fix it.
Install with the following:
npm install vite-tsconfig-paths#latest
Should install v4.0.1 at least.
I think this could be improved on by harmonizing the aliases between the .eslintrc and vite.config so aliases only need to be defined once, using a tactic like the one defined here: https://stackoverflow.com/a/68908814/14198287

Unit testing getting error for importing a png [duplicate]

In React components importing assets
(ex, import logo from "../../../assets/img/logo.png)
gives such error
({"Object.":function(module,exports,require,__dirname,__filename,global,jest){�PNG
SyntaxError: Invalid or unexpected token
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:305:17)
my jest config is
"jest": {
"testRegex": ".*\\.spec\\.js$",
"moduleFileExtensions": [
"js",
"jsx",
"json"
],
"moduleDirectories": [
"node_modules",
"src",
"assets"
],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$/": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less|scss)$": "<rootDir>/__mocks__/styleMock.js"
},
"verbose": true,
"bail": true
}
what am i missing?
When you import image files, Jest tries to interpret the binary codes of the images as .js, hence runs into errors.
The only way out is to mock a default response anytime jest sees an image import!
How do we do this?
first you tell Jest to run the mock file each time an image import is encountered. you do this by adding the key below to your package.json file
"jest": {
"moduleNameMapper": {
"\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/mocks/fileMock.js",
"\\.(css|less)$": "<rootDir>/mocks/fileMock.js"
}
}
Note: if you already have the "Jest" key, just add the "moduleNameMapper" child in it
lastly, create a mocks folder in your root and create fileMock.js file inside it. populate the file with the snippet below
module.exports = '';
Note: If you are using es6 you can use export default ''; to avoid an Eslint flag
when you are done with the above steps, you can restart the test and you are good to go.
Note. remember to add the varying extensions of your image files in the moduleNameMapper so that they can be mocked.
I hope I have been able to help. #cheers!
For anyone looking into this problem. You have to do install npm install --save-dev identity-obj-proxy to get the necessary dependencies.
"jest": {
"moduleNameMapper": {
".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "identity-obj-proxy"
}
}
I had the same problem and I solved it as follows:
npm install -D jest-transform-stub
Then, in package.json, I added the following transformation:
"jest": {
...
"transform": {
...
".+\\.(css|scss|png|jpg|svg)$": "jest-transform-stub"
I had this same issue! I'm not sure if it's the same case as in the original question, but for me jest was still somehow trying to load the images as JS and trying to parse them while I had the files matching image extensions mapped to a mock in moduleNameMapper. My file also included some code to map the # character to the root src directory, since I had webpack and this was configured as a webpack alias in the project (and in TS). The full moduleNameMapper entry in jest.config.js looked like this for me:
moduleNameMapper: {
'^#$': '<rootDir>/src',
'^#/(.*)':
'<rootDir>/src/$1',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/__mocks__/fileMock.js',
// '\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
'.*\\.(css|less)$': 'identity-obj-proxy',
}
For me it turned out that when I was importing the images in my components, the path was something like: '#/assets/someImage.jpg'. However, it seems this would match the first regex first, the one covering the # alias: ^#/(.*). Thus, it was being mapped to <rootDir>/src/$1 instead of the <rootDir>/__mocks__/fileMock.js.
I fixed it by making the alias only match non-images:
moduleNameMapper: {
'^#$': '<rootDir>/src',
'^#/(.*)\\.(?!jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/src/$1',
'.*\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/__mocks__/fileMock.js',
// '\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
'.*\\.(css|less)$': 'identity-obj-proxy',
}
Adding bellow line into jest.config.js file helped me to test pass,
"\\.(jpg|jpeg|png)$": "identity-obj-proxy",
Example:
moduleNameMapper: {
"\\.(css)$": "identity-obj-proxy",
"\\.(jpg|jpeg|png)$": "identity-obj-proxy",
},
If you want to use jest with webpack, you need to explicitly configure it as so. Take a look at this guide here: https://jestjs.io/docs/webpack
For those who use Vue test util in Nuxt 2 and are faced with question or this problem ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){ SyntaxError: Invalid or unexpected token
make a file with the name of fileTransformer.js in the test/unit directory, and then add these codes:
const path = require('path')
module.exports = {
process(src, filename, config, options) {
return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';'
},
}
and then add these codes to jest.config.js file:
transform: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/test/unit/fileTransformer.js',
// ... other configs
},
In case of IOS image names with #
moduleNameMapper: {
"^image![a-zA-Z0-9$_-]+$": "GlobalImageStub",
"^[#./a-zA-Z0-9$_-]+\\.(png|gif)$": "RelativeImageStub"
}
In React Native we use preset: 'react-native'
https://github.com/facebook/react-native/blob/main/jest-preset.js
Or add transform into jest.config.js
transform: {
'^.+\\.(js|ts|tsx)$': 'babel-jest',
'^.+\\.(bmp|gif|jpg|jpeg|mp4|png|psd|svg|webp)$': require.resolve(
'../node_modules/react-native/jest/assetFileTransformer.js',
),
},
If you do not use React Native, need to create a file https://github.com/facebook/react-native/blob/main/jest/assetFileTransformer.js into your project and changes path into require.resolve
Nothing has worked for me, so I replaced
the 'mount' with 'shallow' everywhere and it's working fine now.
npm install --save-dev identity-obj-proxy
and add the following inside your jest.config.js :
moduleNameMapper: {
"\\.(css)$": "identity-obj-proxy",
"\\.(jpg|jpeg|png)$": "identity-obj-proxy",
},
this worked for me .

Laravel mix & react - Module build failed on inline import

I seem to be having an issue when building my frontend using Laravel mix.
I'm using react-loadable for loading components with promises, as for routing I make use of a declarative config file:
export default [
{
path: '/clients',
exact: true,
auth: true,
component: Loadable({
loader: () => import('./screens/index'),
loading: LoadingComponent,
}),
},
]
When building the js files, I get following error (pointing to the 'i' of import):
ERROR in ./resources/js/modules/clients/routes.js Module build failed:
SyntaxError: Unexpected token (10:26)
When searching the web I came across the fact that, when you wanted to use arrow functions or class properties, you'd need to add a Babel plugin (babel-plugin-transform-class-properties).
So I did add a .babelrc file with following config (it also seems that laravel-mix would automatically make use of the babelrc file):
{
"plugins": ["transform-class-properties"]
}
Still no success.
Any ideas?
Try adding this to your .babelrc file:
{
"presets": [
["es2016"],
"react"
],
"plugins": [
"babel-plugin-transform-class-properties"
]
}

Importing images breaks jest test

In React components importing assets
(ex, import logo from "../../../assets/img/logo.png)
gives such error
({"Object.":function(module,exports,require,__dirname,__filename,global,jest){�PNG
SyntaxError: Invalid or unexpected token
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:305:17)
my jest config is
"jest": {
"testRegex": ".*\\.spec\\.js$",
"moduleFileExtensions": [
"js",
"jsx",
"json"
],
"moduleDirectories": [
"node_modules",
"src",
"assets"
],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$/": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less|scss)$": "<rootDir>/__mocks__/styleMock.js"
},
"verbose": true,
"bail": true
}
what am i missing?
When you import image files, Jest tries to interpret the binary codes of the images as .js, hence runs into errors.
The only way out is to mock a default response anytime jest sees an image import!
How do we do this?
first you tell Jest to run the mock file each time an image import is encountered. you do this by adding the key below to your package.json file
"jest": {
"moduleNameMapper": {
"\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/mocks/fileMock.js",
"\\.(css|less)$": "<rootDir>/mocks/fileMock.js"
}
}
Note: if you already have the "Jest" key, just add the "moduleNameMapper" child in it
lastly, create a mocks folder in your root and create fileMock.js file inside it. populate the file with the snippet below
module.exports = '';
Note: If you are using es6 you can use export default ''; to avoid an Eslint flag
when you are done with the above steps, you can restart the test and you are good to go.
Note. remember to add the varying extensions of your image files in the moduleNameMapper so that they can be mocked.
I hope I have been able to help. #cheers!
For anyone looking into this problem. You have to do install npm install --save-dev identity-obj-proxy to get the necessary dependencies.
"jest": {
"moduleNameMapper": {
".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "identity-obj-proxy"
}
}
I had the same problem and I solved it as follows:
npm install -D jest-transform-stub
Then, in package.json, I added the following transformation:
"jest": {
...
"transform": {
...
".+\\.(css|scss|png|jpg|svg)$": "jest-transform-stub"
I had this same issue! I'm not sure if it's the same case as in the original question, but for me jest was still somehow trying to load the images as JS and trying to parse them while I had the files matching image extensions mapped to a mock in moduleNameMapper. My file also included some code to map the # character to the root src directory, since I had webpack and this was configured as a webpack alias in the project (and in TS). The full moduleNameMapper entry in jest.config.js looked like this for me:
moduleNameMapper: {
'^#$': '<rootDir>/src',
'^#/(.*)':
'<rootDir>/src/$1',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/__mocks__/fileMock.js',
// '\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
'.*\\.(css|less)$': 'identity-obj-proxy',
}
For me it turned out that when I was importing the images in my components, the path was something like: '#/assets/someImage.jpg'. However, it seems this would match the first regex first, the one covering the # alias: ^#/(.*). Thus, it was being mapped to <rootDir>/src/$1 instead of the <rootDir>/__mocks__/fileMock.js.
I fixed it by making the alias only match non-images:
moduleNameMapper: {
'^#$': '<rootDir>/src',
'^#/(.*)\\.(?!jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/src/$1',
'.*\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/__mocks__/fileMock.js',
// '\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
'.*\\.(css|less)$': 'identity-obj-proxy',
}
Adding bellow line into jest.config.js file helped me to test pass,
"\\.(jpg|jpeg|png)$": "identity-obj-proxy",
Example:
moduleNameMapper: {
"\\.(css)$": "identity-obj-proxy",
"\\.(jpg|jpeg|png)$": "identity-obj-proxy",
},
If you want to use jest with webpack, you need to explicitly configure it as so. Take a look at this guide here: https://jestjs.io/docs/webpack
For those who use Vue test util in Nuxt 2 and are faced with question or this problem ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){ SyntaxError: Invalid or unexpected token
make a file with the name of fileTransformer.js in the test/unit directory, and then add these codes:
const path = require('path')
module.exports = {
process(src, filename, config, options) {
return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';'
},
}
and then add these codes to jest.config.js file:
transform: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/test/unit/fileTransformer.js',
// ... other configs
},
In case of IOS image names with #
moduleNameMapper: {
"^image![a-zA-Z0-9$_-]+$": "GlobalImageStub",
"^[#./a-zA-Z0-9$_-]+\\.(png|gif)$": "RelativeImageStub"
}
In React Native we use preset: 'react-native'
https://github.com/facebook/react-native/blob/main/jest-preset.js
Or add transform into jest.config.js
transform: {
'^.+\\.(js|ts|tsx)$': 'babel-jest',
'^.+\\.(bmp|gif|jpg|jpeg|mp4|png|psd|svg|webp)$': require.resolve(
'../node_modules/react-native/jest/assetFileTransformer.js',
),
},
If you do not use React Native, need to create a file https://github.com/facebook/react-native/blob/main/jest/assetFileTransformer.js into your project and changes path into require.resolve
Nothing has worked for me, so I replaced
the 'mount' with 'shallow' everywhere and it's working fine now.
npm install --save-dev identity-obj-proxy
and add the following inside your jest.config.js :
moduleNameMapper: {
"\\.(css)$": "identity-obj-proxy",
"\\.(jpg|jpeg|png)$": "identity-obj-proxy",
},
this worked for me .

SyntaxError with Jest and React and importing CSS files

I am trying to get my first Jest Test to pass with React and Babel.
I am getting the following error:
SyntaxError: /Users/manueldupont/test/avid-sibelius-publishing-viewer/src/components/TransportButton/TransportButton.less: Unexpected token
> 7 | #import '../variables.css';
| ^
My package.json config for jest look like this:
"babel": {
"presets": [
"es2015",
"react"
],
"plugins": [
"syntax-class-properties",
"transform-class-properties"
]
},
"jest": {
"moduleNameMapper": {
"^image![a-zA-Z0-9$_-]+$": "GlobalImageStub",
"^[./a-zA-Z0-9$_-]+\\.png$": "RelativeImageStub"
},
"testPathIgnorePatterns": [
"/node_modules/"
],
"collectCoverage": true,
"verbose": true,
"modulePathIgnorePatterns": [
"rpmbuild"
],
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/react/",
"<rootDir>/node_modules/react-dom/",
"<rootDir>/node_modules/react-addons-test-utils/",
"<rootDir>/node_modules/fbjs",
"<rootDir>/node_modules/core-js"
]
},
So what am I missing?
moduleNameMapper is the setting that tells Jest how to interpret files with different extension. You need to tell it how to handle Less files.
Create a file like this in your project (you can use a different name or path if you’d like):
config/CSSStub.js
module.exports = {};
This stub is the module we will tell Jest to use instead of CSS or Less files. Then change moduleNameMapper setting and add this line to its object to use it:
'^.+\\.(css|less)$': '<rootDir>/config/CSSStub.js'
Now Jest will treat any CSS or Less file as a module exporting an empty object. You can do something else too—for example, if you use CSS Modules, you can use a Proxy so every import returns the imported property name.
Read more in this guide.
I solved this by using the moduleNameMapper key in the jest configurations in the package.json file
{
"jest":{
"moduleNameMapper":{
"\\.(css|less|sass|scss)$": "<rootDir>/__mocks__/styleMock.js",
"\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js"
}
}
}
After this you will need to create the two files as described below
__mocks__/styleMock.js
module.exports = {};
__mocks__/fileMock.js
module.exports = 'test-file-stub';
If you are using CSS Modules then it's better to mock a proxy to enable className lookups.
hence your configurations will change to:
{
"jest":{
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less|scss|sass)$": "identity-obj-proxy"
},
}
}
But you will need to install identity-obj-proxy package as a dev dependancy i.e.
yarn add identity-obj-proxy -D
For more information. You can refer to the jest docs
UPDATE who use create-react-app from feb 2018.
You cannot override the moduleNameMapper in package.json but in jest.config.js it works, unfortunately i havent found any docs about this why it does.
So my jest.config.js look like this:
module.exports = {
...,
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(scss|sass|css)$": "identity-obj-proxy"
}
}
and it skips scss files and #import quite well.
Backing my answer i followed jest webpack
Similar situation, installing identity-object-proxy and adding it to my jest config for CSS is what worked for me.
//jest.config.js
module.exports = {
moduleNameMapper: {
"\\.(css|sass)$": "identity-obj-proxy",
},
};
The specific error I was seeing:
Jest encountered an unexpected token
/Users/foo/projects/crepl/components/atoms/button/styles.css:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){.button { }
^
SyntaxError: Unexpected token .
1 | import React from 'react';
> 2 | import styles from './styles.css';
If you're using ts-jest, none of the solutions above will work! You'll need to mock transform.
jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
roots: [
"<rootDir>/src"
],
transform: {
".(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/jest-config/file-mock.js",
'.(css|less)$': '<rootDir>/jest-config/style-mock.js'
},
};
file-mock.js
module.exports = {
process() {
return `module.exports = 'test-file-stub'`;
},
};
style-mock.js
module.exports = {
process() {
return 'module.exports = {};';
}
};
I found this working example if you want more details.
Solution of #import Unexpected token=:)
Install package:
npm i --save-dev identity-obj-proxy
Add in jest.config.js
module.exports = {
"moduleNameMapper": {
"\\.(css|less|scss)$": "identity-obj-proxy"
}
}
Update: Aug 2021
If you are using Next JS with TypeScript. Simply follow the examples repo.
Else you will be wasting days configuring the environment.
https://github.com/vercel/next.js/tree/canary/examples/with-jest
I added moduleNameMapper at the bottom of my package.json where I configured my jest just like this:
"jest": {
"verbose": true,
"moduleNameMapper": {
"\\.(scss|less)$": "<rootDir>/config/CSSStub.js"
}
}

Resources