我正在玩弄反应和开玩笑而且我遇到了以下情况,我根本无法弄明白我应该怎么做。
Todo.js
import React from 'react';
import PropTypes from 'prop-types';
import TodoItem from './TodoItem';
import {fetchTodoItems} from '../helpers/todo';
class Todo extends React.Component {
constructor(props) {
super(props);
this.state = {
todos: [],
error: false,
loading: true
};
this.updateMockState = this.updateMockState.bind(this);
}
updateMockState() {
this.setState({
todos: [{ id: 8101, text: "Cook fresh food", status: "completed" }],
loading: false
});
}
componentDidMount() {
// TODO: add error handling
fetchTodoItems().then(response => {
this.setState({
todos: response.data,
loading: false
})
}, error => {});
}
render() {
let content;
// TODO: add error handling
if (this.state.loading) {
return (
<div>
<div>
<button id="update-data" onClick={this.updateMockState}>Update State</button>
</div>
<p>Todos are being fetched...</p>
</div>
);
}
return (
content ||
<div>
<div>
<button id="update-data" onClick={this.updateMockState}>Update State</button>
</div>
<p><b>{this.state.todos.length}</b> todos fetched so far</p>
{this.state.todos.map(
(todo) => <TodoItem key={todo.id} id={todo.id} status={todo.status} text={todo.text} />)}
</div>
);
}
}
Todo.proptypes = {
timeout: PropTypes.number
};
export default Todo;
Todo.test.js
import React from 'react';
import ReactDOM from 'react-dom';
import renderer from 'react-test-renderer';
import { mount, shallow, render } from 'enzyme';
import Todo from '../components/Todo';
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import toJson from 'enzyme-to-json';
// TODO: remove sinon from NPM packages
Enzyme.configure({ adapter: new Adapter() });
const todos = { data: [{
"id": 4404,
"status": "active",
"text": "Shopping List"
}, {
"id": 7162,
"status": "completed",
"text": "Time Registration"
}]};
describe('Todo', () => {
it('calls mock API', async () => {
fetch = jest.fn().mockReturnValue(Promise.resolve(todos));
const spy = jest.spyOn(Todo.prototype, 'componentDidMount');
var component = mount(<Todo timeout={2000} />);
component.instance().componentDidMount();
expect(spy).toHaveBeenCalled();
expect(toJson(component)).toMatchSnapshot();
});
});
正如您所见,Todo组件是一个简单的组件,在componentDidMount内部调用API,获取响应并显示。在等待api呼叫时,会显示一些信息......还有一个用于虚拟状态更新的按钮,但现在这并不重要。
fetchTodoItems(文件是todo.js)
export const fetchTodoItems = () => {
return fetch("data/todo.json").then(res => res.json());
};
我的问题如下:
一,我应该看到没有待办事项,但在第二天,我应该看到我的待办事项。
这是TodoItem
import React from 'react';
import PropTypes from 'prop-types';
const TodoItem = (props) => {
let htmlClass = [];
if (props.status === 'completed') {
htmlClass.push("todo-completed");
}
return (
<ul>
<p className={htmlClass.join(" ")}>
<small>[#{props.id}]</small> {props.text} <i>({props.status})</i>
</p>
</ul>
);
}
TodoItem.proptypes = {
id: PropTypes.number.required,
text: PropTypes.string.required,
status: PropTypes.string.required
};
export default TodoItem;
到目前为止,我已尝试过以下方法:
使用expect进行纯快照测试(component.toJSON())。toMatchSnapshot() - 在API调用后不显示结果
jest.spyON ...调用该方法,但之后toMatchSnapshot仍显示第一个没有数据的快照
return promise()。then(...仍然没有结果
任何帮助?
修改
如果我从componentDidMount中删除API调用并仅使用setState,那么快照测试会显示todos项目(没有第一种情况,它应该说 todos正在被提取...... )为什么?不应该是一样的吗?
如果只有承诺是根本原因,我怎么能等待所有承诺完成?
答案 0 :(得分:0)
一种方法是等待最后一个事件(promise),如果要解析队列中的任何事件,然后再进行组件实例更新?
const allOver = () => new Promise((resolve) => setImmediate(resolve));
describe('Todo', () => {
it('calls mock API', async () => {
fetch = jest.fn().mockReturnValue(Promise.resolve(todos));
var component = mount(<Todo timeout={2000} />);
await allOver();
component.update();
expect(toJson(component)).toMatchSnapshot();
});
});