Commit 713aeda4f2d for woocommerce

commit 713aeda4f2d242452c04c4aa8a5f73bcf044060b
Author: agent-sandbox-woocommerce[bot] <282076412+agent-sandbox-woocommerce[bot]@users.noreply.github.com>
Date:   Fri Oct 23 13:09:25 2026 +0000

    Fix cart-store nonce refresh E2E test timing flake in parallel runs (#70144)

diff --git a/plugins/woocommerce/changelog/fxlt-12-cart-store-nonce-e2e-timing b/plugins/woocommerce/changelog/fxlt-12-cart-store-nonce-e2e-timing
new file mode 100644
index 00000000000..df9de9831b2
--- /dev/null
+++ b/plugins/woocommerce/changelog/fxlt-12-cart-store-nonce-e2e-timing
@@ -0,0 +1,3 @@
+Significance: patch
+Type: dev
+Comment: Make the cart-store nonce refresh E2E test independent of nonce expiry timing; no production change.
diff --git a/plugins/woocommerce/tests/e2e/tests/blocks/cart/cart-store.block_theme.spec.ts b/plugins/woocommerce/tests/e2e/tests/blocks/cart/cart-store.block_theme.spec.ts
index 9f1bc9945f2..e1d3609f682 100644
--- a/plugins/woocommerce/tests/e2e/tests/blocks/cart/cart-store.block_theme.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/blocks/cart/cart-store.block_theme.spec.ts
@@ -1,21 +1,17 @@
 /**
  * External dependencies
  */
+import type { APIResponse, Route } from '@playwright/test';
 import { test, expect, guestFile } from '@woocommerce/e2e-utils';

 /**
  * Internal dependencies
  */
 import { REGULAR_PRICED_PRODUCT_NAME } from '../checkout/constants';
-import { setFilterValue } from '../../../utils/filters';

 test.describe( 'Cart Store', () => {
 	test.use( { storageState: guestFile } );

-	test.beforeEach( async ( { page } ) => {
-		await setFilterValue( page, 'nonce_life', 2 );
-	} );
-
 	test( 'should refresh nonce from Store API and use it for cart mutations', async ( {
 		page,
 		frontendUtils,
@@ -23,13 +19,34 @@ test.describe( 'Cart Store', () => {
 		let refreshNonce: string | null = null;
 		let requestNonce: string | null = null;
 		let responseNonce: string | null = null;
+		let batchCount = 0;
+		// Between the first and second mutation, every response hands the
+		// client a stale nonce, so the second mutation is rejected without
+		// depending on the nonce lifetime.
+		const STALE_NONCE = 'stale-nonce';
+		const fulfillWithNonce = async (
+			route: Route,
+			response: APIResponse
+		) => {
+			await route.fulfill(
+				batchCount === 1
+					? {
+							response,
+							headers: {
+								...response.headers(),
+								nonce: STALE_NONCE,
+							},
+						}
+					: { response }
+			);
+		};

 		// Intercept GET /cart (refreshCartItems) to capture the nonce.
 		await page.route( '**/wc/store/v1/cart**', async ( route ) => {
 			if ( route.request().method() === 'GET' ) {
 				const response = await route.fetch();
-				refreshNonce = response.headers().nonce || null;
-				await route.fulfill( { response } );
+				refreshNonce ??= response.headers().nonce || null;
+				await fulfillWithNonce( route, response );
 			} else {
 				await route.continue();
 			}
@@ -38,10 +55,11 @@ test.describe( 'Cart Store', () => {
 		// Intercept batch requests to track which nonce the client sends
 		// and which nonce the server returns.
 		await page.route( '**/wc/store/v1/batch**', async ( route ) => {
+			batchCount++;
 			requestNonce = route.request().headers().nonce || null;
 			const response = await route.fetch();
 			responseNonce = response.headers().nonce || null;
-			await route.fulfill( { response } );
+			await fulfillWithNonce( route, response );
 		} );

 		await frontendUtils.goToShop();
@@ -54,18 +72,14 @@ test.describe( 'Cart Store', () => {
 		await frontendUtils.addToCart( REGULAR_PRICED_PRODUCT_NAME );
 		expect( requestNonce ).toBe( refreshNonce );

-		// Wait for the nonce to expire.
-		// eslint-disable-next-line playwright/no-wait-for-timeout, no-restricted-syntax
-		await page.waitForTimeout( 2000 );
-
-		// Adding another product should fail because it is using an expired nonce.
+		// Adding another product should fail because it is using a stale nonce.
 		await frontendUtils.addToCart( REGULAR_PRICED_PRODUCT_NAME );
+		expect( requestNonce ).toBe( STALE_NONCE );
 		await expect( page.getByText( 'Nonce is invalid.' ) ).toBeVisible();
 		const previousResponseNonce = responseNonce;

-		// Nonce should be updated now and the request should succeed.
+		// The client should use the nonce from the failed response and succeed.
 		await frontendUtils.addToCart( REGULAR_PRICED_PRODUCT_NAME );
-		expect( requestNonce ).not.toBe( refreshNonce );
 		expect( requestNonce ).toBe( previousResponseNonce );

 		// Verify the product was actually added to the cart properly.