Commit 32a688d21f8 for woocommerce

commit 32a688d21f837ea59a4910f1385b7eb2d875daa7
Author: Vlad Olaru <vlad.olaru@automattic.com>
Date:   Mon Sep 14 13:55:11 2026 +0300

    [tests] Add Jest and PHPUnit coverage for the Product Results Count block (#68662)

    test(blocks): Add lower-layer coverage for Product Results Count

    The Product Results Count block had one browser test and nothing
    underneath it. This adds both layers it was missing and removes
    nothing.

    A Jest suite covers the editor side: that the block registers its real
    editor placeholder and a dynamic save callback.

    A new PHPUnit class covers the rendered output, which is where this
    block's logic actually lives. It asserts the paginated result count
    rendered with a query context, and the default router region used when
    no query context is supplied.

    The block's browser test is kept exactly as it is. The migration
    branch deletes it; this branch does not, for the same reason as the
    Catalog Sorting batch. That test asserts on the editor canvas, and
    moving it to the rendered archive looks like an improvement until you
    find that whether this block appears there depends on
    wc_blocks_use_blockified_product_grid_block_as_template, which five
    specs in tests/e2e set to false and none restores. A front-end
    assertion would report what ran before it.

    Its render() is also worth noting for anyone tempted to assert on the
    wrapper: it opens a div unconditionally and only then buffers
    woocommerce_result_count(), so the wrapper is present even when the
    count is empty. Any front-end check has to assert the text.

    Consolidates the mega-branch slices:
    - Slice 091

    Refs TESTOPS-234
    Refs #68046

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

diff --git a/plugins/woocommerce/changelog/testops-234-product-results-count b/plugins/woocommerce/changelog/testops-234-product-results-count
new file mode 100644
index 00000000000..d1b5d9cab62
--- /dev/null
+++ b/plugins/woocommerce/changelog/testops-234-product-results-count
@@ -0,0 +1,3 @@
+Significance: patch
+Type: dev
+Comment: Add Jest coverage for the Product Results Count block's registration and PHPUnit coverage for its rendered result count. No E2E test is removed.
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-results-count/test/index.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-results-count/test/index.tsx
new file mode 100644
index 00000000000..82ec74e98ac
--- /dev/null
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-results-count/test/index.tsx
@@ -0,0 +1,59 @@
+/**
+ * External dependencies
+ */
+import { render, screen } from '@testing-library/react';
+import { registerBlockType } from '@wordpress/blocks';
+import type { ComponentType } from 'react';
+
+/**
+ * Internal dependencies
+ */
+import metadata from '../block.json';
+
+jest.mock( '@wordpress/blocks', () => ( {
+	registerBlockType: jest.fn(),
+} ) );
+
+jest.mock( '@wordpress/block-editor', () => ( {
+	useBlockProps: ( props: Record< string, unknown > ) => props,
+} ) );
+
+type RegisteredBlock = {
+	edit: ComponentType< Record< string, unknown > >;
+	save: () => null;
+};
+
+const loadRegisteredBlock = (): RegisteredBlock => {
+	jest.isolateModules( () => {
+		jest.requireActual( '../index' );
+	} );
+
+	expect( registerBlockType ).toHaveBeenCalledTimes( 1 );
+	const [ registeredMetadata, settings ] = ( registerBlockType as jest.Mock )
+		.mock.calls[ 0 ];
+
+	expect( registeredMetadata ).toEqual( metadata );
+	expect( registeredMetadata.name ).toBe(
+		'woocommerce/product-results-count'
+	);
+	expect( settings ).not.toHaveProperty( 'attributes' );
+
+	return settings as RegisteredBlock;
+};
+
+describe( 'Product Results Count block registration', () => {
+	beforeEach( () => {
+		jest.clearAllMocks();
+	} );
+
+	it( 'registers its real editor placeholder and dynamic save callback', () => {
+		const { edit: Edit, save } = loadRegisteredBlock();
+
+		render( <Edit /> );
+
+		expect(
+			screen.getByText( 'Showing 1-X of X results' )
+		).toBeInTheDocument();
+		expect( save() ).toBeNull();
+	} );
+} );
diff --git a/plugins/woocommerce/client/blocks/changelog/testops-234-product-results-count b/plugins/woocommerce/client/blocks/changelog/testops-234-product-results-count
new file mode 100644
index 00000000000..d1b5d9cab62
--- /dev/null
+++ b/plugins/woocommerce/client/blocks/changelog/testops-234-product-results-count
@@ -0,0 +1,3 @@
+Significance: patch
+Type: dev
+Comment: Add Jest coverage for the Product Results Count block's registration and PHPUnit coverage for its rendered result count. No E2E test is removed.
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/ProductResultsCountTest.php b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/ProductResultsCountTest.php
new file mode 100644
index 00000000000..51e24fb1fdc
--- /dev/null
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/ProductResultsCountTest.php
@@ -0,0 +1,96 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace Automattic\WooCommerce\Tests\Blocks\BlockTypes;
+
+use WP_HTML_Tag_Processor;
+use WP_UnitTestCase;
+
+/**
+ * Tests for the Product Results Count block type.
+ */
+class ProductResultsCountTest extends WP_UnitTestCase {
+
+	/**
+	 * Whether the WooCommerce loop existed before the test.
+	 *
+	 * @var bool
+	 */
+	private bool $had_woocommerce_loop;
+
+	/**
+	 * WooCommerce loop value before the test.
+	 *
+	 * @var mixed
+	 */
+	private $original_woocommerce_loop;
+
+	/**
+	 * Set up the paginated product loop.
+	 */
+	public function setUp(): void {
+		parent::setUp();
+
+		$this->had_woocommerce_loop      = array_key_exists( 'woocommerce_loop', $GLOBALS );
+		$this->original_woocommerce_loop = $this->had_woocommerce_loop ? $GLOBALS['woocommerce_loop'] : null;
+
+		wc_setup_loop(
+			array(
+				'is_paginated' => true,
+				'total'        => 12,
+				'per_page'     => 4,
+				'current_page' => 2,
+			)
+		);
+	}
+
+	/**
+	 * Restore the WooCommerce loop.
+	 */
+	public function tearDown(): void {
+		wc_reset_loop();
+
+		if ( $this->had_woocommerce_loop ) {
+			$GLOBALS['woocommerce_loop'] = $this->original_woocommerce_loop;
+		} else {
+			unset( $GLOBALS['woocommerce_loop'] );
+		}
+
+		parent::tearDown();
+	}
+
+	/**
+	 * @testdox Renders exact paginated output and query-specific Interactivity attributes.
+	 */
+	public function test_renders_paginated_result_count_with_query_context(): void {
+		$markup = do_blocks(
+			'<!-- wp:query {"queryId":17} --><div class="wp-block-query"><!-- wp:woocommerce/product-results-count /--></div><!-- /wp:query -->'
+		);
+		$p      = new WP_HTML_Tag_Processor( $markup );
+
+		$this->assertTrue( $p->next_tag( array( 'class_name' => 'wc-block-product-results-count' ) ), 'The rendered result count wrapper should exist.' );
+		$this->assertSame( 'woocommerce/product-results-count', $p->get_attribute( 'data-wp-interactive' ), 'The wrapper should declare the Product Results Count Interactivity store.' );
+		$this->assertSame( 'wc-product-results-count-17', $p->get_attribute( 'data-wp-router-region' ), 'The router region should include the inherited query ID.' );
+		$class_tokens = preg_split( '/\s+/', trim( (string) $p->get_attribute( 'class' ) ) );
+		$class_tokens = is_array( $class_tokens ) ? array_values( array_filter( $class_tokens ) ) : array();
+		$this->assertContains( 'woocommerce', $class_tokens, 'The wrapper should include the WooCommerce class.' );
+		$this->assertContains( 'wp-block-woocommerce-product-results-count', $class_tokens, 'The wrapper should include the WordPress block class.' );
+
+		$text = html_entity_decode( wp_strip_all_tags( $markup ), ENT_QUOTES | ENT_HTML5, 'UTF-8' );
+		$text = preg_replace( '/\s+/', ' ', trim( $text ) );
+		$this->assertIsString( $text );
+		$this->assertStringContainsString( 'Showing 5–8 of 12 results', $text, 'The block should expose the exact second-page result range.' );
+	}
+
+	/**
+	 * @testdox Uses the default router region when no query context is present.
+	 */
+	public function test_uses_default_router_region_without_query_context(): void {
+		$markup = do_blocks( '<!-- wp:woocommerce/product-results-count /-->' );
+		$p      = new WP_HTML_Tag_Processor( $markup );
+
+		$this->assertTrue( $p->next_tag( array( 'class_name' => 'wc-block-product-results-count' ) ), 'The standalone result count wrapper should exist.' );
+		$this->assertSame( 'wc-product-results-count-0', $p->get_attribute( 'data-wp-router-region' ), 'The standalone router region should use the default query ID.' );
+	}
+}