I'm forwarding the code containing the exemplary working steps, finishing with clicking the Add to Basket button.
Steps after that should consider that a cart modal appears, and Cypress should click the Proceed to Checkout button. This is where the issue appears. No matter what I've tried Cypress couldn't find the cart modal on the page. I get various issues like CSS not visible, opacity 0 and so. While manually testing the page, I've noticed that the cart modal disappears pretty fast after clicking on the Add to Basket button so I guess it can be a possible reason why Cypress can't find it.
I have referred to a blog article written by Gleb Bahmutov https://glebbahmutov.com/blog/flaky-iframe-test/, but I couldn't really find the answer there, and I'm not that experienced in test automation, to be honest :)
Cypress.on('uncaught:exception', (err, runnable) => {
// Return false to prevent the test from failing
return false;
});
describe('Iqos Shop Test', () => {
it('Add a product in the basket and proceed to checkout', () => {
// Visit the specified URL
cy.visit('https://www.iqos.com/gb/en/home.html?gr=false');
// Select the month from the dropdown
cy.get('#dropdownMonths')
.parent().click();
cy.get('#sag-month-01').click({ force: true });
// Select the year from the dropdown
cy.get('#dropdownYears')
.parent().click();
cy.get('#sagyear1999').click({ force: true });
// Click the confirm button
cy.get('span.sav-btn-text:contains("Confirm")').click();
// Click on the promotion button on the main banner
cy.get('.btn-white-turquoise').eq(0).click();
// Buy IQOS ILUMA ONE Starter Kit
cy.get('a[href="/gb/en/shop/iqos-iluma-one-starter-kit.html"]')
.should('be.visible')
.eq(0)
.click();
// click on the "Add to cart" button
cy.get('section.product-info__wrapper')
.find('div.product-detail__react--container')
.should('be.visible')
.wait(200)
.within(() => {
cy.contains('button', 'Add to basket').should('be.visible').click({ force: true })
});
});
});
Here, I have copied the Cart modal element:
<div class="minicart__container" id="minicart" aria-label="Minicart" aria-live="polite" aria-relevant="additions removals" tabindex="-1" data-minicart-show-duration="7000" style="top: 139px;"><div class="minicart__list-wrapper"><div class="minicart__actions"><div class="add-to-cart--container"><svg class="message-icon" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><circle cx="16" cy="16" fill="#93b933" r="16"></circle><path d="m8 17.2337322 4.2303003 4.7662678 11.7696997-12" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5"></path></g></svg><span class="add-to-cart">Item added to basket</span></div><button class="btn btn--icon btn-close link-device__header--btn"><svg class="icon-close" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><g fill="none" fill-rule="evenodd" stroke="#545454" stroke-linecap="round" stroke-width="1.5"><path d="M15.485 7L-1.485 7" transform="translate(1 1) rotate(-135 7 7)"></path><path d="M15.485 7L-1.485 7" transform="translate(1 1) rotate(135 7 7)"></path></g></svg></button></div><ul class="minicart__products-list"><li class="minicart__bundle"><div class="product__name">IQOS Iluma One Starter Kit</div><div class="minicart__item"><div class="badge-container"></div><div class="minicart__product"><div class="minicart__product-left"><img class="minicart__product-img" src="/vanity/content/pmisite/gb/en/.rrp.G0000590.00.144x70.jpg/G0000590-2023-11-29T13:52:49.386.jpg" alt="IQOS ILUMA One Kit Pebble Beige 00" title="IQOS ILUMA One Kit Pebble Beige"><div class="minicart__product-info"><a href="/gb/en/shop/iluma-one-kit-pebble-beige.html" class="minicart__product-title"><span>IQOS ILUMA One Kit Pebble Beige</span></a><div class="minicart__product-bottom"><p class="minicart__product-qty"><span class="minicart__qty-label">Quantity</span><span class="minicart__qty-value">1</span></p></div></div></div><div class="minicart__product-right"><div class="minicart__product-price"><span class="minicart__discount-value">£29.00</span><span class="minicart__price-value">£17.00</span></div></div></div></div><div class="minicart__item"><div class="badge-container"></div><div class="minicart__product"><div class="minicart__product-left"><img class="minicart__product-img" src="/vanity/content/pmisite/gb/en/.rrp.G0000692.00.144x70.jpg/G0000692-2023-11-29T13:52:49.386.jpg" alt="TEREA AMBER PACK 00" title="TEREA AMBER PACK"><div class="minicart__product-info"><a href="/gb/en/shop/terea-amber-pack.html" class="minicart__product-title"><span>TEREA AMBER PACK</span></a><div class="minicart__product-bottom"><p class="minicart__product-qty"><span class="minicart__qty-label">Quantity</span><span class="minicart__qty-value">2</span></p></div></div></div><div class="minicart__product-right"><div class="minicart__product-price"><span class="minicart__price-value">£12.00</span></div></div></div></div></li></ul></div><div class="minicart__order-summary"><div class="minicart__buttons other"><a class="minicart__one-click global-btn btn--dark" href="#"><span data-pmi-el="minicart-proceed-to-checkout" class="minicart__btn-label btn__label">Proceed to checkout</span></a><a href="#" class="minicart__view-basket global-btn btn--light"><span data-pmi-el="minicart-view-basket-button" class="minicart__btn-label btn__label">View cart</span><span class="minicart__btn-label btn__label minicart-item__number"> (3)</span></a></div><div class="minicart__info"></div></div></div>
I had a go at this, I think the main problem is the modal is slow to come into full visibility.
It looks like the following things are blocking
one or two API calls are made after the product is added to the cart and the page waits for the response before the modal is shown.
there is some animation attached to the modal, indicated by opacity: 0
, which is the start of the animation, which then gets increased to opacity: 1
for a fade-in effect.
the parent #nbw__header--desktop
has display: none
which is changed after the API call response arrives
Essentially, I added 30 seconds timeout to the modal query, and this seems to fairly consistently pass the test.
In the example below, I moved the visit and age-consent into a beforeEach
to show a more concise log.
Also added cy.intercept({ resourceType: /xhr|fetch/ }, { log: false })
to remove the noisy XHR logs.
Then I bumped up the viewport to reduce issue of elements being invisible because they are off-screen.
Some other elements I changed to search by text, since the class-based selectors aren't the best, as the color themes may be changed.
beforeEach(() => {
cy.intercept({ resourceType: /xhr|fetch/ }, { log: false })
cy.viewport(2000, 2000)
cy.visit('https://www.iqos.com/gb/en/home.html?gr=false');
cy.get('#dropdownMonths').click();
cy.contains('January').click()
cy.get('#dropdownYears').click();
cy.contains('1999').click()
cy.contains('span.sav-btn-text', 'Confirm').click();
cy.contains('Buy from £29', {timeout:10_000}).click() // Click on the promotion button
})
it('Add a product in the basket and proceed to checkout', () => {
cy.get('a[href="/gb/en/shop/iqos-iluma-one-starter-kit.html"]').eq(0).click();
cy.get('#onetrust-reject-all-handler').click() // get rid of cookies popup
cy.get('section.product-info__wrapper')
.find('div.product-detail__react--container')
.should('be.visible')
cy.contains('button', 'Add to basket').should('be.visible').click()
cy.get('#minicart', {timeout:30_000}).should('be.visible')
cy.contains('Proceed to checkout').click()
// confirm checkout is visible
cy.contains('Welcome to secure checkout', {timeout:10_000}).should('be.visible')
})
You could also look into intercepting and waiting on the API calls as an alternative to adding a long timeout.