[API] Configuration for shipment api browsing

This commit is contained in:
Adam Kasperczak 2020-03-13 13:17:25 +01:00 committed by Mateusz Zalewski
parent 8019467266
commit cec2bc0494
No known key found for this signature in database
GPG key ID: 9BECA0BB71612E52
22 changed files with 505 additions and 9 deletions

View file

@ -21,21 +21,21 @@ Feature: Browsing shipments
And the customer chose "UPS" shipping method with "Cash on Delivery" payment
And I am logged in as an administrator
@ui
@ui @api
Scenario: Browsing shipments and their states in one channel
When I browse shipments
Then I should see 2 shipments in the list
And I should see the shipment of order "#00000001" as "Shipped"
And I should see the shipment of order "#00000002" as "Ready"
@ui
@ui @api
Scenario: Shipments are sorted by newest as default
When I browse shipments
Then I should see shipment for the "#00000002" order as 1st in the list
And I should see shipment for the "#00000001" order as 2nd in the list
@ui
@ui @api
Scenario: Not seeing shipments in cart state
Given the customer added "Banana" product to the cart
Given the customer "customer@example.com" added "Banana" product to the cart
When I browse shipments
Then I should see only 2 shipments in the list

View file

@ -27,7 +27,7 @@ Feature: Browsing shipments from multiple channels
And the customer chose "FEDEX" shipping method with "bank transfer" payment
And I am logged in as an administrator
@ui
@ui @api
Scenario: Browsing shipments and their states from multiple channels
When I browse shipments
And I should see 2 shipments in the list

View file

@ -100,6 +100,17 @@ final class ResponseChecker implements ResponseCheckerInterface
return false;
}
public function hasItemWithValues(Response $response, array $parameters): bool
{
foreach ($this->getCollection($response) as $item) {
if ($this->itemHasValues($item, $parameters)) {
return true;
}
}
return false;
}
private function getResponseContentValue(Response $response, string $key)
{
$content = json_decode($response->getContent(), true);
@ -108,4 +119,14 @@ final class ResponseChecker implements ResponseCheckerInterface
return $content[$key];
}
private function itemHasValues(array $element, array $parameters): bool {
foreach ($parameters as $key => $value) {
if ($element[$key] !== $value) {
return false;
}
}
return true;
}
}

View file

@ -42,4 +42,6 @@ interface ResponseCheckerInterface
public function hasItemOnPositionWithValue(Response $response, int $position, string $key, string $value): bool;
public function hasItemWithTranslation(Response $response, string $locale, string $key, string $translation): bool;
public function hasItemWithValues(Response $response, array $parameters): bool;
}

View file

