Commit efe91ec9ff6 for woocommerce

commit efe91ec9ff6b12cccf3a8de499d2a46cc9370234
Author: SH Sajal Chowdhury <72102985+shsajalchowdhury@users.noreply.github.com>
Date:   Mon May 4 09:05:06 2026 +0600

    Fix fatal error in VariationSelectorAttribute block for non-variable products (#64410)

    * Fix fatal error in VariationSelectorAttribute block for non-variable products

    Add product type guard to render() method to prevent calling
    get_variation_attributes() on non-variable products, which causes
    a fatal 'Call to undefined method' error on WC_Product_Simple,
    WC_Product_Grouped, and WC_Product_External.

    The fix follows the same guard pattern used by sibling blocks
    VariationSelector and VariationDescription.

    Fixes #64405

    * Add test for VariationSelectorAttribute product type guard

    Test that VariationSelectorAttribute::render() returns empty string
    for simple, grouped, and external products instead of fataling.

    Also update PR body to follow WooCommerce PR template including
    submission review guidelines, testing instructions, and changelog
    entry details.

    * Add changefile(s) from automation for the following project(s): woocommerce

    * Address CodeRabbit feedback: add try/finally and null/false product tests

    - Wrap test assertions in try/finally to restore original global $product
      and prevent cross-test pollution (matching existing pattern in test suite)
    - Add test cases for null and false global $product context to exercise
      the full production guard (! $product instanceof WC_Product)

    * Remove duplicate changelog file for #64410

    * Simplify variable product guard in VariationSelectorAttribute

    * Fix lint: add end try comment in test file

    ---------

    Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
    Co-authored-by: Tung Du <dinhtungdu@gmail.com>

diff --git a/plugins/woocommerce/changelog/64410-fix-64405-variation-selector-attribute-product-type-guard b/plugins/woocommerce/changelog/64410-fix-64405-variation-selector-attribute-product-type-guard
new file mode 100644
index 00000000000..0b4170daba4
--- /dev/null
+++ b/plugins/woocommerce/changelog/64410-fix-64405-variation-selector-attribute-product-type-guard
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Add product type guard to VariationSelectorAttribute block to prevent fatal error when rendered for non-variable products.
\ No newline at end of file
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/AddToCartWithOptions/VariationSelectorAttribute.php b/plugins/woocommerce/src/Blocks/BlockTypes/AddToCartWithOptions/VariationSelectorAttribute.php
index ecfb1329e76..c4af4f47c7d 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/AddToCartWithOptions/VariationSelectorAttribute.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/AddToCartWithOptions/VariationSelectorAttribute.php
@@ -34,6 +34,10 @@ class VariationSelectorAttribute extends AbstractBlock {
 	protected function render( $attributes, $content, $block ): string {
 		global $product;

+		if ( ! $product instanceof \WC_Product_Variable ) {
+			return '';
+		}
+
 		$content = '';

 		$product_attributes = $product->get_variation_attributes();
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/AddToCartWithOptions.php b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/AddToCartWithOptions.php
index b2040fafe30..4069dd5b4e4 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/AddToCartWithOptions.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/AddToCartWithOptions.php
@@ -470,6 +470,54 @@ class AddToCartWithOptions extends \WP_UnitTestCase {
 		);
 	}

+	/**
+	 * Tests that the VariationSelectorAttribute block returns empty string
+	 * for non-variable products (simple, grouped, external) to prevent
+	 * a fatal error from calling get_variation_attributes() on unsupported
+	 * product types.
+	 *
+	 * @covers VariationSelectorAttribute::render
+	 */
+	public function test_variation_selector_attribute_returns_empty_for_non_variable_products() {
+		global $product;
+		$original_product = $product;
+
+		$block_markup = '<!-- wp:woocommerce/add-to-cart-with-options-variation-selector-attribute /-->';
+
+		try {
+			// Test with a missing/invalid product context.
+			$product = null;
+			$this->assertSame( '', do_blocks( $block_markup ), 'VariationSelectorAttribute should return empty string when the global product is null.' );
+
+			$product = false;
+			$this->assertSame( '', do_blocks( $block_markup ), 'VariationSelectorAttribute should return empty string when the global product is false.' );
+
+			// Test with a simple product.
+			$simple_product = new \WC_Product_Simple();
+			$simple_product->set_regular_price( 10 );
+			$simple_product->save();
+
+			$product = $simple_product;
+			$this->assertSame( '', do_blocks( $block_markup ), 'VariationSelectorAttribute should return empty string for simple products.' );
+
+			// Test with a grouped product.
+			$grouped_product = new \WC_Product_Grouped();
+			$grouped_product->save();
+
+			$product = $grouped_product;
+			$this->assertSame( '', do_blocks( $block_markup ), 'VariationSelectorAttribute should return empty string for grouped products.' );
+
+			// Test with an external product.
+			$external_product = new \WC_Product_External();
+			$external_product->save();
+
+			$product = $external_product;
+			$this->assertSame( '', do_blocks( $block_markup ), 'VariationSelectorAttribute should return empty string for external products.' );
+		} finally {
+			$product = $original_product;
+		}//end try
+	}
+
 	/**
 	 * Tests that the quantity selector and its steppers are hidden when
 	 * a filter sets min and max quantity to the same value for a product.