From c5ac8aed9b50eb2fcbcf27bd269c8c47c088e6b1 Mon Sep 17 00:00:00 2001 From: Manuele Menozzi Date: Wed, 4 Nov 2020 15:02:23 +0100 Subject: [PATCH 1/5] Refactor behat scenarios and context to be less context specific (#12) --- features/enqueuing.feature | 26 ------ features/enqueuing_generic_items.feature | 33 +++++++ features/enqueuing_products.feature | 33 +++---- .../enqueuing_products_associations.feature | 12 +-- ...ng_product_associations_from_queue.feature | 3 +- .../importing_products_from_queue.feature | 42 ++++----- .../Context/Cli/ConsumeCommandContext.php | 6 +- .../Context/Cli/EnqueueCommandContext.php | 65 +++++++++++--- tests/Behat/Context/Db/QueueContext.php | 87 ++++++------------- tests/Behat/Context/Setup/QueueContext.php | 6 +- .../Context/System/FilesystemContext.php | 9 -- tests/Behat/Resources/suites.yml | 53 +++++++++-- 12 files changed, 198 insertions(+), 177 deletions(-) delete mode 100644 features/enqueuing.feature create mode 100644 features/enqueuing_generic_items.feature diff --git a/features/enqueuing.feature b/features/enqueuing.feature deleted file mode 100644 index 5602538f..00000000 --- a/features/enqueuing.feature +++ /dev/null @@ -1,26 +0,0 @@ -@enqueuing -Feature: Enqueuing items - In order to import data from Akeneo - As a Store Owner - I want to add enqueue items to the Akeneo PIM queue - - Scenario: There is nothing modified since a given date - When I run enqueue command with since date "2020-01-20 01:00:00" - Then the command should have run successfully - And there should be no item in the Akeneo queue - - Scenario: The command cannot be run without since parameter - When I run enqueue command with no since date - Then the command should have thrown exception with message containing 'One of "--since" and "--since-file" paramaters must be specified' - And there should be no item in the Akeneo queue - - Scenario: The command cannot be run with bad since date - When I run enqueue command with since date "bad date" - Then the command should have thrown exception with message containing 'The "since" argument must be a valid date' - And there should be no item in the Akeneo queue - - Scenario: Run the command with not existent since file - When I run enqueue command with since file "last-date" - Then the command should have thrown exception with message containing 'does not exists' - And there should be no item in the Akeneo queue - And there is no file with name "last-date" diff --git a/features/enqueuing_generic_items.feature b/features/enqueuing_generic_items.feature new file mode 100644 index 00000000..c1011453 --- /dev/null +++ b/features/enqueuing_generic_items.feature @@ -0,0 +1,33 @@ +@enqueuing_generic_items +Feature: Enqueuing items + In order to import data from Akeneo + As a Store Owner + I want to add enqueue items to the Akeneo PIM queue + + @cli + Scenario: Enqueueing items when no item is modified since the given date + When I enqueue 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 enqueue 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 enqueue 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 enqueue 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: Avoiding to enqueue two times the same item if it has not been imported yet + Given there is a product "product-1" updated at "2020-01-20 22:23:13" on Akeneo + And there is one item to import with identifier "product-1" for the "Product" importer in the Akeneo queue + When I enqueue items for all importers modified since date "2020-01-20 01:00:00" + Then there should be only one queue item with identifier "product-1" for the "Product" importer in the Akeneo queue diff --git a/features/enqueuing_products.feature b/features/enqueuing_products.feature index bd206504..51d94044 100644 --- a/features/enqueuing_products.feature +++ b/features/enqueuing_products.feature @@ -1,41 +1,34 @@ -@enqueuing +@enqueuing_products Feature: Enqueuing products In order to import my products from Akeneo As a Store Owner I want to add them to the Akeneo PIM queue + @cli Scenario: Enqueuing products modified since a given date Given there is a product "product-1" updated at "2020-01-10 22:23:13" on Akeneo And there is a product "product-2" updated at "2020-01-21 09:54:12" on Akeneo And there is a product "product-3" updated at "2020-01-22 08:15:08" on Akeneo - When I run enqueue command with since date "2020-01-20 01:00:00" - Then the command should have run successfully - And the product "product-1" should not be in the Akeneo queue - And the product "product-2" should be in the Akeneo queue - And the product "product-3" should be in the Akeneo queue + When I enqueue items for all importers modified since date "2020-01-20 01:00:00" + Then the queue item with identifier "product-1" for the "Product" importer should not be in the Akeneo queue + And the queue item with identifier "product-2" for the "Product" importer should be in the Akeneo queue + And the queue item with identifier "product-3" for the "Product" importer should be in the Akeneo queue + @cli Scenario: There are no products modified since datetime read in file Given there is a file with name "last-date" and content "2020-01-20 01:00:00" And current date time is "2020-01-25T12:00:00+01:00" - When I run enqueue command with since file "last-date" - Then the command should have run successfully - And there should be no product in the Akeneo queue + When I enqueue items for all importers modified since date specified from file "last-date" + Then there should be no item in the queue for the "Product" importer And there is a file with name "last-date" that contains "2020-01-25T12:00:00+01:00" + @cli Scenario: Enqueuing products modified since datetime read in file Given there is a product "product-1" updated at "2020-01-10 22:23:13" on Akeneo And there is a product "product-2" updated at "2020-01-21 09:54:12" on Akeneo And there is a file with name "last-date" and content "2020-01-20 01:00:00" And current date time is "2020-01-25T12:00:00+01:00" - When I run enqueue command with since file "last-date" - Then the command should have run successfully - And the product "product-1" should not be in the Akeneo queue - And the product "product-2" should be in the Akeneo queue + When I enqueue items for all importers modified since date specified from file "last-date" + Then the queue item with identifier "product-1" for the "Product" importer should not be in the Akeneo queue + And the queue item with identifier "product-2" for the "Product" importer should be in the Akeneo queue And there is a file with name "last-date" that contains "2020-01-25T12:00:00+01:00" - - # todo: this should be generalized and moved into enqueuing.feature - Scenario: Avoiding to enqueue two times the same product if it has not been imported yet - Given there is a product "product-1" updated at "2020-01-20 22:23:13" on Akeneo - And there is one product to import with identifier "product-1" in the Akeneo queue - When I run enqueue command with since date "2020-01-20 01:00:00" - Then there should be only one product queue item for "product-1" in the Akeneo queue diff --git a/features/enqueuing_products_associations.feature b/features/enqueuing_products_associations.feature index b06a7c6e..f0367f1b 100644 --- a/features/enqueuing_products_associations.feature +++ b/features/enqueuing_products_associations.feature @@ -1,15 +1,15 @@ -@enqueuing +@enqueuing_products_associations Feature: Enqueuing products associations In order to import my products associations from Akeneo As a Store Owner I want to add them to the Akeneo PIM queue + @cli Scenario: Enqueuing products associations for products modified since a given date Given there is a product "product-1" updated at "2020-01-10 22:23:13" on Akeneo And there is a product "product-2" updated at "2020-01-21 09:54:12" on Akeneo And there is a product "product-3" updated at "2020-01-22 08:15:08" on Akeneo - When I run enqueue command with since date "2020-01-20 01:00:00" - Then the command should have run successfully - And the product associations for product "product-1" should not be in the Akeneo queue - And the product associations for product "product-2" should be in the Akeneo queue - And the product associations for product "product-3" should be in the Akeneo queue + When I enqueue items for all importers modified since date "2020-01-20 01:00:00" + Then the queue item with identifier "product-1" for the "ProductAssociations" importer should not be in the Akeneo queue + And the queue item with identifier "product-2" for the "ProductAssociations" importer should be in the Akeneo queue + And the queue item with identifier "product-3" for the "ProductAssociations" importer should be in the Akeneo queue diff --git a/features/importing_product_associations_from_queue.feature b/features/importing_product_associations_from_queue.feature index 0dafcc1a..da8618a1 100644 --- a/features/importing_product_associations_from_queue.feature +++ b/features/importing_product_associations_from_queue.feature @@ -4,6 +4,7 @@ Feature: Importing product associations from queue As a Store Owner I want to import product associations from Akeneo PIM queue + @cli Scenario: Import product associations for already existent products Given the store operates on a single channel And the store has a product "10627329" @@ -11,6 +12,6 @@ Feature: Importing product associations from queue And the store has a product "upsell-product-2" with code "upsell-product-2" And there is one product associations to import with identifier "10627329" in the Akeneo queue And the store has a product association type "Upsell" with a code "UPSELL" - When I run the Consume command + When I import all items in queue Then the product "10627329" should be associated to product "upsell-product-1" for association with code "UPSELL" And the product "10627329" should be associated to product "upsell-product-2" for association with code "UPSELL" diff --git a/features/importing_products_from_queue.feature b/features/importing_products_from_queue.feature index 88ed5929..932d0168 100644 --- a/features/importing_products_from_queue.feature +++ b/features/importing_products_from_queue.feature @@ -4,47 +4,35 @@ Feature: Importing products from queue As a Store Owner I want to import products from Akeneo PIM queue + @cli Scenario: Importing single product model and its variants from queue Given the store operates on a single channel And the store is also available in "it_IT" - And there is one product to import with identifier "braided-hat-m" in the Akeneo queue - And there is one product to import with identifier "Braided-hat-l" in the Akeneo queue - When I import products from queue + And there is one item to import with identifier "braided-hat-m" for the "Product" importer in the Akeneo queue + And there is one item to import with identifier "Braided-hat-l" for the "Product" importer in the Akeneo queue + When I import all items in queue Then the product "model-braided-hat" should exists with the right data And the product variant "braided-hat-m" of product "model-braided-hat" should exists with the right data And the product variant "Braided-hat-l" of product "model-braided-hat" should exists with the right data + @cli Scenario: Keeping the queue item as not imported while importing non existent product model from queue Given the store operates on a single channel And the store is also available in "it_IT" - And there is one product to import with identifier "NOT_EXISTS" in the Akeneo queue - When I import products from queue + And there is one item to import with identifier "NOT_EXISTS" for the "Product" importer in the Akeneo queue + When I import all items in queue Then the product "NOT_EXISTS" should not exists - And the queue item for product with identifier "NOT_EXISTS" has not been marked as imported - And the queue item for product with identifier "NOT_EXISTS" has an error message + And the queue item with identifier "NOT_EXISTS" for the "Product" importer has not been marked as imported + And the queue item with identifier "NOT_EXISTS" for the "Product" importer has an error message + @cli Scenario: Going on with subsequent product imports when any fail Given the store operates on a single channel And the store is also available in "it_IT" - And there is one product to import with identifier "NOT_EXISTS" in the Akeneo queue - And there is one product to import with identifier "braided-hat-m" in the Akeneo queue - When I import products from queue + And there is one item to import with identifier "NOT_EXISTS" for the "Product" importer in the Akeneo queue + And there is one item to import with identifier "braided-hat-m" for the "Product" importer in the Akeneo queue + When I import all items in queue Then the product "NOT_EXISTS" should not exists And the product variant "braided-hat-m" of product "model-braided-hat" should exists with the right data - And the queue item for product with identifier "braided-hat-m" has been marked as imported - - # todo: this scenario seems to cover too many cases, it should be split in multiple scenarios - @todo - Scenario: Importing product with missing mandatory data should not mark them as imported and going on importing subsequent products - Given the store operates on a single channel - And the store is also available in "it_IT" - And there is one product to import with identifier "no-name-product" in the Akeneo queue - And there is one product to import with identifier "braided-hat-m" in the Akeneo queue - When I import products from queue - Then there should be only one product queue item for "no-name-product" in the Akeneo queue - And there should be only one product queue item for "braided-hat-m" in the Akeneo queue - And the queue item for product with identifier "no-name-product" has not been marked as imported - And the queue item for product with identifier "no-name-product" has an error message containing "NOT NULL constraint failed: sylius_product_translation.name" - And the queue item for product with identifier "braided-hat-m" has been marked as imported - And the product "no-name-product" should not exists - And the product variant "braided-hat-m" of product "model-braided-hat" should exists with the right data + And the queue item with identifier "braided-hat-m" for the "Product" importer has been marked as imported + And the queue item with identifier "NOT_EXISTS" for the "Product" importer has not been marked as imported diff --git a/tests/Behat/Context/Cli/ConsumeCommandContext.php b/tests/Behat/Context/Cli/ConsumeCommandContext.php index ae076cb2..5926574b 100644 --- a/tests/Behat/Context/Cli/ConsumeCommandContext.php +++ b/tests/Behat/Context/Cli/ConsumeCommandContext.php @@ -27,11 +27,9 @@ public function __construct( } /** - * @todo replace "I import products from queue" with generic "I run the Consume command" - * @When /^I import products from queue$/ - * @When /^I run the Consume command$/ + * @When /^I import all items in queue$/ */ - public function iImportProductsFromQueue() + public function iImportAllItemsInQueue() { $application = new Application($this->kernel); $application->add($this->consumeCommand); diff --git a/tests/Behat/Context/Cli/EnqueueCommandContext.php b/tests/Behat/Context/Cli/EnqueueCommandContext.php index 16a8ee80..7ab97c14 100644 --- a/tests/Behat/Context/Cli/EnqueueCommandContext.php +++ b/tests/Behat/Context/Cli/EnqueueCommandContext.php @@ -35,7 +35,7 @@ public function __construct( } /** - * @When /^I run enqueue command with since date "([^"]+)"$/ + * @When /^I enqueue items for all importers modified since date "([^"]+)"$/ */ public function iRunEnqueueCommandWithSinceDate($date) { @@ -49,7 +49,7 @@ public function iRunEnqueueCommandWithSinceDate($date) } /** - * @When I run enqueue command with no since date + * @When I enqueue items for all importers with no since date */ public function iRunEnqueueCommandWithNoSinceDate() { @@ -63,33 +63,74 @@ public function iRunEnqueueCommandWithNoSinceDate() } /** - * @Then /^the command should have run successfully$/ + * @Then /^I should be notified that a since date is required$/ */ - public function theCommandShouldHaveRunSuccessfully() + public function theCommandShouldHaveThrownExceptionWithMessageContaining() { - if ($this->sharedStorage->has('command_exception')) { - throw $this->sharedStorage->get('command_exception'); + /** @var \Throwable $throwable */ + $throwable = $this->sharedStorage->get('command_exception'); + Assert::isInstanceOf($throwable, \Throwable::class); + Assert::contains($throwable->getMessage(), 'One of "--since" and "--since-file" paramaters must be specified'); + } + + /** + * @When /^I enqueue items for all importers with invalid since date$/ + */ + public function iEnqueueItemsForAllImportersWithInvalidSinceDate() + { + $commandTester = $this->getCommandTester(); + + try { + $commandTester->execute(['command' => 'webgriffe:akeneo:enqueue', '--since' => 'bad date']); + } catch (\Throwable $t) { + $this->sharedStorage->set('command_exception', $t); + } + } + + /** + * @Then /^I should be notified that the since date must be a valid date$/ + */ + public function iShouldBeNotifiedThatTheSinceDateMustBeAValidDate() + { + /** @var \Throwable $throwable */ + $throwable = $this->sharedStorage->get('command_exception'); + Assert::isInstanceOf($throwable, \Throwable::class); + Assert::contains($throwable->getMessage(), 'The "since" argument must be a valid date'); + } + + /** + * @When /^I enqueue items with since date specified from a not existent file$/ + */ + public function iEnqueueItemsWithSinceDateSpecifiedFromANotExistentFile() + { + $commandTester = $this->getCommandTester(); + $filepath = vfsStream::url('root/not-existent-file.txt'); + + try { + $commandTester->execute(['command' => 'webgriffe:akeneo:enqueue', '--since-file' => $filepath]); + } catch (\Throwable $t) { + $this->sharedStorage->set('command_exception', $t); } } /** - * @Then /^the command should have thrown exception with message containing \'([^\']*)\'$/ + * @Then /^I should be notified that the since date file does not exists$/ */ - public function theCommandShouldHaveThrownExceptionWithMessageContaining($message) + public function iShouldBeNotifiedThatTheSinceDateFileDoesNotExists() { /** @var \Throwable $throwable */ $throwable = $this->sharedStorage->get('command_exception'); Assert::isInstanceOf($throwable, \Throwable::class); - Assert::contains($throwable->getMessage(), $message); + Assert::contains($throwable->getMessage(), 'does not exists'); } /** - * @When /^I run enqueue command with since file "([^"]+)"$/ + * @When /^I enqueue items for all importers modified since date specified from file "([^"]+)"$/ */ - public function iRunEnqueueCommandWithSinceFile($filename) + public function iEnqueueItemsWithSinceDateSpecifiedFromFile(string $file) { $commandTester = $this->getCommandTester(); - $filepath = vfsStream::url('root/' . $filename); + $filepath = vfsStream::url('root/' . $file); try { $commandTester->execute(['command' => 'webgriffe:akeneo:enqueue', '--since-file' => $filepath]); diff --git a/tests/Behat/Context/Db/QueueContext.php b/tests/Behat/Context/Db/QueueContext.php index 14d5f105..006813c9 100644 --- a/tests/Behat/Context/Db/QueueContext.php +++ b/tests/Behat/Context/Db/QueueContext.php @@ -21,105 +21,70 @@ public function __construct( } /** - * @Given /^the queue item for product with identifier "([^"]*)" has been marked as imported$/ + * @Given /^the queue item with identifier "([^"]*)" for the "([^"]*)" importer has been marked as imported$/ */ - public function theQueueItemForProductWithIdentifierHasBeenMarkedAsImported(string $identifier) + public function theQueueItemForProductWithIdentifierHasBeenMarkedAsImported(string $identifier, string $importer) { - $queueItem = $this->getQueueItemByProductIdentifier($identifier); + $queueItem = $this->getQueueItemByImporterAndIdentifier($importer, $identifier); Assert::notNull($queueItem->getImportedAt()); } /** - * @Given /^the queue item for product with identifier "([^"]*)" has not been marked as imported$/ + * @Given /^the queue item with identifier "([^"]*)" for the "([^"]*)" importer has not been marked as imported$/ */ - public function theQueueItemForProductWithIdentifierHasNotBeenMarkedAsImported(string $identifier) + public function theQueueItemForProductWithIdentifierHasNotBeenMarkedAsImported(string $identifier, string $importer) { - $queueItem = $this->getQueueItemByProductIdentifier($identifier); + $queueItem = $this->getQueueItemByImporterAndIdentifier($importer, $identifier); Assert::null($queueItem->getImportedAt()); } /** - * @Given /^the queue item for product with identifier "([^"]*)" has an error message$/ + * @Given /^the queue item with identifier "([^"]*)" for the "([^"]*)" importer has an error message$/ */ - public function theQueueItemHasAnErrorMessage(string $identifier) + public function theQueueItemHasAnErrorMessage(string $identifier, string $importer) { - $queueItem = $this->getQueueItemByProductIdentifier($identifier); + $queueItem = $this->getQueueItemByImporterAndIdentifier($importer, $identifier); Assert::notNull($queueItem->getErrorMessage()); } /** - * @Given /^the queue item for product with identifier "([^"]*)" has an error message containing "([^"]*)"$/ + * @Given /^the queue item with identifier "([^"]*)" for the "([^"]*)" importer has an error message containing "([^"]*)"$/ */ - public function theQueueItemHasAnErrorMessageContaining(string $identifier, string $message) + public function theQueueItemHasAnErrorMessageContaining(string $identifier, string $importer, string $message) { - $queueItem = $this->getQueueItemByProductIdentifier($identifier); + $queueItem = $this->getQueueItemByImporterAndIdentifier($importer, $identifier); Assert::contains($queueItem->getErrorMessage(), $message); } /** - * @Then /^the product "([^"]*)" should not be in the Akeneo queue$/ + * @Then /^the queue item with identifier "([^"]*)" for the "([^"]*)" importer should not be in the Akeneo queue$/ */ - public function theProductShouldNotBeInTheAkeneoQueue(string $identifier) + public function theProductShouldNotBeInTheAkeneoQueue(string $identifier, string $importer) { Assert::null( - $this->queueItemRepository->findOneBy( - ['akeneoEntity' => 'Product', 'akeneoIdentifier' => $identifier] - ) - ); - } - - /** - * @Then /^the product associations for product "([^"]*)" should not be in the Akeneo queue$/ - */ - public function theProductAssociationsForProductShouldNotBeInTheAkeneoQueue(string $identifier) - { - Assert::null( - $this->queueItemRepository->findOneBy( - ['akeneoEntity' => 'ProductAssociations', 'akeneoIdentifier' => $identifier] - ) - ); - } - - /** - * @Then /^the product "([^"]*)" should be in the Akeneo queue$/ - */ - public function theProductShouldBeInTheAkeneoQueue(string $identifier) - { - Assert::isInstanceOf( - $this->queueItemRepository->findOneBy( - ['akeneoEntity' => 'Product', 'akeneoIdentifier' => $identifier] - ), - QueueItemInterface::class + $this->queueItemRepository->findOneBy(['akeneoEntity' => $importer, 'akeneoIdentifier' => $identifier]) ); } /** - * @Then /^the product associations for product "([^"]*)" should be in the Akeneo queue$/ + * @Then /^the queue item with identifier "([^"]*)" for the "([^"]*)" importer should be in the Akeneo queue$/ */ - public function theProductAssociationsForProductShouldBeInTheAkeneoQueue(string $identifier) + public function theProductShouldBeInTheAkeneoQueue(string $identifier, string $importer) { Assert::isInstanceOf( $this->queueItemRepository->findOneBy( - ['akeneoEntity' => 'ProductAssociations', 'akeneoIdentifier' => $identifier] + ['akeneoEntity' => $importer, 'akeneoIdentifier' => $identifier] ), QueueItemInterface::class ); } /** - * @Then /^there should be no product in the Akeneo queue$/ - */ - public function thereShouldBeNoProductInTheAkeneoQueue() - { - Assert::isEmpty($this->queueItemRepository->findBy(['akeneoEntity' => 'Product'])); - } - - /** - * @Then /^there should be no product associations in the Akeneo queue$/ + * @Then /^there should be no item in the queue for the "([^"]*)" importer/ */ - public function thereShouldBeNoProductAssociationsInTheAkeneoQueue() + public function thereShouldBeNoProductInTheAkeneoQueue(string $importer) { - Assert::isEmpty($this->queueItemRepository->findBy(['akeneoEntity' => 'ProductAssociations'])); + Assert::isEmpty($this->queueItemRepository->findBy(['akeneoEntity' => $importer])); } /** @@ -131,20 +96,20 @@ public function thereShouldBeNoItemInTheAkeneoQueue() } /** - * @Then /^there should be only one product queue item for "([^"]*)" in the Akeneo queue$/ + * @Then /^there should be only one queue item with identifier "([^"]*)" for the "([^"]*)" importer in the Akeneo queue$/ */ - public function thereShouldBeOnlyOneProductQueueItemForInTheAkeneoQueue(string $identifier) + public function thereShouldBeOnlyOneProductQueueItemForInTheAkeneoQueue(string $identifier, string $importer) { $items = $this->queueItemRepository->findBy( - ['akeneoEntity' => 'Product', 'akeneoIdentifier' => $identifier] + ['akeneoEntity' => $importer, 'akeneoIdentifier' => $identifier] ); Assert::count($items, 1); } - private function getQueueItemByProductIdentifier(string $identifier): QueueItemInterface + private function getQueueItemByImporterAndIdentifier(string $importer, string $identifier): QueueItemInterface { /** @var QueueItemInterface $item */ - $item = $this->queueItemRepository->findOneBy(['akeneoEntity' => 'Product', 'akeneoIdentifier' => $identifier]); + $item = $this->queueItemRepository->findOneBy(['akeneoEntity' => $importer, 'akeneoIdentifier' => $identifier]); Assert::isInstanceOf($item, QueueItemInterface::class); return $item; diff --git a/tests/Behat/Context/Setup/QueueContext.php b/tests/Behat/Context/Setup/QueueContext.php index 8f5a4921..10258e1f 100644 --- a/tests/Behat/Context/Setup/QueueContext.php +++ b/tests/Behat/Context/Setup/QueueContext.php @@ -26,13 +26,13 @@ public function __construct( } /** - * @Given /^there is one product to import with identifier "([^"]*)" in the Akeneo queue$/ + * @Given /^there is one item to import with identifier "([^"]*)" for the "([^"]*)" importer in the Akeneo queue$/ */ - public function thereIsOneProductToImportWithIdentifierInTheAkeneoQueue(string $identifier) + public function thereIsOneProductToImportWithIdentifierInTheAkeneoQueue(string $identifier, string $importer) { /** @var QueueItemInterface $queueItem */ $queueItem = $this->queueItemFactory->createNew(); - $queueItem->setAkeneoEntity('Product'); + $queueItem->setAkeneoEntity($importer); $queueItem->setAkeneoIdentifier($identifier); $queueItem->setCreatedAt(new \DateTime()); $this->queueItemRepository->add($queueItem); diff --git a/tests/Behat/Context/System/FilesystemContext.php b/tests/Behat/Context/System/FilesystemContext.php index e21093e7..915388dc 100644 --- a/tests/Behat/Context/System/FilesystemContext.php +++ b/tests/Behat/Context/System/FilesystemContext.php @@ -39,13 +39,4 @@ public function thereIsAFileWithNameThatContains($filename, $content) $actualFileContent = file_get_contents($file); Assert::same($actualFileContent, $content); } - - /** - * @Given /^there is no file with name "([^"]+)"$/ - */ - public function thereIsNoFileWithName($filename) - { - $file = vfsStream::url('root/' . $filename); - Assert::false(file_exists($file)); - } } diff --git a/tests/Behat/Resources/suites.yml b/tests/Behat/Resources/suites.yml index 78f1963a..8202d2b7 100644 --- a/tests/Behat/Resources/suites.yml +++ b/tests/Behat/Resources/suites.yml @@ -1,8 +1,6 @@ -# Put your Behat suites definitions here - default: suites: - importing_products: + cli_importing_products: contexts: - sylius.behat.context.hook.doctrine_orm @@ -17,9 +15,9 @@ default: - webgriffe_sylius_akeneo.context.db.queue filters: - tags: "@importing_products" + tags: "@importing_products && @cli" - importing_product_associations: + cli_importing_product_associations: contexts: - sylius.behat.context.hook.doctrine_orm @@ -34,9 +32,47 @@ default: - webgriffe_sylius_akeneo.context.db.queue filters: - tags: "@importing_product_associations" + tags: "@importing_product_associations && @cli" + + cli_enqueuing_generic_items: + contexts: + - sylius.behat.context.hook.doctrine_orm + + - sylius.behat.context.transform.date_time + + - webgriffe_sylius_akeneo.context.setup.akeneo + - webgriffe_sylius_akeneo.context.setup.queue + + - webgriffe_sylius_akeneo.context.cli.enqueue_command + + - webgriffe_sylius_akeneo.context.db.queue + + - webgriffe_sylius_akeneo.context.system.filesystem + - webgriffe_sylius_akeneo.context.system.datetime + + filters: + tags: "@enqueuing_generic_items && @cli" + + cli_enqueuing_products: + contexts: + - sylius.behat.context.hook.doctrine_orm + + - sylius.behat.context.transform.date_time + + - webgriffe_sylius_akeneo.context.setup.akeneo + - webgriffe_sylius_akeneo.context.setup.queue + + - webgriffe_sylius_akeneo.context.cli.enqueue_command + + - webgriffe_sylius_akeneo.context.db.queue + + - webgriffe_sylius_akeneo.context.system.filesystem + - webgriffe_sylius_akeneo.context.system.datetime + + filters: + tags: "@enqueuing_products && @cli" - enqueuing: + cli_enqueuing_products_associations: contexts: - sylius.behat.context.hook.doctrine_orm @@ -53,4 +89,5 @@ default: - webgriffe_sylius_akeneo.context.system.datetime filters: - tags: "@enqueuing" + tags: "@enqueuing_products_associations && @cli" + From e0da0eb461bc74e2bd66bff45f0124fd994dad57 Mon Sep 17 00:00:00 2001 From: Manuele Menozzi Date: Sat, 7 Nov 2020 17:28:55 +0100 Subject: [PATCH 2/5] Allow to enqueue items regardless the modified since date (#12) --- features/enqueuing_generic_items.feature | 7 +++++++ src/Command/EnqueueCommand.php | 15 +++++++++++++-- tests/Behat/Context/Cli/EnqueueCommandContext.php | 15 ++++++++++++++- tests/Behat/Context/Db/QueueContext.php | 9 +++++++++ tests/Behat/Context/Setup/AkeneoContext.php | 10 ++++++++++ 5 files changed, 53 insertions(+), 3 deletions(-) diff --git a/features/enqueuing_generic_items.feature b/features/enqueuing_generic_items.feature index c1011453..53324213 100644 --- a/features/enqueuing_generic_items.feature +++ b/features/enqueuing_generic_items.feature @@ -31,3 +31,10 @@ Feature: Enqueuing items And there is one item to import with identifier "product-1" for the "Product" importer in the Akeneo queue When I enqueue items for all importers modified since date "2020-01-20 01:00:00" Then there should be only one queue item with identifier "product-1" for the "Product" importer in the Akeneo queue + + @cli + Scenario: Enqueuing all items regardless last modified date + Given there are 3 products on Akeneo + When I enqueue 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 diff --git a/src/Command/EnqueueCommand.php b/src/Command/EnqueueCommand.php index 30509979..526a048e 100644 --- a/src/Command/EnqueueCommand.php +++ b/src/Command/EnqueueCommand.php @@ -21,6 +21,8 @@ final class EnqueueCommand extends Command public const SINCE_FILE_OPTION_NAME = 'since-file'; + private const ALL_OPTION_NAME = 'all'; + protected static $defaultName = 'webgriffe:akeneo:enqueue'; /** @var QueueItemRepositoryInterface */ @@ -65,6 +67,12 @@ protected function configure(): void InputOption::VALUE_REQUIRED, 'Relative or absolute path to a file containing a datetime' ); + $this->addOption( + self::ALL_OPTION_NAME, + 'a', + InputOption::VALUE_NONE, + 'Enqueue all identifiers regardless their last modified date.' + ); } protected function execute(InputInterface $input, OutputInterface $output): int @@ -84,12 +92,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int Assert::string($sinceFilePath); /** @var string $sinceFilePath */ $sinceDate = $this->getSinceDateByFile($sinceFilePath); + } elseif ($input->getOption(self::ALL_OPTION_NAME) === true) { + $sinceDate = (new \DateTime())->setTimestamp(0); } else { throw new \InvalidArgumentException( sprintf( - 'One of "--%s" and "--%s" paramaters must be specified', + 'One of "--%s", "--%s" or "--%s" option must be specified', self::SINCE_OPTION_NAME, - self::SINCE_FILE_OPTION_NAME + self::SINCE_FILE_OPTION_NAME, + self::ALL_OPTION_NAME ) ); } diff --git a/tests/Behat/Context/Cli/EnqueueCommandContext.php b/tests/Behat/Context/Cli/EnqueueCommandContext.php index 7ab97c14..c4f41247 100644 --- a/tests/Behat/Context/Cli/EnqueueCommandContext.php +++ b/tests/Behat/Context/Cli/EnqueueCommandContext.php @@ -70,7 +70,10 @@ public function theCommandShouldHaveThrownExceptionWithMessageContaining() /** @var \Throwable $throwable */ $throwable = $this->sharedStorage->get('command_exception'); Assert::isInstanceOf($throwable, \Throwable::class); - Assert::contains($throwable->getMessage(), 'One of "--since" and "--since-file" paramaters must be specified'); + Assert::contains( + $throwable->getMessage(), + 'One of "--since", "--since-file" or "--all" option must be specified' + ); } /** @@ -139,6 +142,16 @@ public function iEnqueueItemsWithSinceDateSpecifiedFromFile(string $file) } } + /** + * @When /^I enqueue all items for all importers$/ + */ + public function iEnqueueAllItemsForAllImporters() + { + $commandTester = $this->getCommandTester(); + + $commandTester->execute(['command' => 'webgriffe:akeneo:enqueue', '--all' => true]); + } + private function getCommandTester(): CommandTester { $application = new Application($this->kernel); diff --git a/tests/Behat/Context/Db/QueueContext.php b/tests/Behat/Context/Db/QueueContext.php index 006813c9..8f0568ec 100644 --- a/tests/Behat/Context/Db/QueueContext.php +++ b/tests/Behat/Context/Db/QueueContext.php @@ -106,6 +106,15 @@ public function thereShouldBeOnlyOneProductQueueItemForInTheAkeneoQueue(string $ Assert::count($items, 1); } + /** + * @Then /^there should be (\d+) items for the "([^"]*)" importer in the Akeneo queue$/ + */ + public function thereShouldBeItemsForTheImporterInTheAkeneoQueue(int $count, string $importer) + { + $items = $this->queueItemRepository->findBy(['akeneoEntity' => $importer]); + Assert::count($items, $count); + } + private function getQueueItemByImporterAndIdentifier(string $importer, string $identifier): QueueItemInterface { /** @var QueueItemInterface $item */ diff --git a/tests/Behat/Context/Setup/AkeneoContext.php b/tests/Behat/Context/Setup/AkeneoContext.php index 155b34b9..a9d2b17d 100644 --- a/tests/Behat/Context/Setup/AkeneoContext.php +++ b/tests/Behat/Context/Setup/AkeneoContext.php @@ -27,4 +27,14 @@ public function thereIsAProductUpdatedAtOnAkeneo(string $identifier, \DateTime $ Assert::isInstanceOf($this->apiClient, ApiClientMock::class); $this->apiClient->addProductUpdatedAt($identifier, $date); } + + /** + * @Given /^there are (\d+) products on Akeneo$/ + */ + public function thereAreProductsOnAkeneo(int $count) + { + for ($i = 1; $i <= $count; ++$i) { + $this->apiClient->addProductUpdatedAt('product-' . $i, new \DateTime()); + } + } } From eb23ad37974ca61f6ed00bb1c9c19efe0baa8d7a Mon Sep 17 00:00:00 2001 From: Manuele Menozzi Date: Sat, 7 Nov 2020 17:43:15 +0100 Subject: [PATCH 3/5] Allow to enqueue items only for specific importers (#12) --- features/enqueuing_generic_items.feature | 7 +++++++ src/Command/EnqueueCommand.php | 14 ++++++++++++++ tests/Behat/Context/Cli/EnqueueCommandContext.php | 12 ++++++++++++ tests/Behat/Context/Db/QueueContext.php | 9 +++++++++ 4 files changed, 42 insertions(+) diff --git a/features/enqueuing_generic_items.feature b/features/enqueuing_generic_items.feature index 53324213..9652ee11 100644 --- a/features/enqueuing_generic_items.feature +++ b/features/enqueuing_generic_items.feature @@ -38,3 +38,10 @@ Feature: Enqueuing items When I enqueue 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 enqueue 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 diff --git a/src/Command/EnqueueCommand.php b/src/Command/EnqueueCommand.php index 526a048e..4ba4c42a 100644 --- a/src/Command/EnqueueCommand.php +++ b/src/Command/EnqueueCommand.php @@ -23,6 +23,8 @@ final class EnqueueCommand extends Command private const ALL_OPTION_NAME = 'all'; + private const IMPORTER_OPTION_NAME = 'importer'; + protected static $defaultName = 'webgriffe:akeneo:enqueue'; /** @var QueueItemRepositoryInterface */ @@ -73,6 +75,12 @@ protected function configure(): void InputOption::VALUE_NONE, 'Enqueue all identifiers regardless their last modified date.' ); + $this->addOption( + self::IMPORTER_OPTION_NAME, + 'i', + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'Enqueue items only for specified importers' + ); } protected function execute(InputInterface $input, OutputInterface $output): int @@ -105,8 +113,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int ); } + $importers = $input->getOption(self::IMPORTER_OPTION_NAME); + Assert::isArray($importers); + $runDate = $this->dateTimeBuilder->build(); foreach ($this->importerRegistry->all() as $importer) { + if (count($importers) > 0 && !in_array($importer->getAkeneoEntity(), $importers, true)) { + continue; + } $identifiers = $importer->getIdentifiersModifiedSince($sinceDate); if (count($identifiers) === 0) { $output->writeln( diff --git a/tests/Behat/Context/Cli/EnqueueCommandContext.php b/tests/Behat/Context/Cli/EnqueueCommandContext.php index c4f41247..42dc706b 100644 --- a/tests/Behat/Context/Cli/EnqueueCommandContext.php +++ b/tests/Behat/Context/Cli/EnqueueCommandContext.php @@ -152,6 +152,18 @@ public function iEnqueueAllItemsForAllImporters() $commandTester->execute(['command' => 'webgriffe:akeneo:enqueue', '--all' => true]); } + /** + * @When /^I enqueue all items for the "([^"]+)" importer$/ + */ + public function iEnqueueItemsModifiedSinceDateForTheImporter(string $importer) + { + $commandTester = $this->getCommandTester(); + + $commandTester->execute( + ['command' => 'webgriffe:akeneo:enqueue', '--all' => true, '--importer' => [$importer]] + ); + } + private function getCommandTester(): CommandTester { $application = new Application($this->kernel); diff --git a/tests/Behat/Context/Db/QueueContext.php b/tests/Behat/Context/Db/QueueContext.php index 8f0568ec..80d76d84 100644 --- a/tests/Behat/Context/Db/QueueContext.php +++ b/tests/Behat/Context/Db/QueueContext.php @@ -115,6 +115,15 @@ public function thereShouldBeItemsForTheImporterInTheAkeneoQueue(int $count, str Assert::count($items, $count); } + /** + * @Then /^there should be items for the "([^"]*)" importer only in the Akeneo queue$/ + */ + public function thereShouldBeItemsForTheImporterOnlyInTheAkeneoQueue(string $importer) + { + $importerItems = $this->queueItemRepository->findBy(['akeneoEntity' => $importer]); + Assert::count($this->queueItemRepository->findAll(), count($importerItems)); + } + private function getQueueItemByImporterAndIdentifier(string $importer, string $identifier): QueueItemInterface { /** @var QueueItemInterface $item */ From 9be4cd4e5f5576657f8faf891abc4f52f262c5bb Mon Sep 17 00:00:00 2001 From: Manuele Menozzi Date: Sat, 7 Nov 2020 21:29:58 +0100 Subject: [PATCH 4/5] Validate importers used in the enqueue command (#12) --- features/enqueuing_generic_items.feature | 5 ++ src/Command/EnqueueCommand.php | 46 ++++++++++++++++--- .../Context/Cli/EnqueueCommandContext.php | 27 +++++++++++ 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/features/enqueuing_generic_items.feature b/features/enqueuing_generic_items.feature index 9652ee11..dc2fe730 100644 --- a/features/enqueuing_generic_items.feature +++ b/features/enqueuing_generic_items.feature @@ -45,3 +45,8 @@ Feature: Enqueuing items When I enqueue 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 enqueue all items for a not existent importer + Then I should be notified that the importer does not exists diff --git a/src/Command/EnqueueCommand.php b/src/Command/EnqueueCommand.php index 4ba4c42a..dbd90174 100644 --- a/src/Command/EnqueueCommand.php +++ b/src/Command/EnqueueCommand.php @@ -11,6 +11,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Webgriffe\SyliusAkeneoPlugin\DateTimeBuilderInterface; use Webgriffe\SyliusAkeneoPlugin\Entity\QueueItemInterface; +use Webgriffe\SyliusAkeneoPlugin\ImporterInterface; use Webgriffe\SyliusAkeneoPlugin\ImporterRegistryInterface; use Webgriffe\SyliusAkeneoPlugin\Repository\QueueItemRepositoryInterface; use Webmozart\Assert\Assert; @@ -113,14 +114,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int ); } - $importers = $input->getOption(self::IMPORTER_OPTION_NAME); - Assert::isArray($importers); - $runDate = $this->dateTimeBuilder->build(); - foreach ($this->importerRegistry->all() as $importer) { - if (count($importers) > 0 && !in_array($importer->getAkeneoEntity(), $importers, true)) { - continue; - } + foreach ($this->getImporters($input) as $importer) { $identifiers = $importer->getIdentifiersModifiedSince($sinceDate); if (count($identifiers) === 0) { $output->writeln( @@ -205,4 +200,41 @@ private function isEntityAlreadyQueuedToImport(string $akeneoEntity, string $ake return false; } + + /** + * @return ImporterInterface[] + */ + private function getImporters(InputInterface $input): array + { + $allImporters = $this->importerRegistry->all(); + if (count($allImporters) === 0) { + throw new \RuntimeException('There are no importers in registry.'); + } + $importersCodes = array_map( + static function (ImporterInterface $importer) { + return $importer->getAkeneoEntity(); + }, + $allImporters + ); + + $importersToUse = $input->getOption(self::IMPORTER_OPTION_NAME); + Assert::isArray($importersToUse); + + if (count($importersToUse) === 0) { + return $allImporters; + } + + $allImporters = array_combine($importersCodes, $allImporters); + Assert::isArray($allImporters); + + $importers = []; + foreach ($importersToUse as $importerToUse) { + if (!array_key_exists($importerToUse, $allImporters)) { + throw new \InvalidArgumentException(sprintf('Importer "%s" does not exists.', $importerToUse)); + } + $importers[] = $allImporters[$importerToUse]; + } + + return $importers; + } } diff --git a/tests/Behat/Context/Cli/EnqueueCommandContext.php b/tests/Behat/Context/Cli/EnqueueCommandContext.php index 42dc706b..63c51a07 100644 --- a/tests/Behat/Context/Cli/EnqueueCommandContext.php +++ b/tests/Behat/Context/Cli/EnqueueCommandContext.php @@ -164,6 +164,33 @@ public function iEnqueueItemsModifiedSinceDateForTheImporter(string $importer) ); } + /** + * @When /^I enqueue all items for a not existent importer$/ + */ + public function iEnqueueAllItemsForANotExistentImporter() + { + $commandTester = $this->getCommandTester(); + + try { + $commandTester->execute( + ['command' => 'webgriffe:akeneo:enqueue', '--all' => true, '--importer' => ['not_existent']] + ); + } catch (\Throwable $t) { + $this->sharedStorage->set('command_exception', $t); + } + } + + /** + * @Then /^I should be notified that the importer does not exists$/ + */ + public function iShouldBeNotifiedThatTheImporterDoesNotExists() + { + /** @var \Throwable $throwable */ + $throwable = $this->sharedStorage->get('command_exception'); + Assert::isInstanceOf($throwable, \Throwable::class); + Assert::regex($throwable->getMessage(), '/Importer ".*?" does not exists/'); + } + private function getCommandTester(): CommandTester { $application = new Application($this->kernel); From f7236d4c0f90d609bdafa38ab22c4f17eafeb256 Mon Sep 17 00:00:00 2001 From: Manuele Menozzi Date: Sun, 8 Nov 2020 16:17:08 +0100 Subject: [PATCH 5/5] Add documentation about importer and all options of enqueue command (#12) --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 4e9a077a..6ee45bd2 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,18 @@ When run with the since file, the enqueue command will write the current date/ti This way the enqueue command is run repeatedly enqueing only producs modified since the last command execution. +You can also enqueue items only for specific importers: + +```bash +bin/console webgriffe:akeneno:enqueue --importer="Product" --importer="MyImporter" --since="2020-01-30" +``` + +You can also enqueue items regardless their last update date: + +```bash +bin/console webgriffe:akeneno:enqueue --all +``` + ### Consume command To import the Akeneo entities that are in the queue you can use the `webgriffe:akeneo:consume` console command: