Jest: Test suite failed to run, Unexpected token = - reactjs

I am trying to test a React component with Jest/Enzyme. I expect the test to at least run, but it already fails when it is importing files and does not get to the test itself. So I am wondering what in the configuration I am missing?
Error:
__tests__/Favorite.test.js
● Test suite failed to run
/src/components/favorite/Favorite.js: Unexpected token (13:13)
11 | }
12 |
> 13 | isFavorite = (props) => {
| ^
14 | return localStorage.getItem(props.recipe.id) ? true : false
15 | }
16 |
Test File:
import React from 'react'
import { mount } from 'enzyme'
import Favorite from '../src/components/favorite/Favorite'
describe('Favorite', () => {
const recipe = {id: "12345"}
const favorite = mount(<Favorite recipe={recipe}/>)
// assertions
})
.babelrc:
{
"presets": ["es2015", "react"]
}
package.json:
"devDependencies": {
"babel-jest": "^21.2.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"enzyme": "^3.2.0",
"enzyme-adapter-react-16": "^1.1.0",
"enzyme-to-json": "^3.2.2",
"jest": "^21.2.1",
"react-test-renderer": "^16.1.1"
},
"jest": {
"setupTestFrameworkScriptFile": "./src/setupTests.js",
"moduleNameMapper": {
"\\.(css|jpg|png|svg|ico)$": "<rootDir>/empty-module.js"
}
}
Update:
When I change the declaration of the functions from fat arrow to function keyword, the tests run. I wonder why?
Fat arrow function that does not work with Jest:
// Favorite.js
isFavorite = (props) => {
return localStorage.getItem(props.recipe.id) ? true : false
}
Function keyword that does work with Jest:
// Favorite.js
isFavorite(props) {
return localStorage.getItem(props.recipe.id) ? true : false
}

You missed the babel-preset-stage-0 package.
Add it: yarn add babel-preset-stage-0 --dev
Edit your .babelrc: { "presets": ["es2015", "react", "babel-preset-stage-0"] }

Related

TypeError: Class extends value undefined is not a constructor or null - MockedProvider from #apollo/client/testing

