Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest - Call React Component function without Enzyme

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.

like image 355
Ahmed Avatar asked Apr 30 '26 06:04

Ahmed


1 Answers

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);
    });
});
like image 63
joanmunoz Avatar answered May 02 '26 21:05

joanmunoz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!