From b0a798e7383a585fee0c74bb26d366ca825c2563 Mon Sep 17 00:00:00 2001 From: Geoff Taylor Date: Mon, 23 Mar 2026 22:55:48 -0400 Subject: [PATCH] devops: add attribute term products categoryId filter regression test (#987) Adds test confirming that categoryId filtering works on the products connection from attribute term types (e.g. allPaSeller.products). The issue was reported on v0.12.1 and is not reproducible on the current codebase. --- .../ProductAttributeConnectionsTest.php | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/tests/wpunit/ProductAttributeConnectionsTest.php b/tests/wpunit/ProductAttributeConnectionsTest.php index 3e258d8a..b2f5d21b 100644 --- a/tests/wpunit/ProductAttributeConnectionsTest.php +++ b/tests/wpunit/ProductAttributeConnectionsTest.php @@ -299,4 +299,122 @@ class ProductAttributeConnectionsTest extends \Tests\WPGraphQL\WooCommerce\TestC $attribute_nodes = $this->lodashGet( $response, 'data.productCategory.productAttributes.nodes', [] ); $this->assertEmpty( $attribute_nodes, 'Food category should have no product attributes.' ); } + + /** + * Test filtering products by categoryId on an attribute term's products connection. + * + * @see https://github.com/wp-graphql/wp-graphql-woocommerce/issues/730 + */ + public function testAttributeTermProductsFilteredByCategory() { + $seller_attr = $this->factory->product->createAttribute( 'seller', [ 'acme-store', 'globex-store' ] ); + + $acme_term_id = get_term_by( 'slug', 'acme-store', 'pa_seller' )->term_id; + $globex_term_id = get_term_by( 'slug', 'globex-store', 'pa_seller' )->term_id; + + $cat_fruits = $this->factory->product->createProductCategory( 'fruits' ); + $cat_vegs = $this->factory->product->createProductCategory( 'vegetables' ); + + // Acme sells fruits. + $acme_fruit = $this->factory->product->createVariable( + [ + 'category_ids' => [ $cat_fruits ], + 'attribute_data' => [ + [ + 'attribute_id' => $seller_attr['attribute_id'], + 'attribute_taxonomy' => $seller_attr['attribute_taxonomy'], + 'term_ids' => [ $acme_term_id ], + ], + ], + ] + ); + $this->factory->product_variation->create( + [ + 'parent_id' => $acme_fruit, + 'attributes' => [ 'pa_seller' => 'acme-store' ], + 'image_id' => null, + 'regular_price' => 5, + ] + ); + + // Acme also sells vegetables. + $acme_veg = $this->factory->product->createVariable( + [ + 'category_ids' => [ $cat_vegs ], + 'attribute_data' => [ + [ + 'attribute_id' => $seller_attr['attribute_id'], + 'attribute_taxonomy' => $seller_attr['attribute_taxonomy'], + 'term_ids' => [ $acme_term_id ], + ], + ], + ] + ); + $this->factory->product_variation->create( + [ + 'parent_id' => $acme_veg, + 'attributes' => [ 'pa_seller' => 'acme-store' ], + 'image_id' => null, + 'regular_price' => 3, + ] + ); + + // Globex sells fruits. + $globex_fruit = $this->factory->product->createVariable( + [ + 'category_ids' => [ $cat_fruits ], + 'attribute_data' => [ + [ + 'attribute_id' => $seller_attr['attribute_id'], + 'attribute_taxonomy' => $seller_attr['attribute_taxonomy'], + 'term_ids' => [ $globex_term_id ], + ], + ], + ] + ); + $this->factory->product_variation->create( + [ + 'parent_id' => $globex_fruit, + 'attributes' => [ 'pa_seller' => 'globex-store' ], + 'image_id' => null, + 'regular_price' => 8, + ] + ); + + $this->clearSchema(); + + // Query acme-store's products filtered by fruits category. + $query = ' + query ($slug: [String!], $categoryId: Int) { + allPaSeller(where: { slug: $slug }) { + nodes { + name + products(where: { categoryId: $categoryId }) { + nodes { + databaseId + productCategories { + nodes { + slug + } + } + } + } + } + } + } + '; + + $variables = [ + 'slug' => [ 'acme-store' ], + 'categoryId' => $cat_fruits, + ]; + + $response = $this->graphql( compact( 'query', 'variables' ) ); + $expected = [ + $this->expectedField( 'allPaSeller.nodes.0.products.nodes.#.databaseId', $acme_fruit ), + $this->not()->expectedField( 'allPaSeller.nodes.0.products.nodes.#.databaseId', $acme_veg ), + $this->not()->expectedField( 'allPaSeller.nodes.0.products.nodes.#.databaseId', $globex_fruit ), + ]; + + $this->assertQuerySuccessful( $response, $expected ); + } }