Skip to content

Commit

Permalink
moved adding new field to response and applied new scenario
Browse files Browse the repository at this point in the history
  • Loading branch information
arti0090 committed May 17, 2021
1 parent 7a905e8 commit 2c636cd
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ Feature: Inability to add a specific product to the cart when it is out of stock

Background:
Given the store operates on a single channel in "United States"
And the store has a product "T-shirt banana" priced at "$12.54"
And the store has a product "T-shirt banana"

@ui
@ui @api
Scenario: Not being able to add a product to the cart when it is out of stock
Given the product "T-shirt banana" is out of stock
When I check this product's details
Expand Down
15 changes: 15 additions & 0 deletions src/Sylius/Behat/Context/Api/Shop/CartContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,21 @@ public function iShouldHaveEmptyCart(string $tokenValue): void
Assert::same(count($items), 0, 'There should be an empty cart');
}

/**
* @Then I should be unable to add it to the cart
*/
public function iShouldBeUnableToAddItToTheCart(): void
{
/** @var ProductVariantInterface $productVariant */
$productVariant = $this->sharedStorage->get('productVariant');

$tokenValue = $this->pickupCart();
$this->putProductVariantToCart($productVariant, $tokenValue);

$response = $this->cartsClient->getLastResponse();
Assert::same($response->getStatusCode(), 422);
}

/**
* @Then /^(this product) should have ([^"]+) "([^"]+)"$/
*/
Expand Down
20 changes: 20 additions & 0 deletions src/Sylius/Behat/Context/Api/Shop/ProductContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Product\Model\ProductVariantInterface;
use Sylius\Component\Taxonomy\Model\TaxonInterface;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Webmozart\Assert\Assert;
Expand All @@ -30,6 +31,9 @@ final class ProductContext implements Context
/** @var ApiClientInterface */
private $client;

/** @var ApiClientInterface */
private $productVariantClient;

/** @var ResponseCheckerInterface */
private $responseChecker;

Expand All @@ -41,11 +45,13 @@ final class ProductContext implements Context

