I have a simple test file in ./pages/test.js
import React from 'react'
export default function HomePage () {
return (
<main>
<h1>Testing Next.js With Jest and React Testing Library</h1>
</main>
)
}
In ./test/pages/index.test.js I made the following simple test to check if my page is rendering properly and if it has a heading
import React from 'react'
// Using render and screen from test-utils.js instead of
// #testing-library/react
import { render, screen } from '../test-utils'
import HomePage from '../../pages/test'
describe('HomePage', () => {
it('should render the heading', () => {
render(<HomePage />)
const heading = screen.getByText('Testing Next.js With Jest and React Testing Library')
// we can only use toBeInTheDocument because it was imported
// in the jest.setup.js and configured in jest.config.js
expect(heading).toBeInTheDocument()
})
})
After running the test, I get the following error
FAIL pages/test.js
● Test suite failed to run
Your test suite must contain at least one test.
at onResult (node_modules/#jest/core/build/TestScheduler.js:175:18)
at node_modules/#jest/core/build/TestScheduler.js:304:17
at node_modules/emittery/index.js:260:13
at Array.map (<anonymous>)
at Emittery.Typed.emit (node_modules/emittery/index.js:258:23)
PASS test/pages/index.test.js
Test Suites: 1 failed, 1 passed, 2 total
Tests: 1 passed, 1 total
Why does jest say I am missing a test?
Why does jest say I am missing a test?
Because Jest thinks pages/test.js is a test file. Jest uses the following regex to detect test files.
(/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$
From the docs,
By default it looks for .js, .jsx, .ts and .tsx files inside of __tests__ folders, as well as any files with a suffix of .test or .spec (e.g. Component.test.js or Component.spec.js). It will also find files called test.js or spec.js.
A simple solution would be to rename the file.
Related
I've been having an odd issue with Jest/Enzyme testing on my react typescript app. For some reason it gives a syntax error even though this is following the official documentation, as well as input from several articles.
The Code:
import React from 'react';
import NavbarTop from "../components/navbar";
import { shallow } from 'enzyme';
describe('NavbarTop', () => {
it('renders correctly', () => {
const wrapper = shallow(<NavbarTop />);
expect(wrapper).toMatchSnapshot();
// On the first run of this test, Jest will generate a snapshot file automatically.
});
});
The folder structure. I have a named class and then an index with a default export.
The error log.
Do you have JSX configured for Jest? Looks like you don't have support for JSX in Jest, which probably means this is a configuration issue. Have a look at configuring babel to support JSX in Jest.
Make sure you read this tutorial
I've got a (private) npm module that exports several React components. The module is bundled by Webpack and in the generated bundle a reference to one of the components (say Warning) looks like this:
t.d(n,"Warning",function(){return ge})
Then I've got a React project importing this module:
import { Warning } from 'my-custom-module';
...
render() {
return (
<Warning>Lorem ipsum</Warning>
);
}
This all works OK, but when I create a Jest snapshot of the component above, I expect the snapshot to look like
<Warning>Lorem ipsum</Warning>
but it looks like:
<ge>Lorem ipsum</ge>
For some reason Jest takes the minified identifier instead of the exported name of the component. How can I see the component name in the Jest snapshot? I'm unsure if I do need to adjust my Webpack config or the Jest setup...
Since you are referring the uglified version of the 'my-custom-module' it will try to render to the uglified names. However, I assume what you actually you need is to shallowly render your component.
You can use the Enzyme libraries's shallow renderer for this.
//MyAwesomeComponent.js
import { Warning } from 'my-custom-module';
export default class MyAwesomeComponent extends Component{
render(){
return (<Warning>Lorem ipsum</Warning>);
}
}
//MyAwesomeComponent.test.js
import { shallow } from 'enzyme';
import MyAwesomeComponent from './MyAwesomeComponent';
it('renders <MyAwesomeComponent />', () => {
const shallowMyComponent = shallow(<MyComponent />);
expect(shallowMyComponent).toMatchSnapshot()
});
This should show your snapshot as Warning without going a level deeper.
I'm using a __mocks__ folder to mock a node_module. Nice.
Example to one of the mocks, that mock 'react-relay': https://gist.github.com/robrichard/ad838e599d828a89978f54faaa2070a8
The file is located as such __mocks__/relay-react.js,
the the mock with be used in my test when jest.mock('react-relay) is executed in the testfile.
However, I have many repos that need that same mock. Is it possible to put the mock in a node_module, so to streamline my tests and do not have to copy/paste the mock everywhere?
This is the best solution so far (as described here: https://github.com/facebook/jest/issues/2726#issuecomment-283100333):
testutils.js
import React, { Component } from 'react';
exports.mockRelay = {
createFragmentContainer: Component => props => <Component {...props} />,
...
// all the named imports you want to mock
};
then in the testfile call
jest.mock('react-relay', () => require('util/testutils').mockRelay)
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'm getting this error in my React enzyme test - TypeError: Cannot read property 'have' of undefined
Below is my test file:
import React from 'react';
import ReactDOM from 'react-dom';
import { mount } from 'enzyme';
import TransactionsTable from './TransactionsTable';
import Pagination from './Pagination';
it('contains a table', () => {
const wrapper = mount(<TransactionsTable />);
expect(wrapper.find(Pagination)).to.have.lengthOf(1);
});
I can't see where my code differs from the solutions I've seen to this. Also, it seems in accordance with the docs. Anything I've missed?
UPDATE
I also tried fixing to the following (for Jest), but I huge output of red:
const wrapper = mount(<TransactionsTable />);
expect(wrapper.find(Pagination)).toHaveLength(1);
Error:
FAIL src/components/includes/TransactionsTable.test.js
● <TransactionsTable /> › contains a table
expect(received).toHaveLength(length)
Expected value to have length:
1
Received:
{Symbol(enzyme.__unrendered__): null, Symbol(enzyme.__renderer__): {"batchedUpdates": [Function batchedUpdates], "getNode": [Function getNode], "render":...
It seems to be the correct method call now (toHaveLength) but am I passing in the Pagination component in wrong now?
I suppose that the error, you've got after you have used a valid matcher appears because enzyme cannot find Pagination component in TransactionsTable.
toHaveLength Jest matcher gives strange output when it fails while being used with enzyme wrapper.
Try to use the following statement
expect(wrapper.find(Pagination).length).toBe(1);
and I bet you will get an error that the expected value is 1 but 0 received.
PS: here is the issue in Jest repo about the strange output.
It depends which test runner or assertion library you are using.
For Jest you want to use toHaveLength
it('contains a table', () => {
const wrapper = mount(<TransactionsTable />);
expect(wrapper.find(Pagination)).toHave.lengthOf(1);
});
Where as chai would be to.have.lengthOf(1)