diff --git a/bin/install-wp-tests.sh b/bin/install-wp-tests.sh index b8be670de..cc6ee5491 100755 --- a/bin/install-wp-tests.sh +++ b/bin/install-wp-tests.sh @@ -192,6 +192,8 @@ setup_woocommerce() { wp plugin install wordpress-importer --activate echo "Installing & Activating WooCommerce" wp plugin install woocommerce --activate + echo "Upgrading database" + wp wc update } setup_wpgraphql() { diff --git a/includes/type/object/class-product-type.php b/includes/type/object/class-product-type.php index 878c2116a..d7106e22e 100644 --- a/includes/type/object/class-product-type.php +++ b/includes/type/object/class-product-type.php @@ -340,6 +340,14 @@ public static function register() { 'type' => 'Int', 'description' => __( 'Get the product by its database ID', 'wp-graphql-woocommerce' ), ), + 'slug' => array( + 'type' => 'String', + 'description' => __( 'Get the product by its slug', 'wp-graphql-woocommerce' ), + ), + 'sku' => array( + 'type' => 'String', + 'description' => __( 'Get the product by its sku', 'wp-graphql-woocommerce' ), + ), ); register_graphql_field( @@ -351,22 +359,36 @@ public static function register() { 'args' => $post_by_args, 'resolve' => function ( $source, array $args, AppContext $context, ResolveInfo $info ) { $product_id = 0; + $id_type = ''; if ( ! empty( $args['id'] ) ) { $id_components = Relay::fromGlobalId( $args['id'] ); if ( empty( $id_components['id'] ) || empty( $id_components['type'] ) ) { throw new UserError( __( 'The "id" is invalid', 'wp-graphql-woocommerce' ) ); } $product_id = absint( $id_components['id'] ); + $id_type = 'ID'; } elseif ( ! empty( $args['productId'] ) ) { $product_id = absint( $args['productId'] ); + $id_type = 'product ID'; + } elseif ( ! empty( $args['slug'] ) ) { + $post = get_page_by_path( $args['slug'], OBJECT, 'product' ); + $product_id = ! empty( $post ) ? absint( $post->ID ) : 0; + $id_type = 'slug'; + } elseif ( ! empty( $args['sku'] ) ) { + $product_id = \wc_get_product_id_by_sku( $args['sku'] ); + $id_type = 'sku'; } - $product = Factory::resolve_crud_object( $product_id, $context ); - if ( get_post( $product_id )->post_type !== 'product' ) { - /* translators: not coupon found error message */ - throw new UserError( sprintf( __( 'No product exists with this id: %1$s' ), $args['id'] ) ); + if ( empty( $product_id ) ) { + /* translators: %1$s: ID type, %2$s: ID value */ + throw new UserError( sprintf( __( 'No product ID was found corresponding to the %1$s: %2$s' ), $id_type, $product_id ) ); + } elseif ( get_post( $product_id )->post_type !== 'product' ) { + /* translators: %1$s: ID type, %2$s: ID value */ + throw new UserError( sprintf( __( 'No product exists with the %1$s: %2$s' ), $id_type, $product_id ) ); } + $product = Factory::resolve_crud_object( $product_id, $context ); + return $product; }, ) diff --git a/tests/_support/Helper/crud-helpers/product.php b/tests/_support/Helper/crud-helpers/product.php index 3a2417327..a210dd123 100644 --- a/tests/_support/Helper/crud-helpers/product.php +++ b/tests/_support/Helper/crud-helpers/product.php @@ -67,25 +67,29 @@ public function create_simple( $args = array() ) { $price = $this->dummy->price( 15, 200 ); $regular_price = $this->dummy->price( $price, $price + ( $price * 0.1 ) ); - $product->set_props( - array_merge( - array( - 'name' => $name, - 'slug' => $this->next_slug(), - 'regular_price' => $regular_price, - 'price' => $price, - 'sku' => 'DUMMY SKU '.$this->index, - 'manage_stock' => false, - 'tax_status' => 'taxable', - 'downloadable' => false, - 'virtual' => false, - 'stock_status' => 'instock', - 'weight' => '1.1', - ), - $args - ) + $props = array_merge( + array( + 'name' => $name, + 'slug' => $this->next_slug(), + 'regular_price' => $regular_price, + 'price' => $price, + 'sku' => uniqid(), + 'manage_stock' => false, + 'tax_status' => 'taxable', + 'downloadable' => false, + 'virtual' => false, + 'stock_status' => 'instock', + 'weight' => '1.1', + ), + $args ); + foreach ( $props as $key => $value ) { + if ( is_callable( array( $product, "set_{$key}" ) ) ) { + $product->{"set_{$key}"}( $value ); + } + } + return $product->save(); } diff --git a/tests/wpunit/ProductQueriesTest.php b/tests/wpunit/ProductQueriesTest.php index 6e7507cad..8fbd8706a 100644 --- a/tests/wpunit/ProductQueriesTest.php +++ b/tests/wpunit/ProductQueriesTest.php @@ -36,13 +36,17 @@ public function setUp() { 'image_id' => $this->image_id, 'gallery_image_ids' => array( $this->image_id ), 'downloads' => array( ProductHelper::create_download() ), + 'slug' => 'product-slug', + 'sku' => 'product-sku', ) ); } public function tearDown() { // your tear down methods here - // then + $product = \WC()->product_factory->get_product( $this->product ); + $product->delete( true ); + parent::tearDown(); } @@ -113,15 +117,20 @@ public function testProductQuery() { } public function testProductByQueryAndArgs() { - $id = Relay::toGlobalId( 'product', $this->product ); + $id = $this->helper->to_relay_id( $this->product ); $query = ' - query productQuery( $id: ID, $productId: Int ) { - productBy(id: $id productId: $productId ) { + query productQuery( $id: ID, $productId: Int, $slug: String, $sku: String ) { + productBy( id: $id, productId: $productId, slug: $slug, sku: $sku ) { id } } '; + /** + * Assertion One + * + * Test querying product with "productId" argument. + */ $variables = array( 'productId' => $this->product ); $actual = do_graphql_request( $query, 'productQuery', $variables ); $expected = array( 'data' => array( 'productBy' => array( 'id' => $id ) ) ); @@ -131,6 +140,11 @@ public function testProductByQueryAndArgs() { $this->assertEquals( $expected, $actual ); + /** + * Assertion Two + * + * Test querying product with "id" argument. + */ $variables = array( 'id' => $id ); $actual = do_graphql_request( $query, 'productQuery', $variables ); $expected = array( 'data' => array( 'productBy' => array( 'id' => $id ) ) ); @@ -139,6 +153,34 @@ public function testProductByQueryAndArgs() { codecept_debug( $actual ); $this->assertEquals( $expected, $actual ); + + /** + * Assertion Three + * + * Test querying product with "slug" argument. + */ + $variables = array( 'slug' => 'product-slug' ); + $actual = do_graphql_request( $query, 'productQuery', $variables ); + $expected = array( 'data' => array( 'productBy' => array( 'id' => $id ) ) ); + + // use --debug flag to view. + codecept_debug( $actual ); + + $this->assertEquals( $expected, $actual ); + + /** + * Assertion Four + * + * Test querying product with "sku" argument. + */ + $variables = array( 'sku' => 'product-sku' ); + $actual = do_graphql_request( $query, 'productQuery', $variables ); + $expected = array( 'data' => array( 'productBy' => array( 'id' => $id ) ) ); + + // use --debug flag to view. + codecept_debug( $actual ); + + $this->assertEquals( $expected, $actual ); } public function testProductsQueryAndWhereArgs() {