fix: add calculate_totals() after coupon removal in removeCoupons mutation (#991)

WooCommerce's remove_coupon() does not call calculate_totals() — it only
sets a refresh_totals flag for the next request. This means cart totals
returned in the removeCoupons mutation response may be stale. Add an
explicit calculate_totals() call after the coupon removal loop.
This commit is contained in:
Geoff Taylor
2026-03-24 00:17:12 -04:00
committed by GitHub
parent d3e56ee2a5
commit dd54df3ffe
2 changed files with 92 additions and 0 deletions
+89
View File
@@ -1457,4 +1457,93 @@ class CartMutationsTest extends \Tests\WPGraphQL\WooCommerce\TestCase\WooGraphQL
$response = $this->graphql( compact( 'query', 'variables' ) );
$this->assertQueryError( $response, $expected_error );
}
/**
* Test that removeCoupons recalculates cart totals after coupon removal.
*
* @see https://github.com/wp-graphql/wp-graphql-woocommerce/issues/260
*/
public function testRemoveCouponsRecalculatesTotals() {
$product_id = $this->factory->product->createSimple(
[
'regular_price' => 100,
'price' => 100,
]
);
$coupon_id = $this->factory->coupon->create(
[
'code' => 'half-off',
'discount_type' => 'percent',
'amount' => 50,
]
);
// Add product to cart.
\WC()->cart->add_to_cart( $product_id );
// Apply coupon.
$apply_query = '
mutation applyCoupon($input: ApplyCouponInput!) {
applyCoupon(input: $input) {
cart {
total
discountTotal
appliedCoupons {
code
}
}
}
}
';
$query = $apply_query;
$variables = [ 'input' => [ 'code' => 'half-off' ] ];
$response = $this->graphql( compact( 'query', 'variables' ) );
$this->assertQuerySuccessful( $response, [] );
$total_with_coupon = $this->lodashGet( $response, 'data.applyCoupon.cart.total' );
$discount_with_coupon = $this->lodashGet( $response, 'data.applyCoupon.cart.discountTotal' );
$this->assertNotEmpty( $discount_with_coupon, 'Discount should be applied.' );
// Remove coupon.
$remove_query = '
mutation removeCoupons($input: RemoveCouponsInput!) {
removeCoupons(input: $input) {
cart {
total
discountTotal
discountTax
appliedCoupons {
code
}
}
}
}
';
$variables = [ 'input' => [ 'codes' => [ 'half-off' ] ] ];
$response = $this->graphql(
[
'query' => $remove_query,
'variables' => $variables,
]
);
$this->assertQuerySuccessful( $response, [] );
// Coupon should be removed.
$applied = $this->lodashGet( $response, 'data.removeCoupons.cart.appliedCoupons' );
$this->assertEmpty( $applied, 'No coupons should be applied after removal.' );
// Totals should be recalculated — discount should be zero.
$discount_after = $this->lodashGet( $response, 'data.removeCoupons.cart.discountTotal' );
$total_after = $this->lodashGet( $response, 'data.removeCoupons.cart.total' );
$this->assertNotEquals(
$total_with_coupon,
$total_after,
'Cart total should change after removing coupon.'
);
}
}