How to mock a React Component static method with Jest - reactjs

This was really hard to find out how to do. I could not find any code to show you how to mock a static method in a React Component. This way worked for me.
// YourComponent.js
class YourComponent extends Component {
static getHelloWorld () {
return 'hello world';
}
render() {
return (
<div>{YourComponent.getHelloWorld()}</div>
)
}
}
export default YourComponent;
// YourComponent.test.js
import { mount } from 'enzyme';
import YourComponent from './YourComponent';
YourComponent.__proto__.getHelloWorld = jest.fn(() => { return 'Hello Universe' });
describe('YourComponent test for mocking static method', () => {
it('should render', () => {
const wrapper = mount(<YourComponent />);
expect(wrapper.text()).toEqual('Hello Universe');
});
});

Here is the solution:
index.js:
import { Component } from 'react';
class YourComponent extends Component {
static getHelloWorld() {
return 'hello world';
}
render() {
return <div>{YourComponent.getHelloWorld()}</div>;
}
}
export default YourComponent;
index.test.js:
import { mount } from 'enzyme';
import YourComponent from './';
describe('YourComponent test for mocking static method', () => {
it('should render', () => {
YourComponent.getHelloWorld = jest.fn(() => {
return 'Hello Universe';
});
const wrapper = mount(<YourComponent />);
expect(wrapper.text()).toEqual('Hello Universe');
});
});
unit test result with coverage report:
PASS stackoverflow/61022182/index.test.js (8.455s)
YourComponent test for mocking static method
✓ should render (30ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 88.89 | 100 | 66.67 | 87.5 |
index.js | 88.89 | 100 | 66.67 | 87.5 | 5
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.327s

Related

Jest React: How to mock window eventListener set in componentDidMount

Here I need to add tests for handleBeforeUnload in window eventListener but I am getting error, How will I resolve it?
expect(jest.fn())[.not].toHaveBeenCalled()
Matcher error: received value must be a mock or spy function
Received has value: undefined
map.beforeunload();
expect(wrapper.handleBeforeUnload).toHaveBeenCalled();
My component
componentDidMount() {
window.addEventListener('beforeunload', (event) => {
this.handleBeforeUnload();
});
}
handleBeforeUnload () {
}
My test spec:
it('should call handleBeforeUnload', () => {
const historyMock = { listen: jest.fn(), replace: jest.fn() };
const map = {};
window.addEventListener = jest.fn((event, cb) => {
map[event] = cb;
});
const wrapper = shallow(
<AppRoutes history={historyMock} getDctkConfig={getDctkConfig} />,
);
map.beforeunload();
expect(wrapper.handleBeforeUnload).toHaveBeenCalled();
});
You didn't spy the.handleBeforeUnload() method of the component class. You can spy it through Component.prototype.handleBeforeUnload. Besides, you can mock the implementation of the .addEventListener() method and invoke the listener function manually.
index.tsx:
import React, { Component } from 'react';
export default class AppRoutes extends Component {
componentDidMount() {
window.addEventListener('beforeunload', (event) => {
this.handleBeforeUnload();
});
}
handleBeforeUnload() {}
render() {
return <div>app routes</div>;
}
}
index.test.tsx:
import { shallow } from 'enzyme';
import React from 'react';
import AppRoutes from './';
describe('69346085', () => {
afterEach(() => {
jest.restoreAllMocks();
});
test('should pass', () => {
const handleBeforeUnloadSpy = jest.spyOn(AppRoutes.prototype, 'handleBeforeUnload');
jest
.spyOn(window, 'addEventListener')
.mockImplementation((type: string, listener: EventListenerOrEventListenerObject) => {
typeof listener === 'function' && listener({} as Event);
});
shallow(<AppRoutes />);
expect(handleBeforeUnloadSpy).toHaveBeenCalled();
});
});
test result:
PASS examples/69346085/index.test.tsx (9.191 s)
69346085
✓ should pass (7 ms)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.tsx | 100 | 100 | 100 | 100 |
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.814 s, estimated 10 s

React mock Graphql subscription

I have a react project, which I am testing using Jest. I am trying to mock a call to AWS graphql and in particular, a subscribe. Here is the code I am trying to mock
await API.graphql(
graphqlOperation(subscriptions.addedProduct))
.subscribe({
next: (response) => {
this.setState({ products: [...this.state.products, response.value.data.addedProduct] })
}
});
I usually mock using spyOn with something like this...
const mockProducts = jest.spyOn(API, 'graphql').mockImplementation(async () =>
Promise.resolve(mockResponse)
);
but would get the error
TypeError: _awsAmplify.API.graphql(...).subscribe is not a function
Has anyone got an example of mocking a subscribe in a similar way?
You need to mock the return value of API.graphql as an Observable that come from reactive programming. Then, you can use .subscribe method. Below example, I use the of operator of rxjs to create an Observable.
E.g.
main.jsx:
import React, { Component } from 'react';
import { API } from './api';
export class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
products: [],
};
}
async componentDidMount() {
await API.graphql('graphqlOperation(subscriptions.addedProduct)').subscribe({
next: (response) => {
this.setState({ products: [...this.state.products, response.value.data.addedProduct] });
},
});
}
render() {
return <div>my component</div>;
}
}
main.test.js:
import { MyComponent } from './main';
import { API } from './api';
import { of } from 'rxjs';
describe('61454572', () => {
it('should pass', async () => {
const mockResponse = { value: { data: { addedProduct: 'fake product' } } };
const graphqlSpy = jest.spyOn(API, 'graphql').mockImplementation(() => {
return of(mockResponse);
});
const wrapper = shallow(<MyComponent></MyComponent>);
expect(wrapper.state('products')).toEqual(['fake product']);
expect(graphqlSpy).toBeCalledWith('graphqlOperation(subscriptions.addedProduct)');
graphqlSpy.mockRestore();
});
});
unit test results with coverage report:
PASS stackoverflow/61454572/main.test.jsx (11.328s)
61454572
✓ should pass (12ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 88.24 | 100 | 83.33 | 86.67 |
api.js | 50 | 100 | 0 | 50 | 5-6
main.jsx | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 13.119s

Assert onBlur() funciton in functional component jest

I wrote a test case to call onBlur method, but I'm getting an error when I try to assert it. Here is the above test case.
it("call the handlingBlurEmail method", () => {
const wrapper = mount(
<App childRef={() => {}} />
);
const comp = wrapper.find({ id: "email" }).first();
comp.prop("onBlur")({
target: { id: "email", value: "test#gmail.com" }
});
expect(
wrapper
.find("AccountForm")
.state()
.onBlur()
).toHaveBeenCalled();
});
and the function for which I'm writing test case is
mailReference = React.createRef();
handlingEmailBlur = events => {
this.mailReference.current.validate(events.target.value);
};
render = () {
......
return (
<div className="Form1">
onBlur={this.handlingEmailBlur}
</div>
)
.....
}
Please let me know how to add assert statement in order to call the onBlur() method in the above test case
Here is the unit testing solution:
index.tsx:
import React, { Component } from 'react';
class App extends Component {
mailReference = React.createRef();
handlingEmailBlur = (events) => {
this.mailReference.current.validate(events.target.value);
};
render() {
return (
<div className="Form1" onBlur={this.handlingEmailBlur}>
some component
</div>
);
}
}
export default App;
index.spec.tsx:
import App from './index';
import { mount } from 'enzyme';
import React from 'react';
describe('59455504', () => {
afterEach(() => {
jest.restoreAllMocks();
});
it('call the handlingBlurEmail method', () => {
const mailReference = { current: { validate: jest.fn() } };
jest.spyOn(React, 'createRef').mockReturnValue(mailReference);
const wrapper = mount(<App childRef={() => {}} />);
const mEvent = {
target: { id: 'email', value: 'test#gmail.com' },
};
wrapper.find('.Form1').prop('onBlur')(mEvent);
expect(mailReference.current.validate).toBeCalledWith(mEvent.target.value);
});
});
Unit test result with 100% coverage:
PASS src/stackoverflow/59455504/index.spec.jsx (8.328s)
59455504
✓ call the handlingBlurEmail method (40ms)
-----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.jsx | 100 | 100 | 100 | 100 | |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.769s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59455504

e.target.parentNode.getAttribute("id") / e.targe.getAttribute("id") unit test jest enzyem

Does anyone have a jest/enzyme test example for event.target.getAttribute?
handleButtonsClicks = () => {
if(e.target.parentNode.getAttribute("id")=== "id1") {
//
} else if (e.target.getAttribute("id") === "id2") {
//
}
}
<Button id="id1" onClick={handleButtonsClicks}/>
<Button id="id2" onClick={handleButtonsClicks}/>
Thanks
Here is a completed demo:
index.tsx:
import React, { Component } from 'react';
class SomeComponent extends Component {
constructor(props) {
super(props);
this.handleButtonsClicks = this.handleButtonsClicks.bind(this);
}
handleButtonsClicks(e) {
if (e.target.parentNode.getAttribute('id') === 'id1') {
console.log('do something');
} else if (e.target.getAttribute('id') === 'id2') {
console.log('do another thing');
}
}
render() {
return (
<div>
<button id="id1" onClick={this.handleButtonsClicks}>
Button 1
</button>
<button id="id2" onClick={this.handleButtonsClicks}>
Button 2
</button>
</div>
);
}
}
export default SomeComponent;
index.spec.tsx:
import React from 'react';
import { shallow } from 'enzyme';
import SomeComponent from './';
describe('SomeComponent', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<SomeComponent></SomeComponent>);
jest.restoreAllMocks();
});
test('should handle button click', () => {
const logSpy = jest.spyOn(console, 'log');
expect(wrapper.find('button')).toHaveLength(2);
const mEvent = { target: { parentNode: { getAttribute: jest.fn().mockReturnValueOnce('id1') } } };
wrapper.find('#id1').simulate('click', mEvent);
expect(logSpy).toBeCalledWith('do something');
expect(mEvent.target.parentNode.getAttribute).toBeCalledWith('id');
});
test('should handle button click', () => {
const logSpy = jest.spyOn(console, 'log');
expect(wrapper.find('button')).toHaveLength(2);
const mEvent = {
target: {
getAttribute: jest.fn().mockReturnValueOnce('id2'),
parentNode: { getAttribute: jest.fn() }
}
};
wrapper.find('#id1').simulate('click', mEvent);
expect(logSpy).toBeCalledWith('do another thing');
expect(mEvent.target.getAttribute).toBeCalledWith('id');
});
});
Unit test result:
PASS src/stackoverflow/58457004/index.spec.tsx
SomeComponent
✓ should handle button click (16ms)
✓ should handle button click (3ms)
console.log node_modules/jest-mock/build/index.js:860
do something
console.log node_modules/jest-mock/build/index.js:860
do another thing
-----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files | 100 | 83.33 | 100 | 100 | |
index.tsx | 100 | 83.33 | 100 | 100 | 12 |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 4.139s, estimated 8s