@ -0,0 +1,127 @@
<?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\Behat\Context\Api\Admin;
use ApiPlatform\Core\Api\IriConverterInterface;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Component\Channel\Model\ChannelInterface;
use Sylius\Component\Core\Formatter\StringInflector;
use Sylius\Component\Customer\Model\CustomerInterface;
use Sylius\Component\Order\Model\OrderInterface;
use Webmozart\Assert\Assert;
final class ManagingShipmentsContext implements Context
{
/** @var ApiClientInterface */
private $client;
/** @var ResponseCheckerInterface */
private $responseChecker;
/** @var IriConverterInterface */
private $iriConverter;
public function __construct(
ApiClientInterface $client,
ResponseCheckerInterface $responseChecker,
IriConverterInterface $iriConverter
) {
$this->client = $client;
$this->responseChecker = $responseChecker;
$this->iriConverter = $iriConverter;
}
/**
* @When I browse shipments
*/
public function iBrowseShipments(): void
{
$this->client->index();
}
/**
* @Then I should see( only) :count shipment(s) in the list
* @Then I should see a single shipment in the list
*/
public function iShouldSeeCountShipmentsInList(int $count = 1): void
{
Assert::same($this->responseChecker->countCollectionItems($this->client->getLastResponse()), $count);
}
/**
* @Then /^I should see the shipment of (order "[^"]+") as "([^"]+)"$/
*/
public function iShouldSeeTheShipmentOfOrderAs(OrderInterface $order, string $shippingState): void
{
Assert::true(
$this->responseChecker->hasItemWithValues($this->client->getLastResponse(), [
'order' => $this->iriConverter->getIriFromItem($order),
'state' => strtolower($shippingState)
]),
sprintf('Shipment for order %s with state %s does not exist', $order->getNumber(), $shippingState)
);
}
/**
* @Then /^I should see shipment for the ("[^"]+" order) as (\d+)(?:|st|nd|rd|th) in the list$/
*/
public function iShouldSeeShipmentForTheOrderInTheList(OrderInterface $order, int $position): void
{
Assert::true(
$this->responseChecker->hasItemOnPositionWithValue(
$this->client->getLastResponse(),
--$position,
'order',
$this->iriConverter->getIriFromItem($order)
),
sprintf('On position %s there is no shipment for order %s', $position, $order->getNumber())
);
}
/**
* @Then the shipment of the :orderNumber order should be :shippingState for :customer
* @Then the shipment of the :orderNumber order should be :shippingState for :customer in :channel channel
*/
public function shipmentOfOrderShouldBe(
string $orderNumber,
string $shippingState,
CustomerInterface $customer,
ChannelInterface $channel = null
): void {
$this->client->index();
foreach ($this->responseChecker->getCollectionItemsWithValue($this->client->getLastResponse(), 'state',
StringInflector::nameToLowercaseCode($shippingState)) as $shipment) {
$orderIri = $shipment['order'];
$orderShowResponse = $this->client->showByIri($orderIri);
if (!$this->responseChecker->HasValue($orderShowResponse, 'number', $orderNumber)) {
continue;
}
$this->client->showByIri($this->responseChecker->getValue($orderShowResponse, 'customer'));
if (!$this->responseChecker->HasValue($this->client->getLastResponse(), 'email', $customer->getEmail())) {
continue;
}
$this->client->showByIri($this->responseChecker->getValue($orderShowResponse, 'channel'));
if ($this->responseChecker->HasValue($this->client->getLastResponse(), 'name', $channel->getName())) {
return;
}
}
throw new \InvalidArgumentException('There is no shipment with given data');
}
}

View file

@ -37,6 +37,8 @@ final class OrderContext implements Context
/**
* @Transform :order
* @Transform /^"([^"]+)" order$/
* @Transform /^order "([^"]+)"$/
*/
public function getOrderByNumber(string $orderNumber): OrderInterface
{
@ -51,7 +53,7 @@ final class OrderContext implements Context
/**
* @Transform /^latest order$/
*/
public function getLatestOrder()
public function getLatestOrder(): OrderInterface
{
$orders = $this->orderRepository->findLatest(1);
@ -65,7 +67,7 @@ final class OrderContext implements Context
* @Transform /^order placed by "([^"]+)"$/
* @Transform /^the order of "([^"]+)"$/
*/
public function getOrderByCustomer($email)
public function getOrderByCustomer(string $email): OrderInterface
{
$customer = $this->customerRepository->findOneBy(['email' => $email]);
Assert::notNull($customer, sprintf('Cannot find customer with email %s.', $email));
@ -82,7 +84,7 @@ final class OrderContext implements Context
* @Transform /^the order "([^"]+)"$/
* @Transform /^the "([^"]+)" order$/
*/
public function getOrderNumber($orderNumber)
public function getOrderNumber(string $orderNumber): string
{
return str_replace('#', '', $orderNumber);
}

View file

@ -67,6 +67,12 @@
<argument>tax_categories</argument>
</service>
<service id="sylius.behat.api_platform_client.shipment" class="Sylius\Behat\Client\ApiPlatformClient">
<argument type="service" id="test.client" />
<argument type="service" id="sylius.behat.shared_storage" />
<argument>shipments</argument>
</service>
<service id="Sylius\Behat\Client\ResponseCheckerInterface" class="Sylius\Behat\Client\ResponseChecker">
<argument type="service" id="test.client" />
</service>

View file

@ -77,5 +77,11 @@
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="api_platform.iri_converter" />
</service>
<service id="sylius.behat.context.api.admin.managing_shipments" class="Sylius\Behat\Context\Api\Admin\ManagingShipmentsContext">
<argument type="service" id="sylius.behat.api_platform_client.shipment" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="api_platform.iri_converter" />
</service>
</services>
</container>

View file

@ -10,6 +10,7 @@ imports:
- suites/api/product/managing_product_reviews.yml
- suites/api/product/managing_product_variants.yml
- suites/api/product/managing_products.yml
- suites/api/shipping/managing_shipments.yml
- suites/api/shipping/managing_shipping_categories.yml
- suites/api/taxation/managing_tax_categories.yml
- suites/api/taxon/managing_taxons.yml

View file

@ -0,0 +1,34 @@
# This file is part of the Sylius package.
# (c) Paweł Jędrzejewski
default:
suites:
api_managing_shipments:
contexts:
- sylius.behat.context.hook.doctrine_orm
- sylius.behat.context.transform.address
- sylius.behat.context.transform.channel
- sylius.behat.context.transform.country
- sylius.behat.context.transform.customer
- sylius.behat.context.transform.order
- sylius.behat.context.transform.payment
- sylius.behat.context.transform.product
- sylius.behat.context.transform.shared_storage
- sylius.behat.context.transform.shipping_method
- sylius.behat.context.transform.zone
- sylius.behat.context.setup.admin_api_security
- sylius.behat.context.setup.calendar
- sylius.behat.context.setup.channel
- sylius.behat.context.setup.geographical
- sylius.behat.context.setup.order
- sylius.behat.context.setup.payment
- sylius.behat.context.setup.product
- sylius.behat.context.setup.shipping
- sylius.behat.context.setup.zone
- sylius.behat.context.api.admin.managing_shipments
filters:
tags: "@managing_shipments && @api"
javascript: false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" ?>
<!--
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.
-->
<resources xmlns="https://api-platform.com/schema/metadata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://api-platform.com/schema/metadata https://api-platform.com/schema/metadata/metadata-2.0.xsd"
>
<resource class="%sylius.model.channel.class%" shortName="Channel">
<attribute name="normalization_context">
<attribute name="groups">
<attribute>channel:read</attribute>
</attribute>
</attribute>
<collectionOperations />
<itemOperations>
<itemOperation name="get">
<attribute name="groups">
<attribute>channel:read</attribute>
</attribute>
</itemOperation>
</itemOperations>
<property name="code" identifier="true" writable="false" readable="true" />
<property name="name" writable="true" readable="true"/>
</resource>
</resources>

View file

@ -25,7 +25,11 @@
<collectionOperations />
<itemOperations>
<itemOperation name="get" />
<itemOperation name="get">
<attribute name="groups">
<attribute>customer:read</attribute>
</attribute>
</itemOperation>
</itemOperations>
<property name="id" identifier="true" writable="false" />

View file

@ -22,6 +22,8 @@
</attribute>
</attribute>
<attribute name="validation_groups">sylius</attribute>
<collectionOperations />
<itemOperations>

View file

@ -0,0 +1,55 @@
<?xml version="1.0" ?>
<!--
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.
-->
<resources xmlns="https://api-platform.com/schema/metadata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://api-platform.com/schema/metadata https://api-platform.com/schema/metadata/metadata-2.0.xsd"
>
<resource class="%sylius.model.shipment.class%" shortName="Shipment">
<attribute name="normalization_context">
<attribute name="groups">
<attribute>shipment:read</attribute>
</attribute>
</attribute>
<attribute name="denormalization_context">
<attribute name="groups">
<attribute>shipment:update</attribute>
</attribute>
</attribute>
<attribute name="validation_groups">sylius</attribute>
<attribute name="order">
<attribute name="createdAt">DESC</attribute>
</attribute>
<collectionOperations>
<collectionOperation name="get" />
</collectionOperations>
<itemOperations>
<itemOperation name="get" />
</itemOperations>
<property name="id" identifier="true" />
<property name="createdAt" />
<property name="updatedAt" />
<property name="state" />
<property name="method" />
<property name="units" />
<property name="tracking" />
<property name="shippedAt" />
<property name="order" />
</resource>
</resources>