Cant seem to import MockedProvider from #apollo/client/testing in typescript jest. Looked around and saw this usually occurs with circular dependencies but haven't been able to find any occurrence in my test.
Test suite failed to run
TypeError: Class extends value undefined is not a constructor or null
1 | import 'react-native';
2 | import React from 'react';
> 3 | import { MockedProvider, MockedResponse } from '#apollo/client/testing';
| ^
4 |
5 | import renderer from '#tv/test-utils/renderWithProviders';
6 | import { GetProfileDocument, User } from '#tv/types';
at Object.__extends (../node_modules/tslib/tslib.js:70:19)
at ../node_modules/#apollo/client/testing/react/MockedProvider.js:8:5
at Object.<anonymous> (../node_modules/#apollo/client/testing/react/MockedProvider.js:32:2)
at Object.<anonymous> (pages/ProfilePage/ProfilePage.spec.tsx:3:1)
ProfilePage.spec.tsx - results in above error
import 'react-native';
import React from 'react';
import { MockedProvider, MockedResponse } from '#apollo/client/testing';
describe('Profile Page', () => {
it('console logs', () => {
console.log(MockedProvider);
});
});
These are the relevant dependencies I'm using:
"react-native": "0.64.3",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"#apollo/client": "^3.5.10",
"jest": "^26.6.3",
"jest-expo": "^44.0.1",
"#babel/core": "~7.17.9",
"ts-jest": "^26.5.6",
"ts-node": "^10.8.1",
"typescript": "~4.6.3",
node version: v14.18.1
npm version: 6.14.15
jest.config.ts
import { pathsToModuleNameMapper } from 'ts-jest/utils';
import ts from 'typescript';
const compilerOptions = ts.readConfigFile('tsconfig.json', ts.sys.readFile)
.config.compilerOptions;
const moduleMap = pathsToModuleNameMapper(compilerOptions.paths);
export default {
preset: 'jest-expo',
moduleNameMapper: moduleMap,
moduleDirectories: [
'.',
'src',
'src/components',
'src/hooks',
'node_modules',
],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
rootDir: 'src',
testRegex: '.*\\.spec\\.(t|j)sx?$',
transform: {
'^.+\\.tsx?$': 'ts-jest',
'^.+\\.svg$': 'jest-svg-transformer',
},
collectCoverageFrom: ['**/*.(t|j)sx?'],
coverageDirectory: '../coverage',
transformIgnorePatterns: [
'node_modules/(?!(jest-)?#?react-native|react-clone-referenced-element|#react-native-community|expo(nent)?|#expo(nent)?/.*|react-navigation|#react-navigation/.*|#unimodules/.*|unimodules|sentry-expo|native-base)',
],
setupFilesAfterEnv: ['<rootDir>/test-utils/mock-modules.js'],
};

React test with jest does not honor moduleNameMapper from webpack aliases

I am using jest and enzyme to test my react component. I am also using blueprint icons as one of the dependency in my react component. As part of my webpack config, following is added:
config.resolve.alias = {
blueprintIcons: path.resolve('./node_modules/#blueprintjs/icons'),
blueprint: path.resolve('./node_modules/#blueprintjs/core')
};
Following is added as part of jest config:
rootDir: '.',
roots: [
'<rootDir>/__test__/'
],
transformIgnorePatterns: [
'<rootDir>/node_modules/'
],
transform: {
'^.+\\.jsx?$': 'babel-jest'
},
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$',
moduleDirectories: ['node_modules'],
moduleFileExtensions: [
'js',
'jsx',
'json',
'node'
],
moduleNameMapper: {
'\\.(css|scss)$': 'identity-obj-proxy',
blueprintIcons: '<rootDir>/node_modules/#blueprintjs/core'
blueprint: '<rootDir>/node_modules/#blueprintjs/core'
},
snapshotSerializers: ['enzyme-to-json/serializer']
};
Here is my component:
import React, { Component } from 'react';
import Icon from 'blueprint';
import IconNames from 'blueprintIcons';
class Foo extends Component {
render() {
return (
<div>
<p>Hello Foo</p>
<Icon icon={IconNames.HOME} iconSize={Icon.SIZE_LARGE}/>
</div>
);
}
}
export default Foo;
Here is my foo.test.js
import React from 'react';
import Foo from '../../src/Components/Foo';
import Adapter from 'enzyme-adapter-react-16';
import Enzyme, { mount, shallow } from 'enzyme';
describe('Reviews component', () => {
it('render component when loading in progress', () => {
const mountedComponent = mount(<Foo />);
});
});
When I am trying to test that component, the test fails with
TypeError: Cannot read property 'HOME' of undefined at IconNames.HOME
Here are some packages specified in my package.json
"babel-cli": "6.26.0",
"babel-core": "^6.26.3",
"babel-eslint": "^10.0.1",
"babel-jest": "^23.0.1",
"babel-loader": "7.1.4",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.1.1",
"enzyme-to-json": "^3.3.4",
"jest": "^23.1.0",
"jest-html-reporter": "^2.3.0",
"#blueprintjs/core": "^2.3.1",
"react": "16.2.0"
I am using react 16.2.0
I tried mocking it but doesn't work(maybe I am not doing it correctly) but here is the code which I am using:
jest.mock('#blueprintjs/icons', () => (
{ IconNames: {HOME: 'home' }}));
For me, the following solution worked:
In jest config:
moduleNameMapper: {
'^blueprint': '<rootDir>/node_modules/#blueprintjs/core',
'^#blueprintjs/(.*)$': '<rootDir>/node_modules/#blueprintjs/$1'
}
Rest everything remained the same.
I think mocking is a possible solution - Not sure exactly why your code is not working (possibly because it's not within the default key, or the name of the mock is incorrect), but you can try something else.
In your Jest config, add the following:
"setupFiles": [
"./__mocks__/mockIcons.js"
],
Create /__mocks__ folder in your root folder
Create mockIcons.js inside __mocks__ with the following code:
jest.mock("blueprint", () => ({
default: {
Icon: { SIZE_LARGE: 'large' }
}
}))
jest.mock("blueprintIcons", () => ({
default: {
IconNames: { HOME: 'home' }
}
}))
Try to use #blueprintjs/icons as the mock name if nothing else works.

Getting an error when trying to import a component into Jest

I am using React+Redux/Redux-thunk and I am trying to implement jest/enzyme. I was able to successfully make a passing test for the root component. However I'm stuck at a point where I am trying to make a new test file for another component. No matter what component I try to test (connected or not connected) I am getting the same error.
FAIL src/views/LoginView/LoginView.test.jsx
● Test suite failed to run
Expected the reducer to be a function.
32 | }
33 |
> 34 | const store = middleware(createStore)(rootReducer, initialState);
| ^
35 | const compressor = createCompressor();
36 | const persistor = persistStore(store, { transforms: [compressor] }, () => { store.getState(); });
37 |
at createStore (node_modules/redux/lib/createStore.js:68:11)
at node_modules/redux/lib/applyMiddleware.js:38:19
at middleware (src/redux/configureStore.js:34:17)
at Object.<anonymous> (src/main.jsx:78:37)
I am not able to even write my first test as it errors out while importing the component.
The test file looks like this (pretty much blank) and it is in the same directory as the component LoginView.
import React from 'react';
import { shallow } from 'enzyme';
import LoginView from './LoginView';
test('passing test', () => {
});
My jest.config.js file looks like this:
module.exports = {
setupTestFrameworkScriptFile: '<rootDir>/test/setupTests.js',
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)$': 'identity-obj-proxy',
'^handsontable' : 'handsontable',
},
modulePaths: [
'<rootDir>/node_modules',
],
transformIgnorePatterns: [
'node_modules/(?!(react-joyride)/)',
],
globals: {
__API_BASE__ : '',
__HOT_BUILD_DATE__ : '',
__HOT_PACKAGE_NAME__: '',
__HOT_VERSION__ : '',
__HOT_BASE_VERSION__: '',
__BASENAME__ : false,
__DEBUG__ : false,
},
verbose: true,
};
I'm using the following versions of everything:
"react": "^16.5.2",
"babel-jest": "^23.6.0",
"jest": "^23.6.0",
"jest-enzyme": "^7.0.0",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16": "^1.6.0",
"redux": "^3.7.2",
"redux-persist": "^5.5.0",
"react-redux": "^5.0.6",
"redux-raven-middleware": "^1.2.0",
"redux-thunk": "^2.2.0",
I would appreciate any feedback or guidance on this topic as I am currently unable to write any tests on my components other than my root component.
Thanks in advance!

