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