我正在尝试使用包裹在Router中的useEffect挂钩来测试功能组件。该组件是用TypeScript编写的,但不要分散注意力。
import React, { ReactNode, useEffect, useState, Fragment } from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import { RouterProps } from 'component/hoc/router/Router';
export interface ClassIdChangedProps {
children: ReactNode;
}
const ClassIdChanged = ({
children,
match: {
params: { classId },
},
}: ClassIdChangedProps & RouterProps) => {
const [storedClassId, setStoredClassId] = useState(classId);
useEffect(() => {
if (classId !== storedClassId) {
/** Test should hit this conditional by mocking
* router and grabbing a new classId param
**/
alert('test should hit this');
setStoredClassId(classId);
}
}, [ classId ]);
return (
<Fragment key={classId}>
{ children }
</Fragment>
)
};
export default withRouter<ClassIdChangedProps & RouteComponentProps<any>,
typeof ClassIdChanged>(ClassIdChanged);
该测试应符合上述条件,因此需要更改模拟路由器和classId参数。
import React, { Fragment } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { act } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import { mount } from 'enzyme';
import ClassIdChanged from './ClassIdChanged';
describe('ClassIdChanged', () => {
fit('should rerender children when classId changes on url parameters', () => {
const history = createMemoryHistory();
const spy = jest.fn();
// failed attempt 1 - doesn't hit if block
const wrapper = mount(
<MemoryRouter initialEntries={['/class/1234']} >
<ClassIdChanged>
<Fragment>{spy()}</Fragment>
</ClassIdChanged>
</MemoryRouter>
);
// failed attempt 2 - doesn't hit if block
const wrapper = mount(
<ClassIdChanged>
<Fragment>{spy()}</Fragment>
</ClassIdChanged>, {
wrappingComponent: MemoryRouter,
childContextTypes: { match: { params: { classId: '1234' } } },
});
// failed attempt 3 - doesn't work, doesn't call useEffect,
const wrapper = mount(
<Router>
<ClassIdChanged
match={ { params: { classId: '1234' } } }
>
<div>{ spy() }</div>
</ClassIdChanged>
</Router>
);
// failed attempt 4 - doesn't work, doesn't call useEffect or hit if block
const wrapper = mount(
<MemoryRouter initialEntries={ ['/class/1234'] } >
// @ts-ignore
<ClassIdChanged
match={ { params: { classId: '1234' } } }
>
<div>{ spy() }</div>
</ClassIdChanged>
</MemoryRouter>
);
expect(spy).toHaveBeenCalledTimes(1);
act(() => {
history.push('/class/4321'); // has no effect on any of above route configurations
wrapper.setProps( { match: { params: { classId: '4321' } } } );
expect(spy).toHaveBeenCalledTimes(2);
});
wrapper.unmount();
});
});
我尝试了各种模拟路由器的方法,但是尚不清楚如何在这些不同的尝试中更改路由。
问题归结为以下问题:
主要目标只是在组件代码中达到条件限制。