I have literally trawled everywhere for an answer to this and possibly tried 99% of things out there so i decided to start a thread of its own so others can run their eyes over what i have currently and see if they can spot the issue.
i am very new to Jest testing and decided to try implement it onto our code base. i used this guide to make sure everything i done was perfect but still this error occurs
A Practical Guide To Testing React Applications With Jest
I am testing this aginst a simple functional component which uses react-hook-form to produce a form on the page and then sends the completed form to our backend via a redux call
I have setup the setupTests.js file as:
import '#testing-library/jest-dom'
import { configure } from "enzyme"
import Adapter from "enzyme-adapter-react-16";
import '#testing-library/jest-dom/extend-expect';
configure({ adapter: new Adapter() });
Updated my package.json test command to
"test": "react-scripts test --env=jsdom --setupFiles ./src/setupTests.js"
Here is the test spec im trying to run with a simple test:
import React from 'react';
import { render as rtlRender, screen } from '#testing-library/react';
import { Provider } from 'react-redux';
import store from '../../../store';
import AddNewProperty from './AddNewProperty';
configure({ adapter: new Adapter() });
const render = component => rtlRender(
<Provider store={store()}>
{component}
</Provider>
)
describe('Add New Property', () => {
test('component redners successfully', () => {
render(<AddNewProperty />)
// expect(screen.getByText('Apartment Number')).toBeInTheDocument();
})
});
here is the error returned on the screen for me:
FAIL src/components/Forms/Agency/AddNewProperty.spec.js
● Test suite failed to run
ReferenceError: expect is not defined
3 | import Adapter from "enzyme-adapter-react-16";
4 | import '#testing-library/jest-dom/extend-expect';
> 5 | configure({ adapter: new Adapter() });
| ^
at Object.<anonymous> (node_modules/#testing-library/jest-dom/dist/extend-expect.js:9:1)
at Object.<anonymous> (node_modules/#testing-library/jest-dom/dist/index.js:3:1)
at Object.<anonymous> (src/setupTests.js:5:1)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 0.167s
Ran all test suites related to changed files.
Watch Usage: Press w to show more.
I have all the packages installed in with the latest versions also
You would want to set up the files after the test framework has been installed
Here are a couple of ways you can go about doing it (For this particular question, method 1 is more relevant)
1) react-scripts
Replace/Add --setupFilesAfterEnv instead of using --setupFiles
Example: "test": "react-scripts test --setupFilesAfterEnv <test setup filepath>
2) jest.config.js
setupFilesAfterEnv: [
'./setupTests.js',
],
Along with that make sure your node version is at least 12
Started a new create-react-app which comes with all the necessary react testing lib stuff pre installed:
"#testing-library/jest-dom": "^5.11.4",
"#testing-library/react": "^11.1.0",
"#testing-library/user-event": "^12.1.10",
i have tried to write basic test for one of my components:
import "#testing-library/jest-dom";
import React from "react";
import { render } from "#testing-library/react";
import SomeComponent from "./SomeComponent";
describe("helllo", () => {
it("renders SomeComponent correctley", () => {
const { queryAllByPlaceholderText } = render(<SomeComponent />);
console.log(test);
expect(test).toBeTruthy();
});
});
But i am getting this error message in the console:
Test suite failed to run
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:
6 | describe("helllo", () => {
7 | it("renders SomeComponent correctley", () => {
> 8 | const { queryAllByPlaceholderText } = render(<SomeComponent />);
| ^
My react version is:
"react": "^17.0.2",
I have researched this issue and keep on bumping into bable stuff but i though the react-testing-lib should be working out of box...?
I have created an empty application with create-react-app. it provides a test script at pckage.json and a sample App.test.js. at the first step, I want to set up the test environment according to the documentation of create-react-app. in my app I will use localStorage.
let's say an action like below to be tested
export const cancel = () => {
localStorage.removeItem("MyAppData");
return { type: types.USER_CANCEL};
};
besides the enzyme part, it shows how to initialize localStorage. so I ended up with a setupTests.js file like
import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
// react-testing-library renders your components to document.body,
// this will ensure they're removed after each test.
import "react-testing-library/cleanup-after-each";
// this adds jest-dom's custom assertions
import "jest-dom/extend-expect";
configure({ adapter: new Adapter() });
const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
clear: jest.fn()
};
global.localStorage = localStorageMock;
here if I do not import jest from jest or jest-dom or jest-enzyme, ESLinter shows an error in jest.fn() that jest is not defined. when I import and run yarn test I get
$ react-scripts test --env=jsdom
FAIL src\App.test.js
● Test suite failed to run
TypeError: _jest2.default.fn is not a function
at Object.<anonymous> (src/setupTests.js:15:27)
at <anonymous>
I really dont get from QAs here and in other forums how should I setup localStorage for testing.
You should not need to import jest into your test files.
You should instead tell eslint what Environment it should expect in the file so it knows what globals are present.
Add this to the top of any files where you use jest globals
/* eslint-env jest */
I really do not know what exactly happened, some packages related to jest, jet-dom, jest-enzyme was mkaing a conflict. but I managed to make it work after deleting package-lock.json, yarn.lock, node_modules, removing jest from the dependencies in package.json, then doing npm install and yarn install!
I created a new React application by create-react-app and I wanted to write a unit test to a component named "MessageBox" that I created in the application. This is the unit test that I wrote:
import MessageBox from "../MessageBox";
import { shallow } from 'enzyme';
import React from 'react';
test('message box', () => {
const app = {setState: jest.fn()};
const wrapper = shallow(<MessageBox app={app}/>);
wrapper.find('button').at(0).simulate('click');
expect(app.setState).toHaveBeenLastCalledWith({modalIsOpen: false});
});
I also added a file under 'src' folder named 'setupTests.js' with the content:
import * as enzyme from 'enzyme';
import * as Adapter from 'enzyme-adapter-react-16';
enzyme.configure({ adapter: new Adapter() });
I ran it by:
npm test
and I got the error:
Enzyme Internal Error: Enzyme expects an adapter to be configured, but
found none. To configure an adapter, you should call Enzyme.configure({ > adapter: new Adapter() })
Do you know what can solve this problem?
Add it to your test case file.
import React from 'react';
import Adapter from 'enzyme-adapter-react-16';
import { shallow, configure } from 'enzyme';
configure({adapter: new Adapter()});
test('message box', ()=> {
...
})
Also, if you don't want to import your setupTests.js file into every test file, you can place it in your package.json folder:
"jest": {
"setupTestFrameworkScriptFile": "./test/setupTests.js" }
Update:
Note: setupTestFrameworkScriptFile is deprecated in favor of setupFilesAfterEnv.
https://jestjs.io/docs/en/configuration
The file 'setupTests' has to be imported to the test file:
import MessageBox from "../MessageBox";
import { shallow } from 'enzyme';
import React from 'react';
import "../setupTests"
test('message box', ()=> {
...
})
As Priyank said, if you are using Create React App, it will pick up the configuration from src/setupTests.js.
Add:
import { configure } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
configure({ adapter: new Adapter() })
A lot of answers are saying import setupTests.js into your test file. Or
configure enzyme adapter in each test file. Which does solve the immediate problem.
But long term, if you add a jest.config.js file to the project root. You can configure it to run a setup file on launch.
jest.config.js
module.exports = {
setupTestFrameworkScriptFile: "<rootDir>/src/setupTests.ts"
}
This tells Jest to run setupTest.ts every time it's launched.
This way if you need to add polyfills or add global mock like localstorage, you can add it to your setupTests file and its configured everywhere.
The Enzyme docs don't cover integration with Jest, so it is confusing to fuse these two together.
For me when using React with create-react-app I had to make sure the file name was correct. The file has to be src/setupTests.js with an s at the end of Tests.
Inside setupTests.js is the following:
import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
configure({ adapter: new Adapter() });
When running npm run test it auto finds the setupTests.js file. There is no need to import it into each test file.
You need to use the import like this:
import Adapter from 'enzyme-adapter-react-16';
This way: (import * as Adapter from ...) returns a message "TypeError: Adapter is not a constructor."
Add import React from 'react'; to the top of your file.
You are using JSX syntax <MessageBox app={app}/>, which transpiles into React.createComponent(...). In order for this to work React variable must be defined in the scope of the file.
Try sth like this;
import React from 'react';
import App from './containers/App';
import enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
enzyme.configure({ adapter: new Adapter() });
describe('App Screen', () => {
let mountedAppScreen;
let props;
const appScreen = () => {
if (!mountedAppScreen) {
mountedAppScreen = enzyme.mount(
<App {...props} />
);
}
return mountedAppScreen;
}
it("it always renders div", () => {
const divs = appScreen().find("div");
expect(divs.length).toBeGreaterThanOrEqual(1);
});
});
Using the latest version of the libraries, I've faced the same error reported in every answer of this question. Error: TypeError: Adapter is not a constructor.
I've grouped all the necessary steps in order to proper test your ReactJS component using Enzyme (I've used Jest but it might work with Mocha as well, in that case, just switch the main test package):
1) Libraries (package.json):
"dependencies": {
"jest": "^24.6.0",
(...)
}
"devDependencies": {
"chai": "^4.2.0",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16": "^1.7.0",
(...)
}
2) TEST SETUP: You can setup the Enzyme in every test. But as type_master_flash wisely suggested, you can add a script to do that. In order to do so, create a new setting in your package.json file at the same level of the sessions scripts, dependencies, etc:
Jest Version 23.x (or previous):
"devDependencies": {
(...)
},
"jest": {
"setupTestFrameworkScriptFile": "./tests.setup.js"
},
After Jest 24.0 version: According to Jest Documentation, "setupTestFrameworkScriptFile is deprecated in favor of setupFilesAfterEnv".
"devDependencies": {
(...)
},
"jest": {
"setupFilesAfterEnv": ["./tests.setup.js"]
},
This file can be anywhere you prefer and you can name it as you wish. Just remember to setup the proper file location. In the current example I've stored my file in the root of my project.
3) tests.setup.js: As I've discovered in Enzyme: TypeError: Adapter is not a constructor, the problem here is that we cannot "import '' a module with a default export". The proper way of configuring your file is:
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
Just that and you are good to test your components.
Cheers and hope this helps.
For everyone who read this in the future, setupTestFrameworkScriptFile is deprecated in favor of setupFilesAfterEnv by the documentation, in new versions. We can add our file like this:
"setupFiles": [
"<rootDir>/src/setupTests.js"
]
I faced the same error and for some reason React wasn't picking up setupTests.js file automatically.
I created a new file called jest.config.js at the root directory and added
{ "jest": { "setupTestFrameworkScriptFile": "<rootDir>/path/to/your/file.js", } }
After this, error disappeared.
Note: Later on, I removed the jest.config.js file but it still works now.
Not sure what was actually causing the problem though!
The file configuration must be in setupFilesAfterEnv property of jest.config.js
{
...
setupFilesAfterEnv: ["<rootDir>/jest.transform.js"],
...
}
If anyone comes across this while trying to fix this after setting up Testing React Components with Jest in GatsbyJs (https://www.gatsbyjs.org/docs/testing-react-components/)
In the setup-test-env.js you make, edit it to look like this:
import "#testing-library/jest-dom/extend-expect"
import { configure } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
configure({ adapter: new Adapter() })
Create a file named setupTests.js in the root of your project. jest will automatically look for this file before running any test suits. Add the following content to the file.
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({adapter:new Adapter()})
Note: the filename should be exactly the same.no need to import this setupTests.js file into your test files.it will work automatically
For those who use VS Code and the Jest Runner extension for a React CRA app, don't forget to configure Jest Runner to use CRA's built in script runner by setting the jest command to:
npm test -- --watchAll=false
You will get the error in topic if you forget to do that. And since you are using CRA you won't be able to configure setupFilesAfterEnv in package.json nor jest.config.js. Trying that will result in this error:
These options in your package.json Jest configuration are not currently supported by Create React App
npm i enzyme-adapter-react-16 enzyme-to-json --save-dev
Add to package.json
enter image description here
"jest": {
"collectCoverageFrom": [ "src/**/*.js", "!src/index.js" ]
};
Add two files to src folder ->
setupTests.js
tempPolyfills.js
setupTests.js :
import requestAnimationFrame from './tempPolyfills';
import { configure } from "enzyme";
import Adapter from 'enzyme-adapter-react-16';
configure({adapter: new Adapter(), disableLifecycleMethods:true});
tempPolyfills.js:
const requestAnimationFrame = global.requestAnimationFrame = callback => {
setTimeout(callback,0);
};
export default requestAnimationFrame;
in case shallow -> expect() fails in test case use toJson() :
Example :
import { shallow } from "enzyme";
import App from "./App";
import toJson from 'enzyme-to-json';
describe('App', () => {
const app = shallow(<App />);
it('renders correctly', () => {
expect(toJson(app)).toMatchSnapshot();
});
});
If you think you've otherwise setup everything correctly (e.g. have the #wojtekmaj/enzyme-adapter-react-17 for React 17 support installed), one more pitfall to check with Typescript:
Do you have
"esModuleInterop": true,
and the matching import format for the adapter?
import Adapter from '#wojtekmaj/enzyme-adapter-react-17';
import Enzyme from 'enzyme';
I'm trying to setup a jest snapshot test with redux-persist in my react-native project. I don't think its an es2015 imports problem as my test code looks something like this:
import React from "react"
import "react-native"
// Note: test renderer must be required after react-native.
import renderer from "react-test-renderer"
import App from "../App"
it("renders correctly", () => {
const app = renderer.create(<App />).toJSON()
expect(app).toMatchSnapshot()
})
I ran this exact same test before I added redux-persist and it was working.
Error thrown by jest:
● Test suite failed to run
/Users/a_050313/Documents/dev/scheduling/node_modules/redux-persist/es/integration/react.js:9
import React, { PureComponent } from 'react'; // eslint-disable-line import/no-unresolved
^^^^^^
SyntaxError: Unexpected token import
1 | import React, { Component } from "react"
2 | import { Provider } from "react-redux"
> 3 | import { PersistGate } from "redux-persist/es/integration/react"
4 |
5 | import "./__debug__/ReactotronConfig" // Run Reactron Tools config
6 |
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:318:17)
at Object.<anonymous> (App.js:3:13)
at Object.<anonymous> (__tests__/App.js:7:10)`
The error was related to es2015 imports but It is on jest end. By default jest only transpiles project code and react-native code. So the added libs which aren't already transpilled would error out by jest.
(as mentioned on jest docs)
By default the jest-react-native preset only processes the project's own source files and react-native
Solution provided on the official docs seems a bit hacky but thats the only thing I found:
Add following in your package.json jest: { } section or in jest.config.js file.
"transformIgnorePatterns": [
"node_modules/(?!(react-native|my-project|redux-persist)/)"
]
where the bit redux-persist is the thing that solves the problem. If you have problem with other libs just add their names. My list looks something like this:
"jest": {
"preset": "react-native",
"transformIgnorePatterns": [
"node_modules/(?!(react-native|my-project|redux-persist|react-native-linear-gradient|react-native-vector-icons|react-navigation)/)"
]
}
Additional Note just for redux-persist if you import PersistGate from
import { PersistGate } from "redux-persist/lib/integration/react"
instead
import { PersistGate } from "redux-persist/es/integration/react"
(reference)
you'll get the compiled version but for other libs still you got to this the above mentioned solution.