How to test redirects in ComponentWillMount in enzyme/jest

I am new to testing in Enzyme and Jest.
I want to test my ComponentWillMount method, whether certain redirect will happen or not.
Here is the code of my component:
class ActivationSF extends Component {
constructor(props) {
super(props);
this.className = 'ActivationSF.js'
this.state = {
messages: null,
}
}
render() {
return (
<ActivationUI
context={this.props.context}
messages={this.state.messages}
/>
);
}
componentWillMount() {
let context = this.props.context
if(!context.userInfo){
window.location.replace('/identify')
}
let externalLP = ExternalLandingPageUtil.getExternalLandingPageUrl(context);
if (externalLP) {
window.location.replace(`${externalLP}`);
return;
}
if (context.userInfo)
{
window.location = '/store'
}
}
componentDidMount() {
document.body.classList.add('sdp')
}
Here is a unit test strategy:
index.tsx:
import React, { Component } from 'react';
import { ExternalLandingPageUtil } from './ExternalLandingPageUtil';
import { ActivationUI } from './ActivationUI';
export class ActivationSF extends Component<any, any> {
public className: string;
constructor(props) {
super(props);
this.className = 'ActivationSF.js';
this.state = {
messages: null
};
}
render() {
return <ActivationUI context={this.props.context} messages={this.state.messages} />;
}
componentWillMount() {
let context = this.props.context;
if (!context.userInfo) {
window.location.replace('/identify');
}
let externalLP = ExternalLandingPageUtil.getExternalLandingPageUrl(context);
if (externalLP) {
window.location.replace(`${externalLP}`);
return;
}
if (context.userInfo) {
window.location.replace('/store');
}
}
componentDidMount() {
document.body.classList.add('sdp');
}
}
ActivationUI.tsx:
import React from 'react';
export const ActivationUI = ({ context, messages }) => <div>ActivationUI</div>;
ExternalLandingPageUtil.ts:
export const ExternalLandingPageUtil = {
getExternalLandingPageUrl(context) {
return context.externalLP;
}
};
index.spec.tsx:
import React from 'react';
import { ActivationSF } from './';
import { ExternalLandingPageUtil } from './ExternalLandingPageUtil';
import { shallow } from 'enzyme';
window.location.replace = jest.fn();
describe('ActivationSF', () => {
afterEach(() => {
jest.resetAllMocks();
});
test('should redirect to /identify', () => {
const mProps = { context: {} };
const wrapper = shallow(<ActivationSF {...mProps}></ActivationSF>);
expect(window.location.replace).toBeCalledWith('/identify');
});
test('should redirect to external IP address', () => {
const spy = jest.spyOn(ExternalLandingPageUtil, 'getExternalLandingPageUrl');
const mProps = { context: { userInfo: {}, externalLP: '10.0.0.1' } };
const wrapper = shallow(<ActivationSF {...mProps}></ActivationSF>);
expect(window.location.replace).toBeCalledWith('10.0.0.1');
expect(spy).toBeCalledWith(mProps.context);
});
test('should redirect to /store', () => {
const mProps = { context: { userInfo: {} } };
const wrapper = shallow(<ActivationSF {...mProps}></ActivationSF>);
expect(window.location.replace).toBeCalledWith('/store');
});
test('should render correctly', () => {
const mProps = { context: {} };
const addSpy = jest.spyOn(document.body.classList, 'add');
const wrapper = shallow(<ActivationSF {...mProps}></ActivationSF>);
expect(wrapper.prop('context')).toEqual(mProps.context);
expect(wrapper.state('messages')).toBeNull();
expect(addSpy).toBeCalledWith('sdp');
addSpy.mockRestore();
});
});
Unit test result with 100% coverage for ActivationSF component.
PASS src/stackoverflow/57673447/index.spec.tsx (12.286s)
ActivationSF
✓ should redirect to /identify (14ms)
✓ should redirect to external IP address (2ms)
✓ should redirect to /store (1ms)
✓ should render correctly (2ms)
----------------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------------------------|----------|----------|----------|----------|-------------------|
All files | 90.32 | 100 | 85.71 | 100 | |
ActivationUI.tsx | 40 | 100 | 0 | 100 | |
ExternalLandingPageUtil.ts | 100 | 100 | 100 | 100 | |
index.tsx | 100 | 100 | 100 | 100 | |
----------------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 4 passed, 4 total
Snapshots: 0 total
Time: 14.412s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57673447

Resources