getting jest to work with babel / laravel-mix - reactjs

I'm using jest and testing-library/react for tests of my ReactJS components in a Laravel app.
My tests break because the component to to test isn't recognised by jest even after importing it into the test. I have the following settings in jest.config.js
module.exports = {
testRegex: 'resources/js/tests/.*.test.js$',
roots: ["<rootDir>/resources/js/"],
moduleDirectories: ["resources/js/components", "resources/js/containers", "resources/js/views", "node_modules"]
}
And in the package.json file
"test": "cross-env NODE_ENV=test jest",
Here's a simple test that fails due to error
import React from "react";
import { render, fireEvent, waitForElement } from "#testing-library/react";
import "#testing-library/jest-dom/extend-expect";
import axiosMock from "axios";
// the component to test
import BlogEditor from "../../components/BlogEditor/BlogEditor";
jest.mock("axios");
test("Blog Editor recieves props and renders", () => {
const { getByTestId } = render(
<BlogEditor
tags={[{ id: 1, name: "A tag"}]}
suggestions={[{id: 2, name: "A Suggestion"}]}
/>
);
});
The error I get is rather cryptic
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.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
SyntaxError: /Users/anadi/Code/adminpanel/resources/js/tests/BlogEditor/BlogEditor.test.js: Unexpected token (16:8)
14 | test("Blog Editor recived props and renders element", () => {
15 | const { getByTestId } = render(
> 16 | <BlogEditor
| ^
17 | tags={[{ id: 1, name: "A tag"}]}
18 | suggestions={[{id: 2, name: "A Suggestion"}]}
19 | />
at Parser.raise (node_modules/#babel/parser/src/parser/location.js:41:63)
at Parser.unexpected (node_modules/#babel/parser/src/parser/util.js:150:16)
at Parser.parseExprAtom (node_modules/#babel/parser/src/parser/expression.js:1123:20)
at Parser.parseExprSubscripts (node_modules/#babel/parser/src/parser/expression.js:529:23)
at Parser.parseMaybeUnary (node_modules/#babel/parser/src/parser/expression.js:509:21)
at Parser.parseExprOps (node_modules/#babel/parser/src/parser/expression.js:279:23)
at Parser.parseMaybeConditional (node_modules/#babel/parser/src/parser/expression.js:234:23)
at Parser.parseMaybeAssign (node_modules/#babel/parser/src/parser/expression.js:185:21)
at Parser.parseExprListItem (node_modules/#babel/parser/src/parser/expression.js:2077:18)
at Parser.parseCallExpressionArguments (node_modules/#babel/parser/src/parser/expression.js:817:14)

The problem was with my babel and jest configurations, moved jest configuration to package.json (I have no clue why this actually helped) but it did
"jest": {
"verbose": true,
"clearMocks": true,
"collectCoverage": true,
"testRegex" : "resources/js/tests/.*.test.js$",
"roots": ["<rootDir>/resources/js/"],
"moduleDirectories": ["resources/js/components", "resources/js/containers", "resources/js/views", "node_modules"],
"transform": {
"^.+\\.js$": "babel-jest"
},
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/resources/js/__mocks__/fileMock.js",
"\\.(css|scss)$": "<rootDir>/resources/js/__mocks__/styleMock.js"
}
and updated the babel configuration too
{
"presets": [
"#babel/preset-env",
"#babel/preset-react"
],
"plugins": [
"#babel/plugin-proposal-class-properties",
"#babel/plugin-syntax-dynamic-import"
]
}

Related

Trying to test using jest but running into issues

Im trying to test a component using jest. The component imports spacetime npm module, which uses es-modules on main
https://www.npmjs.com/package/spacetime
I'm running into the following issues:
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
• 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.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
/Users/wscott/dev/pm/client/node_modules/spacetime/src/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import Spacetime from './spacetime.js'
^^^^^^
SyntaxError: Cannot use import statement outside a module
6 | import search from '../../assets/images/search.svg';
7 | import Dropdown from 'react-bootstrap/Dropdown';
> 8 | import spacetime from "spacetime";
| ^
9 | import languages from "../../libraries/languages/language-list";
10 | import { Rating } from 'react-simple-star-rating';
11 |
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
at Object.<anonymous> (src/components/Mentor/MentorList.js:8:1)
Here's my jest.config.js file
module.exports = {
preset: 'ts-jest',
transform: {
'^.+\\.(ts|tsx)?$': 'ts-jest',
"^.+\\.(js|jsx)$": "babel-jest",
".+\\.(css|styl|less|sass|scss)$": "jest-transform-css"
},
"moduleNameMapper": {
"\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/src/__mocks__/fileMock.js",
"\\.(css|less)$": "<rootDir>/src//__mocks__/fileMock.js"
},
"setupFiles":["./src/browserMocks.js"],
"globals": {
"window": {
location: {
href: ""
},
localStorage: {
getItem: () => {
}
}
},
"localStorage": {
getItem: () => {
}
}
}
};
Here's my babel.config.js file:
module.exports = {
presets:[
"#babel/preset-env",
"#babel/preset-react"
],
"env": {
"test": {
"plugins": ["#babel/plugin-transform-modules-commonjs"]
}
}
}
Can someone help?
Downgrading to 6.12.3 fixes the issue with jest. The issue is space time use es-module imports which jest doesn't support but downgrading should work
Try to set the transformIgnorePatterns property to let jest transform the file before tests:
transformIgnorePatterns: [
'node_modules/(?!(spacetime)/)',
],
This way you are telling to skip transformation for all your node_modules except spacetime, which will be transformed by babel-jest as is set in you configuration.

Jest test error - Cannot find module meteor/tprzytula:remember-me

I am using meteor/tprzytula:remember-me package in my Meteor React app.
I also use Jest for test automation.
I use the RememberMe component in my Signin form (a React functional component in Meteor)
When I try running tests with Jest I get the following error:
Cannot find module 'meteor/tprzytula:remember-me' from 'imports/ui/components/signin/SigninForm.js'
Require stack:
imports/ui/components/signin/SigninForm.js
tests/Signin.test.js
2 | import React, {useState, useRef} from 'react';
3 | import {Accounts} from 'meteor/accounts-base';
> 4 | import RememberMe from 'meteor/tprzytula:remember-me';
| ^
Here is my test code using Jest and Enzyme
tests/Signin.test.js
const wrapper = mount(<SigninForm />);
Update
I run my tests using npm test. Here is my entry on package.json
package.json
"test": "./node_modules/.bin/jest --verbose --silent",
Also adding my jest.config.js. Note I commented out moduleNameMapper. It errors out either way.
jest.config.js
module.exports = {
setupFiles: [
'./tests/setupTests.js',
],
transform: {
'^.+\\.jsx?$': 'babel-jest',
},
moduleFileExtensions: [
'js',
'jsx',
],
modulePaths: [
'<rootDir>/node_modules/',
'<rootDir>/node_modules/jest-meteor-stubs/lib/',
],
// moduleNameMapper: {
// 'meteor/tprzytula:remember-me': 'meteor/tprzytula:remember-me',
// '^(.*):(.*)$': '$1_$2',
// },
unmockedModulePathPatterns: [
'/^imports\\/.*\\.jsx?$/',
'/^node_modules/',
],
};
Is there a solution/workaround for this problem?

Jest SyntaxError: Unexpected token <

I'm want to test a component in a React app using Jest Enzyme with TypeScript. I follow the instructions on the Jest site, but for some reason I get:
SyntaxError: Unexpected token <
I can test test some functions. There isn't any problem with that, but when I use a component, I get an error.
This is the Jest configuration in file package.json:
"jest": {
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"testMatch": ["**/__tests__/*.(ts|tsx)"],
"snapshotSerializers": ["enzyme-to-json/serializer"],
"setupFilesAfterEnv": ["<rootDir>/src/setupEnzyme.ts"],
"unmockedModulePathPatterns": ["node_modules/react/", "node_modules/enzyme/"]
}
Enzyme configuration
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
export default class TesComponent extends Component {
render(){
return (
<div>test</div>
)
}
}
import { shallow } from 'enzyme'
import TestCompoenent from '../TestComponent'
test('component testing', () => {
const component = shallow(<TestCompoenent />)
expect(component.contains(<div>test</div>)).toBeTruthy()
})
This is the error:
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.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
/home/user/Documents/local-platform/frontend/src/pages/__tests__/settigs.test.tsx:9
var component = enzyme_1.shallow(<TestComponent_1.default />);
^
SyntaxError: Unexpected token <
at ScriptTransformer._transformAndBuildScript (node_modules/#jest/transform/build/ScriptTransformer.js:471:17)
at ScriptTransformer.transform (node_modules/#jest/transform/build/ScriptTransformer.js:513:25)
I expect for the tests to pass, because Test Component does include <div>test</div>.
Try changing tsconfig.json
"jsx": "preserve" -> "jsx": "react"
It seems that your configuration does not process the TypeScript file (.tsx) properly.
Here is part of my working configuration:
"jest": {
"transform": {
"^.+\\.tsx?$": "ts-jest",
},
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"json"
],
"setupTestFrameworkScriptFile": "<rootDir>/src/setupSpecs.ts"
}
I have used setupTestFrameworkScriptFile instead of setupFilesAfterEnv.

JEST Test suite failed to run: TypeError: (0 , _reactRedux.connect) is not a function

So I want to test react components, and I just added testing library Enzyme and Jest, try to setup tests. But I got an error which come from my node modules if I import a component in my test code.
My app is using: React + Webpack + Babel.
I have "react": "^0.14.8","enzyme": "^3.3.0",, "enzyme-adapter-react-14": "^1.0.5" , "jest": "^22.4.2" , "webpack": "^3.8.1" , and "node": "5.6.0".
I installed Enzyme & Jest, wrote simple test like this and passed.
import enzyme, {shallow} from 'enzyme';
describe('Testing test', () => {
it('This test will always pass!', () => {
const test = "test"
expect(test).to.have.length(4);
})
})
This is Fine. BUT when I import components, just import, not even use it, I got an error:
(UPDATE: I feel the moduleNameMapper in package.json isn't correct)
import DealList from './DealList';
Test suite failed to run
TypeError: (0 , _reactRedux.connect) is not a function
35 | case("integer"):
36 | return integer
> 37 | case("required, integer"):
38 | return [required, integer]
39 | }
40 | }
at createConnectedField (node_modules/redux-form/lib/ConnectedField.js:329:43)
at createField (node_modules/redux-form/lib/createField.js:48:53)
at Object.<anonymous> (node_modules/redux-form/lib/Field.js:17:45)
at Object.<anonymous> (node_modules/redux-form/lib/index.js:122:14)
at Object.<anonymous> (src/components/CreateDealForm/CreateFundDealForm.js:37:18)
at Object.<anonymous> (src/components/index.js:24:28)
at Object.<anonymous> (src/containers/DealList/DealList.js:35:19)
at Object.<anonymous> (src/containers/DealList/DealList.test.js:7:17)
This is my package.json
"scripts" :{
...
"test": "jest"
},
"jest": {
"verbose": true,
"setupTestFrameworkScriptFile": "<rootDir>test/setup.js",
"moduleNameMapper": {
"components(.*)$": "<rootDir>/src/components"
},
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/redux-form/"
]
}
my .babelrc:
{
"presets": ["env", "stage-0", "react"],
"plugins": [
"syntax-dynamic-import",
"dynamic-import-node",
"transform-runtime",
"add-module-exports",
"transform-decorators-legacy",
"transform-react-display-name"
],
"env": {
"development": {
"plugins": [
"typecheck",
["react-transform", {
"transforms": [{
"transform": "react-transform-catch-errors",
"imports": ["react", "redbox-react"]
}
]
}]
]
},
"test": {
"presets": ["env", "stage-0", "react"]
}
}
}
my test/setup.js
import Enzyme from 'enzyme'
import Adapter from 'enzyme-adapter-react-14'
import { expect } from 'chai';
Enzyme.configure({ adapter: new Adapter() })
global.expect = expect;
Any thoughts would be awesome. Thank you!
I figured out that the moduleNameMapper on package.json is wrong.
This is correct:
"jest": {
"setupTestFrameworkScriptFile": "<rootDir>test/setup.js",
"moduleNameMapper": {
"^components(.*)$": "<rootDir>/src/components$1"
},
"verbose": true
},
And got another one which asks me to install the legacy decorators transform, but it is already installed. I will close this question.

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