From b143e7ba59c6e32b4edbafc9537fe044116fff01 Mon Sep 17 00:00:00 2001 From: "ivan.pletnyov" Date: Fri, 24 Jan 2020 16:11:32 +0200 Subject: [PATCH 1/5] MC-24894: Admin: Check Product categories indexing when add/remove category in product using category link management --- .../Model/CategoryLinkManagementTest.php | 227 ++++++++++++++++++ ...ith_category_which_has_parent_category.php | 47 ++++ ...ory_which_has_parent_category_rollback.php | 23 ++ .../Catalog/_files/product_with_category.php | 2 +- 4 files changed, 298 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryLinkManagementTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_category_which_has_parent_category.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_category_which_has_parent_category_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryLinkManagementTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryLinkManagementTest.php new file mode 100644 index 0000000000000..50d0ddbf5dccf --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryLinkManagementTest.php @@ -0,0 +1,227 @@ +objectManager = Bootstrap::getObjectManager(); + $this->tableMaintainer = $this->objectManager->get(TableMaintainer::class); + $this->storeRepository = $this->objectManager->get(StoreRepositoryInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->categoryResourceModel = $this->objectManager->get(CategoryResourceModel::class); + $this->categoryLinkManagement = $this->objectManager->create(CategoryLinkManagementInterface::class); + $this->productRepository->cleanCache(); + parent::setUp(); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->objectManager->removeSharedInstance(CategoryLinkRepository::class); + $this->objectManager->removeSharedInstance(CategoryRepository::class); + parent::tearDown(); + } + + /** + * Assert that product correctly assigned to category and index table contain indexed data. + * + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * @magentoDataFixture Magento/Catalog/_files/category.php + * + * @magentoDbIsolation disabled + * + * @return void + */ + public function testAssignProductToCategory(): void + { + $product = $this->productRepository->get('simple2'); + $this->assertEquals(0, $this->getCategoryProductRelationRecordsCount((int)$product->getId(), [333])); + $this->assertEquals(0, $this->getCategoryProductIndexRecordsCount((int)$product->getId(), [333])); + $this->categoryLinkManagement->assignProductToCategories('simple2', [333]); + $this->assertEquals(1, $this->getCategoryProductRelationRecordsCount((int)$product->getId(), [333])); + $this->assertEquals(1, $this->getCategoryProductIndexRecordsCount((int)$product->getId(), [333])); + } + + /** + * Assert that product correctly unassigned from category and index table not contain indexed data. + * + * @magentoDataFixture Magento/Catalog/_files/product_with_category.php + * + * @magentoDbIsolation disabled + * + * @return void + */ + public function testUnassignProductFromCategory(): void + { + $product = $this->productRepository->get('in-stock-product'); + $this->assertEquals(1, $this->getCategoryProductRelationRecordsCount((int)$product->getId(), [333])); + $this->assertEquals(1, $this->getCategoryProductIndexRecordsCount((int)$product->getId(), [333])); + $this->categoryLinkManagement->assignProductToCategories('in-stock-product', []); + $this->assertEquals(0, $this->getCategoryProductRelationRecordsCount((int)$product->getId(), [333])); + $this->assertEquals(0, $this->getCategoryProductIndexRecordsCount((int)$product->getId(), [333])); + } + + /** + * Assert that product correctly assigned to category and index table contain index data. + * + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * @magentoDataFixture Magento/Catalog/_files/categories_no_products.php + * + * @magentoDbIsolation disabled + * + * @return void + */ + public function testAssignProductToCategoryWhichHasParentCategories(): void + { + $product = $this->productRepository->get('simple2'); + $this->assertEquals(0, $this->getCategoryProductRelationRecordsCount((int)$product->getId(), [5])); + $this->assertEquals(0, $this->getCategoryProductIndexRecordsCount((int)$product->getId(), [3, 4, 5])); + $this->categoryLinkManagement->assignProductToCategories('simple2', [5]); + $this->assertEquals(1, $this->getCategoryProductRelationRecordsCount((int)$product->getId(), [5])); + $this->assertEquals(3, $this->getCategoryProductIndexRecordsCount((int)$product->getId(), [3, 4, 5])); + } + + /** + * Assert that product correctly unassigned from category and index table doesn't contain index data. + * + * @magentoDataFixture Magento/Catalog/_files/product_simple_with_category_which_has_parent_category.php + * + * @magentoDbIsolation disabled + * + * @return void + */ + public function testUnassignProductFromCategoryWhichHasParentCategories(): void + { + $product = $this->productRepository->get('simple_with_child_category'); + $this->assertEquals(1, $this->getCategoryProductRelationRecordsCount((int)$product->getId(), [5])); + $this->assertEquals(3, $this->getCategoryProductIndexRecordsCount((int)$product->getId(), [3, 4, 5])); + $this->categoryLinkManagement->assignProductToCategories('simple_with_child_category', []); + $this->assertEquals(0, $this->getCategoryProductRelationRecordsCount((int)$product->getId(), [5])); + $this->assertEquals(0, $this->getCategoryProductIndexRecordsCount((int)$product->getId(), [3, 4, 5])); + } + + /** + * Assert that product correctly reassigned to another category. + * + * @magentoDataFixture Magento/Catalog/_files/product_simple_with_category_which_has_parent_category.php + * + * @magentoDbIsolation disabled + * + * @return void + */ + public function testReassignProductToOtherCategory(): void + { + $product = $this->productRepository->get('simple_with_child_category'); + $this->assertEquals(1, $this->getCategoryProductRelationRecordsCount((int)$product->getId(), [5])); + $this->assertEquals(3, $this->getCategoryProductIndexRecordsCount((int)$product->getId(), [3, 4, 5])); + $this->categoryLinkManagement->assignProductToCategories('simple_with_child_category', [6]); + $this->assertEquals(1, $this->getCategoryProductRelationRecordsCount((int)$product->getId(), [6])); + $this->assertEquals(1, $this->getCategoryProductIndexRecordsCount((int)$product->getId(), [6])); + $this->assertEquals(0, $this->getCategoryProductRelationRecordsCount((int)$product->getId(), [5])); + $this->assertEquals(0, $this->getCategoryProductIndexRecordsCount((int)$product->getId(), [3, 4, 5])); + } + + /** + * Return count of product which assigned to provided categories. + * + * @param int $productId + * @param int[] $categoryIds + * @return int + */ + private function getCategoryProductRelationRecordsCount(int $productId, array $categoryIds): int + { + $select = $this->categoryResourceModel->getConnection()->select(); + $select->from( + $this->categoryResourceModel->getCategoryProductTable(), + [ + 'row_count' => new \Zend_Db_Expr('COUNT(*)') + ] + ); + $select->where('product_id = ?', $productId); + $select->where('category_id IN (?)', $categoryIds); + + return (int)$this->categoryResourceModel->getConnection()->fetchOne($select); + } + + /** + * Return count of products which added to index table with all provided category ids. + * + * @param int $productId + * @param array $categoryIds + * @param string $storeCode + * @return int + */ + private function getCategoryProductIndexRecordsCount( + int $productId, + array $categoryIds, + string $storeCode = 'default' + ): int { + $storeId = (int)$this->storeRepository->get($storeCode)->getId(); + $select = $this->categoryResourceModel->getConnection()->select(); + $select->from( + $this->tableMaintainer->getMainTable($storeId), + [ + 'row_count' => new \Zend_Db_Expr('COUNT(*)') + ] + ); + $select->where('product_id = ?', $productId); + $select->where('category_id IN (?)', $categoryIds); + + return (int)$this->categoryResourceModel->getConnection()->fetchOne($select); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_category_which_has_parent_category.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_category_which_has_parent_category.php new file mode 100644 index 0000000000000..4d3ad8fcbf2f4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_category_which_has_parent_category.php @@ -0,0 +1,47 @@ +get(ProductRepositoryInterface::class); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +/** @var ProductInterfaceFactory $productFactory */ +$productFactory = $objectManager->get(ProductInterfaceFactory::class); +$defaultWebsiteId = $websiteRepository->get('base')->getId(); +$product = $productFactory->create(); +$product->setData( + [ + 'attribute_set_id' => $product->getDefaultAttributeSetId(), + 'website_ids' => [ + $defaultWebsiteId + ], + 'name' => 'Simple product with child category', + 'sku' => 'simple_with_child_category', + 'price' => 10, + 'description' => 'Description product with category which has parent category', + 'visibility' => Visibility::VISIBILITY_BOTH, + 'status' => Status::STATUS_ENABLED, + 'category_ids' => [5], + 'stock_data' => [ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1 + ], + 'url_key' => 'simple-with-child-category' + ] +); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_category_which_has_parent_category_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_category_which_has_parent_category_rollback.php new file mode 100644 index 0000000000000..58acf8e35129e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_category_which_has_parent_category_rollback.php @@ -0,0 +1,23 @@ +get(ProductRepositoryInterface::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +try { + $productRepository->deleteById('simple_with_child_category'); +} catch (NoSuchEntityException $exception) { + //Product already deleted. +} +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_category.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_category.php index 28c235e4e3e87..ebc6bce655198 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_category.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_category.php @@ -30,7 +30,7 @@ ->setSku('in-stock-product') ->setPrice(10) ->setWeight(1) - ->setShortDescription("Short description") + ->setShortDescription('Short description') ->setTaxClassId(0) ->setDescription('Description with html tag') ->setMetaTitle('meta title') From 1ba225d9a7cf78a5dffb7249418eca6638965168 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha Date: Mon, 27 Jan 2020 15:27:46 +0200 Subject: [PATCH 2/5] MC-29688: Storefront: Check multiple currencies per websites/store views --- .../Model/RemoveCurrencyRateByCode.php | 40 +++++ .../Product/View/AbstractCurrencyTest.php | 111 +++++++++++++ .../Product/View/MultiStoreCurrencyTest.php | 147 ++++++++++++++++++ .../Product/View/SingleStoreCurrencyTest.php | 64 ++++++++ .../Magento/Directory/Block/CurrencyTest.php | 123 +++++++++++++++ .../Magento/Directory/_files/usd_cny_rate.php | 16 ++ .../_files/usd_cny_rate_rollback.php | 14 ++ .../Magento/Directory/_files/usd_uah_rate.php | 16 ++ .../_files/usd_uah_rate_rollback.php | 14 ++ 9 files changed, 545 insertions(+) create mode 100644 dev/tests/integration/framework/Magento/TestFramework/Directory/Model/RemoveCurrencyRateByCode.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/AbstractCurrencyTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/MultiStoreCurrencyTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/SingleStoreCurrencyTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Directory/Block/CurrencyTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Directory/_files/usd_cny_rate.php create mode 100644 dev/tests/integration/testsuite/Magento/Directory/_files/usd_cny_rate_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Directory/_files/usd_uah_rate.php create mode 100644 dev/tests/integration/testsuite/Magento/Directory/_files/usd_uah_rate_rollback.php diff --git a/dev/tests/integration/framework/Magento/TestFramework/Directory/Model/RemoveCurrencyRateByCode.php b/dev/tests/integration/framework/Magento/TestFramework/Directory/Model/RemoveCurrencyRateByCode.php new file mode 100644 index 0000000000000..86895045db945 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Directory/Model/RemoveCurrencyRateByCode.php @@ -0,0 +1,40 @@ +currencyResource = $currencyResource; + } + + /** + * Remove currency rates + * + * @param string $currencyCode + * @return void + */ + public function execute(string $currencyCode): void + { + $connection = $this->currencyResource->getConnection(); + $rateTable = $this->currencyResource->getTable('directory_currency_rate'); + $connection->delete($rateTable, $connection->quoteInto('currency_to = ? OR currency_from = ?', $currencyCode)); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/AbstractCurrencyTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/AbstractCurrencyTest.php new file mode 100644 index 0000000000000..2ae71797e52e5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/AbstractCurrencyTest.php @@ -0,0 +1,111 @@ +objectManager = Bootstrap::getObjectManager(); + $this->registry = $this->objectManager->get(Registry::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->pageFactory = $this->objectManager->get(PageFactory::class); + } + + /** + * @inheridoc + */ + protected function tearDown() + { + $this->registry->unregister('product'); + + parent::tearDown(); + } + + /** + * Process price view on product page + * + * @param string|ProductInterface $product + * @param string $blockName + * @return string + */ + protected function processPriceView($product, string $blockName = self::FINAL_PRICE_BLOCK_NAME): string + { + $product = is_string($product) ? $this->productRepository->get($product) : $product; + $this->registerProduct($product); + + return trim( + preg_replace('/(?:\s| )+/', ' ', strip_tags($this->getProductPriceBlockHtml($blockName))) + ); + } + + /** + * Get product price block content + * + * @param string $blockName + * @return string + */ + private function getProductPriceBlockHtml(string $blockName): string + { + $page = $this->pageFactory->create(); + $page->addHandle([ + 'default', + 'catalog_product_view', + 'catalog_product_view_type_configurable', + ]); + $page->getLayout()->generateXml(); + $block = $page->getLayout()->getBlock($blockName); + $this->assertNotFalse($block); + + return $block->toHtml(); + } + + /** + * Register the product + * + * @param ProductInterface $product + * @return void + */ + private function registerProduct(ProductInterface $product): void + { + $this->registry->unregister('product'); + $this->registry->register('product', $product); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/MultiStoreCurrencyTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/MultiStoreCurrencyTest.php new file mode 100644 index 0000000000000..22d30fd3d9ea8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/MultiStoreCurrencyTest.php @@ -0,0 +1,147 @@ +storeManager = $this->objectManager->get(StoreManagerInterface::class); + } + + /** + * @magentoConfigFixture default/currency/options/base USD + * @magentoConfigFixture current_store currency/options/default CNY + * @magentoConfigFixture current_store currency/options/allow CNY,USD + * @magentoConfigFixture fixturestore_store currency/options/default UAH + * @magentoConfigFixture fixturestore_store currency/options/allow UAH,USD + * + * @magentoDataFixture Magento/Store/_files/core_fixturestore.php + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * @magentoDataFixture Magento/Directory/_files/usd_cny_rate.php + * @magentoDataFixture Magento/Directory/_files/usd_uah_rate.php + * + * @return void + */ + public function testMultiStoreRenderPrice(): void + { + $this->assertProductStorePrice('simple2', 'CN¥70.00'); + $this->reloadProductPriceInfo(); + $this->assertProductStorePrice('simple2', '₴240.00', 'fixturestore'); + } + + /** + * @magentoConfigFixture default/currency/options/base USD + * @magentoConfigFixture current_store currency/options/default CNY + * @magentoConfigFixture current_store currency/options/allow CNY,USD + * @magentoConfigFixture fixturestore_store currency/options/default UAH + * @magentoConfigFixture fixturestore_store currency/options/allow UAH,USD + * + * @magentoDataFixture Magento/Store/_files/core_fixturestore.php + * @magentoDataFixture Magento/Catalog/_files/product_special_price.php + * @magentoDataFixture Magento/Directory/_files/usd_cny_rate.php + * @magentoDataFixture Magento/Directory/_files/usd_uah_rate.php + * + * @return void + */ + public function testMultiStoreRenderSpecialPrice(): void + { + $this->assertProductStorePrice('simple', 'Special Price CN¥41.93 Regular Price CN¥70.00'); + $this->reloadProductPriceInfo(); + $this->assertProductStorePrice('simple', 'Special Price ₴143.76 Regular Price ₴240.00', 'fixturestore'); + } + + /** + * @magentoConfigFixture default/currency/options/base USD + * @magentoConfigFixture current_store currency/options/default CNY + * @magentoConfigFixture current_store currency/options/allow CNY,USD + * @magentoConfigFixture fixturestore_store currency/options/default UAH + * @magentoConfigFixture fixturestore_store currency/options/allow UAH,USD + * + * @magentoDataFixture Magento/Store/_files/core_fixturestore.php + * @magentoDataFixture Magento/Catalog/_files/product_simple_with_fixed_tier_price.php + * @magentoDataFixture Magento/Directory/_files/usd_cny_rate.php + * @magentoDataFixture Magento/Directory/_files/usd_uah_rate.php + * + * @return void + */ + public function testMultiStoreRenderTierPrice(): void + { + $this->assertProductStorePrice( + 'simple-product-tax-none', + 'Buy 2 for CN¥280.00 each and save 80%', + 'default', + self::TIER_PRICE_BLOCK_NAME + ); + $this->reloadProductPriceInfo(); + $this->assertProductStorePrice( + 'simple-product-tax-none', + 'Buy 2 for ₴960.00 each and save 80%', + 'fixturestore', + self::TIER_PRICE_BLOCK_NAME + ); + } + + /** + * Check price per stores + * + * @param string $productSku + * @param string $expectedData + * @param string $storeCode + * @param string $priceBlockName + * @return void + */ + private function assertProductStorePrice( + string $productSku, + string $expectedData, + string $storeCode = 'default', + string $priceBlockName = self::FINAL_PRICE_BLOCK_NAME + ): void { + $currentStore = $this->storeManager->getStore(); + try { + if ($currentStore->getCode() !== $storeCode) { + $this->storeManager->setCurrentStore($storeCode); + } + + $actualData = $this->processPriceView($productSku, $priceBlockName); + $this->assertEquals($expectedData, $actualData); + } finally { + if ($currentStore->getCode() !== $storeCode) { + $this->storeManager->setCurrentStore($currentStore); + } + } + } + + /** + * Reload product price info + * + * @return void + */ + private function reloadProductPriceInfo(): void + { + $product = $this->registry->registry('product'); + $this->assertNotNull($product); + $product->reloadPriceInfo(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/SingleStoreCurrencyTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/SingleStoreCurrencyTest.php new file mode 100644 index 0000000000000..284d85ccc9ebd --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/SingleStoreCurrencyTest.php @@ -0,0 +1,64 @@ +processPriceView('simple2'); + $this->assertEquals('CN¥70.00', $priceHtml); + } + + /** + * @magentoConfigFixture current_store currency/options/base USD + * @magentoConfigFixture current_store currency/options/default CNY + * @magentoConfigFixture current_store currency/options/allow EUR,CNY + * + * @magentoDataFixture Magento/Catalog/_files/product_special_price.php + * @magentoDataFixture Magento/Directory/_files/usd_cny_rate.php + * + * @return void + */ + public function testRenderSpecialPrice(): void + { + $priceHtml = $this->processPriceView('simple'); + $this->assertEquals('Special Price CN¥41.93 Regular Price CN¥70.00', $priceHtml); + } + + /** + * @magentoConfigFixture current_store currency/options/base USD + * @magentoConfigFixture current_store currency/options/default CNY + * @magentoConfigFixture current_store currency/options/allow CNY,USD + * + * @magentoDataFixture Magento/Catalog/_files/product_simple_with_fixed_tier_price.php + * @magentoDataFixture Magento/Directory/_files/usd_cny_rate.php + * + * @return void + */ + public function testRenderTierPrice(): void + { + $priceHtml = $this->processPriceView('simple-product-tax-none', self::TIER_PRICE_BLOCK_NAME); + $this->assertEquals('Buy 2 for CN¥280.00 each and save 80%', $priceHtml); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Directory/Block/CurrencyTest.php b/dev/tests/integration/testsuite/Magento/Directory/Block/CurrencyTest.php new file mode 100644 index 0000000000000..30527bc2fa926 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Directory/Block/CurrencyTest.php @@ -0,0 +1,123 @@ +objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); + } + + /** + * @magentoConfigFixture current_store currency/options/allow USD + * + * @return void + */ + public function testDefaultCurrencySwitcher(): void + { + $this->assertCurrencySwitcherPerStore(''); + } + + /** + * @magentoConfigFixture current_store currency/options/allow EUR,USD + * + * @return void + */ + public function testCurrencySwitcher(): void + { + $this->assertCurrencySwitcherPerStore('Currency USD - US Dollar EUR - Euro'); + } + + /** + * @magentoConfigFixture current_store currency/options/allow USD,CNY + * @magentoConfigFixture fixturestore_store currency/options/allow USD,UAH + * + * @magentoDataFixture Magento/Store/_files/core_fixturestore.php + * @magentoDataFixture Magento/Directory/_files/usd_cny_rate.php + * @magentoDataFixture Magento/Directory/_files/usd_uah_rate.php + * + * @return void + */ + public function testMultiStoreCurrencySwitcher(): void + { + $this->assertCurrencySwitcherPerStore('Currency USD - US Dollar CNY - Chinese Yuan'); + $this->assertCurrencySwitcherPerStore('Currency USD - US Dollar UAH - Ukrainian Hryvnia', 'fixturestore'); + } + + /** + * Check currency switcher diplaying per stores + * + * @param string $expectedData + * @param string $storeCode + * @return void + */ + private function assertCurrencySwitcherPerStore( + string $expectedData, + string $storeCode = 'default' + ): void { + $currentStore = $this->storeManager->getStore(); + try { + if ($currentStore->getCode() !== $storeCode) { + $this->storeManager->setCurrentStore($storeCode); + } + + $actualData = trim(preg_replace('/\s+/', ' ', strip_tags($this->getBlock()->toHtml()))); + $this->assertEquals($expectedData, $actualData); + } finally { + if ($currentStore->getCode() !== $storeCode) { + $this->storeManager->setCurrentStore($currentStore); + } + } + } + + /** + * Get currency block + * + * @return Currency + */ + private function getBlock(): Currency + { + $block = $this->layout->createBlock(Currency::class); + $block->setTemplate(self::CURRENCY_SWITCHER_TEMPLATE); + + return $block; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Directory/_files/usd_cny_rate.php b/dev/tests/integration/testsuite/Magento/Directory/_files/usd_cny_rate.php new file mode 100644 index 0000000000000..8651f2cc760d2 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Directory/_files/usd_cny_rate.php @@ -0,0 +1,16 @@ + ['CNY' => '7.0000']]; +/** @var Currency $currencyModel */ +$currencyModel = $objectManager->create(Currency::class); +$currencyModel->saveRates($rates); diff --git a/dev/tests/integration/testsuite/Magento/Directory/_files/usd_cny_rate_rollback.php b/dev/tests/integration/testsuite/Magento/Directory/_files/usd_cny_rate_rollback.php new file mode 100644 index 0000000000000..c553995e6288c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Directory/_files/usd_cny_rate_rollback.php @@ -0,0 +1,14 @@ +get(RemoveCurrencyRateByCode::class); +$deleteRateByCode->execute('CNY'); diff --git a/dev/tests/integration/testsuite/Magento/Directory/_files/usd_uah_rate.php b/dev/tests/integration/testsuite/Magento/Directory/_files/usd_uah_rate.php new file mode 100644 index 0000000000000..3bb4bded1979c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Directory/_files/usd_uah_rate.php @@ -0,0 +1,16 @@ + ['UAH' => '24.0000']]; +/** @var Currency $currencyModel */ +$currencyModel = $objectManager->create(Currency::class); +$currencyModel->saveRates($rates); diff --git a/dev/tests/integration/testsuite/Magento/Directory/_files/usd_uah_rate_rollback.php b/dev/tests/integration/testsuite/Magento/Directory/_files/usd_uah_rate_rollback.php new file mode 100644 index 0000000000000..131f533666132 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Directory/_files/usd_uah_rate_rollback.php @@ -0,0 +1,14 @@ +get(RemoveCurrencyRateByCode::class); +$deleteRateByCode->execute('UAH'); From cf30cfb482641217b1bee91278512825151af709 Mon Sep 17 00:00:00 2001 From: DmytroPaidych Date: Mon, 27 Jan 2020 15:39:00 +0200 Subject: [PATCH 3/5] MC-30642: Storefront: Configurable product prices --- .../Type/ConfigurableProductPriceTest.php | 211 ++++++++++++++++++ ...figurable_with_custom_option_type_text.php | 32 +++ ..._with_custom_option_type_text_rollback.php | 8 + .../Renderer/Configurable/PriceTest.php | 187 ++++++++++++++++ 4 files changed, 438 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/View/Type/ConfigurableProductPriceTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_custom_option_type_text.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_custom_option_type_text_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/PriceTest.php diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/View/Type/ConfigurableProductPriceTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/View/Type/ConfigurableProductPriceTest.php new file mode 100644 index 0000000000000..977a130eff838 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/View/Type/ConfigurableProductPriceTest.php @@ -0,0 +1,211 @@ +objectManager = Bootstrap::getObjectManager(); + $this->registry = $this->objectManager->get(Registry::class); + $this->page = $this->objectManager->get(Page::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->productCustomOption = $this->objectManager->get(ProductCustomOptionInterface::class); + $this->json = $this->objectManager->get(SerializerInterface::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister('product'); + $this->registry->unregister('current_product'); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + * + * @return void + */ + public function testConfigurablePrice(): void + { + $this->assertPrice($this->processPriceView('configurable'), 10.00); + } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable_disable_first_child.php + * + * @return void + */ + public function testConfigurablePriceWithDisabledFirstChild(): void + { + $this->assertPrice($this->processPriceView('configurable'), 20.00); + } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable_zero_qty_first_child.php + * + * @return void + */ + public function testConfigurablePriceWithOutOfStockFirstChild(): void + { + $this->assertPrice($this->processPriceView('configurable'), 20.00); + } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + * @magentoDataFixture Magento/CatalogRule/_files/rule_apply_as_percentage_of_original_not_logged_user.php + * @magentoDbIsolation disabled + * + * @return void + */ + public function testConfigurablePriceWithCatalogRule(): void + { + $this->assertPrice($this->processPriceView('configurable'), 9.00); + } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable_with_custom_option_type_text.php + * + * @return void + */ + public function testConfigurablePriceWithCustomOption(): void + { + $product = $this->productRepository->get('configurable'); + $this->registerProduct($product); + $this->preparePageLayout(); + $customOptionsBlock = $this->page->getLayout() + ->getChildBlock('product.info.options.wrapper', 'product_options'); + $option = $product->getOptions()[0] ?? null; + $this->assertNotNull($option); + $this->assertJsonConfig($customOptionsBlock->getJsonConfig(), '15', (int)$option->getId()); + $optionBlock = $customOptionsBlock->getChildBlock($this->productCustomOption->getGroupByType('area')); + $optionPrice = $optionBlock->setProduct($product)->setOption($option)->getFormattedPrice(); + $this->assertEquals('+$15.00', preg_replace('/[\n\s]/', '', strip_tags($optionPrice))); + } + + /** + * Register the product. + * + * @param ProductInterface $product + * @return void + */ + private function registerProduct(ProductInterface $product): void + { + $this->registry->unregister('product'); + $this->registry->register('product', $product); + $this->registry->unregister('current_product'); + $this->registry->register('current_product', $product); + } + + /** + * Prepare configurable product page. + * + * @return void + */ + private function preparePageLayout(): void + { + $this->page->addHandle([ + 'default', + 'catalog_product_view', + 'catalog_product_view_type_configurable', + ]); + $this->page->getLayout()->generateXml(); + } + + /** + * Process view product final price block html. + * + * @param string $sku + * @return string + */ + private function processPriceView(string $sku): string + { + $product = $this->productRepository->get($sku); + $this->registerProduct($product); + $this->preparePageLayout(); + + return $this->page->getLayout()->getBlock('product.price.final')->toHtml(); + } + + /** + * Assert that html contain price label and expected final price amount. + * + * @param string $priceBlockHtml + * @param float $expectedPrice + * @return void + */ + private function assertPrice(string $priceBlockHtml, float $expectedPrice): void + { + $regexp = '/As low as<\/span>.*'; + $regexp .= '\$%.2f<\/span><\/span>/'; + $this->assertRegExp( + sprintf($regexp, round($expectedPrice, 2), $expectedPrice), + preg_replace('/[\n\r]/', '', $priceBlockHtml) + ); + } + + /** + * Assert custom option price json config. + * + * @param string $config + * @param string $expectedPrice + * @param int $optionId + * @return void + */ + private function assertJsonConfig(string $config, string $expectedPrice, int $optionId): void + { + $price = $this->json->unserialize($config)[$optionId]['prices']['finalPrice']['amount'] ?? null; + $this->assertNotNull($price); + $this->assertEquals($expectedPrice, $price); + } +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_custom_option_type_text.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_custom_option_type_text.php new file mode 100644 index 0000000000000..dc173b1cd7607 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_custom_option_type_text.php @@ -0,0 +1,32 @@ +get(ProductCustomOptionInterfaceFactory::class); + +$createdOption = $optionRepository->create([ + 'data' => [ + 'is_require' => 0, + 'sku' => 'option-1', + 'title' => 'Option 1', + 'type' => ProductCustomOptionInterface::OPTION_TYPE_AREA, + 'price' => 15, + 'price_type' => 'fixed', + ] +]); +$createdOption->setProductSku($product->getSku()); +$product->setOptions([$createdOption]); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_custom_option_type_text_rollback.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_custom_option_type_text_rollback.php new file mode 100644 index 0000000000000..c6c17b956ee37 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_with_custom_option_type_text_rollback.php @@ -0,0 +1,8 @@ +objectManager = Bootstrap::getObjectManager(); + $this->registry = $this->objectManager->get(Registry::class); + $this->page = $this->objectManager->get(Page::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->json = $this->objectManager->get(SerializerInterface::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister('product'); + + parent::tearDown(); + } + + /** + * @dataProvider childProductsDataProvider + * @magentoDataFixture Magento/Swatches/_files/configurable_product_visual_swatch_attribute.php + * @magentoCache config disabled + * + * @param array $updateData + * @param array $expectedData + * @return void + */ + public function testConfigurableOptionPrices(array $updateData, array $expectedData): void + { + $this->updateProducts($updateData); + $product = $this->productRepository->get('configurable'); + $this->registerProduct($product); + $configurableOptions = $this->getProductSwatchOptionsBlock()->getJsonConfig(); + $optionsData = $this->json->unserialize($configurableOptions); + $this->assertArrayHasKey('optionPrices', $optionsData); + $this->assertEquals($expectedData, array_values($optionsData['optionPrices'])); + } + + /** + * @return array + */ + public function childProductsDataProvider(): array + { + return [ + [ + 'update_data' => [ + 'simple_option_1' => [ + 'special_price' => 50, + ], + 'simple_option_2' => [ + 'special_price' => 58.55, + ], + 'simple_option_3' => [ + 'tier_price' => [ + [ + 'website_id' => 0, + 'cust_group' => Group::CUST_GROUP_ALL, + 'price_qty' => 1, + 'value_type' => TierPriceInterface::PRICE_TYPE_FIXED, + 'price' => 75, + ], + ], + ], + ], + 'expected_data' => [ + [ + 'oldPrice' => ['amount' => 150], + 'basePrice' => ['amount' => 50], + 'finalPrice' => ['amount' => 50], + 'tierPrices' => [], + 'msrpPrice' => ['amount' => null], + ], + [ + 'oldPrice' => ['amount' => 150], + 'basePrice' => ['amount' => 58.55], + 'finalPrice' => ['amount' => 58.55], + 'tierPrices' => [], + 'msrpPrice' => ['amount' => null], + ], + [ + 'oldPrice' => ['amount' => 150], + 'basePrice' => ['amount' => 75], + 'finalPrice' => ['amount' => 75], + 'tierPrices' => [], + 'msrpPrice' => ['amount' => null], + ], + ] + ], + ]; + } + + /** + * Update products. + * + * @param array $data + * @return void + */ + private function updateProducts(array $data): void + { + foreach ($data as $sku => $updateData) { + $product = $this->productRepository->get($sku); + $product->addData($updateData); + $this->productRepository->save($product); + } + } + + /** + * Register the product. + * + * @param ProductInterface $product + * @return void + */ + private function registerProduct(ProductInterface $product): void + { + $this->registry->unregister('product'); + $this->registry->register('product', $product); + } + + /** + * Get product swatch options block. + * + * @return Configurable + */ + private function getProductSwatchOptionsBlock(): Configurable + { + $this->page->addHandle([ + 'default', + 'catalog_product_view', + 'catalog_product_view_type_configurable', + ]); + $this->page->getLayout()->generateXml(); + + return $this->page->getLayout()->getChildBlock('product.info.options.wrapper', 'swatch_options'); + } +} From 16a5930c45b118cd1d52e4b50e9b3cc81b4e1c51 Mon Sep 17 00:00:00 2001 From: Mykhailo Matiola Date: Thu, 30 Jan 2020 09:35:03 +0200 Subject: [PATCH 4/5] MC-30722: Layered Navigation with default product attribute "Price" --- .../_files/category_with_three_products.php | 17 ++ .../category_with_three_products_rollback.php | 9 + .../Block/Navigation/AbstractFiltersTest.php | 5 +- .../Navigation/Category/DecimalFilterTest.php | 19 -- .../Navigation/Category/PriceFilterTest.php | 212 ++++++++++++++++++ .../Navigation/Search/PriceFilterTest.php | 51 +++++ 6 files changed, 293 insertions(+), 20 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/PriceFilterTest.php create mode 100644 dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Search/PriceFilterTest.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products.php new file mode 100644 index 0000000000000..dcb184083529c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products.php @@ -0,0 +1,17 @@ +get(CategoryLinkManagementInterface::class); +$categoryLinkManagement->assignProductToCategories('simple2', [$category->getId()]); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products_rollback.php new file mode 100644 index 0000000000000..839f9d74222fa --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products_rollback.php @@ -0,0 +1,9 @@ + $stringValue) { $product = $this->productRepository->get($productSku, false, $storeId, true); + $productValue = $attribute->usesSource() + ? $attribute->getSource()->getOptionId($stringValue) + : $stringValue; $product->addData( - [$attribute->getAttributeCode() => $attribute->getSource()->getOptionId($stringValue)] + [$attribute->getAttributeCode() => $productValue] ); $this->productRepository->save($product); } diff --git a/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/DecimalFilterTest.php b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/DecimalFilterTest.php index eb4148d77b21e..f84cd5ba08259 100644 --- a/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/DecimalFilterTest.php +++ b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/DecimalFilterTest.php @@ -71,25 +71,6 @@ protected function prepareFilterItems(AbstractFilter $filter): array return $items; } - /** - * @inheritdoc - */ - protected function updateProducts( - array $products, - string $attributeCode, - int $storeId = Store::DEFAULT_STORE_ID - ): void { - $attribute = $this->attributeRepository->get($attributeCode); - - foreach ($products as $productSku => $value) { - $product = $this->productRepository->get($productSku, false, $storeId, true); - $product->addData( - [$attribute->getAttributeCode() => $value] - ); - $this->productRepository->save($product); - } - } - /** * @return array */ diff --git a/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/PriceFilterTest.php b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/PriceFilterTest.php new file mode 100644 index 0000000000000..f380e440d9e09 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/PriceFilterTest.php @@ -0,0 +1,212 @@ +scopeConfig = $this->objectManager->get(MutableScopeConfigInterface::class); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/category_with_three_products.php + * @dataProvider getFiltersDataProvider + * @param array $config + * @param array $products + * @param array $expectation + * @return void + */ + public function testGetFilters(array $config, array $products, array $expectation): void + { + $this->applyCatalogConfig($config); + $this->getCategoryFiltersAndAssert( + $products, + ['is_filterable' => AbstractFilter::ATTRIBUTE_OPTIONS_ONLY_WITH_RESULTS], + $expectation, + 'Category 999' + ); + } + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @return array + */ + public function getFiltersDataProvider(): array + { + return [ + 'auto_calculation_variation_with_small_price_difference' => [ + 'config' => ['catalog/layered_navigation/price_range_calculation' => 'auto'], + 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple2' => 50.00], + 'expectation' => [ + ['label' => '$10.00 - $19.99', 'value' => '10-20', 'count' => 1], + ['label' => '$20.00 - $29.99', 'value' => '20-30', 'count' => 1], + ['label' => '$50.00 and above', 'value' => '50-', 'count' => 1], + ], + ], + 'auto_calculation_variation_with_big_price_difference' => [ + 'config' => ['catalog/layered_navigation/price_range_calculation' => 'auto'], + 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple2' => 300.00], + 'expectation' => [ + ['label' => '$0.00 - $99.99', 'value' => '-100', 'count' => 2], + ['label' => '$300.00 and above', 'value' => '300-', 'count' => 1], + ], + ], + 'auto_calculation_variation_with_fixed_price_step' => [ + 'config' => ['catalog/layered_navigation/price_range_calculation' => 'auto'], + 'products_data' => ['simple1000' => 300.00, 'simple1001' => 400.00, 'simple2' => 500.00], + 'expectation' => [ + ['label' => '$300.00 - $399.99', 'value' => '300-400', 'count' => 1], + ['label' => '$400.00 - $499.99', 'value' => '400-500', 'count' => 1], + ['label' => '$500.00 and above', 'value' => '500-', 'count' => 1], + ], + ], + 'improved_calculation_variation_with_small_price_difference' => [ + 'config' => [ + 'catalog/layered_navigation/price_range_calculation' => 'improved', + 'catalog/layered_navigation/interval_division_limit' => 3, + ], + 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple2' => 50.00], + 'expectation' => [ + ['label' => '$0.00 - $49.99', 'value' => '-50', 'count' => 2], + ['label' => '$50.00 and above', 'value' => '50-', 'count' => 1], + ], + ], + 'improved_calculation_variation_with_big_price_difference' => [ + 'config' => [ + 'catalog/layered_navigation/price_range_calculation' => 'improved', + 'catalog/layered_navigation/interval_division_limit' => 3, + ], + 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple2' => 300.00], + 'expectation' => [ + ['label' => '$0.00 - $299.99', 'value' => '-300', 'count' => 2.0], + ['label' => '$300.00 and above', 'value' => '300-', 'count' => 1.0], + ], + ], + 'manual_calculation_with_price_step_200' => [ + 'config' => [ + 'catalog/layered_navigation/price_range_calculation' => 'manual', + 'catalog/layered_navigation/price_range_step' => 200, + ], + 'products_data' => ['simple1000' => 300.00, 'simple1001' => 300.00, 'simple2' => 500.00], + 'expectation' => [ + ['label' => '$200.00 - $399.99', 'value' => '200-400', 'count' => 2], + ['label' => '$400.00 and above', 'value' => '400-', 'count' => 1], + ], + ], + 'manual_calculation_with_price_step_10' => [ + 'config' => [ + 'catalog/layered_navigation/price_range_calculation' => 'manual', + 'catalog/layered_navigation/price_range_step' => 10, + ], + 'products_data' => ['simple1000' => 300.00, 'simple1001' => 300.00, 'simple2' => 500.00], + 'expectation' => [ + ['label' => '$300.00 - $309.99', 'value' => '300-310', 'count' => 2], + ['label' => '$500.00 and above', 'value' => '500-', 'count' => 1], + ], + ], + 'manual_calculation_with_number_of_intervals_10' => [ + 'config' => [ + 'catalog/layered_navigation/price_range_calculation' => 'manual', + 'catalog/layered_navigation/price_range_step' => 10, + 'catalog/layered_navigation/price_range_max_intervals' => 10, + ], + 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple2' => 30.00], + 'expectation' => [ + ['label' => '$10.00 - $19.99', 'value' => '10-20', 'count' => 1], + ['label' => '$20.00 - $29.99', 'value' => '20-30', 'count' => 1], + ['label' => '$30.00 and above', 'value' => '30-', 'count' => 1], + ], + ], + 'manual_calculation_with_number_of_intervals_2' => [ + 'config' => [ + 'catalog/layered_navigation/price_range_calculation' => 'manual', + 'catalog/layered_navigation/price_range_step' => 10, + 'catalog/layered_navigation/price_range_max_intervals' => 2, + ], + 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple2' => 30.00], + 'expectation' => [ + ['label' => '$10.00 - $19.99', 'value' => '10-20', 'count' => 1], + ['label' => '$20.00 and above', 'value' => '20-', 'count' => 2], + ], + ], + ]; + } + + /** + * @inheritdoc + */ + protected function getLayerType(): string + { + return Resolver::CATALOG_LAYER_CATEGORY; + } + + /** + * @inheritdoc + */ + protected function getAttributeCode(): string + { + return 'price'; + } + + /** + * @inheritdoc + */ + protected function prepareFilterItems(AbstractFilter $filter): array + { + $items = []; + /** @var Item $item */ + foreach ($filter->getItems() as $item) { + $items[] = [ + 'label' => strip_tags(__($item->getData('label'))->render()), + 'value' => $item->getData('value'), + 'count' => $item->getData('count'), + ]; + } + + return $items; + } + + /** + * Updates price filter store configuration. + * + * @param array $config + * @return void + */ + protected function applyCatalogConfig(array $config): void + { + foreach ($config as $path => $value) { + $this->scopeConfig->setValue($path, $value, StoreScope::SCOPE_STORE, ScopeInterface::SCOPE_DEFAULT); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Search/PriceFilterTest.php b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Search/PriceFilterTest.php new file mode 100644 index 0000000000000..d9ac02b2bff11 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Search/PriceFilterTest.php @@ -0,0 +1,51 @@ +applyCatalogConfig($config); + $this->getSearchFiltersAndAssert( + $products, + [ + 'is_filterable' => AbstractFilter::ATTRIBUTE_OPTIONS_ONLY_WITH_RESULTS, + 'is_filterable_in_search' => 1, + ], + $expectation + ); + } + + /** + * @inheritdoc + */ + protected function getLayerType(): string + { + return Resolver::CATALOG_LAYER_SEARCH; + } +} From 0cc7d3d3d243f09b99dce4bf49dc8e43a16ab68c Mon Sep 17 00:00:00 2001 From: Mykhailo Matiola Date: Thu, 30 Jan 2020 10:42:44 +0200 Subject: [PATCH 5/5] MC-30722: Layered Navigation with default product attribute "Price" --- .../_files/category_with_three_products.php | 25 +++++++++++++------ .../category_with_three_products_rollback.php | 21 +++++++++++++++- .../Navigation/Category/PriceFilterTest.php | 18 ++++++------- 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products.php index dcb184083529c..b29c17e392ed9 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products.php @@ -5,13 +5,24 @@ */ declare(strict_types=1); -use Magento\Catalog\Api\CategoryLinkManagementInterface; -use Magento\TestFramework\Helper\Bootstrap; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Store\Model\Store; require __DIR__ . '/category_with_different_price_products.php'; -require __DIR__ . '/second_product_simple.php'; -$objectManager = Bootstrap::getObjectManager(); -/** @var CategoryLinkManagementInterface $categoryLinkManagement */ -$categoryLinkManagement = $objectManager->get(CategoryLinkManagementInterface::class); -$categoryLinkManagement->assignProductToCategories('simple2', [$category->getId()]); +$product = $productFactory->create(); +$product->setTypeId(Type::TYPE_SIMPLE) + ->setAttributeSetId(4) + ->setStoreId(Store::DEFAULT_STORE_ID) + ->setWebsiteIds([1]) + ->setName('Simple Product2') + ->setSku('simple1002') + ->setPrice(10) + ->setWeight(1) + ->setStockData(['use_config_manage_stock' => 0]) + ->setCategoryIds([$category->getId()]) + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products_rollback.php index 839f9d74222fa..a90b9e732e827 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_three_products_rollback.php @@ -5,5 +5,24 @@ */ declare(strict_types=1); -require __DIR__ . '/second_product_simple_rollback.php'; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +$registry = $objectManager->get(Registry::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +try { + $productRepository->deleteById('simple1002'); +} catch (NoSuchEntityException $e) { + //Already deleted. +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); + require __DIR__ . '/category_with_different_price_products_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/PriceFilterTest.php b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/PriceFilterTest.php index f380e440d9e09..a82b4bf0fd00d 100644 --- a/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/PriceFilterTest.php +++ b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/PriceFilterTest.php @@ -67,7 +67,7 @@ public function getFiltersDataProvider(): array return [ 'auto_calculation_variation_with_small_price_difference' => [ 'config' => ['catalog/layered_navigation/price_range_calculation' => 'auto'], - 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple2' => 50.00], + 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple1002' => 50.00], 'expectation' => [ ['label' => '$10.00 - $19.99', 'value' => '10-20', 'count' => 1], ['label' => '$20.00 - $29.99', 'value' => '20-30', 'count' => 1], @@ -76,7 +76,7 @@ public function getFiltersDataProvider(): array ], 'auto_calculation_variation_with_big_price_difference' => [ 'config' => ['catalog/layered_navigation/price_range_calculation' => 'auto'], - 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple2' => 300.00], + 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple1002' => 300.00], 'expectation' => [ ['label' => '$0.00 - $99.99', 'value' => '-100', 'count' => 2], ['label' => '$300.00 and above', 'value' => '300-', 'count' => 1], @@ -84,7 +84,7 @@ public function getFiltersDataProvider(): array ], 'auto_calculation_variation_with_fixed_price_step' => [ 'config' => ['catalog/layered_navigation/price_range_calculation' => 'auto'], - 'products_data' => ['simple1000' => 300.00, 'simple1001' => 400.00, 'simple2' => 500.00], + 'products_data' => ['simple1000' => 300.00, 'simple1001' => 400.00, 'simple1002' => 500.00], 'expectation' => [ ['label' => '$300.00 - $399.99', 'value' => '300-400', 'count' => 1], ['label' => '$400.00 - $499.99', 'value' => '400-500', 'count' => 1], @@ -96,7 +96,7 @@ public function getFiltersDataProvider(): array 'catalog/layered_navigation/price_range_calculation' => 'improved', 'catalog/layered_navigation/interval_division_limit' => 3, ], - 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple2' => 50.00], + 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple1002' => 50.00], 'expectation' => [ ['label' => '$0.00 - $49.99', 'value' => '-50', 'count' => 2], ['label' => '$50.00 and above', 'value' => '50-', 'count' => 1], @@ -107,7 +107,7 @@ public function getFiltersDataProvider(): array 'catalog/layered_navigation/price_range_calculation' => 'improved', 'catalog/layered_navigation/interval_division_limit' => 3, ], - 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple2' => 300.00], + 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple1002' => 300.00], 'expectation' => [ ['label' => '$0.00 - $299.99', 'value' => '-300', 'count' => 2.0], ['label' => '$300.00 and above', 'value' => '300-', 'count' => 1.0], @@ -118,7 +118,7 @@ public function getFiltersDataProvider(): array 'catalog/layered_navigation/price_range_calculation' => 'manual', 'catalog/layered_navigation/price_range_step' => 200, ], - 'products_data' => ['simple1000' => 300.00, 'simple1001' => 300.00, 'simple2' => 500.00], + 'products_data' => ['simple1000' => 300.00, 'simple1001' => 300.00, 'simple1002' => 500.00], 'expectation' => [ ['label' => '$200.00 - $399.99', 'value' => '200-400', 'count' => 2], ['label' => '$400.00 and above', 'value' => '400-', 'count' => 1], @@ -129,7 +129,7 @@ public function getFiltersDataProvider(): array 'catalog/layered_navigation/price_range_calculation' => 'manual', 'catalog/layered_navigation/price_range_step' => 10, ], - 'products_data' => ['simple1000' => 300.00, 'simple1001' => 300.00, 'simple2' => 500.00], + 'products_data' => ['simple1000' => 300.00, 'simple1001' => 300.00, 'simple1002' => 500.00], 'expectation' => [ ['label' => '$300.00 - $309.99', 'value' => '300-310', 'count' => 2], ['label' => '$500.00 and above', 'value' => '500-', 'count' => 1], @@ -141,7 +141,7 @@ public function getFiltersDataProvider(): array 'catalog/layered_navigation/price_range_step' => 10, 'catalog/layered_navigation/price_range_max_intervals' => 10, ], - 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple2' => 30.00], + 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple1002' => 30.00], 'expectation' => [ ['label' => '$10.00 - $19.99', 'value' => '10-20', 'count' => 1], ['label' => '$20.00 - $29.99', 'value' => '20-30', 'count' => 1], @@ -154,7 +154,7 @@ public function getFiltersDataProvider(): array 'catalog/layered_navigation/price_range_step' => 10, 'catalog/layered_navigation/price_range_max_intervals' => 2, ], - 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple2' => 30.00], + 'products_data' => ['simple1000' => 10.00, 'simple1001' => 20.00, 'simple1002' => 30.00], 'expectation' => [ ['label' => '$10.00 - $19.99', 'value' => '10-20', 'count' => 1], ['label' => '$20.00 and above', 'value' => '20-', 'count' => 2],