woocommerce/plugins/woocommerce-blocks/tests/php/StoreApi/Utilities/CartController.php

70 lines
2.5 KiB
PHP
Raw Normal View History

Catch errors during cart validation (https://github.com/woocommerce/woocommerce-blocks/pull/3703) * Add new exceptions for out of stock scenarios These are needed to differentiate between the different stock validation errors, and so we can create the correct error message. * Catch new out of stock exceptions when checking the cart for errors This is so we can get the cart sent back to the client, if we don't catch these, then the route will just return a 500 error and crash. * Add ArrayUtils class This will contain methods used to operate on arrays that don't fit anywhere else. * Handle the case in Checkout where the error is already a WP_Error This will happen when the cart fails validation. * Handle StockAvailabilityException in AbstractRoute This will happen when an item or number of items in the cart are out of stock/insufficient stock. * Throw exceptions for each type of invalid stock in validate_cart_items This will allow us to create an error message for each type of violation to display to the user. * Display additional error notices returned by the API * Fix wording when throwing exceptions relating to stock * Handle TooManyInCartException in CartController * Abstract the merging of cart, status, and additional data into new fn This allows us to simplify the way errors are returned from the API. The reason we have to add all of the data at once is because of how WP_Error works with the additional data, if there is already existing data in a WP_Error object, it gets moved into additional_data. By adding all of the data in one place, we stop this from happening. Also since we're only adding status and/or cart explicitly, it makes sense to just do it in one place. * Add get_route_error_response_from_object method This is so we can differentiate between a string and WP_Error object. * Remove unnecessary slashes from WP_Error instantiation * Add option to enclose each item in quotes in natural_language_join * Abstract adding error messages to error object into single function A lot of code was repeated, so doing this cuts down on that and ensures any changes only need to be made in one place. * Create new parent exception for each type of out of stock exception This is so we don't have to repeat code inside each different exception and we can simply inherit StockAvailabilityException. * Catch the generic StockAvailabilityException in get_cart_item_errors * No longer recalculate totals in validate function It is not needed, the totals are recalculated elsewhere. This call was superfluous. * Reduce nesting, and only throw exception if error object has errors * Improve comment on get_route_error_response_from_object method * Fix nesting when throwing the InvalidStockLevelsInCartException * Catch errors during cart validation * Add get_error_message_for_stock_exception_type function This will be used to get an error message depending on the type of extension, and whether the plural form, or singular form is needed. This abstraction is better because the code is used in more than one place in the API. * Use error message generation function instead of creating errors individually * Use specific error codes for each type of error & fix PHPDoc Now the stock_exceptions_to_wp_errors function will return an array of WP_Errors this is better as the client needs a distinct error code to display and replace notices. * No longer remove items from cart or modify quantity if there is an error * Return the WP_Error from RouteException or all Stock WP_Errors * Fix error in PHPDoc * No longer necessary to add get_cart_item_errors into an array This is because the method always returns an array now. * Rename variables in get_cart_item_errors to be more descriptive * Improve PHPDoc on get_cart_item_errors * Replace underscores with hyphens in error code * Only return WP_Errors that have an actual error in them * Add unit test for ensure the cart errors relating to stock are handled * Fix typo in comment * Use optional chaining to add errors to cart
2021-02-15 14:03:04 +00:00
<?php
/**
* OrderController Tests.
*/
namespace Automattic\WooCommerce\Blocks\Tests\StoreApi\Utilities;
use Automattic\WooCommerce\Blocks\StoreApi\Utilities\CartController;
use PHPUnit\Framework\TestCase;
use \WC_Helper_Product as ProductHelper;
class OrderControllerTests extends TestCase {
public function test_get_cart_item_errors() {
$class = new CartController();
// This product will simply be in/out of stock.
$out_of_stock_product = ProductHelper::create_simple_product();
$out_of_stock_product_key = wc()->cart->add_to_cart( $out_of_stock_product->get_id(), 2 );
$out_of_stock_in_cart = wc()->cart->get_cart_item( $out_of_stock_product_key )['data'];
// This product will have exact levels of stock known
$partially_out_of_stock_product = ProductHelper::create_simple_product();
$partially_out_of_stock_key = wc()->cart->add_to_cart( $partially_out_of_stock_product->get_id(), 4 );
$partially_out_of_stock_in_cart = wc()->cart->get_cart_item( $partially_out_of_stock_key )['data'];
// This product will have exact levels of stock known
$too_many_in_cart_product = ProductHelper::create_simple_product();
$too_many_in_cart_product_key = wc()->cart->add_to_cart( $too_many_in_cart_product->get_id(), 4 );
$too_many_in_cart_in_cart = wc()->cart->get_cart_item( $too_many_in_cart_product_key )['data'];
$out_of_stock_in_cart->set_stock_status( 'outofstock' );
$partially_out_of_stock_in_cart->set_manage_stock( true );
$partially_out_of_stock_in_cart->set_stock_quantity( 2 );
$too_many_in_cart_in_cart->set_sold_individually( true );
// This product will not be purchasable
$not_purchasable_product = ProductHelper::create_simple_product();
wc()->cart->add_to_cart( $not_purchasable_product->get_id(), 2 );
// This function will force the $product->is_purchasable() function to return false for our $not_purchasable_product
add_filter( 'woocommerce_is_purchasable', function( $is_purchasable, $product ) use ( $not_purchasable_product ) {
if ( $product->get_id() === $not_purchasable_product->get_id() ) {
return false;
}
return true;
}, 10, 2 );
$errors = array_map(
function( $error ) {
return $error->get_error_code();
},
$class->get_cart_item_errors()
);
$expected_errors = [
'woocommerce-blocks-product-partially-out-of-stock',
'woocommerce-blocks-product-out-of-stock',
'woocommerce-blocks-product-not-purchasable',
'woocommerce-blocks-too-many-of-product-in-cart',
];
foreach( $expected_errors as $expected_error ) {
$this->assertContains( $expected_error, $errors );
}
}
}