Tests en React: setProps en un elemento que requiere history
Tenemos un componente que requiere history
:
export const RuleImplementationsFromRuleLoader = ({
clearRuleImplementations,
deletionQuery,
fetchRuleImplementations,
ruleImplementationsLoading,
ruleImplementations,
}) => {
const history = useHistory();
useEffect(() => {
if (id) {
fetchRuleImplementations({ id, deleted: deletionQuery.deleted });
}
}, [clearRuleImplementations, deletionQuery, fetchRuleImplementations, id]);
useEffect(() => {
return history.listen((location) => {
const value = [RULE, RULE_IMPLEMENTATIONS, RULE_EVENTS].some(
(tabRoute) => (
return matchPath(location.pathname, tabRoute)?.isExact
)
)
value || clearRuleImplementations();
});
}, [clearRuleImplementations, history]);
return ruleImplementationsLoading ? (
<Dimmer active={ruleImplementationsLoading} inverted>
<Loader size="massive" inverted />
</Dimmer>
) : null;
};
Si intentamos hacer un test así:
it("calls fetchRuleImplementations when component updates", () => {
const history = createMemoryHistory();
const existingProps = ...
const wrapper = mount(
<Router history={history}>
<RuleImplementationsFromRuleLoader {...existingProps} />
</Router>
);
expect(fetchRuleImplementations).toHaveBeenCalledTimes(1);
wrapper.setProps({ deletionQuery: { deleted: true } });
expect(fetchRuleImplementations).toHaveBeenCalledTimes(2);
expect(fetchRuleImplementations).toHaveBeenCalledWith({
id: 1,
deleted: true,
});
});
Saltará el error ReactWrapper::setProps() can only be called on the root
(línea wrapper.setProps...
) Para evitarlo, podemos envolver todo en otro componente creado con React.createElement
, que recibe las propiedades y las pasa al componente contenido. Visto en este enlace:
it("calls fetchRuleImplementations when component updates", () => {
const history = createMemoryHistory();
const existingProps = ...
const wrapper = mount(
React.createElement(
(props) => (
<Router history={history}>
<RuleImplementationsFromRuleLoader {...existingProps} />
</Router>
),
props
)
);
expect(fetchRuleImplementations).toHaveBeenCalledTimes(1);
wrapper.setProps({ deletionQuery: { deleted: true } });
expect(fetchRuleImplementations).toHaveBeenCalledTimes(2);
expect(fetchRuleImplementations).toHaveBeenCalledWith({
id: 1,
deleted: true,
});
});