diff --git a/UPGRADE-API-1.13.md b/UPGRADE-API-1.13.md index 7c93e1a2acf..cf1335afbf3 100644 --- a/UPGRADE-API-1.13.md +++ b/UPGRADE-API-1.13.md @@ -1,5 +1,41 @@ # UPGRADE FROM `v1.12.x` TO `v1.13.0` +1. The signature of constructor of 'Sylius\Bundle\ApiBundle\Command\Cart\ChangeItemQuantityInCart' command changed: + +````diff + public function __construct( +- public int $quantity, ++ public ?int $quantity, + ) { + } +```` + +1. The constructor signature of 'Sylius\Bundle\ApiBundle\Command\Cart\AddItemToCart' changed: + +````diff + public function __construct( +- public string $productCode, ++ public ?string $productCode, +- public int $quantity, ++ public ?int $quantity, + ) { + } +```` + +1. The constructor signature of `Sylius\Bundle\ApiBundle\Command\Catalog\AddProductReview` changed: + +````diff + public function __construct( + public ?string $title, + public ?int $rating, + public ?string $comment, +- public string $productCode, ++ public ?string $productCode, + public ?string $email = null, + ) { + } +```` + 1. The item operation paths for ProductVariantTranslation resource changed: - `GET /admin/product-variant-translation/{id}` -> `GET /admin/product-variant-translations/{id}` diff --git a/src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php b/src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php index 2eef494cf77..65b0e211bc9 100644 --- a/src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php @@ -1052,7 +1052,7 @@ public function iShouldBeInformedThatProductVariantDoesNotExist(ProductVariantIn { Assert::true($this->isViolationWithMessageInResponse( $this->client->getLastResponse(), - sprintf('The product variant with %s does not exist.', $productVariant->getCode()), + sprintf('The product variant %s does not exist.', $productVariant->getCode()), )); } @@ -1063,7 +1063,7 @@ public function iShouldBeInformedThatProductVariantWithCodeDoesNotExist(string $ { Assert::true($this->isViolationWithMessageInResponse( $this->client->getLastResponse(), - sprintf('The product variant with %s does not exist.', $code), + sprintf('The product variant %s does not exist.', $code), )); } diff --git a/src/Sylius/Bundle/ApiBundle/Command/Account/ChangePaymentMethod.php b/src/Sylius/Bundle/ApiBundle/Command/Account/ChangePaymentMethod.php index 610120cc2ef..8b3b7b3fd46 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/Account/ChangePaymentMethod.php +++ b/src/Sylius/Bundle/ApiBundle/Command/Account/ChangePaymentMethod.php @@ -30,16 +30,8 @@ class ChangePaymentMethod implements OrderTokenValueAwareInterface, SubresourceI */ public $paymentId; - /** - * @psalm-immutable - * - * @var string - */ - public $paymentMethodCode; - - public function __construct(string $paymentMethodCode) + public function __construct(public string $paymentMethodCode) { - $this->paymentMethodCode = $paymentMethodCode; } public function getOrderTokenValue(): ?string diff --git a/src/Sylius/Bundle/ApiBundle/Command/Account/ChangeShopUserPassword.php b/src/Sylius/Bundle/ApiBundle/Command/Account/ChangeShopUserPassword.php index 4758fbda690..76a9b42ff99 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/Account/ChangeShopUserPassword.php +++ b/src/Sylius/Bundle/ApiBundle/Command/Account/ChangeShopUserPassword.php @@ -21,32 +21,8 @@ class ChangeShopUserPassword implements ShopUserIdAwareInterface /** @var mixed|null */ public $shopUserId; - /** - * @psalm-immutable - * - * @var string|null - */ - public $newPassword; - - /** - * @psalm-immutable - * - * @var string|null - */ - public $confirmNewPassword; - - /** - * @psalm-immutable - * - * @var string|null - */ - public $currentPassword; - - public function __construct(?string $newPassword, ?string $confirmNewPassword, ?string $currentPassword) + public function __construct(public ?string $newPassword, public ?string $confirmNewPassword, public ?string $currentPassword) { - $this->newPassword = $newPassword; - $this->confirmNewPassword = $confirmNewPassword; - $this->currentPassword = $currentPassword; } public function getShopUserId() diff --git a/src/Sylius/Bundle/ApiBundle/Command/Cart/AddItemToCart.php b/src/Sylius/Bundle/ApiBundle/Command/Cart/AddItemToCart.php index 71670241f91..52954b9ca5c 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/Cart/AddItemToCart.php +++ b/src/Sylius/Bundle/ApiBundle/Command/Cart/AddItemToCart.php @@ -22,24 +22,8 @@ class AddItemToCart implements OrderTokenValueAwareInterface, IriToIdentifierCon /** @var string|null */ public $orderTokenValue; - /** - * @psalm-immutable - * - * @var string - */ - public $productVariantCode; - - /** - * @psalm-immutable - * - * @var int - */ - public $quantity; - - public function __construct(string $productVariantCode, int $quantity) + public function __construct(public ?string $productVariantCode, public ?int $quantity) { - $this->productVariantCode = $productVariantCode; - $this->quantity = $quantity; } public static function createFromData(string $tokenValue, string $productVariantCode, int $quantity): self diff --git a/src/Sylius/Bundle/ApiBundle/Command/Cart/BlameCart.php b/src/Sylius/Bundle/ApiBundle/Command/Cart/BlameCart.php index bd4cea3b59b..1b1e52f6ea3 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/Cart/BlameCart.php +++ b/src/Sylius/Bundle/ApiBundle/Command/Cart/BlameCart.php @@ -16,23 +16,7 @@ /** @experimental */ class BlameCart { - /** - * @psalm-immutable - * - * @var string - */ - public $shopUserEmail; - - /** - * @psalm-immutable - * - * @var string - */ - public $orderTokenValue; - - public function __construct(string $shopUserEmail, string $orderTokenValue) + public function __construct(public string $shopUserEmail, public string $orderTokenValue) { - $this->shopUserEmail = $shopUserEmail; - $this->orderTokenValue = $orderTokenValue; } } diff --git a/src/Sylius/Bundle/ApiBundle/Command/Cart/ChangeItemQuantityInCart.php b/src/Sylius/Bundle/ApiBundle/Command/Cart/ChangeItemQuantityInCart.php index 3ee1a338e50..0ac9ba88898 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/Cart/ChangeItemQuantityInCart.php +++ b/src/Sylius/Bundle/ApiBundle/Command/Cart/ChangeItemQuantityInCart.php @@ -25,16 +25,8 @@ class ChangeItemQuantityInCart implements OrderTokenValueAwareInterface, Subreso /** @var string|null */ public $orderItemId; - /** - * @psalm-immutable - * - * @var int - */ - public $quantity; - - public function __construct(int $quantity) + public function __construct(public ?int $quantity) { - $this->quantity = $quantity; } public static function createFromData(string $tokenValue, string $orderItemId, int $quantity): self diff --git a/src/Sylius/Bundle/ApiBundle/Command/Cart/PickupCart.php b/src/Sylius/Bundle/ApiBundle/Command/Cart/PickupCart.php index 1a08b89695a..f4618b0afc8 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/Cart/PickupCart.php +++ b/src/Sylius/Bundle/ApiBundle/Command/Cart/PickupCart.php @@ -20,13 +20,6 @@ /** @experimental */ class PickupCart implements ChannelCodeAwareInterface, CustomerEmailAwareInterface, LocaleCodeAwareInterface { - /** - * @psalm-immutable - * - * @var string|null - */ - public $tokenValue; - /** @var string|null */ public $localeCode; @@ -36,9 +29,8 @@ class PickupCart implements ChannelCodeAwareInterface, CustomerEmailAwareInterfa /** @var string|null */ public $email; - public function __construct(?string $tokenValue = null) + public function __construct(public ?string $tokenValue = null) { - $this->tokenValue = $tokenValue; } public function getChannelCode(): ?string diff --git a/src/Sylius/Bundle/ApiBundle/Command/Cart/RemoveItemFromCart.php b/src/Sylius/Bundle/ApiBundle/Command/Cart/RemoveItemFromCart.php index c359baf5ab7..c7004a62345 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/Cart/RemoveItemFromCart.php +++ b/src/Sylius/Bundle/ApiBundle/Command/Cart/RemoveItemFromCart.php @@ -18,20 +18,8 @@ /** @experimental */ class RemoveItemFromCart implements OrderTokenValueAwareInterface { - /** @var string|null */ - public $orderTokenValue; - - /** - * @psalm-immutable - * - * @var string - */ - public $itemId; - - public function __construct(?string $orderTokenValue, string $itemId) + public function __construct(public ?string $orderTokenValue, public string $itemId) { - $this->orderTokenValue = $orderTokenValue; - $this->itemId = $itemId; } public static function removeFromData(string $tokenValue, string $orderItemId): self diff --git a/src/Sylius/Bundle/ApiBundle/Command/Catalog/AddProductReview.php b/src/Sylius/Bundle/ApiBundle/Command/Catalog/AddProductReview.php index 52af00ce339..387f8fb75ef 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/Catalog/AddProductReview.php +++ b/src/Sylius/Bundle/ApiBundle/Command/Catalog/AddProductReview.php @@ -19,53 +19,13 @@ /** @experimental */ class AddProductReview implements IriToIdentifierConversionAwareInterface, CustomerEmailAwareInterface { - /** - * @psalm-immutable - * - * @var string|null - */ - public $title; - - /** - * @psalm-immutable - * - * @var int|null - */ - public $rating; - - /** - * @psalm-immutable - * - * @var string|null - */ - public $comment; - - /** - * @psalm-immutable - * - * @var string - */ - public $productCode; - - /** - * @psalm-immutable - * - * @var string|null - */ - public $email; - public function __construct( - ?string $title, - ?int $rating, - ?string $comment, - string $productCode, - ?string $email = null, + public ?string $title, + public ?int $rating, + public ?string $comment, + public ?string $productCode, + public ?string $email = null, ) { - $this->title = $title; - $this->rating = $rating; - $this->comment = $comment; - $this->productCode = $productCode; - $this->email = $email; } public function getEmail(): ?string diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/Catalog/AddProductReviewHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/Catalog/AddProductReviewHandler.php index 67f588b9030..6bd6ab893fd 100644 --- a/src/Sylius/Bundle/ApiBundle/CommandHandler/Catalog/AddProductReviewHandler.php +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/Catalog/AddProductReviewHandler.php @@ -14,6 +14,7 @@ namespace Sylius\Bundle\ApiBundle\CommandHandler\Catalog; use Sylius\Bundle\ApiBundle\Command\Catalog\AddProductReview; +use Sylius\Bundle\ApiBundle\Exception\ProductNotFoundException; use Sylius\Bundle\CoreBundle\Resolver\CustomerResolverInterface; use Sylius\Component\Core\Model\CustomerInterface; use Sylius\Component\Core\Model\ProductInterface; @@ -21,6 +22,7 @@ use Sylius\Component\Resource\Factory\FactoryInterface; use Sylius\Component\Resource\Repository\RepositoryInterface; use Sylius\Component\Review\Model\ReviewInterface; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Messenger\Handler\MessageHandlerInterface; /** @experimental */ @@ -36,9 +38,13 @@ public function __construct( public function __invoke(AddProductReview $addProductReview): ReviewInterface { - /** @var ProductInterface $product */ + /** @var ProductInterface|null $product */ $product = $this->productRepository->findOneByCode($addProductReview->productCode); + if ($product === null) { + throw new ProductNotFoundException(Response::HTTP_UNPROCESSABLE_ENTITY); + } + /** @var string|null $email */ $email = $addProductReview->getEmail(); diff --git a/src/Sylius/Bundle/ApiBundle/Exception/ProductNotFoundException.php b/src/Sylius/Bundle/ApiBundle/Exception/ProductNotFoundException.php new file mode 100644 index 00000000000..6d25db789bb --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Exception/ProductNotFoundException.php @@ -0,0 +1,26 @@ +sylius + + + + + + + + + + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/validation/AddProductReview.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/validation/AddProductReview.xml index 528ca0871c6..92285bd629c 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/validation/AddProductReview.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/validation/AddProductReview.xml @@ -52,6 +52,14 @@ + + + + + + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ChangeItemQuantityInCart.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ChangeItemQuantityInCart.xml index 5eaaab51fb6..e3b4dacc803 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ChangeItemQuantityInCart.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ChangeItemQuantityInCart.xml @@ -24,6 +24,10 @@ + + + + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/translations/validators.en.yaml b/src/Sylius/Bundle/ApiBundle/Resources/translations/validators.en.yaml index a20959fa6e7..53e8897d5b2 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/translations/validators.en.yaml +++ b/src/Sylius/Bundle/ApiBundle/Resources/translations/validators.en.yaml @@ -19,7 +19,7 @@ sylius: product: not_exist: 'The product %productName% does not exist.' product_variant: - not_exist: 'The product variant with %productVariantCode% does not exist.' + not_exist: 'The product variant %productVariantCode% does not exist.' not_longer_available: 'The product variant with name %productVariantName% does not exist.' not_sufficient: 'The product variant with %productVariantCode% code does not have sufficient stock.' product_variant_with_name_not_sufficient: 'The product variant with %productVariantName% name does not have sufficient stock.' diff --git a/src/Sylius/Bundle/ApiBundle/Validator/Constraints/AddingEligibleProductVariantToCartValidator.php b/src/Sylius/Bundle/ApiBundle/Validator/Constraints/AddingEligibleProductVariantToCartValidator.php index c4edeade03b..9d43e13cbe1 100644 --- a/src/Sylius/Bundle/ApiBundle/Validator/Constraints/AddingEligibleProductVariantToCartValidator.php +++ b/src/Sylius/Bundle/ApiBundle/Validator/Constraints/AddingEligibleProductVariantToCartValidator.php @@ -41,6 +41,10 @@ public function validate($value, Constraint $constraint) /** @var AddingEligibleProductVariantToCart $constraint */ Assert::isInstanceOf($constraint, AddingEligibleProductVariantToCart::class); + if ($value->productVariantCode === null) { + return; + } + /** @var ProductVariantInterface|null $productVariant */ $productVariant = $this->productVariantRepository->findOneBy(['code' => $value->productVariantCode]); diff --git a/src/Sylius/Bundle/ApiBundle/Validator/Constraints/ChangedItemQuantityInCartValidator.php b/src/Sylius/Bundle/ApiBundle/Validator/Constraints/ChangedItemQuantityInCartValidator.php index 980384e4495..0f5655279d9 100644 --- a/src/Sylius/Bundle/ApiBundle/Validator/Constraints/ChangedItemQuantityInCartValidator.php +++ b/src/Sylius/Bundle/ApiBundle/Validator/Constraints/ChangedItemQuantityInCartValidator.php @@ -40,6 +40,10 @@ public function validate($value, Constraint $constraint) /** @var ChangedItemQuantityInCart $constraint */ Assert::isInstanceOf($constraint, ChangedItemQuantityInCart::class); + if ($value->quantity === null) { + return; + } + /** @var OrderItemInterface|null $orderItem */ $orderItem = $this->orderItemRepository->findOneBy(['id' => $value->orderItemId]); Assert::notNull($orderItem); diff --git a/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Catalog/AddProductReviewHandlerSpec.php b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Catalog/AddProductReviewHandlerSpec.php index 02da3964c91..61be96ac045 100644 --- a/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Catalog/AddProductReviewHandlerSpec.php +++ b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Catalog/AddProductReviewHandlerSpec.php @@ -15,6 +15,7 @@ use PhpSpec\ObjectBehavior; use Sylius\Bundle\ApiBundle\Command\Catalog\AddProductReview; +use Sylius\Bundle\ApiBundle\Exception\ProductNotFoundException; use Sylius\Bundle\CoreBundle\Resolver\CustomerResolverInterface; use Sylius\Component\Core\Model\CustomerInterface; use Sylius\Component\Core\Model\ProductInterface; @@ -91,4 +92,21 @@ function it_throws_an_exception_if_email_has_not_been_found( ]) ; } + + function it_throws_an_exception_if_product_has_not_been_found(ProductRepositoryInterface $productRepository): void + { + $productRepository->findOneByCode('winter_cap')->willReturn(null); + + $this + ->shouldThrow(ProductNotFoundException::class) + ->during('__invoke', [ + new AddProductReview( + 'Good stuff', + 5, + 'Really good stuff', + 'winter_cap', + ), + ]) + ; + } } diff --git a/src/Sylius/Bundle/ApiBundle/spec/Validator/Constraints/AddingEligibleProductVariantToCartValidatorSpec.php b/src/Sylius/Bundle/ApiBundle/spec/Validator/Constraints/AddingEligibleProductVariantToCartValidatorSpec.php index 41068710b2b..4dd3e2e92a4 100644 --- a/src/Sylius/Bundle/ApiBundle/spec/Validator/Constraints/AddingEligibleProductVariantToCartValidatorSpec.php +++ b/src/Sylius/Bundle/ApiBundle/spec/Validator/Constraints/AddingEligibleProductVariantToCartValidatorSpec.php @@ -15,6 +15,7 @@ use Doctrine\Common\Collections\Collection; use PhpSpec\ObjectBehavior; +use Prophecy\Argument; use Sylius\Bundle\ApiBundle\Command\Cart\AddItemToCart; use Sylius\Bundle\ApiBundle\Command\Checkout\CompleteOrder; use Sylius\Bundle\ApiBundle\Validator\Constraints\AddingEligibleProductVariantToCart; @@ -135,6 +136,37 @@ function it_adds_violation_if_product_variant_is_disabled( ); } + function it_does_nothing_if_product_variant_is_not_provided( + ProductVariantRepositoryInterface $productVariantRepository, + OrderRepositoryInterface $orderRepository, + AvailabilityCheckerInterface $availabilityChecker, + AddItemToCart $addItemToCart, + ExecutionContextInterface $executionContext, + ProductInterface $product, + ProductVariantInterface $productVariant, + ): void { + $this->initialize($executionContext); + + $productVariantRepository->findOneBy(['code' => null])->shouldNotBeCalled(); + $productVariant->getProduct()->shouldNotBeCalled(); + $product->isEnabled()->shouldNotBeCalled(); + + $addItemToCart->getOrderTokenValue()->willReturn('TOKEN'); + $orderRepository->findCartByTokenValue('TOKEN')->shouldNotBeCalled(); + + $availabilityChecker->isStockSufficient($productVariant, 1)->shouldNotBeCalled(); + + $executionContext + ->addViolation(Argument::any()) + ->shouldNotBeCalled() + ; + + $this->validate( + new AddItemToCart(null, 1), + new AddingEligibleProductVariantToCart(), + ); + } + function it_adds_violation_if_product_variant_stock_is_not_sufficient_and_cart_has_same_units( ProductVariantRepositoryInterface $productVariantRepository, OrderRepositoryInterface $orderRepository, diff --git a/src/Sylius/Bundle/ApiBundle/spec/Validator/Constraints/ChangedItemQuantityInCartValidatorSpec.php b/src/Sylius/Bundle/ApiBundle/spec/Validator/Constraints/ChangedItemQuantityInCartValidatorSpec.php index dae9de3a778..a83976bb55f 100644 --- a/src/Sylius/Bundle/ApiBundle/spec/Validator/Constraints/ChangedItemQuantityInCartValidatorSpec.php +++ b/src/Sylius/Bundle/ApiBundle/spec/Validator/Constraints/ChangedItemQuantityInCartValidatorSpec.php @@ -14,6 +14,7 @@ namespace spec\Sylius\Bundle\ApiBundle\Validator\Constraints; use PhpSpec\ObjectBehavior; +use Prophecy\Argument; use Sylius\Bundle\ApiBundle\Command\Cart\ChangeItemQuantityInCart; use Sylius\Bundle\ApiBundle\Command\Checkout\CompleteOrder; use Sylius\Bundle\ApiBundle\Validator\Constraints\AddingEligibleProductVariantToCart; diff --git a/src/Sylius/Bundle/CoreBundle/Resources/translations/validators.en.yml b/src/Sylius/Bundle/CoreBundle/Resources/translations/validators.en.yml index 35b7f78cd89..1da5419edd1 100644 --- a/src/Sylius/Bundle/CoreBundle/Resources/translations/validators.en.yml +++ b/src/Sylius/Bundle/CoreBundle/Resources/translations/validators.en.yml @@ -125,6 +125,8 @@ sylius: review: author: not_blank: Please enter your email. + product: + not_blank: Please enter a product. rating: range: Review rating must be an integer in the range 1-5. not_in_range: Review rating must be between {{ min }} and {{ max }}. diff --git a/src/Sylius/Bundle/OrderBundle/Resources/translations/validators.en.yml b/src/Sylius/Bundle/OrderBundle/Resources/translations/validators.en.yml index b984f947d6b..c7ee1e52bb3 100644 --- a/src/Sylius/Bundle/OrderBundle/Resources/translations/validators.en.yml +++ b/src/Sylius/Bundle/OrderBundle/Resources/translations/validators.en.yml @@ -1,4 +1,10 @@ +# This file is part of the Sylius package. +# (c) Sylius Sp. z o.o. + sylius: order_item: + product_variant: + not_blank: The product variant has not been provided. quantity: min: Quantity of an order item cannot be lower than 1. + not_blank: The quantity has not been provided. diff --git a/tests/Api/Shop/OrdersTest.php b/tests/Api/Shop/OrdersTest.php index d440f7434f2..5f2cb8fc67f 100644 --- a/tests/Api/Shop/OrdersTest.php +++ b/tests/Api/Shop/OrdersTest.php @@ -477,4 +477,83 @@ public function it_returns_unprocessable_entity_status_if_tries_to_remove_an_ite $this->assertResponseCode($this->client->getResponse(), Response::HTTP_UNPROCESSABLE_ENTITY); } + + /** @test */ + public function it_prevents_from_adding_an_item_to_the_cart_if_product_variant_is_missing(): void + { + $this->loadFixturesFromFiles(['channel.yaml', 'cart.yaml']); + + $tokenValue = 'nAWw2jewpA'; + + /** @var MessageBusInterface $commandBus */ + $commandBus = self::getContainer()->get('sylius.command_bus'); + + $pickupCartCommand = new PickupCart($tokenValue); + $pickupCartCommand->setChannelCode('WEB'); + $commandBus->dispatch($pickupCartCommand); + + $this->client->request( + method: 'POST', + uri: sprintf('/api/v2/shop/orders/%s/items', $tokenValue), + server: self::CONTENT_TYPE_HEADER, + content: json_encode([ + 'quantity' => 3, + ], JSON_THROW_ON_ERROR), + ); + $response = $this->client->getResponse(); + + $this->assertResponseCode($response, Response::HTTP_UNPROCESSABLE_ENTITY); + } + + /** @test */ + public function it_prevents_from_adding_an_item_to_the_cart_if_quantity_is_missing(): void + { + $this->loadFixturesFromFiles(['channel.yaml', 'cart.yaml']); + + $tokenValue = 'nAWw2jewpA'; + + /** @var MessageBusInterface $commandBus */ + $commandBus = self::getContainer()->get('sylius.command_bus'); + + $pickupCartCommand = new PickupCart($tokenValue); + $pickupCartCommand->setChannelCode('WEB'); + $commandBus->dispatch($pickupCartCommand); + + $this->client->request( + method: 'POST', + uri: sprintf('/api/v2/shop/orders/%s/items', $tokenValue), + server: self::CONTENT_TYPE_HEADER, + content: json_encode([ + 'productVariant' => 'MUG_BLUE', + ], JSON_THROW_ON_ERROR), + ); + $response = $this->client->getResponse(); + + $this->assertResponseCode($response, Response::HTTP_UNPROCESSABLE_ENTITY); + } + + /** @test */ + public function it_prevents_from_changing_an_item_quantity_if_quantity_is_missing(): void + { + $this->loadFixturesFromFiles(['channel.yaml', 'cart.yaml']); + + $tokenValue = 'nAWw2jewpA'; + + /** @var MessageBusInterface $commandBus */ + $commandBus = self::getContainer()->get('sylius.command_bus'); + + $pickupCartCommand = new PickupCart($tokenValue); + $pickupCartCommand->setChannelCode('WEB'); + $commandBus->dispatch($pickupCartCommand); + + $this->client->request( + method: 'PATCH', + uri: sprintf('/api/v2/shop/orders/%s/items/%s', $tokenValue, 1), + server: self::PATCH_CONTENT_TYPE_HEADER, + content: json_encode([]), + ); + $response = $this->client->getResponse(); + + $this->assertResponseCode($response, Response::HTTP_UNPROCESSABLE_ENTITY); + } } diff --git a/tests/Api/Shop/ProductReviewsTest.php b/tests/Api/Shop/ProductReviewsTest.php index 342a96fbced..afac1a7eff1 100644 --- a/tests/Api/Shop/ProductReviewsTest.php +++ b/tests/Api/Shop/ProductReviewsTest.php @@ -80,4 +80,45 @@ public function it_creates_a_product_review(): void Response::HTTP_CREATED, ); } + + /** @test */ + public function it_prevents_from_creating_a_product_review_with_non_existing_product(): void + { + $this->loadFixturesFromFiles(['product/product_variant.yaml']); + + $this->client->request( + method: 'POST', + uri: '/api/v2/shop/product-reviews', + server: self::CONTENT_TYPE_HEADER, + content: json_encode([ + 'title' => 'Greatest product!', + 'rating' => 3, + 'comment' => 'I\'ve never bought anything better.', + 'email' => 'test@test.com', + 'product' => '/api/v2/shop/products/NON-EXISTING-PRODUCT', + ], JSON_THROW_ON_ERROR), + ); + + $this->assertResponseCode($this->client->getResponse(), Response::HTTP_UNPROCESSABLE_ENTITY); + } + + /** @test */ + public function it_prevents_from_creating_a_product_review_if_no_product_provided(): void + { + $this->loadFixturesFromFiles(['product/product_variant.yaml']); + + $this->client->request( + method: 'POST', + uri: '/api/v2/shop/product-reviews', + server: self::CONTENT_TYPE_HEADER, + content: json_encode([ + 'title' => 'Greatest product!', + 'rating' => 3, + 'comment' => 'I\'ve never bought anything better.', + 'email' => 'test@test.com', + ], JSON_THROW_ON_ERROR), + ); + + $this->assertResponseCode($this->client->getResponse(), Response::HTTP_UNPROCESSABLE_ENTITY); + } }