From ff434528534e0702a968fffbf18661b0e20579db Mon Sep 17 00:00:00 2001
From: Kamil Grygierzec <kam.grygierzec@gmail.com>
Date: Mon, 23 Sep 2024 14:44:46 +0200
Subject: [PATCH] Cover behat tests

---
 .../reordering_product_images.feature         | 23 ++++++++
 .../show/viewing_product_image.feature        | 16 ------
 .../show/viewing_product_images.feature       | 28 +++++++++
 .../Api/Admin/ManagingProductsContext.php     | 57 +++++++++++++++++++
 .../Behat/Context/Api/Shop/ProductContext.php | 34 +++++++++++
 .../Behat/Context/Setup/ProductContext.php    | 10 ++++
 .../Ui/Admin/ManagingProductsContext.php      | 35 ++++++++++++
 ...gBetweenProductShowAndEditPagesContext.php |  8 +++
 .../Behat/Context/Ui/Shop/ProductContext.php  | 30 +++++++++-
 .../Admin/Product/MediaFormElement.php        | 54 ++++++++++++++++++
 .../Product/MediaFormElementInterface.php     |  8 +++
 .../Behat/Page/Shop/Product/ShowPage.php      | 33 +++++++++--
 .../Page/Shop/Product/ShowPageInterface.php   |  8 ++-
 .../config/services/contexts/api/shop.xml     |  1 +
 14 files changed, 321 insertions(+), 24 deletions(-)
 create mode 100644 features/admin/product/managing_products/reordering_product_images.feature
 delete mode 100644 features/shop/product/show/viewing_product_image.feature
 create mode 100644 features/shop/product/show/viewing_product_images.feature

diff --git a/features/admin/product/managing_products/reordering_product_images.feature b/features/admin/product/managing_products/reordering_product_images.feature
new file mode 100644
index 000000000000..77acab81382c
--- /dev/null
+++ b/features/admin/product/managing_products/reordering_product_images.feature
@@ -0,0 +1,23 @@
+@managing_products
+Feature: Reordering product images
+    In order to have the most important product image displayed first
+    As an Administrator
+    I want to be able to reorder product images
+
+    Background:
+        Given the store operates on a channel named "Web-US" in "USD" currency
+        And the store has a product "Dice Brewing" priced at "$10.00" in "Web-US" channel
+        And this product has an image "ford.jpg" with "small" type at position 0
+        And this product has an image "ford.jpg" with "medium" type at position 1
+        And this product has an image "ford.jpg" with "large" type at position 2
+        And I am logged in as an administrator
+
+    @api @ui @mink:chromedriver
+    Scenario: Reordering product images
+        When I want to modify the images of "Dice Brewing" product
+        And I change the "small" image position to 2
+        And I change the "medium" image position to 0
+        And I change the "large" image position to 1
+        Then I save my changes to the images
+        And the one before last image on the list should have type "large" with position 1
+        And the last image on the list should have type small with position 2
diff --git a/features/shop/product/show/viewing_product_image.feature b/features/shop/product/show/viewing_product_image.feature
deleted file mode 100644
index f76bb5d4912b..000000000000
--- a/features/shop/product/show/viewing_product_image.feature
+++ /dev/null
@@ -1,16 +0,0 @@
-@viewing_products
-Feature: Viewing a product's image on a product details page
-    In order to see images of a product
-    As a Visitor
-    I want to be able to view an image of a single product
-
-    Background:
-        Given the store operates on a single channel in "United States"
-        And the store has a product "Lamborghini Gallardo Model"
-        And this product has an image "lamborghini.jpg" with "main" type
-
-    @api @ui @javascript
-    Scenario: Viewing a product's image on a product details page
-        When I check this product's details
-        Then I should see the product name "Lamborghini Gallardo Model"
-        And I should see a main image
diff --git a/features/shop/product/show/viewing_product_images.feature b/features/shop/product/show/viewing_product_images.feature
new file mode 100644
index 000000000000..bee896ed9c43
--- /dev/null
+++ b/features/shop/product/show/viewing_product_images.feature
@@ -0,0 +1,28 @@
+@viewing_products
+Feature: Viewing a product's images on a product details page
+    In order to see images of a product
+    As a Visitor
+    I want to be able to view a product's images
+
+    Background:
+        Given the store operates on a single channel in "United States"
+
+    @api @ui @mink:chromedriver
+    Scenario: Viewing a product's main image on a product details page
+        Given the store has a product "Lamborghini Gallardo Model"
+        And this product has an image "lamborghini.jpg" with "other" type at position 2
+        And this product has an image "lamborghini.jpg" with "main" type at position 1
+        When I check this product's details
+        Then I should see the product name "Lamborghini Gallardo Model"
+        And I should see a main image of type "main"
+
+    @api @ui @mink:chromedriver
+    Scenario: Viewing a products images in correct order
+        Given the store has a product "Lamborghini Gallardo Model"
+        And this product has an image "lamborghini.jpg" with "other" type at position 2
+        And this product has an image "lamborghini.jpg" with "thumbnail" type at position 1
+        When I check this product's details
+        Then I should see the product name "Lamborghini Gallardo Model"
+        And the main image should be of type "thumbnail"
+        And the first thumbnail image should be of type "thumbnail"
+        And the second thumbnail image should be of type "other"
diff --git a/src/Sylius/Behat/Context/Api/Admin/ManagingProductsContext.php b/src/Sylius/Behat/Context/Api/Admin/ManagingProductsContext.php
index 87307d5c8e28..f63c3079bbd6 100644
--- a/src/Sylius/Behat/Context/Api/Admin/ManagingProductsContext.php
+++ b/src/Sylius/Behat/Context/Api/Admin/ManagingProductsContext.php
@@ -15,6 +15,7 @@
 
 use Behat\Behat\Context\Context;
 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\Resources;
