Commit fda344a4c22 for woocommerce

commit fda344a4c22877c1b5f53a4a1fae21cb95d04a13
Author: Adrian Moldovan <3854374+adimoldovan@users.noreply.github.com>
Date:   Mon Jun 22 12:26:15 2026 +0300

    e2e-tests: move coupon discount arithmetic from E2E to PHPUnit and downsize coupons e2e tests (#65873)

    testops: move coupon discount arithmetic from E2E to PHPUnit

    Coupon type (fixed_cart / percent / fixed_product), duplicate-application
    rejection, and removal-restores-total are now asserted in fast PHPUnit
    tests. The E2E suites are trimmed to a single wiring smoke-test each:
    apply a coupon, assert the success notice and a discount line render.

diff --git a/plugins/woocommerce/changelog/testops-181-coupon-e2e-downgrade-move-discount-arithmetic-to-phpunit b/plugins/woocommerce/changelog/testops-181-coupon-e2e-downgrade-move-discount-arithmetic-to-phpunit
new file mode 100644
index 00000000000..02f60a80404
--- /dev/null
+++ b/plugins/woocommerce/changelog/testops-181-coupon-e2e-downgrade-move-discount-arithmetic-to-phpunit
@@ -0,0 +1,3 @@
+Significance: patch
+Type: dev
+Comment: Move coupon discount-arithmetic coverage from e2e to PHPUnit; reduce coupon cart e2e to a single wiring smoke.
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/coupons/cart-block-coupons.spec.ts b/plugins/woocommerce/tests/e2e-pw/tests/coupons/cart-block-coupons.spec.ts
index 81893ec8295..81a1c2f7602 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/coupons/cart-block-coupons.spec.ts
+++ b/plugins/woocommerce/tests/e2e-pw/tests/coupons/cart-block-coupons.spec.ts
@@ -12,31 +12,20 @@ import {
 import { expect, tags, test as baseTest } from '../../fixtures/fixtures';

 const simpleProductName = 'Cart Coupons Product';
-const singleProductFullPrice = '110.00';
-const singleProductSalePrice = '55.00';
-const coupons = [
-	{
-		code: '5fixedcart',
-		discount_type: 'fixed_cart',
-		amount: '5.00',
-	},
-	{
-		code: '50percoff',
-		discount_type: 'percent',
-		amount: '50',
-	},
-	{
-		code: '10fixedproduct',
-		discount_type: 'fixed_product',
-		amount: '10.00',
-	},
-];
+const coupon = {
+	code: '5fixedcart',
+	discount_type: 'fixed_cart',
+	amount: '5.00',
+};
 const couponLimitedCode = '10fixedcartlimited';
 const customerBilling = {
 	email: 'john.doe.merchant.test@example.com',
 };

-let productId: number, orderId: number, limitedCouponId: number;
+let productId: number,
+	orderId: number,
+	couponId: number,
+	limitedCouponId: number;

 const test = baseTest.extend( {
 	page: async ( { page }, use ) => {
@@ -50,8 +39,6 @@ test.describe(
 	'Cart Block Applying Coupons',
 	{ tag: [ tags.PAYMENTS, tags.SERVICES ] },
 	() => {
-		const couponBatchId: number[] = [];
-
 		test.beforeAll( async ( { restApi } ) => {
 			// make sure the currency is USD
 			await restApi.put(
@@ -65,21 +52,16 @@ test.describe(
 				.post( `${ WC_API_PATH }/products`, {
 					name: simpleProductName,
 					type: 'simple',
-					regular_price: singleProductFullPrice,
-					sale_price: singleProductSalePrice,
+					regular_price: '110.00',
 				} )
 				.then( ( response: { data: { id: number } } ) => {
 					productId = response.data.id;
 				} );
-			// add coupons
+			// add coupon
 			await restApi
-				.post( `${ WC_API_PATH }/coupons/batch`, {
-					create: coupons,
-				} )
-				.then( ( response: { data: { create: { id: number }[] } } ) => {
-					for ( let i = 0; i < response.data.create.length; i++ ) {
-						couponBatchId.push( response.data.create[ i ].id );
-					}
+				.post( `${ WC_API_PATH }/coupons`, coupon )
+				.then( ( response: { data: { id: number } } ) => {
+					couponId = response.data.id;
 				} );
 			// add limited coupon
 			await restApi
@@ -114,157 +96,38 @@ test.describe(
 				delete: [ productId ],
 			} );
 			await restApi.post( `${ WC_API_PATH }/coupons/batch`, {
-				delete: [ ...couponBatchId, limitedCouponId ],
+				delete: [ couponId, limitedCouponId ],
 			} );
 			await restApi.post( `${ WC_API_PATH }/orders/batch`, {
 				delete: [ orderId ],
 			} );
 		} );

-		test(
-			'allows cart block to apply coupon of any type',
-			{ tag: [ tags.COULD_BE_LOWER_LEVEL_TEST ] },
-			async ( { page } ) => {
-				const totals = [ '$50.00', '$27.50', '$45.00' ];
-
-				// apply all coupon types
-				for ( let i = 0; i < coupons.length; i++ ) {
-					await page
-						.getByRole( 'button', { name: 'Add coupons' } )
-						.click();
-					await page
-						.getByLabel( 'Enter code' )
-						.fill( coupons[ i ].code );
-					await page.getByText( 'Apply', { exact: true } ).click();
-					await expect(
-						page
-							.locator(
-								'.wc-block-components-notice-banner__content'
-							)
-							.getByText(
-								`Coupon code "${ coupons[ i ].code }" has been applied to your cart.`
-							)
-					).toBeVisible();
-					await expect(
-						page.locator(
-							'.wc-block-components-totals-footer-item > .wc-block-components-totals-item__value'
-						)
-					).toHaveText( totals[ i ] );
-					await page
-						.getByLabel( `Remove coupon "${ coupons[ i ].code }"` )
-						.click();
-					await expect(
-						page
-							.locator(
-								'.wc-block-components-notice-banner__content'
-							)
-							.getByText(
-								`Coupon code "${ coupons[ i ].code }" has been removed from your cart.`
-							)
-					).toBeVisible();
-				}
-			}
-		);
-
-		test(
-			'allows cart block to apply multiple coupons',
-			{ tag: [ tags.COULD_BE_LOWER_LEVEL_TEST ] },
-			async ( { page } ) => {
-				const totals = [ '$50.00', '$22.50', '$12.50' ];
-				const totalsReverse = [ '$17.50', '$45.00', '$55.00' ];
-				const discounts = [ '-$5.00', '-$32.50', '-$42.50' ];
-
-				// add all coupons and verify prices
-				for ( let i = 0; i < coupons.length; i++ ) {
-					await page
-						.getByRole( 'button', { name: 'Add coupons' } )
-						.click();
-					await page
-						.getByLabel( 'Enter code' )
-						.fill( coupons[ i ].code );
-					await page.getByText( 'Apply', { exact: true } ).click();
-					await expect(
-						page
-							.locator(
-								'.wc-block-components-notice-banner__content'
-							)
-							.getByText(
-								`Coupon code "${ coupons[ i ].code }" has been applied to your cart.`
-							)
-					).toBeVisible();
-					await expect(
-						page.locator(
-							'.wc-block-components-totals-discount > .wc-block-components-totals-item__value'
-						)
-					).toHaveText( discounts[ i ] );
-					await expect(
-						page.locator(
-							'.wc-block-components-totals-footer-item > .wc-block-components-totals-item__value'
-						)
-					).toHaveText( totals[ i ] );
-				}
-
-				for ( let i = 0; i < coupons.length; i++ ) {
-					await page
-						.getByLabel( `Remove coupon "${ coupons[ i ].code }"` )
-						.click();
-					await expect(
-						page
-							.locator(
-								'.wc-block-components-notice-banner__content'
-							)
-							.getByText(
-								`Coupon code "${ coupons[ i ].code }" has been removed from your cart.`
-							)
-					).toBeVisible();
-					await expect(
-						page.locator(
-							'.wc-block-components-totals-footer-item > .wc-block-components-totals-item__value'
-						)
-					).toHaveText( totalsReverse[ i ] );
-				}
-			}
-		);
+		test( 'applies a coupon via the cart block form', async ( {
+			page,
+		} ) => {
+			await page.getByRole( 'button', { name: 'Add coupons' } ).click();
+			await page.getByLabel( 'Enter code' ).fill( coupon.code );
+			await page.getByText( 'Apply', { exact: true } ).click();

-		test(
-			'prevents cart block applying same coupon twice',
-			{ tag: [ tags.COULD_BE_LOWER_LEVEL_TEST ] },
-			async ( { page } ) => {
-				// try to add two same coupons and verify the error message
-				await page
-					.getByRole( 'button', { name: 'Add coupons' } )
-					.click();
-				await page.getByLabel( 'Enter code' ).fill( coupons[ 0 ].code );
-				await page.getByText( 'Apply', { exact: true } ).click();
-				await expect(
-					page
-						.locator(
-							'.wc-block-components-notice-banner__content'
-						)
-						.getByText(
-							`Coupon code "${ coupons[ 0 ].code }" has been applied to your cart.`
-						)
-				).toBeVisible();
-				await page
-					.getByRole( 'button', { name: 'Add coupons' } )
-					.click();
-				await page.getByLabel( 'Enter code' ).fill( coupons[ 0 ].code );
-				await page.getByText( 'Apply', { exact: true } ).click();
-				await expect(
-					page
-						.getByRole( 'alert' )
-						.getByText(
-							`Coupon code "${ coupons[ 0 ].code }" has already been applied.`
-						)
-				).toBeVisible();
-			}
-		);
+			// The block form is wired end-to-end: success notice renders...
+			await expect(
+				page
+					.locator( '.wc-block-components-notice-banner__content' )
+					.getByText(
+						`Coupon code "${ coupon.code }" has been applied to your cart.`
+					)
+			).toBeVisible();
+			// ...and a discount line appears. Value is asserted in PHPUnit, not here.
+			await expect(
+				page.locator( '.wc-block-components-totals-discount' )
+			).toBeVisible();
+		} );

 		test(
 			'prevents cart block applying coupon with usage limit',
 			{ tag: [ tags.COULD_BE_LOWER_LEVEL_TEST ] },
 			async ( { page } ) => {
-				// add coupon with usage limit
 				await page
 					.getByRole( 'button', { name: 'Add coupons' } )
 					.click();
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/coupons/cart-checkout-coupons.spec.ts b/plugins/woocommerce/tests/e2e-pw/tests/coupons/cart-checkout-coupons.spec.ts
index 8b52ade7b93..cf39fd6ddcb 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/coupons/cart-checkout-coupons.spec.ts
+++ b/plugins/woocommerce/tests/e2e-pw/tests/coupons/cart-checkout-coupons.spec.ts
@@ -10,62 +10,38 @@ import {
  * Internal dependencies
  */
 import { tags, test, expect } from '../../fixtures/fixtures';
-import {
-	createClassicCartPage,
-	createClassicCheckoutPage,
-	CLASSIC_CART_PAGE,
-	CLASSIC_CHECKOUT_PAGE,
-} from '../../utils/pages';
+import { createClassicCartPage, CLASSIC_CART_PAGE } from '../../utils/pages';
 import { updateIfNeeded } from '../../utils/settings';

 const firstProductName = 'Coupon test product';
-const coupons = [
-	{
-		code: 'fixed-cart-off',
-		discount_type: 'fixed_cart',
-		amount: '5.00',
-	},
-	{
-		code: 'percent-off',
-		discount_type: 'percent',
-		amount: '50',
-	},
-	{
-		code: 'fixed-product-off',
-		discount_type: 'fixed_product',
-		amount: '7.00',
-	},
-];
-
-const discounts = [ '$5.00', '$10.00', '$7.00' ];
-const totals = [ '$15.00', '$10.00', '$13.00' ];
+const coupon = {
+	code: 'fixed-cart-off',
+	discount_type: 'fixed_cart',
+	amount: '5.00',
+};

 test.describe(
-	'Cart & Checkout applying coupons',
+	'Cart applying coupons',
 	{ tag: [ tags.PAYMENTS, tags.SERVICES, tags.HPOS ] },
 	() => {
 		let firstProductId: number;
-		const couponBatchId: number[] = [];
+		let couponId: number;

 		test.beforeAll( async ( { restApi } ) => {
-			// Make sure the classic cart and checkout pages exist
+			// Make sure the classic cart page exists.
 			await createClassicCartPage();
-			await createClassicCheckoutPage();

 			await updateIfNeeded( 'general/woocommerce_calc_taxes', 'no' );

-			// make sure the currency is USD
+			// Make sure the currency is USD.
 			await restApi.put(
 				`${ WC_API_PATH }/settings/general/woocommerce_currency`,
 				{
 					value: 'USD',
 				}
 			);
-			// enable COD
-			await restApi.put( `${ WC_API_PATH }/payment_gateways/cod`, {
-				enabled: true,
-			} );
-			// add product
+
+			// Add product.
 			await restApi
 				.post( `${ WC_API_PATH }/products`, {
 					name: firstProductName,
@@ -75,20 +51,17 @@ test.describe(
 				.then( ( response: { data: { id: number } } ) => {
 					firstProductId = response.data.id;
 				} );
-			// add coupons
+
+			// Add coupon.
 			await restApi
-				.post( `${ WC_API_PATH }/coupons/batch`, {
-					create: coupons,
-				} )
-				.then( ( response: { data: { create: { id: number }[] } } ) => {
-					for ( let i = 0; i < response.data.create.length; i++ ) {
-						couponBatchId.push( response.data.create[ i ].id );
-					}
+				.post( `${ WC_API_PATH }/coupons`, coupon )
+				.then( ( response: { data: { id: number } } ) => {
+					couponId = response.data.id;
 				} );
 		} );

 		test.beforeEach( async ( { context } ) => {
-			// Shopping cart is very sensitive to cookies, so be explicit
+			// Shopping cart is very sensitive to cookies, so be explicit.
 			await context.clearCookies();
 		} );

@@ -99,360 +72,36 @@ test.describe(
 					force: true,
 				}
 			);
-			await restApi.post( `${ WC_API_PATH }/coupons/batch`, {
-				delete: [ ...couponBatchId ],
-			} );
-			await restApi.put( `${ WC_API_PATH }/payment_gateways/cod`, {
-				enabled: false,
+			await restApi.delete( `${ WC_API_PATH }/coupons/${ couponId }`, {
+				force: true,
 			} );
 		} );

-		for ( let i = 0; i < coupons.length; i++ ) {
-			test(
-				`allows applying coupon of type ${ coupons[ i ].discount_type }`,
-				{ tag: [ tags.COULD_BE_LOWER_LEVEL_TEST ] },
-				async ( { page, context } ) => {
-					await test.step( 'Load cart page and apply coupons', async () => {
-						await addAProductToCart( page, firstProductId );
-
-						await page.goto( CLASSIC_CART_PAGE.slug );
-						await page
-							.locator( '#coupon_code' )
-							.fill( coupons[ i ].code );
-						await page
-							.locator( '.blockOverlay' )
-							.first()
-							.waitFor( { state: 'hidden' } );
-						await page
-							.getByRole( 'button', { name: 'Apply coupon' } )
-							.click();
-
-						await expect(
-							page.getByText(
-								'Coupon code applied successfully.'
-							)
-						).toBeVisible();
-						// Checks the coupon amount is credited properly
-						await expect(
-							page
-								.locator( '.cart-discount .amount' )
-								.filter( { hasText: discounts[ i ] } )
-						).toBeVisible();
-						// Checks that the cart total is updated
-						await expect(
-							page
-								.locator( '.order-total .amount' )
-								.filter( { hasText: totals[ i ] } )
-						).toBeVisible();
-					} );
-
-					await context.clearCookies();
-
-					await test.step( 'Load checkout page and apply coupons', async () => {
-						await addAProductToCart( page, firstProductId );
-
-						await page.goto( CLASSIC_CHECKOUT_PAGE.slug );
-						await page
-							.locator( 'text=Click here to enter your code' )
-							.click();
-						await page
-							.locator( '#coupon_code' )
-							.fill( coupons[ i ].code );
-						await page
-							.locator( '.blockOverlay' )
-							.first()
-							.waitFor( { state: 'hidden' } );
-						await page.locator( 'text=Apply coupon' ).click();
-
-						await expect(
-							page.getByText(
-								'Coupon code applied successfully.'
-							)
-						).toBeVisible();
-						await expect(
-							page
-								.locator( '.cart-discount .amount' )
-								.filter( { hasText: discounts[ i ] } )
-						).toBeVisible();
-						await expect(
-							page
-								.locator( '.order-total .amount' )
-								.filter( { hasText: totals[ i ] } )
-						).toBeVisible();
-					} );
-				}
-			);
-		}
-
-		test(
-			'prevents applying same coupon twice',
-			{ tag: [ tags.COULD_BE_LOWER_LEVEL_TEST ] },
-			async ( { page, context } ) => {
-				await test.step( 'Load cart page and try applying same coupon twice', async () => {
-					await addAProductToCart( page, firstProductId );
-
-					await page.goto( CLASSIC_CART_PAGE.slug );
-					await page
-						.locator( '#coupon_code' )
-						.fill( coupons[ 0 ].code );
-					await page
-						.getByRole( 'button', { name: 'Apply coupon' } )
-						.click();
-					// successful first time
-					await expect(
-						page.getByText( 'Coupon code applied successfully.' )
-					).toBeVisible();
-
-					// try to apply the same coupon
-					await page.goto( CLASSIC_CART_PAGE.slug );
-					await page
-						.locator( '#coupon_code' )
-						.fill( coupons[ 0 ].code );
-					await page
-						.getByRole( 'button', { name: 'Apply coupon' } )
-						.click();
-
-					// error received
-					await expect(
-						page.getByText(
-							`Coupon code "${ coupons[ 0 ].code }" already applied!`
-						)
-					).toBeVisible();
-					// check cart total
-					await expect(
-						page
-							.locator( '.cart-discount .amount' )
-							.filter( { hasText: discounts[ 0 ] } )
-					).toBeVisible();
-					await expect(
-						page
-							.locator( '.order-total .amount' )
-							.filter( { hasText: totals[ 0 ] } )
-					).toBeVisible();
-				} );
-
-				await context.clearCookies();
-
-				await test.step( 'Load checkout page and try applying same coupon twice', async () => {
-					await addAProductToCart( page, firstProductId );
-
-					await page.goto( CLASSIC_CHECKOUT_PAGE.slug );
-					await page
-						.locator( 'text=Click here to enter your code' )
-						.click();
-					await page
-						.locator( '#coupon_code' )
-						.fill( coupons[ 0 ].code );
-					await page.locator( 'text=Apply coupon' ).click();
-					// successful first time
-					await expect(
-						page.getByText( 'Coupon code applied successfully.' )
-					).toBeVisible();
-					// try to apply the same coupon
-					await page
-						.locator( 'text=Click here to enter your code' )
-						.click();
-					await page
-						.locator( '#coupon_code' )
-						.fill( coupons[ 0 ].code );
-					await page.locator( 'text=Apply coupon' ).click();
-					// error received
-					await expect(
-						page.getByText(
-							`Coupon code "${ coupons[ 0 ].code }" already applied!`
-						)
-					).toBeVisible();
-					// check cart total
-					await expect(
-						page
-							.locator( '.cart-discount .amount' )
-							.filter( { hasText: discounts[ 0 ] } )
-					).toBeVisible();
-					await expect(
-						page
-							.locator( '.order-total .amount' )
-							.filter( { hasText: totals[ 0 ] } )
-					).toBeVisible();
-				} );
-			}
-		);
-
-		test(
-			'allows applying multiple coupons',
-			{ tag: [ tags.COULD_BE_LOWER_LEVEL_TEST ] },
-			async ( { page, context } ) => {
-				await test.step( 'Load cart page and try applying multiple coupons', async () => {
-					await addAProductToCart( page, firstProductId );
-
-					await page.goto( CLASSIC_CHECKOUT_PAGE.slug );
-					await page
-						.locator( 'text=Click here to enter your code' )
-						.click();
-					await page
-						.locator( '#coupon_code' )
-						.fill( coupons[ 0 ].code );
-					await page
-						.getByRole( 'button', { name: 'Apply coupon' } )
-						.click();
-					// successful
-					await expect(
-						page.getByText( 'Coupon code applied successfully.' )
-					).toBeVisible();
-
-					await page
-						.locator( 'text=Click here to enter your code' )
-						.click();
-					await page
-						.locator( '#coupon_code' )
-						.fill( coupons[ 2 ].code );
-					await page
-						.getByRole( 'button', { name: 'Apply coupon' } )
-						.click();
-					// successful
-					await expect(
-						page.getByText( 'Coupon code applied successfully.' )
-					).toBeVisible();
-					// check cart total
-					await expect(
-						page
-							.locator( '.cart-discount .amount >> nth=0' )
-							.filter( { hasText: discounts[ 0 ] } )
-					).toBeVisible();
-					await expect(
-						page
-							.locator( '.cart-discount .amount >> nth=1' )
-							.filter( { hasText: discounts[ 2 ] } )
-					).toBeVisible();
-					await expect(
-						page
-							.locator( '.order-total .amount' )
-							.filter( { hasText: '$8.00' } )
-					).toBeVisible();
-				} );
-
-				await context.clearCookies();
-
-				await test.step( 'Load checkout page and try applying multiple coupons', async () => {
-					await addAProductToCart( page, firstProductId );
-
-					await page.goto( CLASSIC_CHECKOUT_PAGE.slug );
-					await page
-						.locator( 'text=Click here to enter your code' )
-						.click();
-					await page
-						.locator( '#coupon_code' )
-						.fill( coupons[ 0 ].code );
-					await page.locator( 'text=Apply coupon' ).click();
-					// successful
-					await expect(
-						page.getByText( 'Coupon code applied successfully.' )
-					).toBeVisible();
-
-					await page
-						.locator( 'text=Click here to enter your code' )
-						.click();
-					await page
-						.locator( '#coupon_code' )
-						.fill( coupons[ 2 ].code );
-					await page.locator( 'text=Apply coupon' ).click();
-					// successful
-					await expect(
-						page.getByText( 'Coupon code applied successfully.' )
-					).toBeVisible();
-					// check cart total
-					await expect(
-						page
-							.locator( '.cart-discount .amount >> nth=0' )
-							.filter( { hasText: discounts[ 0 ] } )
-					).toBeVisible();
-					await expect(
-						page
-							.locator( '.cart-discount .amount >> nth=1' )
-							.filter( { hasText: discounts[ 2 ] } )
-					).toBeVisible();
-					await expect(
-						page
-							.locator( '.order-total .amount' )
-							.filter( { hasText: '$8.00' } )
-					).toBeVisible();
-				} );
-			}
-		);
-
-		test(
-			'restores total when coupons are removed',
-			{ tag: [ tags.COULD_BE_LOWER_LEVEL_TEST ] },
-			async ( { page, context } ) => {
-				await test.step( 'Load cart page and try restoring total when removed coupons', async () => {
-					await addAProductToCart( page, firstProductId );
-
-					await page.goto( CLASSIC_CART_PAGE.slug );
-					await page
-						.locator( '#coupon_code' )
-						.fill( coupons[ 0 ].code );
-					await page
-						.getByRole( 'button', { name: 'Apply coupon' } )
-						.click();
-					await expect(
-						page.getByText( 'Coupon code applied successfully.' )
-					).toBeVisible();
-
-					// confirm numbers
-					await expect(
-						page
-							.locator( '.cart-discount .amount' )
-							.filter( { hasText: discounts[ 0 ] } )
-					).toBeVisible();
-					await expect(
-						page
-							.locator( '.order-total .amount' )
-							.filter( { hasText: totals[ 0 ] } )
-					).toBeVisible();
-
-					await page.locator( 'a.woocommerce-remove-coupon' ).click();
-
-					await expect(
-						page
-							.locator( '.order-total .amount' )
-							.filter( { hasText: '$20.00' } )
-					).toBeVisible();
-				} );
-
-				await context.clearCookies();
-
-				await test.step( 'Load checkout page and try restoring total when removed coupons', async () => {
-					await addAProductToCart( page, firstProductId );
-
-					await page.goto( CLASSIC_CHECKOUT_PAGE.slug );
-					await page
-						.locator( 'text=Click here to enter your code' )
-						.click();
-					await page
-						.locator( '#coupon_code' )
-						.fill( coupons[ 0 ].code );
-					await page.locator( 'text=Apply coupon' ).click();
-
-					// confirm numbers
-					await expect(
-						page
-							.locator( '.cart-discount .amount' )
-							.filter( { hasText: discounts[ 0 ] } )
-					).toBeVisible();
-					await expect(
-						page
-							.locator( '.order-total .amount' )
-							.filter( { hasText: totals[ 0 ] } )
-					).toBeVisible();
-
-					await page.locator( 'a.woocommerce-remove-coupon' ).click();
-
-					await expect(
-						page
-							.locator( '.order-total .amount' )
-							.filter( { hasText: '$20.00' } )
-					).toBeVisible();
-				} );
-			}
-		);
+		test( 'applies a coupon via the classic cart form', async ( {
+			page,
+		} ) => {
+			await addAProductToCart( page, firstProductId );
+
+			await page.goto( CLASSIC_CART_PAGE.slug );
+			await page.locator( '#coupon_code' ).fill( coupon.code );
+			await page
+				.locator( '.blockOverlay' )
+				.first()
+				.waitFor( { state: 'hidden' } );
+			await page.getByRole( 'button', { name: 'Apply coupon' } ).click();
+			await page
+				.locator( '.blockOverlay' )
+				.first()
+				.waitFor( { state: 'hidden' } );
+
+			// The form is wired end-to-end: success notice renders...
+			await expect(
+				page.getByText( 'Coupon code applied successfully.' )
+			).toBeVisible();
+			// ...and a discount line appears. Value is asserted in PHPUnit, not here.
+			await expect(
+				page.locator( '.cart-discount .amount' )
+			).toBeVisible();
+		} );
 	}
 );
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-cart-test.php b/plugins/woocommerce/tests/php/includes/class-wc-cart-test.php
index 8ebb39c1309..d0744ab13e6 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-cart-test.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-cart-test.php
@@ -1416,4 +1416,38 @@ class WC_Cart_Test extends \WC_Unit_Test_Case {
 		$variation->delete( true );
 		$product->delete( true );
 	}
+
+	/**
+	 * Applying the same coupon a second time returns false and leaves the discount total unchanged.
+	 */
+	public function test_apply_same_coupon_twice_returns_false() {
+		update_option( 'woocommerce_calc_taxes', 'no' );
+		WC()->cart->empty_cart();
+
+		$product = WC_Helper_Product::create_simple_product( true, array( 'regular_price' => 20 ) );
+		$coupon  = WC_Helper_Coupon::create_coupon(
+			'dup-coupon',
+			array(
+				'discount_type' => 'fixed_cart',
+				'coupon_amount' => '5',
+			)
+		);
+
+		WC()->cart->add_to_cart( $product->get_id(), 1 );
+
+		$first = WC()->cart->apply_coupon( $coupon->get_code() );
+		WC()->cart->calculate_totals();
+		$discount_after_first = WC()->cart->get_discount_total();
+
+		$second = WC()->cart->apply_coupon( $coupon->get_code() );
+		WC()->cart->calculate_totals();
+
+		$this->assertTrue( $first, 'first application should succeed' );
+		$this->assertFalse( $second, 'second application of same coupon should be rejected' );
+		$this->assertEqualsWithDelta( $discount_after_first, WC()->cart->get_discount_total(), 0.001, 'discount total should be unchanged after rejected re-application' );
+
+		WC()->cart->empty_cart();
+		$product->delete( true );
+		$coupon->delete( true );
+	}
 }
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-cart-totals-test.php b/plugins/woocommerce/tests/php/includes/class-wc-cart-totals-test.php
index 6f95c460bdc..0347b9617a1 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-cart-totals-test.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-cart-totals-test.php
@@ -158,4 +158,124 @@ class WC_Cart_Totals_Tests extends WC_Unit_Test_Case {
 		$this->assertEquals( '36.99', WC()->cart->get_total( 'edit' ) );
 		$this->assertEquals( '6.17', WC()->cart->get_total_tax() );
 	}
+
+	/**
+	 * A fixed_cart $5 coupon on a $20 product yields a $5 discount and $15 total.
+	 */
+	public function test_fixed_cart_coupon_discounts_cart_total() {
+		update_option( 'woocommerce_calc_taxes', 'no' );
+		WC()->cart->empty_cart();
+
+		$product = WC_Helper_Product::create_simple_product( true, array( 'regular_price' => 20 ) );
+		$coupon  = WC_Helper_Coupon::create_coupon(
+			'fixed-cart-off',
+			array(
+				'discount_type' => 'fixed_cart',
+				'coupon_amount' => '5',
+			)
+		);
+
+		WC()->cart->add_to_cart( $product->get_id(), 1 );
+		WC()->cart->apply_coupon( $coupon->get_code() );
+		WC()->cart->calculate_totals();
+
+		$this->assertEqualsWithDelta( 5.0, WC()->cart->get_discount_total(), 0.001, 'fixed_cart $5 should discount $5' );
+		$this->assertEquals( '15.00', wc_format_decimal( WC()->cart->get_total( 'edit' ), 2 ), 'fixed_cart $5 on $20 should total $15' );
+
+		WC()->cart->empty_cart();
+		$product->delete( true );
+		$coupon->delete( true );
+	}
+
+	/**
+	 * A percent 50% coupon on a $20 product yields a $10 discount and $10 total.
+	 */
+	public function test_percent_coupon_discounts_cart_total() {
+		update_option( 'woocommerce_calc_taxes', 'no' );
+		WC()->cart->empty_cart();
+
+		$product = WC_Helper_Product::create_simple_product( true, array( 'regular_price' => 20 ) );
+		$coupon  = WC_Helper_Coupon::create_coupon(
+			'percent-off',
+			array(
+				'discount_type' => 'percent',
+				'coupon_amount' => '50',
+			)
+		);
+
+		WC()->cart->add_to_cart( $product->get_id(), 1 );
+		WC()->cart->apply_coupon( $coupon->get_code() );
+		WC()->cart->calculate_totals();
+
+		$this->assertEqualsWithDelta( 10.0, WC()->cart->get_discount_total(), 0.001, 'percent 50% should discount $10' );
+		$this->assertEquals( '10.00', wc_format_decimal( WC()->cart->get_total( 'edit' ), 2 ), 'percent 50% on $20 should total $10' );
+
+		WC()->cart->empty_cart();
+		$product->delete( true );
+		$coupon->delete( true );
+	}
+
+	/**
+	 * A fixed_product $7 coupon on a $20 product yields a $7 discount and $13 total.
+	 */
+	public function test_fixed_product_coupon_discounts_cart_total() {
+		update_option( 'woocommerce_calc_taxes', 'no' );
+		WC()->cart->empty_cart();
+
+		$product = WC_Helper_Product::create_simple_product( true, array( 'regular_price' => 20 ) );
+		$coupon  = WC_Helper_Coupon::create_coupon(
+			'fixed-product-off',
+			array(
+				'discount_type' => 'fixed_product',
+				'coupon_amount' => '7',
+			)
+		);
+
+		WC()->cart->add_to_cart( $product->get_id(), 1 );
+		WC()->cart->apply_coupon( $coupon->get_code() );
+		WC()->cart->calculate_totals();
+
+		$this->assertEqualsWithDelta( 7.0, WC()->cart->get_discount_total(), 0.001, 'fixed_product $7 should discount $7' );
+		$this->assertEquals( '13.00', wc_format_decimal( WC()->cart->get_total( 'edit' ), 2 ), 'fixed_product $7 on $20 should total $13' );
+
+		WC()->cart->empty_cart();
+		$product->delete( true );
+		$coupon->delete( true );
+	}
+
+	/**
+	 * Removing an applied coupon restores the cart to its undiscounted total.
+	 */
+	public function test_cart_total_restored_after_coupon_removed() {
+		update_option( 'woocommerce_calc_taxes', 'no' );
+		WC()->cart->empty_cart();
+
+		$product = WC_Helper_Product::create_simple_product( true, array( 'regular_price' => 20 ) );
+		$coupon  = WC_Helper_Coupon::create_coupon(
+			'fixed-cart-restore',
+			array(
+				'discount_type' => 'fixed_cart',
+				'coupon_amount' => '5',
+			)
+		);
+
+		WC()->cart->add_to_cart( $product->get_id(), 1 );
+		WC()->cart->apply_coupon( $coupon->get_code() );
+		WC()->cart->calculate_totals();
+
+		// Sanity: coupon is applied.
+		$this->assertEquals( '15.00', wc_format_decimal( WC()->cart->get_total( 'edit' ), 2 ), 'coupon should reduce total to $15' );
+
+		// Act: remove the coupon.
+		WC()->cart->remove_coupon( $coupon->get_code() );
+		WC()->cart->calculate_totals();
+
+		// Assert: total restored to base, discount cleared.
+		$this->assertEqualsWithDelta( 0.0, WC()->cart->get_discount_total(), 0.001, 'discount total should be cleared after removal' );
+		$this->assertEquals( '20.00', wc_format_decimal( WC()->cart->get_total( 'edit' ), 2 ), 'total should return to $20 after coupon removed' );
+
+		WC()->cart->empty_cart();
+		$product->delete( true );
+		$coupon->delete( true );
+	}
 }