Commit ac192ff3ac8 for woocommerce
commit ac192ff3ac8e7ba21219d21ec6d2fa93d7a0326e
Author: Seghir Nadir <nadir.seghir@gmail.com>
Date: Thu May 21 10:54:42 2026 +0200
Fix deferred email and checkout PHPUnit assertions (#65226)
* Fix email and checkout CI assertions
* Add changelog for email and checkout CI fix
* Clarify checkout retry session assertion
diff --git a/plugins/woocommerce/changelog/fix-email-checkout-ci-tests b/plugins/woocommerce/changelog/fix-email-checkout-ci-tests
new file mode 100644
index 00000000000..871b6afcdb2
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-email-checkout-ci-tests
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Fix PHPUnit assertions for deferred email queue object round trips and Store API checkout failed-payment retries.
diff --git a/plugins/woocommerce/tests/php/src/Blocks/StoreApi/Routes/Checkout.php b/plugins/woocommerce/tests/php/src/Blocks/StoreApi/Routes/Checkout.php
index b3bd5733a28..a918122f908 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/StoreApi/Routes/Checkout.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/StoreApi/Routes/Checkout.php
@@ -2246,7 +2246,18 @@ class Checkout extends MockeryTestCase {
remove_action( 'woocommerce_store_api_checkout_order_processed', $fail_hook, 999 );
// Second POST on the same session should reuse the existing pending order.
- $second_response = rest_get_server()->dispatch( $this->build_valid_post_request() );
+ $session_order_id_during_retry = null;
+ $capture_session_order_id = function () use ( &$session_order_id_during_retry ) {
+ $session_order_id_during_retry = (int) WC()->session->get( 'store_api_draft_order' );
+ };
+ add_action( 'woocommerce_store_api_checkout_order_processed', $capture_session_order_id, 999, 0 );
+
+ try {
+ $second_response = rest_get_server()->dispatch( $this->build_valid_post_request() );
+ } finally {
+ remove_action( 'woocommerce_store_api_checkout_order_processed', $capture_session_order_id, 999 );
+ }
+
$this->assertEquals( 200, $second_response->get_status(), print_r( $second_response->get_data(), true ) );
$second_order_id = (int) $second_response->get_data()['order_id'];
@@ -2255,7 +2266,8 @@ class Checkout extends MockeryTestCase {
$second_order_id,
'Second POST must reuse the existing pending order, not create a new one (regression: issue #64792).'
);
- $this->assertSame( $first_order_id, (int) WC()->session->get( 'store_api_draft_order' ), 'Session pointer should still reference the reused order.' );
+ $this->assertSame( $first_order_id, $session_order_id_during_retry, 'Session pointer should reference the reused order while the second POST is being processed.' );
+ $this->assertEmpty( WC()->session->get( 'store_api_draft_order' ), 'Successful checkout should clear the draft order pointer when the cart is emptied.' );
}
/**
diff --git a/plugins/woocommerce/tests/php/src/Internal/Email/DeferredEmailQueueTest.php b/plugins/woocommerce/tests/php/src/Internal/Email/DeferredEmailQueueTest.php
index 5ccb2a4deb9..862fada93cd 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Email/DeferredEmailQueueTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Email/DeferredEmailQueueTest.php
@@ -469,8 +469,7 @@ class DeferredEmailQueueTest extends WC_Unit_Test_Case {
$this->sut->push( $filter, $args );
$this->sut->dispatch();
- $queue = $this->get_test_queue();
- $scheduled_arg = $queue->actions[0]['args'];
+ $scheduled_arg = $this->get_scheduled_email_action()['args'];
$encoded_arg = wp_json_encode( $scheduled_arg );
$this->assert_queued_object_reference( $scheduled_arg[1][ $wrapped_position ], $expected_type, $expected_id );
@@ -529,6 +528,30 @@ class DeferredEmailQueueTest extends WC_Unit_Test_Case {
);
}
+ /**
+ * Get the scheduled Action Scheduler email action from the test queue.
+ *
+ * Other fixture setup can enqueue unrelated actions before the email queue
+ * dispatches, so object round-trip assertions must target the email action.
+ *
+ * @return array{timestamp: int, hook: string, args: array, group: string}
+ */
+ private function get_scheduled_email_action(): array {
+ foreach ( $this->get_test_queue()->actions as $action ) {
+ if ( 'woocommerce_send_queued_transactional_email' === $action['hook'] ) {
+ return $action;
+ }
+ }
+
+ $this->fail( 'Expected a queued transactional email action to be scheduled.' );
+ return array(
+ 'timestamp' => 0,
+ 'hook' => '',
+ 'args' => array(),
+ 'group' => '',
+ );
+ }
+
/**
* Assert a queued object reference has the expected wrapper shape.
*