@@ -32,6 +33,7 @@
 use Sylius\Component\Product\Model\ProductAssociationTypeInterface;
 use Sylius\Component\Product\Model\ProductAttributeInterface;
 use Sylius\Component\Product\Model\ProductOptionInterface;
+use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Webmozart\Assert\Assert;
 
@@ -343,6 +345,39 @@ public function iSetTheInvalidStringValueOfTheNonTranslatableAttributeTo(Product
         );
     }
 
+    /**
+     * @When I want to modify the images of :product product
+     */
+    public function iWantToModifyTheImagesOfProduct(ProductInterface $product): void
+    {
+        $this->sharedStorage->set('productIri', $this->iriConverter->getIriFromResource($product));
+    }
+
+    /**
+     * @When I change the :type image position to :position
+     */
+    public function iChangeTheImagePositionTo(string $imageType, int $position): void
+    {
+        $images = $this->responseChecker->getValue($this->client->showByIri($this->sharedStorage->get('productIri')), 'images');
+        $productCode = $this->responseChecker->getValue($this->client->getLastResponse(), 'code');
+
+        foreach ($images as $key => $imageData) {
+            if ($imageData['type'] === $imageType) {
+                $imageId = $imageData['id'];
+            }
+        }
+
+        $builder = RequestBuilder::create(
+            sprintf('/api/v2/admin/products/%s/images/%s', $productCode, $imageId),
+            Request::METHOD_PUT,
+        );
+        $builder->withContent(['position' => $position]);
+        $builder->withHeader('HTTP_Authorization', 'Bearer ' . $this->sharedStorage->get('token'));
+        $builder->withHeader('CONTENT_TYPE', 'application/ld+json');
+
+        $this->client->request($builder->build());
+    }
+
     /**
      * @When I set its :attribute attribute to :value
      * @When I set its :attribute attribute to :value in :localeCode locale
@@ -616,6 +651,28 @@ public function iShouldBeNotifiedThatIsRequired(string $element): void
         );
     }
 
+    /**
+     * @Then the one before last image on the list should have type :type with position :position
+     */
+    public function theOneBeforeLastImageOnTheListShouldHaveNameWithPosition(string $imageType, int $position): void
+    {
+        $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);
+    }
+
+    /**
+     * @Then the last image on the list should have type :type with position :position
+     */
+    public function theLastImageOnTheListShouldHaveNameWithPosition(string $imageType, int $position): void
+    {
+        $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);
+    }
+
     /**
      * @Then I should be notified that meta keywords are too long
      */
