diff --git a/config/bundles.php b/config/bundles.php index 7e4ff0cddb3..bd719d17cd9 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -1,5 +1,16 @@ ['all' => true], Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], @@ -56,5 +67,5 @@ Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true], Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true], Fidry\AliceDataFixtures\Bridge\Symfony\FidryAliceDataFixturesBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true], - Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true] + Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true], ]; diff --git a/features/product/managing_products/select_taxons_for_new_product.feature b/features/product/managing_products/select_taxons_for_new_product.feature new file mode 100644 index 00000000000..770251ac29a --- /dev/null +++ b/features/product/managing_products/select_taxons_for_new_product.feature @@ -0,0 +1,34 @@ +@managing_products +Feature: Select taxon for a new product + In order to specify in which taxons a product is available + As an Administrator + I want to be able to select taxons for a new product + + Background: + Given the store operates on a single channel in "United States" + And the store classifies its products as "T-Shirts", "Accessories", "Funny" and "Sad" + And I am logged in as an administrator + And I am using "English (United Kingdom)" locale for my panel + + @ui @javascript + Scenario: Specifying main taxon for configurable product + Given I want to create a new configurable product + When I choose main taxon "Sad" + And I name it "Gentleman Jack" in "English (United States)" + And I specify its code as "WHISKEY_GENTLEMEN" + And I set its slug to "whiskey/gentleman-jack" in "English (United States)" + And I add it + Then I should be notified that it has been successfully created + And main taxon of product "Gentleman Jack" should be "Sad" + + @ui @javascript + Scenario: Specifying main taxon for simple product + Given I want to create a new simple product + When I choose main taxon "Sad" + And I name it "Mansion of Madness" in "English (United States)" + And I specify its code as "BOARD_MANSION_OF_MADNESS" + And I set its price to "$100.00" for "United States" channel + And I set its slug to "mom-board-game" in "English (United States)" + And I add it + Then I should be notified that it has been successfully created + And main taxon of product "Mansion of Madness" should be "Sad" diff --git a/features/product/managing_products/select_taxons_for_product.feature b/features/product/managing_products/select_taxons_for_product.feature index 8f0d74f55dc..e5a831ca7db 100644 --- a/features/product/managing_products/select_taxons_for_product.feature +++ b/features/product/managing_products/select_taxons_for_product.feature @@ -1,8 +1,8 @@ @managing_products -Feature: Select taxon for a product +Feature: Select taxon for an existing product In order to specify in which taxons a product is available As an Administrator - I want to be able to select taxons for a product + I want to be able to select taxons for an existing product Background: Given the store operates on a single channel in "United States" @@ -27,3 +27,4 @@ Feature: Select taxon for a product And I save my changes Then I should be notified that it has been successfully edited And this product main taxon should be "Sad" + diff --git a/features/product/viewing_products/viewing_products_from_taxon_and_children.feature b/features/product/viewing_products/viewing_products_from_taxon_and_children.feature new file mode 100644 index 00000000000..c8c2358b6b9 --- /dev/null +++ b/features/product/viewing_products/viewing_products_from_taxon_and_children.feature @@ -0,0 +1,38 @@ +@viewing_products +Feature: Viewing products from taxon children + In order to browse products from general taxons + As a Visitor + I want to be able to view products from taxon and from taxon children + + Background: + Given the store has currency "Euro" + And the store operates on a channel named "Poland" + And the store classifies its products as "T-Shirts" + And the "T-Shirts" taxon has children taxon "Men" and "Women" + And the store has a product "T-Shirt Coconut" available in "Poland" channel + And this product belongs to "T-Shirts" + And the store has a product "T-Shirt Banana For Men" available in "Poland" channel + And this product belongs to "T-Shirts" + And this product belongs to "Men" + And the store has a product "T-Shirt Apple" available in "Poland" channel + And this product belongs to "T-Shirts" + And this product belongs to "Men" + And the store has a product "T-Shirt Pear" available in "Poland" channel + And this product belongs to "T-Shirts" + And this product belongs to "Men" + And the store has a product "T-Shirt Watermelon" available in "Poland" channel + And this product belongs to "T-Shirts" + And this product belongs to "Men" + And the store has a product "T-Shirt Lemon" available in "Poland" channel + And this product belongs to "T-Shirts" + And this product belongs to "Men" + + @ui + Scenario: Viewing products from taxon children + When I browse products from taxon "T-Shirts" + Then I should see the product "T-Shirt Coconut" + And I should see the product "T-Shirt Banana For Men" + And I should see the product "T-Shirt Apple" + And I should see the product "T-Shirt Pear" + And I should see the product "T-Shirt Watermelon" + And I should see the product "T-Shirt Lemon" diff --git a/src/Sylius/Behat/Context/Ui/Admin/ManagingProductsContext.php b/src/Sylius/Behat/Context/Ui/Admin/ManagingProductsContext.php index a00cf6d0ffd..16261d3affe 100644 --- a/src/Sylius/Behat/Context/Ui/Admin/ManagingProductsContext.php +++ b/src/Sylius/Behat/Context/Ui/Admin/ManagingProductsContext.php @@ -579,6 +579,7 @@ public function productSlugShouldBe(ProductInterface $product, $slug, $locale = /** * @Then /^(this product) main taxon should be "([^"]+)"$/ + * @Then /^main taxon of (product "[^"]+") should be "([^"]+)"$/ */ public function thisProductMainTaxonShouldBe(ProductInterface $product, $taxonName) { diff --git a/src/Sylius/Behat/Page/Admin/Product/CreateConfigurableProductPage.php b/src/Sylius/Behat/Page/Admin/Product/CreateConfigurableProductPage.php index 43484ad1ca8..2ba2aacf7cf 100644 --- a/src/Sylius/Behat/Page/Admin/Product/CreateConfigurableProductPage.php +++ b/src/Sylius/Behat/Page/Admin/Product/CreateConfigurableProductPage.php @@ -17,7 +17,9 @@ use Behat\Mink\Element\NodeElement; use Sylius\Behat\Behaviour\SpecifiesItsCode; use Sylius\Behat\Page\Admin\Crud\CreatePage as BaseCreatePage; +use Sylius\Behat\Service\AutocompleteHelper; use Sylius\Behat\Service\SlugGenerationHelper; +use Sylius\Component\Core\Model\TaxonInterface; use Webmozart\Assert\Assert; class CreateConfigurableProductPage extends BaseCreatePage implements CreateConfigurableProductPageInterface @@ -26,6 +28,8 @@ class CreateConfigurableProductPage extends BaseCreatePage implements CreateConf public function nameItIn(string $name, string $localeCode): void { + $this->clickTabIfItsNotActive('details'); + $this->getDocument()->fillField( sprintf('sylius_product_translations_%s_name', $localeCode), $name ); @@ -35,12 +39,29 @@ public function nameItIn(string $name, string $localeCode): void } } + public function isMainTaxonChosen(string $taxonName): bool + { + $this->openTaxonBookmarks(); + Assert::notNull($this->getDocument()->find('css', '.search > .text')); + + return $taxonName === $this->getDocument()->find('css', '.search > .text')->getText(); + } + + public function selectMainTaxon(TaxonInterface $taxon): void + { + $this->openTaxonBookmarks(); + + $mainTaxonElement = $this->getElement('main_taxon')->getParent(); + + AutocompleteHelper::chooseValue($this->getSession(), $mainTaxonElement, $taxon->getName()); + } + public function selectOption(string $optionName): void { $this->getDocument()->selectFieldOption('Options', $optionName); } - public function attachImage(string $path, string $type = null): void + public function attachImage(string $path, ?string $type = null): void { $this->clickTabIfItsNotActive('media'); @@ -61,12 +82,21 @@ protected function getDefinedElements(): array return array_merge(parent::getDefinedElements(), [ 'code' => '#sylius_product_code', 'images' => '#sylius_product_images', + 'main_taxon' => '#sylius_product_mainTaxon', 'name' => '#sylius_product_translations_en_US_name', + 'search' => '.ui.fluid.search.selection.dropdown', + 'search_item_selected' => 'div.menu > div.item.selected', 'slug' => '#sylius_product_translations_en_US_slug', 'tab' => '.menu [data-tab="%name%"]', + 'taxonomy' => 'a[data-tab="taxonomy"]', ]); } + private function openTaxonBookmarks(): void + { + $this->getElement('taxonomy')->click(); + } + private function clickTabIfItsNotActive(string $tabName): void { $attributesTab = $this->getElement('tab', ['%name%' => $tabName]); diff --git a/src/Sylius/Behat/Page/Admin/Product/CreateConfigurableProductPageInterface.php b/src/Sylius/Behat/Page/Admin/Product/CreateConfigurableProductPageInterface.php index 4ed111fef2c..bce40dc1c33 100644 --- a/src/Sylius/Behat/Page/Admin/Product/CreateConfigurableProductPageInterface.php +++ b/src/Sylius/Behat/Page/Admin/Product/CreateConfigurableProductPageInterface.php @@ -14,6 +14,7 @@ namespace Sylius\Behat\Page\Admin\Product; use Sylius\Behat\Page\Admin\Crud\CreatePageInterface as BaseCreatePageInterface; +use Sylius\Component\Core\Model\TaxonInterface; interface CreateConfigurableProductPageInterface extends BaseCreatePageInterface { @@ -23,8 +24,9 @@ public function specifyCode(string $code): void; public function nameItIn(string $name, string $localeCode): void; - /** - * @param string $type - */ - public function attachImage(string $path, string $type = null): void; + public function isMainTaxonChosen(string $taxonName): bool; + + public function selectMainTaxon(TaxonInterface $taxon): void; + + public function attachImage(string $path, ?string $type = null): void; } diff --git a/src/Sylius/Behat/Page/Admin/Product/CreateSimpleProductPage.php b/src/Sylius/Behat/Page/Admin/Product/CreateSimpleProductPage.php index 882df65d7a6..65d47e57e4e 100644 --- a/src/Sylius/Behat/Page/Admin/Product/CreateSimpleProductPage.php +++ b/src/Sylius/Behat/Page/Admin/Product/CreateSimpleProductPage.php @@ -17,7 +17,9 @@ use Behat\Mink\Element\NodeElement; use Sylius\Behat\Behaviour\SpecifiesItsCode; use Sylius\Behat\Page\Admin\Crud\CreatePage as BaseCreatePage; +use Sylius\Behat\Service\AutocompleteHelper; use Sylius\Behat\Service\SlugGenerationHelper; +use Sylius\Component\Core\Model\TaxonInterface; use Sylius\Component\Product\Model\ProductAssociationTypeInterface; use Webmozart\Assert\Assert; @@ -32,6 +34,7 @@ public function getRouteName(): string public function nameItIn(string $name, string $localeCode): void { + $this->clickTabIfItsNotActive('details'); $this->activateLanguageTab($localeCode); $this->getElement('name', ['%locale%' => $localeCode])->setValue($name); @@ -91,6 +94,28 @@ public function removeAttribute(string $attributeName, string $localeCode): void $this->getElement('attribute_delete_button', ['%attributeName%' => $attributeName, '%localeCode%' => $localeCode])->press(); } + public function checkAttributeErrors($attributeName, $localeCode): void + { + $this->clickTabIfItsNotActive('attributes'); + $this->clickLocaleTabIfItsNotActive($localeCode); + } + + public function selectMainTaxon(TaxonInterface $taxon): void + { + $this->openTaxonBookmarks(); + + $mainTaxonElement = $this->getElement('main_taxon')->getParent(); + + AutocompleteHelper::chooseValue($this->getSession(), $mainTaxonElement, $taxon->getName()); + } + + public function isMainTaxonChosen(string $taxonName): bool + { + $this->openTaxonBookmarks(); + + return $taxonName === $this->getDocument()->find('css', '.search > .text')->getText(); + } + public function attachImage(string $path, string $type = null): void { $this->clickTabIfItsNotActive('media'); @@ -209,6 +234,7 @@ protected function getDefinedElements(): array 'images' => '#sylius_product_images', 'language_tab' => '[data-locale="%locale%"] .title', 'locale_tab' => '#attributesContainer .menu [data-tab="%localeCode%"]', + 'main_taxon' => '#sylius_product_mainTaxon', 'name' => '#sylius_product_translations_%locale%_name', 'price' => '#sylius_product_variant_channelPricings > .field:contains("%channelName%") input[name$="[price]"]', 'original_price' => '#sylius_product_variant_channelPricings > .field:contains("%channelName%") input[name$="[originalPrice]"]', @@ -217,10 +243,16 @@ protected function getDefinedElements(): array 'shipping_required' => '#sylius_product_variant_shippingRequired', 'slug' => '#sylius_product_translations_%locale%_slug', 'tab' => '.menu [data-tab="%name%"]', + 'taxonomy' => 'a[data-tab="taxonomy"]', 'toggle_slug_modification_button' => '.toggle-product-slug-modification', ]); } + private function openTaxonBookmarks(): void + { + $this->getElement('taxonomy')->click(); + } + private function selectElementFromAttributesDropdown(string $id): void { /** @var Selenium2Driver $driver */ diff --git a/src/Sylius/Behat/Page/Admin/Product/CreateSimpleProductPageInterface.php b/src/Sylius/Behat/Page/Admin/Product/CreateSimpleProductPageInterface.php index 65c779867b0..9188bcad42d 100644 --- a/src/Sylius/Behat/Page/Admin/Product/CreateSimpleProductPageInterface.php +++ b/src/Sylius/Behat/Page/Admin/Product/CreateSimpleProductPageInterface.php @@ -14,6 +14,7 @@ namespace Sylius\Behat\Page\Admin\Product; use Sylius\Behat\Page\Admin\Crud\CreatePageInterface as BaseCreatePageInterface; +use Sylius\Component\Core\Model\TaxonInterface; use Sylius\Component\Product\Model\ProductAssociationTypeInterface; interface CreateSimpleProductPageInterface extends BaseCreatePageInterface @@ -38,10 +39,11 @@ public function getAttributeValidationErrors(string $attributeName, string $loca public function removeAttribute(string $attributeName, string $localeCode): void; - /** - * @param string $type - */ - public function attachImage(string $path, string $type = null): void; + public function isMainTaxonChosen(string $taxonName): bool; + + public function selectMainTaxon(TaxonInterface $taxon): void; + + public function attachImage(string $path, ?string $type = null): void; /** * @param string[] $productsNames diff --git a/src/Sylius/Bundle/CoreBundle/Doctrine/ORM/ProductRepository.php b/src/Sylius/Bundle/CoreBundle/Doctrine/ORM/ProductRepository.php index 416b76ba9e3..2e2da0ffca5 100644 --- a/src/Sylius/Bundle/CoreBundle/Doctrine/ORM/ProductRepository.php +++ b/src/Sylius/Bundle/CoreBundle/Doctrine/ORM/ProductRepository.php @@ -71,6 +71,7 @@ public function createShopListQueryBuilder( bool $includeAllDescendants = false ): QueryBuilder { $queryBuilder = $this->createQueryBuilder('o') + ->distinct() ->addSelect('translation') ->innerJoin('o.translations', 'translation', 'WITH', 'translation.locale = :locale') ->innerJoin('o.productTaxons', 'productTaxon'); diff --git a/src/Sylius/Bundle/ThemeBundle/Tests/Functional/TemplatingTest.php b/src/Sylius/Bundle/ThemeBundle/Tests/Functional/TemplatingTest.php index 4b5ab50c7fb..0e53428251c 100644 --- a/src/Sylius/Bundle/ThemeBundle/Tests/Functional/TemplatingTest.php +++ b/src/Sylius/Bundle/ThemeBundle/Tests/Functional/TemplatingTest.php @@ -92,9 +92,6 @@ public function it_renders_sylius_plugin_templates_using_namespaced_paths(string $this->assertEquals($contents, trim($crawler->text())); } - /** - * @return array - */ public function getPluginTemplatesUsingNamespacedPaths(): array { return [