我正在使用withRouter并连接到一个无状态的React组件中。我在组件中有一个按钮,用于调用propDispatchToProps提供的props中的方法。
我正在尝试编写一个测试,该测试断言按下按钮会调用history.push()。
到目前为止,我还没有找到一种方法来做到这一点。有些地方说传递这样的模拟历史对象
const historyMock = { push: jest.fn() };
...
<MyComponent history={mockHistory}/>
可以做到,但这不起作用。我认为对withRouter的调用将覆盖它。我还尝试将其放置在提供程序和路由器中。没有工作。
我还尝试过模拟mapDispatchToProps,或者以其他方式在setHistory上设置间谍。这一切似乎都是不可能的。
我还尝试监视MyComponent函数以将道具传递给它-这也是不可能的。
wrapper.setProps()-也不起作用。
我有这些文件。
my.component.container.jsx
import React from 'react';
import { Button } from '@material-ui/core';
const MyComponent = (props) => {
const {setHistory, id} = props;
return (
<React.Fragment>
<Button id="history_button" onClick={() => {
setHistory(id)
}}>View</Button>
</React.Fragment>
)
};
export default MyComponent;
my.component.js
import { connect } from 'react-redux';
import { withRouter } from 'react-router';
import MyComponentContainer from './my.component.container';
export const mapStateToProps = (state) => {
const id = state?.data?.id || null;
return {id};
};
export const mapDispatchToProps = (dispatch, ownProps) => {
return {
setHistory: (id) => {
const {history} = ownProps;
history.push(`/path/${id}`);
},
};
};
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(MyComponentContainer));
my.component.test.js
import React from 'react';
import { BrowserRouter as Router } from "react-router-dom";
import MyComponent from './my.component';
import { Provider } from 'react-redux'
import configureStore from 'redux-mock-store'
import { mount } from 'enzyme';
describe('MyComponent', () => {
afterEach(function() {
jest.clearAllMocks();
jest.restoreAllMocks();
});
const getNode = (wrapper, search) => {
return wrapper.find(search).hostNodes();
};
it('history buttons calls history.push()', () => {
const initialState = {data: {id: 'id-1'}};
const mockStore = configureStore();
const store = mockStore(initialState);
const wrapper = mount(<Provider store={store}><Router><MyComponent/></Router></Provider>);
const button = getNode(wrapper, '#history_button');
button.simulate('click');
// to do - assert that history.push was called with '/path/id-1'
});
});
我将把它作为我不太喜欢的解决方案。我通常希望监视历史对象。
expect(window.history.length).toEqual(1);
expect(window.location.href).toEqual('http://localhost/');
button.simulate('click');
expect(window.history.length).toEqual(2);
expect(window.location.href).toEqual('http://localhost/path/id-1');
答案 0 :(得分:1)
我尝试像您一样将历史记录传递给Router
组件:
<Router history={historyMock}>
我运行测试时说:
console.warn node_modules/tiny-warning/dist/tiny-warning.cjs.js:13
Warning: <BrowserRouter> ignores the history prop. To use a custom history, use `import { Router }` instead of `import { BrowserRouter as Router }`.
一旦按照建议的方式更改了导入,将Router
的模拟历史记录对象传递给工作即可。
my.component.test.js
import React from 'react';
// import { BrowserRouter as Router } from "react-router-dom"; // Warning: <BrowserRouter> ignores the history prop. To use a custom history, use `import { Router }` instead of `import { BrowserRouter as Router }`.
import { Router } from "react-router-dom";
import MyComponent from './my.component';
import { Provider } from 'react-redux'
import configureStore from 'redux-mock-store'
import { mount } from 'enzyme';
describe('MyComponent', () => {
afterEach(function() {
jest.clearAllMocks();
jest.restoreAllMocks();
});
const getNode = (wrapper, search) => {
return wrapper.find(search).hostNodes();
};
it('history buttons calls history.push()', () => {
const initialState = {data: {id: 'id-1'}};
const mockStore = configureStore();
const store = mockStore(initialState);
const historyMock = {
listen: () => {},
location: {
pathname: 'fake-path-name',
},
push: jest.fn(),
};
const wrapper = mount(<Provider store={store}><Router history={historyMock}><MyComponent history={'this is ignored and useless'}/></Router></Provider>);
const button = getNode(wrapper, '#history_button');
button.simulate('click');
expect(historyMock.push).toHaveBeenCalledTimes(1);
expect(historyMock.push).toHaveBeenCalledWith('/path/id-1');
});
});