diff --git a/src/Sylius/Behat/Context/Api/Shop/ProductContext.php b/src/Sylius/Behat/Context/Api/Shop/ProductContext.php
index 4c1acb0a412b..9c7ba5fe104f 100644
--- a/src/Sylius/Behat/Context/Api/Shop/ProductContext.php
+++ b/src/Sylius/Behat/Context/Api/Shop/ProductContext.php
@@ -16,6 +16,7 @@
 use ApiPlatform\Api\IriConverterInterface;
 use Behat\Behat\Context\Context;
 use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Persistence\ObjectManager;
 use Sylius\Behat\Client\ApiClientInterface;
 use Sylius\Behat\Client\RequestFactoryInterface;
 use Sylius\Behat\Client\ResponseCheckerInterface;
@@ -41,6 +42,7 @@ public function __construct(
         private IriConverterInterface $iriConverter,
         private ChannelContextSetterInterface $channelContextSetter,
         private RequestFactoryInterface $requestFactory,
+        private ObjectManager $objectManager,
         private string $apiUrlPrefix,
     ) {
     }
@@ -52,6 +54,7 @@ public function __construct(
      */
     public function iViewProduct(ProductInterface $product): void
     {
+        $this->objectManager->clear(); // it's needed to clear the entity manager to receive the product images in correct order, as the images are using fallback order when added programmatically
         $this->client->show(Resources::PRODUCTS, $product->getCode());
 
         /** @var ProductVariantInterface $productVariant */
@@ -473,6 +476,37 @@ public function iShouldSeeProductName(string $name): void
         Assert::true($this->responseChecker->hasValue($this->client->getLastResponse(), 'name', $name));
     }
 
+    /**
+     * @Then the main image should be of type :type
+     * @Then I should see a main image of type :type
+     */
+    public function theMainImageShouldBeOfType(string $type): void
+    {
+        $images = $this->responseChecker->getValue($this->client->getLastResponse(), 'images');
+
+        Assert::same($images[0]['type'], $type);
+    }
+
+    /**
+     * @Then the first thumbnail image should be of type :type
+     */
+    public function theFirstThumbnailImageShouldBeOfType(string $type): void
+    {
+        $images = $this->responseChecker->getValue($this->client->getLastResponse(), 'images');
+
+        Assert::same($images[0]['type'], $type);
+    }
+
+    /**
+     * @Then the second thumbnail image should be of type :type
+     */
+    public function theSecondThumbnailImageShouldBeOfType(string $type): void
+    {
+        $images = $this->responseChecker->getValue($this->client->getLastResponse(), 'images');
+
+        Assert::same($images[1]['type'], $type);
+    }
+
     /**
      * @Then /^I should not be able to view (this product) in the ("([^"]+)" locale)$/
      */
diff --git a/src/Sylius/Behat/Context/Setup/ProductContext.php b/src/Sylius/Behat/Context/Setup/ProductContext.php
index 8bda9f883d40..ea63a0e4ca2f 100644
--- a/src/Sylius/Behat/Context/Setup/ProductContext.php
+++ b/src/Sylius/Behat/Context/Setup/ProductContext.php
@@ -862,6 +862,14 @@ public function thisProductHasAnImageWithType(ProductInterface $product, $imageP
         $this->createProductImage($product, $imagePath, $imageType);
     }
 
+    /**
+     * @Given /^(this product) has an image "([^"]+)" with "([^"]+)" type at position (\d+)$/
+     */
+    public function thisProductHasAnImageWithTypeAtPosition(ProductInterface $product, string $imagePath, string $imageType, int $position): void
+    {
+        $this->createProductImage($product, $imagePath, $imageType, null, $position);
+    }
+
     /**
      * @Given /^(this product) has an image "([^"]+)" with "([^"]+)" type for ("[^"]+" variant)$/
      */
@@ -1585,6 +1593,7 @@ private function createProductImage(
         string $imagePath,
         string $imageType,
         ?ProductVariantInterface $variant = null,
+        ?int $position = null,
     ): void {
         $filesPath = $this->getParameter('files_path');
 
@@ -1592,6 +1601,7 @@ private function createProductImage(
         $productImage = $this->productImageFactory->createNew();
         $productImage->setFile(new UploadedFile($filesPath . $imagePath, basename($imagePath)));
         $productImage->setType($imageType);
+        $productImage->setPosition($position);
 
         if (null !== $variant) {
             $productImage->addProductVariant($variant);
diff --git a/src/Sylius/Behat/Context/Ui/Admin/ManagingProductsContext.php b/src/Sylius/Behat/Context/Ui/Admin/ManagingProductsContext.php
index 6a93ef9b8231..67c6cc453c20 100644
--- a/src/Sylius/Behat/Context/Ui/Admin/ManagingProductsContext.php
+++ b/src/Sylius/Behat/Context/Ui/Admin/ManagingProductsContext.php
@@ -401,6 +401,32 @@ public function theOneBeforeLastProductOnTheListShouldHaveNameWithPosition(strin
         $this->sharedStorage->set('product_taxon_name', $productName);
     }
 
+    /**
+     * @Then the one before last image on the list should have type :type with position :position
+     */
+    public function theOneBeforeLastImageOnTheListShouldHaveNameWithPosition(string $imageType, int $position): void
+    {
+        $images = $this->mediaFormElement->getImages();
+        if (count($images) < 2) {
+            throw new \Exception('There are less than two images on the list.');
+        }
+
+        $oneBeforeLastImage = $images[count($images) - 2];
+
+        $this->mediaFormElement->assertImageTypeAndPosition($oneBeforeLastImage, $imageType, $position);
+    }
+
+    /**
+     * @Then the last image on the list should have type :type with position :position
+     */
+    public function theLastImageOnTheListShouldHaveNameWithPosition(string $imageType, int $position): void
+    {
+        $images = $this->mediaFormElement->getImages();
+        $lastImage = end($images);
+
+        $this->mediaFormElement->assertImageTypeAndPosition($lastImage, $imageType, $position);
+    }
+
     /**
      * @Then the last product on the list should have :field :value
      * @Then the last product on the list within this taxon should have :field :value
@@ -492,6 +518,7 @@ public function productShouldExistInTheProductCatalog(ProductInterface $product)
      * @When /^I want to modify (this product)$/
      * @When /^I want to edit (this product)$/
      * @When I modify the :product product
+     * @When I want to modify the images of :product product
      */
     public function iWantToModifyAProduct(ProductInterface $product): void
     {
@@ -1000,6 +1027,14 @@ public function iChangeTheFirstImageTypeTo(string $type): void
         $this->mediaFormElement->modifyFirstImageType($type);
     }
 
+    /**
+     * @When I change the :type image position to :position
+     */
+    public function iChangeTheImagePositionTo(string $image, int $position): void
+    {
+        $this->mediaFormElement->modifyPositionOfImageWithType($image, $position);
+    }
+
     /**
      * @Then /^(this product) should not have any images$/
      */
diff --git a/src/Sylius/Behat/Context/Ui/Admin/NavigatingBetweenProductShowAndEditPagesContext.php b/src/Sylius/Behat/Context/Ui/Admin/NavigatingBetweenProductShowAndEditPagesContext.php
index d3034c34d7f7..a10680d67f30 100644
--- a/src/Sylius/Behat/Context/Ui/Admin/NavigatingBetweenProductShowAndEditPagesContext.php
+++ b/src/Sylius/Behat/Context/Ui/Admin/NavigatingBetweenProductShowAndEditPagesContext.php
@@ -92,6 +92,14 @@ public function iWantToModifyAProduct(ProductInterface $product): void
         $this->updateSimpleProductPage->open(['id' => $product->getId()]);
     }
 
+    /**
+     * @When I change position of the :image image to :position
+     */
+    public function iChangePositionOfTheImageTo(string $image, int $position): void
+    {
+        $this->updateSimpleProductPage->changeImagePosition($image, $position);
+    }
+
     /**
      * @Then I should be on :product product edit page
      */
diff --git a/src/Sylius/Behat/Context/Ui/Shop/ProductContext.php b/src/Sylius/Behat/Context/Ui/Shop/ProductContext.php
index 5f78239b98c9..a89fdb6d4207 100644
--- a/src/Sylius/Behat/Context/Ui/Shop/ProductContext.php
+++ b/src/Sylius/Behat/Context/Ui/Shop/ProductContext.php
@@ -591,11 +591,35 @@ public function iShouldBeNotifiedThatTheQuantityOfThisProductMustBeBetween1And99
     }
 
     /**
-     * @Then I should see a main image
+     * @Then I should see a main image of type :type
      */
-    public function iShouldSeeAMainImage(): void
+    public function iShouldSeeAMainImageOfType(string $type): void
     {
-        Assert::true($this->showPage->isMainImageDisplayed());
+        Assert::true($this->showPage->isMainImageOfTypeDisplayed($type));
+    }
+
+    /**
+     * @Then the main image should be of type :type
+     */
+    public function theMainImageShouldBeOfType(string $type): void
+    {
+        Assert::true($this->showPage->isMainImageOfType($type));
+    }
+
+    /**
+     * @Then the first thumbnail image should be of type :type
+     */
+    public function theFirstThumbnailImageShouldBeOfType(string $type): void
+    {
+        Assert::true($this->showPage->getFirstThumbnailsImageType() === $type);
+    }
+
+    /**
+     * @Then the second thumbnail image should be of type :type
+     */
+    public function theSecondThumbnailImageShouldBeOfType(string $type): void
+    {
+        Assert::true($this->showPage->getSecondThumbnailsImageType() === $type);
     }
 
     /**
diff --git a/src/Sylius/Behat/Element/Admin/Product/MediaFormElement.php b/src/Sylius/Behat/Element/Admin/Product/MediaFormElement.php
index 39fd95ba7561..81da8cd8f3a9 100644
--- a/src/Sylius/Behat/Element/Admin/Product/MediaFormElement.php
+++ b/src/Sylius/Behat/Element/Admin/Product/MediaFormElement.php
@@ -119,6 +119,32 @@ public function countImages(): int
         return count($imageSubforms);
     }
 
+    public function getImages(): array
+    {
+        $images = $this->getElement('images');
+        $imageSubforms = $images->findAll('css', '[data-test-image-subform]');
+
+        return $imageSubforms;
+    }
+
+    public function assertImageTypeAndPosition($image, string $expectedType, int $expectedPosition): void
+    {
+        $type = $image->find('css', 'input[data-test-type]')->getValue();
+        $position = $image->find('css', 'input[data-test-position]')->getValue();
+
+        if (!$type || !$position) {
+            throw new \Exception('Type or position element not found in the image subform.');
+        }
+
+        if ($type !== $expectedType) {
+            throw new \Exception(sprintf('Expected type "%s", but got "%s".', $expectedType, $type));
+        }
+
+        if ((int) $position !== $expectedPosition) {
+            throw new \Exception(sprintf('Expected position "%d", but got "%d".', $expectedPosition, $position));
+        }
+    }
+
     public function modifyFirstImageType(string $type): void
     {
         $this->changeTab();
@@ -128,6 +154,34 @@ public function modifyFirstImageType(string $type): void
         $firstImageSubform->find('css', 'input[data-test-type]')->setValue($type);
     }
 
+    public function modifyFirstImagePosition(int $position): void
+    {
+        $this->changeTab();
+
+        $firstImageSubform = $this->getFirstImageSubform();
+
+        $firstImageSubform->find('css', 'input[data-test-position]')->setValue($position);
+    }
+
+    public function modifyPositionOfImageWithType(string $type, int $position): void
+    {
+        $this->changeTab();
+
+        $imageSubform = $this->getElement('image_subform_with_type', ['%type%' => $type]);
+
+        $imageSubform->find('css', 'input[data-test-position]')->setValue($position);
+    }
+
+    public function hasImageWithTypeOnPosition(string $type, int $position): bool
+    {
+        $this->changeTab();
+
+        $imageSubform = $this->getElement('image_subform_with_type', ['%type%' => $type]);
+        $imagePosition = $imageSubform->find('css', 'input[data-test-position]')->getValue();
+
+        return $imagePosition === (string) $position;
+    }
+
     public function selectVariantForFirstImage(ProductVariantInterface $productVariant): void
     {
         $this->changeTab();
diff --git a/src/Sylius/Behat/Element/Admin/Product/MediaFormElementInterface.php b/src/Sylius/Behat/Element/Admin/Product/MediaFormElementInterface.php
index 9ceb8b150e48..f160d1d2742f 100644
--- a/src/Sylius/Behat/Element/Admin/Product/MediaFormElementInterface.php
+++ b/src/Sylius/Behat/Element/Admin/Product/MediaFormElementInterface.php
@@ -31,7 +31,15 @@ public function hasImageWithVariant(ProductVariantInterface $productVariant): bo
 
     public function countImages(): int;
 
+    public function getImages(): array;
+
+    public function assertImageTypeAndPosition($image, string $expectedType, int $expectedPosition): void;
+
     public function modifyFirstImageType(string $type): void;
 
+    public function modifyFirstImagePosition(int $position): void;
+
+    public function modifyPositionOfImageWithType(string $type, int $position): void;
+
     public function selectVariantForFirstImage(ProductVariantInterface $productVariant): void;
 }
diff --git a/src/Sylius/Behat/Page/Shop/Product/ShowPage.php b/src/Sylius/Behat/Page/Shop/Product/ShowPage.php
index 6f77db73db33..07a6e21d163a 100644
--- a/src/Sylius/Behat/Page/Shop/Product/ShowPage.php
+++ b/src/Sylius/Behat/Page/Shop/Product/ShowPage.php
@@ -230,13 +230,20 @@ public function isOutOfStock(): bool
         return $this->hasElement('out_of_stock');
     }
 
-    public function isMainImageDisplayed(): bool
+    public function isMainImageOfType(string $type): bool
     {
-        if (!$this->hasElement('main_image')) {
+        $mainImage = $this->getElement('main_image', ['%type%' => $type]);
+
+        return $mainImage !== null;
+    }
+
+    public function isMainImageOfTypeDisplayed(string $type): bool
+    {
+        if (!$this->hasElement('main_image', ['%type%' => $type])) {
             return false;
         }
 
-        $imageUrl = $this->getElement('main_image')->getAttribute('src');
+        $imageUrl = $this->getElement('main_image', ['%type%' => $type])->getAttribute('src');
         $this->getDriver()->visit($imageUrl);
         $pageText = $this->getDocument()->getText();
         $this->getDriver()->back();
@@ -244,6 +251,22 @@ public function isMainImageDisplayed(): bool
         return false === stripos($pageText, '404 Not Found');
     }
 
+    public function getFirstThumbnailsImageType(): string
+    {
+        $thumbnails = $this->getElement('thumbnails');
+        $images = $thumbnails->findAll('css', 'img');
+
+        return $images[0]->getAttribute('data-test-thumbnail-image');
+    }
+
+    public function getSecondThumbnailsImageType(): string
+    {
+        $thumbnails = $this->getElement('thumbnails');
+        $images = $thumbnails->findAll('css', 'img');
+
+        return $images[1]->getAttribute('data-test-thumbnail-image');
+    }
+
     public function countReviews(): int
     {
         return count($this->getElement('reviews')->findAll('css', '[data-test-title]'));
@@ -340,7 +363,9 @@ protected function getDefinedElements(): array
             'catalog_promotion' => '[data-test-promotion-label]',
             'current_variant_input' => '[data-test-product-variants] td input:checked',
             'details' => '[data-test-product-details]',
-            'main_image' => '[data-test-main-image]',
+            'main_image' => '[data-test-main-image="%type%"]',
+            'thumbnail_image' => '[data-test-thumbnail-image="%type%"]',
+            'thumbnails' => '[data-test-thumbnails]',
             'name' => '[data-test-product-name]',
             'option_select' => '#sylius_shop_add_to_cart_cartItem_variant_%optionCode%',
             'out_of_stock' => '[data-test-product-out-of-stock]',
diff --git a/src/Sylius/Behat/Page/Shop/Product/ShowPageInterface.php b/src/Sylius/Behat/Page/Shop/Product/ShowPageInterface.php
index 5ae1c45f8f39..bddc35c5d6d5 100644
--- a/src/Sylius/Behat/Page/Shop/Product/ShowPageInterface.php
+++ b/src/Sylius/Behat/Page/Shop/Product/ShowPageInterface.php
@@ -77,7 +77,13 @@ public function hasReviewTitled(string $title): bool;
 
     public function isOutOfStock(): bool;
 
-    public function isMainImageDisplayed(): bool;
+    public function isMainImageOfTypeDisplayed(string $type): bool;
+
+    public function isMainImageOfType(string $type): bool;
+
+    public function getFirstThumbnailsImageType(): string;
+
+    public function getSecondThumbnailsImageType(): string;
 
     public function countReviews(): int;
 
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 3290b4ee6287..59c7c131fb96 100644
--- a/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml
+++ b/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml
@@ -111,6 +111,7 @@
             <argument type="service" id="api_platform.iri_converter" />
             <argument type="service" id="sylius.behat.channel_context_setter" />
             <argument type="service" id="sylius.behat.request_factory" />
+            <argument type="service" id="doctrine.orm.entity_manager" />
             <argument>%sylius.security.new_api_route%</argument>
         </service>