Commit afdc536af33 for woocommerce
commit afdc536af33e331d3fa9593923fa60076f118e2a
Author: Vlad Olaru <vlad.olaru@automattic.com>
Date: Tue Sep 15 16:05:45 2026 +0300
[tests] Cover the trashed shop page rewrite-flush guard (#68686)
* test(php): Cover the trashed shop page rewrite-flush guard
`queue_rewrite_rules_on_shop_page_save()` returns early when the saved
page is trashed, so a trashed shop page keeps serving the product
archive at its previous URL. #65967 added that guard and no test held
it: `class-wc-post-types-test.php` exercised the flush queue in several
ways but never through a status change.
An E2E spec used to be the only thing that would go red if the guard
were removed, and #68642 demotes that spec, so add the coverage here
instead. Two tests, because a negative assertion on its own would pass
just as happily if the hook stopped firing: one saves the published
shop page and expects the flush queued, the other trashes it and
expects the queue untouched.
Refs TESTOPS-288
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* test(php): Point the shop page option away from the trashed page
The trash test leaves `woocommerce_shop_page_id` pointing at a page
WordPress has renamed to `shop__trashed`. The class tear down then runs
`unregister_post_type( 'product' )` and `WC_Post_Types::register_post_types()`
before the transaction rolls back, and that reads the option to build
`has_archive`.
The WordPress base class only resets post types when WP_RUN_CORE_TESTS is
set, which the WooCommerce suite never sets, so the registered object
survives into the rest of the process. Measured with theme support on:
the archive registers as `shop__trashed` and stays there. It does not
fire today only because `should_register_product_archive()` is false for
the suite's active theme, which this test neither controls nor asserts.
Restore the option in a `finally` so the tear down re-registers against
the published page. Verified the same way: `shop__trashed` before the
restore, `shop` after.
Refs #68686
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* test(php): Trash the shop page through wp_trash_post()
The trash test moved the shop page to the trash with wp_update_post()
and a post_status of trash. Merchants trash pages from the editor or
the REST API, and both call wp_trash_post(), which also fires the
wp_trash_post and trashed_post actions and records the trash meta
before saving through the same wp_update_post() call.
Calling wp_trash_post() exercises that real path. It still reaches the
save_post_page guard, and the test still fails when the trash check is
removed from the guard.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
diff --git a/plugins/woocommerce/changelog/test-shop-page-trash-rewrite-guard b/plugins/woocommerce/changelog/test-shop-page-trash-rewrite-guard
new file mode 100644
index 00000000000..6cab33d743f
--- /dev/null
+++ b/plugins/woocommerce/changelog/test-shop-page-trash-rewrite-guard
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Cover the trashed-shop-page guard that keeps a rewrite flush from being queued.
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-post-types-test.php b/plugins/woocommerce/tests/php/includes/class-wc-post-types-test.php
index 13beadefaae..7e0b91de911 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-post-types-test.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-post-types-test.php
@@ -444,6 +444,70 @@ class WC_Post_Types_Test extends WC_Unit_Test_Case {
$this->assertSame( $original_blog_id, get_current_blog_id(), 'The original site context should be restored.' );
}
+ /**
+ * @testdox Saving the shop page queues a rewrite flush.
+ */
+ public function test_saving_the_shop_page_queues_a_rewrite_flush(): void {
+ $shop_page_id = $this->prepare_shop_page();
+
+ wp_update_post(
+ array(
+ 'ID' => $shop_page_id,
+ 'post_title' => 'Shop, renamed',
+ )
+ );
+
+ $this->assertSame(
+ 'yes',
+ get_option( 'woocommerce_queue_flush_rewrite_rules' ),
+ 'Saving the shop page should queue a rewrite flush.'
+ );
+ }
+
+ /**
+ * @testdox Trashing the shop page does not queue a rewrite flush.
+ */
+ public function test_trashing_the_shop_page_does_not_queue_a_rewrite_flush(): void {
+ $previous_shop_page_id = get_option( 'woocommerce_shop_page_id' );
+ $shop_page_id = $this->prepare_shop_page();
+
+ try {
+ wp_trash_post( $shop_page_id );
+
+ $this->assertSame(
+ 'no',
+ get_option( 'woocommerce_queue_flush_rewrite_rules' ),
+ 'A trashed shop page keeps serving the product archive at its previous URL, so it must not queue a flush.'
+ );
+ } finally {
+ // Trashing renames the page to `shop__trashed`, and `tearDown()` re-registers the
+ // product post type before the transaction rolls back. The base class only resets
+ // post types for core's own suite, so a theme that supports WooCommerce would hand
+ // that name to `has_archive` and leave it there for the rest of the process.
+ update_option( 'woocommerce_shop_page_id', $previous_shop_page_id );
+ }
+ }
+
+ /**
+ * Publish a page, make it the shop page, and empty the rewrite flush queue.
+ *
+ * @return int The shop page ID.
+ */
+ private function prepare_shop_page(): int {
+ $shop_page_id = self::factory()->post->create(
+ array(
+ 'post_type' => 'page',
+ 'post_status' => 'publish',
+ 'post_title' => 'Shop',
+ )
+ );
+
+ update_option( 'woocommerce_shop_page_id', $shop_page_id );
+ update_option( 'woocommerce_queue_flush_rewrite_rules', 'no' );
+
+ return $shop_page_id;
+ }
+
/**
* Register a public post type standing in for one owned by a third-party plugin.
*/