From 77b515ea96c880125f947fbc7ca62e9d774510b1 Mon Sep 17 00:00:00 2001 From: Ferror Date: Tue, 26 Apr 2022 09:58:56 +0200 Subject: [PATCH] Extract building and creating Request object outside of API client --- .../Behat/Client/ApiClientInterface.php | 10 +- src/Sylius/Behat/Client/ApiPlatformClient.php | 80 ++++--- src/Sylius/Behat/Client/ContentTypeGuide.php | 36 ++++ .../Client/ContentTypeGuideInterface.php | 19 ++ src/Sylius/Behat/Client/Request.php | 180 +--------------- src/Sylius/Behat/Client/RequestBuilder.php | 77 +++++++ src/Sylius/Behat/Client/RequestFactory.php | 196 ++++++++++++++++++ .../Behat/Client/RequestFactoryInterface.php | 92 ++++++++ src/Sylius/Behat/Client/RequestInterface.php | 53 ----- .../Admin/ManagingAdministratorsContext.php | 44 ++-- .../Behat/Context/Api/Shop/CartContext.php | 93 +++++---- .../Context/Api/Shop/CheckoutContext.php | 29 ++- .../Context/Api/Shop/CustomerContext.php | 39 +--- .../Behat/Context/Api/Shop/LoginContext.php | 37 +--- .../Behat/Context/Api/Shop/OrderContext.php | 41 ++-- .../Behat/Context/Api/Shop/ProductContext.php | 9 +- .../Context/Api/Shop/PromotionContext.php | 2 - .../Behat/Resources/config/services.xml | 4 + .../Behat/Resources/config/services/api.xml | 7 + .../config/services/contexts/api/admin.xml | 1 + .../config/services/contexts/api/shop.xml | 6 + 21 files changed, 612 insertions(+), 443 deletions(-) create mode 100644 src/Sylius/Behat/Client/ContentTypeGuide.php create mode 100644 src/Sylius/Behat/Client/ContentTypeGuideInterface.php create mode 100644 src/Sylius/Behat/Client/RequestBuilder.php create mode 100644 src/Sylius/Behat/Client/RequestFactory.php create mode 100644 src/Sylius/Behat/Client/RequestFactoryInterface.php diff --git a/src/Sylius/Behat/Client/ApiClientInterface.php b/src/Sylius/Behat/Client/ApiClientInterface.php index 30d0524282f..541c2d8b140 100644 --- a/src/Sylius/Behat/Client/ApiClientInterface.php +++ b/src/Sylius/Behat/Client/ApiClientInterface.php @@ -18,6 +18,8 @@ interface ApiClientInterface { + public function request(RequestInterface $request): Response; + public function index(string $resource): Response; public function showByIri(string $iri): Response; @@ -42,8 +44,6 @@ public function customItemAction(string $resource, string $id, string $type, str public function customAction(string $url, string $method): Response; - public function upload(): Response; - public function resend(): Response; public function executeCustomRequest(RequestInterface $request): Response; @@ -52,8 +52,6 @@ public function buildCreateRequest(string $resource): void; public function buildUpdateRequest(string $resource, string $id): void; - public function buildUploadRequest(string $resource): void; - public function setRequestData(array $data): void; /** @param string|int $value */ @@ -66,8 +64,8 @@ public function clearParameters(): void; public function addFile(string $key, UploadedFile $file): void; - /** @param string|int|array $value */ - public function addRequestData(string $key, $value): void; + /** @param string|int|bool|array $value */ + public function addRequestData(string $key, mixed $value): void; public function setSubResourceData(string $key, array $data): void; diff --git a/src/Sylius/Behat/Client/ApiPlatformClient.php b/src/Sylius/Behat/Client/ApiPlatformClient.php index 6e7aa57e553..048f08f73b3 100644 --- a/src/Sylius/Behat/Client/ApiPlatformClient.php +++ b/src/Sylius/Behat/Client/ApiPlatformClient.php @@ -25,6 +25,8 @@ final class ApiPlatformClient implements ApiClientInterface private SharedStorageInterface $sharedStorage; + private RequestFactoryInterface $requestFactory; + private string $authorizationHeader; private ?string $section; @@ -34,25 +36,27 @@ final class ApiPlatformClient implements ApiClientInterface public function __construct( AbstractBrowser $client, SharedStorageInterface $sharedStorage, + RequestFactoryInterface $requestFactory, string $authorizationHeader, ?string $section = null ) { $this->client = $client; $this->sharedStorage = $sharedStorage; + $this->requestFactory = $requestFactory; $this->authorizationHeader = $authorizationHeader; $this->section = $section; } public function index(string $resource): Response { - $this->request = Request::index($this->section, $resource, $this->authorizationHeader, $this->getToken()); + $this->request = $this->requestFactory->index($this->section, $resource, $this->authorizationHeader, $this->getToken()); return $this->request($this->request); } public function showByIri(string $iri): Response { - $request = Request::custom($iri, HttpRequest::METHOD_GET); + $request = $this->requestFactory->custom($iri, HttpRequest::METHOD_GET); $request->authorize($this->getToken(), $this->authorizationHeader); return $this->request($request); @@ -60,7 +64,7 @@ public function showByIri(string $iri): Response public function subResourceIndex(string $resource, string $subResource, string $id): Response { - $request = Request::subResourceIndex($this->section, $resource, $id, $subResource); + $request = $this->requestFactory->subResourceIndex($this->section, $resource, $id, $subResource); $request->authorize($this->getToken(), $this->authorizationHeader); return $this->request($request); @@ -68,13 +72,15 @@ public function subResourceIndex(string $resource, string $subResource, string $ public function show(string $resource, string $id): Response { - return $this->request(Request::show( - $this->section, - $resource, - $id, - $this->authorizationHeader, - $this->getToken() - )); + return $this->request( + $this->requestFactory->show( + $this->section, + $resource, + $id, + $this->authorizationHeader, + $this->getToken() + ) + ); } public function create(?RequestInterface $request = null): Response @@ -87,15 +93,22 @@ public function update(): Response return $this->request($this->request); } + public function resend(): Response + { + return $this->request($this->request); + } + public function delete(string $resource, string $id): Response { - return $this->request(Request::delete( - $this->section, - $resource, - $id, - $this->authorizationHeader, - $this->getToken() - )); + return $this->request( + $this->requestFactory->delete( + $this->section, + $resource, + $id, + $this->authorizationHeader, + $this->getToken() + ) + ); } public function filter(): Response @@ -112,7 +125,7 @@ public function sort(array $sorting): Response public function applyTransition(string $resource, string $id, string $transition, array $content = []): Response { - $request = Request::transition($this->section, $resource, $id, $transition); + $request = $this->requestFactory->transition($this->section, $resource, $id, $transition); $request->authorize($this->getToken(), $this->authorizationHeader); $request->setContent($content); @@ -121,7 +134,7 @@ public function applyTransition(string $resource, string $id, string $transition public function customItemAction(string $resource, string $id, string $type, string $action): Response { - $request = Request::customItemAction($this->section, $resource, $id, $type, $action); + $request = $this->requestFactory->customItemAction($this->section, $resource, $id, $type, $action); $request->authorize($this->getToken(), $this->authorizationHeader); return $this->request($request); @@ -129,23 +142,12 @@ public function customItemAction(string $resource, string $id, string $type, str public function customAction(string $url, string $method): Response { - $request = Request::custom($url, $method); - + $request = $this->requestFactory->custom($url, $method); $request->authorize($this->getToken(), $this->authorizationHeader); return $this->request($request); } - public function upload(): Response - { - return $this->request($this->request); - } - - public function resend(): Response - { - return $this->request($this->request); - } - public function executeCustomRequest(RequestInterface $request): Response { $request->authorize($this->getToken(), $this->authorizationHeader); @@ -155,15 +157,14 @@ public function executeCustomRequest(RequestInterface $request): Response public function buildCreateRequest(string $resource): void { - $this->request = Request::create($this->section, $resource, $this->authorizationHeader); - $this->request->authorize($this->getToken(), $this->authorizationHeader); + $this->request = $this->requestFactory->create($this->section, $resource, $this->authorizationHeader, $this->getToken()); } public function buildUpdateRequest(string $resource, string $id): void { $this->show($resource, $id); - $this->request = Request::update( + $this->request = $this->requestFactory->update( $this->section, $resource, $id, @@ -175,7 +176,7 @@ public function buildUpdateRequest(string $resource, string $id): void public function buildCustomUpdateRequest(string $resource, string $id, string $customSuffix): void { - $this->request = Request::update( + $this->request = $this->requestFactory->update( $this->section, $resource, sprintf('%s/%s', $id, $customSuffix), @@ -184,11 +185,6 @@ public function buildCustomUpdateRequest(string $resource, string $id, string $c ); } - public function buildUploadRequest(string $resource): void - { - $this->request = Request::upload($this->section, $resource, $this->authorizationHeader, $this->getToken()); - } - /** @param string|int $value */ public function addParameter(string $key, $value): void { @@ -216,7 +212,7 @@ public function addFile(string $key, UploadedFile $file): void $this->request->updateFiles([$key => $file]); } - /** @param string|int|array $value */ + /** @param string|int|bool|array $value */ public function addRequestData(string $key, $value): void { $this->request->updateContent([$key => $value]); @@ -257,7 +253,7 @@ public function getToken(): ?string return $this->sharedStorage->has('token') ? $this->sharedStorage->get('token') : null; } - private function request(RequestInterface $request): Response + public function request(RequestInterface $request): Response { $this->setServerParameters(); diff --git a/src/Sylius/Behat/Client/ContentTypeGuide.php b/src/Sylius/Behat/Client/ContentTypeGuide.php new file mode 100644 index 00000000000..fe22e166c3b --- /dev/null +++ b/src/Sylius/Behat/Client/ContentTypeGuide.php @@ -0,0 +1,36 @@ + 'application/ld+json']; - - private array $content = []; - - /** @var array */ - private $parameters = []; - - /** @var array */ - private $files = []; - - private function __construct(string $url, string $method, array $headers = []) - { - $this->url = $url; - $this->method = $method; - $this->headers = array_merge($this->headers, $headers); - } - - public static function index( - ?string $section, - string $resource, - string $authorizationHeader, - ?string $token = null - ): RequestInterface { - $headers = $token ? ['HTTP_' . $authorizationHeader => 'Bearer ' . $token] : []; - - return new self( - sprintf('/api/v2/%s%s', self::prepareSection($section), $resource), - HttpRequest::METHOD_GET, - $headers - ); - } - - public static function subResourceIndex(?string $section, string $resource, string $id, string $subResource): RequestInterface - { - return new self( - sprintf('/api/v2/%s%s/%s/%s', self::prepareSection($section), $resource, $id, $subResource), - HttpRequest::METHOD_GET - ); - } - - public static function show( - ?string $section, - string $resource, - string $id, - string $authorizationHeader, - ?string $token = null - ): RequestInterface { - $headers = $token ? ['HTTP_' . $authorizationHeader => 'Bearer ' . $token] : []; - - return new self( - sprintf('/api/v2/%s%s/%s', self::prepareSection($section), $resource, $id), - HttpRequest::METHOD_GET, - $headers - ); - } - - public static function create( - ?string $section, - string $resource, - string $authorizationHeader, - ?string $token = null - ): RequestInterface { - $headers = ['CONTENT_TYPE' => 'application/ld+json']; - if ($token !== null) { - $headers['HTTP_' . $authorizationHeader] = 'Bearer ' . $token; - } - - return new self( - sprintf('/api/v2/%s%s', self::prepareSection($section), $resource), - HttpRequest::METHOD_POST, - $headers - ); - } - - public static function update( - ?string $section, - string $resource, - string $id, - string $authorizationHeader, - ?string $token = null - ): RequestInterface { - $headers = ['CONTENT_TYPE' => 'application/ld+json']; - if ($token !== null) { - $headers['HTTP_' . $authorizationHeader] = 'Bearer ' . $token; - } - - return new self( - sprintf('/api/v2/%s%s/%s', self::prepareSection($section), $resource, $id), - HttpRequest::METHOD_PUT, - $headers - ); - } - - public static function delete( - ?string $section, - string $resource, - string $id, - string $authorizationHeader, - ?string $token = null - ): RequestInterface { - $headers = $token ? ['HTTP_' . $authorizationHeader => 'Bearer ' . $token] : []; - - return new self( - sprintf('/api/v2/%s%s/%s', self::prepareSection($section), $resource, $id), - HttpRequest::METHOD_DELETE, - $headers - ); - } - - public static function transition(?string $section, string $resource, string $id, string $transition): RequestInterface - { - return self::customItemAction($section, $resource, $id, HttpRequest::METHOD_PATCH, $transition); - } - - public static function customItemAction(?string $section, string $resource, string $id, string $type, string $action): RequestInterface - { - return new self( - sprintf('/api/v2/%s%s/%s/%s', self::prepareSection($section), $resource, $id, $action), - $type, - ['CONTENT_TYPE' => self::resolveHttpMethod($type)] - ); - } - - public static function upload( - ?string $section, - string $resource, - string $authorizationHeader, - ?string $token = null - ): RequestInterface { - $headers = ['CONTENT_TYPE' => 'multipart/form-data']; - if ($token !== null) { - $headers['HTTP_' . $authorizationHeader] = 'Bearer ' . $token; - } - - return new self( - sprintf('/api/v2/%s%s', self::prepareSection($section), $resource), - HttpRequest::METHOD_POST, - $headers - ); - } - - public static function custom(string $url, string $method, array $additionalHeaders = [], ?string $token = null): RequestInterface - { - $headers = ['CONTENT_TYPE' => self::resolveHttpMethod($method)]; - if ($token !== null) { - $headers['HTTP_Authorization'] = 'Bearer ' . $token; - } - - $headers = array_merge($headers, $additionalHeaders); - - return new self($url, $method, $headers); + public function __construct( + private string $url, + private string $method, + private array $parameters = [], + private array $headers = [], + private array $content = [], + private array $files = [], + ) { } public function url(): string @@ -272,18 +122,4 @@ private function mergeArraysUniquely(array $firstArray, array $secondArray): arr return $firstArray; } - - private static function prepareSection(?string $section): string - { - if ($section === null) { - return ''; - } - - return $section . '/'; - } - - private static function resolveHttpMethod(string $method): string - { - return $method === HttpRequest::METHOD_PATCH ? 'application/merge-patch+json' : 'application/json'; - } } diff --git a/src/Sylius/Behat/Client/RequestBuilder.php b/src/Sylius/Behat/Client/RequestBuilder.php new file mode 100644 index 00000000000..70b0a3a6583 --- /dev/null +++ b/src/Sylius/Behat/Client/RequestBuilder.php @@ -0,0 +1,77 @@ +uri = $uri; + $this->method = $method; + } + + public static function create(string $uri, string $method): self + { + return new self($uri, $method); + } + + public function withHeader(string $name, string $value): self + { + $this->headers[$name] = $value; + + return $this; + } + + public function withFile(string $key, UploadedFile $file): self + { + $this->files[$key] = $file; + + return $this; + } + + public function withContent(array $content): self + { + $this->content = $content; + + return $this; + } + + public function withParameter(string $key, string $value): self + { + $this->parameters[$key] = $value; + + return $this; + } + + public function build(): RequestInterface + { + return new Request( + $this->uri, + $this->method, + $this->parameters, + $this->headers, + $this->content, + $this->files, + ); + } +} diff --git a/src/Sylius/Behat/Client/RequestFactory.php b/src/Sylius/Behat/Client/RequestFactory.php new file mode 100644 index 00000000000..a32dcaa221d --- /dev/null +++ b/src/Sylius/Behat/Client/RequestFactory.php @@ -0,0 +1,196 @@ +withHeader('HTTP_ACCEPT', self::LINKED_DATA_JSON_CONTENT_TYPE); + + if ($token) { + $builder->withHeader('HTTP_' . $authorizationHeader, 'Bearer ' . $token); + } + + return $builder->build(); + } + + public function subResourceIndex(string $section, string $resource, string $id, string $subResource): RequestInterface + { + $builder = RequestBuilder::create( + sprintf('/api/v2/%s/%s/%s/%s', $section, $resource, $id, $subResource), + HttpRequest::METHOD_GET, + ); + $builder->withHeader('HTTP_ACCEPT', self::LINKED_DATA_JSON_CONTENT_TYPE); + + return $builder->build(); + } + + public function show( + string $section, + string $resource, + string $id, + string $authorizationHeader, + ?string $token = null + ): RequestInterface { + $builder = RequestBuilder::create( + sprintf('/api/v2/%s/%s/%s', $section, $resource, $id), + HttpRequest::METHOD_GET, + ); + $builder->withHeader('HTTP_ACCEPT', self::LINKED_DATA_JSON_CONTENT_TYPE); + + if ($token) { + $builder->withHeader('HTTP_' . $authorizationHeader, 'Bearer ' . $token); + } + + return $builder->build(); + } + + public function create( + string $section, + string $resource, + string $authorizationHeader, + ?string $token = null + ): RequestInterface { + $builder = RequestBuilder::create( + sprintf('/api/v2/%s/%s', $section, $resource), + HttpRequest::METHOD_POST, + ); + $builder->withHeader('HTTP_ACCEPT', self::LINKED_DATA_JSON_CONTENT_TYPE); + $builder->withHeader('CONTENT_TYPE', self::LINKED_DATA_JSON_CONTENT_TYPE); + + if ($token) { + $builder->withHeader('HTTP_' . $authorizationHeader, 'Bearer ' . $token); + } + + return $builder->build(); + } + + public function update( + string $section, + string $resource, + string $id, + string $authorizationHeader, + ?string $token = null + ): RequestInterface { + $builder = RequestBuilder::create( + sprintf('/api/v2/%s/%s/%s', $section, $resource, $id), + HttpRequest::METHOD_PUT, + ); + $builder->withHeader('HTTP_ACCEPT', self::LINKED_DATA_JSON_CONTENT_TYPE); + $builder->withHeader('CONTENT_TYPE', $this->contentTypeGuide->guide(HttpRequest::METHOD_PUT)); + + if ($token) { + $builder->withHeader('HTTP_' . $authorizationHeader, 'Bearer ' . $token); + } + + return $builder->build(); + } + + public function delete( + string $section, + string $resource, + string $id, + string $authorizationHeader, + ?string $token = null + ): RequestInterface { + $builder = RequestBuilder::create( + sprintf('/api/v2/%s/%s/%s', $section, $resource, $id), + HttpRequest::METHOD_DELETE, + ); + $builder->withHeader('HTTP_ACCEPT', self::LINKED_DATA_JSON_CONTENT_TYPE); + + if ($token) { + $builder->withHeader('HTTP_' . $authorizationHeader, 'Bearer ' . $token); + } + + return $builder->build(); + } + + public function transition(string $section, string $resource, string $id, string $transition): RequestInterface + { + return self::customItemAction($section, $resource, $id, HttpRequest::METHOD_PATCH, $transition); + } + + public function customItemAction(string $section, string $resource, string $id, string $type, string $action): RequestInterface + { + $builder = RequestBuilder::create( + sprintf('/api/v2/%s/%s/%s/%s', $section, $resource, $id, $action), + $type, + ); + $builder->withHeader('CONTENT_TYPE', $this->contentTypeGuide->guide($type)); + + return $builder->build(); + } + + public function upload( + string $section, + string $resource, + array $files, + string $authorizationHeader, + ?string $token = null + ): RequestInterface { + $builder = RequestBuilder::create( + sprintf('/api/v2/%s/%s', $section, $resource), + HttpRequest::METHOD_POST, + ); + $builder->withHeader('HTTP_ACCEPT', self::LINKED_DATA_JSON_CONTENT_TYPE); + $builder->withHeader('CONTENT_TYPE', self::UPLOAD_FILE_CONTENT_TYPE); + + if ($token) { + $builder->withHeader('HTTP_' . $authorizationHeader, 'Bearer ' . $token); + } + + foreach ($files as $name => $value) { + $builder->withFile($name, $value); + } + + return $builder->build(); + } + + public function custom(string $url, string $method, array $additionalHeaders = [], ?string $token = null): RequestInterface + { + $builder = RequestBuilder::create($url, $method); + $builder->withHeader('HTTP_ACCEPT', self::LINKED_DATA_JSON_CONTENT_TYPE); + $builder->withHeader('CONTENT_TYPE', $this->contentTypeGuide->guide($method)); + + if ($token) { + $builder->withHeader('HTTP_Authorization', 'Bearer ' . $token); + } + + foreach ($additionalHeaders as $name => $value) { + $builder->withHeader($name, $value); + } + + return $builder->build(); + } +} diff --git a/src/Sylius/Behat/Client/RequestFactoryInterface.php b/src/Sylius/Behat/Client/RequestFactoryInterface.php new file mode 100644 index 00000000000..4c61443eaea --- /dev/null +++ b/src/Sylius/Behat/Client/RequestFactoryInterface.php @@ -0,0 +1,92 @@ +client = $client; - $this->responseChecker = $responseChecker; - $this->iriConverter = $iriConverter; - $this->sharedStorage = $sharedStorage; - $this->minkParameters = $minkParameters; } /** @@ -158,10 +147,17 @@ public function iDeleteAdministratorWithEmail(AdminUserInterface $adminUser): vo */ public function iUploadTheImageAsMyAvatar(string $avatar, AdminUserInterface $administrator): void { - $this->client->buildUploadRequest(Resources::AVATAR_IMAGES); - $this->client->addParameter('owner', $this->iriConverter->getIriFromItem($administrator)); - $this->client->addFile('file', new UploadedFile($this->minkParameters['files_path'] . $avatar, basename($avatar))); - $response = $this->client->upload(); + $builder = RequestBuilder::create( + sprintf('/api/v2/%s/%s', 'admin', Resources::AVATAR_IMAGES), + Request::METHOD_POST, + ); + $builder->withHeader('CONTENT_TYPE', 'multipart/form-data'); + $builder->withHeader('HTTP_ACCEPT', 'application/ld+json'); + $builder->withHeader('HTTP_Authorization', 'Bearer ' . $this->sharedStorage->get('token')); + $builder->withParameter('owner', $this->iriConverter->getIriFromItem($administrator)); + $builder->withFile('file', new UploadedFile($this->minkParameters['files_path'] . $avatar, basename($avatar))); + + $response = $this->client->request($builder->build()); $this->sharedStorage->set(StringInflector::nameToCode($avatar), $this->responseChecker->getValue($response, '@id')); } diff --git a/src/Sylius/Behat/Context/Api/Shop/CartContext.php b/src/Sylius/Behat/Context/Api/Shop/CartContext.php index 0c90268559e..5f8eed4ec0c 100644 --- a/src/Sylius/Behat/Context/Api/Shop/CartContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/CartContext.php @@ -16,7 +16,7 @@ use ApiPlatform\Core\Api\IriConverterInterface; use Behat\Behat\Context\Context; 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\Resources; use Sylius\Behat\Service\SharedStorageInterface; @@ -31,32 +31,15 @@ final class CartContext implements Context { - private ApiClientInterface $shopClient; - - private ApiClientInterface $adminClient; - - private ResponseCheckerInterface $responseChecker; - - private SharedStorageInterface $sharedStorage; - - private ProductVariantResolverInterface $productVariantResolver; - - private IriConverterInterface $iriConverter; - public function __construct( - ApiClientInterface $shopClient, - ApiClientInterface $adminClient, - ResponseCheckerInterface $responseChecker, - SharedStorageInterface $sharedStorage, - ProductVariantResolverInterface $productVariantResolver, - IriConverterInterface $iriConverter + private ApiClientInterface $shopClient, + private ApiClientInterface $adminClient, + private ResponseCheckerInterface $responseChecker, + private SharedStorageInterface $sharedStorage, + private ProductVariantResolverInterface $productVariantResolver, + private IriConverterInterface $iriConverter, + private RequestFactoryInterface $requestFactory, ) { - $this->shopClient = $shopClient; - $this->adminClient = $adminClient; - $this->responseChecker = $responseChecker; - $this->sharedStorage = $sharedStorage; - $this->productVariantResolver = $productVariantResolver; - $this->iriConverter = $iriConverter; } /** @@ -171,8 +154,13 @@ public function iAddThisProductWithToTheCart( $tokenValue = $this->pickupCart(); - $request = Request::customItemAction('shop', Resources::ORDERS, $tokenValue, HttpRequest::METHOD_POST, 'items'); - + $request = $this->requestFactory->customItemAction( + 'shop', + Resources::ORDERS, + $tokenValue, + HttpRequest::METHOD_POST, + 'items' + ); $request->updateContent([ 'productCode' => $productData['code'], 'productVariant' => $variantIri, @@ -562,8 +550,13 @@ public function theVisitorCanSeeProductInTheCart( */ public function iCheckItemsOfMyCart(string $tokenValue): void { - $request = Request::customItemAction('shop', Resources::ORDERS, $tokenValue, HttpRequest::METHOD_GET, 'items'); - + $request = $this->requestFactory->customItemAction( + 'shop', + Resources::ORDERS, + $tokenValue, + HttpRequest::METHOD_GET, + 'items' + ); $this->shopClient->executeCustomRequest($request); } @@ -678,8 +671,11 @@ public function thisItemShouldHaveOptionValue(ProductInterface $product, string private function pickupCart(?string $localeCode = null): string { - $request = Request::custom('/api/v2/shop/orders', HttpRequest::METHOD_POST, ['HTTP_ACCEPT_LANGUAGE' => $localeCode]); - + $request = $this->requestFactory->custom( + '/api/v2/shop/orders', + HttpRequest::METHOD_POST, + $localeCode ? ['HTTP_ACCEPT_LANGUAGE' => $localeCode] : [] + ); $this->shopClient->executeCustomRequest($request); $tokenValue = $this->responseChecker->getValue($this->shopClient->getLastResponse(), 'tokenValue'); @@ -693,8 +689,13 @@ private function putProductToCart(ProductInterface $product, ?string $tokenValue { $tokenValue = $tokenValue ?? $this->pickupCart(); - $request = Request::customItemAction('shop', Resources::ORDERS, $tokenValue, HttpRequest::METHOD_POST, 'items'); - + $request = $this->requestFactory->customItemAction( + 'shop', + Resources::ORDERS, + $tokenValue, + HttpRequest::METHOD_POST, + 'items' + ); $request->updateContent([ 'productVariant' => $this->iriConverter->getIriFromItem($this->productVariantResolver->getVariant($product)), 'quantity' => $quantity, @@ -707,8 +708,13 @@ private function putProductVariantToCart(ProductVariantInterface $productVariant { $tokenValue = $tokenValue ?? $this->pickupCart(); - $request = Request::customItemAction('shop', Resources::ORDERS, $tokenValue, HttpRequest::METHOD_POST, 'items'); - + $request = $this->requestFactory->customItemAction( + 'shop', + Resources::ORDERS, + $tokenValue, + HttpRequest::METHOD_POST, + 'items' + ); $request->updateContent([ 'productVariant' => $this->iriConverter->getIriFromItem($productVariant), 'quantity' => $quantity, @@ -719,14 +725,13 @@ private function putProductVariantToCart(ProductVariantInterface $productVariant private function removeOrderItemFromCart(string $orderItemId, string $tokenValue): void { - $request = Request::customItemAction( + $request = $this->requestFactory->customItemAction( 'shop', Resources::ORDERS, $tokenValue, HttpRequest::METHOD_DELETE, - \sprintf('items/%s', $orderItemId) + sprintf('items/%s', $orderItemId) ); - $this->shopClient->executeCustomRequest($request); } @@ -753,7 +758,8 @@ private function getProductVariantForItem(array $item): Response ); } - $this->shopClient->executeCustomRequest(Request::custom($item['variant'], HttpRequest::METHOD_GET)); + $request = $this->requestFactory->custom($item['variant'], HttpRequest::METHOD_GET); + $this->shopClient->executeCustomRequest($request); return $this->shopClient->getLastResponse(); } @@ -774,8 +780,13 @@ private function getOrderItemResponseFromProductInCart(ProductInterface $product private function changeQuantityOfOrderItem(string $orderItemId, int $quantity, string $tokenValue): void { - $request = Request::customItemAction('shop', Resources::ORDERS, $tokenValue, HttpRequest::METHOD_PATCH, sprintf('items/%s', $orderItemId)); - + $request = $this->requestFactory->customItemAction( + 'shop', + Resources::ORDERS, + $tokenValue, + HttpRequest::METHOD_PATCH, + sprintf('items/%s', $orderItemId) + ); $request->updateContent(['quantity' => $quantity]); $this->shopClient->executeCustomRequest($request); diff --git a/src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php b/src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php index e1ce1200d8e..19b9cee9302 100644 --- a/src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php @@ -16,7 +16,7 @@ use ApiPlatform\Core\Api\IriConverterInterface; use Behat\Behat\Context\Context; 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\Resources; use Sylius\Behat\Service\SharedStorageInterface; @@ -62,6 +62,8 @@ final class CheckoutContext implements Context private SharedStorageInterface $sharedStorage; + private RequestFactoryInterface $requestFactory; + /** @var string[] */ private array $content = []; @@ -78,6 +80,7 @@ public function __construct( ProductVariantResolverInterface $productVariantResolver, IriConverterInterface $iriConverter, SharedStorageInterface $sharedStorage, + RequestFactoryInterface $requestFactory, string $paymentMethodClass, string $shippingMethodClass ) { @@ -89,6 +92,7 @@ public function __construct( $this->productVariantResolver = $productVariantResolver; $this->iriConverter = $iriConverter; $this->sharedStorage = $sharedStorage; + $this->requestFactory = $requestFactory; $this->paymentMethodClass = $paymentMethodClass; $this->shippingMethodClass = $shippingMethodClass; } @@ -390,14 +394,13 @@ public function iProceededWithShippingMethod(ShippingMethodInterface $shippingMe */ public function iTryToSelectShippingMethod(string $shippingMethodCode): void { - $request = Request::customItemAction( + $request = $this->requestFactory->customItemAction( 'shop', Resources::ORDERS, $this->sharedStorage->get('cart_token'), HTTPRequest::METHOD_PATCH, sprintf('shipments/%s', $this->getCart()['shipments'][0]['id']) ); - $request->setContent(['shippingMethod' => $this->iriConverter->getItemIriFromResourceClass($this->shippingMethodClass, ['code' => $shippingMethodCode])]); $this->client->executeCustomRequest($request); @@ -408,14 +411,13 @@ public function iTryToSelectShippingMethod(string $shippingMethodCode): void */ public function iTryToSelectPaymentMethod(string $paymentMethodCode): void { - $request = Request::customItemAction( + $request = $this->requestFactory->customItemAction( 'shop', Resources::ORDERS, $this->sharedStorage->get('cart_token'), HTTPRequest::METHOD_PATCH, sprintf('payments/%s', $this->getCart()['payments'][0]['id']) ); - $request->setContent(['paymentMethod' => $this->iriConverter->getItemIriFromResourceClass($this->paymentMethodClass, ['code' => $paymentMethodCode])]); $this->client->executeCustomRequest($request); @@ -479,14 +481,13 @@ public function iCompleteTheShippingStepWithFirstShippingMethod(): void */ public function iChoosePaymentMethod(PaymentMethodInterface $paymentMethod): void { - $request = Request::customItemAction( + $request = $this->requestFactory->customItemAction( 'shop', Resources::ORDERS, $this->sharedStorage->get('cart_token'), HTTPRequest::METHOD_PATCH, \sprintf('payments/%s', $this->getCart()['payments'][0]['id']) ); - $request->setContent(['paymentMethod' => $this->iriConverter->getIriFromItem($paymentMethod)]); $this->client->executeCustomRequest($request); @@ -1080,14 +1081,13 @@ public function iTryToAddProductVariantWithCode(ProductInterface $product, strin { $tokenValue = $this->getCartTokenValue(); - $request = Request::customItemAction( + $request = $this->requestFactory->customItemAction( 'shop', Resources::ORDERS, $tokenValue, HTTPRequest::METHOD_POST, 'items' ); - $request->setContent([ 'productVariant' => $this->iriConverter->getItemIriFromResourceClass(\get_class($product->getVariants()->first()), ['code' => $code]), 'quantity' => 1, @@ -1380,14 +1380,13 @@ private function putProductToCart(ProductInterface $product, string $tokenValue, private function putVariantToCart(ProductVariantInterface $productVariant, string $tokenValue, int $quantity = 1): void { - $request = Request::customItemAction( + $request = $this->requestFactory->customItemAction( 'shop', Resources::ORDERS, $tokenValue, HTTPRequest::METHOD_POST, 'items' ); - $request->setContent([ 'productVariant' => $this->iriConverter->getIriFromItem($productVariant), 'quantity' => $quantity, @@ -1398,7 +1397,7 @@ private function putVariantToCart(ProductVariantInterface $productVariant, strin private function removeOrderItemFromCart(int $orderItemId, string $tokenValue): void { - $request = Request::customItemAction( + $request = $this->requestFactory->customItemAction( 'shop', Resources::ORDERS, $tokenValue, @@ -1451,14 +1450,13 @@ private function completeOrder(): Response { $notes = $this->content['additionalNote'] ?? null; - $request = Request::customItemAction( + $request = $this->requestFactory->customItemAction( 'shop', Resources::ORDERS, $this->sharedStorage->get('cart_token'), HTTPRequest::METHOD_PATCH, 'complete' ); - $request->setContent(['notes' => $notes]); return $this->client->executeCustomRequest($request); @@ -1466,14 +1464,13 @@ private function completeOrder(): Response private function selectShippingMethod(ShippingMethodInterface $shippingMethod): Response { - $request = Request::customItemAction( + $request = $this->requestFactory->customItemAction( 'shop', Resources::ORDERS, $this->sharedStorage->get('cart_token'), HTTPRequest::METHOD_PATCH, sprintf('shipments/%s', $this->getCart()['shipments'][0]['id']) ); - $request->setContent(['shippingMethod' => $this->iriConverter->getIriFromItem($shippingMethod)]); return $this->client->executeCustomRequest($request); diff --git a/src/Sylius/Behat/Context/Api/Shop/CustomerContext.php b/src/Sylius/Behat/Context/Api/Shop/CustomerContext.php index 9d3e8309d89..df795dc001e 100644 --- a/src/Sylius/Behat/Context/Api/Shop/CustomerContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/CustomerContext.php @@ -15,7 +15,7 @@ use Behat\Behat\Context\Context; 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\Resources; use Sylius\Behat\Context\Setup\ShopSecurityContext; @@ -28,34 +28,17 @@ final class CustomerContext implements Context { - private ApiClientInterface $client; - - private SharedStorageInterface $sharedStorage; - - private ResponseCheckerInterface $responseChecker; - - private RegistrationContext $registrationContext; - - private LoginContext $loginContext; - - private ShopSecurityContext $shopApiSecurityContext; - private ?string $verificationToken = ''; public function __construct( - ApiClientInterface $client, - SharedStorageInterface $sharedStorage, - ResponseCheckerInterface $responseChecker, - RegistrationContext $registrationContext, - LoginContext $loginContext, - ShopSecurityContext $shopApiSecurityContext + private ApiClientInterface $client, + private SharedStorageInterface $sharedStorage, + private ResponseCheckerInterface $responseChecker, + private RegistrationContext $registrationContext, + private LoginContext $loginContext, + private ShopSecurityContext $shopApiSecurityContext, + private RequestFactoryInterface $requestFactory, ) { - $this->client = $client; - $this->sharedStorage = $sharedStorage; - $this->responseChecker = $responseChecker; - $this->registrationContext = $registrationContext; - $this->loginContext = $loginContext; - $this->shopApiSecurityContext = $shopApiSecurityContext; } /** @@ -486,7 +469,7 @@ private function isViolationWithMessageInResponse(Response $response, string $me private function verifyAccount(string $token): void { - $request = Request::custom( + $request = $this->requestFactory->custom( \sprintf('/api/v2/shop/account-verification-requests/%s', $token), HttpRequest::METHOD_PATCH, ); @@ -496,7 +479,7 @@ private function verifyAccount(string $token): void private function registerAccount(?string $email = 'example@example.com', ?string $password = 'example'): void { - $request = Request::create('shop', Resources::CUSTOMERS, ''); + $request = $this->requestFactory->create('shop', Resources::CUSTOMERS, ''); $request->setContent([ 'firstName' => 'First', @@ -510,7 +493,7 @@ private function registerAccount(?string $email = 'example@example.com', ?string private function resendVerificationEmail(string $email): void { - $request = Request::create('shop', 'account-verification-requests', 'Bearer'); + $request = $this->requestFactory->create('shop', 'account-verification-requests', 'Bearer'); $request->setContent(['email' => $email]); diff --git a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php index eb57ec3378e..36b5c5f488d 100644 --- a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php @@ -13,12 +13,12 @@ namespace Sylius\Behat\Context\Api\Shop; +use Sylius\Behat\Client\RequestFactoryInterface; use Sylius\Behat\Client\RequestInterface; use ApiPlatform\Core\Api\IriConverterInterface; use Behat\Behat\Context\Context; use Sylius\Behat\Client\ApiClientInterface; use Sylius\Behat\Client\ApiSecurityClientInterface; -use Sylius\Behat\Client\Request; use Sylius\Behat\Client\ResponseCheckerInterface; use Sylius\Behat\Service\SharedStorageInterface; use Sylius\Component\Core\Model\CustomerInterface; @@ -30,34 +30,17 @@ final class LoginContext implements Context { - private ApiSecurityClientInterface $apiSecurityClient; - - private ApiClientInterface $client; - - private IriConverterInterface $iriConverter; - - private AbstractBrowser $shopAuthenticationTokenClient; - - private ResponseCheckerInterface $responseChecker; - - private SharedStorageInterface $sharedStorage; - private ?RequestInterface $request = null; public function __construct( - ApiSecurityClientInterface $apiSecurityClient, - ApiClientInterface $client, - IriConverterInterface $iriConverter, - AbstractBrowser $shopAuthenticationTokenClient, - ResponseCheckerInterface $responseChecker, - SharedStorageInterface $sharedStorage + private ApiSecurityClientInterface $apiSecurityClient, + private ApiClientInterface $client, + private IriConverterInterface $iriConverter, + private AbstractBrowser $shopAuthenticationTokenClient, + private ResponseCheckerInterface $responseChecker, + private SharedStorageInterface $sharedStorage, + private RequestFactoryInterface $requestFactory, ) { - $this->apiSecurityClient = $apiSecurityClient; - $this->client = $client; - $this->iriConverter = $iriConverter; - $this->shopAuthenticationTokenClient = $shopAuthenticationTokenClient; - $this->responseChecker = $responseChecker; - $this->sharedStorage = $sharedStorage; } /** @@ -101,7 +84,7 @@ public function iWantToLogIn(): void */ public function iWantToResetPassword(): void { - $this->request = Request::create('shop', 'reset-password-requests', 'Bearer'); + $this->request = $this->requestFactory->create('shop', 'reset-password-requests', 'Bearer'); } /** @@ -120,7 +103,7 @@ public function iResetPasswordForEmailInLocale(string $email, LocaleInterface $l */ public function iFollowLinkOnMyEmailToResetPassword(ShopUserInterface $user): void { - $this->request = Request::custom( + $this->request = $this->requestFactory->custom( sprintf('api/v2/shop/reset-password-requests/%s', $user->getPasswordResetToken()), HttpRequest::METHOD_PATCH ); diff --git a/src/Sylius/Behat/Context/Api/Shop/OrderContext.php b/src/Sylius/Behat/Context/Api/Shop/OrderContext.php index 0cfb168f6d3..763b1ab2e7f 100644 --- a/src/Sylius/Behat/Context/Api/Shop/OrderContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/OrderContext.php @@ -16,7 +16,7 @@ use ApiPlatform\Core\Api\IriConverterInterface; use Behat\Behat\Context\Context; 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\Resources; use Sylius\Behat\Service\SecurityServiceInterface; @@ -36,32 +36,15 @@ final class OrderContext implements Context { - private ApiClientInterface $shopClient; - - private ApiClientInterface $adminClient; - - private ResponseCheckerInterface $responseChecker; - - private SharedStorageInterface $sharedStorage; - - private IriConverterInterface $iriConverter; - - private SecurityServiceInterface $securityService; - public function __construct( - ApiClientInterface $shopClient, - ApiClientInterface $adminClient, - ResponseCheckerInterface $responseChecker, - SharedStorageInterface $sharedStorage, - IriConverterInterface $iriConverter, - SecurityServiceInterface $securityService + private ApiClientInterface $shopClient, + private ApiClientInterface $adminClient, + private ResponseCheckerInterface $responseChecker, + private SharedStorageInterface $sharedStorage, + private IriConverterInterface $iriConverter, + private SecurityServiceInterface $securityService, + private RequestFactoryInterface $requestFactory, ) { - $this->shopClient = $shopClient; - $this->adminClient = $adminClient; - $this->responseChecker = $responseChecker; - $this->sharedStorage = $sharedStorage; - $this->iriConverter = $iriConverter; - $this->securityService = $securityService; } /** @@ -72,8 +55,8 @@ public function iChangeMyPaymentMethodTo(PaymentMethodInterface $paymentMethod): /** @var OrderInterface $order */ $order = $this->sharedStorage->get('order'); - $request = Request::custom( - \sprintf( + $request = $this->requestFactory->custom( + sprintf( '/api/v2/shop/account/orders/%s/payments/%s', $order->getTokenValue(), (string) $order->getPayments()->first()->getId() @@ -82,7 +65,6 @@ public function iChangeMyPaymentMethodTo(PaymentMethodInterface $paymentMethod): [], $this->shopClient->getToken() ); - $request->setContent(['paymentMethod' => $this->iriConverter->getIriFromItem($paymentMethod)]); $this->shopClient->executeCustomRequest($request); @@ -428,7 +410,8 @@ private function getProductForItem(array $item): Response ); } - $this->shopClient->executeCustomRequest(Request::custom($item['variant'], HttpRequest::METHOD_GET)); + $request = $this->requestFactory->custom($item['variant'], HttpRequest::METHOD_GET); + $this->shopClient->executeCustomRequest($request); return $this->shopClient->showByIri($this->responseChecker->getValue($this->shopClient->getLastResponse(), 'product')); } diff --git a/src/Sylius/Behat/Context/Api/Shop/ProductContext.php b/src/Sylius/Behat/Context/Api/Shop/ProductContext.php index d750a88e543..c59e87ea743 100644 --- a/src/Sylius/Behat/Context/Api/Shop/ProductContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/ProductContext.php @@ -17,7 +17,7 @@ use Behat\Behat\Context\Context; use Doctrine\Common\Collections\ArrayCollection; 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\Resources; use Sylius\Behat\Service\Setter\ChannelContextSetterInterface; @@ -38,6 +38,7 @@ public function __construct( private SharedStorageInterface $sharedStorage, private IriConverterInterface $iriConverter, private ChannelContextSetterInterface $channelContextSetter, + private RequestFactoryInterface $requestFactory, ) { } @@ -423,7 +424,8 @@ public function itsCurrentVariantShouldBeNamed(string $variantName): void $response = $this->client->getLastResponse(); $productVariant = $this->responseChecker->getValue($response, 'variants'); - $this->client->executeCustomRequest(Request::custom($productVariant[0], HttpRequest::METHOD_GET)); + $request = $this->requestFactory->custom($productVariant[0], HttpRequest::METHOD_GET); + $this->client->executeCustomRequest($request); Assert::true($this->responseChecker->hasValue($this->client->getLastResponse(), 'name', $variantName)); } @@ -556,7 +558,8 @@ private function hasProductWithPrice( } foreach ($product['variants'] as $variantIri) { - $response = $this->client->executeCustomRequest(Request::custom($variantIri, HttpRequest::METHOD_GET)); + $request = $this->requestFactory->custom($variantIri, HttpRequest::METHOD_GET); + $response = $this->client->executeCustomRequest($request); /** @var int $variantPrice */ $variantPrice = $this->responseChecker->getValue($response, $priceType); diff --git a/src/Sylius/Behat/Context/Api/Shop/PromotionContext.php b/src/Sylius/Behat/Context/Api/Shop/PromotionContext.php index 843e352d268..c6e11e8fd93 100644 --- a/src/Sylius/Behat/Context/Api/Shop/PromotionContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/PromotionContext.php @@ -15,11 +15,9 @@ use Behat\Behat\Context\Context; use Sylius\Behat\Client\ApiClientInterface; -use Sylius\Behat\Client\Request; use Sylius\Behat\Client\ResponseCheckerInterface; use Sylius\Behat\Context\Api\Resources; use Sylius\Behat\Service\SharedStorageInterface; -use Symfony\Component\HttpFoundation\Request as HttpRequest; use Webmozart\Assert\Assert; final class PromotionContext implements Context diff --git a/src/Sylius/Behat/Resources/config/services.xml b/src/Sylius/Behat/Resources/config/services.xml index dc5462ec1ec..9ead1f058b6 100644 --- a/src/Sylius/Behat/Resources/config/services.xml +++ b/src/Sylius/Behat/Resources/config/services.xml @@ -69,17 +69,21 @@ + + + + diff --git a/src/Sylius/Behat/Resources/config/services/api.xml b/src/Sylius/Behat/Resources/config/services/api.xml index e45493b9d51..626948845b3 100644 --- a/src/Sylius/Behat/Resources/config/services/api.xml +++ b/src/Sylius/Behat/Resources/config/services/api.xml @@ -16,6 +16,7 @@ + %sylius.api.authorization_header% @@ -42,5 +43,11 @@ shop + + + + + + diff --git a/src/Sylius/Behat/Resources/config/services/contexts/api/admin.xml b/src/Sylius/Behat/Resources/config/services/contexts/api/admin.xml index 5accd33b84a..86d15cf534d 100644 --- a/src/Sylius/Behat/Resources/config/services/contexts/api/admin.xml +++ b/src/Sylius/Behat/Resources/config/services/contexts/api/admin.xml @@ -33,6 +33,7 @@ + diff --git a/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml b/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml index 5d6a33727f6..f63e5ea13b1 100644 --- a/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml +++ b/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml @@ -44,6 +44,7 @@ + @@ -53,6 +54,7 @@ + @@ -70,6 +72,7 @@ + %sylius.model.payment_method.class% %sylius.model.shipping_method.class% @@ -86,6 +89,7 @@ + @@ -94,6 +98,7 @@ + @@ -124,6 +129,7 @@ +