From e13e27ac5b355bd473b0aba65e4ef5136eb8e0ab Mon Sep 17 00:00:00 2001 From: Lorenzo Ruozzi Date: Mon, 1 Aug 2022 12:57:00 +0200 Subject: [PATCH] WIP: refactor behat enqueuing products test (#123) --- features/enqueuing_generic_items.feature | 45 ---------- features/importing_generic_items.feature | 63 +++++++++++++ ...cts.feature => importing_products.feature} | 2 +- ...> importing_products_associations.feature} | 2 +- src/Product/Importer.php | 6 +- src/ProductAssociations/Importer.php | 5 +- .../config/packages/test/messenger.yaml | 2 +- .../Context/Messenger/MessengerContext.php | 8 -- .../Ui/Admin/ManagingProductsContext.php | 48 ++++++++++ tests/Behat/Resources/services.xml | 2 + tests/Behat/Resources/suites.yml | 10 ++- .../ApiClientMock/Product/10597353.json | 82 +++++++++++++++++ .../ApiClientMock/Product/11164822.json | 84 ++++++++++++++++++ .../ApiClientMock/Product/1314976.json | 72 +++++++++++++++ ...829a75beedf374533b1ff8bc_10597353_1104.jpg | Bin 0 -> 7896 bytes ...dbeababd84389b31159f8_11164822_Philips.jpg | Bin 0 -> 8545 bytes ...a0e6e91d0c512bc37c8780c21_1314976_5566.jpg | Bin 0 -> 8660 bytes 17 files changed, 369 insertions(+), 62 deletions(-) delete mode 100644 features/enqueuing_generic_items.feature create mode 100644 features/importing_generic_items.feature rename features/{enqueuing_products.feature => importing_products.feature} (99%) rename features/{enqueuing_products_associations.feature => importing_products_associations.feature} (96%) create mode 100644 tests/Integration/DataFixtures/ApiClientMock/Product/10597353.json create mode 100644 tests/Integration/DataFixtures/ApiClientMock/Product/11164822.json create mode 100644 tests/Integration/DataFixtures/ApiClientMock/Product/1314976.json create mode 100644 tests/Integration/DataFixtures/ApiClientMock/media-files/6/5/8/8/65887ee600d9d66e829a75beedf374533b1ff8bc_10597353_1104.jpg create mode 100644 tests/Integration/DataFixtures/ApiClientMock/media-files/7/3/6/b/736bbc43fd1e384f4badbeababd84389b31159f8_11164822_Philips.jpg create mode 100644 tests/Integration/DataFixtures/ApiClientMock/media-files/8/e/2/d/8e2d8254e599201a0e6e91d0c512bc37c8780c21_1314976_5566.jpg diff --git a/features/enqueuing_generic_items.feature b/features/enqueuing_generic_items.feature deleted file mode 100644 index 6713e3cc..00000000 --- a/features/enqueuing_generic_items.feature +++ /dev/null @@ -1,45 +0,0 @@ -@enqueuing_generic_items -Feature: Enqueuing items - In order to import data from Akeneo - As a Store Owner - I want to import items from the Akeneo PIM - - @cli - Scenario: Enqueueing items when no item is modified since the given date - When I import items for all importers modified since date "2020-01-20 01:00:00" - Then there should be no item in the Akeneo queue - - @cli - Scenario: Enqueueing items without a since date - When I import items for all importers with no since date - Then I should be notified that a since date is required - And there should be no item in the Akeneo queue - - @cli - Scenario: Enqueueing items with an invalid since date - When I import items for all importers with invalid since date - Then I should be notified that the since date must be a valid date - - @cli - Scenario: Enqueueing items with a since date specified from a not existent file - When I import items with since date specified from a not existent file - Then I should be notified that the since date file does not exists - - @cli - Scenario: Enqueuing all items regardless last modified date - Given there are 3 products on Akeneo - When I import all items for all importers - Then there should be 3 items for the "Product" importer in the Akeneo queue - And there should be 3 items for the "ProductAssociations" importer in the Akeneo queue - - @cli - Scenario: Enqueuing all items for one importer only - Given there are 3 products on Akeneo - When I import all items for the "Product" importer - Then there should be 3 items for the "Product" importer in the Akeneo queue - And there should be items for the "Product" importer only in the Akeneo queue - - @cli - Scenario: Enqueuing all items for a not existent importer - When I import all items for a not existent importer - Then I should be notified that the importer does not exists diff --git a/features/importing_generic_items.feature b/features/importing_generic_items.feature new file mode 100644 index 00000000..b3f038e7 --- /dev/null +++ b/features/importing_generic_items.feature @@ -0,0 +1,63 @@ +@importing_generic_items +Feature: Importing items + In order to import data from Akeneo + As an Administrator + I want to import items from the Akeneo PIM + + Background: + Given I am logged in as an administrator + And the store has a product association type "Pack" with a code "PACK" + + @cli @ui + Scenario: Importing items when no item is modified since the given date + When I import items for all importers modified since date "2020-01-20 01:00:00" + And I browse products + Then I should see 0 products in the list + + @cli @ui + Scenario: Importing items without a since date + When I import items for all importers with no since date + Then I should be notified that a since date is required + When I browse products + Then I should see 0 products in the list + + @cli @ui + Scenario: Importing items with an invalid since date + When I import items for all importers with invalid since date + Then I should be notified that the since date must be a valid date + When I browse products + Then I should see 0 products in the list + + @cli @ui + Scenario: Importing items with a since date specified from a not existent file + When I import items with since date specified from a not existent file + Then I should be notified that the since date file does not exists + When I browse products + Then I should see 0 products in the list + + @cli @ui + Scenario: Importing all items regardless last modified date + Given there is a product "1314976" updated at "2022-06-15" on Akeneo + And there is a product "10597353" updated at "2022-07-23" on Akeneo + And there is a product "11164822" updated at "2022-08-01" on Akeneo + When I import all items for all importers + And I browse products + Then I should see 3 products in the list + And the product with code "11164822" should have an association "Pack" with product "10597353" + + @cli @ui + Scenario: Importing all items for one importer only + Given there is a product "1314976" updated at "2022-06-15" on Akeneo + And there is a product "10597353" updated at "2022-07-23" on Akeneo + And there is a product "11164822" updated at "2022-08-01" on Akeneo + When I import all items for the "Product" importer + And I browse products + Then I should see 3 products in the list + And the product with code "11164822" should not have an association "Pack" with product "10597353" + + @cli @ui + Scenario: Enqueuing all items for a not existent importer + When I import all items for a not existent importer + Then I should be notified that the importer does not exists + When I browse products + Then I should see 0 products in the list diff --git a/features/enqueuing_products.feature b/features/importing_products.feature similarity index 99% rename from features/enqueuing_products.feature rename to features/importing_products.feature index 8f7718ad..3a400457 100644 --- a/features/enqueuing_products.feature +++ b/features/importing_products.feature @@ -1,4 +1,4 @@ -@enqueuing_products +@importing_products Feature: Enqueuing products In order to import my products from Akeneo As a Store Owner diff --git a/features/enqueuing_products_associations.feature b/features/importing_products_associations.feature similarity index 96% rename from features/enqueuing_products_associations.feature rename to features/importing_products_associations.feature index df84f23d..7e05c0b3 100644 --- a/features/enqueuing_products_associations.feature +++ b/features/importing_products_associations.feature @@ -1,4 +1,4 @@ -@enqueuing_products_associations +@importing_products_associations Feature: Enqueuing products associations In order to import my products associations from Akeneo As a Store Owner diff --git a/src/Product/Importer.php b/src/Product/Importer.php index 991d1c64..fe7629e6 100644 --- a/src/Product/Importer.php +++ b/src/Product/Importer.php @@ -104,8 +104,10 @@ public function getIdentifiersModifiedSince(DateTime $sinceDate): array $products = $this->apiClient->getProductApi()->all(50, ['search' => $searchBuilder->getFilters()]); $identifiers = []; foreach ($products as $product) { - Assert::string($product['identifier']); - $identifiers[] = $product['identifier']; + Assert::keyExists($product, 'identifier'); + $productIdentifier = (string) $product['identifier']; + Assert::stringNotEmpty($productIdentifier); + $identifiers[] = $productIdentifier; } return $identifiers; diff --git a/src/ProductAssociations/Importer.php b/src/ProductAssociations/Importer.php index bfdd9200..3f08d3f4 100644 --- a/src/ProductAssociations/Importer.php +++ b/src/ProductAssociations/Importer.php @@ -131,7 +131,10 @@ public function getIdentifiersModifiedSince(DateTime $sinceDate): array $products = $this->apiClient->getProductApi()->all(50, ['search' => $searchBuilder->getFilters()]); $identifiers = []; foreach ($products as $product) { - $identifiers[] = $product['identifier']; + Assert::keyExists($product, 'identifier'); + $productIdentifier = (string) $product['identifier']; + Assert::stringNotEmpty($productIdentifier); + $identifiers[] = $productIdentifier; } return $identifiers; diff --git a/tests/Application/config/packages/test/messenger.yaml b/tests/Application/config/packages/test/messenger.yaml index febf1335..561f725d 100644 --- a/tests/Application/config/packages/test/messenger.yaml +++ b/tests/Application/config/packages/test/messenger.yaml @@ -1,4 +1,4 @@ framework: messenger: transports: - main: 'in-memory://' + main: 'sync://' diff --git a/tests/Behat/Context/Messenger/MessengerContext.php b/tests/Behat/Context/Messenger/MessengerContext.php index d451437a..51aa358e 100644 --- a/tests/Behat/Context/Messenger/MessengerContext.php +++ b/tests/Behat/Context/Messenger/MessengerContext.php @@ -7,22 +7,14 @@ use Behat\Behat\Context\Context; use InvalidArgumentException; use Symfony\Component\Messenger\Envelope; -use Symfony\Component\Messenger\Transport\InMemoryTransport; use Throwable; use Webgriffe\SyliusAkeneoPlugin\Message\ItemImport; -use Webgriffe\SyliusAkeneoPlugin\MessageHandler\ItemImportHandler; use Webmozart\Assert\Assert; final class MessengerContext implements Context { private array $failedMessages = []; - public function __construct( - private InMemoryTransport $transport, - private ItemImportHandler $itemImportHandler, - ) { - } - /** * @Then the queue item with identifier :identifier for the :importer importer should not be in the Akeneo queue */ diff --git a/tests/Behat/Context/Ui/Admin/ManagingProductsContext.php b/tests/Behat/Context/Ui/Admin/ManagingProductsContext.php index cf780a1d..e752fce8 100644 --- a/tests/Behat/Context/Ui/Admin/ManagingProductsContext.php +++ b/tests/Behat/Context/Ui/Admin/ManagingProductsContext.php @@ -8,9 +8,13 @@ use Behat\Mink\Element\NodeElement; use Sylius\Behat\NotificationType; use Sylius\Behat\Page\Admin\Product\IndexPageInterface; +use Sylius\Behat\Page\Admin\Product\UpdateSimpleProductPageInterface; use Sylius\Behat\Service\Helper\JavaScriptTestHelperInterface; use Sylius\Behat\Service\NotificationCheckerInterface; use Sylius\Component\Core\Model\ProductInterface; +use Sylius\Component\Core\Repository\ProductRepositoryInterface; +use Sylius\Component\Product\Model\ProductAssociationTypeInterface; +use Webmozart\Assert\Assert; final class ManagingProductsContext implements Context { @@ -20,6 +24,8 @@ public function __construct( private IndexPageInterface $indexPage, private JavaScriptTestHelperInterface $testHelper, private NotificationCheckerInterface $notificationChecker, + private UpdateSimpleProductPageInterface $updateSimpleProductPage, + private ProductRepositoryInterface $productRepository, ) { } @@ -45,4 +51,46 @@ public function iShouldBeNotifiedThatItHasBeenSuccessfullyEnqueued(): void 'Akeneo PIM product import has been successfully scheduled', ); } + + /** + * @Then the product with code :code should have an association :productAssociationType with product :productName + */ + public function theProductShouldHaveAnAssociationWithProducts( + string $code, + ProductAssociationTypeInterface $productAssociationType, + ...$productsNames, + ): void { + $product = $this->productRepository->findOneByCode($code); + $this->updateSimpleProductPage->open(['id' => $product->getId()]); + foreach ($productsNames as $productName) { + Assert::true( + $this->updateSimpleProductPage->hasAssociatedProduct($productName, $productAssociationType), + sprintf( + 'This product should have an association %s with product %s.', + $productAssociationType->getName(), + $productName, + ), + ); + } + } + + /** + * @Then the product with code :code should not have an association :productAssociationType with product :productName + */ + public function theProductShouldNotHaveAnAssociationWithProduct( + string $code, + ProductAssociationTypeInterface $productAssociationType, + string $productName, + ): void { + $product = $this->productRepository->findOneByCode($code); + $this->updateSimpleProductPage->open(['id' => $product->getId()]); + Assert::false( + $this->updateSimpleProductPage->hasAssociatedProduct($productName, $productAssociationType), + sprintf( + 'This product should have an association %s with product %s.', + $productAssociationType->getName(), + $productName, + ), + ); + } } diff --git a/tests/Behat/Resources/services.xml b/tests/Behat/Resources/services.xml index 061af732..0b09cbff 100644 --- a/tests/Behat/Resources/services.xml +++ b/tests/Behat/Resources/services.xml @@ -47,6 +47,8 @@ + + diff --git a/tests/Behat/Resources/suites.yml b/tests/Behat/Resources/suites.yml index fc505897..ab35510a 100644 --- a/tests/Behat/Resources/suites.yml +++ b/tests/Behat/Resources/suites.yml @@ -31,24 +31,28 @@ default: filters: tags: "@importing_product_associations && @cli" - cli_enqueuing_generic_items: + cli_ui_importing_generic_items: contexts: - sylius.behat.context.hook.doctrine_orm - sylius.behat.context.transform.date_time + - sylius.behat.context.transform.product_association_type + - sylius.behat.context.setup.admin_security + - sylius.behat.context.setup.product_association - webgriffe_sylius_akeneo.behat.context.setup.akeneo - webgriffe_sylius_akeneo.behat.context.setup.queue - webgriffe_sylius_akeneo.behat.context.cli.import_command - - webgriffe_sylius_akeneo.behat.context.messenger + - sylius.behat.context.ui.admin.managing_products + - webgriffe_sylius_akeneo.behat.context.ui.admin.managing_products - webgriffe_sylius_akeneo.behat.context.system.filesystem - webgriffe_sylius_akeneo.behat.context.system.datetime filters: - tags: "@enqueuing_generic_items && @cli" + tags: "@importing_generic_items && @cli && @ui" cli_enqueuing_products: contexts: diff --git a/tests/Integration/DataFixtures/ApiClientMock/Product/10597353.json b/tests/Integration/DataFixtures/ApiClientMock/Product/10597353.json new file mode 100644 index 00000000..0b986ea8 --- /dev/null +++ b/tests/Integration/DataFixtures/ApiClientMock/Product/10597353.json @@ -0,0 +1,82 @@ +{ + "identifier": "10597353", + "enabled": true, + "family": "loudspeakers", + "categories": [ + "audio_video_sales", + "loudspeakers", + "nec" + ], + "groups": [], + "parent": null, + "values": { + "picture": [ + { + "locale": null, + "scope": null, + "data": "6/5/8/8/65887ee600d9d66e829a75beedf374533b1ff8bc_10597353_1104.jpg", + "_links": { + "download": { + "href": "http://127.0.0.1:8081/api/rest/v1/media-files/6/5/8/8/65887ee600d9d66e829a75beedf374533b1ff8bc_10597353_1104.jpg/download" + } + } + } + ], + "name": [ + { + "locale": null, + "scope": null, + "data": "NEC SP-4046PV" + } + ], + "description": [ + { + "locale": "de_DE", + "scope": "print", + "data": "Dem edlen Design der Displays angepasst und mit wenigen Handgriffen montiert bzw. demontiert." + }, + { + "locale": "en_US", + "scope": "print", + "data": "Enhance your Large-Screen Display Speakers without breaking your budget with NEC's SP-4046PV." + }, + { + "locale": "fr_FR", + "scope": "print", + "data": "Adapté au design des moniteurs LCD NEC Public Display, montage et démontage faciles." + } + ], + "release_date": [ + { + "locale": null, + "scope": "ecommerce", + "data": "2011-08-07T00:00:00+00:00" + } + ] + }, + "created": "2022-04-14T13:14:05+00:00", + "updated": "2022-04-14T13:14:05+00:00", + "associations": { + "PACK": { + "products": [], + "product_models": [], + "groups": [] + }, + "UPSELL": { + "products": [], + "product_models": [], + "groups": [] + }, + "X_SELL": { + "products": [], + "product_models": [], + "groups": [] + }, + "SUBSTITUTION": { + "products": [], + "product_models": [], + "groups": [] + } + }, + "quantified_associations": {} +} diff --git a/tests/Integration/DataFixtures/ApiClientMock/Product/11164822.json b/tests/Integration/DataFixtures/ApiClientMock/Product/11164822.json new file mode 100644 index 00000000..97b29406 --- /dev/null +++ b/tests/Integration/DataFixtures/ApiClientMock/Product/11164822.json @@ -0,0 +1,84 @@ +{ + "identifier": "11164822", + "enabled": true, + "family": "loudspeakers", + "categories": [ + "audio_video_sales", + "loudspeakers", + "philips" + ], + "groups": [], + "parent": null, + "values": { + "picture": [ + { + "locale": null, + "scope": null, + "data": "7/3/6/b/736bbc43fd1e384f4badbeababd84389b31159f8_11164822_Philips.jpg", + "_links": { + "download": { + "href": "http://127.0.0.1:8081/api/rest/v1/media-files/7/3/6/b/736bbc43fd1e384f4badbeababd84389b31159f8_11164822_Philips.jpg/download" + } + } + } + ], + "name": [ + { + "locale": null, + "scope": null, + "data": "Philips AD7000W" + } + ], + "description": [ + { + "locale": "de_DE", + "scope": "print", + "data": "Eleganz und erstklassige Audio-Qualität, kabellos dank AirPlay\\nBegeistert von Sound\\n\\nDieser kabellose Philips Fidelio-Lautsprecher ermöglicht es Ihnen, Titel direkt von Ihrem iPod/iPhone/iPad und über iTunes auf Ihrem Computer abzuspielen, und das ganze kabellos dank AirPlay. Dieser elegante und kompakte Lautsprecher erfüllt Ihr Zuhause mit großartiger Musik ganz ohne Kabelgewirr.\\n\\nKristallklarer Klang\\n- SoundAvia für eine ausgewogene Klangleistung\\n- 10 W RMS Gesamtausgangsleistung\\n\\nElegant und kompakt\\n- Kompaktes Design mit minimalem Platzbedarf für jeden Lebensstil\\n\\nNoch vielseitiger\\n- Musikübertragung mit kabelloser AirPlay-Technologie\\n- Gleichzeitiges Wiedergeben und Aufladen Ihres iPods/iPhones/iPads\\n- AUX-Eingang für einfaches Anschließen an nahezu jedes elektronische Gerät\\n- Entdecken Sie Musik und weitere Funktionen, und teilen Sie diese über die kostenlose Fidelio\\nApp" + }, + { + "locale": "en_US", + "scope": "print", + "data": "Elegance and superb audio, wirelessly with AirPlay\\nObsessed with sound\\n\\nThis Philips Fidelio wireless speaker gives you the freedom to play songs directly from\\nyour iPod/iPhone/iPad, and from your computer’s iTunes - wirelessly via AirPlay. Elegant\\nand compact, it fills your home with great music, not clutter.\\n\\nCrystal clear sound\\n- SoundAvia for well-balanced sound performance\\n- 10 W RMS total output power\\n\\nElegant and compact\\n- Compact design for any space, any lifestyle\\n\\nAdvanced versatility\\n- Stream music with AirPlay wireless technology\\n- Play and charge your iPod/iPhone/iPad simultaneously\\n- AUX-in for easy connection to almost any electronic device\\n- Discover, share music and more features via free Fidelio app" + }, + { + "locale": "fr_FR", + "scope": "print", + "data": "Élégance et qualité audio exceptionnelle, sans fil avec AirPlay\\nL'obsession du son\\n\\nCette enceinte sans fil Philips Fidelio vous laisse la liberté d'écouter des morceaux directement à partir de votre iPod/iPhone/iPad ou depuis iTunes sur votre ordinateur, tout cela sans fil grâce à AirPlay. Élégante et compacte, elle emplit votre maison d'un son haute qualité, sans l'encombrer inutilement.\\n\\nSon limpide\\n- SoundAvia pour des performances sonores équilibrées\\n- Puissance de sortie totale de 10 W RMS\\n\\nÉlégante et compacte\\n- Design compact pour tous les intérieurs et tous les modes de vie\\n\\nPolyvalence accrue\\n- Technologie de diffusion de la musique sans fil AirPlay\\n- Écoutez et chargez simultanément votre iPod/iPhone/iPad\\n- Entrée AUX, pour une connexion facile à la plupart des périphériques électroniques\\n- Découvrez et partagez de la musique et bien plus via l'appli Fidelio gratuite" + } + ], + "release_date": [ + { + "locale": null, + "scope": "ecommerce", + "data": "2011-10-09T00:00:00+00:00" + } + ] + }, + "created": "2022-04-14T13:14:01+00:00", + "updated": "2022-04-14T13:14:01+00:00", + "associations": { + "PACK": { + "products": [ + "10597353" + ], + "product_models": [], + "groups": [] + }, + "UPSELL": { + "products": [], + "product_models": [], + "groups": [] + }, + "X_SELL": { + "products": [], + "product_models": [], + "groups": [] + }, + "SUBSTITUTION": { + "products": [], + "product_models": [], + "groups": [] + } + }, + "quantified_associations": {} +} diff --git a/tests/Integration/DataFixtures/ApiClientMock/Product/1314976.json b/tests/Integration/DataFixtures/ApiClientMock/Product/1314976.json new file mode 100644 index 00000000..07d2baf9 --- /dev/null +++ b/tests/Integration/DataFixtures/ApiClientMock/Product/1314976.json @@ -0,0 +1,72 @@ +{ + "identifier": "1314976", + "enabled": true, + "family": "loudspeakers", + "categories": [ + "audio_video_sales", + "loudspeakers", + "sony" + ], + "groups": [], + "parent": null, + "values": { + "picture": [ + { + "locale": null, + "scope": null, + "data": "8/e/2/d/8e2d8254e599201a0e6e91d0c512bc37c8780c21_1314976_5566.jpg", + "_links": { + "download": { + "href": "http://127.0.0.1:8081/api/rest/v1/media-files/8/e/2/d/8e2d8254e599201a0e6e91d0c512bc37c8780c21_1314976_5566.jpg/download" + } + } + } + ], + "name": [ + { + "locale": null, + "scope": null, + "data": "Sony SS-SP32FWB" + } + ], + "description": [ + { + "locale": "en_US", + "scope": "print", + "data": "When it comes to creating high-quality Hi-Fi sound in your home, selecting the proper speakers is even more important. Sony makes it easy with an extremely wide range of different speakers. Whether you're listening to a refined string quartet or watching a powerful action-packed movie, Sony's speakers are designed to deliver an intensive acoustic experience that is both powerful and emotional." + } + ], + "release_date": [ + { + "locale": null, + "scope": "ecommerce", + "data": "2007-10-13T00:00:00+00:00" + } + ] + }, + "created": "2022-04-14T13:14:11+00:00", + "updated": "2022-04-14T13:14:11+00:00", + "associations": { + "PACK": { + "products": [], + "product_models": [], + "groups": [] + }, + "UPSELL": { + "products": [], + "product_models": [], + "groups": [] + }, + "X_SELL": { + "products": [], + "product_models": [], + "groups": [] + }, + "SUBSTITUTION": { + "products": [], + "product_models": [], + "groups": [] + } + }, + "quantified_associations": {} +} diff --git a/tests/Integration/DataFixtures/ApiClientMock/media-files/6/5/8/8/65887ee600d9d66e829a75beedf374533b1ff8bc_10597353_1104.jpg b/tests/Integration/DataFixtures/ApiClientMock/media-files/6/5/8/8/65887ee600d9d66e829a75beedf374533b1ff8bc_10597353_1104.jpg new file mode 100644 index 0000000000000000000000000000000000000000..350bc04c3f2007ca60541228db2e1b394e263ff6 GIT binary patch literal 7896 zcmai21yCH_vR*6+B)A3*ZUM45*~J3{SZr}maCg@PcXti8xU;wf4<0-~fUvl`+sl3L z{_nr{=2g9(sXAwBditE{>aY9j^Z4WO7XU{_Qd$y#goFfm|N8Qb6d4r_3FWtfEDit(85I>7?HTIxrzmK@m5`880H|oVPo6%b#si|`(}*fz z5O999{~Vh`NXz9wFD4E(@QbUi={zDLrgO}#9amQA;(ll7eEi$k%YXjGUrYTSQBaYP z(SE<;z(oQeq5NJ64ehtme=8s%<5B}fQIzbDI6r>Q!J~<-9>*8!TsfwNIy}w;UZDKm zIW7t=Kp3!$KmvRcd4=-~6&dB1L94RJ*DGy2LmhRfMRed%AaZROkY4viV-4#HwEV?}E;w!qJmtxZn z9OR3qg_Ma=(G*&%7`(dMj{r3Rg=j~7oLpxoaO;hHUXcB{_ST?LuK_H~2D6V~&|A!V zz(Xfvt-CXcd}l7+ee#F3#q*8P>r-#?7$|Whk(9J`qRkGG}`6~sT7V7ZPXFumy*nIavIUAg= zb-B|iExw`*IVl~cZc$T<;nL$GE+Mif0$fmF1{_OL^qj~uhT^Aq zG|7|?mV+B(fwCFS7z%8i^~e1>Y5(i^zb8lp&Wjp0pK~L%r*)x zZ&FJJ@~)m@H%-gdC*&T2YmM@eJOQZC42VPb$c6z&`6RPk{pLdb!ZshT_cJ%jUAyM^ zI;D;6mhmQGpv3HG_)_6;2ShyW%fL(N0A&-ZLOviHU-VX7r7VO-+6;TJoWrgh9>`mj zOAv>dmuSwRGQ32Ti=}sZJ1nZchy1tq{u#)q$lLP8G>PL2Wzva7bb_%Y^C{>c`+=<-}3d_0hQaQPTOaZ+57M zL+iHd6e)E-QhIM|bj?W0GabyP7ZMUI3SXfsZXk_-+2id5WoQIcA4to;72*>wS{$t( z3b*zU`F#Cv?Eae*3{GKwb-hpX7*$WBb7moZSY2l>FU_sF8(^hPv3}dokz@)~>YB3& z{tK307{AcGXatpQ!_p5qct(m-GYJyM7Il9mTFbL4;+sGpj-Hj z>$5v0l9ZN0M_7v>ZDPu9IZU>W;myyrxJ;YE8D_XbFxS>T~ zN-od-T3Q{@)`WA^;peW2k)|0RKJ$Rk2il&n&C_y0uNo2*oNjh@X^$gXbts zTV@H1i8~IC8p!n7(Xy*dnSb7Jp*=wBc-dWRG)up%5&=v!P53j)o{%@Y?=Z)0jgF=o z<6s&Rt`)GMx9>tveV>jo)AsMIkqh;tTuMdpDuny`m73n0@zcj>Hlf&IEok`fkXb?W zG9Zo*F&UEuc~mN{Q{UcIC>k_8S+pI;dswQ6^Y|9ZVlC^$~>h%Y|*XSA1g@KBl~xQV_jqXaFq8e9%rD?&eVF$D= zYu7+39vE2gUI66#g$!LdgsVZ{S#6!%JA!Xqu%cmuL2*7|Dn4!&@12 z#n@(B&!3qWm(jbM#O{~U)(l0}CHJp~<82C|O{g2QYZ*T~2R8&3`oOclO7jzzt~cOw z;OHg&0^6I>0+O~wOW?we8uDGGagIa> zHvH~Q{^qpB@{!jA3c`*yo}VdMqmyO(lN++N_bw$Km`7l=O}911YYj3J+Wi#F&S~8i zcu+y|RDU)>ZW!ut9(Qr`P_3%u27Q-GaUffop^OaP{MF>^o%c=e)wF6O?clhUkg7;n zllCtGRc*(>eDy~7BLGddl+RWkm`uxuLIRY3mYS@OOuB+gzL5%SRGop_*&CY)~)C07}baYznx>@IjkYo<+ zagBP|QR+BIJ={Mt0S#Dn?G}BIPr~(OxAYNh{+Sev=k~!$s{eR zj}7K4AqGiLxhFZS8e&}iv#{f6?pL>5Fz@Xv11-%n=--aIw~UGe5-j&v*)Ci6SFoHM zT16-&jlGCWebT27Ix$}vvw1Pm#WMeMjMX7ZoflRSw+{3u%0zf4bvA5ew;$eyM__XB z|7R%SJj48OR}i|Xm@lT2yED0&HRUfQd)$0~RCxB4NO1S*c+49-@h2@DgjtGbP1>!lv&eR;(MCjYQI>{ z^&NJ-pYD4SeD>*ociiL0jQU+} ztAG-IgzeJP$*s$>s~(mKTC=;s<1#p85=1;`!O+!@B;)DQy&r#@r;jD1a~Z&3E2tX_ zvE935SRq?T{PapAGiY3n(%OBK?17>q2?Nt4N>yMUVavnWwh;T_ZEI&Y%fW5zVBvaJ z`~?jcS%00x?S(epa<0#9_5q8Kr}F5(dgY&dUtyUU8MZnfJgG`j=f~&Ao-Nr7F-~Cf`{^XHA{_AMrA=I|wXgG1U@~mI2sJa8HW5X=(>s3Z$o0 zfEw(XV8H#VNOCGn_1|o+@qtC48_i*`1r_s?6wz(g>GJ5s5;JelA;tM4K#vvyuQbcJ zoGryq`<1$TDihG#iPy+3qM;E!JXNBgse!%L@v&g?hMY=k za;~?jsmP)kt?7&Oc-6qca)Y==M>DnB+?VX3SBTRfd+M&&?%!Pd65WKH*37Pvr&2 zF1V?U$H_f)g|?0l`sZeABe{Czgpl8~$9vuS{e$U-EtO!w?O(0o-@${F=c}-9H02?t z6XRHy_C(D1wZEqy9-~F$Lq*-`0$kA7w}PWPU0KlgMXNj9esWfg91nr_O%Y}98y#7E zbp!BTPjFQ_+y@$(GK4eV=>^%O-IDv3)a~Y+;Ad;YyGg0oL}t^G;hxgY5xAWS-?uD- zo!B1L6fI&lyFQoefa7bf=poM_BxHH)^W)wh?|pj~=rP6=y<*`M%r^zZ z&5Vd8oXFTLYQ_9&KqT!rgg^DwLUqh8o!*BLE!S6YQ;Q$RCHhQ=KG>hm|DP2K|7>%r z^%0QY%}-AxSL8-aZ_Y#vk8`+@Y^u7Qp1$P^ALq^exgH(Kb(0h_lGh>0MD7*pth0yX zo*A?x1U%ed9vAd#IUFm+xk+;!9ec65?Dxql0c{U zmc~g~p1CS@u(`lm+%rCm>nW-F$bBx1hUcmPmPxI9AS+WqVm|W-*yamQJ4asBYaWSq zMMMXf!;a-ZkcC+Vy)!YBQz0941vdh?(c#z6^{e0CGi)dui(Ch(oI^QP=XTQ zk0C^vd}pIj{jg=YPli*}?YWrq&AqNP&3d=zC7l&p!?T4X1d}|CPM}QyJ!>@*8a({L zZ=$^4rwbdjv{Y($G?a5EAnHbTKBXnw@Ce|{e%*1Gw+R28@V4)QU!|#wtk|J@OP5b z_9nqa5i8|H=49AaQRU6NX`Do9xR!P$`md`>)Eiu_N~qrsiPd;fux;?XFlIqgNL$@o zOkiGv($~_G%KpIGee$3LOTA_e->10EQLCM%q9guccG8S*X>Ie3_(CEh{XF?cx*NJc zq62eMio@;FNELkl7WiZSw$+?#>~N{nmh=3O|En9j!R78z7OBUBpf#4L>mxwLYop=K zABh*~${oj@q8;SRk1>3Ht!>j*DQK+ny|OfAYQ}+kdUTz;)mSbfnfIi6rJo7+OH5Ep@ zbjPC>1D|dAMy;+B8fZ`ix}!B4ihhvH$+eRjaHj+?YR(ZG-D2k1JB7O~^#?Cjg@MPk zg#smplv((A?_MejQQZ=^gM*G7=CXxu6YHDA4)qf?EsprGKfEB=KlD6L(Ti(Y?)V3Q z4F2rnk2R~P+))s9AsDsJ!XfFE7LHK2NETEzXOztIH_~VEd}$ihJ?WH2{$}Hlk-XQ= z?;z8IkATsR{^T@}fRb_)b1x1K5oYC5jNE;T?=406eoJiq__FulGh;ZVA%Q6+QJ$=9 zivUkZEoG=oQsPJW+p~r940R5gsTMXm-F_VhVct~Uud*^)CGxl7b3Ba%I ztS0$=w-JCb;Hq-}at*Gvm4% zNXNhZewXmPq^ascvc&MgX&yJzbQ(##9@={e>HdnXu2scmYos+(2X1Q$7JfQ~)_1mj z54%torgE?$mpwzTZ0mBQ|Ljp@T!i^!REuhWm-q)_^nb-x_g~*Kg;1c zRQUjnj7G*@)y63y{WEpT7Ctui1qsqgDsB$!3W$R$=q6!NHk41iaLL1HmN@WwY?}l9WVL~ykAiilg6O9VXP|wVq(bj zW34svb0_0M_BvBpI-n|(eLs-X!I$s!4CR?I#+%>JzIuQFTomTC}?QFP|$AV-BErq zwTe4SrUpj{mN}>ByGzvclV~0{S z_j@!@#8&SP9o+%i?DFVrqz=dnH(lB0_JCGBob(H4hBe2Cy{jDL^3bPk;@Lw>Zi@i; zx+8zMi;$6fUa}8r&POzVGK#&7xzbysMdMmI9u%A1c60w`4S%-naK=~?Pvv8#vD*Zm zAOH4$R&Z3!SqkG;;oN&IHC<|^!tDl7HiDs(MZh*>UbO9EzcFRc61jqrlG!>xd!TBN zUHEE2#@g2YN-})EguCxylp>Ph$}Wgelcvib`s9LkmtIE%%y%zzOi^M#YVs^}bRcl; z4%(|g-t&ctP6x`n7s=vB)|0yhw#;r zJXxJ##Em!TVJ6whVwlA;Z&yO0%&(BUEsic0k%9D1>H!#4NvLajkZaQ)^PjW;<$DQq z8{X`+PgAWBTQX6?IXW=K3}=>hzeeAdnozteTT585w6M@MqhrIOmR96_74kyc^bsId zD8-PYu2`g2cP&2TrJ$tgJgggsU+b=_k<8Sh;H9z=u65@kIMU@|O7X(7@pmhhnJvAzw0u0g7%Vm&(-MJIRQ_^dAeE^%wog zsxYUDwFB-!p;%pw0mHZAPQkUre8(nEA0-!xCN1=3KadZV%1^x+eMKb&X*5Rdj4h^y z9tLfYxXAUqo$zE)8zoo@Igu>7E(n{OA{dsVl3?~epl3A-2e%vT@oiEbz<^#_LeZ`- z##vM9i$)lqjkEICmz@@ym*^4XO;z(q&l2V5Fi8mcv%Wb=?#qXD5;su-hfcdwdJHMH zH?OroEe+^cIB`3Np_A^tvNW%n<&NpZZiKh6-jzsk5?p~g99D`zNzR*0@-h;N}-(R zd(wex>S1g7smdiL(98%ryk50*_Q3X&m>@cOUMJ&q zuU%)baQ=(ZvZ)2{fmp$m2z4%{Upq_Mi$S%dwaUhIbd`b3vLbf*bpB@NJhQ^h-oOjj zffz7Z@=Nbzm1F6lJxu>2HfCmYIj$!wVU$EMV)!-$G*EwP_IW6Ph#VZ?)^;ioJMuUB Ig&*hs3)yj&YybcN literal 0 HcmV?d00001 diff --git a/tests/Integration/DataFixtures/ApiClientMock/media-files/7/3/6/b/736bbc43fd1e384f4badbeababd84389b31159f8_11164822_Philips.jpg b/tests/Integration/DataFixtures/ApiClientMock/media-files/7/3/6/b/736bbc43fd1e384f4badbeababd84389b31159f8_11164822_Philips.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ff7eb26930334d336900cd4b4dd62d57a69fb116 GIT binary patch literal 8545 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 OEE1t2S$=lCjO=CU8sDFV; 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