I am new to cypress and testing as such, I want to do e2e user journey for my project. This is an online store with the cart implemented on the backend so when I click on the add to cart button the request is made and until I get the response from the CMS the button is disabled. Response is usually quite fast but when I try to test it it takes long time, sometime it passes when I set wait to 3000 and sometimes it fails on 5000. I have a similar story with login, it passes 90% of a time when I check if a page was redirected properly and sometimes it fails. I have red that it is an anti pattern to do conditionals in tests so how can Imtest if a respose came back and only then proceed with the rest of the test? here is my test:
describe("Logged in user journey", () => {
it("customer is able to do the full journey from login to purchase", () => {
context("User logs in to make a puchase", () => {
cy.visit("/auth/login");
cy.getByData("email").type(Cypress.env("login"));
cy.getByData("password").type(Cypress.env("password"));
cy.get("form").find("button").click();
cy.location().should((loc) => {
expect(loc.pathname).to.eq("/auth/dashboard");
});
cy.get("section").should("contain.text", Cypress.env("login"));
});
context("user adds two items of this same type", () => {
cy.visit("/products");
cy.getByData("add-to-cart-button").first().click();
cy.getByData("cart-icon").first().should("contain.text", "1");
cy.wait(3000).then(() => {
cy.getByData("add-to-cart-button").first().click();
cy.visit("/cart");
cy.getByData("cart-item-quantity").should("contain.text", "2");
});
});
});
});
and this is the handler
const addItemToCart = (newItem: CartItem) => {
setClickedItemSlug(newItem.product.slug);
upsertOrderMutation({
variables: {
id: {
id: cartIdFromStorage,
},
data: {
create: createOrderInput(newItem),
update: updateOrderInput(cartItems, newItem),
},
},
})
.then(({ data }) => {
const newCartId = data?.upsertOrder?.id;
const newCartTotal = data?.upsertOrder?.total;
if (!cartIdFromStorage && newCartId) {
setCartIdInStorage(newCartId);
}
setClickedItemSlug("");
if (!newCartTotal) return;
setCartTotal(newCartTotal);
const upsertedOrderItem = data?.upsertOrder?.orderItems.find(
(upsertedItem) => upsertedItem?.product?.slug === newItem.product.slug
);
setCartItems((prevCart) => {
const existingItem = prevCart.find(
(cartItem) => cartItem.product.slug === newItem.product.slug
);
if (!existingItem) {
return [
...prevCart,
{ ...newItem, id: upsertedOrderItem?.id || "" },
];
}
return prevCart.map((cartItem) => {
if (cartItem.product.slug === newItem.product.slug) {
return {
...cartItem,
quantity: upsertedOrderItem?.quantity as number,
id: upsertedOrderItem?.id || "",
};
}
return cartItem;
});
});
})
.catch((error) => {
if (error instanceof Error) {
console.log("Error upserting order " + error.message);
}
});
In teh handler there is a state setter
setClickedItemSlug(newItem.product.slug);
and this handler make the button disabled, so perhaps I could wait for a button to be enabled again or the state of setClickedItemSlug would be an empty string, is it possible? And how could I do that?