问题
My component looks something like this: (It has more functionality as well as columns, but I have not included that to make the example simpler)
const WeatherReport: FunctionComponent<Props> = ({ cityWeatherCollection, loading, rerender }) => {
/* some use effects skipped */
/* some event handlers skipped */
const columns = React.useMemo(() => [
{
header: 'City',
cell: ({ name, title }: EnhancedCityWeather) => <Link to={`/${name}`} className="city">{title}</Link>
},
{
header: 'Temp',
cell: ({ temperature }: EnhancedCityWeather) => (
<div className="temperature">
<span className="celcius">{`${temperature}°C`}</span>
<span className="fahrenheit">{` (~${Math.round(temperature * (9 / 5)) + 32}°F)`}</span>
</div>
)
},
{
header: '',
cell: ({ isFavorite } : EnhancedCityWeather) => isFavorite && (
<HeartIcon
fill="#6d3fdf"
height={20}
width={20}
/>
),
},
], []);
return (
<Table columns={columns} items={sortedItems} loading={loading} />
);
};
Now, I wrote some tests like this:
jest.mock('../../../components/Table', () => ({
__esModule: true,
default: jest.fn(() => <div data-testid="Table" />),
}));
let cityWeatherCollection: EnhancedCityWeather[];
let loading: boolean;
let rerender: () => {};
beforeEach(() => {
cityWeatherCollection = [/*...some objects...*/];
loading = true;
rerender = jest.fn();
render(
<BrowserRouter>
<WeatherReport
cityWeatherCollection={cityWeatherCollection}
loading={loading}
rerender={rerender}
/>
</BrowserRouter>
);
});
it('renders a Table', () => {
expect(screen.queryByTestId('Table')).toBeInTheDocument();
});
it('passes loading prop to Table', () => {
expect(Table).toHaveBeenCalledWith(
expect.objectContaining({ loading }),
expect.anything(),
);
});
it('passes items prop to Table after sorting by isFavorite and then alphabetically', () => {
expect(Table).toHaveBeenCalledWith(
expect.objectContaining({
items: cityWeatherCollection.sort((item1, item2) => (
+item2.isFavorite - +item1.isFavorite
|| item1.name.localeCompare(item2.name)
)),
}),
expect.anything(),
);
});
If you check my component, it has a variable called columns. I am assigning that variable to Table component.
I think, I should test that columns are being passed as props to the Table component. Am I thinking right? If so, can you please tell me how can I write a test case for that?
Also, it will be helpful if you can suggest me how can i test each cell declared inside columns property.
回答1:
It is not recommended to test implementation details, such as component props, with React Testing Library. Instead you should be asserting on the screen content.
Recommended
expect(await screen.findByText('some city')).toBeInTheDocument();
expect(screen.queryByText('filtered out city')).not.toBeInTheDocument();
Not Recommended
If you want to test props anyways, you can try the sample code below. Source
import Table from './Table'
jest.mock('./Table', () => jest.fn(() => null))
// ... in your test
expect(Table).toHaveBeenCalledWith(props, context)
You might consider this approach mainly on the two following scenarios.
You already tried the recommended approach but you noticed the component is:
- using legacy code and because of that it makes testing very hard. Refactoring the component would also take too long or be too risky.
- is very slow and it drastically increases the testing time. The component is also already tested somewhere else.
have a look at a very similar question here
回答2:
You can use the props()
method, doing something like this:
expect(Table.props().propYouWantToCheck).toBeFalsy();
Just doing your component.props() then the prop you want, you can make any assert with it.
来源:https://stackoverflow.com/questions/64939196/how-can-i-test-if-a-prop-is-passed-to-child