Skip to content

Stop waiting on the one-shot added-to-cart notice - #67

Merged
edpittol merged 1 commit into
mainfrom
66-addproducttocart-drop-one-shot-notice-wait
Sep 2, 2026
Merged

Stop waiting on the one-shot added-to-cart notice#67
edpittol merged 1 commit into
mainfrom
66-addproducttocart-drop-one-shot-notice-wait

Conversation

@fafera

@fafera fafera commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Closes #66.

Problem

CartMethods::addProductToCart() waited for WooCommerce's "product added to cart" notice. That notice is a one-shot session notice: it lives in wc_notices, is rendered once, and is cleared on print. Anything that rewrites the WooCommerce session between the add-to-cart request and the render — an async loopback, a persistent object cache, a plugin touching the session — destroys the wait target while the add itself succeeds, because the cart is restored from the persistent-cart user meta and notices have no such fallback. Result: intermittent TimeoutException, a different test or two per run, always green when re-run in isolation. Full diagnosis and field evidence in #66.

Change

The wait is removed rather than retargeted:

public function addProductToCart(int $productId, int $quantity = 1): void
{
    $this->wpWebDriver()->amOnPage("/?add-to-cart=$productId&quantity=$quantity");
}

There is nothing left to synchronize. amOnPage() returns only once the add-to-cart request has been served, so the cart is already populated when the method returns — the wait was never synchronization, it was an implicit assertion.

PRODUCT_ADDED_TO_CART_MESSAGE_SELECTOR loses its only consumer and is removed from CartPageObject.

Why not wait on the cart item instead

That was the fix suggested in the issue, and it needs the cart page: CART_ITEM_SELECTOR is rendered nowhere else. Reaching it means either navigating on every add, or branching on whether the store already redirected there. Neither earns its cost:

  • 19 of this package's own call sites go straight to amOnCheckoutPage() and never look at the cart. Both options spend a page load on a page the test abandons on the next line.
  • The branch would compare the current URL against cartPageSlug, which promotes that config value from "only matters if you call amOnCartPage()" to "breaks every add when wrong" — and it degrades silently in subdirectory installs, where the paths never match.
  • The wait would not be product-specific either: CART_ITEM_SELECTOR only proves the cart is non-empty, so on a second consecutive add it passes on the first item's markup and proves nothing.

Keeping the method to the add alone leaves it agnostic to the store's "Add to cart behaviour" setting and to the woocommerce_add_to_cart_redirect filter, and keeps the browser layer free of store shape (ADR-0008).

Trade-off

A failed add (out of stock, invalid product) now surfaces at the next see* rather than inside addProductToCart(). No DOM element is reliably present on every landing page a store can choose, which is exactly why the fragile notice was picked originally. Tests that want the guarantee assert it explicitly — amOnCartPage() then seeCartTotalQuantity() — which is a stronger check than the generic wait ever was.

Consumer impact

Tests that assert on cart contents must navigate first. This is what the suites already do; the package's own Cests are unchanged by this PR.

Verification

  • composer check — composer validate, PHPStan level max over src and tests, PHPCS: clean.
  • codecept run unit — 60/60.
  • codecept run acceptance198 tests, 427 assertions, no failures.

Ran against a locally built runner image; the pre-push hook was bypassed because ghcr.io/aztecweb/aztecweb-wp-browser-runner requires authentication in this environment, so the suites above were run by hand instead. Unrelated, but noticed while doing it: the hook's file-to-Cest map still uses pre-namespace paths (src/Method/CartMethods.php), so no changed source file maps to a Cest any more and it silently falls through to bootstrap only.

addProductToCart waited for WooCommerce's "product added to cart" notice,
a one-shot session notice: it is cleared on print and is lost whenever
anything rewrites the WooCommerce session between the add-to-cart request
and the render — an async loopback, a persistent object cache, a plugin
touching the session. The wait then timed out on runs where the product
had in fact been added, one or two different tests per run, always green
when re-run in isolation.

The wait is now gone rather than retargeted. There is nothing left to
synchronize: amOnPage returns only once the add-to-cart request has been
served, so the cart is already populated when the method returns. The
notice was picked in the first place because it is the only element
guaranteed to exist on every page a store can land on after an add — cart
state is only rendered on the cart page, and reaching it would mean either
navigating on every add or branching on the store's configuration. Neither
is warranted: 19 of the package's own call sites go straight to the
checkout page and never look at the cart, so both options spend a page
load, and the branch would additionally turn cartPageSlug into a value
that breaks every add when it is wrong.

The method is therefore agnostic again to the "Add to cart behaviour"
setting and to the woocommerce_add_to_cart_redirect filter, and tests
navigate explicitly before asserting on cart contents, as they already
did. PRODUCT_ADDED_TO_CART_MESSAGE_SELECTOR loses its only consumer and
is removed from the cart page object.
@edpittol
edpittol self-requested a review September 2, 2026 17:56
@edpittol
edpittol merged commit 5d7bb48 into main Sep 2, 2026
3 checks passed
@edpittol
edpittol deleted the 66-addproducttocart-drop-one-shot-notice-wait branch September 2, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

addProductToCart waits on a one-shot session notice, causing flaky timeouts

2 participants