public function __construct(
ApiClientInterface $client,
ApiClientInterface $productVariantClient,
ResponseCheckerInterface $responseChecker,
SharedStorageInterface $sharedStorage,
IriConverterInterface $iriConverter
) {
$this->client = $client;
$this->productVariantClient = $productVariantClient;
$this->responseChecker = $responseChecker;
$this->sharedStorage = $sharedStorage;
$this->iriConverter = $iriConverter;
Expand All @@ -58,6 +64,7 @@ public function __construct(
public function iOpenProductPage(ProductInterface $product): void
{
$this->client->show($product->getCode());
$this->sharedStorage->set('productVariant', current($product->getVariants()->getValues()));
}

/**
Expand Down Expand Up @@ -107,6 +114,19 @@ public function iShouldSeeTheProduct(string $name): void
));
}

/**
* @Then I should see that it is out of stock
*/
public function iShouldSeeItIsOutOfStock(): void
{
/** @var ProductVariantInterface $productVariant */
$productVariant = $this->sharedStorage->get('productVariant');

$variantResponse = $this->productVariantClient->showByIri($this->iriConverter->getIriFromItem($productVariant));

Assert::false($this->responseChecker->getValue($variantResponse, 'inStock'));
}

/**
* @Then I should not see the product :name
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@

<service id="sylius.behat.context.api.shop.product" class="Sylius\Behat\Context\Api\Shop\ProductContext">
<argument type="service" id="sylius.behat.api_platform_client.shop.product" />
<argument type="service" id="sylius.behat.api_platform_client.shop.product_variant" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="sylius.behat.shared_storage" />
<argument type="service" id="api_platform.iri_converter" />
Expand Down
1 change: 1 addition & 0 deletions src/Sylius/Behat/Resources/config/suites.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ imports:
- suites/api/currency/managing_currencies.yml
- suites/api/currency/managing_exchange_rates.yml
- suites/api/homepage/viewing_products.yml
- suites/api/inventory/cart_inventory.yml
- suites/api/locale/managing_locales.yml
- suites/api/order/managing_orders.yml
- suites/api/payment/managing_payments.yml
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# This file is part of the Sylius package.
# (c) Paweł Jędrzejewski

default:
suites:
api_cart_inventory:
contexts:
- sylius.behat.context.hook.doctrine_orm

- sylius.behat.context.setup.channel
- sylius.behat.context.setup.product

- sylius.behat.context.transform.lexical
- sylius.behat.context.transform.product
- sylius.behat.context.transform.shared_storage

- sylius.behat.context.api.shop.cart
- sylius.behat.context.api.shop.product


filters:
tags: "@cart_inventory && @api"
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<service id="sylius.api.validator.adding_eligible_product_variant_to_cart" class="Sylius\Bundle\ApiBundle\Validator\Constraints\AddingEligibleProductVariantToCartValidator">
<argument type="service" id="sylius.repository.product_variant" />
<argument type="service" id="sylius.repository.order" />
<argument type="service" id="sylius.availability_checker" />
<tag name="validator.constraint_validator" alias="sylius_api_validator_adding_eligible_product_variant_to_cart" />
</service>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ sylius:
not_exist: 'The product %productName% does not exist.'
product_variant:
not_exist: 'The product variant with %productVariantCode% does not exist.'
not_sufficient: 'The product variant with %productVariantCode% does not have sufficient stock.'
shipment:
shipped: 'You cannot ship a shipment that was shipped before.'
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,15 @@ public function normalize($object, $format = null, array $context = [])
Assert::isInstanceOf($object, ProductVariantInterface::class);

$data = $this->objectNormalizer->normalize($object, $format, $context);

try {
$data['price'] = $this->priceCalculator->calculate($object, ['channel' => $this->channelContext->getChannel()]);
$data['inStock'] = $this->availabilityChecker->isStockAvailable($object);
} catch (ChannelNotFoundException $exception) {
unset($data['price']);
}

$data['inStock'] = $this->availabilityChecker->isStockAvailable($object);

return $data;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ final class AddingEligibleProductVariantToCart extends Constraint
/** @var string */
public $productVariantNotExistMessage = 'sylius.product_variant.not_exist';

/** @var string */
public $productVariantNotSufficient = 'sylius.product_variant.not_sufficient';

public function validatedBy(): string
{
return 'sylius_api_validator_adding_eligible_product_variant_to_cart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Inventory\Checker\AvailabilityCheckerInterface;
use Sylius\Component\Product\Repository\ProductVariantRepositoryInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
Expand All @@ -32,12 +33,17 @@ final class AddingEligibleProductVariantToCartValidator extends ConstraintValida
/** @var OrderRepositoryInterface */
private $orderRepository;

/** @var AvailabilityCheckerInterface */
private $availabilityChecker;

public function __construct(
ProductVariantRepositoryInterface $productVariantRepository,
OrderRepositoryInterface $orderRepository
OrderRepositoryInterface $orderRepository,
AvailabilityCheckerInterface $availabilityChecker
) {
$this->productVariantRepository = $productVariantRepository;
$this->orderRepository = $orderRepository;
$this->availabilityChecker = $availabilityChecker;
}

public function validate($value, Constraint $constraint)
Expand Down Expand Up @@ -79,6 +85,15 @@ public function validate($value, Constraint $constraint)
return;
}

if (!$this->availabilityChecker->isStockSufficient($productVariant, $value->quantity)) {
$this->context->addViolation(
$constraint->productVariantNotSufficient,
['%productVariantCode%' => $productVariant->getCode()]
);

return;
}

/** @var OrderInterface|null $cart */
$cart = $this->orderRepository->findCartByTokenValue($value->getOrderTokenValue());
Assert::notNull($cart);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
use Sylius\Component\Inventory\Checker\AvailabilityCheckerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidatorInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
Expand All @@ -31,9 +32,10 @@ final class AddingEligibleProductVariantToCartValidatorSpec extends ObjectBehavi
{
function let(
ProductVariantRepositoryInterface $productVariantRepository,
OrderRepositoryInterface $orderRepository
OrderRepositoryInterface $orderRepository,
AvailabilityCheckerInterface $availabilityChecker
): void {
$this->beConstructedWith($productVariantRepository, $orderRepository);
$this->beConstructedWith($productVariantRepository, $orderRepository, $availabilityChecker);
}

function it_is_a_constraint_validator(): void
Expand Down Expand Up @@ -129,14 +131,43 @@ function it_adds_violation_if_product_variant_is_disabled(
);
}

function it_adds_violation_if_product_variant_stock_is_not_sufficient(
ProductVariantRepositoryInterface $productVariantRepository,
ExecutionContextInterface $executionContext,
ProductVariantInterface $productVariant,
ProductInterface $product,
AvailabilityCheckerInterface $availabilityChecker
): void {
$this->initialize($executionContext);

$productVariantRepository->findOneBy(['code' => 'productVariantCode'])->willReturn($productVariant);
$productVariant->getCode()->willReturn('productVariantCode');
$productVariant->isEnabled()->willReturn(true);
$productVariant->getProduct()->willReturn($product);
$product->isEnabled()->willReturn(true);

$availabilityChecker->isStockSufficient($productVariant, 1)->willReturn(false);

$executionContext
->addViolation('sylius.product_variant.not_sufficient', ['%productVariantCode%' => 'productVariantCode'])
->shouldBeCalled()
;

$this->validate(
new AddItemToCart( 'productVariantCode', 1),
new AddingEligibleProductVariantToCart()
);
}

function it_adds_violation_if_product_is_not_available_in_channel(
ProductVariantRepositoryInterface $productVariantRepository,
OrderRepositoryInterface $orderRepository,
ExecutionContextInterface $executionContext,
ChannelInterface $channel,
ProductVariantInterface $productVariant,
ProductInterface $product,
OrderInterface $cart
OrderInterface $cart,
AvailabilityCheckerInterface $availabilityChecker
): void {
$this->initialize($executionContext);

Expand All @@ -149,6 +180,8 @@ function it_adds_violation_if_product_is_not_available_in_channel(
$productVariant->getProduct()->willReturn($product);

$product->isEnabled()->willReturn(true);
$availabilityChecker->isStockSufficient($productVariant, 1)->willReturn(true);

$product->hasChannel($channel)->willReturn(false);
$product->getName()->willReturn('PRODUCT NAME');

Expand All @@ -170,7 +203,8 @@ function it_does_nothing_if_product_and_variant_are_enabled_and_available_in_cha
ChannelInterface $channel,
ProductVariantInterface $productVariant,
ProductInterface $product,
OrderInterface $cart
OrderInterface $cart,
AvailabilityCheckerInterface $availabilityChecker
): void {
$this->initialize($executionContext);

Expand All @@ -183,6 +217,8 @@ function it_does_nothing_if_product_and_variant_are_enabled_and_available_in_cha
$productVariant->getProduct()->willReturn($product);

$product->isEnabled()->willReturn(true);
$availabilityChecker->isStockSufficient($productVariant, 1)->willReturn(true);

$product->hasChannel($channel)->willReturn(true);
$product->getName()->willReturn('PRODUCT NAME');

Expand All @@ -197,6 +233,10 @@ function it_does_nothing_if_product_and_variant_are_enabled_and_available_in_cha
->addViolation('sylius.product.not_exist', ['%productName%' => 'PRODUCT NAME'])
->shouldNotBeCalled()
;
$executionContext
->addViolation('sylius.product_variant.not_sufficient', ['%productVariantCode%' => 'productVariantCode'])
->shouldNotBeCalled()
;

$this->validate($command, new AddingEligibleProductVariantToCart());
}
Expand Down

0 comments on commit 2c636cd

Please sign in to comment.