Commit dfd9d3e8e2e for woocommerce

commit dfd9d3e8e2e2168ce39bb27fc6f8665296d1b320
Author: Vlad Olaru <vlad.olaru@automattic.com>
Date:   Wed Sep 16 00:00:43 2026 +0300

    [tests] Make the MetaDataUtil default_id test able to fail and correct a product button spec comment (#68747)

    * test(php): Make the MetaDataUtil default_id test able to fail

    test_update_passes_default_id passed 99 as default_id to an order
    with no metadata. WC_Data::update_meta_data() finds no row with id
    99 and falls back to adding the entry, which is exactly what it does
    when no id is passed, so the test stayed green whether update()
    forwarded default_id or dropped it.

    Seed a metadata row and pass its real id as default_id with a new
    key and value. When the id is forwarded, that row is updated in
    place; when it is dropped, a second row is added instead. CodeRabbit
    raised this in its review of #68637.

    Refs TESTOPS-288

    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    * test(e2e): Correct the product button AJAX setting comment

    The comment above the AJAX setting change in the Blocks product
    button spec said nothing in the E2E lifecycle puts the setting back,
    so the classic theme spec would run with AJAX disabled. That is not
    true: the Blocks page fixture restores the database after every
    test, failed ones included, so the setting cannot reach the next
    spec. #68595 added the comment in reply to a review claim that was
    never checked; its own description says the per-test restore
    handles it.

    Say what actually restores the setting, and keep the finally block
    as the safety net it is.

    Refs TESTOPS-234

    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    * chore(changelog): Make the follow-up entry comment-only

    The change is test-only, so it should not add a line to the release
    changelog. A Comment header with an empty entry keeps changelogger
    satisfied without one, matching the other test PRs in this series.

    Refs TESTOPS-288

    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-meta-data-util-default-id b/plugins/woocommerce/changelog/test-meta-data-util-default-id
new file mode 100644
index 00000000000..58a8750c691
--- /dev/null
+++ b/plugins/woocommerce/changelog/test-meta-data-util-default-id
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+Comment: Make the MetaDataUtil default_id test able to fail, and correct a misleading comment in the Blocks product button spec.
+
diff --git a/plugins/woocommerce/tests/e2e/tests/blocks/product-button/product-button.block_theme.spec.ts b/plugins/woocommerce/tests/e2e/tests/blocks/product-button/product-button.block_theme.spec.ts
index 38068b4a726..40c41714944 100644
--- a/plugins/woocommerce/tests/e2e/tests/blocks/product-button/product-button.block_theme.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/blocks/product-button/product-button.block_theme.spec.ts
@@ -50,9 +50,9 @@ test.describe( `${ blockData.name } Block`, () => {
 		page,
 		admin,
 	} ) => {
-		// The setting is store-wide and nothing in the E2E lifecycle puts it back, so
-		// product-button.classic_theme.spec.ts would run with AJAX still disabled and
-		// never see the "1 in cart" button it asserts on.
+		// The setting is store-wide, but the Blocks `page` fixture restores the database
+		// after every test, failed ones included, so the next spec starts with AJAX
+		// enabled again. The `finally` below is only a safety net.
 		await handleAddToCartAjaxSetting( admin, page, {
 			isChecked: true,
 		} );
diff --git a/plugins/woocommerce/tests/php/src/Utilities/MetaDataUtilTest.php b/plugins/woocommerce/tests/php/src/Utilities/MetaDataUtilTest.php
index 6264673388d..3a58140b854 100644
--- a/plugins/woocommerce/tests/php/src/Utilities/MetaDataUtilTest.php
+++ b/plugins/woocommerce/tests/php/src/Utilities/MetaDataUtilTest.php
@@ -180,11 +180,29 @@ class MetaDataUtilTest extends WC_Unit_Test_Case {
 	}

 	/**
-	 * @testdox `update` passes custom default_id through to normalize.
+	 * @testdox `update` uses default_id for entries without an id, updating that metadata row in place.
 	 */
 	public function test_update_passes_default_id(): void {
 		$order = wc_create_order();
+		$order->add_meta_data( 'original_key', 'original_value' );
+		$order->save();
+
+		$rows_with_key = static function ( \WC_Order $order, string $key ): array {
+			return array_values(
+				array_filter(
+					$order->get_meta_data(),
+					static function ( $meta ) use ( $key ): bool {
+						return $key === $meta->key;
+					}
+				)
+			);
+		};
+		$existing_rows = $rows_with_key( $order, 'original_key' );
+		$this->assertCount( 1, $existing_rows, 'The seeded metadata row should exist before the update.' );
+		$existing_id = $existing_rows[0]->id;

+		// The id has to name a real row. An id that matches nothing makes update_meta_data() add
+		// a new row, which is also what it does when no id arrives at all.
 		MetaDataUtil::update(
 			array(
 				array(
@@ -193,19 +211,13 @@ class MetaDataUtilTest extends WC_Unit_Test_Case {
 				),
 			),
 			$order,
-			99
+			$existing_id
 		);

-		$meta_data = array_values(
-			array_filter(
-				$order->get_meta_data(),
-				static function ( $meta ): bool {
-					return 'k' === $meta->key;
-				}
-			)
-		);
-		$this->assertCount( 1, $meta_data );
-		$this->assertSame( 'k', $meta_data[0]->key );
-		$this->assertSame( 'v', $meta_data[0]->value );
+		$updated_rows = $rows_with_key( $order, 'k' );
+		$this->assertCount( 1, $updated_rows );
+		$this->assertSame( $existing_id, $updated_rows[0]->id, 'The entry should update the row named by default_id rather than add a new one.' );
+		$this->assertSame( 'v', $updated_rows[0]->value );
+		$this->assertCount( 0, $rows_with_key( $order, 'original_key' ), 'The row named by default_id should have been rewritten in place.' );
 	}
 }