#reactjs #enzyme
#reactjs #enzyme
Вопрос:
как я могу протестировать дочерний компонент onclick.
Пожалуйста, посмотрите фрагмент ниже.
// App.js
import React, {Component, Fragment} from 'react'
import Child from './child'
class App extends Component{
state = {
data: null,
enable: false
}
componentDidMount(){
this.getData()
}
getData = async () => {
const response = await fetch('http://www.example.com');
const data = await response.json();
this.setState({
data
})
}
_handleChildClick = () => {
this.setState({
enable: true
})
}
render(){
const {data, enable} = this.state
if(!data){
return (
<div>
Loading
</div>
)
}else{
<Fragment>
<Child
handleChildClick={this._handleChildClick}
/>
</Fragment>
}
}
}
export default App
import React from 'react';
const child = () => {
return(
<div>
<button
className="toggle"
onClick={props.handleChildClick}
>
Toggle
</button>
</div>
)
}
export default child
// App.test.js
import React from 'react';
import {enzyme} from 'enzyme';
import App from './App';
describe("App test cases", () => {
it('should trigger _handleChildClick', async () => {
window.fetch = jest.fn().mockImplementation(() => ({
status: 200,
json: () => new Promise((resolve, reject) => {
resolve(
{
name: "some data"
}
)
})
}))
const mountWrapper = await mount(<App />)
setTimeout(() => {
mountWrapper.update()
const SpyhandleChildClick = jest.spyOn(mountWrapper.instance(),'_handleChildClick')
mountWrapper.find('.toggle').simulate('click')
expect(SpyhandleChildClick).toHaveBeenCalled() // not called
},0)
})
})
Комментарии:
1. Привет @DILEEPTHOMAS Ты нашел ответ?
Ответ №1:
Некоторые важные моменты, которые следует учитывать.
Асинхронный код в ваших тестах
Если вам нужно выполнять асинхронные задачи в ваших тестах, вам всегда приходится ждать, пока асинхронный материал не будет завершен.
setTimeout(() => {
mountWrapper.update()
const SpyhandleChildClick = jest.spyOn(mountWrapper.instance(),'_handleChildClick')
mountWrapper.find('.toggle').simulate('click')
expect(SpyhandleChildClick).toHaveBeenCalled() // not called
},0)
Выше в вашем коде у вас есть сегмент тайм-аута. Любое тестовое условие внутри этого блока кода не будет оценено, поскольку к моменту их оценки ваш «тестовый сеанс» уже будет завершен из-за характера aync.
Тестирование функций со стрелкой в React с помощью enzyme — forceUpdate()
Похоже, что существует проблема с библиотекой enzyme, где вам приходится принудительно обновлять компонент react после того, как вы следите за тем, чтобы он привязался к методу. Пожалуйста, следите за выпуском github для получения дополнительной информации:https://github.com/airbnb/enzyme/issues/365
Я также немного почистил ваш тестовый код, чтобы сделать его более понятным!
// App.test.js
import React from 'react';
import {enzyme} from 'enzyme';
import App from './App';
describe("App test cases", () => {
it("should trigger _handleChildClick", async () => {
window.fetch = jest.fn().mockImplementation(() => ({
status: 200,
json: () =>
new Promise((resolve, reject) => {
resolve({
name: "some data"
});
})
}));
const mountWrapper = mount(<App />);
mountWrapper.update();
console.log("mountWrapper", mountWrapper.debug()); // showing the loader one
//[FIX]This code will block and wait for your asynchronous tasks to be completed
await new Promise(res => setTimeout(() => res(), 0));
mountWrapper.update();
console.log("mountWrapper", mountWrapper.debug()); // nothing showing
expect(mountWrapper.find(".toggle").length).toEqual(1);
//[FIX]Get a reference from the wrapper and force update after the spyOn call
const instance = mountWrapper.instance();
const spy = jest.spyOn(instance, "_handleChildClick");
instance.forceUpdate();
mountWrapper.find(".toggle").simulate("click");
expect(spy).toHaveBeenCalled();
});
});
Ссылка на демонстрационную версию: Нажмите на вкладку «Тесты» в браузере, чтобы увидеть результаты теста
https://codesandbox.io/s/mz21kpm37j