Шутка — вызов функции компонента React без фермента

#javascript #reactjs #jestjs #react-testing-library #babel-jest

#javascript #reactjs #jestjs #react-тестирование-библиотека #babel-шутка

Вопрос:

Я пишу тест для компонента React Product . Я использую простой Jest без react-renderer или enzyme , и я стремлюсь сохранить его таким на данный момент. Мне нужно протестировать функцию компонента, и я не смог вызвать ее напрямую через jest. Код, приведенный ниже.

Компонент:

 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 Тест:

 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);
    });
});
  

или

    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);
    });
  

Но это не сработало. Как я могу получить доступ к changeHeading функции из компонента в моем тесте jest? и вызвать ее, чтобы изменить содержимое <p> тега?

Редактировать

Я буду использовать react-test-library, если потребуется, в настоящее время. Но было бы здорово, если бы кто-нибудь мог объяснить и внутреннюю работу.

Спасибо.

Комментарии:

1. Я тоже вижу, что ты помечен react-testing-library . Вы пытаетесь использовать это вместо enzyme?

2. Разве это не может быть достигнуто без какой-либо из этих библиотек?

3. Теоретически, вы должны быть в состоянии (хотя я настоятельно рекомендую использовать react-testing-library ) Вы должны быть в состоянии протестировать это следующим образом: act(() => { render(<Product />, container); }); expect(container.textContent).toBe("Old Heading");

4. Не могли бы вы, пожалуйста, поделиться примером вызова функции компонента без использования react-testing-library ? Спасибо

5. Я думаю, вы подходите к этому неправильно. Эта функция должна запускаться каким-то действием или условием. В настоящее время он просто сидит там и никогда не выполняется. Когда заголовок изменится? Это нажатие кнопки? Затем назначьте его в качестве обработчика событий. Это какое-то условие, переданное в качестве реквизита? Если это так, вам нужно передать prop и убедиться, что ваше состояние инициализировано в конструкторе, иначе prop будет проигнорирован. Затем функцию можно вызвать с помощью user-event библиотеки из testing-library или enzyme's simulate, у вас есть несколько вариантов

Ответ №1:

Чтобы проверить это, вам нужно взаимодействие с пользователем, которое вызывает changeHeading() . В вашем тесте, когда вы это делаете const result = render(<Product />, container); , вы сохраняете ссылку на компонентный DOM-узел.

Итак, вам нужно изменить свой компонент, чтобы иметь возможность взаимодействовать:

 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;
  

и ваш тест был бы:

 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);
    });
});