diff --git a/.github/workflows/continous-integration.yml b/.github/workflows/continous-integration.yml index e99d5f12..90a10fbe 100644 --- a/.github/workflows/continous-integration.yml +++ b/.github/workflows/continous-integration.yml @@ -62,7 +62,7 @@ jobs: WP_VERSION: ${{ matrix.wordpress }} PHP_VERSION: ${{ matrix.php }} run: | - HPOS="${{ matrix.hpos }}" FILTER="acceptance --fail-fast ${{ matrix.coverage == true && '--coverage=acceptance.serialized' || '' }} ${{ matrix.debug }}" composer dRunTestStandalone + HPOS="${{ matrix.hpos }}" FILTER="acceptance --fail-fast ${{ matrix.coverage == true && '--coverage=acceptance.cov' || '' }} ${{ matrix.debug }}" composer dRunTestStandalone - name: Retry on failure id: retry @@ -72,7 +72,7 @@ jobs: WP_VERSION: ${{ matrix.wordpress }} PHP_VERSION: ${{ matrix.php }} run: | - HPOS="${{ matrix.hpos }}" FILTER="acceptance ${{ matrix.coverage == true && '--coverage=acceptance.serialized' || '' }} ${{ matrix.debug }}" composer dRunTestStandalone + HPOS="${{ matrix.hpos }}" FILTER="acceptance ${{ matrix.coverage == true && '--coverage=acceptance.cov' || '' }} ${{ matrix.debug }}" composer dRunTestStandalone - name: Fail if both attempts failed if: ${{ steps.tests.outcome == 'failure' && steps.retry.outcome == 'failure' }} @@ -83,7 +83,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: coverage-acceptance - path: tests/_output/acceptance.serialized + path: tests/_output/acceptance.cov if-no-files-found: ignore functional: @@ -133,7 +133,7 @@ jobs: WP_VERSION: ${{ matrix.wordpress }} PHP_VERSION: ${{ matrix.php }} run: | - HPOS="${{ matrix.hpos }}" FILTER="functional --fail-fast ${{ matrix.coverage == true && '--coverage=functional.serialized' || '' }} ${{ matrix.debug }}" composer dRunTestStandalone + HPOS="${{ matrix.hpos }}" FILTER="functional --fail-fast ${{ matrix.coverage == true && '--coverage=functional.cov' || '' }} ${{ matrix.debug }}" composer dRunTestStandalone - name: Retry on failure id: retry @@ -143,7 +143,7 @@ jobs: WP_VERSION: ${{ matrix.wordpress }} PHP_VERSION: ${{ matrix.php }} run: | - HPOS="${{ matrix.hpos }}" FILTER="functional ${{ matrix.coverage == true && '--coverage=functional.serialized' || '' }} ${{ matrix.debug }}" composer dRunTestStandalone + HPOS="${{ matrix.hpos }}" FILTER="functional ${{ matrix.coverage == true && '--coverage=functional.cov' || '' }} ${{ matrix.debug }}" composer dRunTestStandalone - name: Fail if both attempts failed if: ${{ steps.tests.outcome == 'failure' && steps.retry.outcome == 'failure' }} @@ -154,7 +154,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: coverage-functional - path: tests/_output/functional.serialized + path: tests/_output/functional.cov if-no-files-found: ignore wpunit: @@ -204,7 +204,7 @@ jobs: WP_VERSION: ${{ matrix.wordpress }} PHP_VERSION: ${{ matrix.php }} run: | - HPOS="${{ matrix.hpos }}" FILTER="wpunit --fail-fast ${{ matrix.coverage == true && '--coverage=wpunit.serialized' || '' }} ${{ matrix.debug }}" composer dRunTestStandalone + HPOS="${{ matrix.hpos }}" FILTER="wpunit --fail-fast ${{ matrix.coverage == true && '--coverage=wpunit.cov' || '' }} ${{ matrix.debug }}" composer dRunTestStandalone - name: Retry on failure id: retry @@ -214,7 +214,7 @@ jobs: WP_VERSION: ${{ matrix.wordpress }} PHP_VERSION: ${{ matrix.php }} run: | - HPOS="${{ matrix.hpos }}" FILTER="wpunit ${{ matrix.coverage == true && '--coverage=wpunit.serialized' || '' }} ${{ matrix.debug }}" composer dRunTestStandalone + HPOS="${{ matrix.hpos }}" FILTER="wpunit ${{ matrix.coverage == true && '--coverage=wpunit.cov' || '' }} ${{ matrix.debug }}" composer dRunTestStandalone - name: Fail if both attempts failed if: ${{ steps.tests.outcome == 'failure' && steps.retry.outcome == 'failure' }} @@ -225,7 +225,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: coverage-wpunit - path: tests/_output/wpunit.serialized + path: tests/_output/wpunit.cov if-no-files-found: ignore coverage: @@ -248,7 +248,7 @@ jobs: - name: Install dependencies run: | - composer global require phpunit/phpcov php-coveralls/php-coveralls + composer global require phpunit/phpcov:^8 php-coveralls/php-coveralls - name: Download coverage artifacts uses: actions/download-artifact@v4 @@ -262,7 +262,7 @@ jobs: run: | mkdir -p tests/_output ls -la coverage-files/ 2>/dev/null || echo "No coverage files found" - if ls coverage-files/*.serialized 1>/dev/null 2>&1; then + if ls coverage-files/*.cov 1>/dev/null 2>&1; then phpcov merge --clover=tests/_output/coverage.xml coverage-files else echo "No serialized coverage files to merge" diff --git a/includes/type/interface/class-product-attribute.php b/includes/type/interface/class-product-attribute.php index ead15792..3deecbec 100644 --- a/includes/type/interface/class-product-attribute.php +++ b/includes/type/interface/class-product-attribute.php @@ -58,7 +58,7 @@ class Product_Attribute { 'type' => 'String', 'description' => __( 'Attribute name', 'wp-graphql-woocommerce' ), 'resolve' => static function ( $attribute ) { - return ! empty( $attribute->get_name() ) ? $attribute->get_name() : null; + return ! empty( $attribute->get_name() ) ? sanitize_title( $attribute->get_name() ) : null; }, ], 'label' => [ diff --git a/tests/wpunit/AttributeNameConsistencyTest.php b/tests/wpunit/AttributeNameConsistencyTest.php new file mode 100644 index 00000000..3f4b7100 --- /dev/null +++ b/tests/wpunit/AttributeNameConsistencyTest.php @@ -0,0 +1,78 @@ +factory->product_variation->createSome(); + $product_id = $product_ids['product']; + $variation_id = $product_ids['variations'][0]; + + $query = ' + query ($productId: ID!, $variationId: ID!) { + product(id: $productId) { + ... on VariableProduct { + attributes { + nodes { + name + label + scope + } + } + } + } + productVariation(id: $variationId) { + attributes { + nodes { + name + label + value + } + } + } + } + '; + + $variables = [ + 'productId' => $this->toRelayId( 'post', $product_id ), + 'variationId' => $this->toRelayId( 'post', $variation_id ), + ]; + + $response = $this->graphql( compact( 'query', 'variables' ) ); + + // Get the variation's attribute names to use as expected values. + $product = wc_get_product( $variation_id ); + $var_attrs = $product->get_attributes(); + + $expected = []; + foreach ( $var_attrs as $name => $value ) { + $is_taxonomy = taxonomy_exists( $name ); + + // The ProductAttribute.name should be sanitized and match the VariationAttribute.name. + $expected[] = $this->expectedNode( + 'product.attributes.nodes', + [ + $this->expectedField( 'name', $is_taxonomy ? $name : sanitize_title( $name ) ), + ] + ); + + // The VariationAttribute should have the same name. + $expected[] = $this->expectedNode( + 'productVariation.attributes.nodes', + [ + $this->expectedField( 'name', $is_taxonomy ? $name : sanitize_title( $name ) ), + ] + ); + } + + $this->assertQuerySuccessful( $response, $expected ); + } +} diff --git a/tests/wpunit/ProductAttributeConnectionsTest.php b/tests/wpunit/ProductAttributeConnectionsTest.php index b2f5d21b..14a52943 100644 --- a/tests/wpunit/ProductAttributeConnectionsTest.php +++ b/tests/wpunit/ProductAttributeConnectionsTest.php @@ -182,7 +182,7 @@ class ProductAttributeConnectionsTest extends \Tests\WPGraphQL\WooCommerce\TestC $this->expectedNode( 'product.localAttributes.nodes', [ - $this->expectedField( 'name', 'Engraving' ), + $this->expectedField( 'name', 'engraving' ), ] ), ]; @@ -193,7 +193,7 @@ class ProductAttributeConnectionsTest extends \Tests\WPGraphQL\WooCommerce\TestC $local_attrs = $this->lodashGet( $response, 'data.product.localAttributes.nodes', [] ); $engraving_node = null; foreach ( $local_attrs as $node ) { - if ( 'Engraving' === $node['name'] ) { + if ( 'engraving' === $node['name'] ) { $engraving_node = $node; break; }