woocommerce/plugins/woocommerce-blocks/tests/php/StoreApi/Routes/CartItems.php

285 lines
9.8 KiB
PHP
Raw Normal View History

<?php
/**
* Controller Tests.
*/
namespace Automattic\WooCommerce\Blocks\Tests\StoreApi\Controllers;
use \WP_REST_Request;
use \WC_REST_Unit_Test_Case as TestCase;
use \WC_Helper_Product as ProductHelper;
use Automattic\WooCommerce\Blocks\Tests\Helpers\ValidateSchema;
use Automattic\WooCommerce\Blocks\Domain\Services\ExtendRestApi;
use Automattic\WooCommerce\Blocks\Package;
use Automattic\WooCommerce\Blocks\Domain\Package as DomainPackage;
use Automattic\WooCommerce\Blocks\StoreApi\Formatters;
use Automattic\WooCommerce\Blocks\StoreApi\Formatters\MoneyFormatter;
use Automattic\WooCommerce\Blocks\StoreApi\Formatters\HtmlFormatter;
use Automattic\WooCommerce\Blocks\StoreApi\Formatters\CurrencyFormatter;
use Automattic\WooCommerce\Blocks\Registry\Container;
use Automattic\WooCommerce\Blocks\Domain\Services\FeatureGating;
/**
* Cart Controller Tests.
*/
class CartItems extends TestCase {
private $mock_extend;
/**
* Setup test products data. Called before every test.
*/
public function setUp() {
global $wpdb;
parent::setUp();
$formatters = new Formatters();
$formatters->register( 'money', MoneyFormatter::class );
$formatters->register( 'html', HtmlFormatter::class );
$formatters->register( 'currency', CurrencyFormatter::class );
$this->mock_extend = new ExtendRestApi( new DomainPackage( '', '', new FeatureGating( 2 ) ), $formatters );
wp_set_current_user( 0 );
update_option( 'woocommerce_weight_unit', 'g' );
$this->products = [];
// Create a test simple product.
$this->products[0] = ProductHelper::create_simple_product( false );
$this->products[0]->set_weight( 10 );
$this->products[0]->set_regular_price( 10 );
$this->products[0]->save();
$image_url = media_sideload_image( 'http://cldup.com/Dr1Bczxq4q.png', $this->products[0]->get_id(), '', 'src' );
$image_id = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE guid = %s", $image_url ) );
$this->products[0]->set_image_id( $image_id[0] );
$this->products[0]->save();
// Create a test variable product.
$this->products[1] = ProductHelper::create_variation_product();
$this->products[1]->set_weight( 10 );
$this->products[1]->set_regular_price( 10 );
$this->products[1]->save();
wc_empty_cart();
$this->keys = [];
$this->keys[] = wc()->cart->add_to_cart( $this->products[0]->get_id(), 2 );
$this->keys[] = wc()->cart->add_to_cart(
$this->products[1]->get_id(),
1,
current( $this->products[1]->get_children() ),
array(
'attribute_pa_colour' => 'red',
'attribute_pa_number' => '2',
)
);
}
/**
* Test route registration.
*/
public function test_register_routes() {
$routes = $this->server->get_routes();
$this->assertArrayHasKey( '/wc/store/cart/items', $routes );
$this->assertArrayHasKey( '/wc/store/cart/items/(?P<key>[\w-]{32})', $routes );
}
/**
* Test getting cart.
*/
public function test_get_items() {
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/store/cart/items' ) );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 2, count( $data ) );
}
/**
* Test getting cart item by key.
*/
public function test_get_item() {
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/store/cart/items/' . $this->keys[0] ) );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( $this->keys[0], $data['key'] );
$this->assertEquals( $this->products[0]->get_id(), $data['id'] );
$this->assertEquals( $this->products[0]->get_name(), $data['name'] );
$this->assertEquals( $this->products[0]->get_sku(), $data['sku'] );
$this->assertEquals( $this->products[0]->get_permalink(), $data['permalink'] );
$this->assertEquals( 2, $data['quantity'] );
$this->assertEquals( '2000', $data['totals']->line_subtotal );
$this->assertEquals( '2000', $data['totals']->line_total );
$request = new WP_REST_Request( 'DELETE', '/wc/store/cart/items/XXX815416f775098fe977004015c6193' );
$request->set_header( 'X-WC-Store-API-Nonce', wp_create_nonce( 'wc_store_api' ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 404, $response->get_status() );
}
/**
* Test add to cart.
*/
public function test_create_item() {
wc_empty_cart();
$request = new WP_REST_Request( 'POST', '/wc/store/cart/items' );
$request->set_header( 'X-WC-Store-API-Nonce', wp_create_nonce( 'wc_store_api' ) );
$request->set_body_params(
array(
'id' => $this->products[0]->get_id(),
'quantity' => '10',
)
);
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 201, $response->get_status() );
$this->assertEquals( $this->products[0]->get_id(), $data['id'] );
$this->assertEquals( 10, $data['quantity'] );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 201, $response->get_status() );
$this->assertEquals( $this->products[0]->get_id(), $data['id'] );
$this->assertEquals( 20, $data['quantity'] );
}
/**
* Test add to cart does not allow invalid items.
*/
public function test_invalid_create_item() {
wc_empty_cart();
$invalid_product = ProductHelper::create_simple_product( false );
$invalid_product->set_regular_price( '' );
$invalid_product->save();
$request = new WP_REST_Request( 'POST', '/wc/store/cart/items' );
$request->set_header( 'X-WC-Store-API-Nonce', wp_create_nonce( 'wc_store_api' ) );
$request->set_body_params(
array(
'id' => $invalid_product->get_id(),
'quantity' => '10',
)
);
$response = $this->server->dispatch( $request );
$this->assertEquals( 400, $response->get_status() );
}
/**
* Test updating an item.
*/
public function test_update_item() {
$request = new WP_REST_Request( 'PUT', '/wc/store/cart/items/' . $this->keys[0] );
$request->set_header( 'X-WC-Store-API-Nonce', wp_create_nonce( 'wc_store_api' ) );
$request->set_body_params(
array(
'quantity' => '10',
)
);
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 10, $data['quantity'] );
}
/**
* Test delete item.
*/
public function test_delete_item() {
$request = new WP_REST_Request( 'DELETE', '/wc/store/cart/items/' . $this->keys[0] );
$request->set_header( 'X-WC-Store-API-Nonce', wp_create_nonce( 'wc_store_api' ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 204, $response->get_status() );
$this->assertEmpty( $data );
$request = new WP_REST_Request( 'DELETE', '/wc/store/cart/items/' . $this->keys[0] );
$request->set_header( 'X-WC-Store-API-Nonce', wp_create_nonce( 'wc_store_api' ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 404, $response->get_status() );
}
/**
* Test delete all items.
*/
public function test_delete_items() {
$request = new WP_REST_Request( 'DELETE', '/wc/store/cart/items' );
$request->set_header( 'X-WC-Store-API-Nonce', wp_create_nonce( 'wc_store_api' ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( [], $data );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/store/cart/items' ) );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 0, count( $data ) );
}
/**
* Test conversion of cart item to rest response.
*/
public function test_prepare_item_for_response() {
$routes = new \Automattic\WooCommerce\Blocks\StoreApi\RoutesController( new \Automattic\WooCommerce\Blocks\StoreApi\SchemaController( $this->mock_extend ) );
$controller = $routes->get( 'cart-items' );
$cart = wc()->cart->get_cart();
$response = $controller->prepare_item_for_response( current( $cart ), new \WP_REST_Request() );
$data = $response->get_data();
$this->assertArrayHasKey( 'key', $data );
$this->assertArrayHasKey( 'id', $data );
$this->assertArrayHasKey( 'quantity', $data );
$this->assertArrayHasKey( 'name', $data );
$this->assertArrayHasKey( 'sku', $data );
$this->assertArrayHasKey( 'permalink', $data );
$this->assertArrayHasKey( 'images', $data );
$this->assertArrayHasKey( 'totals', $data );
$this->assertArrayHasKey( 'variation', $data );
$this->assertArrayHasKey( 'item_data', $data );
$this->assertArrayHasKey( 'low_stock_remaining', $data );
$this->assertArrayHasKey( 'backorders_allowed', $data );
$this->assertArrayHasKey( 'show_backorder_badge', $data );
$this->assertArrayHasKey( 'short_description', $data );
Stop hidden products from being linked in cart and checkout blocks (https://github.com/woocommerce/woocommerce-blocks/pull/3415) * Add catalog_visibility to CartItemSchema.php This is used to get whether the product is visible in the catalogue, visible in the shop only, visible in search results only, or visible everywhere. We need to know this so we can pass it to the ProductImage and ProductName components. * Remove links from CartLineItemRow if not visible in catalogue Added catalog_visibility to lineItems prop, and when the product is not visible in the catalogue do not wrap product image in a link. Also pass down the hasLink prop to ProductName. * Add hasLink prop to ProductName When this prop is false we should not output the link around the product name. This is for when the product is hidden from the catalogue but we still want to show its name somewhere. * Add tests and storybook for ProductName * Add catalog_visibility check to OrderSummaryItem When the catalogue visibility of a product is set to hidden or search, then the product name in the checkout sidebar should not be hyperlinked. * Reverse logic for hiding link on product image & disabling link on name Following a point from @budzanowski we do not need the hasLink prop, making use of disabled is probably a better idea. * Remove tabindex from a in ProductName & output span if name is disabled This change removes the need to pass a tabindex to the a in ProductName. This is because a disabled ProductName will now never output an a tag. When the ProductName is disabled a span is output instead, which has no tabindex by default. This change also reverses the logic to decide whether the a or span should be output so as to make the code more readable and flow better. * Update storybook and tests/snapshots for ProductName
2020-11-23 13:03:08 +00:00
$this->assertArrayHasKey( 'catalog_visibility', $data );
}
/**
* Test schema matches responses.
*
* Tests schema of both products in cart to cover as much schema as possible.
*/
public function test_schema_matches_response() {
$routes = new \Automattic\WooCommerce\Blocks\StoreApi\RoutesController( new \Automattic\WooCommerce\Blocks\StoreApi\SchemaController( $this->mock_extend ) );
$controller = $routes->get( 'cart-items' );
$schema = $controller->get_item_schema();
$cart = wc()->cart->get_cart();
$validate = new ValidateSchema( $schema );
// Simple product.
$response = $controller->prepare_item_for_response( current( $cart ), new \WP_REST_Request() );
$diff = $validate->get_diff_from_object( $response->get_data() );
$this->assertEmpty( $diff, print_r( $diff, true ) );
// Variable product.
$response = $controller->prepare_item_for_response( end( $cart ), new \WP_REST_Request() );
$diff = $validate->get_diff_from_object( $response->get_data() );
$this->assertEmpty( $diff, print_r( $diff, true ) );
}
}