Why enzyme gives "Failed prop type" on a decorated child component

If I use a Higher-Order Component (HOC) as a decorator, i.e.,
#withStyles({})
class Bar extends React.Component { ... }
I'd get this error with enzyme:
console.error node_modules/prop-types/checkPropTypes.js:19
Warning: Failed prop type: The prop `classes` is marked as required in `_class`, but its value is `undefined`.
in _class
If I use the function form, i.e.,
const Bar = withStyles({})(class extends React.Component { ... });
there are no errors.
Why?
Note that this warning only happens on a child component; see the code from reproduction steps for what I mean.
Reproduction steps
package.json:
{
"name": "test",
"version": "1.0.0",
"description": "",
"scripts": {
"test": "jest"
},
"author": "",
"dependencies": {
"prop-types": "^15.6.2",
"react": "^16.4.1",
"react-dom": "^16.4.1"
},
"devDependencies": {
"babel-jest": "^23.2.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.5",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"jest": "^23.3.0"
},
"babel": {
"plugins": [
"transform-class-properties",
"transform-decorators-legacy"
],
"presets": [
"env",
"react"
]
}
}
__tests__/app.test.js:
import Adapter from 'enzyme-adapter-react-16';
import Enzyme from 'enzyme';
import PropTypes from 'prop-types';
import React from 'react';
import { shallow } from 'enzyme';
Enzyme.configure({ adapter: new Adapter() });
const withStyles = styles => Component => class extends React.Component {
render() {
return <Component classes={styles} />
}
}
// This will produce a failed prop type warning:
#withStyles({})
class Bar extends React.Component {
static propTypes = {
classes: PropTypes.object.isRequired,
}
render() {
return <div>test</div>;
}
}
// This will NOT produce a failed prop type warning:
// const Bar = withStyles({})(class extends React.Component {
// static propTypes = {
// classes: PropTypes.object.isRequired,
// }
// render() {
// return <div>test</div>;
// }
// });
class Test extends React.Component {
render() {
return <Bar />;
}
}
it('renders without crashing', () => {
shallow(<Test />);
expect(true).toBe(true);
});
Run npm t
There are two code blocks: one with decoration and the other (currently commented out) with function form. Simply comment out the decorator block and uncomment the function form block to test both cases.
This problem originally arose when using material-ui and I can confirm that both cases render the same UI visually. This prevented me from using the decorator form of withStyles.
Note that there are some more investigations by me here: https://github.com/airbnb/enzyme/issues/1505
The #babel/plugin-proposal-decorators needs come before #babel/plugin-proposal-class-properties, i.e., in the package.json:
"babel": {
"plugins": [
"transform-decorators-legacy",
"transform-class-properties"
],

Jest fails unless use --no-cache, even with babel-jest and .babelrc

This test passes if run Jest with --no-cache, but as per error msg below, I shouldn't get error with babel-jest, which I have.
See my .babelrc and package.json below, and test files.
ERROR:
Using Jest CLI v12.1.1, jasmine2, babel-jest
FAIL __tests__/junk-test.js
Runtime Error
- SyntaxError: Unexpected reserved word in file 'junk.js'.
Make sure your preprocessor is set up correctly and ensure your 'preprocessorIgnorePatterns' configuration is correct: http://facebook.github.io/jest/docs/api.html#preprocessorignorepatterns-array-string
If you are currently setting up Jest or modifying your preprocessor, try `jest --no-cache`.
Preprocessor: node_modules/babel-jest/src/index.js.
Make sure your '.babelrc' is set up correctly, for example it should include the 'es2015' preset.
Jest tried to the execute the following preprocessed code:
var junk = function () {
return "thing";};
export { junk };
__tests__/junk-test.js
// __tests__/junk-test.js
jest.unmock('../junk.js');
import {junk} from '../junk';
describe('JUNK AwesomeProject', () => {
it('Junk var = string', () => {
var retVal = junk();
expect(retVal).toEqual("thing");
});
});
junk.js
var junk = function(){
return "thing";
}
export {junk};
package.json
{
"dependencies": {
"babel-preset-react": "6.5.0",
"babelify": "7.3.0",
"react": "15.1.0",
"react-dom": "15.1.0"
},
"devDependencies": {
"babel-jest": "12.1.0",
"babel-polyfill": "6.9.0",
"babel-preset-es2015": "*",
"jest-cli": "12.1.1",
"react-addons-test-utils": "15.1.0"
},
"scripts": {
"test": "jest"
},
"jest": {
"verbose": true,
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/react/",
"<rootDir>/node_modules/react-dom/",
"<rootDir>/node_modules/react-addons-test-utils/"
]
}
}
.babelrc
{
"presets": ["es2015", "react"]
}
UPDATE
Ahh. Changing junk.js to an explicit return and now the test passes.
What's odd is Flow didn't catch this, maybe ESlint would, that's next on my list to try:
var junk = function() {
var stuff = "thing";
return stuff;
}

Resources