mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
[API] Adding inexistent product variant
This commit is contained in:
parent
3b9cbb5ee8
commit
f5f16454f7
8 changed files with 261 additions and 9 deletions
|
|
@ -0,0 +1,18 @@
|
|||
@checkout
|
||||
Feature: Preventing adding to cart inexistent product variant
|
||||
In order to have correct products in cart when adding them
|
||||
As a Customer
|
||||
I want to have the added product variants validated
|
||||
|
||||
Background:
|
||||
Given the store operates on a single channel in "United States"
|
||||
And the store has a "Super Cool T-Shirt" configurable product
|
||||
And this product has "Small", "Medium" and "Large" variants
|
||||
And I am a logged in customer
|
||||
|
||||
@api
|
||||
Scenario: Preventing customer from adding inexistent variant
|
||||
Given the "Large" product variant is disabled
|
||||
When I pick up my cart
|
||||
And I try to add product "Super Cool T-Shirt" with variant code "Magic"
|
||||
Then I should be informed that product variant with code "Magic" does not exist
|
||||
|
|
@ -804,6 +804,17 @@ final class CheckoutContext implements Context
|
|||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should be informed that product variant with code :code does not exist
|
||||
*/
|
||||
public function iShouldBeInformedThatProductVariantWithCodeDoesNotExist(string $code): void
|
||||
{
|
||||
Assert::true($this->isViolationWithMessageInResponse(
|
||||
$this->ordersClient->getLastResponse(),
|
||||
sprintf('The product variant with %s does not exist.', $code)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should not see the thank you page
|
||||
*/
|
||||
|
|
@ -867,6 +878,15 @@ final class CheckoutContext implements Context
|
|||
$this->putVariantToCart($productVariant, $tokenValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^I try to add (product "[^"]+") with variant code "([^"]+)"$/
|
||||
*/
|
||||
public function iTryToAddProductVariantWithCode(ProductInterface $product, string $code): void
|
||||
{
|
||||
$tokenValue = $this->getCartTokenValue();
|
||||
$this->putProductWithVariantCode($product, $tokenValue, $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^I try to remove (product "[^"]+") from the (cart)$/
|
||||
*/
|
||||
|
|
@ -1150,6 +1170,30 @@ final class CheckoutContext implements Context
|
|||
$this->sharedStorage->set('response', $this->ordersClient->executeCustomRequest($request));
|
||||
}
|
||||
|
||||
private function putProductWithVariantCode(ProductInterface $product, string $tokenValue, string $code): void
|
||||
{
|
||||
$request = $this->preparePutProductRequest($tokenValue);
|
||||
|
||||
$request->setContent([
|
||||
'productCode' => $product->getCode(),
|
||||
'productVariantCode' => $code,
|
||||
'quantity' => 1,
|
||||
]);
|
||||
|
||||
$this->sharedStorage->set('response', $this->ordersClient->executeCustomRequest($request));
|
||||
}
|
||||
|
||||
private function preparePutProductRequest(string $tokenValue): Request
|
||||
{
|
||||
return Request::customItemAction(
|
||||
'shop',
|
||||
'orders',
|
||||
$tokenValue,
|
||||
HTTPRequest::METHOD_PATCH,
|
||||
'items'
|
||||
);
|
||||
}
|
||||
|
||||
private function removeOrderItemFromCart(int $orderItemId, string $tokenValue): void
|
||||
{
|
||||
$request = Request::customItemAction(
|
||||
|
|
|
|||
|
|
@ -49,6 +49,11 @@
|
|||
<tag name="validator.constraint_validator" alias="sylius_api_validator_product_or_variant_enabled" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.api.validator.product_variant_exist" class="Sylius\Bundle\ApiBundle\Validator\Constraints\ProductVariantExistValidator">
|
||||
<argument type="service" id="sylius.repository.product_variant" />
|
||||
<tag name="validator.constraint_validator" alias="sylius_api_validator_product_variant_exist" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.api.validator.payment_method_eligibility" class="Sylius\Bundle\ApiBundle\Validator\Constraints\OrderPaymentMethodEligibilityValidator">
|
||||
<argument type="service" id="sylius.repository.order" />
|
||||
<tag name="validator.constraint_validator" alias="sylius_api_order_payment_method_eligibility" />
|
||||
|
|
|
|||
|
|
@ -13,15 +13,22 @@
|
|||
|
||||
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/services/constraint-mapping-1.0.xsd">
|
||||
<class name="Sylius\Bundle\ApiBundle\Command\Cart\AddItemToCart">
|
||||
<constraint name="Sylius\Bundle\ApiBundle\Validator\Constraints\ProductOrVariantEnabled">
|
||||
<option name="groups">
|
||||
<value>sylius</value>
|
||||
</option>
|
||||
</constraint>
|
||||
<constraint name="Sylius\Bundle\ApiBundle\Validator\Constraints\ProductAvailableInChannel">
|
||||
<option name="groups">
|
||||
<value>sylius</value>
|
||||
</option>
|
||||
<constraint name="Sequentially">
|
||||
<constraint name="Sylius\Bundle\ApiBundle\Validator\Constraints\ProductVariantExist">
|
||||
<option name="groups">
|
||||
<value>sylius</value>
|
||||
</option>
|
||||
</constraint>
|
||||
<constraint name="Sylius\Bundle\ApiBundle\Validator\Constraints\ProductOrVariantEnabled">
|
||||
<option name="groups">
|
||||
<value>sylius</value>
|
||||
</option>
|
||||
</constraint>
|
||||
<constraint name="Sylius\Bundle\ApiBundle\Validator\Constraints\ProductAvailableInChannel">
|
||||
<option name="groups">
|
||||
<value>sylius</value>
|
||||
</option>
|
||||
</constraint>
|
||||
</constraint>
|
||||
<property name="quantity">
|
||||
<constraint name="Range">
|
||||
|
|
|
|||
|
|
@ -4,5 +4,7 @@ sylius:
|
|||
product_does_not_exist: 'The product %productName% does not exist.'
|
||||
product:
|
||||
not_exist: 'The product %productName% does not exist.'
|
||||
product_variant:
|
||||
not_exist: 'The product variant with %productVariantCode% does not exist.'
|
||||
shipment:
|
||||
shipped: 'You cannot ship a shipment that was shipped before.'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\Validator\Constraints;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductVariantExist extends Constraint
|
||||
{
|
||||
/** @var string */
|
||||
public $message = 'sylius.product_variant.not_exist';
|
||||
|
||||
public function validatedBy(): string
|
||||
{
|
||||
return 'sylius_api_validator_product_variant_exist';
|
||||
}
|
||||
|
||||
public function getTargets(): string
|
||||
{
|
||||
return self::CLASS_CONSTRAINT;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\Validator\Constraints;
|
||||
|
||||
use Sylius\Bundle\ApiBundle\Command\Cart\AddItemToCart;
|
||||
use Sylius\Component\Core\Model\ProductVariantInterface;
|
||||
use Sylius\Component\Product\Repository\ProductVariantRepositoryInterface;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductVariantExistValidator extends ConstraintValidator
|
||||
{
|
||||
/** @var ProductVariantRepositoryInterface */
|
||||
private $productVariantRepository;
|
||||
|
||||
public function __construct(ProductVariantRepositoryInterface $productVariantRepository)
|
||||
{
|
||||
$this->productVariantRepository = $productVariantRepository;
|
||||
}
|
||||
|
||||
public function validate($value, Constraint $constraint): void
|
||||
{
|
||||
Assert::isInstanceOf($value, AddItemToCart::class);
|
||||
|
||||
/** @var ProductVariantExist $constraint */
|
||||
Assert::isInstanceOf($constraint, ProductVariantExist::class);
|
||||
|
||||
/** @var ProductVariantInterface|null $productVariant */
|
||||
if ($this->productVariantRepository->findOneBy(['code' =>$value->productVariantCode]) === null) {
|
||||
$this->context->addViolation(
|
||||
$constraint->message,
|
||||
['%productVariantCode%' => $value->productVariantCode]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace spec\Sylius\Bundle\ApiBundle\Validator\Constraints;
|
||||
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Bundle\ApiBundle\Command\Cart\AddItemToCart;
|
||||
use Sylius\Bundle\ApiBundle\Command\Checkout\CompleteOrder;
|
||||
use Sylius\Bundle\ApiBundle\Validator\Constraints\ProductVariantExist;
|
||||
use Sylius\Component\Core\Model\ProductVariantInterface;
|
||||
use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidatorInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
final class ProductVariantExistValidatorSpec extends ObjectBehavior
|
||||
{
|
||||
function let(ProductVariantRepositoryInterface $productVariantRepository): void
|
||||
{
|
||||
$this->beConstructedWith($productVariantRepository);
|
||||
}
|
||||
|
||||
function it_is_a_constraint_validator(): void
|
||||
{
|
||||
$this->shouldImplement(ConstraintValidatorInterface::class);
|
||||
}
|
||||
|
||||
function it_throws_an_exception_if_value_is_not_an_instance_of_add_item_to_cart_command(): void
|
||||
{
|
||||
$this
|
||||
->shouldThrow(\InvalidArgumentException::class)
|
||||
->during('validate', [new CompleteOrder(), new ProductVariantExist()]);
|
||||
}
|
||||
|
||||
function it_throws_an_exception_if_constraint_is_not_an_instance_of_product_variant_exist(): void
|
||||
{
|
||||
$this
|
||||
->shouldThrow(\InvalidArgumentException::class)
|
||||
->during('validate', [new AddItemToCart('productCode', 'productVariantCode', 1), new class() extends Constraint {
|
||||
}])
|
||||
;
|
||||
}
|
||||
|
||||
function it_adds_violation_if_product_variant_does_not_exist(
|
||||
ProductVariantRepositoryInterface $productVariantRepository,
|
||||
ExecutionContextInterface $executionContext
|
||||
): void {
|
||||
$this->initialize($executionContext);
|
||||
|
||||
$value = new AddItemToCart('productCode', 'productVariantCode', 1);
|
||||
$constraint = new ProductVariantExist();
|
||||
$constraint->message = 'message';
|
||||
|
||||
$productVariantRepository->findOneBy(['code' => 'productVariantCode'])->willReturn(null);
|
||||
|
||||
$executionContext
|
||||
->addViolation('message', ['%productVariantCode%' => 'productVariantCode'])
|
||||
->shouldBeCalled()
|
||||
;
|
||||
|
||||
$this->validate($value, $constraint);
|
||||
}
|
||||
|
||||
function it_does_nothing_if_product_variant_does_exist(
|
||||
ProductVariantRepositoryInterface $productVariantRepository,
|
||||
ProductVariantInterface $productVariant,
|
||||
ExecutionContextInterface $executionContext
|
||||
): void {
|
||||
$this->initialize($executionContext);
|
||||
|
||||
$value = new AddItemToCart('productCode', 'productVariantCode', 1);
|
||||
$constraint = new ProductVariantExist();
|
||||
$constraint->message = 'message';
|
||||
|
||||
$productVariantRepository->findOneBy(['code' => 'productVariantCode'])->willReturn($productVariant);
|
||||
|
||||
$executionContext
|
||||
->addViolation('message', ['%productVariantCode%' => 'productVariantCode'])
|
||||
->shouldNotBeCalled()
|
||||
;
|
||||
|
||||
$this->validate($value, $constraint);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue