This commit is contained in:
Francis Hilaire 2026-06-24 11:24:16 +00:00 committed by GitHub
commit a9841a6030
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 700 additions and 300 deletions

View file

@ -18,6 +18,7 @@ use Symfony\Component\BrowserKit\AbstractBrowser;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
final class ApiPlatformClient implements ApiClientInterface
{
@ -30,6 +31,7 @@ final class ApiPlatformClient implements ApiClientInterface
private readonly SharedStorageInterface $sharedStorage,
private readonly RequestFactoryInterface $requestFactory,
private readonly ResponseCheckerInterface $responseChecker,
private readonly ?NameConverterInterface $nameConverter,
private readonly string $authorizationHeader,
private readonly string $section,
) {
@ -210,7 +212,7 @@ final class ApiPlatformClient implements ApiClientInterface
public function setRequestData(array $data): self
{
$this->request->setContent($data);
$this->request->setContent($this->convertArrayAttributesRecursively($data));
return $this;
}
@ -233,7 +235,9 @@ final class ApiPlatformClient implements ApiClientInterface
/** @param array<string, mixed> $value */
public function addRequestData(string $key, array|bool|int|string|null $value): self
{
$this->request->updateContent([$key => $value]);
$this->request->updateContent([
$this->getNormalizedKey($key) => is_array($value) ? $this->convertArrayAttributesRecursively($value) : $value,
]);
return $this;
}
@ -243,35 +247,37 @@ final class ApiPlatformClient implements ApiClientInterface
{
$requestContent = $this->request->getContent();
$this->request->setContent(array_replace($requestContent, [$key => $value]));
$this->request->setContent(array_replace($requestContent, [
$this->getNormalizedKey($key) => is_array($value) ? $this->convertArrayAttributesRecursively($value) : $value,
]));
}
/** @param array<string, mixed> $data */
public function updateRequestData(array $data): void
{
$this->request->updateContent($data);
$this->request->updateContent($this->convertArrayAttributesRecursively($data));
}
/** @param array<string, mixed> $data */
public function setSubResourceData(string $key, array $data): void
{
$this->request->setSubResource($key, $data);
$this->request->setSubResource($this->getNormalizedKey($key), $this->convertArrayAttributesRecursively($data));
}
/** @param array<string, mixed> $data */
public function addSubResourceData(string $key, array $data): void
{
$this->request->addSubResource($key, $data);
$this->request->addSubResource($this->getNormalizedKey($key), $this->convertArrayAttributesRecursively($data));
}
public function removeSubResourceIri(string $subResourceKey, string $iri): void
{
$this->request->removeSubResource($subResourceKey, $iri);
$this->request->removeSubResource($this->getNormalizedKey($subResourceKey), $iri);
}
public function removeSubResourceObject(string $subResourceKey, string $value, string $key = '@id'): void
{
$this->request->removeSubResource($subResourceKey, $value, $key);
$this->request->removeSubResource($this->getNormalizedKey($subResourceKey), $value, $key);
}
/** @return array<string, mixed> */
@ -389,4 +395,29 @@ final class ApiPlatformClient implements ApiClientInterface
throw new \InvalidArgumentException('URI should not start with "api".');
}
}
/**
* @param array<string, mixed> $data
*
* @return array<string, mixed>
*/
private function convertArrayAttributesRecursively(array $data): array
{
$convertedData = [];
/** @var array<string, mixed>|bool|int|string|null $value */
foreach ($data as $attribute => $value) {
$convertedAttribute = is_string($attribute) ? $this->getNormalizedKey($attribute) : $attribute;
$convertedData[$convertedAttribute] = is_array($value)
? $this->convertArrayAttributesRecursively($value)
: $value;
}
return $convertedData;
}
private function getNormalizedKey(string $key): string
{
return $this->nameConverter ? $this->nameConverter->normalize($key) : $key;
}
}

View file

@ -16,6 +16,7 @@ namespace Sylius\Behat\Client;
use Lexik\Bundle\JWTAuthenticationBundle\Response\JWTAuthenticationFailureResponse;
use Sylius\Behat\Service\SprintfResponseEscaper;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final class ResponseChecker implements ResponseCheckerInterface
@ -23,8 +24,9 @@ final class ResponseChecker implements ResponseCheckerInterface
/** @var array<array-key, string> */
private array $errors;
public function __construct()
{
public function __construct(
private ?NameConverterInterface $nameConverter
) {
$this->errors = [];
}
@ -45,21 +47,24 @@ final class ResponseChecker implements ResponseCheckerInterface
public function getCollectionItemsWithValue(Response $response, string $key, string $value): array
{
$items = array_filter($this->getCollection($response), fn (array $item): bool => $item[$key] === $value);
$items = array_filter(
$this->getCollection($response),
fn (array $item): bool => $item[$this->getNormalizedKey($key)] === $value,
);
return $items;
}
public function getValue(Response $response, string $key)
{
return $this->getResponseContentValue($response, $key);
return $this->getResponseContentValue($response, $this->getNormalizedKey($key));
}
public function getTranslationValue(Response $response, string $key, ?string $localeCode = 'en_US'): string
{
$translations = $this->getResponseContentValue($response, 'translations');
return $translations[$localeCode][$key];
return $translations[$localeCode][$this->getNormalizedKey($key)];
}
public function getError(Response $response): ?string
@ -118,23 +123,27 @@ final class ResponseChecker implements ResponseCheckerInterface
public function hasValue(Response $response, string $key, bool|int|string|null $value, bool $isCaseSensitive = true): bool
{
$normalizedKey = $this->getNormalizedKey($key);
if ($isCaseSensitive) {
return $this->getResponseContentValue($response, $key) === $value;
return $this->getResponseContentValue($response, $normalizedKey) === $value;
}
return strcasecmp((string) $this->getResponseContentValue($response, $key), (string) $value) === 0;
return strcasecmp((string) $this->getResponseContentValue($response, $normalizedKey), (string) $value) === 0;
}
public function hasValueInCollection(Response $response, string $key, bool|int|string $value): bool
{
return in_array($value, $this->getResponseContentValue($response, $key), true);
return in_array($value, $this->getResponseContentValue($response, $this->getNormalizedKey($key)), true);
}
/** @param string|int $value */
public function hasItemWithValue(Response $response, string $key, $value): bool
{
$normalizedKey = $this->getNormalizedKey($key);
foreach ($this->getCollection($response) as $resource) {
if ($resource[$key] === $value) {
if ($resource[$normalizedKey] === $value) {
return true;
}
}
@ -192,27 +201,29 @@ final class ResponseChecker implements ResponseCheckerInterface
$this->assertIsArray($resource);
return $resource[$key] === $expectedValue;
return $resource[$this->getNormalizedKey($key)] === $expectedValue;
}
/** @param string|array $value */
public function hasItemOnPositionWithValue(Response $response, int $position, string $key, $value): bool
{
return $this->getCollection($response)[$position][$key] === $value;
return $this->getCollection($response)[$position][$this->getNormalizedKey($key)] === $value;
}
public function hasItemWithTranslation(Response $response, string $locale, string $key, string $translation): bool
{
$normalizedKey = $this->getNormalizedKey($key);
if (!$this->hasCollection($response)) {
$resource = $this->getResponseContent($response);
if (isset($resource['translations'][$locale]) && $resource['translations'][$locale][$key] === $translation) {
if (isset($resource['translations'][$locale]) && $resource['translations'][$locale][$normalizedKey] === $translation) {
return true;
}
}
foreach ($this->getCollection($response) as $resource) {
if (isset($resource['translations'][$locale]) && $resource['translations'][$locale][$key] === $translation) {
if (isset($resource['translations'][$locale]) && $resource['translations'][$locale][$normalizedKey] === $translation) {
return true;
}
}
@ -222,8 +233,10 @@ final class ResponseChecker implements ResponseCheckerInterface
public function hasItemWithTranslationInCollection(array $items, string $locale, string $key, string $translation): bool
{
$normalizedKey = $this->getNormalizedKey($key);
foreach ($items as $item) {
if (isset($item['translations'][$locale]) && $item['translations'][$locale][$key] === $translation) {
if (isset($item['translations'][$locale]) && $item['translations'][$locale][$normalizedKey] === $translation) {
return true;
}
}
@ -235,14 +248,14 @@ final class ResponseChecker implements ResponseCheckerInterface
{
$content = json_decode($response->getContent(), true);
return array_key_exists($key, $content);
return array_key_exists($this->getNormalizedKey($key), $content);
}
public function hasTranslation(Response $response, string $locale, string $key, string $translation): bool
{
$resource = $this->getResponseContent($response);
return isset($resource['translations'][$locale]) && $resource['translations'][$locale][$key] === $translation;
return isset($resource['translations'][$locale]) && $resource['translations'][$locale][$this->getNormalizedKey($key)] === $translation;
}
public function hasItemWithValues(Response $response, array $parameters): bool
@ -347,7 +360,7 @@ final class ResponseChecker implements ResponseCheckerInterface
private function itemHasValues(array $element, array $parameters): bool
{
foreach ($parameters as $key => $value) {
if ($element[$key] !== $value) {
if ($element[$this->getNormalizedKey($key)] !== $value) {
return false;
}
}
@ -376,4 +389,9 @@ final class ResponseChecker implements ResponseCheckerInterface
),
);
}
private function getNormalizedKey(string $key): string
{
return $this->nameConverter ? $this->nameConverter->normalize($key) : $key;
}
}

View file

@ -17,19 +17,24 @@ use ApiPlatform\Metadata\IriConverterInterface;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final class BrowsingCatalogPromotionProductVariantsContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private IriConverterInterface $iriConverter,
private ?NameConverterInterface $nameConverter,
) {
}
@ -145,9 +150,13 @@ final class BrowsingCatalogPromotionProductVariantsContext implements Context
): bool {
$variantData = $this->getDataOfVariantWithCode($variant->getCode());
$promotions = $variantData['channelPricings'][$channel->getCode()]['appliedPromotions'] ?? [];
$channelPricingsKey = $this->getNormalizedKey('channelPricings');
$appliedPromotionsKey = $this->getNormalizedKey('appliedPromotions');
$codeKey = $this->getNormalizedKey('code');
$promotions = $variantData[$channelPricingsKey][$channel->getCode()][$appliedPromotionsKey] ?? [];
foreach ($promotions as $promotion) {
if ($promotion['code'] === $catalogPromotion->getCode()) {
if ($promotion[$codeKey] === $catalogPromotion->getCode()) {
return true;
}
}
@ -158,8 +167,10 @@ final class BrowsingCatalogPromotionProductVariantsContext implements Context
private function getDataOfVariantWithCode(string $code): array
{
$variantsData = $this->responseChecker->getCollection($this->client->getLastResponse());
$codeKey = $this->getNormalizedKey('code');
foreach ($variantsData as $variantData) {
if ($variantData['code'] === $code) {
if ($variantData[$codeKey] === $code) {
return $variantData;
}
}

View file

@ -16,17 +16,22 @@ namespace Sylius\Behat\Context\Api\Admin;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final class ChannelPricingLogEntryContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private SharedStorageInterface $sharedStorage,
private ?NameConverterInterface $nameConverter,
) {
}
@ -69,8 +74,8 @@ final class ChannelPricingLogEntryContext implements Context
$logEntry = $this->responseChecker->getCollection($this->client->getLastResponse())[$position - 1];
Assert::same($logEntry['price'], $price);
Assert::same($logEntry['originalPrice'], $originalPrice);
Assert::same($logEntry[$this->getNormalizedKey('price')], $price);
Assert::same($logEntry[$this->getNormalizedKey('originalPrice')], $originalPrice);
Assert::keyExists($logEntry, 'loggedAt');
}

View file

@ -16,16 +16,21 @@ namespace Sylius\Behat\Context\Api\Admin;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Component\Addressing\Model\CountryInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final readonly class ManagingChannelsBillingDataContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private ?NameConverterInterface $nameConverter,
) {
}
@ -36,7 +41,7 @@ final readonly class ManagingChannelsBillingDataContext implements Context
{
$shopBillingData = $this->getShopBillingDataFromChannel($channel);
Assert::same($shopBillingData['company'], $company);
Assert::same($shopBillingData[$this->getNormalizedKey('company')], $company);
}
/**
@ -46,7 +51,7 @@ final readonly class ManagingChannelsBillingDataContext implements Context
{
$shopBillingData = $this->getShopBillingDataFromChannel($channel);
Assert::same($shopBillingData['taxId'], $taxId);
Assert::same($shopBillingData[$this->getNormalizedKey('taxId')], $taxId);
}
/**
@ -62,10 +67,10 @@ final readonly class ManagingChannelsBillingDataContext implements Context
): void {
$shopBillingData = $this->getShopBillingDataFromChannel($channel);
Assert::same($shopBillingData['street'], $street);
Assert::same($shopBillingData['postcode'], $postcode);
Assert::same($shopBillingData['city'], $city);
Assert::same($shopBillingData['countryCode'], $country->getCode());
Assert::same($shopBillingData[$this->getNormalizedKey('street')], $street);
Assert::same($shopBillingData[$this->getNormalizedKey('postcode')], $postcode);
Assert::same($shopBillingData[$this->getNormalizedKey('city')], $city);
Assert::same($shopBillingData[$this->getNormalizedKey('countryCode')], $country->getCode());
}
/**

View file

@ -16,19 +16,24 @@ namespace Sylius\Behat\Context\Api\Admin;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Currency\Model\CurrencyInterface;
use Sylius\Component\Currency\Model\ExchangeRateInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final readonly class ManagingExchangeRatesContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private SharedStorageInterface $sharedStorage,
private string $apiUrlPrefix,
private ?NameConverterInterface $nameConverter,
) {
}
@ -237,7 +242,7 @@ final readonly class ManagingExchangeRatesContext implements Context
$exchangeRate->getTargetCurrency(),
);
Assert::same($exchangeRate['ratio'], $ratio);
Assert::same($exchangeRate[$this->getNormalizedKey('ratio')], $ratio);
}
/**
@ -361,8 +366,8 @@ final readonly class ManagingExchangeRatesContext implements Context
/** @var array $item */
foreach ($this->responseChecker->getCollection($this->client->index(Resources::EXCHANGE_RATES)) as $item) {
if (
$item['sourceCurrency'] === sprintf('%s/admin/currencies/%s', $this->apiUrlPrefix, $sourceCurrency->getCode()) &&
$item['targetCurrency'] === sprintf('%s/admin/currencies/%s', $this->apiUrlPrefix, $targetCurrency->getCode())
$item[$this->getNormalizedKey('sourceCurrency')] === sprintf('%s/admin/currencies/%s', $this->apiUrlPrefix, $sourceCurrency->getCode()) &&
$item[$this->getNormalizedKey('targetCurrency')] === sprintf('%s/admin/currencies/%s', $this->apiUrlPrefix, $targetCurrency->getCode())
) {
return $item;
}
@ -382,6 +387,6 @@ final readonly class ManagingExchangeRatesContext implements Context
return false;
}
return $exchangeRateResponse['ratio'] === $ratio;
return $exchangeRateResponse[$this->getNormalizedKey('ratio')] === $ratio;
}
}

View file

@ -39,6 +39,7 @@ use Sylius\Component\Shipping\ShipmentTransitions;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Intl\Countries;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final readonly class ManagingOrdersContext implements Context
@ -50,6 +51,7 @@ final readonly class ManagingOrdersContext implements Context
private SecurityServiceInterface $adminSecurityService,
private SharedStorageInterface $sharedStorage,
private SharedSecurityServiceInterface $sharedSecurityService,
private ?NameConverterInterface $nameConverter
) {
}
@ -325,10 +327,11 @@ final readonly class ManagingOrdersContext implements Context
/** @var string $lastResponseContent */
$lastResponseContent = $this->client->getLastResponse()->getContent();
/** @var array{productName: string}[] $items */
$items = json_decode($lastResponseContent, true)['items'];
$items = json_decode($lastResponseContent, true)[$this->getNormalizedKey('items')];
$productNameKey = $this->getNormalizedKey('productName');
foreach ($items as $item) {
if ($item['productName'] === $itemName) {
if ($item[$productNameKey] === $itemName) {
$this->sharedStorage->set('item', $item);
return;
@ -480,10 +483,12 @@ final readonly class ManagingOrdersContext implements Context
{
$order = $this->responseChecker->getCollection($this->client->getLastResponse())[0];
$paymentStateKey = $this->getNormalizedKey('paymentState');
$tokenValueKey = $this->getNormalizedKey('tokenValue');
Assert::same(
$order['paymentState'],
$order[$paymentStateKey],
strtolower($orderPaymentState),
sprintf('Order "%s" does not have "%s" payment state', $order['tokenValue'], $orderPaymentState),
sprintf('Order "%s" does not have "%s" payment state', $order[$tokenValueKey], $orderPaymentState),
);
}
@ -502,8 +507,9 @@ final readonly class ManagingOrdersContext implements Context
{
$items = $this->responseChecker->getValue($this->client->getLastResponse(), 'items');
$productNameKey = $this->getNormalizedKey('productName');
foreach ($items as $item) {
if ($item['productName'] === $productName) {
if ($item[$productNameKey] === $productName) {
return;
}
}
@ -724,7 +730,7 @@ final readonly class ManagingOrdersContext implements Context
$items = $this->responseChecker->getValue($this->client->getLastResponse(), 'hydra:member');
$firstItem = $items[0];
Assert::same($firstItem['number'], str_replace('#', '', $number));
Assert::same($firstItem[$this->getNormalizedKey('number')], str_replace('#', '', $number));
}
/**
@ -739,7 +745,7 @@ final readonly class ManagingOrdersContext implements Context
)[0];
Assert::same(
$order['total'],
$order[$this->getNormalizedKey('total')],
$total,
);
}
@ -767,7 +773,7 @@ final readonly class ManagingOrdersContext implements Context
$firstItem = array_pop($itemsWithCurrency);
Assert::notEmpty($firstItem);
Assert::same($firstItem['total'], $total);
Assert::same($firstItem[$this->getNormalizedKey('total')], $total);
}
/**
@ -787,7 +793,7 @@ final readonly class ManagingOrdersContext implements Context
public function itShouldBeShippedViaTheShippingMethod(ShippingMethodInterface $shippingMethod): void
{
Assert::same(
$this->responseChecker->getValue($this->client->getLastResponse(), 'shipments')[0]['method'],
$this->responseChecker->getValue($this->client->getLastResponse(), 'shipments')[0][$this->getNormalizedKey('method')],
$this->iriConverter->getIriFromResource($shippingMethod),
);
}
@ -798,7 +804,7 @@ final readonly class ManagingOrdersContext implements Context
public function itShouldBePaidWith(PaymentMethodInterface $paymentMethod): void
{
Assert::same(
$this->responseChecker->getValue($this->client->getLastResponse(), 'payments')[0]['method'],
$this->responseChecker->getValue($this->client->getLastResponse(), 'payments')[0][$this->getNormalizedKey('method')],
$this->iriConverter->getIriFromResource($paymentMethod),
);
}
@ -860,8 +866,9 @@ final readonly class ManagingOrdersContext implements Context
*/
public function iShouldSeeAsProvinceInTheShippingAddress(string $provinceName): void
{
$provinceNameKey = $this->getNormalizedKey('provinceName');
Assert::same(
$this->responseChecker->getValue($this->client->getLastResponse(), 'shippingAddress')['provinceName'],
$this->responseChecker->getValue($this->client->getLastResponse(), 'shippingAddress')[$provinceNameKey],
$provinceName,
);
}
@ -871,8 +878,9 @@ final readonly class ManagingOrdersContext implements Context
*/
public function iShouldSeeAsProvinceInTheBillingAddress(string $provinceName): void
{
$provinceNameKey = $this->getNormalizedKey('provinceName');
Assert::same(
$this->responseChecker->getValue($this->client->getLastResponse(), 'billingAddress')['provinceName'],
$this->responseChecker->getValue($this->client->getLastResponse(), 'billingAddress')[$provinceNameKey],
$provinceName,
);
}
@ -895,7 +903,8 @@ final readonly class ManagingOrdersContext implements Context
*/
public function itemUnitPriceShouldBe(array $orderItem, string $unitPrice): void
{
Assert::same($this->getTotalAsInt($unitPrice), $orderItem['unitPrice']);
$unitPriceKey = $this->getNormalizedKey('unitPrice');
Assert::same($this->getTotalAsInt($unitPrice), $orderItem[$unitPriceKey]);
}
/**
@ -903,7 +912,7 @@ final readonly class ManagingOrdersContext implements Context
*/
public function itemTotalShouldBe(array $orderItem, string $total): void
{
Assert::same($this->getTotalAsInt($total), $orderItem['total']);
Assert::same($this->getTotalAsInt($total), $orderItem[$this->getNormalizedKey('total')]);
}
/**
@ -911,7 +920,7 @@ final readonly class ManagingOrdersContext implements Context
*/
public function itemCodeShouldBe(array $orderItem, string $code): void
{
Assert::endsWith($orderItem['variant'], $code);
Assert::endsWith($orderItem[$this->getNormalizedKey('variant')], $code);
}
/**
@ -919,7 +928,7 @@ final readonly class ManagingOrdersContext implements Context
*/
public function itemQuantityShouldBe(array $orderItem, int $quantity): void
{
Assert::same($quantity, $orderItem['quantity']);
Assert::same($quantity, $orderItem[$this->getNormalizedKey('quantity')]);
}
/**
@ -943,14 +952,18 @@ final readonly class ManagingOrdersContext implements Context
{
$orderItem = $this->sharedStorage->get('item');
$typeKey = $this->getNormalizedKey('type');
$amountKey = $this->getNormalizedKey('amount');
$unitPriceKey = $this->getNormalizedKey('unitPrice');
$quantityKey = $this->getNormalizedKey('quantity');
$unitPromotionAdjustments = 0;
foreach ($this->responseChecker->getCollection($this->client->getLastResponse()) as $item) {
if (in_array($item['type'], [AdjustmentInterface::ORDER_UNIT_PROMOTION_ADJUSTMENT, AdjustmentInterface::ORDER_PROMOTION_ADJUSTMENT])) {
$unitPromotionAdjustments += $item['amount'];
if (in_array($item[$typeKey], [AdjustmentInterface::ORDER_UNIT_PROMOTION_ADJUSTMENT, AdjustmentInterface::ORDER_PROMOTION_ADJUSTMENT])) {
$unitPromotionAdjustments += $item[$amountKey];
}
}
Assert::same($this->getTotalAsInt($subtotal), $orderItem['unitPrice'] * $orderItem['quantity'] + $unitPromotionAdjustments);
Assert::same($this->getTotalAsInt($subtotal), $orderItem[$unitPriceKey] * $orderItem[$quantityKey] + $unitPromotionAdjustments);
}
/**
@ -994,8 +1007,8 @@ final readonly class ManagingOrdersContext implements Context
$totalTax = 0;
foreach ($unitPromotionAdjustments as $unitPromotionAdjustment) {
if (true === $unitPromotionAdjustment['neutral']) {
$totalTax += $unitPromotionAdjustment['amount'];
if (true === $unitPromotionAdjustment[$this->getNormalizedKey('neutral')]) {
$totalTax += $unitPromotionAdjustment[$this->getNormalizedKey('amount')];
}
}
@ -1041,9 +1054,10 @@ final readonly class ManagingOrdersContext implements Context
*/
public function productUnitPriceShouldBe(string $productName, string $price): void
{
$unitPriceKey = $this->getNormalizedKey('unitPrice');
$this->iCheckData($productName);
$orderItem = $this->sharedStorage->get('item');
Assert::same($this->getTotalAsInt($price), $orderItem['unitPrice']);
Assert::same($this->getTotalAsInt($price), $orderItem[$unitPriceKey]);
}
/**
@ -1052,7 +1066,8 @@ final readonly class ManagingOrdersContext implements Context
public function productDiscountedUnitPriceShouldBe(string $productName, string $price): void
{
$orderItem = $this->sharedStorage->get('item');
Assert::same($this->getTotalAsInt($price), $orderItem['fullDiscountedUnitPrice']);
$fullDiscountedUnitPriceKey = $this->getNormalizedKey('fullDiscountedUnitPrice');
Assert::same($this->getTotalAsInt($price), $orderItem[$fullDiscountedUnitPriceKey]);
}
/**
@ -1061,7 +1076,8 @@ final readonly class ManagingOrdersContext implements Context
public function productQuantityShouldBe(string $productName, int $quantity): void
{
$orderItem = $this->sharedStorage->get('item');
Assert::same($quantity, $orderItem['quantity']);
$quantityKey = $this->getNormalizedKey('quantity');
Assert::same($quantity, $orderItem[$quantityKey]);
}
/**
@ -1077,9 +1093,12 @@ final readonly class ManagingOrdersContext implements Context
AdjustmentInterface::ORDER_UNIT_PROMOTION_ADJUSTMENT,
);
$orderItemUnitKey = $this->getNormalizedKey('orderItemUnit');
$unitsKey = $this->getNormalizedKey('units');
$amountKey = $this->getNormalizedKey('amount');
foreach ($adjustments as $adjustment) {
if (in_array($adjustment['orderItemUnit'], $orderItem['units'])) {
Assert::same($this->getTotalAsInt($price), $adjustment['amount']);
if (in_array($adjustment[$orderItemUnitKey], $orderItem[$unitsKey])) {
Assert::same($this->getTotalAsInt($price), $adjustment[$amountKey]);
return;
}
@ -1099,9 +1118,12 @@ final readonly class ManagingOrdersContext implements Context
AdjustmentInterface::ORDER_PROMOTION_ADJUSTMENT,
);
$orderItemUnitKey = $this->getNormalizedKey('orderItemUnit');
$unitsKey = $this->getNormalizedKey('units');
$amountKey = $this->getNormalizedKey('amount');
foreach ($adjustments as $adjustment) {
if (in_array($adjustment['orderItemUnit'], $orderItem['units'])) {
Assert::same($this->getTotalAsInt(trim($price, ' ~')), $adjustment['amount']);
if (in_array($adjustment[$orderItemUnitKey], $orderItem[$unitsKey])) {
Assert::same($this->getTotalAsInt(trim($price, ' ~')), $adjustment[$amountKey]);
return;
}
@ -1116,16 +1138,22 @@ final readonly class ManagingOrdersContext implements Context
$orderItem = $this->sharedStorage->get('item');
$response = $this->getAdjustmentsResponseForOrder(true);
$typeKey = $this->getNormalizedKey('type');
$orderItemUnitKey = $this->getNormalizedKey('orderItemUnit');
$unitsKey = $this->getNormalizedKey('units');
$amountKey = $this->getNormalizedKey('amount');
$unitPromotionAdjustments = 0;
foreach ($this->responseChecker->getCollection($response) as $adjustment) {
if (in_array($adjustment['type'], [AdjustmentInterface::ORDER_UNIT_PROMOTION_ADJUSTMENT, AdjustmentInterface::ORDER_PROMOTION_ADJUSTMENT])) {
if (in_array($adjustment['orderItemUnit'], $orderItem['units'])) {
$unitPromotionAdjustments += $adjustment['amount'];
if (in_array($adjustment[$typeKey], [AdjustmentInterface::ORDER_UNIT_PROMOTION_ADJUSTMENT, AdjustmentInterface::ORDER_PROMOTION_ADJUSTMENT])) {
if (in_array($adjustment[$orderItemUnitKey], $orderItem[$unitsKey])) {
$unitPromotionAdjustments += $adjustment[$amountKey];
}
}
}
Assert::same($this->getTotalAsInt($subTotal), $orderItem['unitPrice'] * $orderItem['quantity'] + $unitPromotionAdjustments);
$quantityKey = $this->getNormalizedKey('quantity');
$unitPriceKey = $this->getNormalizedKey('unitPrice');
Assert::same($this->getTotalAsInt($subTotal), $orderItem[$unitPriceKey] * $orderItem[$quantityKey] + $unitPromotionAdjustments);
}
/**
@ -1305,11 +1333,17 @@ final readonly class ManagingOrdersContext implements Context
string $city,
string $countryName,
): void {
Assert::same($address['firstName'] . ' ' . $address['lastName'], $customerName);
Assert::same($address['street'], $street);
Assert::same($address['postcode'], $postcode);
Assert::same($address['city'], $city);
Assert::same($address['countryCode'], $this->getCountryCodeFromName($countryName));
$firstNameKey = $this->getNormalizedKey('firstName');
$lastNameKey = $this->getNormalizedKey('lastName');
$streetKey = $this->getNormalizedKey('street');
$postcodeKey = $this->getNormalizedKey('postcode');
$cityKey = $this->getNormalizedKey('city');
$countryCodeKey = $this->getNormalizedKey('countryCode');
Assert::same($address[$firstNameKey] . ' ' . $address[$lastNameKey], $customerName);
Assert::same($address[$streetKey], $street);
Assert::same($address[$postcodeKey], $postcode);
Assert::same($address[$cityKey], $city);
Assert::same($address[$countryCodeKey], $this->getCountryCodeFromName($countryName));
}
private function getCountryCodeFromName(string $name): string
@ -1352,4 +1386,9 @@ final readonly class ManagingOrdersContext implements Context
forgetResponse: $forgetResponse,
);
}
private function getNormalizedKey(string $key): string
{
return $this->nameConverter ? $this->nameConverter->normalize($key) : $key;
}
}

View file

@ -17,6 +17,7 @@ use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\Admin\Helper\ValidationTrait;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Service\Converter\IriConverterInterface;
use Sylius\Component\Core\Formatter\StringInflector;
@ -27,11 +28,13 @@ use Sylius\Component\Product\Model\ProductOptionInterface;
use Sylius\Component\Product\Model\ProductOptionValueInterface;
use Sylius\Component\Product\Resolver\ProductVariantResolverInterface;
use Sylius\Component\Shipping\Model\ShippingCategoryInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final class ManagingProductVariantsContext implements Context
{
use ValidationTrait;
use NormalizedKeyAwareTrait;
private const FIRST_COLLECTION_ITEM = 0;
@ -42,6 +45,7 @@ final class ManagingProductVariantsContext implements Context
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private IriConverterInterface $iriConverter,
private ?NameConverterInterface $nameConverter,
) {
}
@ -374,12 +378,15 @@ final class ManagingProductVariantsContext implements Context
'name' => $name,
];
$translationInLocale = $response[self::FIRST_COLLECTION_ITEM]['translations'][$localeCode];
$translationsKey = $this->getNormalizedKey('translations');
$nameKey = $this->getNormalizedKey('name');
$translationInLocale = $response[self::FIRST_COLLECTION_ITEM][$translationsKey][$localeCode];
Assert::allInArray(
$expectedTranslation,
$translationInLocale,
sprintf('Expected translation %s, got %s', $expectedTranslation['name'], $translationInLocale['name']),
sprintf('Expected translation %s, got %s', $expectedTranslation['name'], $translationInLocale[$nameKey]),
);
}
@ -394,7 +401,10 @@ final class ManagingProductVariantsContext implements Context
): void {
$response = $this->responseChecker->getCollection($this->client->index(Resources::PRODUCT_VARIANTS));
Assert::same($response[self::FIRST_COLLECTION_ITEM]['channelPricings'][$channel->getCode()]['price'], $price);
$channelPricingsKey = $this->getNormalizedKey('channelPricings');
$priceKey = $this->getNormalizedKey('price');
Assert::same($response[self::FIRST_COLLECTION_ITEM][$channelPricingsKey][$channel->getCode()][$priceKey], $price);
}
/**
@ -408,7 +418,10 @@ final class ManagingProductVariantsContext implements Context
): void {
$response = $this->responseChecker->getCollection($this->client->index(Resources::PRODUCT_VARIANTS));
Assert::same($response[self::FIRST_COLLECTION_ITEM]['channelPricings'][$channel->getCode()]['originalPrice'], $originalPrice);
$channelPricingsKey = $this->getNormalizedKey('channelPricings');
$originalPriceKey = $this->getNormalizedKey('originalPrice');
Assert::same($response[self::FIRST_COLLECTION_ITEM][$channelPricingsKey][$channel->getCode()][$originalPriceKey], $originalPrice);
}
/**
@ -428,7 +441,10 @@ final class ManagingProductVariantsContext implements Context
{
$response = $this->responseChecker->getCollection($this->client->index(Resources::PRODUCT_VARIANTS));
Assert::same($response[self::FIRST_COLLECTION_ITEM]['channelPricings'][$channel->getCode()]['minimumPrice'], $minimumPrice);
$channelPricingsKey = $this->getNormalizedKey('channelPricings');
$minimumPriceKey = $this->getNormalizedKey('minimumPrice');
Assert::same($response[self::FIRST_COLLECTION_ITEM][$channelPricingsKey][$channel->getCode()][$minimumPriceKey], $minimumPrice);
}
/**

View file

@ -18,6 +18,7 @@ use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\RequestBuilder;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\Admin\Helper\ValidationTrait;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Service\Converter\IriConverterInterface;
use Sylius\Behat\Service\SharedStorageInterface;
@ -35,11 +36,13 @@ use Sylius\Component\Product\Model\ProductAttributeInterface;
use Sylius\Component\Product\Model\ProductOptionInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final readonly class ManagingProductsContext implements Context
{
use ValidationTrait;
use NormalizedKeyAwareTrait;
public const SORT_TYPES = ['ascending' => 'asc', 'descending' => 'desc'];
@ -49,6 +52,7 @@ final readonly class ManagingProductsContext implements Context
private IriConverterInterface $iriConverter,
private SharedStorageInterface $sharedStorage,
private string $apiUrlPrefix,
private ?NameConverterInterface $nameConverter,
) {
}
@ -360,10 +364,12 @@ final readonly class ManagingProductsContext implements Context
{
$images = $this->responseChecker->getValue($this->client->showByIri($this->sharedStorage->get('productIri')), 'images');
$productCode = $this->responseChecker->getValue($this->client->getLastResponse(), 'code');
$typeKey = $this->getNormalizedKey('type');
$idKey = $this->getNormalizedKey('id');
foreach ($images as $key => $imageData) {
if ($imageData['type'] === $imageType) {
$imageId = $imageData['id'];
if ($imageData[$typeKey] === $imageType) {
$imageId = $imageData[$idKey];
}
}
@ -541,7 +547,7 @@ final readonly class ManagingProductsContext implements Context
public function iShouldSeeVariants(int $count): void
{
Assert::count(
$this->responseChecker->getResponseContent($this->client->getLastResponse())['variants'] ?? [],
$this->responseChecker->getResponseContent($this->client->getLastResponse())[$this->getNormalizedKey('variants')] ?? [],
$count,
);
}
@ -650,8 +656,11 @@ final readonly class ManagingProductsContext implements Context
{
$images = $this->responseChecker->getValue($this->client->showByIri($this->sharedStorage->get('productIri')), 'images');
Assert::same($images[count($images) - 2]['type'], $imageType);
Assert::same($images[count($images) - 2]['position'], $position);
$typeKey = $this->getNormalizedKey('type');
$positionKey = $this->getNormalizedKey('position');
Assert::same($images[count($images) - 2][$typeKey], $imageType);
Assert::same($images[count($images) - 2][$positionKey], $position);
}
/**
@ -661,8 +670,11 @@ final readonly class ManagingProductsContext implements Context
{
$images = $this->responseChecker->getValue($this->client->showByIri($this->sharedStorage->get('productIri')), 'images');
Assert::same($images[count($images) - 1]['type'], $imageType);
Assert::same($images[count($images) - 1]['position'], $position);
$typeKey = $this->getNormalizedKey('type');
$positionKey = $this->getNormalizedKey('position');
Assert::same($images[count($images) - 1][$typeKey], $imageType);
Assert::same($images[count($images) - 1][$positionKey], $position);
}
/**
@ -831,7 +843,7 @@ final readonly class ManagingProductsContext implements Context
$productFromResponse = $this->responseChecker->getResponseContent($response);
Assert::true(
in_array($this->iriConverter->getIriFromResourceInSection($productOption, 'admin'), $productFromResponse['options'], true),
in_array($this->iriConverter->getIriFromResourceInSection($productOption, 'admin'), $productFromResponse[$this->getNormalizedKey('options')], true),
sprintf('Product with option %s does not exist', $productOption->getName()),
);
}
@ -976,8 +988,9 @@ final readonly class ManagingProductsContext implements Context
public function productShouldNotHaveAttribute(ProductInterface $product, ProductAttributeInterface $attribute): void
{
$attributes = $this->responseChecker->getValue($this->client->getLastResponse(), 'attributes');
$attributeKey = $this->getNormalizedKey('attribute');
foreach ($attributes as $attributeValue) {
if ($attributeValue['attribute'] === $this->iriConverter->getIriFromResourceInSection($attribute, 'admin')) {
if ($attributeValue[$attributeKey] === $this->iriConverter->getIriFromResourceInSection($attribute, 'admin')) {
throw new \InvalidArgumentException(
sprintf('Product %s have attribute %s', $product->getName(), $attribute->getName()),
);
@ -1093,11 +1106,14 @@ final readonly class ManagingProductsContext implements Context
private function getFieldValueOfProduct(array $product, string $field): ?string
{
if ($field === 'code') {
return $product['code'];
return $product[$this->getNormalizedKey('code')];
}
if ($field === 'name') {
return $product['translations'][$this->getAdminLocaleCode()]['name'] ?? null;
$translationsKey = $this->getNormalizedKey('translations');
$nameKey = $this->getNormalizedKey('name');
return $product[$translationsKey][$this->getAdminLocaleCode()][$nameKey] ?? null;
}
return null;
@ -1106,10 +1122,12 @@ final readonly class ManagingProductsContext implements Context
private function hasProductImage(Response $response, ProductInterface $product): bool
{
$productFromResponse = $this->responseChecker->getResponseContent($response);
$imagesKey = $this->getNormalizedKey('images');
$pathKey = $this->getNormalizedKey('path');
return
isset($productFromResponse['images'][0]) &&
str_contains($productFromResponse['images'][0]['path'], $product->getImages()->first()->getPath())
isset($productFromResponse[$imagesKey][0]) &&
str_contains($productFromResponse[$imagesKey][0][$pathKey], $product->getImages()->first()->getPath())
;
}
@ -1171,9 +1189,12 @@ final readonly class ManagingProductsContext implements Context
$attributeIri = $this->iriConverter->getIriFromResourceInSection($attribute, 'admin');
$attributes = $this->responseChecker->getValue($this->client->getLastResponse(), 'attributes');
$attributeKey = $this->getNormalizedKey('attribute');
$localeCodeKey = $this->getNormalizedKey('localeCode');
$valueKey = $this->getNormalizedKey('value');
foreach ($attributes as $attributeValue) {
if ($attributeValue['attribute'] === $attributeIri && $attributeValue['localeCode'] === $localeCode) {
$this->assertAttributeValue($value, $attributeValue['value']);
if ($attributeValue[$attributeKey] === $attributeIri && $attributeValue[$localeCodeKey] === $localeCode) {
$this->assertAttributeValue($value, $attributeValue[$valueKey]);
return;
}

View file

@ -18,6 +18,7 @@ use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\Admin\Helper\ValidationTrait;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\ProductInterface;
@ -35,16 +36,19 @@ use Sylius\Component\Core\Promotion\Checker\Rule\ItemTotalRuleChecker;
use Sylius\Component\Core\Promotion\Checker\Rule\TotalOfItemsFromTaxonRuleChecker;
use Sylius\Component\Customer\Model\CustomerGroupInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final readonly class ManagingPromotionsContext implements Context
{
use ValidationTrait;
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private IriConverterInterface $iriConverter,
private ?NameConverterInterface $nameConverter,
) {
}
@ -509,7 +513,7 @@ final readonly class ManagingPromotionsContext implements Context
));
Assert::true(
$returnedPromotion['couponBased'],
$returnedPromotion[$this->getNormalizedKey('couponBased')],
sprintf('The promotion %s isn\'t coupon based', $promotion->getName()),
);
}
@ -659,9 +663,12 @@ final readonly class ManagingPromotionsContext implements Context
public function itShouldHaveOfItemPercentageDiscount(float $percentage, ChannelInterface $channel): void
{
$actions = $this->responseChecker->getValue($this->client->getLastResponse(), 'actions');
$typeKey = $this->getNormalizedKey('type');
$configurationKey = $this->getNormalizedKey('configuration');
$percentageKey = $this->getNormalizedKey('percentage');
foreach ($actions as $action) {
if ($action['type'] === 'unit_percentage_discount') {
Assert::same((float) $action['configuration'][$channel->getCode()]['percentage'], $percentage);
if ($action[$typeKey] === 'unit_percentage_discount') {
Assert::same((float) $action[$configurationKey][$channel->getCode()][$percentageKey], $percentage);
}
}
}
@ -672,7 +679,10 @@ final readonly class ManagingPromotionsContext implements Context
public function itShouldHaveOfOrderPercentageDiscount(float $percentage): void
{
$actions = $this->responseChecker->getValue($this->client->getLastResponse(), 'actions');
Assert::same((float) $actions[0]['configuration']['percentage'], $percentage);
Assert::same(
(float) $actions[0][$this->getNormalizedKey('configuration')][$this->getNormalizedKey('percentage')],
$percentage,
);
}
/**
@ -891,9 +901,9 @@ final readonly class ManagingPromotionsContext implements Context
));
Assert::same(
$returnedPromotion['used'],
$returnedPromotion[$this->getNormalizedKey('used')],
$usage,
sprintf('The promotion %s has been used %s times', $promotion->getName(), $returnedPromotion['used']),
sprintf('The promotion %s has been used %s times', $promotion->getName(), $returnedPromotion[$this->getNormalizedKey('used')]),
);
}

View file

@ -0,0 +1,22 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* 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;
trait NormalizedKeyAwareTrait
{
private function getNormalizedKey(string $key): string
{
return $this->nameConverter?->normalize($key) ?? $key;
}
}

View file

@ -16,20 +16,25 @@ namespace Sylius\Behat\Context\Api\Shop;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Service\Converter\IriConverterInterface;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Addressing\Model\ProvinceInterface;
use Sylius\Component\Core\Model\AddressInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final readonly class AddressContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private IriConverterInterface $iriConverter,
private SharedStorageInterface $sharedStorage,
private ?NameConverterInterface $nameConverter,
) {
}
@ -359,7 +364,7 @@ final readonly class AddressContext implements Context
{
$response = $this->responseChecker->getResponseContent($this->client->getLastResponse());
Assert::same(count($response['violations']), $expectedCount);
Assert::same(count($response[$this->getNormalizedKey('violations')]), $expectedCount);
}
/**
@ -438,16 +443,25 @@ final readonly class AddressContext implements Context
private function addressBookHasAddress(array $addressBook, AddressInterface $addressToCompare): bool
{
$firstNameKey = $this->getNormalizedKey('firstName');
$lastNameKey = $this->getNormalizedKey('lastName');
$countryCodeKey = $this->getNormalizedKey('countryCode');
$streetKey = $this->getNormalizedKey('street');
$cityKey = $this->getNormalizedKey('city');
$postcodeKey = $this->getNormalizedKey('postcode');
$provinceNameKey = $this->getNormalizedKey('provinceName');
$provinceCodeKey = $this->getNormalizedKey('provinceCode');
foreach ($addressBook as $address) {
if (
$address['firstName'] === $addressToCompare->getFirstName() &&
$address['lastName'] === $addressToCompare->getLastName() &&
$address['countryCode'] === $addressToCompare->getCountryCode() &&
$address['street'] === $addressToCompare->getStreet() &&
$address['city'] === $addressToCompare->getCity() &&
$address['postcode'] === $addressToCompare->getPostcode() &&
$address['provinceName'] === $addressToCompare->getProvinceName() &&
$address['provinceCode'] === $addressToCompare->getProvinceCode()
$address[$firstNameKey] === $addressToCompare->getFirstName() &&
$address[$lastNameKey] === $addressToCompare->getLastName() &&
$address[$countryCodeKey] === $addressToCompare->getCountryCode() &&
$address[$streetKey] === $addressToCompare->getStreet() &&
$address[$cityKey] === $addressToCompare->getCity() &&
$address[$postcodeKey] === $addressToCompare->getPostcode() &&
$address[$provinceNameKey] === $addressToCompare->getProvinceName() &&
$address[$provinceCodeKey] === $addressToCompare->getProvinceCode()
) {
return true;
}
@ -460,12 +474,15 @@ final readonly class AddressContext implements Context
{
Assert::notNull($fullName);
[$firstName, $lastName] = explode(' ', $fullName);
$firstNameKey = $this->getNormalizedKey('firstName');
$lastNameKey = $this->getNormalizedKey('lastName');
$idKey = $this->getNormalizedKey('id');
$addresses = $this->responseChecker->getCollection($this->client->getLastResponse());
/** @var AddressInterface $address */
foreach ($addresses as $address) {
if ($firstName === $address['firstName'] && $lastName === $address['lastName']) {
return (string) $address['id'];
if ($firstName === $address[$firstNameKey] && $lastName === $address[$lastNameKey]) {
return (string) $address[$idKey];
}
}
@ -487,11 +504,13 @@ final readonly class AddressContext implements Context
{
Assert::notNull($fullName);
[$firstName, $lastName] = explode(' ', $fullName);
$firstNameKey = $this->getNormalizedKey('firstName');
$lastNameKey = $this->getNormalizedKey('lastName');
$addresses = $this->responseChecker->getCollection($this->client->index(Resources::ADDRESSES));
/** @var AddressInterface $address */
foreach ($addresses as $address) {
if ($firstName === $address['firstName'] && $lastName === $address['lastName']) {
if ($firstName === $address[$firstNameKey] && $lastName === $address[$lastNameKey]) {
return $address['@id'];
}
}

View file

@ -20,6 +20,7 @@ use Behat\Step\When;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\RequestFactoryInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Behat\Service\SprintfResponseEscaper;
@ -31,10 +32,13 @@ use Sylius\Component\Locale\Model\LocaleInterface;
use Sylius\Component\Product\Resolver\ProductVariantResolverInterface;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final class CartContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $shopClient,
private ApiClientInterface $adminClient,
@ -45,6 +49,7 @@ final class CartContext implements Context
private RequestFactoryInterface $requestFactory,
private string $apiUrlPrefix,
private OrderRepositoryInterface $orderRepository,
private ?NameConverterInterface $nameConverter,
) {
}
@ -146,19 +151,24 @@ final class CartContext implements Context
string $productOptionValue,
): void {
$productData = json_decode($this->shopClient->show(Resources::PRODUCTS, $product->getCode())->getContent(), true, 512, \JSON_THROW_ON_ERROR);
$optionsKey = $this->getNormalizedKey('options');
$nameKey = $this->getNormalizedKey('name');
$valuesKey = $this->getNormalizedKey('values');
$valueKey = $this->getNormalizedKey('value');
$codeKey = $this->getNormalizedKey('code');
$variantIri = null;
foreach ($productData['options'] as $optionIri) {
foreach ($productData[$optionsKey] as $optionIri) {
$optionData = json_decode($this->shopClient->showByIri($optionIri)->getContent(), true, 512, \JSON_THROW_ON_ERROR);
if ($optionData['name'] !== $productOption) {
if ($optionData[$nameKey] !== $productOption) {
continue;
}
foreach ($optionData['values'] as $valueIri) {
foreach ($optionData[$valuesKey] as $valueIri) {
$optionValueData = json_decode($this->shopClient->showByIri($valueIri)->getContent(), true, 512, \JSON_THROW_ON_ERROR);
if ($optionValueData['value'] !== $productOptionValue) {
if ($optionValueData[$valueKey] !== $productOptionValue) {
continue;
}
@ -170,7 +180,7 @@ final class CartContext implements Context
Assert::same($variantsData['hydra:totalItems'], 1);
$variantIri = $variantsData['@id'] . '/' . $variantsData['hydra:member'][0]['code'];
$variantIri = $variantsData['@id'] . '/' . $variantsData['hydra:member'][0][$codeKey];
}
}
@ -188,7 +198,7 @@ final class CartContext implements Context
'items',
);
$request->updateContent([
'productCode' => $productData['code'],
'productCode' => $productData[$codeKey],
'productVariant' => $variantIri,
'quantity' => 1,
]);
@ -211,14 +221,14 @@ final class CartContext implements Context
}
$itemResponse = $this->getOrderItemResponseFromProductInCart($product, $tokenValue);
$this->changeQuantityOfOrderItem((string) $itemResponse['id'], $quantity, $tokenValue);
$this->changeQuantityOfOrderItem((string) $itemResponse[$this->getNormalizedKey('id')], $quantity, $tokenValue);
}
#[When('/^I remove (product "[^"]+") from the (cart)$/')]
public function iRemoveProductFromTheCart(ProductInterface $product, string $tokenValue): void
{
$itemResponse = $this->getOrderItemResponseFromProductInCart($product, $tokenValue);
$this->removeOrderItemFromCart((string) $itemResponse['id'], $tokenValue);
$this->removeOrderItemFromCart((string) $itemResponse[$this->getNormalizedKey('id')], $tokenValue);
}
/**
@ -227,7 +237,7 @@ final class CartContext implements Context
public function iRemoveVariantFromTheCart(ProductVariantInterface $variant, string $tokenValue): void
{
$itemResponse = $this->getOrderItemResponseFromProductVariantInCart($variant, $tokenValue);
$this->removeOrderItemFromCart((string) $itemResponse['id'], $tokenValue);
$this->removeOrderItemFromCart((string) $itemResponse[$this->getNormalizedKey('id')], $tokenValue);
}
/**
@ -448,10 +458,12 @@ final class CartContext implements Context
public function iShouldSeeProductWithUnitPriceInMyCart(string $productName, int $unitPrice): void
{
$response = $this->shopClient->getLastResponse();
$productNameKey = $this->getNormalizedKey('productName');
$unitPriceKey = $this->getNormalizedKey('unitPrice');
foreach ($this->responseChecker->getValue($response, 'items') as $item) {
if ($item['productName'] === $productName) {
Assert::same($item['unitPrice'], $unitPrice);
if ($item[$productNameKey] === $productName) {
Assert::same($item[$unitPriceKey], $unitPrice);
return;
}
@ -467,10 +479,12 @@ final class CartContext implements Context
public function iShouldSeeProductWithDiscountedUnitPriceInMyCart(string $productName, int $discountedUnitPrice): void
{
$response = $this->shopClient->getLastResponse();
$productNameKey = $this->getNormalizedKey('productName');
$discountedUnitPriceKey = $this->getNormalizedKey('discountedUnitPrice');
foreach ($this->responseChecker->getValue($response, 'items') as $item) {
if ($item['productName'] === $productName) {
Assert::same($item['discountedUnitPrice'], $discountedUnitPrice);
if ($item[$productNameKey] === $productName) {
Assert::same($item[$discountedUnitPriceKey], $discountedUnitPrice);
return;
}
@ -486,10 +500,12 @@ final class CartContext implements Context
public function theProductShouldHaveTotalPriceInTheCart(string $productName, int $totalPrice): void
{
$response = $this->shopClient->getLastResponse();
$productNameKey = $this->getNormalizedKey('productName');
$totalKey = $this->getNormalizedKey('total');
foreach ($this->responseChecker->getValue($response, 'items') as $item) {
if ($item['productName'] === $productName) {
Assert::same($item['total'], $totalPrice);
if ($item[$productNameKey] === $productName) {
Assert::same($item[$totalKey], $totalPrice);
return;
}
@ -510,7 +526,7 @@ final class CartContext implements Context
Assert::count($items, 1);
if (null !== $productName) {
Assert::same($items[0]['productName'], $productName);
Assert::same($items[0][$this->getNormalizedKey('productName')], $productName);
}
$this->sharedStorage->set('item', $items[0]);
@ -767,19 +783,23 @@ final class CartContext implements Context
public function thisItemShouldHaveOptionValue(string $expectedOptionName, string $expectedOptionValueValue): void
{
$item = $this->sharedStorage->get('item');
$variantKey = $this->getNormalizedKey('variant');
$valueKey = $this->getNormalizedKey('value');
$optionKey = $this->getNormalizedKey('option');
$nameKey = $this->getNormalizedKey('name');
$optionValues = $this->responseChecker->getValue($this->shopClient->showByIri($item['variant']), 'optionValues');
$optionValues = $this->responseChecker->getValue($this->shopClient->showByIri($item[$variantKey]), 'optionValues');
foreach ($optionValues as $optionValueIri) {
$optionValue = $this->responseChecker->getResponseContent($this->shopClient->showByIri($optionValueIri));
if ($optionValue['value'] !== $expectedOptionValueValue) {
if ($optionValue[$valueKey] !== $expectedOptionValueValue) {
continue;
}
$option = $this->responseChecker->getResponseContent($this->shopClient->showByIri($optionValue['option']));
$option = $this->responseChecker->getResponseContent($this->shopClient->showByIri($optionValue[$optionKey]));
if ($option['name'] === $expectedOptionName) {
if ($option[$nameKey] === $expectedOptionName) {
return;
}
}
@ -795,10 +815,12 @@ final class CartContext implements Context
public function iShouldSeeWithOriginalPriceInMyCart(string $productName, int $originalPrice): void
{
$response = $this->shopClient->getLastResponse();
$productNameKey = $this->getNormalizedKey('productName');
$originalUnitPriceKey = $this->getNormalizedKey('originalUnitPrice');
foreach ($this->responseChecker->getValue($response, 'items') as $item) {
if ($item['productName'] === $productName) {
Assert::same($item['originalUnitPrice'], $originalPrice);
if ($item[$productNameKey] === $productName) {
Assert::same($item[$originalUnitPriceKey], $originalPrice);
return;
}
@ -813,11 +835,14 @@ final class CartContext implements Context
public function iShouldSeeOnlyWithUnitPriceInMyCart(string $productName, int $unitPrice): void
{
$response = $this->shopClient->getLastResponse();
$productNameKey = $this->getNormalizedKey('productName');
$unitPriceKey = $this->getNormalizedKey('unitPrice');
$originalPriceKey = $this->getNormalizedKey('originalPrice');
foreach ($this->responseChecker->getValue($response, 'items') as $item) {
if ($item['productName'] === $productName) {
Assert::same($item['unitPrice'], $unitPrice);
Assert::false(isset($item['originalPrice']));
if ($item[$productNameKey] === $productName) {
Assert::same($item[$unitPriceKey], $unitPrice);
Assert::false(isset($item[$originalPriceKey]));
return;
}
@ -907,28 +932,32 @@ final class CartContext implements Context
private function getProductForItem(array $item): Response
{
if (!isset($item['variant'])) {
$variantKey = $this->getNormalizedKey('variant');
if (!isset($item[$variantKey])) {
throw new \InvalidArgumentException(
'Expected array to have variant key and variant to have product, but one these keys is missing. Current array: ' .
serialize($item),
);
}
$response = $this->shopClient->showByIri(urldecode($item['variant']));
$response = $this->shopClient->showByIri(urldecode($item[$variantKey]));
return $this->shopClient->showByIri(urldecode($this->responseChecker->getValue($response, 'product')));
}
private function getProductVariantForItem(array $item): Response
{
if (!isset($item['variant'])) {
$variantKey = $this->getNormalizedKey('variant');
if (!isset($item[$variantKey])) {
throw new \InvalidArgumentException(
'Expected array to have variant key and variant to have product, but one these keys is missing. Current array: ' .
serialize($item),
);
}
$request = $this->requestFactory->custom($item['variant'], HttpRequest::METHOD_GET);
$request = $this->requestFactory->custom($item[$variantKey], HttpRequest::METHOD_GET);
$this->shopClient->executeCustomRequest($request);
return $this->shopClient->getLastResponse();
@ -981,9 +1010,11 @@ final class CartContext implements Context
private function hasItemWithNameAndQuantity(Response $response, string $productName, int $quantity): bool
{
$items = $this->responseChecker->getCollection($response);
$productNameKey = $this->getNormalizedKey('productName');
$quantityKey = $this->getNormalizedKey('quantity');
foreach ($items as $item) {
if ($item['productName'] === $productName && $item['quantity'] === $quantity) {
if ($item[$productNameKey] === $productName && $item[$quantityKey] === $quantity) {
return true;
}
}
@ -998,7 +1029,7 @@ final class CartContext implements Context
foreach ($items as $item) {
$productResponse = $this->getProductForItem($item);
if ($this->responseChecker->hasTranslation($productResponse, 'en_US', 'name', $productName)) {
$this->assertItemQuantity($productResponse, $item['quantity'], $quantity);
$this->assertItemQuantity($productResponse, $item[$this->getNormalizedKey('quantity')], $quantity);
return;
}
@ -1014,7 +1045,7 @@ final class CartContext implements Context
foreach ($items as $item) {
$productResponse = $this->getProductForItem($item);
if ($this->responseChecker->hasValue($productResponse, 'name', $productName)) {
$this->assertItemQuantity($cartResponse, $item['quantity'], $quantity);
$this->assertItemQuantity($cartResponse, $item[$this->getNormalizedKey('quantity')], $quantity);
return;
}
@ -1038,10 +1069,12 @@ final class CartContext implements Context
private function compareItemPrice(string $productName, int $productPrice, string $priceType = 'total'): void
{
$items = $this->responseChecker->getValue($this->getCartResponse(), 'items');
$productNameKey = $this->getNormalizedKey('productName');
$priceTypeKey = $this->getNormalizedKey($priceType);
foreach ($items as $item) {
if ($item['productName'] === $productName) {
Assert::same($item[$priceType], $productPrice);
if ($item[$productNameKey] === $productName) {
Assert::same($item[$priceTypeKey], $productPrice);
return;
}
@ -1061,7 +1094,7 @@ final class CartContext implements Context
if ($this->responseChecker->hasValue($productResponse, 'name', $product->getName())) {
$variantForItem = $this->getProductVariantForItem($item);
return $this->responseChecker->getValue($variantForItem, 'price') * $item['quantity'];
return $this->responseChecker->getValue($variantForItem, 'price') * $item[$this->getNormalizedKey('quantity')];
}
}

View file

@ -16,19 +16,24 @@ namespace Sylius\Behat\Context\Api\Shop\Checkout;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\OrderPaymentStates;
use Sylius\Component\Payment\Model\PaymentInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final class CheckoutOrderDetailsContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private SharedStorageInterface $sharedStorage,
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private ?NameConverterInterface $nameConverter,
) {
}
@ -82,7 +87,7 @@ final class CheckoutOrderDetailsContext implements Context
$payments = $this->responseChecker->getValue($response, 'payments');
$payment = end($payments);
$paymentId = $payment['id'];
$paymentId = $payment[$this->getNormalizedKey('id')];
$response = $this->client->requestGet(sprintf('orders/%s/payments/%s', $this->sharedStorage->get('cart_token'), $paymentId));
return $this->responseChecker->getValue($response, 'state');

View file

@ -19,14 +19,18 @@ use Behat\Step\Then;
use Behat\Step\When;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\ShippingMethodInterface;
use Sylius\Component\Core\OrderCheckoutStates;
use Sylius\Component\Core\Repository\ShippingMethodRepositoryInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final readonly class CheckoutShippingContext implements Context
{
use NormalizedKeyAwareTrait;
/** @param ShippingMethodRepositoryInterface<ShippingMethodInterface> $shippingMethodRepository */
public function __construct(
private ApiClientInterface $client,
@ -34,6 +38,7 @@ final readonly class CheckoutShippingContext implements Context
private SharedStorageInterface $sharedStorage,
private IriConverterInterface $iriConverter,
private ShippingMethodRepositoryInterface $shippingMethodRepository,
private ?NameConverterInterface $nameConverter,
) {
}
@ -55,7 +60,7 @@ final readonly class CheckoutShippingContext implements Context
uri: sprintf(
'orders/%s/shipments/%s',
$this->sharedStorage->get('cart_token'),
$content['shipments'][0]['id'],
$content[$this->getNormalizedKey('shipments')][0][$this->getNormalizedKey('id')],
),
body: ['shippingMethod' => '/api/v2/shop/shipping-methods/NON_EXISTING'],
);
@ -75,7 +80,7 @@ final readonly class CheckoutShippingContext implements Context
uri: sprintf(
'orders/%s/shipments/%s',
$this->sharedStorage->get('cart_token'),
$content['shipments'][0]['id'],
$content[$this->getNormalizedKey('shipments')][0][$this->getNormalizedKey('id')],
),
body: ['shippingMethod' => $this->iriConverter->getIriFromResource($shippingMethod)],
);
@ -174,7 +179,7 @@ final readonly class CheckoutShippingContext implements Context
uri: sprintf(
'orders/%s/shipments/%s',
$this->sharedStorage->get('cart_token'),
$content['shipments'][0]['id'],
$content[$this->getNormalizedKey('shipments')][0][$this->getNormalizedKey('id')],
),
body: ['shippingMethod' => $this->iriConverter->getIriFromResource(
$shippingMethod ?? $this->shippingMethodRepository->findOneBy([]),

View file

@ -20,6 +20,7 @@ use Behat\Step\When;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\RequestFactoryInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Context\Api\Shop\Checkout\CheckoutShippingContext;
use Sylius\Behat\Service\Converter\IriConverterInterface;
@ -43,10 +44,13 @@ use Sylius\Component\Product\Resolver\ProductVariantResolverInterface;
use Sylius\Resource\Doctrine\Persistence\RepositoryInterface;
use Symfony\Component\HttpFoundation\Request as HTTPRequest;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final class CheckoutContext implements Context
{
use NormalizedKeyAwareTrait;
public const CHECKOUT_STATE_TYPES = [
'address' => OrderCheckoutStates::STATE_ADDRESSED,
'shipping method' => OrderCheckoutStates::STATE_SHIPPING_SELECTED,
@ -73,6 +77,7 @@ final class CheckoutContext implements Context
private readonly AddressFactoryInterface $addressFactory,
private readonly string $shippingMethodClass,
private readonly string $paymentMethodClass,
private readonly ?NameConverterInterface $nameConverter,
) {
}
@ -103,9 +108,9 @@ final class CheckoutContext implements Context
uri: sprintf(
'orders/%s/shipments/%s',
$this->sharedStorage->get('cart_token'),
$content['shipments'][0]['id'],
$content[$this->getNormalizedKey('shipments')][0][$this->getNormalizedKey('id')],
),
body: ['shippingMethod' => $content['shipments'][0]['method']],
body: ['shippingMethod' => $content[$this->getNormalizedKey('shipments')][0][$this->getNormalizedKey('method')]],
);
}
@ -128,7 +133,7 @@ final class CheckoutContext implements Context
uri: sprintf(
'orders/%s/shipments/%s',
$this->sharedStorage->get('cart_token'),
$content['shipments'][0]['id'],
$content[$this->getNormalizedKey('shipments')][0][$this->getNormalizedKey('id')],
),
body: ['shippingMethod' => $this->iriConverter->getIriFromResource($shippingMethod)],
);
@ -470,7 +475,7 @@ final class CheckoutContext implements Context
Resources::ORDERS,
$this->sharedStorage->get('cart_token'),
HTTPRequest::METHOD_PATCH,
sprintf('shipments/%s', $this->getCart()['shipments'][0]['id']),
sprintf('shipments/%s', $this->getCart()[$this->getNormalizedKey('shipments')][0][$this->getNormalizedKey('id')]),
);
$request->setContent([
'shippingMethod' => $this->iriConverter->getIriFromResource(
@ -493,7 +498,7 @@ final class CheckoutContext implements Context
Resources::ORDERS,
$this->sharedStorage->get('cart_token'),
HTTPRequest::METHOD_PATCH,
sprintf('payments/%s', $cart['payments'][0]['id']),
sprintf('payments/%s', $cart[$this->getNormalizedKey('payments')][0][$this->getNormalizedKey('id')]),
);
$request->setContent([
'paymentMethod' => $this->iriConverter->getIriFromResource(
@ -556,7 +561,7 @@ final class CheckoutContext implements Context
Resources::ORDERS,
$this->sharedStorage->get('cart_token'),
HTTPRequest::METHOD_PATCH,
\sprintf('payments/%s', $this->getCart()['payments'][0]['id']),
\sprintf('payments/%s', $this->getCart()[$this->getNormalizedKey('payments')][0][$this->getNormalizedKey('id')]),
);
$request->setContent(['paymentMethod' => $this->iriConverter->getIriFromResource($paymentMethod)]);
@ -628,12 +633,13 @@ final class CheckoutContext implements Context
Assert::notEmpty($payments, 'No payments found in response.');
$paymentMethodIri = $this->iriConverter->getIriFromResource($paymentMethod);
$methodKey = $this->getNormalizedKey('method');
foreach ($payments as $payment) {
if ($payment['method'] !== $paymentMethodIri) {
if ($payment[$methodKey] !== $paymentMethodIri) {
continue;
}
$customRequest = $this->requestFactory->custom($payment['method'], HTTPRequest::METHOD_GET);
$customRequest = $this->requestFactory->custom($payment[$methodKey], HTTPRequest::METHOD_GET);
$paymentMethodResponse = $this->client->executeCustomRequest($customRequest);
Assert::same(
$this->responseChecker->getValue(
@ -704,7 +710,7 @@ final class CheckoutContext implements Context
{
$paymentMethods = $this->getPossiblePaymentMethods();
Assert::notFalse(array_search($paymentMethodName, array_column($paymentMethods, 'name'), true));
Assert::notFalse(array_search($paymentMethodName, array_column($paymentMethods, $this->getNormalizedKey('name')), true));
}
/**
@ -715,7 +721,7 @@ final class CheckoutContext implements Context
$paymentMethods = $this->getPossiblePaymentMethods();
foreach ($paymentMethodsNames as $paymentMethodName) {
Assert::inArray($paymentMethodName, array_column($paymentMethods, 'name'));
Assert::inArray($paymentMethodName, array_column($paymentMethods, $this->getNormalizedKey('name')));
}
}
@ -727,7 +733,7 @@ final class CheckoutContext implements Context
$paymentMethods = $this->getPossiblePaymentMethods();
foreach ($paymentMethodsNames as $paymentMethodName) {
Assert::false(in_array($paymentMethodName, array_column($paymentMethods, 'name'), true));
Assert::false(in_array($paymentMethodName, array_column($paymentMethods, $this->getNormalizedKey('name')), true));
}
}
@ -740,10 +746,10 @@ final class CheckoutContext implements Context
Assert::notEmpty($paymentMethods);
if ($choice === 'first') {
Assert::same(reset($paymentMethods)['name'], $paymentMethodName);
Assert::same(reset($paymentMethods)[$this->getNormalizedKey('name')], $paymentMethodName);
}
if ($choice === 'last') {
Assert::same(end($paymentMethods)['name'], $paymentMethodName);
Assert::same(end($paymentMethods)[$this->getNormalizedKey('name')], $paymentMethodName);
}
}
@ -752,7 +758,7 @@ final class CheckoutContext implements Context
*/
public function iShouldStillBeOnTheCheckoutAddressingStep(): void
{
Assert::same($this->getCart()['checkoutState'], OrderCheckoutStates::STATE_CART);
Assert::same($this->getCart()[$this->getNormalizedKey('checkoutState')], OrderCheckoutStates::STATE_CART);
}
/**
@ -773,7 +779,7 @@ final class CheckoutContext implements Context
{
$response = $this->client->getLastResponse();
Assert::true(empty($this->responseChecker->getResponseContent($response)['payments']));
Assert::true(empty($this->responseChecker->getResponseContent($response)[$this->getNormalizedKey('payments')]));
}
/**
@ -801,7 +807,7 @@ final class CheckoutContext implements Context
$paymentMethodName = $paymentMethod->getName();
foreach ($paymentMethods as $method) {
if ($method['name'] === $paymentMethodName) {
if ($method[$this->getNormalizedKey('name')] === $paymentMethodName) {
return;
}
}
@ -818,7 +824,7 @@ final class CheckoutContext implements Context
$shippingMethodName = $shippingMethod->getName();
foreach ($shippingMethods as $method) {
if ($method['name'] === $shippingMethodName) {
if ($method[$this->getNormalizedKey('name')] === $shippingMethodName) {
return;
}
}
@ -838,7 +844,7 @@ final class CheckoutContext implements Context
public function iShouldNotBeAbleToProceedCheckoutShippingStep(): void
{
Assert::same($this->getCheckoutState(), OrderCheckoutStates::STATE_ADDRESSED);
Assert::isEmpty($this->getCart()['shipments']);
Assert::isEmpty($this->getCart()[$this->getNormalizedKey('shipments')]);
}
/**
@ -847,7 +853,7 @@ final class CheckoutContext implements Context
public function iShouldNotBeAbleToProceedCheckoutPaymentStep(): void
{
$this->iShouldBeOnTheCheckoutPaymentStep();
Assert::isEmpty($this->getCart()['payments']);
Assert::isEmpty($this->getCart()[$this->getNormalizedKey('payments')]);
}
/**
@ -938,7 +944,7 @@ final class CheckoutContext implements Context
{
$shippingMethods = $this->getCartShippingMethods($this->getCart());
Assert::true($shippingMethods[0]['code'] === $shippingMethod->getCode());
Assert::true($shippingMethods[0][$this->getNormalizedKey('code')] === $shippingMethod->getCode());
}
/**
@ -948,7 +954,7 @@ final class CheckoutContext implements Context
{
$shippingMethods = $this->getCartShippingMethods($this->getCart());
Assert::true(end($shippingMethods)['code'] === $shippingMethod->getCode());
Assert::true(end($shippingMethods)[$this->getNormalizedKey('code')] === $shippingMethod->getCode());
}
/**
@ -956,7 +962,7 @@ final class CheckoutContext implements Context
*/
public function myOrderTotalShouldBe(int $total): void
{
Assert::same($total, (int) $this->getCart()['total']);
Assert::same($total, (int) $this->getCart()[$this->getNormalizedKey('total')]);
}
/**
@ -1052,7 +1058,7 @@ final class CheckoutContext implements Context
Assert::true($response->getStatusCode() === 422);
/** @var array|null $violations */
$violations = $this->responseChecker->getResponseContent($response)['violations'];
$violations = $this->responseChecker->getResponseContent($response)[$this->getNormalizedKey('violations')];
$detailType .= 'Address';
@ -1061,7 +1067,7 @@ final class CheckoutContext implements Context
$violations,
$detailType . '.' . StringInflector::nameToCamelCase($element),
);
Assert::same($violation['message'], sprintf('Please enter %s.', $element));
Assert::same($violation[$this->getNormalizedKey('message')], sprintf('Please enter %s.', $element));
}
}
@ -1071,14 +1077,14 @@ final class CheckoutContext implements Context
public function iShouldBeNotifiedThatTheInShippingDetailsIsRequired(string $element, string $type): void
{
/** @var array|null $violations */
$violations = $this->responseChecker->getResponseContent($this->client->getLastResponse())['violations'];
$violations = $this->responseChecker->getResponseContent($this->client->getLastResponse())[$this->getNormalizedKey('violations')];
$type .= 'Address';
$violation = $this->getViolation(
$violations,
$type . '.' . StringInflector::nameToCamelCase($element),
);
Assert::same($violation['message'], sprintf('Please enter %s.', $element));
Assert::same($violation[$this->getNormalizedKey('message')], sprintf('Please enter %s.', $element));
}
/**
@ -1302,9 +1308,11 @@ final class CheckoutContext implements Context
public function iShouldBeCheckingOutAs(string $email): void
{
$cart = $this->getCart();
$customerKey = $this->getNormalizedKey('customer');
$emailKey = $this->getNormalizedKey('email');
Assert::notNull($cart['customer'], sprintf('Customer with an email "%s" was not expected to be null.', $email));
Assert::same($cart['customer']['email'], $email);
Assert::notNull($cart[$customerKey], sprintf('Customer with an email "%s" was not expected to be null.', $email));
Assert::same($cart[$customerKey][$emailKey], $email);
}
/**
@ -1399,7 +1407,11 @@ final class CheckoutContext implements Context
private function getCartShippingMethods(array $cart): array
{
$this->client->customAction(
sprintf('/api/v2/shop/orders/%s/shipments/%s/methods', $cart['tokenValue'], $cart['shipments'][0]['id']),
sprintf(
'/api/v2/shop/orders/%s/shipments/%s/methods',
$cart[$this->getNormalizedKey('tokenValue')],
$cart[$this->getNormalizedKey('shipments')][0][$this->getNormalizedKey('id')],
),
HTTPRequest::METHOD_GET,
);
@ -1409,7 +1421,7 @@ final class CheckoutContext implements Context
private function hasShippingMethod(ShippingMethodInterface $shippingMethod): bool
{
foreach ($this->getCartShippingMethods($this->getCart()) as $cartShippingMethod) {
if ($cartShippingMethod['code'] === $shippingMethod->getCode()) {
if ($cartShippingMethod[$this->getNormalizedKey('code')] === $shippingMethod->getCode()) {
return true;
}
}
@ -1421,8 +1433,8 @@ final class CheckoutContext implements Context
{
foreach ($this->getCartShippingMethods($this->getCart()) as $cartShippingMethod) {
if (
$cartShippingMethod['price'] === $fee &&
$cartShippingMethod['code'] === $shippingMethod->getCode()
$cartShippingMethod[$this->getNormalizedKey('price')] === $fee &&
$cartShippingMethod[$this->getNormalizedKey('code')] === $shippingMethod->getCode()
) {
return true;
}
@ -1455,7 +1467,10 @@ final class CheckoutContext implements Context
$items = $this->responseChecker->getValue($this->client->getLastResponse(), 'items');
foreach ($items as $item) {
if ($item['productName'] === $productName && $item['quantity'] === $quantity) {
if (
$item[$this->getNormalizedKey('productName')] === $productName &&
$item[$this->getNormalizedKey('quantity')] === $quantity
) {
return true;
}
}
@ -1469,7 +1484,10 @@ final class CheckoutContext implements Context
$items = $this->responseChecker->getValue($this->client->getLastResponse(), 'items');
foreach ($items as $item) {
if ($item['productName'] === $productName && $item['unitPrice'] === $unitPrice) {
if (
$item[$this->getNormalizedKey('productName')] === $productName &&
$item[$this->getNormalizedKey('unitPrice')] === $unitPrice
) {
return true;
}
}
@ -1516,7 +1534,7 @@ final class CheckoutContext implements Context
private function getViolation(array $violations, string $element): array
{
return $violations[array_search($element, array_column($violations, 'propertyPath'), true)];
return $violations[array_search($element, array_column($violations, $this->getNormalizedKey('propertyPath')), true)];
}
private function hasFullNameInAddress(string $fullName, string $addressType): void
@ -1527,11 +1545,11 @@ final class CheckoutContext implements Context
$addressType .= 'Address';
Assert::same(
$this->responseChecker->getResponseContent($response)[$addressType]['firstName'],
$this->responseChecker->getResponseContent($response)[$addressType][$this->getNormalizedKey('firstName')],
$names[0],
);
Assert::same(
$this->responseChecker->getResponseContent($response)[$addressType]['lastName'],
$this->responseChecker->getResponseContent($response)[$addressType][$this->getNormalizedKey('lastName')],
$names[1],
);
}
@ -1542,7 +1560,7 @@ final class CheckoutContext implements Context
$addressType .= 'Address';
Assert::same(
$this->responseChecker->getResponseContent($response)[$addressType]['provinceName'],
$this->responseChecker->getResponseContent($response)[$addressType][$this->getNormalizedKey('provinceName')],
$provinceName,
);
}
@ -1587,6 +1605,8 @@ final class CheckoutContext implements Context
private function getAddressByFieldValue(array $addressBook, string $fieldName, string $fieldValue): array
{
$fieldName = $this->getNormalizedKey($fieldName);
foreach ($addressBook as $address) {
if ($address[$fieldName] === $fieldValue) {
return $address;
@ -1601,15 +1621,23 @@ final class CheckoutContext implements Context
*/
private function addressesAreEqual(array $address, AddressInterface $addressToCompare): bool
{
$firstNameKey = $this->getNormalizedKey('firstName');
$lastNameKey = $this->getNormalizedKey('lastName');
$countryCodeKey = $this->getNormalizedKey('countryCode');
$streetKey = $this->getNormalizedKey('street');
$cityKey = $this->getNormalizedKey('city');
$postcodeKey = $this->getNormalizedKey('postcode');
$provinceNameKey = $this->getNormalizedKey('provinceName');
if (
$address['firstName'] === $addressToCompare->getFirstName() &&
$address['lastName'] === $addressToCompare->getLastName() &&
$address['countryCode'] === $addressToCompare->getCountryCode() &&
$address['street'] === $addressToCompare->getStreet() &&
$address['city'] === $addressToCompare->getCity() &&
$address['postcode'] === $addressToCompare->getPostcode() &&
($addressToCompare->getProvinceName() !== null && isset($address['provinceName'])) ?
$address['provinceName'] === $addressToCompare->getProvinceName() : true
$address[$firstNameKey] === $addressToCompare->getFirstName() &&
$address[$lastNameKey] === $addressToCompare->getLastName() &&
$address[$countryCodeKey] === $addressToCompare->getCountryCode() &&
$address[$streetKey] === $addressToCompare->getStreet() &&
$address[$cityKey] === $addressToCompare->getCity() &&
$address[$postcodeKey] === $addressToCompare->getPostcode() &&
($addressToCompare->getProvinceName() !== null && isset($address[$provinceNameKey])) ?
$address[$provinceNameKey] === $addressToCompare->getProvinceName() : true
) {
return true;
}
@ -1649,7 +1677,7 @@ final class CheckoutContext implements Context
Resources::ORDERS,
$this->sharedStorage->get('cart_token'),
HTTPRequest::METHOD_PATCH,
sprintf('shipments/%s', $this->getCart()['shipments'][0]['id']),
sprintf('shipments/%s', $this->getCart()[$this->getNormalizedKey('shipments')][0][$this->getNormalizedKey('id')]),
);
$request->setContent(['shippingMethod' => $this->iriConverter->getIriFromResource($shippingMethod)]);

View file

@ -16,14 +16,19 @@ namespace Sylius\Behat\Context\Api\Shop;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final readonly class ExchangeRateContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private ?NameConverterInterface $nameConverter,
) {
}
@ -50,7 +55,7 @@ final readonly class ExchangeRateContext implements Context
{
$exchangeRate = $this->getExchangeRateByTargetCurrency($sourceCurrency, $targetCurrency);
Assert::same($exchangeRate['ratio'], $ratio);
Assert::same($exchangeRate[$this->getNormalizedKey('ratio')], $ratio);
}
/**
@ -71,8 +76,8 @@ final readonly class ExchangeRateContext implements Context
foreach ($exchangeRates as $exchangeRate) {
if (
str_ends_with($exchangeRate['sourceCurrency'], $sourceCurrencyCode) &&
str_ends_with($exchangeRate['targetCurrency'], $targetCurrencyCode)
str_ends_with($exchangeRate[$this->getNormalizedKey('sourceCurrency')], $sourceCurrencyCode) &&
str_ends_with($exchangeRate[$this->getNormalizedKey('targetCurrency')], $targetCurrencyCode)
) {
return $exchangeRate;
}

View file

@ -18,6 +18,7 @@ use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\RequestFactoryInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Service\SecurityServiceInterface;
use Sylius\Behat\Service\SharedStorageInterface;
@ -32,10 +33,13 @@ use Sylius\Component\Core\Model\PromotionInterface;
use Sylius\Component\Core\OrderCheckoutStates;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final readonly class OrderContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $shopClient,
private ApiClientInterface $adminClient,
@ -45,6 +49,7 @@ final readonly class OrderContext implements Context
private SecurityServiceInterface $securityService,
private RequestFactoryInterface $requestFactory,
private string $apiUrlPrefix,
private ?NameConverterInterface $nameConverter,
) {
}
@ -134,15 +139,21 @@ final readonly class OrderContext implements Context
string $addressType,
): void {
$address = $this->responseChecker->getValue($this->shopClient->getLastResponse(), ($addressType . 'Address'));
$firstNameKey = $this->getNormalizedKey('firstName');
$lastNameKey = $this->getNormalizedKey('lastName');
$streetKey = $this->getNormalizedKey('street');
$postcodeKey = $this->getNormalizedKey('postcode');
$cityKey = $this->getNormalizedKey('city');
$countryCodeKey = $this->getNormalizedKey('countryCode');
$names = explode(' ', $customerName);
Assert::same($address['firstName'], $names[0]);
Assert::same($address['lastName'], $names[1]);
Assert::same($address['street'], $street);
Assert::same($address['postcode'], $postcode);
Assert::same($address['city'], $city);
Assert::same($address['countryCode'], $country->getCode());
Assert::same($address[$firstNameKey], $names[0]);
Assert::same($address[$lastNameKey], $names[1]);
Assert::same($address[$streetKey], $street);
Assert::same($address[$postcodeKey], $postcode);
Assert::same($address[$cityKey], $city);
Assert::same($address[$countryCodeKey], $country->getCode());
}
/**
@ -159,9 +170,10 @@ final readonly class OrderContext implements Context
public function theProductShouldBeInTheItemsList(string $productName): void
{
$items = $this->responseChecker->getValue($this->shopClient->getLastResponse(), 'items');
$productNameKey = $this->getNormalizedKey('productName');
foreach ($items as $item) {
if ($item['productName'] === $productName) {
if ($item[$productNameKey] === $productName) {
return;
}
}
@ -197,7 +209,7 @@ final readonly class OrderContext implements Context
{
$address = $this->responseChecker->getValue($this->shopClient->getLastResponse(), ($addressType . 'Address'));
Assert::same($address['provinceName'], $provinceName);
Assert::same($address[$this->getNormalizedKey('provinceName')], $provinceName);
}
/**
@ -208,9 +220,10 @@ final readonly class OrderContext implements Context
$items = $this->responseChecker->getValue($this->shopClient->getLastResponse(), 'items');
$subtotal = 0;
$subtotalKey = $this->getNormalizedKey('subtotal');
foreach ($items as $item) {
$subtotal = $subtotal + $item['subtotal'];
$subtotal += $item[$subtotalKey];
}
Assert::same($subtotal, $expectedSubtotal);
@ -252,7 +265,7 @@ final readonly class OrderContext implements Context
{
$adjustment = $this->getAdjustmentWithLabel($promotion->getName());
Assert::notNull($adjustment);
Assert::same($discount, $adjustment['amount']);
Assert::same($discount, $adjustment[$this->getNormalizedKey('amount')]);
}
/**
@ -263,8 +276,9 @@ final readonly class OrderContext implements Context
$discount = 0;
$itemId = $this->geOrderItemIdForProductInCart($product, $this->sharedStorage->get('cart_token'));
$adjustments = $this->getAdjustmentsForOrderItem($itemId);
$amountKey = $this->getNormalizedKey('amount');
foreach ($adjustments as $adjustment) {
$discount += $adjustment['amount'];
$discount += $adjustment[$amountKey];
}
Assert::same(-$discount, $amount);
@ -296,7 +310,7 @@ final readonly class OrderContext implements Context
->getValue($this->shopClient->show(Resources::ORDERS, $this->sharedStorage->get('cart_token')), 'payments')[0]
;
Assert::same($this->iriConverter->getIriFromResource($paymentMethod), $payment['method']);
Assert::same($this->iriConverter->getIriFromResource($paymentMethod), $payment[$this->getNormalizedKey('method')]);
}
/**
@ -322,7 +336,7 @@ final readonly class OrderContext implements Context
{
$paymentMethodIri = $this
->responseChecker
->getValue($this->shopClient->getLastResponse(), 'payments')[0]['method']
->getValue($this->shopClient->getLastResponse(), 'payments')[0][$this->getNormalizedKey('method')]
;
Assert::same($this->iriConverter->getResourceFromIri($paymentMethodIri)->getCode(), $paymentMethod->getCode());
@ -384,7 +398,7 @@ final readonly class OrderContext implements Context
foreach ($items as $item) {
$response = $this->getProductForItem($item);
if ($this->responseChecker->hasValue($response, 'code', $product->getCode())) {
return (string) $item['id'];
return (string) $item[$this->getNormalizedKey('id')];
}
}
@ -393,14 +407,14 @@ final readonly class OrderContext implements Context
private function getProductForItem(array $item): Response
{
if (!isset($item['variant'])) {
if (!isset($item[$this->getNormalizedKey('variant')])) {
throw new \InvalidArgumentException(
'Expected array to have variant key, but this key is missing. Current array: ' .
json_encode($item),
);
}
$request = $this->requestFactory->custom($item['variant'], HttpRequest::METHOD_GET);
$request = $this->requestFactory->custom($item[$this->getNormalizedKey('variant')], HttpRequest::METHOD_GET);
$this->shopClient->executeCustomRequest($request);
return $this->shopClient->showByIri($this->responseChecker->getValue($this->shopClient->getLastResponse(), 'product'));
@ -409,7 +423,7 @@ final readonly class OrderContext implements Context
private function getAdjustmentWithLabel(string $label): ?array
{
$adjustments = $this->getAdjustmentsForOrder();
$index = array_search($label, array_column($adjustments, 'label'));
$index = array_search($label, array_column($adjustments, $this->getNormalizedKey('label')));
if ($index) {
return $adjustments[$index];
}
@ -429,7 +443,7 @@ final readonly class OrderContext implements Context
/** @var int $index */
foreach ($adjustments as $index => $adjustment) {
if (-$amounts[$index] !== $adjustment['amount']) {
if (-$amounts[$index] !== $adjustment[$this->getNormalizedKey('amount')]) {
return false;
}
}

View file

@ -16,18 +16,23 @@ namespace Sylius\Behat\Context\Api\Shop;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final readonly class PaymentContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private SharedStorageInterface $sharedStorage,
private ?NameConverterInterface $nameConverter,
) {
}
@ -65,7 +70,7 @@ final readonly class PaymentContext implements Context
$payments = $this->responseChecker->getValue($response, 'payments');
$token = $this->responseChecker->getValue($response, 'tokenValue');
$response = $this->client->requestGet(sprintf('orders/%s/payments/%s', $token, $payments[0]['id']));
$response = $this->client->requestGet(sprintf('orders/%s/payments/%s', $token, $payments[0][$this->getNormalizedKey('id')]));
Assert::true($this->responseChecker->hasValue($response, 'state', $state, isCaseSensitive: false));
}

View file

@ -18,21 +18,26 @@ use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\Request;
use Sylius\Behat\Client\RequestFactoryInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\PaymentMethodInterface;
use Sylius\Component\Payment\Repository\PaymentRequestRepositoryInterface;
use Symfony\Component\HttpFoundation\Request as HTTPRequest;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final readonly class PaymentRequestContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private SharedStorageInterface $sharedStorage,
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private RequestFactoryInterface $requestFactory,
private PaymentRequestRepositoryInterface $paymentRequestRepository,
private ?NameConverterInterface $nameConverter,
) {
}
@ -85,8 +90,8 @@ final readonly class PaymentRequestContext implements Context
);
$request->setContent([
'paymentId' => $payment['id'],
'paymentMethodCode' => $payment['method'],
'paymentId' => $payment[$this->getNormalizedKey('id')],
'paymentMethodCode' => $payment[$this->getNormalizedKey('method')],
'payload' => $payload,
]);
@ -112,7 +117,7 @@ final readonly class PaymentRequestContext implements Context
$orderToken = $this->sharedStorage->get('cart_token');
$order = $this->client->show(Resources::ORDERS, $orderToken);
$payments = $this->responseChecker->getValue($order, 'payments');
$paymentId = end($payments)['id'];
$paymentId = end($payments)[$this->getNormalizedKey('id')];
$paymentRequest = $this->paymentRequestRepository->findOneBy(['payment' => $paymentId, 'action' => $action]);
return $paymentRequest ? $this->requestFactory->custom('/api/v2/shop/payment-requests/' . $paymentRequest->getHash(), HttpRequest::METHOD_GET, [], $this->client->getToken()) : null;

View file

@ -20,6 +20,7 @@ use Doctrine\Persistence\ObjectManager;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\RequestFactoryInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Service\Setter\ChannelContextSetterInterface;
use Sylius\Behat\Service\SharedStorageInterface;
@ -32,10 +33,13 @@ use Sylius\Component\Product\Model\ProductVariantInterface;
use Sylius\Component\Product\Resolver\ProductVariantResolverInterface;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final class ProductContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
@ -46,6 +50,7 @@ final class ProductContext implements Context
private ObjectManager $objectManager,
private string $apiUrlPrefix,
private ProductVariantResolverInterface $productVariantResolver,
private ?NameConverterInterface $nameConverter,
) {
}
@ -289,8 +294,8 @@ final class ProductContext implements Context
$checkedVariant = $this->sharedStorage->get('product_variant');
$variant = $this->fetchItemByIri($this->iriConverter->getIriFromResource($checkedVariant));
Assert::same($variant['price'], $price);
Assert::same($variant['code'], $checkedVariant->getCode());
Assert::same($variant[$this->getNormalizedKey('price')], $price);
Assert::same($variant[$this->getNormalizedKey('code')], $checkedVariant->getCode());
}
/**
@ -303,8 +308,8 @@ final class ProductContext implements Context
$checkedVariant = $this->sharedStorage->get('product_variant');
$variant = $this->responseChecker->getResponseContent($this->client->getLastResponse());
Assert::same($variant['originalPrice'], $originalPrice);
Assert::same($variant['code'], $checkedVariant->getCode());
Assert::same($variant[$this->getNormalizedKey('originalPrice')], $originalPrice);
Assert::same($variant[$this->getNormalizedKey('code')], $checkedVariant->getCode());
}
/**
@ -314,8 +319,8 @@ final class ProductContext implements Context
{
$variant = $this->responseChecker->getResponseContent($this->client->getLastResponse());
Assert::same($variant['originalPrice'], $variant['price']);
Assert::keyNotExists($variant, 'appliedPromotions');
Assert::same($variant[$this->getNormalizedKey('originalPrice')], $variant[$this->getNormalizedKey('price')]);
Assert::keyNotExists($variant, $this->getNormalizedKey('appliedPromotions'));
}
/**
@ -324,8 +329,11 @@ final class ProductContext implements Context
public function iShouldNotSeeAnyOriginalPrice(): void
{
$product = $this->responseChecker->getResponseContent($this->client->getLastResponse());
$defaultVariantDataKey = $this->getNormalizedKey('defaultVariantData');
$originalPriceKey = $this->getNormalizedKey('originalPrice');
$priceKey = $this->getNormalizedKey('price');
Assert::same($product['defaultVariantData']['originalPrice'], $product['defaultVariantData']['price']);
Assert::same($product[$defaultVariantDataKey][$originalPriceKey], $product[$defaultVariantDataKey][$priceKey]);
}
/**
@ -384,7 +392,7 @@ final class ProductContext implements Context
{
$products = $this->responseChecker->getCollection($this->client->getLastResponse());
Assert::same($products[0]['code'], $code);
Assert::same($products[0][$this->getNormalizedKey('code')], $code);
}
/**
@ -394,7 +402,7 @@ final class ProductContext implements Context
{
$products = $this->responseChecker->getCollection($this->client->getLastResponse());
Assert::same(end($products)['code'], $code);
Assert::same(end($products)[$this->getNormalizedKey('code')], $code);
}
/**
@ -404,7 +412,7 @@ final class ProductContext implements Context
{
$products = $this->responseChecker->getCollection($this->client->getLastResponse());
Assert::same($products[0]['name'], $name);
Assert::same($products[0][$this->getNormalizedKey('name')], $name);
}
/**
@ -414,8 +422,8 @@ final class ProductContext implements Context
{
$product = $this->responseChecker->getCollection($this->client->resend())[0];
Assert::same($product['name'], $name);
Assert::same($product['defaultVariantData']['price'], $price);
Assert::same($product[$this->getNormalizedKey('name')], $name);
Assert::same($product[$this->getNormalizedKey('defaultVariantData')][$this->getNormalizedKey('price')], $price);
}
/**
@ -425,7 +433,7 @@ final class ProductContext implements Context
{
$products = $this->responseChecker->getCollection($this->client->getLastResponse());
Assert::same(end($products)['name'], $name);
Assert::same(end($products)[$this->getNormalizedKey('name')], $name);
}
/**
@ -436,8 +444,8 @@ final class ProductContext implements Context
$products = $this->responseChecker->getCollection($this->client->resend());
$product = end($products);
Assert::same($product['name'], $name);
Assert::same($product['defaultVariantData']['price'], $price);
Assert::same($product[$this->getNormalizedKey('name')], $name);
Assert::same($product[$this->getNormalizedKey('defaultVariantData')][$this->getNormalizedKey('price')], $price);
}
/**
@ -477,7 +485,7 @@ final class ProductContext implements Context
{
$images = $this->responseChecker->getValue($this->client->getLastResponse(), 'images');
Assert::same($images[0]['type'], $type);
Assert::same($images[0][$this->getNormalizedKey('type')], $type);
}
/**
@ -487,7 +495,7 @@ final class ProductContext implements Context
{
$images = $this->responseChecker->getValue($this->client->getLastResponse(), 'images');
Assert::same($images[1]['type'], $type);
Assert::same($images[1][$this->getNormalizedKey('type')], $type);
}
/**
@ -540,7 +548,7 @@ final class ProductContext implements Context
$productNamesFromResponse = new ArrayCollection();
foreach ($this->responseChecker->getCollection($this->client->getLastResponse()) as $productItem) {
$productNamesFromResponse->add($productItem['name']);
$productNamesFromResponse->add($productItem[$this->getNormalizedKey('name')]);
}
foreach ($productNamesFromResponse as $key => $name) {
@ -555,7 +563,7 @@ final class ProductContext implements Context
{
$defaultVariant = $this->responseChecker->getValue($this->client->getLastResponse(), 'defaultVariantData');
Assert::same($defaultVariant['price'], $price);
Assert::same($defaultVariant[$this->getNormalizedKey('price')], $price);
}
/**
@ -691,10 +699,10 @@ final class ProductContext implements Context
public function iShouldNotSeeInformationAboutItsLowestPrice(): void
{
$product = $this->responseChecker->getResponseContent($this->client->getLastResponse());
$variant = $product['defaultVariantData'];
$variant = $product[$this->getNormalizedKey('defaultVariantData')];
Assert::keyExists($variant, 'lowestPriceBeforeDiscount');
Assert::same($variant['lowestPriceBeforeDiscount'], null);
Assert::keyExists($variant, $this->getNormalizedKey('lowestPriceBeforeDiscount'));
Assert::same($variant[$this->getNormalizedKey('lowestPriceBeforeDiscount')], null);
}
/**
@ -703,10 +711,10 @@ final class ProductContext implements Context
public function iShouldSeeAsItsLowestPriceBeforeTheDiscount(int $lowestPriceBeforeDiscount): void
{
$product = $this->responseChecker->getResponseContent($this->client->getLastResponse());
$variant = $product['defaultVariantData'];
$variant = $product[$this->getNormalizedKey('defaultVariantData')];
Assert::keyExists($variant, 'lowestPriceBeforeDiscount');
Assert::same($variant['lowestPriceBeforeDiscount'], $lowestPriceBeforeDiscount);
Assert::keyExists($variant, $this->getNormalizedKey('lowestPriceBeforeDiscount'));
Assert::same($variant[$this->getNormalizedKey('lowestPriceBeforeDiscount')], $lowestPriceBeforeDiscount);
}
/**
@ -731,12 +739,15 @@ final class ProductContext implements Context
?string $productCode = null,
string $priceType = 'price',
): bool {
$codeKey = $this->getNormalizedKey('code');
$variantsKey = $this->getNormalizedKey('variants');
foreach ($products as $product) {
if ($productCode !== null && $product['code'] !== $productCode) {
if ($productCode !== null && $product[$codeKey] !== $productCode) {
continue;
}
foreach ($product['variants'] as $variantIri) {
foreach ($product[$variantsKey] as $variantIri) {
$request = $this->requestFactory->custom($variantIri, HttpRequest::METHOD_GET);
$response = $this->client->executeCustomRequest($request);
@ -755,7 +766,7 @@ final class ProductContext implements Context
private function hasProductWithName(array $products, string $name): bool
{
foreach ($products as $product) {
if ($product['name'] === $name) {
if ($product[$this->getNormalizedKey('name')] === $name) {
return true;
}
}
@ -765,8 +776,11 @@ final class ProductContext implements Context
private function hasProductWithNameAndShortDescription(array $products, string $name, string $shortDescription): bool
{
$nameKey = $this->getNormalizedKey('name');
$shortDescriptionKey = $this->getNormalizedKey('shortDescription');
foreach ($products as $product) {
if ($product['name'] === $name && $product['shortDescription'] === $shortDescription) {
if ($product[$nameKey] === $name && $product[$shortDescriptionKey] === $shortDescription) {
return true;
}
}
@ -784,11 +798,14 @@ final class ProductContext implements Context
);
foreach ($productVariants as $productVariant) {
foreach ($productVariant['optionValues'] as $optionValueIri) {
foreach ($productVariant[$this->getNormalizedKey('optionValues')] as $optionValueIri) {
$optionValueData = $this->fetchItemByIri($optionValueIri);
$optionData = $this->fetchItemByIri($optionValueData['option']);
$optionData = $this->fetchItemByIri($optionValueData[$this->getNormalizedKey('option')]);
if ($optionData['name'] === $expectedOptionName && $optionValueData['value'] === $expectedOptionValueValue) {
if (
$optionData[$this->getNormalizedKey('name')] === $expectedOptionName &&
$optionValueData[$this->getNormalizedKey('value')] === $expectedOptionValueValue
) {
return true;
}
}
@ -812,7 +829,7 @@ final class ProductContext implements Context
{
$images = $this->responseChecker->getValue($this->client->getLastResponse(), 'images');
return $images[0]['type'] === 'main' && $images[0]['path'];
return $images[0][$this->getNormalizedKey('type')] === 'main' && $images[0][$this->getNormalizedKey('path')];
}
private function hasAssociationsWithProducts(

View file

@ -17,21 +17,26 @@ use ApiPlatform\Metadata\IriConverterInterface;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Formatter\StringInflector;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Product\Model\ProductOptionValueInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final class ProductVariantContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private SharedStorageInterface $sharedStorage,
private IriConverterInterface $iriConverter,
private ?NameConverterInterface $nameConverter,
) {
}
@ -94,7 +99,7 @@ final class ProductVariantContext implements Context
{
$response = $this->responseChecker->getResponseContent($this->client->getLastResponse());
Assert::same($response['price'], $price);
Assert::same($response[$this->getNormalizedKey('price')], $price);
}
/**
@ -104,7 +109,7 @@ final class ProductVariantContext implements Context
{
$response = $this->responseChecker->getResponseContent($this->client->getLastResponse());
Assert::same($response['originalPrice'], $originalPrice);
Assert::same($response[$this->getNormalizedKey('originalPrice')], $originalPrice);
}
/**
@ -122,13 +127,13 @@ final class ProductVariantContext implements Context
): void {
$content = $this->findVariant($variant);
Assert::same($content['price'], $price);
Assert::same($content['originalPrice'], $originalPrice);
foreach ($content['appliedPromotions'] as $promotionIri) {
Assert::same($content[$this->getNormalizedKey('price')], $price);
Assert::same($content[$this->getNormalizedKey('originalPrice')], $originalPrice);
foreach ($content[$this->getNormalizedKey('appliedPromotions')] as $promotionIri) {
$catalogPromotionContent = $this->responseChecker->getResponseContent(
$this->client->showByIri($promotionIri),
);
Assert::inArray($catalogPromotionContent['label'], $promotionsNames);
Assert::inArray($catalogPromotionContent[$this->getNormalizedKey('label')], $promotionsNames);
}
}
@ -143,9 +148,9 @@ final class ProductVariantContext implements Context
): void {
$content = $this->findVariant($variant);
Assert::same($content['price'], $price);
Assert::same($content['originalPrice'], $originalPrice);
Assert::count($content['appliedPromotions'], $numberOfPromotions);
Assert::same($content[$this->getNormalizedKey('price')], $price);
Assert::same($content[$this->getNormalizedKey('originalPrice')], $originalPrice);
Assert::count($content[$this->getNormalizedKey('appliedPromotions')], $numberOfPromotions);
}
/**
@ -158,13 +163,13 @@ final class ProductVariantContext implements Context
string $promotionName,
): void {
$variantContent = $this->findVariant($variant);
$catalogPromotionResponse = $this->client->showByIri($variantContent['appliedPromotions'][0]);
$catalogPromotionResponse = $this->client->showByIri($variantContent[$this->getNormalizedKey('appliedPromotions')][0]);
$catalogPromotionContent = $this->responseChecker->getResponseContent($catalogPromotionResponse);
Assert::count($variantContent['appliedPromotions'], 1);
Assert::same($variantContent['price'], $price);
Assert::same($variantContent['originalPrice'], $originalPrice);
Assert::same($catalogPromotionContent['label'], $promotionName);
Assert::count($variantContent[$this->getNormalizedKey('appliedPromotions')], 1);
Assert::same($variantContent[$this->getNormalizedKey('price')], $price);
Assert::same($variantContent[$this->getNormalizedKey('originalPrice')], $originalPrice);
Assert::same($catalogPromotionContent[$this->getNormalizedKey('label')], $promotionName);
}
/**
@ -206,7 +211,7 @@ final class ProductVariantContext implements Context
$items = $this->responseChecker->getCollectionItemsWithValue($response, 'code', $variant->getCode());
$item = array_pop($items);
Assert::keyNotExists($item, 'appliedPromotions');
Assert::keyNotExists($item, $this->getNormalizedKey('appliedPromotions'));
}
/**
@ -227,7 +232,7 @@ final class ProductVariantContext implements Context
{
$content = $this->responseChecker->getResponseContent($this->client->show(Resources::PRODUCT_VARIANTS, $variant->getCode()));
Assert::keyNotExists($content, 'appliedPromotions');
Assert::keyNotExists($content, $this->getNormalizedKey('appliedPromotions'));
}
/**
@ -243,7 +248,7 @@ final class ProductVariantContext implements Context
$content = $this->responseChecker->getResponseContent($this->client->show(Resources::PRODUCT_VARIANTS, $variant->getCode()));
Assert::keyExists(
$content,
'appliedPromotions',
$this->getNormalizedKey('appliedPromotions'),
sprintf('%s variant should be discounted', $variant->getName()),
);
}
@ -262,7 +267,7 @@ final class ProductVariantContext implements Context
$content = $this->responseChecker->getResponseContent($this->client->show(Resources::PRODUCT_VARIANTS, $variant->getCode()));
Assert::keyNotExists(
$content,
'appliedPromotions',
$this->getNormalizedKey('appliedPromotions'),
sprintf('%s variant should not be discounted', $variant->getName()),
);
}
@ -293,7 +298,7 @@ final class ProductVariantContext implements Context
foreach ($variants as $variant) {
$content = $this->responseChecker->getResponseContent($this->client->show(Resources::PRODUCT_VARIANTS, $variant->getCode()));
Assert::same(
$content['name'],
$content[$this->getNormalizedKey('name')],
$variant->getName(),
sprintf('%s variant should be visible', $variant->getName()),
);
@ -313,11 +318,11 @@ final class ProductVariantContext implements Context
Assert::greaterThan(count($variants), $position - 1, 'There are less variants than expected');
$variant = $variants[$position - 1];
Assert::same($variant['price'], $price);
Assert::same($variant[$this->getNormalizedKey('price')], $price);
Assert::true(
$this->isOptionValueInVariant(
$variant['optionValues'],
$variant[$this->getNormalizedKey('optionValues')],
$expectedOptionName,
$expectedOptionValueValue,
),
@ -335,7 +340,7 @@ final class ProductVariantContext implements Context
foreach ($variants as $variant) {
Assert::false(
$this->isOptionValueInVariant(
$variant['optionValues'],
$variant[$this->getNormalizedKey('optionValues')],
$expectedOptionName,
$expectedOptionValueValue,
),

View file

@ -17,17 +17,20 @@ use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\RequestFactoryInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Context\Api\Resources;
use Sylius\Behat\Context\Ui\Admin\Helper\SecurePasswordTrait;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final class RegistrationContext implements Context
{
use SecurePasswordTrait;
use NormalizedKeyAwareTrait;
private array $content = [];
@ -38,6 +41,7 @@ final class RegistrationContext implements Context
private ResponseCheckerInterface $responseChecker,
private RequestFactoryInterface $requestFactory,
private string $apiUrlPrefix,
private ?NameConverterInterface $nameConverter,
) {
}
@ -268,7 +272,7 @@ final class RegistrationContext implements Context
$response = $this->shopClient->show(Resources::CUSTOMERS, (string) $customer->getId());
Assert::true($this->responseChecker->getResponseContent($response)['subscribedToNewsletter']);
Assert::true($this->responseChecker->getResponseContent($response)[$this->getNormalizedKey('subscribedToNewsletter')]);
}
/**
@ -282,11 +286,13 @@ final class RegistrationContext implements Context
private function assertFieldValidationMessage(string $path, string $message): void
{
$decodedResponse = $this->getResponseContent();
$violationsKey = $this->getNormalizedKey('violations');
$codeKey = $this->getNormalizedKey('code');
Assert::keyExists($decodedResponse, 'violations');
Assert::keyExists($decodedResponse, $violationsKey);
Assert::same(
$decodedResponse['violations'][0],
['propertyPath' => $path, 'message' => $message, 'code' => $decodedResponse['violations'][0]['code']],
$decodedResponse[$violationsKey][0],
['propertyPath' => $path, 'message' => $message, 'code' => $decodedResponse[$violationsKey][0][$codeKey]],
);
}

View file

@ -16,18 +16,23 @@ namespace Sylius\Behat\Context\Api\Shop;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Api\NormalizedKeyAwareTrait;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\ShipmentInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final readonly class ShipmentContext implements Context
{
use NormalizedKeyAwareTrait;
public function __construct(
private ApiClientInterface $client,
private ResponseCheckerInterface $responseChecker,
private SharedStorageInterface $sharedStorage,
private ?NameConverterInterface $nameConverter,
) {
}
@ -58,7 +63,7 @@ final readonly class ShipmentContext implements Context
$shipments = $this->responseChecker->getValue($response, 'shipments');
$token = $this->responseChecker->getValue($response, 'tokenValue');
$response = $this->client->requestGet(sprintf('orders/%s/shipments/%s', $token, $shipments[0]['id']));
$response = $this->client->requestGet(sprintf('orders/%s/shipments/%s', $token, $shipments[0][$this->getNormalizedKey('id')]));
Assert::true($this->responseChecker->hasValue($response, 'state', $state, isCaseSensitive: false));
}

View file

@ -18,6 +18,7 @@
<argument type="service" id="sylius.behat.shared_storage" />
<argument type="service" id="sylius.behat.request_factory" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>%sylius.api.authorization_header%</argument>
</service>
@ -29,7 +30,9 @@
<argument>admin</argument>
</service>
<service id="Sylius\Behat\Client\ResponseCheckerInterface" class="Sylius\Behat\Client\ResponseChecker"/>
<service id="Sylius\Behat\Client\ResponseCheckerInterface" class="Sylius\Behat\Client\ResponseChecker">
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.client.admin_api_platform_security_client" class="Sylius\Behat\Client\ApiPlatformSecurityClient">
<argument type="service" id="test.client" />

View file

@ -32,6 +32,7 @@
<argument type="service" id="sylius.behat.api_platform_client.admin" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="api_platform.iri_converter" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.admin.browsing_product_variant" class="Sylius\Behat\Context\Api\Admin\BrowsingProductVariantsContext">
@ -68,6 +69,7 @@
<service id="Sylius\Behat\Context\Api\Admin\ManagingChannelsBillingDataContext">
<argument type="service" id="sylius.behat.api_platform_client.admin" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.admin.managing_countries" class="Sylius\Behat\Context\Api\Admin\ManagingCountriesContext">
@ -87,6 +89,7 @@
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="sylius.behat.shared_storage" />
<argument>%sylius.security.api_route%</argument>
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.admin.managing_locales" class="Sylius\Behat\Context\Api\Admin\ManagingLocalesContext">
@ -135,6 +138,7 @@
<argument type="service" id="Sylius\Behat\Service\Converter\IriConverter" />
<argument type="service" id="sylius.behat.shared_storage" />
<argument>%sylius.security.api_route%</argument>
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.admin.managing_product_variants" class="Sylius\Behat\Context\Api\Admin\ManagingProductVariantsContext">
@ -142,6 +146,7 @@
<argument type="service" id="sylius.behat.api_platform_client.admin" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="api_platform.symfony.iri_converter" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.admin.managing_product_variants_prices" class="Sylius\Behat\Context\Api\Admin\ManagingProductVariantsPricesContext">
@ -208,6 +213,7 @@
<argument type="service" id="sylius.behat.api_admin_security" />
<argument type="service" id="sylius.behat.shared_storage" />
<argument type="service" id="sylius.behat.api.shared_security" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.admin.managing_payment_methods" class="Sylius\Behat\Context\Api\Admin\ManagingPaymentMethodsContext">
@ -237,6 +243,7 @@
<argument type="service" id="sylius.behat.api_platform_client.admin" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="api_platform.iri_converter" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.admin.managing_catalog_promotions" class="Sylius\Behat\Context\Api\Admin\ManagingCatalogPromotionsContext">
@ -265,6 +272,7 @@
<argument type="service" id="sylius.behat.api_platform_client.admin" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="sylius.behat.shared_storage" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.admin.managing_customers" class="Sylius\Behat\Context\Api\Admin\ManagingCustomersContext">

View file

@ -23,6 +23,7 @@
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="api_platform.symfony.iri_converter" />
<argument type="service" id="sylius.behat.shared_storage" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.channel" class="Sylius\Behat\Context\Api\Shop\ChannelContext">
@ -48,6 +49,7 @@
<argument type="service" id="sylius.behat.request_factory" />
<argument>%sylius.security.api_route%</argument>
<argument type="service" id="sylius.repository.order"/>
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.customer" class="Sylius\Behat\Context\Api\Shop\CustomerContext">
@ -64,6 +66,7 @@
<service id="sylius.behat.context.api.shop.exchange_rate" class="Sylius\Behat\Context\Api\Shop\ExchangeRateContext">
<argument type="service" id="sylius.behat.api_platform_client.shop" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.promotion" class="Sylius\Behat\Context\Api\Shop\PromotionContext">
@ -85,6 +88,7 @@
<argument type="service" id="sylius.behat.factory.address" />
<argument>%sylius.model.shipping_method.class%</argument>
<argument>%sylius.model.payment_method.class%</argument>
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.homepage" class="Sylius\Behat\Context\Api\Shop\HomepageContext">
@ -116,6 +120,7 @@
<argument type="service" id="doctrine.orm.entity_manager" />
<argument>%sylius.security.api_route%</argument>
<argument type="service" id="sylius.resolver.product_variant.default" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.product_attribute" class="Sylius\Behat\Context\Api\Shop\ProductAttributeContext">
@ -129,6 +134,7 @@
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="sylius.behat.shared_storage" />
<argument type="service" id="api_platform.iri_converter" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.product_review" class="Sylius\Behat\Context\Api\Shop\ProductReviewContext">
@ -145,6 +151,7 @@
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="sylius.behat.request_factory" />
<argument>%sylius.security.api_route%</argument>
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.order" class="Sylius\Behat\Context\Api\Shop\OrderContext">
@ -156,6 +163,7 @@
<argument type="service" id="sylius.behat.api_admin_security" />
<argument type="service" id="sylius.behat.request_factory" />
<argument>%sylius.security.api_route%</argument>
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.order_item" class="Sylius\Behat\Context\Api\Shop\OrderItemContext">
@ -170,18 +178,21 @@
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="sylius.behat.request_factory" />
<argument type="service" id="sylius.repository.payment_request" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.payment" class="Sylius\Behat\Context\Api\Shop\PaymentContext">
<argument type="service" id="sylius.behat.api_platform_client.shop" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="sylius.behat.shared_storage" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.shipment" class="Sylius\Behat\Context\Api\Shop\ShipmentContext">
<argument type="service" id="sylius.behat.api_platform_client.shop" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="sylius.behat.shared_storage" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.locale" class="Sylius\Behat\Context\Api\Shop\LocaleContext">
@ -202,6 +213,7 @@
<argument type="service" id="sylius.behat.shared_storage" />
<argument type="service" id="api_platform.iri_converter" />
<argument type="service" id="sylius.repository.shipping_method" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.checkout.complete" class="Sylius\Behat\Context\Api\Shop\Checkout\CheckoutCompleteContext">
@ -214,6 +226,7 @@
<argument type="service" id="sylius.behat.shared_storage" />
<argument type="service" id="sylius.behat.api_platform_client.shop" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
</service>
<service id="sylius.behat.context.api.shop.taxon" class="Sylius\Behat\Context\Api\Shop\TaxonContext">

View file

@ -24,6 +24,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\ChannelCodeAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\ChannelCodeAware::DEFAULT_ARGUMENT_NAME</argument>
<argument type="service" id="sylius.context.channel" />
@ -36,6 +37,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\LoggedInCustomerEmailAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\LoggedInCustomerEmailAware::DEFAULT_ARGUMENT_NAME</argument>
<argument type="service" id="sylius_api.context.user.token_based" />
@ -58,6 +60,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\LocaleCodeAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\LocaleCodeAware::DEFAULT_ARGUMENT_NAME</argument>
<argument type="service" id="sylius.context.locale" />
@ -89,6 +92,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\ShopUserIdAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\ShopUserIdAware::DEFAULT_ARGUMENT_NAME</argument>
<argument type="service" id="sylius_api.context.user.token_based" />
@ -101,6 +105,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\ShipmentIdAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\ShipmentIdAware::DEFAULT_ARGUMENT_NAME</argument>
<argument>Sylius\Component\Core\Model\ShipmentInterface</argument>
@ -113,6 +118,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\PaymentIdAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\PaymentIdAware::DEFAULT_ARGUMENT_NAME</argument>
<argument>Sylius\Component\Core\Model\PaymentInterface</argument>
@ -125,6 +131,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\PaymentRequestHashAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\PaymentRequestHashAware::DEFAULT_ARGUMENT_NAME</argument>
<argument>Sylius\Component\Payment\Model\PaymentRequestInterface</argument>
@ -137,6 +144,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\OrderTokenValueAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\OrderTokenValueAware::DEFAULT_ARGUMENT_NAME</argument>
<argument>Sylius\Component\Core\Model\OrderInterface</argument>
@ -149,6 +157,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\OrderItemIdAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\OrderItemIdAware::DEFAULT_ARGUMENT_NAME</argument>
<argument>Sylius\Component\Core\Model\OrderItemInterface</argument>
@ -161,6 +170,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\PromotionCodeAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\PromotionCodeAware::DEFAULT_ARGUMENT_NAME</argument>
<argument>Sylius\Component\Core\Model\PromotionInterface</argument>
@ -173,6 +183,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\TokenAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\TokenAware::DEFAULT_ARGUMENT_NAME</argument>
<argument>Sylius\Bundle\ApiBundle\Command\Admin\Account\ResetPassword</argument>
@ -185,6 +196,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\TokenAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\TokenAware::DEFAULT_ARGUMENT_NAME</argument>
<argument>Sylius\Bundle\ApiBundle\Command\Account\ResetPassword</argument>
@ -197,6 +209,7 @@
decoration-priority="64"
>
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\TokenAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\TokenAware::DEFAULT_ARGUMENT_NAME</argument>
<argument>Sylius\Bundle\ApiBundle\Command\Account\VerifyShopUser</argument>
@ -210,6 +223,7 @@
>
<argument type="service" id="sylius_api.converter.iri_to_identifier" />
<argument type="service" id=".inner" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<argument>Sylius\Bundle\ApiBundle\Attribute\PaymentRequestActionAware</argument>
<argument type="constant">Sylius\Bundle\ApiBundle\Attribute\PaymentRequestActionAware::DEFAULT_ARGUMENT_NAME</argument>
<argument type="service" id="sylius.provider.payment_request.default_action" />

View file

@ -18,7 +18,7 @@
>
<services>
<service id="sylius_api.denormalizer.address" class="Sylius\Bundle\ApiBundle\Serializer\Denormalizer\AddressDenormalizer">
<argument type="service" id="serializer.normalizer.object" />
<argument type="service" id="api_platform.normalizer.object" />
<argument type="string">%sylius.model.address.class%</argument>
<argument type="string">%sylius.model.address.interface%</argument>
<tag name="serializer.normalizer" priority="64" />
@ -32,7 +32,7 @@
<service id="sylius_api.denormalizer.command" class="Sylius\Bundle\ApiBundle\Serializer\Denormalizer\CommandDenormalizer">
<argument type="service" id="api_platform.serializer.normalizer.item" />
<argument type="service" id="serializer.name_converter.metadata_aware" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
<tag name="serializer.normalizer" />
</service>
@ -44,7 +44,7 @@
<argument>sylius:shop:product:index</argument>
<argument>sylius:shop:product:show</argument>
</argument>
<argument type="service" id="serializer.normalizer.object" />
<argument type="service" id="api_platform.normalizer.object" />
<argument type="collection">
<argument>sylius:shop:product:index:default_variant</argument>
<argument>sylius:shop:product:show:default_variant</argument>
@ -80,7 +80,7 @@
</service>
<service id="sylius_api.normalizer.command" class="Sylius\Bundle\ApiBundle\Serializer\Normalizer\CommandNormalizer">
<argument type="service" id="serializer.normalizer.object" />
<argument type="service" id="api_platform.normalizer.object" />
<tag name="serializer.normalizer" priority="64" />
</service>
@ -119,7 +119,7 @@
</service>
<service id="sylius_api.denormalizer.zone" class="Sylius\Bundle\ApiBundle\Serializer\Denormalizer\ZoneDenormalizer">
<argument type="service" id="serializer.normalizer.object" />
<argument type="service" id="api_platform.normalizer.object" />
<argument type="service" id="sylius.section_resolver.uri_based" />
<tag name="serializer.normalizer" priority="64" />
</service>

View file

@ -15,12 +15,15 @@ namespace Sylius\Bundle\ApiBundle\Serializer\ContextBuilder;
use ApiPlatform\State\SerializerContextBuilderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
abstract class AbstractInputContextBuilder implements SerializerContextBuilderInterface
{
public function __construct(
protected readonly SerializerContextBuilderInterface $decoratedContextBuilder,
protected readonly ?NameConverterInterface $nameConverter,
protected readonly string $attributeClass,
protected readonly string $defaultConstructorArgumentName,
) {
@ -36,6 +39,10 @@ abstract class AbstractInputContextBuilder implements SerializerContextBuilderIn
}
$constructorArgumentName = $this->getConstructorArgumentName($inputClass) ?? $this->defaultConstructorArgumentName;
$constructorArgumentName = $this->nameConverter
? $this->nameConverter->normalize($constructorArgumentName, $inputClass, JsonEncoder::FORMAT, $context)
: $constructorArgumentName
;
if (isset($context[AbstractNormalizer::DEFAULT_CONSTRUCTOR_ARGUMENTS][$inputClass]) && is_array($context[AbstractNormalizer::DEFAULT_CONSTRUCTOR_ARGUMENTS][$inputClass])) {
$context[AbstractNormalizer::DEFAULT_CONSTRUCTOR_ARGUMENTS][$inputClass] = array_merge($context[AbstractNormalizer::DEFAULT_CONSTRUCTOR_ARGUMENTS][$inputClass], [$constructorArgumentName => $this->resolveValue($context, $extractedAttributes)]);

View file

@ -16,16 +16,18 @@ namespace Sylius\Bundle\ApiBundle\Serializer\ContextBuilder;
use ApiPlatform\State\SerializerContextBuilderInterface;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
final class ChannelCodeAwareContextBuilder extends AbstractInputContextBuilder
{
public function __construct(
SerializerContextBuilderInterface $decoratedContextBuilder,
?NameConverterInterface $nameConverter,
string $attributeClass,
string $defaultConstructorArgumentName,
private readonly ChannelContextInterface $channelContext,
) {
parent::__construct($decoratedContextBuilder, $attributeClass, $defaultConstructorArgumentName);
parent::__construct($decoratedContextBuilder, $nameConverter, $attributeClass, $defaultConstructorArgumentName);
}
protected function supports(Request $request, array $context, ?array $extractedAttributes): bool

View file

@ -16,16 +16,18 @@ namespace Sylius\Bundle\ApiBundle\Serializer\ContextBuilder;
use ApiPlatform\State\SerializerContextBuilderInterface;
use Sylius\Component\Locale\Context\LocaleContextInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
final class LocaleCodeAwareContextBuilder extends AbstractInputContextBuilder
{
public function __construct(
SerializerContextBuilderInterface $decoratedContextBuilder,
?NameConverterInterface $nameConverter,
string $attributeClass,
string $defaultConstructorArgumentName,
private readonly LocaleContextInterface $localeContext,
) {
parent::__construct($decoratedContextBuilder, $attributeClass, $defaultConstructorArgumentName);
parent::__construct($decoratedContextBuilder, $nameConverter, $attributeClass, $defaultConstructorArgumentName);
}
protected function supports(Request $request, array $context, ?array $extractedAttributes): bool

View file

@ -19,17 +19,19 @@ use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\User\Model\UserInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Webmozart\Assert\Assert;
final class LoggedInCustomerEmailAwareContextBuilder extends AbstractInputContextBuilder
{
public function __construct(
SerializerContextBuilderInterface $decoratedContextBuilder,
?NameConverterInterface $nameConverter,
string $attributeClass,
string $defaultConstructorArgumentName,
private readonly UserContextInterface $userContext,
) {
parent::__construct($decoratedContextBuilder, $attributeClass, $defaultConstructorArgumentName);
parent::__construct($decoratedContextBuilder, $nameConverter, $attributeClass, $defaultConstructorArgumentName);
}
protected function supports(Request $request, array $context, ?array $extractedAttributes): bool

View file

@ -17,16 +17,18 @@ use ApiPlatform\State\SerializerContextBuilderInterface;
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
final class LoggedInShopUserIdAwareContextBuilder extends AbstractInputContextBuilder
{
public function __construct(
SerializerContextBuilderInterface $decoratedContextBuilder,
?NameConverterInterface $nameConverter,
string $attributeClass,
string $defaultConstructorArgumentName,
private readonly UserContextInterface $userContext,
) {
parent::__construct($decoratedContextBuilder, $attributeClass, $defaultConstructorArgumentName);
parent::__construct($decoratedContextBuilder, $nameConverter, $attributeClass, $defaultConstructorArgumentName);
}
protected function supports(Request $request, array $context, ?array $extractedAttributes): bool

View file

@ -18,6 +18,7 @@ use Sylius\Bundle\ApiBundle\Attribute\PaymentRequestActionAware;
use Sylius\Bundle\ApiBundle\Converter\IriToIdentifierConverterInterface;
use Sylius\Bundle\PaymentBundle\Provider\DefaultActionProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
/** @experimental */
final class PaymentRequestActionAwareContextBuilder extends AbstractInputContextBuilder
@ -27,11 +28,12 @@ final class PaymentRequestActionAwareContextBuilder extends AbstractInputContext
public function __construct(
private readonly IriToIdentifierConverterInterface $iriToIdentifierConverter,
SerializerContextBuilderInterface $decoratedContextBuilder,
?NameConverterInterface $nameConverter,
string $attributeClass,
string $defaultConstructorArgumentName,
private readonly DefaultActionProviderInterface $defaultActionProvider,
) {
parent::__construct($decoratedContextBuilder, $attributeClass, $defaultConstructorArgumentName);
parent::__construct($decoratedContextBuilder, $nameConverter, $attributeClass, $defaultConstructorArgumentName);
}
public function createFromRequest(Request $request, bool $normalization, ?array $extractedAttributes = null): array

View file

@ -16,16 +16,18 @@ namespace Sylius\Bundle\ApiBundle\Serializer\ContextBuilder;
use ApiPlatform\Metadata\HttpOperation;
use ApiPlatform\State\SerializerContextBuilderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
final class UriVariablesAwareContextBuilder extends AbstractInputContextBuilder
{
public function __construct(
SerializerContextBuilderInterface $decoratedContextBuilder,
?NameConverterInterface $nameConverter,
string $attributeClass,
string $defaultConstructorArgumentName,
private readonly string $objectInterface,
) {
parent::__construct($decoratedContextBuilder, $attributeClass, $defaultConstructorArgumentName);
parent::__construct($decoratedContextBuilder, $nameConverter, $attributeClass, $defaultConstructorArgumentName);
}
protected function supports(Request $request, array $context, ?array $extractedAttributes): bool

View file

@ -24,7 +24,7 @@ final class CommandDenormalizer implements DenormalizerInterface
{
public function __construct(
private DenormalizerInterface $itemNormalizer,
private NameConverterInterface $nameConverter,
private ?NameConverterInterface $nameConverter,
) {
}
@ -70,6 +70,6 @@ final class CommandDenormalizer implements DenormalizerInterface
private function normalizeFieldName(string $field, string $class): string
{
return $this->nameConverter->normalize($field, $class);
return $this->nameConverter ? $this->nameConverter->normalize($field, $class) : $field;
}
}

View file

@ -39,6 +39,7 @@ final class ChannelCodeAwareContextBuilderTest extends TestCase
$this->channelContext = $this->createMock(ChannelContextInterface::class);
$this->channelCodeAwareContextBuilder = new ChannelCodeAwareContextBuilder(
$this->decoratedContextBuilder,
null,
ChannelCodeAware::class,
'channelCode',
$this->channelContext,

View file

@ -38,6 +38,7 @@ final class LocaleCodeAwareContextBuilderTest extends TestCase
$this->localeContext = $this->createMock(LocaleContextInterface::class);
$this->localeCodeAwareContextBuilder = new LocaleCodeAwareContextBuilder(
$this->decoratedContextBuilder,
null,
LocaleCodeAware::class,
'localeCode',
$this->localeContext,

View file

@ -41,6 +41,7 @@ final class LoggedInCustomerEmailAwareContextBuilderTest extends TestCase
$this->userContext = $this->createMock(UserContextInterface::class);
$this->loggedInCustomerEmailAwareContextBuilder = new LoggedInCustomerEmailAwareContextBuilder(
$this->decoratedContextBuilder,
null,
LoggedInCustomerEmailAware::class,
'email',
$this->userContext,

View file

@ -39,6 +39,7 @@ final class LoggedInShopUserIdAwareContextBuilderTest extends TestCase
$this->userContext = $this->createMock(UserContextInterface::class);
$this->loggedInShopUserIdAwareContextBuilder = new LoggedInShopUserIdAwareContextBuilder(
$this->decoratedContextBuilder,
null,
ShopUserIdAware::class,
'shopUserId',
$this->userContext,

View file

@ -43,6 +43,7 @@ final class PaymentRequestActionAwareContextBuilderTest extends TestCase
$this->paymentRequestActionAwareContextBuilder = new PaymentRequestActionAwareContextBuilder(
$this->iriToIdentifierConverterMock,
$this->decoratedContextBuilderMock,
null,
PaymentRequestActionAware::class,
PaymentRequestActionAware::DEFAULT_ARGUMENT_NAME,
$this->defaultActionProviderMock,

View file

@ -42,6 +42,7 @@ final class UriVariablesAwareContextBuilderTest extends TestCase
$this->decoratedContextBuilder = $this->createMock(SerializerContextBuilderInterface::class);
$this->uriVariablesAwareContextBuilder = new UriVariablesAwareContextBuilder(
$this->decoratedContextBuilder,
null,
ShipmentIdAware::class,
'shipmentId',
ShipmentInterface::class,
@ -163,6 +164,7 @@ final class UriVariablesAwareContextBuilderTest extends TestCase
$this->uriVariablesAwareContextBuilder = new UriVariablesAwareContextBuilder(
$this->decoratedContextBuilder,
null,
OrderTokenValueAware::class,
'orderTokenValue',
OrderInterface::class,
@ -197,6 +199,7 @@ final class UriVariablesAwareContextBuilderTest extends TestCase
$this->uriVariablesAwareContextBuilder = new UriVariablesAwareContextBuilder(
$this->decoratedContextBuilder,
null,
OrderItemIdAware::class,
'orderItemId',
OrderItemInterface::class,