View file

@ -0,0 +1,33 @@
<?xml version="1.0" ?>
<!--
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.
-->
<resources xmlns="https://api-platform.com/schema/metadata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://api-platform.com/schema/metadata https://api-platform.com/schema/metadata/metadata-2.0.xsd"
>
<resource class="%sylius.model.shipment_unit.class%" shortName="ShipmentUnit">
<attribute name="normalization_context">
<attribute name="groups">
<attribute>shipment_unit:read</attribute>
</attribute>
</attribute>
<itemOperations>
<itemOperation name="get" />
</itemOperations>
<collectionOperations />
<property name="id" identifier="true" writable="false" />
</resource>
</resources>

View file

@ -0,0 +1,33 @@
<?xml version="1.0" ?>
<!--
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.
-->
<resources xmlns="https://api-platform.com/schema/metadata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://api-platform.com/schema/metadata https://api-platform.com/schema/metadata/metadata-2.0.xsd"
>
<resource class="%sylius.model.shipping_method.class%" shortName="ShippingMethod">
<attribute name="normalization_context">
<attribute name="groups">
<attribute>shipping_method:read</attribute>
</attribute>
</attribute>
<itemOperations>
<itemOperation name="get" />
</itemOperations>
<collectionOperations />
<property name="id" identifier="true" writable="false" />
</resource>
</resources>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" ?>
<!--
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.
-->
<serializer xmlns="http://symfony.com/schema/dic/serializer-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/serializer-mapping https://symfony.com/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd"
>
<class name="Sylius\Component\Core\Model\Channel">
<attribute name="code">
<group>channel:read</group>
</attribute>
<attribute name="name">
<group>channel:read</group>
</attribute>
</class>
</serializer>

View file

@ -19,6 +19,7 @@
<attribute name="id">
<group>customer:read</group>
</attribute>
<attribute name="email">
<group>customer:read</group>
</attribute>

View file

@ -19,12 +19,15 @@
<attribute name="id">
<group>order:read</group>
</attribute>
<attribute name="number">
<group>order:read</group>
</attribute>
<attribute name="channel">
<group>order:read</group>
</attribute>
<attribute name="customer">
<group>order:read</group>
</attribute>

View file

@ -0,0 +1,55 @@
<?xml version="1.0" ?>
<!--
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.
-->
<serializer xmlns="http://symfony.com/schema/dic/serializer-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/serializer-mapping https://symfony.com/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd"
>
<class name="Sylius\Component\Core\Model\Shipment">
<attribute name="createdAt">
<group>shipment:read</group>
</attribute>
<attribute name="updatedAt">
<group>shipment:read</group>
</attribute>
<attribute name="id">
<group>shipment:read</group>
</attribute>
<attribute name="state">
<group>shipment:read</group>
</attribute>
<attribute name="method">
<group>shipment:read</group>
</attribute>
<attribute name="units">
<group>shipment:read</group>
</attribute>
<attribute name="tracking">
<group>shipment:read</group>
</attribute>
<attribute name="shippedAt">
<group>shipment:read</group>
</attribute>
<attribute name="order">
<group>shipment:read</group>
</attribute>
</class>
</serializer>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" ?>
<!--
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.
-->
<serializer xmlns="http://symfony.com/schema/dic/serializer-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/serializer-mapping https://symfony.com/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd"
>
<class name="Sylius\Component\Shipping\Model\ShipmentUnit">
<attribute name="id">
<group>shipment_unit:read</group>
</attribute>
</class>
</serializer>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" ?>
<!--
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.
-->
<serializer xmlns="http://symfony.com/schema/dic/serializer-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/serializer-mapping https://symfony.com/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd"
>
<class name="Sylius\Component\Shipping\Model\ShippingMethod">
<attribute name="id">
<group>shipping_method:read</group>
</attribute>
</class>
</serializer>