#reactjs #jestjs #state #enzyme
Вопрос:
Я пытаюсь протестировать свой метод в поставщике контекста. У меня есть одна ветвь в методе, которую нужно охватить, и это то, чем я задыхаюсь. Конкретная ветвь вводится только при выполнении определенного условия: if (offset !== 0 amp;amp; total !== 0 amp;amp; offset >= total)
Смотрите мой компонент класса ниже:
class JourneyProvider extends Component<
{
children: ReactNode;
},
JourneyContextData
> {
constructor(props: { children: ReactNode }) {
super(props);
this.state = {
...defaultValues,
};
}
getContextValue = (): JourneyContextData => {
const { products, total, limit, offset, loading, disabled, setProducts } =
this.state;
return {
products,
total,
limit,
offset,
loading,
disabled,
setProducts,
};
};
setProducts = async (): Promise<void> => {
const { limit, offset, total, products } = this.state;
if (total === 0 || offset < total) {
const gqlRequest = new GQLRequest(query);
this.setLoading(true);
try {
await gqlRequest.post().then(({ products: { edges, totalCount } }) => {
const newOffset = offset limit;
this.setState({
products,
total: totalCount,
offset: newOffset,
});
this.setLoading(false);
// Disable button if there are no more products
if (offset !== 0 amp;amp; total !== 0 amp;amp; offset >= total) {
// never gets in here when testing.
this.setDisabled(true);
}
});
} catch (e) {
this.setLoading(false);
}
}
};
}
Это мой тест:
it("setProducts is successful and disable button", async () => {
const wrapper = shallow(
<JourneyProvider>
<div>test</div>
</JourneyProvider>
) as any;
const result = {
products: {
edges: [
{
node: {
id: "1",
name: "test-name",
},
},
],
totalCount: 1,
},
};
mockedClient.post.mockResolvedValueOnce(result);
jest
.spyOn(ProductsQuery, "getProductsQuery")
.mockResolvedValueOnce(new Query("test", true) as never);
const setLoadingSpy = jest.spyOn(wrapper.instance(), "setLoading");
const setDisabledSpy = jest.spyOn(wrapper.instance(), "setDisabled");
wrapper.state().limit = result.products.totalCount;
console.log(wrapper.state().offset); //this returns 0
await wrapper.instance().setProducts();
console.log(wrapper.state().offset); //this returns 0
expect(setLoadingSpy).toHaveBeenCalledWith(true); // this passes
expect(setLoadingSpy).toHaveBeenCalledWith(false); // this passes
expect(setDisabledSpy).toHaveBeenCalledWith(true); // this fails
});
Комментарии:
1. Попробуйте обернуть все методы, которые обновляют состояния реакции, действием(() => {})>
Ответ №1:
Вам следует изменить логику в коде, в котором вы проводите сравнение, потому что вы используете устаревшее состояние, имейте в виду, что вызов setState
не изменяет состояние немедленно. Сравните новые значения, которые вы установили для состояния, вместо старых значений состояния
if (newOffset !== 0 amp;amp; totalCount !== 0 amp;amp; newOffset >= totalCount) {
или поместите этот код в обратный вызов setState, чтобы гарантировать, что вы используете обновленные значения
...
const newOffset = offset limit;
this.setState({
products,
total: totalCount,
offset: newOffset,
}, () => {
this.setLoading(false);
if (offset !== 0 amp;amp; total !== 0 amp;amp; offset >= total) {
this.setDisabled(true);
}
});
...