I am writing a Test for a React Component Product
. I am using plain simple Jest without react-renderer
or enzyme
and I am aiming to keep it this way for the time being. I need to test a function of a component and havent been able to call it directly through jest. Code given below.
Component:
import React, { Component } from 'react';
class Product extends Component {
state = {
heading: `Old Heading`
};
changeHeading() {
this.setState({ heading: `New Heading` });
}
render() {
return (
<div>
<p data-testid='heading'> {this.state.heading} </p>
</div>
);
}
}
export default Product;
Jest
Test:
import React from 'react';
import { render } from 'react-dom';
// import { act } from 'react-dom/test-utils';
import Product from './Product';
let container = null;
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
document.body.removeChild(container);
container = null;
});
describe(`Testing Product Component`, () => {
it('renders without crashing', () => {
// act(() => {
// render(<Product />, container);
// });
const result = render(<Product />, container);
const heading = container.querySelector("[data-testid='heading']");
console.log(heading);
expect(heading).toBe(`Old Heading`);
result.changeHeading();
expect(heading).toBe(`New Heading`);
ReactDOM.unmountComponentAtNode(div);
});
});
OR
it('renders without crashing', () => {
const productComponent = <Product />;
render(productComponent, container);
const heading = container.querySelector("[data-testid='heading']");
console.log(heading);
expect(heading).toBe(`Old Heading`);
productComponent.changeHeading();
expect(heading).toBe(`New Heading`);
ReactDOM.unmountComponentAtNode(div);
});
But it didn't worked. How can I access the changeHeading
function from the component in my jest test? and call it to change the content of <p>
tag?
EDIT
I will reside with react-test-library if I have to for the timebeing. But it would be great if someone can explain the internal workings as well.
Thank you.
To test that, you need a user interaction that calls changeHeading()
. In your test, when you do const result = render(<Product />, container);
you are storing a reference to the component DOM node.
So, you need to modify your component to be able to have an interaction:
import React, { Component } from 'react';
class Product extends Component {
state = {
heading: `Old Heading`
};
changeHeading() {
this.setState({ heading: `New Heading` });
}
render() {
return (
<div>
<p data-testid='heading'> {this.state.heading} </p>
<button onclick={this.changeHeading}></button>
</div>
);
}
}
export default Product;
and your test would be:
import React from 'react';
import { render } from 'react-dom';
import { act } from 'react-dom/test-utils';
import Product from './Product';
let container = null;
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
document.body.removeChild(container);
container = null;
});
describe(`Testing Product Component`, () => {
it('renders without crashing', async () => {
act(() => {
render(<Product />, container);
});
let heading = container.querySelector("[data-testid='heading']");
expect(heading).toBe(`Old Heading`);
const button = container.querySelector('button');
await act(async () => {
button.dispatchEvent(new MouseEvent('click', { bubbles: true }));
});
heading = container.querySelector("[data-testid='heading']");
expect(heading).toBe(`New Heading`);
ReactDOM.unmountComponentAtNode(div);
});
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.