I am new to writing Unit tests and i am trying to write unit tests to my react application using testing-library/react and jest
Here is the test code "Home.test.js"
import React from 'react';
import {render, cleanup} from '#testing-library/react';
import '#testing-library/jest-dom/extend-expect';
import Home from "../src/Home";
afterEach(cleanup);
describe("Tests for HomePage", function() {
it("should render without throwing an error", function() {
const { homePage } = render(<Home />);
//check something here
});
});
Here is my code in component "Home.js"
import * as React from "react";
import { Panel, Shell, Button } from "#myorg/core";
import { home_icon, new_icon } from "#myorg/icons";
function Home(props) {
const openDialog = React.useCallback(() => {
//do something
});
return (
<Shell.Page breadcrumbs={[t("demo:Home")]}>
<Panel style={{ height: "100%" }}>
<h2>App Header</h2>
<Button onClick={openDialog} variant="primary">
<img src={new_icon} width="20" />
{t("demo:New Asset")}
</Button>
</Panel>
</Shell.Page>
);
}
error I get when I run "npm run test"
Cannot find module '#myorg/icons' from 'Home.js'
I believe you are trying to use the tsconfig.json options paths, which will be ignored by jest (or by other testing frameworks). You need to manually replicate all your paths definition in jest.config.js and manually keep them updated using the jest config option moduleNameMapper like this:
moduleNameMapper: {
// translate all your custom paths here, read the doc in the link above
'^#finder/(.*)$': '<rootDir>/files-manipulation/$1',
'^#metadata/(.*)$': '<rootDir>/folder-metadata/$1',
'^#logger/(.*)$': '<rootDir>/logging/$1',
// ...and so on
},
Related
I'm using react-hook-media-query in my project but the test is failing because of it.
This is the code:
import React from 'react';
import useMediaQuery from 'react-hook-media-query';
const MyCompp = (props) => {
const minWidth1200 = useMediaQuery('(min-width: 1200px)');
...
}
test file:
import React from 'react';
import App from './App';
import { render } from '#testing-library/react';
import { WrapIntlProvider, WrapStore } from '../testsHelper';
jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
useSelector: () => ({
locale: 'en-US',
messages: {}
})
}));
describe('<App />', function () {
it('should render <App />', () => {
const { container } = render(
<WrapStore>
<WrapIntlProvider>
<App />
</WrapIntlProvider>
</WrapStore>
);
expect(container).toMatchSnapshot();
});
});
and when I run the tests it throws this error message:
● 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:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
• 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:
/.../node_modules/react-hook-media-query/dist/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import
{ useState, useEffect } from 'react';
^^^^^^
SyntaxError: Cannot use import statement outside a module
> 2 | import useMediaQuery from 'react-hook-media-query';
| ^
Any ideas how to get rid of it?
I am getting SyntaxError: /test/ut/client/breadcrumbs/BreadCrumbs.ut.test.js: Unexpected token (12:6) error. Code is given below. And the code coverage is 0% because test suits failed.
I am using jest v-"^24.8.0", jest-dom v-"^3.5.0", jest-junit v-"^6.4.0"
describe("BreadCrumbs", () => {
afterEach(cleanup);
test("Should render breadcrumbs on usecase page", () => {
const useCaseBreadCrumbs = create(
<BreadCrumbs
list={USECASE_BREADCRUMBS.list}
disabledLabel={USECASE_BREADCRUMBS.disabledLink}
/>
);
console.log(useCaseBreadCrumbs);
expect(tree).toMatchSnapshot();
});
});
You need to add import React from "react"; on top
import React from 'react'
import toJson from 'enzyme-to-json'
import {ScreensCreateAccount} from './CreateAccount'
describe('Testing CreateAccount Component', () => {
const props = {
auth: {
isAuth: false,
isLoadding: false
}
}
it('should render correctly', () => {
const wrapper = shallow(<ScreensCreateAccount {...props}/>)
expect(toJson(wrapper)).toMatchSnapshot()
})
})
I have this test for my component CreateAccount, and i want to know if is necessary to use expect(toJson(wrapper)).toMatchSnapshot() or using just
expect(wrapper).toMatchSnapshot() is correct too. Both implementation build a folder with snapshots with file CreateAccount.test.js.snap. Whats is the diference?
Enzyme-to-json serializes component, created by Enzyme. If your tests work without it, then you have it already configured in jest configuration file.
If no, you can add this to package.json to work:
"jest": {
"snapshotSerializers": ["enzyme-to-json/serializer"]
}
I'm using react-native-fcm and jest to test my React Native app. I have a pretty basic test, it looks like this:
import 'react-native';
import React from 'react';
import PushController from '../app/PushController';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('works correctly', () => {
const tree = renderer.create(
<PushController />
);
});
And PushController is somewhat large, so here's the interesting parts
import React, { Component } from 'react';
import { AsyncStorage } from 'react-native';
import FCM from 'react-native-fcm';
export default class PushController extends Component {
(...)
componentDidMount() {
if (this.notificationListener) this.notificationListener.remove();
this.notificationListener = FCM.on('notification', (notif) => {
if (!notif.local_notification) {
this.notifyUser(notif.coffee);
}
});
FCM.unsubscribeFromTopic('/topics/coffee');
FCM.subscribeToTopic('/topics/coffee');
}
(...)
However, when running the test I get
__tests__/PushControllerTest.js
● works correctly
TypeError: Cannot read property 'unsubscribeFromTopic' of undefined
at Object.FCM.unsubscribeFromTopic (node_modules/react-native-fcm/index.js:86:15)
at PushController.componentDidMount (app/PushController.js:44:26)
at node_modules/react-test-renderer/lib/ReactCompositeComponent.js:265:25
at measureLifeCyclePerf (node_modules/react-test-renderer/lib/ReactCompositeComponent.js:75:12)
at node_modules/react-test-renderer/lib/ReactCompositeComponent.js:264:11
at CallbackQueue.notifyAll (node_modules/react-test-renderer/lib/CallbackQueue.js:76:22)
at ReactTestReconcileTransaction.ON_DOM_READY_QUEUEING.close (node_modules/react-test-renderer/lib/ReactTestReconcileTransaction.js:36:26)
at ReactTestReconcileTransaction.TransactionImpl.closeAll (node_modules/react-test-renderer/lib/Transaction.js:206:25)
at ReactTestReconcileTransaction.TransactionImpl.perform (node_modules/react-test-renderer/lib/Transaction.js:153:16)
at batchedMountComponentIntoNode (node_modules/react-test-renderer/lib/ReactTestMount.js:69:27)
I've tried including lots of stuff in the test, like jest.mock('react-native-fcm') and others, but I can't get it to work at all. I get that jest automatically mocks the library, but I don't understand why FCM is undefined. Any ideas?
I managed to solve it, finally! Simply needed to change my test to
import 'react-native';
import React from 'react';
import PushController from '../app/PushController';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
import FCM from 'react-native-fcm'; // <-- This
it('works correctly', () => {
FCM.unsubscribeFromTopic = jest.fn(); // <-- These two
FCM.subscribeToTopic = jest.fn();
const tree = renderer.create(
<PushController />
);
});
To make sure the actual calls are mocked. I did a lot of googling before this, so I'm sure this will be useful for someone.
Currently I am manually initializing Quill editor on componentDidMount and jest tests fail for me. Looks like ref value that I am getting is null in jsdom. There is and issue here: https://github.com/facebook/react/issues/7371 but looks like refs should work. Any ideas what I should check?
Component:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
componentDidMount() {
console.log(this._p)
}
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro" ref={(c) => { this._p = c }}>
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}
Test:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import renderer from 'react-test-renderer'
it('snapshot testing', () => {
const tree = renderer.create(
<App />
).toJSON()
expect(tree).toMatchSnapshot()
})
As a result, console.log outputs null. But I would expect P tag
Since test renderer is not coupled to React DOM, it doesn't know anything about what refs are supposed to look like. React 15.4.0 adds the ability to mock refs for test renderer but you should provide those mocks yourself. React 15.4.0 release notes include an example of doing so.
import React from 'react';
import App from './App';
import renderer from 'react-test-renderer';
function createNodeMock(element) {
if (element.type === 'p') {
// This is your fake DOM node for <p>.
// Feel free to add any stub methods, e.g. focus() or any
// other methods necessary to prevent crashes in your components.
return {};
}
// You can return any object from this method for any type of DOM component.
// React will use it as a ref instead of a DOM node when snapshot testing.
return null;
}
it('renders correctly', () => {
const options = {createNodeMock};
// Don't forget to pass the options object!
const tree = renderer.create(<App />, options);
expect(tree).toMatchSnapshot();
});
Note that it only works with React 15.4.0 and higher.
I used Enzyme-based test from this repo to solve this issue like that:
import { shallow } from 'enzyme'
import toJson from 'enzyme-to-json'
describe('< SomeComponent />', () => {
it('renders', () => {
const wrapper = shallow(<SomeComponent />);
expect(toJson(wrapper)).toMatchSnapshot();
});
});