From 2769f7c8d8caa58fab0f1e6c6f27879859d1b573 Mon Sep 17 00:00:00 2001 From: Jens Scherbl Date: Sun, 22 Sep 2019 15:13:39 +0200 Subject: [PATCH 001/176] Allows additional payment checks in payment method list --- app/code/Magento/Payment/Model/MethodList.php | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Payment/Model/MethodList.php b/app/code/Magento/Payment/Model/MethodList.php index 5a426d72e4cfd..e5b961f87e426 100644 --- a/app/code/Magento/Payment/Model/MethodList.php +++ b/app/code/Magento/Payment/Model/MethodList.php @@ -39,16 +39,24 @@ class MethodList */ private $paymentMethodInstanceFactory; + /** + * @var array + */ + private $additionalChecks; + /** * @param \Magento\Payment\Helper\Data $paymentHelper - * @param Checks\SpecificationFactory $specificationFactory + * @param Checks\SpecificationFactory $specificationFactory + * @param array $additionalChecks */ public function __construct( \Magento\Payment\Helper\Data $paymentHelper, - \Magento\Payment\Model\Checks\SpecificationFactory $specificationFactory + \Magento\Payment\Model\Checks\SpecificationFactory $specificationFactory, + array $additionalChecks = [] ) { $this->paymentHelper = $paymentHelper; $this->methodSpecificationFactory = $specificationFactory; + $this->additionalChecks = $additionalChecks; } /** @@ -80,12 +88,15 @@ public function getAvailableMethods(\Magento\Quote\Api\Data\CartInterface $quote protected function _canUseMethod($method, \Magento\Quote\Api\Data\CartInterface $quote) { return $this->methodSpecificationFactory->create( - [ - AbstractMethod::CHECK_USE_CHECKOUT, - AbstractMethod::CHECK_USE_FOR_COUNTRY, - AbstractMethod::CHECK_USE_FOR_CURRENCY, - AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX, - ] + array_merge( + [ + AbstractMethod::CHECK_USE_CHECKOUT, + AbstractMethod::CHECK_USE_FOR_COUNTRY, + AbstractMethod::CHECK_USE_FOR_CURRENCY, + AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX, + ], + $this->additionalChecks + ) )->isApplicable( $method, $quote From 882868a5c33712691a79f62dfdf05459427cc31d Mon Sep 17 00:00:00 2001 From: Jens Scherbl Date: Sun, 22 Sep 2019 16:34:48 +0200 Subject: [PATCH 002/176] Fixes unrelated code style issues --- app/code/Magento/Payment/Model/MethodList.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Payment/Model/MethodList.php b/app/code/Magento/Payment/Model/MethodList.php index e5b961f87e426..746306cbd0bbf 100644 --- a/app/code/Magento/Payment/Model/MethodList.php +++ b/app/code/Magento/Payment/Model/MethodList.php @@ -60,6 +60,8 @@ public function __construct( } /** + * Returns all available payment methods for the given quote. + * * @param \Magento\Quote\Api\Data\CartInterface $quote * @return \Magento\Payment\Model\MethodInterface[] */ From 504dd9144be469897baf834e58ae057537a07288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 3 Oct 2019 15:55:56 +0200 Subject: [PATCH 003/176] Issue #24842: Unable to delete custom option file in admin order create Fix inputBox selector to match html structure --- .../catalog/product/composite/fieldset/options/type/file.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml index da0b3b36d561e..89d005a178fac 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml @@ -22,7 +22,7 @@ require(['prototype'], function(){ initializeFile: function(inputBox) { this.inputFile = inputBox.select('input[name=""]')[0]; this.inputFileAction = inputBox.select('input[name=""]')[0]; - this.fileNameBox = inputBox.up('dd').select('.')[0]; + this.fileNameBox = inputBox.up('div').select('.')[0]; }, toggleFileChange: function(inputBox) { From 6b3bd36cb4fda9a9f162f123932c6b9f93291ae9 Mon Sep 17 00:00:00 2001 From: "vishalverma.magento279" Date: Wed, 23 Oct 2019 21:02:10 +0530 Subject: [PATCH 004/176] #25245 fixed --- app/code/Magento/Search/Block/Term.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Search/Block/Term.php b/app/code/Magento/Search/Block/Term.php index b27ef6b01fda2..6dab372df3edc 100644 --- a/app/code/Magento/Search/Block/Term.php +++ b/app/code/Magento/Search/Block/Term.php @@ -99,6 +99,9 @@ protected function _loadTerms() $temp[$term->getQueryText()] = $term; $termKeys[] = $term->getQueryText(); } + if (empty($termKeys)) { + return $this; + } natcasesort($termKeys); foreach ($termKeys as $termKey) { From c5eb6233e693c9ae7178aff6d1580d372e40c059 Mon Sep 17 00:00:00 2001 From: Nikita Sarychev Date: Tue, 22 Oct 2019 20:22:26 +0300 Subject: [PATCH 005/176] upgrade method delete by ids to inject array skus --- .../Api/CategoryLinkRepositoryInterface.php | 15 +++++- .../Catalog/Model/CategoryLinkManagement.php | 2 +- .../Catalog/Model/CategoryLinkRepository.php | 46 ++++++++++++++++++- .../Unit/Model/CategoryLinkRepositoryTest.php | 4 +- app/code/Magento/Catalog/etc/webapi.xml | 2 +- 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php b/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php index a65355c690923..b4f5b6472661a 100644 --- a/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php @@ -36,6 +36,19 @@ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $pro */ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink); + /** + * Remove the product assignment from the category by category id and array of sku + * + * @param int $categoryId + * @param array $sku + * @return bool will returned True if products successfully deleted + * + * @throws \Magento\Framework\Exception\CouldNotSaveException + * @throws \Magento\Framework\Exception\StateException + * @throws \Magento\Framework\Exception\InputException + */ + public function deleteByIds($categoryId, $sku); + /** * Remove the product assignment from the category by category id and sku * @@ -47,5 +60,5 @@ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $p * @throws \Magento\Framework\Exception\StateException * @throws \Magento\Framework\Exception\InputException */ - public function deleteByIds($categoryId, $sku); + public function deleteById($categoryId, $sku); } diff --git a/app/code/Magento/Catalog/Model/CategoryLinkManagement.php b/app/code/Magento/Catalog/Model/CategoryLinkManagement.php index 8966848a6d036..103cc0970603b 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkManagement.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkManagement.php @@ -93,7 +93,7 @@ public function assignProductToCategories($productSku, array $categoryIds) $product = $this->getProductRepository()->get($productSku); $assignedCategories = $this->getProductResource()->getCategoryIds($product); foreach (array_diff($assignedCategories, $categoryIds) as $categoryId) { - $this->getCategoryLinkRepository()->deleteByIds($categoryId, $productSku); + $this->getCategoryLinkRepository()->deleteById($categoryId, $productSku); } foreach (array_diff($categoryIds, $assignedCategories) as $categoryId) { diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index fb0ea680569a8..b7d7d09a9a0e6 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -21,16 +21,24 @@ class CategoryLinkRepository implements \Magento\Catalog\Api\CategoryLinkReposit */ protected $productRepository; + /** + * @var \Magento\Catalog\Model\ResourceModel\Product + */ + private $productResource; + /** * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository + * @param \Magento\Catalog\Model\ResourceModel\Product $productResource */ public function __construct( \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository, - \Magento\Catalog\Api\ProductRepositoryInterface $productRepository + \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, + \Magento\Catalog\Model\ResourceModel\Product $productResource ) { $this->categoryRepository = $categoryRepository; $this->productRepository = $productRepository; + $this->productResource = $productResource; } /** @@ -64,13 +72,47 @@ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $pro */ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink) { - return $this->deleteByIds($productLink->getCategoryId(), $productLink->getSku()); + return $this->deleteById($productLink->getCategoryId(), $productLink->getSku()); } /** * {@inheritdoc} */ public function deleteByIds($categoryId, $sku) + { + $category = $this->categoryRepository->get($categoryId); + $products = $this->productResource->getProductsIdsBySkus($sku); + + $productPositions = $category->getProductsPosition(); + + foreach ($products as $productSku => $productId) { + if (isset($productPositions[$productId])) { + unset($productPositions[$productId]); + } + } + + $category->setPostedProducts($productPositions); + try { + $category->save(); + } catch (\Exception $e) { + throw new CouldNotSaveException( + __( + 'Could not save products "%products" to category %category', + [ + "products" => implode(',', $sku), + "category" => $category->getId() + ] + ), + $e + ); + } + return true; + } + + /** + * {@inheritDoc} + */ + public function deleteById($categoryId, $sku) { $category = $this->categoryRepository->get($categoryId); $product = $this->productRepository->get($sku); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index b42262f1f0384..1af8669bbc9fb 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -113,7 +113,7 @@ public function testDeleteByIds() $productMock->expects($this->once())->method('getId')->willReturn($productId); $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('save'); - $this->assertTrue($this->model->deleteByIds($categoryId, $productSku)); + $this->assertTrue($this->model->deleteById($categoryId, $productSku)); } /** @@ -140,7 +140,7 @@ public function testDeleteByIdsWithCouldNotSaveException() $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('getId')->willReturn($categoryId); $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); - $this->model->deleteByIds($categoryId, $productSku); + $this->model->deleteById($categoryId, $productSku); } /** diff --git a/app/code/Magento/Catalog/etc/webapi.xml b/app/code/Magento/Catalog/etc/webapi.xml index 3f82175ab02eb..a001aed3c7e5f 100644 --- a/app/code/Magento/Catalog/etc/webapi.xml +++ b/app/code/Magento/Catalog/etc/webapi.xml @@ -457,7 +457,7 @@ - + From 3558184bca391cf790aebaf20d3b61bf2b90b842 Mon Sep 17 00:00:00 2001 From: Nikita Sarychev Date: Wed, 23 Oct 2019 23:49:18 +0300 Subject: [PATCH 006/176] refactor getByIds method and use object manager into constructor class --- .../Api/CategoryLinkRepositoryInterface.php | 17 +------ .../Catalog/Model/CategoryLinkManagement.php | 2 +- .../Catalog/Model/CategoryLinkRepository.php | 50 ++++--------------- .../Unit/Model/CategoryLinkRepositoryTest.php | 4 +- app/code/Magento/Catalog/etc/webapi.xml | 2 +- 5 files changed, 16 insertions(+), 59 deletions(-) diff --git a/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php b/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php index b4f5b6472661a..2d14f11d05d31 100644 --- a/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php @@ -37,10 +37,10 @@ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $pro public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink); /** - * Remove the product assignment from the category by category id and array of sku + * Remove the product assignment from the category by category id and array or string of sku * * @param int $categoryId - * @param array $sku + * @param string|array $sku * @return bool will returned True if products successfully deleted * * @throws \Magento\Framework\Exception\CouldNotSaveException @@ -48,17 +48,4 @@ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $p * @throws \Magento\Framework\Exception\InputException */ public function deleteByIds($categoryId, $sku); - - /** - * Remove the product assignment from the category by category id and sku - * - * @param int $categoryId - * @param string $sku - * @return bool will returned True if products successfully deleted - * - * @throws \Magento\Framework\Exception\CouldNotSaveException - * @throws \Magento\Framework\Exception\StateException - * @throws \Magento\Framework\Exception\InputException - */ - public function deleteById($categoryId, $sku); } diff --git a/app/code/Magento/Catalog/Model/CategoryLinkManagement.php b/app/code/Magento/Catalog/Model/CategoryLinkManagement.php index 103cc0970603b..8966848a6d036 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkManagement.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkManagement.php @@ -93,7 +93,7 @@ public function assignProductToCategories($productSku, array $categoryIds) $product = $this->getProductRepository()->get($productSku); $assignedCategories = $this->getProductResource()->getCategoryIds($product); foreach (array_diff($assignedCategories, $categoryIds) as $categoryId) { - $this->getCategoryLinkRepository()->deleteById($categoryId, $productSku); + $this->getCategoryLinkRepository()->deleteByIds($categoryId, $productSku); } foreach (array_diff($categoryIds, $assignedCategories) as $categoryId) { diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index b7d7d09a9a0e6..580fe288b1ee7 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -29,16 +29,14 @@ class CategoryLinkRepository implements \Magento\Catalog\Api\CategoryLinkReposit /** * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository - * @param \Magento\Catalog\Model\ResourceModel\Product $productResource */ public function __construct( \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository, - \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, - \Magento\Catalog\Model\ResourceModel\Product $productResource + \Magento\Catalog\Api\ProductRepositoryInterface $productRepository ) { $this->categoryRepository = $categoryRepository; $this->productRepository = $productRepository; - $this->productResource = $productResource; + $this->productResource = \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Catalog\Model\ResourceModel\Product::class); } /** @@ -72,7 +70,7 @@ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $pro */ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink) { - return $this->deleteById($productLink->getCategoryId(), $productLink->getSku()); + return $this->deleteByIds($productLink->getCategoryId(), $productLink->getSku()); } /** @@ -80,9 +78,16 @@ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $p */ public function deleteByIds($categoryId, $sku) { + if (!is_array($sku)) { + $sku = [$sku]; + } $category = $this->categoryRepository->get($categoryId); $products = $this->productResource->getProductsIdsBySkus($sku); + if (!$products) { + throw new InputException(__("The category doesn't contain the specified products.")); + } + $productPositions = $category->getProductsPosition(); foreach ($products as $productSku => $productId) { @@ -108,39 +113,4 @@ public function deleteByIds($categoryId, $sku) } return true; } - - /** - * {@inheritDoc} - */ - public function deleteById($categoryId, $sku) - { - $category = $this->categoryRepository->get($categoryId); - $product = $this->productRepository->get($sku); - $productPositions = $category->getProductsPosition(); - - $productID = $product->getId(); - if (!isset($productPositions[$productID])) { - throw new InputException(__("The category doesn't contain the specified product.")); - } - $backupPosition = $productPositions[$productID]; - unset($productPositions[$productID]); - - $category->setPostedProducts($productPositions); - try { - $category->save(); - } catch (\Exception $e) { - throw new CouldNotSaveException( - __( - 'Could not save product "%product" with position %position to category %category', - [ - "product" => $product->getId(), - "position" => $backupPosition, - "category" => $category->getId() - ] - ), - $e - ); - } - return true; - } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index 1af8669bbc9fb..b42262f1f0384 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -113,7 +113,7 @@ public function testDeleteByIds() $productMock->expects($this->once())->method('getId')->willReturn($productId); $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('save'); - $this->assertTrue($this->model->deleteById($categoryId, $productSku)); + $this->assertTrue($this->model->deleteByIds($categoryId, $productSku)); } /** @@ -140,7 +140,7 @@ public function testDeleteByIdsWithCouldNotSaveException() $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('getId')->willReturn($categoryId); $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); - $this->model->deleteById($categoryId, $productSku); + $this->model->deleteByIds($categoryId, $productSku); } /** diff --git a/app/code/Magento/Catalog/etc/webapi.xml b/app/code/Magento/Catalog/etc/webapi.xml index a001aed3c7e5f..3f82175ab02eb 100644 --- a/app/code/Magento/Catalog/etc/webapi.xml +++ b/app/code/Magento/Catalog/etc/webapi.xml @@ -457,7 +457,7 @@ - + From 98e06135d2eed049ed693bffe9fe71049e7615d3 Mon Sep 17 00:00:00 2001 From: Nikita Sarychev Date: Sat, 26 Oct 2019 17:08:33 +0300 Subject: [PATCH 007/176] add constructor parameter --- app/code/Magento/Catalog/Model/CategoryLinkRepository.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index 580fe288b1ee7..a109a5bf6582e 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -29,14 +29,16 @@ class CategoryLinkRepository implements \Magento\Catalog\Api\CategoryLinkReposit /** * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository + * @param \Magento\Catalog\Model\ResourceModel\Product $productResource */ public function __construct( \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository, - \Magento\Catalog\Api\ProductRepositoryInterface $productRepository + \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, + \Magento\Catalog\Model\ResourceModel\Product $productResource = null ) { $this->categoryRepository = $categoryRepository; $this->productRepository = $productRepository; - $this->productResource = \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Catalog\Model\ResourceModel\Product::class); + $this->productResource = $productResource ?? \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Catalog\Model\ResourceModel\Product::class); } /** From 49809a7af6493851d88e858cf5b7dcead56ec38e Mon Sep 17 00:00:00 2001 From: "Zeno F. Pensky" Date: Wed, 6 Nov 2019 11:51:57 +0100 Subject: [PATCH 008/176] Update composer dependency to fix Redis Key Expiery I experienced a situation on production system with 15 stores and organic trafic, where the redis cache grows to over 30GB. It looks like magento is putting a lot of entries into the redis cache without any expiary. I needed to limit redis memory to prevent the server from dying, not how it should be. This had some performance influences. For this issue there is actualy a fix in place which just need to be pulled in. This commit is do this. With the fix in place the redis stabalized at arround 3GB. Over all performance is was also increased with this change. Referces: [1] https://github.com/colinmollenhour/Cm_Cache_Backend_Redis/commit/bc63e7226a525fe95865c756aad0037f0d57d03c [2] https://github.com/magento/magento2/commit/32058c748731348e7d38cffa7a6c56113e17b3d8 [3] https://github.com/magento/magento2/issues/25487 --- composer.json | 2 +- composer.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 4b0ad8a67fedb..0995bf862e7b8 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "lib-libxml": "*", "braintree/braintree_php": "3.35.0", "colinmollenhour/cache-backend-file": "~1.4.1", - "colinmollenhour/cache-backend-redis": "1.10.6", + "colinmollenhour/cache-backend-redis": "1.11.0", "colinmollenhour/credis": "1.10.0", "colinmollenhour/php-redis-session-abstract": "~1.4.0", "composer/composer": "^1.6", diff --git a/composer.lock b/composer.lock index 49177a9159559..ccf1c0a87eec3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2e70a2d627872624e03d089cd7e51618", + "content-hash": "87b9056fd6a41a41d36ab8e1943d3f7a", "packages": [ { "name": "braintree/braintree_php", @@ -88,16 +88,16 @@ }, { "name": "colinmollenhour/cache-backend-redis", - "version": "1.10.6", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/colinmollenhour/Cm_Cache_Backend_Redis.git", - "reference": "cc941a5f4cc017e11d3eab9061811ba9583ed6bf" + "reference": "389fb68de15660e39b055d149d31f3708b5d6cbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/colinmollenhour/Cm_Cache_Backend_Redis/zipball/cc941a5f4cc017e11d3eab9061811ba9583ed6bf", - "reference": "cc941a5f4cc017e11d3eab9061811ba9583ed6bf", + "url": "https://api.github.com/repos/colinmollenhour/Cm_Cache_Backend_Redis/zipball/389fb68de15660e39b055d149d31f3708b5d6cbc", + "reference": "389fb68de15660e39b055d149d31f3708b5d6cbc", "shasum": "" }, "require": { @@ -120,7 +120,7 @@ ], "description": "Zend_Cache backend using Redis with full support for tags.", "homepage": "https://github.com/colinmollenhour/Cm_Cache_Backend_Redis", - "time": "2018-09-24T16:02:07+00:00" + "time": "2019-03-03T04:04:49+00:00" }, { "name": "colinmollenhour/credis", From 02edd9d1196659e6204c7839d400fbb4542b48c2 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Wed, 20 Nov 2019 12:47:47 +0200 Subject: [PATCH 009/176] magento/magento2#25488: Composer update. --- composer.lock | 132 +++++++++++++++++++++++++------------------------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/composer.lock b/composer.lock index 373047ee14d6b..2f7d1daebed7f 100644 --- a/composer.lock +++ b/composer.lock @@ -1,11 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - - "content-hash": "e75fa994f056960e832018efd6af5a40", + "content-hash": "55df86da292527ebe5be6743c30ed808", "packages": [ { "name": "braintree/braintree_php", @@ -531,6 +530,7 @@ ], "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", "homepage": "https://github.com/container-interop/container-interop", + "abandoned": "psr/container", "time": "2017-02-14T19:40:03+00:00" }, { @@ -1112,16 +1112,16 @@ }, { "name": "monolog/monolog", - "version": "1.25.1", + "version": "1.25.2", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "70e65a5470a42cfec1a7da00d30edb6e617e8dcf" + "reference": "d5e2fb341cb44f7e2ab639d12a1e5901091ec287" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/70e65a5470a42cfec1a7da00d30edb6e617e8dcf", - "reference": "70e65a5470a42cfec1a7da00d30edb6e617e8dcf", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/d5e2fb341cb44f7e2ab639d12a1e5901091ec287", + "reference": "d5e2fb341cb44f7e2ab639d12a1e5901091ec287", "shasum": "" }, "require": { @@ -1186,7 +1186,7 @@ "logging", "psr-3" ], - "time": "2019-09-06T13:49:17+00:00" + "time": "2019-11-13T10:00:05+00:00" }, { "name": "paragonie/random_compat", @@ -1391,39 +1391,36 @@ }, { "name": "php-amqplib/php-amqplib", - "version": "v2.7.3", + "version": "v2.10.1", "source": { "type": "git", "url": "https://github.com/php-amqplib/php-amqplib.git", - "reference": "a8ba54bd35b973fc6861e4c2e105f71e9e95f43f" + "reference": "6e2b2501e021e994fb64429e5a78118f83b5c200" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/a8ba54bd35b973fc6861e4c2e105f71e9e95f43f", - "reference": "a8ba54bd35b973fc6861e4c2e105f71e9e95f43f", + "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/6e2b2501e021e994fb64429e5a78118f83b5c200", + "reference": "6e2b2501e021e994fb64429e5a78118f83b5c200", "shasum": "" }, "require": { "ext-bcmath": "*", - "ext-mbstring": "*", - "php": ">=5.3.0" + "ext-sockets": "*", + "php": ">=5.6" }, "replace": { "videlalvaro/php-amqplib": "self.version" }, "require-dev": { - "phpdocumentor/phpdocumentor": "^2.9", - "phpunit/phpunit": "^4.8", - "scrutinizer/ocular": "^1.1", + "ext-curl": "*", + "nategood/httpful": "^0.2.20", + "phpunit/phpunit": "^5.7|^6.5|^7.0", "squizlabs/php_codesniffer": "^2.5" }, - "suggest": { - "ext-sockets": "Use AMQPSocketConnection" - }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.10-dev" } }, "autoload": { @@ -1449,6 +1446,11 @@ "name": "Raúl Araya", "email": "nubeiro@gmail.com", "role": "Maintainer" + }, + { + "name": "Luke Bakken", + "email": "luke@bakken.io", + "role": "Maintainer" } ], "description": "Formerly videlalvaro/php-amqplib. This library is a pure PHP implementation of the AMQP protocol. It's been tested against RabbitMQ.", @@ -1458,7 +1460,7 @@ "queue", "rabbitmq" ], - "time": "2018-04-30T03:54:54+00:00" + "time": "2019-10-10T13:23:40+00:00" }, { "name": "phpseclib/mcrypt_compat", @@ -2081,7 +2083,7 @@ }, { "name": "symfony/css-selector", - "version": "v4.3.7", + "version": "v4.3.8", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -2134,7 +2136,7 @@ }, { "name": "symfony/event-dispatcher", - "version": "v4.3.7", + "version": "v4.3.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -2262,7 +2264,7 @@ }, { "name": "symfony/filesystem", - "version": "v4.3.7", + "version": "v4.3.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", @@ -2312,7 +2314,7 @@ }, { "name": "symfony/finder", - "version": "v4.3.7", + "version": "v4.3.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -2478,7 +2480,7 @@ }, { "name": "symfony/process", - "version": "v4.3.7", + "version": "v4.3.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", @@ -3642,19 +3644,20 @@ }, { "name": "zendframework/zend-i18n", - "version": "2.9.2", + "version": "2.10.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-i18n.git", - "reference": "e17a54b3aee333ab156958f570cde630acee8b07" + "reference": "561a815ce32c86b0f1de11135477e637926d56b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-i18n/zipball/e17a54b3aee333ab156958f570cde630acee8b07", - "reference": "e17a54b3aee333ab156958f570cde630acee8b07", + "url": "https://api.github.com/repos/zendframework/zend-i18n/zipball/561a815ce32c86b0f1de11135477e637926d56b6", + "reference": "561a815ce32c86b0f1de11135477e637926d56b6", "shasum": "" }, "require": { + "ext-intl": "*", "php": "^5.6 || ^7.0", "zendframework/zend-stdlib": "^2.7 || ^3.0" }, @@ -3670,7 +3673,6 @@ "zendframework/zend-view": "^2.6.3" }, "suggest": { - "ext-intl": "Required for most features of Zend\\I18n; included in default builds of PHP", "zendframework/zend-cache": "Zend\\Cache component", "zendframework/zend-config": "Zend\\Config component", "zendframework/zend-eventmanager": "You should install this package to use the events in the translator", @@ -3683,8 +3685,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.9.x-dev", - "dev-develop": "2.10.x-dev" + "dev-master": "2.10.x-dev", + "dev-develop": "2.11.x-dev" }, "zf": { "component": "Zend\\I18n", @@ -3706,7 +3708,7 @@ "i18n", "zf" ], - "time": "2019-09-30T12:04:37+00:00" + "time": "2019-11-18T20:31:29+00:00" }, { "name": "zendframework/zend-inputfilter", @@ -6160,16 +6162,16 @@ }, { "name": "doctrine/cache", - "version": "1.9.0", + "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "c15dcd24b756f9e52ea7c3ae8227354f3628f11a" + "reference": "89a5c76c39c292f7798f964ab3c836c3f8192a55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/c15dcd24b756f9e52ea7c3ae8227354f3628f11a", - "reference": "c15dcd24b756f9e52ea7c3ae8227354f3628f11a", + "url": "https://api.github.com/repos/doctrine/cache/zipball/89a5c76c39c292f7798f964ab3c836c3f8192a55", + "reference": "89a5c76c39c292f7798f964ab3c836c3f8192a55", "shasum": "" }, "require": { @@ -6239,7 +6241,7 @@ "riak", "xcache" ], - "time": "2019-11-11T10:31:52+00:00" + "time": "2019-11-15T14:31:57+00:00" }, { "name": "doctrine/inflector", @@ -6616,16 +6618,16 @@ }, { "name": "fzaninotto/faker", - "version": "v1.8.0", + "version": "v1.9.0", "source": { "type": "git", "url": "https://github.com/fzaninotto/Faker.git", - "reference": "f72816b43e74063c8b10357394b6bba8cb1c10de" + "reference": "27a216cbe72327b2d6369fab721a5843be71e57d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/f72816b43e74063c8b10357394b6bba8cb1c10de", - "reference": "f72816b43e74063c8b10357394b6bba8cb1c10de", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/27a216cbe72327b2d6369fab721a5843be71e57d", + "reference": "27a216cbe72327b2d6369fab721a5843be71e57d", "shasum": "" }, "require": { @@ -6634,13 +6636,11 @@ "require-dev": { "ext-intl": "*", "phpunit/phpunit": "^4.8.35 || ^5.7", - "squizlabs/php_codesniffer": "^1.5" + "squizlabs/php_codesniffer": "^2.9.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } + "branch-alias": [] }, "autoload": { "psr-4": { @@ -6662,7 +6662,7 @@ "faker", "fixtures" ], - "time": "2018-07-12T10:23:15+00:00" + "time": "2019-11-14T13:13:06+00:00" }, { "name": "grasmash/expander", @@ -7668,16 +7668,16 @@ }, { "name": "phpcompatibility/php-compatibility", - "version": "9.3.3", + "version": "9.3.4", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", - "reference": "1af08ca3861048a8bfb39d0405d0ac3e50ba2696" + "reference": "1f37659196e4f3113ea506a7efba201c52303bf1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/1af08ca3861048a8bfb39d0405d0ac3e50ba2696", - "reference": "1af08ca3861048a8bfb39d0405d0ac3e50ba2696", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/1f37659196e4f3113ea506a7efba201c52303bf1", + "reference": "1f37659196e4f3113ea506a7efba201c52303bf1", "shasum": "" }, "require": { @@ -7722,7 +7722,7 @@ "phpcs", "standards" ], - "time": "2019-11-11T03:25:23+00:00" + "time": "2019-11-15T04:12:02+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -9243,7 +9243,7 @@ }, { "name": "symfony/browser-kit", - "version": "v4.3.7", + "version": "v4.3.8", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", @@ -9302,7 +9302,7 @@ }, { "name": "symfony/config", - "version": "v4.3.7", + "version": "v4.3.8", "source": { "type": "git", "url": "https://github.com/symfony/config.git", @@ -9366,7 +9366,7 @@ }, { "name": "symfony/dependency-injection", - "version": "v4.3.7", + "version": "v4.3.8", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", @@ -9439,7 +9439,7 @@ }, { "name": "symfony/dom-crawler", - "version": "v4.3.7", + "version": "v4.3.8", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", @@ -9500,16 +9500,16 @@ }, { "name": "symfony/http-foundation", - "version": "v2.8.50", + "version": "v2.8.52", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "746f8d3638bf46ee8b202e62f2b214c3d61fb06a" + "reference": "3929d9fe8148d17819ad0178c748b8d339420709" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/746f8d3638bf46ee8b202e62f2b214c3d61fb06a", - "reference": "746f8d3638bf46ee8b202e62f2b214c3d61fb06a", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3929d9fe8148d17819ad0178c748b8d339420709", + "reference": "3929d9fe8148d17819ad0178c748b8d339420709", "shasum": "" }, "require": { @@ -9551,11 +9551,11 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2019-04-16T10:00:53+00:00" + "time": "2019-11-12T12:34:41+00:00" }, { "name": "symfony/options-resolver", - "version": "v4.3.7", + "version": "v4.3.8", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", @@ -9895,7 +9895,7 @@ }, { "name": "symfony/stopwatch", - "version": "v4.3.7", + "version": "v4.3.8", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -9945,7 +9945,7 @@ }, { "name": "symfony/yaml", - "version": "v4.3.7", + "version": "v4.3.8", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", From 7885d47cc37ecdc7d8845e652387bc630677f783 Mon Sep 17 00:00:00 2001 From: Nikita Sarychev Date: Sun, 1 Dec 2019 15:24:53 +0300 Subject: [PATCH 010/176] return changes and add additional interface for CategoryLinkRepository --- .../Api/CategoryLinkRepositoryInterface.php | 4 +- ...egoryListRepositoryAdditionalInterface.php | 26 +++++++++++ .../Catalog/Model/CategoryLinkRepository.php | 45 ++++++++++++++++--- 3 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 app/code/Magento/Catalog/Api/CategoryListRepositoryAdditionalInterface.php diff --git a/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php b/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php index 2d14f11d05d31..a65355c690923 100644 --- a/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php @@ -37,10 +37,10 @@ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $pro public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink); /** - * Remove the product assignment from the category by category id and array or string of sku + * Remove the product assignment from the category by category id and sku * * @param int $categoryId - * @param string|array $sku + * @param string $sku * @return bool will returned True if products successfully deleted * * @throws \Magento\Framework\Exception\CouldNotSaveException diff --git a/app/code/Magento/Catalog/Api/CategoryListRepositoryAdditionalInterface.php b/app/code/Magento/Catalog/Api/CategoryListRepositoryAdditionalInterface.php new file mode 100644 index 0000000000000..a02246a8964c6 --- /dev/null +++ b/app/code/Magento/Catalog/Api/CategoryListRepositoryAdditionalInterface.php @@ -0,0 +1,26 @@ +categoryRepository->get($categoryId); + $product = $this->productRepository->get($sku); + $productPositions = $category->getProductsPosition(); + + $productID = $product->getId(); + if (!isset($productPositions[$productID])) { + throw new InputException(__("The category doesn't contain the specified product.")); } + $backupPosition = $productPositions[$productID]; + unset($productPositions[$productID]); + + $category->setPostedProducts($productPositions); + try { + $category->save(); + } catch (\Exception $e) { + throw new CouldNotSaveException( + __( + 'Could not save product "%product" with position %position to category %category', + [ + "product" => $product->getId(), + "position" => $backupPosition, + "category" => $category->getId() + ] + ), + $e + ); + } + return true; + } + + /** + * {@inheritDoc} + */ + public function deleteBySkus($categoryId, array $productSkuList) + { $category = $this->categoryRepository->get($categoryId); - $products = $this->productResource->getProductsIdsBySkus($sku); + $products = $this->productResource->getProductsIdsBySkus($productSkuList); if (!$products) { throw new InputException(__("The category doesn't contain the specified products.")); @@ -99,6 +132,7 @@ public function deleteByIds($categoryId, $sku) } $category->setPostedProducts($productPositions); + try { $category->save(); } catch (\Exception $e) { @@ -106,13 +140,14 @@ public function deleteByIds($categoryId, $sku) __( 'Could not save products "%products" to category %category', [ - "products" => implode(',', $sku), + "products" => implode(',', $productSkuList), "category" => $category->getId() ] ), $e ); } + return true; } } From c50bb9ad55370382274ed2a93b6e6e82b065c32f Mon Sep 17 00:00:00 2001 From: Nikita Sarychev Date: Mon, 2 Dec 2019 20:05:07 +0300 Subject: [PATCH 011/176] change interface name --- ...tionalInterface.php => CategoryListDeleteBySkuInterface.php} | 2 +- app/code/Magento/Catalog/Model/CategoryLinkRepository.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename app/code/Magento/Catalog/Api/{CategoryListRepositoryAdditionalInterface.php => CategoryListDeleteBySkuInterface.php} (90%) diff --git a/app/code/Magento/Catalog/Api/CategoryListRepositoryAdditionalInterface.php b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php similarity index 90% rename from app/code/Magento/Catalog/Api/CategoryListRepositoryAdditionalInterface.php rename to app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php index a02246a8964c6..357da2b638802 100644 --- a/app/code/Magento/Catalog/Api/CategoryListRepositoryAdditionalInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php @@ -10,7 +10,7 @@ * @api * @since 100.0.2 */ -interface CategoryListRepositoryAdditionalInterface +interface CategoryListDeleteBySkuInterface { /** * delete by skus list diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index ef6e8dd8da29c..8e430addb91bb 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -10,7 +10,7 @@ use Magento\Framework\Exception\CouldNotSaveException; class CategoryLinkRepository implements \Magento\Catalog\Api\CategoryLinkRepositoryInterface, - \Magento\Catalog\Api\CategoryListRepositoryAdditionalInterface + \Magento\Catalog\Api\CategoryListDeleteBySkuInterface { /** * @var CategoryRepository From 00db6429d580eec4b7979f361c51dc5edfeec782 Mon Sep 17 00:00:00 2001 From: Nikita Sarychev Date: Sun, 8 Dec 2019 13:10:19 +0300 Subject: [PATCH 012/176] add auto tests --- .../Api/CategoryListDeleteBySkuInterface.php | 2 +- .../Catalog/Model/CategoryLinkRepository.php | 2 +- .../Unit/Model/CategoryLinkRepositoryTest.php | 74 ++++++++++++++++++- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php index 357da2b638802..9ae9067e3f71b 100644 --- a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php @@ -13,7 +13,7 @@ interface CategoryListDeleteBySkuInterface { /** - * delete by skus list + * Delete by skus list * * @param int $categoryId * @param array $productSkuList diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index 8e430addb91bb..1c5c924a04409 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -125,7 +125,7 @@ public function deleteBySkus($categoryId, array $productSkuList) $productPositions = $category->getProductsPosition(); - foreach ($products as $productSku => $productId) { + foreach ($products as $productId) { if (isset($productPositions[$productId])) { unset($productPositions[$productId]); } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index b42262f1f0384..e1fa175db4d44 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -6,6 +6,8 @@ namespace Magento\Catalog\Test\Unit\Model; +use Magento\Framework\Exception\InputException; + class CategoryLinkRepositoryTest extends \PHPUnit\Framework\TestCase { /** @@ -28,14 +30,22 @@ class CategoryLinkRepositoryTest extends \PHPUnit\Framework\TestCase */ protected $productLinkMock; + protected $productResourceMock; + protected function setUp() { + + $this->productResourceMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product::class) + ->disableOriginalConstructor() + ->setMethods(['getProductsIdsBySkus']) + ->getMock(); $this->categoryRepositoryMock = $this->createMock(\Magento\Catalog\Api\CategoryRepositoryInterface::class); $this->productRepositoryMock = $this->createMock(\Magento\Catalog\Api\ProductRepositoryInterface::class); $this->productLinkMock = $this->createMock(\Magento\Catalog\Api\Data\CategoryProductLinkInterface::class); $this->model = new \Magento\Catalog\Model\CategoryLinkRepository( $this->categoryRepositoryMock, - $this->productRepositoryMock + $this->productRepositoryMock, + $this->productResourceMock ); } @@ -194,4 +204,66 @@ public function testDelete() $categoryMock->expects($this->once())->method('save'); $this->assertTrue($this->model->delete($this->productLinkMock)); } + + public function testDeleteBySkus() + { + $categoryId = "42"; + $productSku = "testSku"; + $productId = 55; + $productPositions = [55 => 1]; + $categoryMock = $this->createPartialMock( + \Magento\Catalog\Model\Category::class, + ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] + ); + $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) + ->willReturn($categoryMock); + $this->productResourceMock->expects($this->once())->method('getProductsIdsBySkus') + ->willReturn(['testSku' => $productId]); + $categoryMock->expects($this->once())->method('getProductsPosition')->willReturn($productPositions); + $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); + $categoryMock->expects($this->once())->method('save'); + $this->assertTrue($this->model->deleteBySkus($categoryId, [$productSku])); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage The category doesn't contain the specified products. + */ + public function testDeleteBySkusWithInputException() + { + $categoryId = "42"; + $productSku = "testSku"; + $categoryMock = $this->createPartialMock( + \Magento\Catalog\Model\Category::class, + ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] + ); + $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) + ->willReturn($categoryMock); + $this->model->deleteBySkus($categoryId, [$productSku]); + } + + /** + * @expectedException \Magento\Framework\Exception\CouldNotSaveException + * @expectedExceptionMessage Could not save products "testSku" to category 42 + */ + public function testDeleteSkusIdsWithCouldNotSaveException() + { + $categoryId = "42"; + $productSku = "testSku"; + $productId = 55; + $productPositions = [55 => 1]; + $categoryMock = $this->createPartialMock( + \Magento\Catalog\Model\Category::class, + ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] + ); + $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) + ->willReturn($categoryMock); + $this->productResourceMock->expects($this->once())->method('getProductsIdsBySkus') + ->willReturn(['testSku' => $productId]); + $categoryMock->expects($this->once())->method('getProductsPosition')->willReturn($productPositions); + $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); + $categoryMock->expects($this->once())->method('getId')->willReturn($categoryId); + $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); + $this->assertTrue($this->model->deleteBySkus($categoryId, [$productSku])); + } } From fda5b4dfd28345bb082204f63dcc30affd5c3c83 Mon Sep 17 00:00:00 2001 From: Nikita Sarychev Date: Wed, 11 Dec 2019 22:58:48 +0300 Subject: [PATCH 013/176] add return function type --- .../Catalog/Api/CategoryListDeleteBySkuInterface.php | 2 +- app/code/Magento/Catalog/Model/CategoryLinkRepository.php | 2 +- .../Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php index 9ae9067e3f71b..e4fefd19d78b7 100644 --- a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php @@ -22,5 +22,5 @@ interface CategoryListDeleteBySkuInterface * @throws \Magento\Framework\Exception\CouldNotSaveException * @throws \Magento\Framework\Exception\InputException */ - public function deleteBySkus($categoryId, array $productSkuList); + public function deleteBySkus(int $categoryId, array $productSkuList): bool; } diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index 1c5c924a04409..ae30efdee6e18 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -114,7 +114,7 @@ public function deleteByIds($categoryId, $sku) /** * {@inheritDoc} */ - public function deleteBySkus($categoryId, array $productSkuList) + public function deleteBySkus(int $categoryId, array $productSkuList): bool { $category = $this->categoryRepository->get($categoryId); $products = $this->productResource->getProductsIdsBySkus($productSkuList); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index e1fa175db4d44..3e679fce64421 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -207,7 +207,7 @@ public function testDelete() public function testDeleteBySkus() { - $categoryId = "42"; + $categoryId = 42; $productSku = "testSku"; $productId = 55; $productPositions = [55 => 1]; @@ -231,7 +231,7 @@ public function testDeleteBySkus() */ public function testDeleteBySkusWithInputException() { - $categoryId = "42"; + $categoryId = 42; $productSku = "testSku"; $categoryMock = $this->createPartialMock( \Magento\Catalog\Model\Category::class, @@ -248,7 +248,7 @@ public function testDeleteBySkusWithInputException() */ public function testDeleteSkusIdsWithCouldNotSaveException() { - $categoryId = "42"; + $categoryId = 42; $productSku = "testSku"; $productId = 55; $productPositions = [55 => 1]; From 9f1be1dbba124ca102ec414fa82f7e4967341d4e Mon Sep 17 00:00:00 2001 From: Adarsh Manickam Date: Wed, 11 Dec 2019 18:10:39 +0530 Subject: [PATCH 014/176] Added more specific element for keyboard navigation listener --- .../Ui/view/base/web/js/grid/columns/image-preview.js | 10 ++++++++-- .../Ui/view/base/web/templates/grid/masonry.html | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/image-preview.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/image-preview.js index 2549fa93a834f..5dd2b53ec54c6 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/image-preview.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/image-preview.js @@ -13,6 +13,8 @@ define([ defaults: { bodyTmpl: 'ui/grid/columns/image-preview', previewImageSelector: '[data-image-preview]', + masonrySelector: '.masonry-image-grid', + isListenerActive: false, visibleRecord: null, height: 0, displayedRecord: {}, @@ -46,7 +48,6 @@ define([ */ initialize: function () { this._super(); - $(document).on('keydown', this.handleKeyDown.bind(this)); return this; }, @@ -130,6 +131,11 @@ define([ show: function (record) { var img; + if (!this.isListenerActive) { + $(this.masonrySelector).on('keydown', this.handleKeyDown.bind(this)); + this.isListenerActive = true; + } + if (record._rowIndex === this.visibleRecord()) { this.hide(); @@ -239,7 +245,7 @@ define([ handleKeyDown: function (e) { var key = keyCodes[e.keyCode]; - if (this.visibleRecord() !== null) { + if (this.visibleRecord() !== null && document.activeElement.tagName !== 'INPUT') { if (key === 'pageLeftKey') { this.prev(this.displayedRecord()); } else if (key === 'pageRightKey') { diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/masonry.html b/app/code/Magento/Ui/view/base/web/templates/grid/masonry.html index 089ee21bec15c..788cb0c2b5e56 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/masonry.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/masonry.html @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ --> -
+
From 1e915d4bc3600f8049cadc6746f1b4cfcf930f29 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych Date: Tue, 17 Dec 2019 10:12:25 +0200 Subject: [PATCH 015/176] Cover changes with unit test --- .../Test/Unit/Model/MethodListTest.php | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Payment/Test/Unit/Model/MethodListTest.php b/app/code/Magento/Payment/Test/Unit/Model/MethodListTest.php index 3f4af635974e8..ee42b2bd03507 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/MethodListTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/MethodListTest.php @@ -6,8 +6,8 @@ namespace Magento\Payment\Test\Unit\Model; -use Magento\Payment\Model\MethodList; use Magento\Payment\Model\Method\AbstractMethod; +use Magento\Payment\Model\MethodList; class MethodListTest extends \PHPUnit\Framework\TestCase { @@ -36,6 +36,11 @@ class MethodListTest extends \PHPUnit\Framework\TestCase */ protected $specificationFactoryMock; + /** + * @var array $additionalChecks + */ + private $additionalChecks; + protected function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -49,10 +54,14 @@ protected function setUp() )->disableOriginalConstructor()->getMock(); $this->specificationFactoryMock = $this->createMock(\Magento\Payment\Model\Checks\SpecificationFactory::class); + + $this->additionalChecks = ['acme_custom_payment_method_check' => 'acme_custom_payment_method_check']; + $this->methodList = $this->objectManager->getObject( \Magento\Payment\Model\MethodList::class, [ - 'specificationFactory' => $this->specificationFactoryMock + 'specificationFactory' => $this->specificationFactoryMock, + 'additionalChecks' => $this->additionalChecks ] ); @@ -68,6 +77,9 @@ protected function setUp() ); } + /** + * Verify available payment methods + */ public function testGetAvailableMethods() { $storeId = 1; @@ -90,13 +102,17 @@ public function testGetAvailableMethods() $this->specificationFactoryMock->expects($this->atLeastOnce()) ->method('create') - ->with([ - AbstractMethod::CHECK_USE_CHECKOUT, - AbstractMethod::CHECK_USE_FOR_COUNTRY, - AbstractMethod::CHECK_USE_FOR_CURRENCY, - AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX - ]) - ->will($this->returnValue($compositeMock)); + ->with( + array_merge( + [ + AbstractMethod::CHECK_USE_CHECKOUT, + AbstractMethod::CHECK_USE_FOR_COUNTRY, + AbstractMethod::CHECK_USE_FOR_CURRENCY, + AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX + ], + $this->additionalChecks + ) + )->will($this->returnValue($compositeMock)); $methodMock = $this->getMockForAbstractClass(\Magento\Payment\Api\Data\PaymentMethodInterface::class); $this->paymentMethodList->expects($this->once()) From 81b580accc3e0c48fb96f668be63680d9f055acd Mon Sep 17 00:00:00 2001 From: Andrea Parmeggiani Date: Thu, 19 Dec 2019 20:34:53 +0100 Subject: [PATCH 016/176] Update modal-custom.html --- .../Magento/Ui/view/base/web/templates/modal/modal-custom.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html b/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html index 5e7fd11dbf693..7d7d4b6ae88cb 100644 --- a/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html +++ b/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html @@ -27,7 +27,7 @@

+ data-role="subTitle"> <%= data.subTitle %> <% } %> From 75b6674a6dbaa6ddce5ca4d11e48e8f787210280 Mon Sep 17 00:00:00 2001 From: Andrea Parmeggiani Date: Thu, 19 Dec 2019 20:37:20 +0100 Subject: [PATCH 017/176] Modal subTitle fix --- .../Magento/Ui/view/base/web/templates/modal/modal-popup.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html b/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html index 53661ed8df87f..08376964eee63 100644 --- a/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html +++ b/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html @@ -27,7 +27,7 @@

+ data-role="subTitle"> <%= data.subTitle %> <% } %> From 748fd85bc7c963b665c73428f098f5d70d0e0ccc Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun Date: Thu, 26 Dec 2019 16:52:32 +0200 Subject: [PATCH 018/176] MC-29047: Fix MFTF test --- ...ProductDetailPageNameAndUrlActionGroup.xml | 24 ++++ ...rontCategoryPageOpenProductActionGroup.xml | 21 +++ ...tCheckCategorySimpleProductActionGroup.xml | 1 + ...urableProductCategoryViewChildOnlyTest.xml | 4 +- ...uctChildAssignedToSeparateCategoryTest.XML | 134 ++++++++++++++++++ 5 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageNameAndUrlActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryPageOpenProductActionGroup.xml create mode 100644 app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.XML diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageNameAndUrlActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageNameAndUrlActionGroup.xml new file mode 100644 index 0000000000000..e31fef0f463e1 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageNameAndUrlActionGroup.xml @@ -0,0 +1,24 @@ + + + + + + + Validates that the Product name and Url are correct. + + + + + + + + + + + diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryPageOpenProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryPageOpenProductActionGroup.xml new file mode 100644 index 0000000000000..86ce7a602315d --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryPageOpenProductActionGroup.xml @@ -0,0 +1,21 @@ + + + + + + + Click on the provided product on category page. + + + + + + + + + diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml index 1f8234498ffa7..33956073bcd88 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml @@ -16,6 +16,7 @@ + diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml index 9d7807c543def..6c9b985bf38f7 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml @@ -12,13 +12,13 @@ - + <title value="DEPRECATED It should be possible to only view the child product of a configurable product"/> <description value="Create configurable product, add to category such that only child variation is visible in category"/> <severity value="CRITICAL"/> <testCaseId value="MC-5832"/> <group value="ConfigurableProduct"/> <skip> - <issueId value="MC-17140"/> + <issueId value="DEPRECATED">Use StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest instead</issueId> </skip> </annotations> <before> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.XML b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.XML new file mode 100644 index 0000000000000..7df075f2179f6 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.XML @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest"> + <annotations> + <features value="ConfigurableProduct"/> + <stories value="View products"/> + <title value="It should be possible to only view the child product of a configurable product"/> + <description value="Create configurable product, add to category such that only child variation is visible in category"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-5832"/> + <group value="configurable_product"/> + </annotations> + <before> + <!-- Create the category --> + <createData entity="ApiCategory" stepKey="createCategory"/> + <createData entity="_defaultCategory" stepKey="secondCategory"/> + + <!-- Create an attribute with two options to be used in the first child product --> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="productAttributeOption2" stepKey="createConfigProductAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + + <!-- Add the attribute we just created to default attribute set --> + <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + + <!-- Get the first option of the attribute we created --> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + + <!-- Get the second option of the attribute we created --> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getConfigAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + + <!-- Create the configurable product and add it to the category --> + <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + + <!-- Create a simple product and give it the attribute with the first option --> + <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + </createData> + + <!-- Create a simple product and give it the attribute with the second option --> + <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + </createData> + + <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + </createData> + + <!-- Add the first simple product to the configurable product --> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct1"/> + </createData> + + <!-- Add the second simple product to the configurable product --> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild2"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct2"/> + </createData> + + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdmin"/> + </before> + + <after> + <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> + <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> + <deleteData createDataKey="secondCategory" stepKey="deleteSecondCategory"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + </after> + + <!-- Go to the product page for the first product --> + <actionGroup ref="goToProductPageViaID" stepKey="openConfigChildProduct1Page"> + <argument name="productId" value="$$createConfigChildProduct1.id$$"/> + </actionGroup> + + <!-- Edit the visibility the first simple product --> + <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="Catalog, Search" stepKey="selectVisibilityCatalogSearch"/> + <!--Add to category--> + <actionGroup ref="AdminAssignCategoryToProductAndSaveActionGroup" stepKey="addProductToCategoryAndSaveProduct"> + <argument name="categoryName" value="$$secondCategory.name$$"/> + </actionGroup> + + <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext" stepKey="reindexSearchIndex"/> + + <!-- Go to storefront to view child product --> + <actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="goToSecondCategoryStorefront"> + <argument name="category" value="$$secondCategory$$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckCategorySimpleProductActionGroup" stepKey="seeChildProductInCategory"> + <argument name="product" value="$createConfigChildProduct1$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckProductIsMissingInCategoryProductsPageActionGroup" stepKey="dontSeeOtherChildProduct"> + <argument name="productName" value="$$createConfigChildProduct2.name$$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckProductIsMissingInCategoryProductsPageActionGroup" stepKey="dontSeeParentProduct"> + <argument name="productName" value="$$createConfigProduct.name$$"/> + </actionGroup> + <actionGroup ref="StorefrontCategoryPageOpenProductActionGroup" stepKey="openConfigChildProductFromCategoryPage"> + <argument name="productName" value="$$createConfigChildProduct1.name$$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontProductDetailPageNameAndUrlActionGroup" stepKey="checkStorefrontConfigChildProductPage"> + <argument name="productName" value="$$createConfigChildProduct1.name$$"/> + <argument name="productUrl" value="$$createConfigChildProduct1.custom_attributes[url_key]$$"/> + </actionGroup> + </test> +</tests> From 8ecddac6d3c8dc38186e58478fa0ab9c45e93aa1 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Fri, 27 Dec 2019 09:05:37 +0200 Subject: [PATCH 019/176] MC-29047: Fix MFTF test --- .../StorefrontCheckCategorySimpleProductActionGroup.xml | 2 +- ...yConfigurableProductChildAssignedToSeparateCategoryTest.xml} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename app/code/Magento/ConfigurableProduct/Test/Mftf/Test/{StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.XML => StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml} (98%) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml index 33956073bcd88..ef8d5e3a1212a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml @@ -16,7 +16,7 @@ <argument name="product"/> </arguments> - <waitForElementVisible selector="{{StorefrontCategoryProductSection.ProductTitleByName(productName)}}" stepKey="waitForProduct"/> + <waitForElementVisible selector="{{StorefrontCategoryProductSection.ProductTitleByName(product.name)}}" stepKey="waitForProduct"/> <seeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName(product.name)}}" stepKey="assertProductName"/> <see userInput="${{product.price}}.00" selector="{{StorefrontCategoryProductSection.ProductPriceByName(product.name)}}" stepKey="AssertProductPrice"/> <!-- @TODO: MAGETWO-80272 Move to Magento_Checkout --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.XML b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml similarity index 98% rename from app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.XML rename to app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml index 7df075f2179f6..56a4e35995ba2 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.XML +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml @@ -97,7 +97,7 @@ </after> <!-- Go to the product page for the first product --> - <actionGroup ref="goToProductPageViaID" stepKey="openConfigChildProduct1Page"> + <actionGroup ref="GoToProductPageViaIDActionGroup" stepKey="openConfigChildProduct1Page"> <argument name="productId" value="$$createConfigChildProduct1.id$$"/> </actionGroup> From 118f0c08f30bc6f4651d296b7e8d56e92ba9aa75 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Tue, 31 Dec 2019 08:27:44 +0200 Subject: [PATCH 020/176] MC-29047: Fix MFTF test --- ...lyConfigurableProductChildAssignedToSeparateCategoryTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml index 56a4e35995ba2..5f2fc5c8caca7 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml @@ -15,7 +15,7 @@ <title value="It should be possible to only view the child product of a configurable product"/> <description value="Create configurable product, add to category such that only child variation is visible in category"/> <severity value="CRITICAL"/> - <testCaseId value="MC-5832"/> + <testCaseId value="MC-25651"/> <group value="configurable_product"/> </annotations> <before> From 6134b10749e71d861922ecfa899aaa0b9d60a658 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Fri, 3 Jan 2020 09:23:17 +0200 Subject: [PATCH 021/176] MC-24169: Fix Skipped MFTF Tests From MC-17140: MC-5719, MC-10924 --- ...ontOpenOrderFromSuccessPageActionGroup.xml | 23 ++++++++ .../Section/CheckoutSuccessMainSection.xml | 1 + ...dminChangeAllCustomersGroupViaGridTest.xml | 22 ++++++++ ...inChangeSingleCustomerGroupViaGridTest.xml | 55 +++++++++++++++++++ .../Mftf/Test/ChangeCustomerGroupTest.xml | 9 ++- ...eateCreditMemoFromOrderPageActionGroup.xml | 22 ++++++++ .../Section/AdminCreditMemoTotalSection.xml | 2 +- 7 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenOrderFromSuccessPageActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/Test/AdminChangeAllCustomersGroupViaGridTest.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/Test/AdminChangeSingleCustomerGroupViaGridTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminStartCreateCreditMemoFromOrderPageActionGroup.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenOrderFromSuccessPageActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenOrderFromSuccessPageActionGroup.xml new file mode 100644 index 0000000000000..80c9ff0a45135 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenOrderFromSuccessPageActionGroup.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontOpenOrderFromSuccessPageActionGroup"> + <annotations> + <description>Click order number link from checkout success page and check order number on order view page.</description> + </annotations> + <arguments> + <argument name="orderNumber" defaultValue="000000001" type="string"/> + </arguments> + + <click selector="{{CheckoutSuccessMainSection.orderLinkByOrderNumber(orderNumber)}}" stepKey="clickOrderNumberLink"/> + <waitForPageLoad stepKey="waitForOrderPageIsLoaded"/> + <see userInput="Order # {{orderNumber}}" selector="{{StorefrontCustomerOrderViewSection.orderTitle}}" stepKey="assertOrderNumberIsCorrect"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutSuccessMainSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutSuccessMainSection.xml index c486e13ecf58b..d15b89e58a550 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutSuccessMainSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutSuccessMainSection.xml @@ -20,5 +20,6 @@ <element name="createAnAccount" type="button" selector="[data-bind*="i18n: 'Create an Account'"]" timeout="30"/> <element name="printLink" type="button" selector=".print" timeout="30"/> <element name="orderNumberWithoutLink" type="text" selector="//div[contains(@class, 'checkout-success')]//p/span"/> + <element name="orderLinkByOrderNumber" type="text" selector="//div[contains(@class,'success')]//a[contains(.,'{{orderNumber}}')]" parameterized="true" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeAllCustomersGroupViaGridTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeAllCustomersGroupViaGridTest.xml new file mode 100644 index 0000000000000..59c50f905878b --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeAllCustomersGroupViaGridTest.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminChangeAllCustomersGroupViaGridTest" extends="AdminChangeSingleCustomerGroupViaGridTest"> + <annotations> + <title value="Change all customers' group via grid"/> + <description value="Select All customers to change their group"/> + <testCaseId value="MC-26040"/> + </annotations> + + <remove keyForRemoval="filterCustomer"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" before="selectCustomer" stepKey="clearFilters"/> + <actionGroup ref="AdminSelectAllCustomers" stepKey="selectCustomer"/> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeSingleCustomerGroupViaGridTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeSingleCustomerGroupViaGridTest.xml new file mode 100644 index 0000000000000..2478334de3baf --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeSingleCustomerGroupViaGridTest.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminChangeSingleCustomerGroupViaGridTest"> + <annotations> + <features value="Customer"/> + <title value="Change a single customer group via grid"/> + <description value="From the selection of All Customers select a single customer to change their group"/> + <severity value="MAJOR"/> + <testCaseId value="MC-26039"/> + <stories value="Customer Edit"/> + <group value="customer"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + <createData entity="CustomerGroupChange" stepKey="createCustomerGroup"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!--Delete created data--> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="createCustomerGroup" stepKey="deleteCustomerGroup"/> + <actionGroup ref="NavigateToAllCustomerPage" stepKey="navigateToCustomersPage"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearCustomersGridFilter"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + </after> + + <actionGroup ref="NavigateToAllCustomerPage" stepKey="navigateToCustomersPage"/> + <actionGroup ref="AdminFilterCustomerGridByEmail" stepKey="filterCustomer"> + <argument name="email" value="$$createCustomer.email$$"/> + </actionGroup> + <actionGroup ref="AdminSelectCustomerByEmail" stepKey="selectCustomer"> + <argument name="customerEmail" value="$$createCustomer.email$$"/> + </actionGroup> + <actionGroup ref="SetCustomerGroupForSelectedCustomersViaGrid" stepKey="setCustomerGroup"> + <argument name="groupName" value="$$createCustomerGroup.code$$"/> + </actionGroup> + <actionGroup ref="AdminFilterCustomerGridByEmail" stepKey="filterCustomerAfterGroupChange"> + <argument name="email" value="$$createCustomer.email$$"/> + </actionGroup> + <actionGroup ref="VerifyCustomerGroupForCustomer" stepKey="verifyCustomerGroupSet"> + <argument name="customerEmail" value="$$createCustomer.email$$"/> + <argument name="groupName" value="$$createCustomerGroup.code$$"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/ChangeCustomerGroupTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/ChangeCustomerGroupTest.xml index d9b71e1e6e9ba..7de52875d4341 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/ChangeCustomerGroupTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/ChangeCustomerGroupTest.xml @@ -10,13 +10,16 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="ChangingSingleCustomerGroupViaGrid"> <annotations> - <title value="Change a single customer group via grid"/> + <title value="DEPRECATED Change a single customer group via grid"/> <description value="From the selection of All Customers select a single customer to change their group"/> <severity value="MAJOR"/> <testCaseId value="MC-10921"/> <stories value="Change Customer Group"/> <group value="customer"/> <group value="mtf_migrated"/> + <skip> + <issueId value="DEPRECATED">Use AdminChangeSingleCustomerGroupViaGridTest instead</issueId> + </skip> </annotations> <before> @@ -60,7 +63,7 @@ <test name="ChangingAllCustomerGroupViaGrid" extends="ChangingSingleCustomerGroupViaGrid"> <annotations> - <title value="Change all customers' group via grid"/> + <title value="DEPRECATED Change all customers' group via grid"/> <description value="Select All customers to change their group"/> <severity value="MAJOR"/> <testCaseId value="MC-10924"/> @@ -68,7 +71,7 @@ <group value="customer"/> <group value="mtf_migrated"/> <skip> - <issueId value="MC-17140"/> + <issueId value="DEPRECATED">Use AdminChangeAllCustomersGroupViaGridTest instead</issueId> </skip> </annotations> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminStartCreateCreditMemoFromOrderPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminStartCreateCreditMemoFromOrderPageActionGroup.xml new file mode 100644 index 0000000000000..e10c438652d90 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminStartCreateCreditMemoFromOrderPageActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminStartCreateCreditMemoFromOrderPageActionGroup"> + <annotations> + <description>Start to create Credit Memo from order page</description> + </annotations> + <click selector="{{AdminOrderDetailsMainActionsSection.creditMemo}}" stepKey="clickCreditMemoButton"/> + <conditionalClick selector="{{AdminConfirmationModalSection.ok}}" dependentSelector="{{AdminConfirmationModalSection.ok}}" + visible="true" stepKey="acceptModal"/> + <waitForPageLoad time="30" stepKey="waitPageLoaded"/> + <seeInCurrentUrl url="{{AdminCreditMemoNewPage.url}}" stepKey="seeNewCreditMemoUrl"/> + <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Memo" stepKey="seeNewCreditMemoPageTitle"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml index 6b4bdf69361a5..10a10e77ea57c 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml @@ -18,7 +18,7 @@ <element name="appendComments" type="checkbox" selector=".order-totals-actions #notify_customer"/> <element name="emailCopy" type="checkbox" selector=".order-totals-actions #send_email"/> <element name="refundStoreCredit" type="checkbox" selector=".order-totals-actions .field-refund-store-credit input[type='checkbox']"/> - <element name="submitRefundOffline" type="button" selector=".order-totals-actions button[data-ui-id='order-items-submit-button']" timeout="30"/> + <element name="submitRefundOffline" type="button" selector=".order-totals-actions button[data-ui-id='order-items-submit-button']" timeout="60"/> <element name="creditMemoItem" type="text" selector="#sales_order_view_tabs_order_creditmemos"/> <element name="viewMemo" type="text" selector="div#sales_order_view_tabs_order_creditmemos_content a.action-menu-item"/> <element name="refundOffline" type="button" selector=".order-totals-actions button[data-ui-id='order-items-submit-offline']"/> From 26872216194a2c534104573bb3e25075d933fc0c Mon Sep 17 00:00:00 2001 From: Yurii Tvardyi <yurii.tvaryi@smile-ukraine.com> Date: Mon, 6 Jan 2020 12:16:44 +0200 Subject: [PATCH 022/176] Fix issue #26276 with clonning quote billing address --- .../view/frontend/web/js/action/select-billing-address.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js index 086859fa8021d..1f14ab444e0c1 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js @@ -18,7 +18,7 @@ define([ if (quote.shippingAddress() && billingAddress.getCacheKey() == //eslint-disable-line eqeqeq quote.shippingAddress().getCacheKey() ) { - address = $.extend({}, billingAddress); + address = $.extend(true, {}, billingAddress); address.saveInAddressBook = null; } else { address = billingAddress; From 7141278628d4ef0d54d244ab337cbea62e7f37d8 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Fri, 3 Jan 2020 02:05:01 +0200 Subject: [PATCH 023/176] magento/magento2#26245: Magento does not send an email about a refunded grouped product --- .../Order/Email/Items/CreditMemo/Grouped.php | 40 +++++++++++++++++++ ...sales_email_order_creditmemo_renderers.xml | 5 ++- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/Grouped.php diff --git a/app/code/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/Grouped.php b/app/code/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/Grouped.php new file mode 100644 index 0000000000000..6df890b3e94dc --- /dev/null +++ b/app/code/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/Grouped.php @@ -0,0 +1,40 @@ +<?php +/** + * Order Email items grouped renderer + * + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\GroupedProduct\Block\Order\Email\Items\CreditMemo; + +use Magento\Sales\Block\Order\Email\Items\DefaultItems; + +/** + * Class renders grouped product(s) in the CreditMemo email + * + * @api + */ +class Grouped extends DefaultItems +{ + /** + * Prepare item html + * + * This method uses renderer for real product type + * + * @return string + */ + protected function _toHtml() + { + if ($this->getItem()->getOrderItem()) { + $item = $this->getItem()->getOrderItem(); + } else { + $item = $this->getItem(); + } + if ($productType = $item->getRealProductType()) { + $renderer = $this->getRenderedBlock()->getItemRenderer($productType); + $renderer->setItem($this->getItem()); + return $renderer->toHtml(); + } + return parent::_toHtml(); + } +} diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml index 77875ac70427c..95fe2f37044c7 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml @@ -8,7 +8,10 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="Email Creditmemo Items List" design_abstraction="custom"> <body> <referenceBlock name="sales.email.order.creditmemo.renderers"> - <block class="Magento\GroupedProduct\Block\Order\Email\Items\Order\Grouped" name="sales.email.order.creditmemo.renderers.grouped" as="grouped" template="Magento_Sales::email/items/creditmemo/default.phtml"/> + <block class="Magento\GroupedProduct\Block\Order\Email\Items\CreditMemo\Grouped" + name="sales.email.order.creditmemo.renderers.grouped" + as="grouped" + template="Magento_Sales::email/items/creditmemo/default.phtml"/> </referenceBlock> </body> </page> From 065353971c4dd2e835723d2702f391000cddb219 Mon Sep 17 00:00:00 2001 From: Tejash Kumbhare <tejas@wagento.com> Date: Fri, 10 Jan 2020 12:10:59 +0530 Subject: [PATCH 024/176] Module xml extra end tag removed --- app/code/Magento/AdvancedPricingImportExport/etc/module.xml | 3 +-- app/code/Magento/Dhl/etc/module.xml | 3 +-- app/code/Magento/Rss/etc/module.xml | 3 +-- app/code/Magento/Translation/etc/module.xml | 3 +-- app/code/Magento/Ups/etc/module.xml | 3 +-- 5 files changed, 5 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml index 230fb17ae5544..4482ba7a0a5e8 100644 --- a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml +++ b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml @@ -6,6 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_AdvancedPricingImportExport" > - </module> + <module name="Magento_AdvancedPricingImportExport" /> </config> diff --git a/app/code/Magento/Dhl/etc/module.xml b/app/code/Magento/Dhl/etc/module.xml index b1af1baf97fc2..c8f63d08f87a5 100644 --- a/app/code/Magento/Dhl/etc/module.xml +++ b/app/code/Magento/Dhl/etc/module.xml @@ -6,6 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_Dhl" > - </module> + <module name="Magento_Dhl" /> </config> diff --git a/app/code/Magento/Rss/etc/module.xml b/app/code/Magento/Rss/etc/module.xml index 196d8c3ac5655..eb56eef3d526f 100644 --- a/app/code/Magento/Rss/etc/module.xml +++ b/app/code/Magento/Rss/etc/module.xml @@ -6,6 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_Rss" > - </module> + <module name="Magento_Rss" /> </config> diff --git a/app/code/Magento/Translation/etc/module.xml b/app/code/Magento/Translation/etc/module.xml index 23ebfe1b0751d..f3f146b65416c 100644 --- a/app/code/Magento/Translation/etc/module.xml +++ b/app/code/Magento/Translation/etc/module.xml @@ -6,6 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_Translation" > - </module> + <module name="Magento_Translation" /> </config> diff --git a/app/code/Magento/Ups/etc/module.xml b/app/code/Magento/Ups/etc/module.xml index cc4599627ffb9..70cf0bc5ae98a 100644 --- a/app/code/Magento/Ups/etc/module.xml +++ b/app/code/Magento/Ups/etc/module.xml @@ -6,6 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_Ups" > - </module> + <module name="Magento_Ups" /> </config> From 9abbd3263157756785b3f3a9a698538b15465eeb Mon Sep 17 00:00:00 2001 From: Tejash Kumbhare <tejas@wagento.com> Date: Fri, 10 Jan 2020 14:42:19 +0530 Subject: [PATCH 025/176] Remove extra space before semicolon and remove extra comma in php, phtml and js files --- .../view/adminhtml/templates/notification.phtml | 2 +- .../Block/Widget/Grid/Column/Renderer/AbstractRenderer.php | 2 +- .../DataProvider/Product/SearchCriteriaBuilder.php | 2 +- .../Csp/Model/Collector/CspWhitelistXml/SchemaLocator.php | 2 +- .../Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php | 4 ++-- .../Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php | 4 ++-- .../Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php | 2 +- .../view/base/web/tiny_mce/plugins/table/editor_plugin_src.js | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/AdminAnalytics/view/adminhtml/templates/notification.phtml b/app/code/Magento/AdminAnalytics/view/adminhtml/templates/notification.phtml index 4b1f971670184..81b923be71655 100644 --- a/app/code/Magento/AdminAnalytics/view/adminhtml/templates/notification.phtml +++ b/app/code/Magento/AdminAnalytics/view/adminhtml/templates/notification.phtml @@ -10,7 +10,7 @@ define('analyticsPopupConfig', function () { return { analyticsVisible: <?= $block->getNotification()->isAnalyticsVisible() ? 1 : 0; ?>, - releaseVisible: <?= $block->getNotification()->isReleaseVisible() ? 1 : 0; ?>, + releaseVisible: <?= $block->getNotification()->isReleaseVisible() ? 1 : 0; ?> } }); </script> diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php index 623a75015eb2f..c58bcdf5108cb 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php @@ -62,7 +62,7 @@ public function render(DataObject $row) $result .= $this->getColumn()->getEditOnly() ? '' : '<span class="admin__grid-control-value">' . $this->_getValue($row) . '</span>'; - return $result . $this->_getInputValueElement($row) . '</div>' ; + return $result . $this->_getInputValueElement($row) . '</div>'; } return $this->_getValue($row); } diff --git a/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php b/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php index 0e92bbbab4259..dc8d71ba867c9 100644 --- a/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php +++ b/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php @@ -123,7 +123,7 @@ private function addVisibilityFilter(SearchCriteriaInterface $searchCriteria, bo { if ($isFilter && $isSearch) { // Index already contains products filtered by visibility: catalog, search, both - return ; + return; } $visibilityIds = $isSearch ? $this->visibility->getVisibleInSearchIds() diff --git a/app/code/Magento/Csp/Model/Collector/CspWhitelistXml/SchemaLocator.php b/app/code/Magento/Csp/Model/Collector/CspWhitelistXml/SchemaLocator.php index 285d37a1b6270..ed4d4a6fde51d 100644 --- a/app/code/Magento/Csp/Model/Collector/CspWhitelistXml/SchemaLocator.php +++ b/app/code/Magento/Csp/Model/Collector/CspWhitelistXml/SchemaLocator.php @@ -22,7 +22,7 @@ class SchemaLocator implements SchemaLocatorInterface * * @var string */ - private $schema ; + private $schema; /** * @param Reader $moduleReader diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php index dc9a51b30cfea..e816533d59088 100644 --- a/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php @@ -40,11 +40,11 @@ protected function setUp() public function testGetOrder() { - $this->assertSame($this->orderMock, $this->model->getOrder()) ; + $this->assertSame($this->orderMock, $this->model->getOrder()); } public function testGetPayment() { - $this->assertSame($this->paymentMock, $this->model->getPayment()) ; + $this->assertSame($this->paymentMock, $this->model->getPayment()); } } diff --git a/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php b/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php index cd7a54455a994..896879c4f67c6 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php @@ -15,7 +15,7 @@ class UpdateQuoteItemsTest extends \PHPUnit\Framework\TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Quote\Model\ResourceModel\Quote */ - private $quoteResource ; + private $quoteResource; protected function setUp() { @@ -58,7 +58,7 @@ public function aroundUpdateDataProvider() [10, 20, 'once'], [null, 10, 'never'], [10, 10, 'never'], - [10, 10, 'once', true], + [10, 10, 'once', true] ]; } } diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php index 1b275c4d809cb..dd62411ea3454 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php @@ -100,7 +100,7 @@ protected function _addStoresFieldset($model, $form) 'fieldset_html_class' => 'store' ] ); - return ; + return; } $renderer = $this->getLayout()->createBlock( diff --git a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/table/editor_plugin_src.js b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/table/editor_plugin_src.js index 8170e4ed44eea..512f3520f2ef0 100644 --- a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/table/editor_plugin_src.js +++ b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/table/editor_plugin_src.js @@ -1222,7 +1222,7 @@ var last; // Skip empty text nodes form the end - for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling) ; + for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling); if (last && last.nodeName == 'TABLE') ed.dom.add(ed.getBody(), 'p', null, '<br mce_bogus="1" />'); From 399fe8eb8f463bf85702e10e0c81c8cfe99a2abf Mon Sep 17 00:00:00 2001 From: Tejash Kumbhare <tejas@wagento.com> Date: Fri, 10 Jan 2020 17:18:20 +0530 Subject: [PATCH 026/176] model xml issues fixed --- app/code/Magento/AdvancedPricingImportExport/etc/module.xml | 2 +- app/code/Magento/Dhl/etc/module.xml | 2 +- app/code/Magento/Rss/etc/module.xml | 2 +- app/code/Magento/Translation/etc/module.xml | 2 +- app/code/Magento/Ups/etc/module.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml index 4482ba7a0a5e8..ac7e6f860382b 100644 --- a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml +++ b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_AdvancedPricingImportExport" /> + <module name="Magento_AdvancedPricingImportExport"/> </config> diff --git a/app/code/Magento/Dhl/etc/module.xml b/app/code/Magento/Dhl/etc/module.xml index c8f63d08f87a5..e46bb72ad7b3c 100644 --- a/app/code/Magento/Dhl/etc/module.xml +++ b/app/code/Magento/Dhl/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_Dhl" /> + <module name="Magento_Dhl"/> </config> diff --git a/app/code/Magento/Rss/etc/module.xml b/app/code/Magento/Rss/etc/module.xml index eb56eef3d526f..c00b53e716230 100644 --- a/app/code/Magento/Rss/etc/module.xml +++ b/app/code/Magento/Rss/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_Rss" /> + <module name="Magento_Rss"/> </config> diff --git a/app/code/Magento/Translation/etc/module.xml b/app/code/Magento/Translation/etc/module.xml index f3f146b65416c..5bf40ec19b6e2 100644 --- a/app/code/Magento/Translation/etc/module.xml +++ b/app/code/Magento/Translation/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_Translation" /> + <module name="Magento_Translation"/> </config> diff --git a/app/code/Magento/Ups/etc/module.xml b/app/code/Magento/Ups/etc/module.xml index 70cf0bc5ae98a..1c449f6b1cdb5 100644 --- a/app/code/Magento/Ups/etc/module.xml +++ b/app/code/Magento/Ups/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_Ups" /> + <module name="Magento_Ups"/> </config> From 638ccd5bde4ff0d966231cb22c232270a2f2e706 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 10 Jan 2020 18:45:01 +0200 Subject: [PATCH 027/176] MC-25108: MFTF Flakiness because of bad design - StoreFrontMyAccountWithMultishipmentTest --- ...tomerOrderMatchesGrandTotalActionGroup.xml | 28 +++++ ...oreFrontMyAccountWithMultishipmentTest.xml | 4 +- .../StorefrontOrderWithMultishippingTest.xml | 105 ++++++++++++++++++ ...rontCustomerOrdersViewOrderActionGroup.xml | 22 ++++ .../StorefrontCustomerOrdersGridSection.xml | 4 +- 5 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml create mode 100644 app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontCustomerOrdersViewOrderActionGroup.xml diff --git a/app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml b/app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml new file mode 100644 index 0000000000000..9281cdf03a1ab --- /dev/null +++ b/app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <actionGroup name="AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup"> + <grabTextFrom selector="{{StorefrontSalesOrderSection.salesOrderPrice('subtotal')}}" stepKey="grabValueForSubtotal"/> + <grabTextFrom selector="{{StorefrontSalesOrderSection.salesOrderPrice('shipping')}}" stepKey="grabValueForShippingHandling"/> + <grabTextFrom selector="{{StorefrontSalesOrderSection.salesOrderPrice('grand_total')}}" stepKey="grabValueForGrandTotal"/> + <executeJS function=" + var grandTotal = '{$grabValueForGrandTotal}'.substr(1); + return (grandTotal);" stepKey="grandTotalValue"/> + <executeJS function=" + var subtotal = '{$grabValueForSubtotal}'.substr(1); + var handling = '{$grabValueForShippingHandling}'.substr(1); + var subtotalHandling = (parseFloat(subtotal) + parseFloat(handling)).toFixed(2); + return (subtotalHandling);" stepKey="sumTotalValue"/> + <assertEquals stepKey="assertSubTotalPrice"> + <expectedResult type="variable">sumTotalValue</expectedResult> + <actualResult type="variable">grandTotalValue</actualResult> + </assertEquals> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMyAccountWithMultishipmentTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMyAccountWithMultishipmentTest.xml index ad68b709c5729..d8b6a35a4885c 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMyAccountWithMultishipmentTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMyAccountWithMultishipmentTest.xml @@ -12,13 +12,13 @@ <annotations> <features value="Multishipping"/> <stories value="Shipping price shows 0 on Order view page after multiple address checkout"/> - <title value="Verify Shipping price for Storefront after multiple address checkout"/> + <title value="DEPRECATED. Verify Shipping price for Storefront after multiple address checkout"/> <description value="Verify that shipping price on My account matches with shipping method prices after multiple addresses checkout (Order view page)"/> <severity value="CRITICAL"/> <testCaseId value="MC-19303"/> <group value="multishipping"/> <skip> - <issueId value="MC-22683"/> + <issueId value="DEPRECATED">Please use StorefrontOrderWithMultishippingTest instead</issueId> </skip> </annotations> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml new file mode 100644 index 0000000000000..26a1892cb679e --- /dev/null +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontOrderWithMultishippingTest"> + <annotations> + <features value="Multishipping"/> + <stories value="Shipping price shows 0 on Order view page after multiple address checkout"/> + <title value="Verify Shipping price for Storefront after multiple address checkout"/> + <description value="Verify that shipping price on My account matches with shipping method prices after multiple addresses checkout (Order view page)"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-28900"/> + <group value="catalog"/> + <group value="sales"/> + <group value="multishipping"/> + </annotations> + + <before> + <createData entity="SimpleProduct2" stepKey="createProduct1"/> + <createData entity="SimpleProduct2" stepKey="createProduct2"/> + <createData entity="Simple_US_Customer_Two_Addresses" stepKey="createCustomer"/> + <!-- Set configurations --> + <magentoCLI command="config:set {{EnableMultiShippingCheckoutMultiple.path}} {{EnableMultiShippingCheckoutMultiple.value}}" stepKey="allowShippingToMultipleAddresses"/> + <magentoCLI command="config:set {{EnableFreeShippingMethod.path}} {{EnableFreeShippingMethod.value}}" stepKey="enableFreeShipping"/> + <magentoCLI command="config:set {{EnableFlatRateShippingMethod.path}} {{EnableFlatRateShippingMethod.value}}" stepKey="enableFlatRateShipping"/> + <magentoCLI command="config:set {{EnableCheckMoneyOrderPaymentMethod.path}} {{EnableCheckMoneyOrderPaymentMethod.value}}" stepKey="enableCheckMoneyOrderPaymentMethod"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + </before> + + <after> + <deleteData createDataKey="createProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="createProduct2" stepKey="deleteProduct2"/> + <!-- Need logout before customer delete. Fatal error appears otherwise --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <magentoCLI command="config:set {{DisableMultiShippingCheckoutMultiple.path}} {{DisableMultiShippingCheckoutMultiple.value}}" stepKey="withdrawShippingToMultipleAddresses"/> + <magentoCLI command="config:set {{DisableFreeShippingMethod.path}} {{DisableFreeShippingMethod.value}}" stepKey="disableFreeShipping"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearAllOrdersGridFilters"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + </after> + + <actionGroup ref="AddSimpleProductToCartActionGroup" stepKey="addSimpleProduct1ToCart"> + <argument name="product" value="$$createProduct1$$"/> + </actionGroup> + <actionGroup ref="AddSimpleProductToCartActionGroup" stepKey="addSimpleProduct2ToCart"> + <argument name="product" value="$$createProduct2$$"/> + </actionGroup> + <actionGroup ref="StorefrontOpenCartFromMinicartActionGroup" stepKey="openCart"/> + <actionGroup ref="CheckingWithMultipleAddressesActionGroup" stepKey="checkoutWithMultipleAddresses"/> + <waitForPageLoad stepKey="waitForShippingInfoPageLoad"/> + <actionGroup ref="SelectMultiShippingInfoActionGroup" stepKey="checkoutWithMultipleShipping"/> + <!--Select Check / Money order Payment method--> + <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyPayment"/> + <actionGroup ref="SelectBillingInfoActionGroup" stepKey="checkoutWithPaymentMethod"/> + <waitForPageLoad stepKey="waitForReviewOrderPageLoad"/> + <actionGroup ref="ReviewOrderForMultiShipmentActionGroup" stepKey="reviewOrderForMultiShipment"> + <argument name="totalNameForFirstOrder" value="Shipping & Handling"/> + <argument name="totalPositionForFirstOrder" value="1"/> + <argument name="totalNameForSecondOrder" value="Shipping & Handling"/> + <argument name="totalPositionForSecondOrder" value="2"/> + </actionGroup> + <waitForPageLoad stepKey="waitForPlaceOrderPageLoad"/> + <actionGroup ref="StorefrontPlaceOrderForMultipleAddressesActionGroup" stepKey="placeOrder"> + <argument name="firstOrderPosition" value="1"/> + <argument name="secondOrderPosition" value="2"/> + </actionGroup> + <waitForPageLoad stepKey="waitForOrderPageLoad"/> + + <!-- Check first order--> + <actionGroup ref="StorefrontCustomerOrdersViewOrderActionGroup" stepKey="openFirstOrder"> + <argument name="orderNumber" value="{$getFirstOrderIdPlaceOrder}"/> + </actionGroup> + <actionGroup ref="AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup" stepKey="checkFirstOrderTotals"/> + <!-- Check second order--> + <actionGroup ref="StorefrontCustomerOrdersViewOrderActionGroup" stepKey="openSecondOrder"> + <argument name="orderNumber" value="{$getSecondOrderIdPlaceOrder}"/> + </actionGroup> + <actionGroup ref="AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup" stepKey="checkSecondOrderTotals"/> + + <!--Assert order in orders grid --> + <!-- Go to order page --> + <actionGroup ref="OpenOrderByIdActionGroup" stepKey="openFirstOrderPage"> + <argument name="orderId" value="{$getFirstOrderIdPlaceOrder}"/> + </actionGroup> + <!-- Check status --> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeFirstOrderPendingStatus"/> + <actionGroup ref="AdminSalesOrderActionGroup" stepKey="validateOrderTotalsForFirstOrder"/> + <!-- Go to order page --> + <actionGroup ref="OpenOrderByIdActionGroup" stepKey="openSecondOrderPage"> + <argument name="orderId" value="{$getSecondOrderIdPlaceOrder}"/> + </actionGroup> + <!-- Check status --> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeSecondOrderPendingStatus"/> + <actionGroup ref="AdminSalesOrderActionGroup" stepKey="validateOrderTotalsForSecondOrder"/> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontCustomerOrdersViewOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontCustomerOrdersViewOrderActionGroup.xml new file mode 100644 index 0000000000000..88d79268d440e --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontCustomerOrdersViewOrderActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontCustomerOrdersViewOrderActionGroup"> + <annotations> + <description>Navigate to customer dashboard -> orders. Press 'View Order' button for specified order number. Notice: customer should be logged in.</description> + </annotations> + <arguments> + <argument name="orderNumber" type="string" defaultValue="000000001"/> + </arguments> + + <amOnPage url="{{StorefrontCustomerOrdersHistoryPage.url}}" stepKey="openCustomerOrdersHistoryPage"/> + <click selector="{{StorefrontCustomerOrdersGridSection.orderView(orderNumber)}}" stepKey="clickViewOrderButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml index c0deb9ab55d2b..5b079891f657a 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontCustomerOrdersGridSection"> - <element name="orderView" type="button" selector="//td[text()='{{orderNumber}}']/following-sibling::td[@class='col actions']/a[contains(@class, 'view')]" parameterized="true" /> - <element name="reorderBtn" type="button" selector="//td[text()='{{orderNumber}}']/following-sibling::td[@class='col actions']/a[contains(@class, 'order')]" parameterized="true" /> + <element name="orderView" type="button" selector="//td[text()='{{orderNumber}}']/following-sibling::td[@class='col actions']/a[contains(@class, 'view')]" parameterized="true" timeout="30" /> + <element name="reorderBtn" type="button" selector="//td[text()='{{orderNumber}}']/following-sibling::td[@class='col actions']/a[contains(@class, 'order')]" parameterized="true" timeout="30" /> </section> </sections> From 89d09ac6bcfdcf5a22f86ff83999893627eca081 Mon Sep 17 00:00:00 2001 From: Tejash Kumbhare <tejas@wagento.com> Date: Mon, 13 Jan 2020 10:27:05 +0530 Subject: [PATCH 028/176] revert back and added comma --- .../AdminAnalytics/view/adminhtml/templates/notification.phtml | 2 +- .../Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/AdminAnalytics/view/adminhtml/templates/notification.phtml b/app/code/Magento/AdminAnalytics/view/adminhtml/templates/notification.phtml index 81b923be71655..4b1f971670184 100644 --- a/app/code/Magento/AdminAnalytics/view/adminhtml/templates/notification.phtml +++ b/app/code/Magento/AdminAnalytics/view/adminhtml/templates/notification.phtml @@ -10,7 +10,7 @@ define('analyticsPopupConfig', function () { return { analyticsVisible: <?= $block->getNotification()->isAnalyticsVisible() ? 1 : 0; ?>, - releaseVisible: <?= $block->getNotification()->isReleaseVisible() ? 1 : 0; ?> + releaseVisible: <?= $block->getNotification()->isReleaseVisible() ? 1 : 0; ?>, } }); </script> diff --git a/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php b/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php index 896879c4f67c6..279b2c4b4091f 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php @@ -58,7 +58,7 @@ public function aroundUpdateDataProvider() [10, 20, 'once'], [null, 10, 'never'], [10, 10, 'never'], - [10, 10, 'once', true] + [10, 10, 'once', true], ]; } } From b94c4abbbdd9780936ac399a3c1e054800c4c43b Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Mon, 13 Jan 2020 11:36:21 +0200 Subject: [PATCH 029/176] MC-23546: Child Configurable product does not save disabled status via API --- .../Mftf/Test/SearchEntityResultsTest.xml | 4 +- ...ontQuickSearchConfigurableChildrenTest.xml | 109 ++++++++++++++++++ 2 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml index cc6f202272e3b..c289fc7868a10 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml @@ -607,14 +607,14 @@ <test name="QuickSearchConfigurableChildren"> <annotations> <stories value="Search Product on Storefront"/> - <title value="User should be able to use Quick Search to a configurable product's child products"/> + <title value="Deprecated. User should be able to use Quick Search to a configurable product's child products"/> <description value="Use Quick Search to find a configurable product with enabled/disable children"/> <severity value="MAJOR"/> <testCaseId value="MC-14798"/> <group value="CatalogSearch"/> <group value="mtf_migrated"/> <skip> - <issueId value="MC-15101"/> + <issueId value="DEPRECATED">Use StorefrontQuickSearchConfigurableChildrenTest instead.</issueId> </skip> </annotations> <before> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml new file mode 100644 index 0000000000000..03ce878ef4f9f --- /dev/null +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontQuickSearchConfigurableChildrenTest"> + <annotations> + <stories value="Search Product on Storefront"/> + <title value="User should be able to use Quick Search to a configurable product's child products"/> + <description value="Use Quick Search to find a configurable product with enabled/disable children"/> + <severity value="MAJOR"/> + <testCaseId value="MC-14798"/> + <group value="CatalogSearch"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create the category --> + <createData entity="ApiCategory" stepKey="createCategory"/> + <!-- Create blank AttributeSet--> + <createData entity="CatalogAttributeSet" stepKey="createAttributeSet"/> + <!-- Create an attribute with two options to be used in the first child product --> + <createData entity="hiddenDropdownAttributeWithOptions" stepKey="createProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createProductAttributeOption"> + <requiredEntity createDataKey="createProductAttribute"/> + </createData> + + <!-- Assign attribute to set --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <actionGroup ref="GoToAttributeGridPageActionGroup" stepKey="goToAttributeSetPage"/> + <actionGroup ref="GoToAttributeSetByNameActionGroup" stepKey="openAttributeSetByName"> + <argument name="name" value="$createAttributeSet.attribute_set_name$"/> + </actionGroup> + <actionGroup ref="AssignAttributeToGroupActionGroup" stepKey="assignAttributeToGroup"> + <argument name="group" value="Product Details"/> + <argument name="attribute" value="$createProductAttribute.attribute_code$"/> + </actionGroup> + <actionGroup ref="SaveAttributeSetActionGroup" stepKey="savePage"/> + + <!-- Get the first option of the attribute we created --> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getAttributeOption"> + <requiredEntity createDataKey="createProductAttribute"/> + </getData> + + <!-- Create a simple product --> + <createData entity="ApiSimpleOneHidden" storeCode="all" stepKey="createSimpleProduct"> + <field key="attribute_set_id">$createAttributeSet.attribute_set_id$</field> + <requiredEntity createDataKey="createProductAttribute"/> + <requiredEntity createDataKey="getAttributeOption"/> + </createData> + <updateData entity="ApiSimpleProductUpdateDescription" createDataKey="createSimpleProduct" stepKey="updateSimpleProduct"/> + + <!-- Create the configurable product --> + <createData entity="ApiConfigurableProduct" stepKey="createConfigurableProduct"> + <field key="attribute_set_id">$createAttributeSet.attribute_set_id$</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <!-- Create the configurable product option --> + <createData entity="ConfigurableProductOneOption" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigurableProduct"/> + <requiredEntity createDataKey="createProductAttribute"/> + <requiredEntity createDataKey="getAttributeOption"/> + </createData> + <!-- Add the first simple product to the configurable product --> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild"> + <requiredEntity createDataKey="createConfigurableProduct"/> + <requiredEntity createDataKey="createSimpleProduct"/> + </createData> + + <!-- Perform reindex --> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + </before> + <after> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <deleteData createDataKey="createConfigurableProduct" stepKey="deleteConfigurableProduct"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> + <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + </after> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePage"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> + <argument name="phrase" value="$createConfigurableProduct.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameInGridActionGroup" stepKey="seeProductInGrid"> + <argument name="productName" value="$createConfigurableProduct.name$"/> + <argument name="index" value="1"/> + </actionGroup> + + <!-- Disable Child Product --> + <actionGroup ref="GoToProductPageViaIDActionGroup" stepKey="openSimpleProduct"> + <argument name="productId" value="$createSimpleProduct.id$"/> + </actionGroup> + <actionGroup ref="ToggleProductEnabledActionGroup" stepKey="disableProduct"/> + <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> + + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePageAgain"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefrontAgain"> + <argument name="phrase" value="$createConfigurableProduct.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGridActionGroup" stepKey="dontSeeProductAnymore"> + <argument name="productName" value="$createConfigurableProduct.name$"/> + </actionGroup> + </test> +</tests> From daec86e617f04a317a7f00113c38e3d13f80fa37 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 14 Jan 2020 12:39:00 +0200 Subject: [PATCH 030/176] MC-30409: [FT] [MFTF] [2.4] Fix flaky test AdminCreateDuplicateProductTest (MC-14714) --- .../Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml | 1 + .../Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml index 4507e1f880a86..3eb617d19d54c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml @@ -22,6 +22,7 @@ <createData entity="Two_nested_categories" stepKey="subCategory"> <requiredEntity createDataKey="category"/> </createData> + <magentoCLI command="config:set catalog/seo/generate_category_product_rewrites 1" stepKey="enableGenerateUrlRewrite"/> <actionGroup ref="LoginAsAdmin" stepKey="login"/> </before> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml index a3d3b897ef75d..9fcca06df5c69 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml @@ -42,7 +42,7 @@ <deleteData createDataKey="simpleSubCategory2" stepKey="deleteSimpleSubCategory2"/> <deleteData createDataKey="simpleSubCategory1" stepKey="deleteSimpleSubCategory1"/> <comment userInput="Disable config to generate category/product URL Rewrites " stepKey="commentDisableConfig" /> - <magentoCLI command="config:set catalog/seo/generate_category_product_rewrites 0" stepKey="disableGenerateUrlRewrite"/> + <magentoCLI command="config:set catalog/seo/generate_category_product_rewrites 1" stepKey="disableGenerateUrlRewrite"/> <amOnPage url="{{AdminLogoutPage.url}}" stepKey="amOnLogoutPage"/> </after> From 4d814cba6ad8969a01e84113eacff03a1547c77e Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 15 Jan 2020 13:49:18 +0200 Subject: [PATCH 031/176] MC-30409: [FT] [MFTF] [2.4] Fix flaky test AdminCreateDuplicateProductTest (MC-14714) --- .../Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml | 3 --- .../Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml | 3 --- 2 files changed, 6 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml index 472de07baccdd..3eb617d19d54c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml @@ -15,9 +15,6 @@ <testCaseId value="MC-14714"/> <severity value="CRITICAL"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-30409"/> - </skip> </annotations> <before> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml index 3f2ae13a16657..9fcca06df5c69 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml @@ -16,9 +16,6 @@ <severity value="MAJOR"/> <testCaseId value="MC-20229"/> <group value="urlRewrite"/> - <skip> - <issueId value="MC-30409"/> - </skip> </annotations> <before> <comment userInput="Set the configuration for Generate category/product URL Rewrites" stepKey="commentSetURLRewriteConfiguration" /> From b6a0f86313ceb261638c6d648e8624e0971f36a3 Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Thu, 16 Jan 2020 11:13:20 +0200 Subject: [PATCH 032/176] MC-30111: [2.4] Test StorefrontCustomerCheckoutTest fails on Jenkins --- .../Test/StorefrontCustomerCheckoutTest.xml | 117 ++++++++---------- 1 file changed, 53 insertions(+), 64 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml index 861f379988031..8bdbabb584b83 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml @@ -10,88 +10,77 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="StorefrontCustomerCheckoutTest"> <annotations> - <features value="Checkout"/> - <stories value="Checkout via the Admin"/> - <title value="Customer Checkout via the Admin"/> + <features value="Customer Checkout"/> + <stories value="Checkout via Storefront"/> + <title value="Customer Checkout via Storefront"/> <description value="Should be able to place an order as a customer."/> <severity value="CRITICAL"/> - <testCaseId value="MC-5922"/> + <testCaseId value="MC-30274"/> <group value="checkout"/> - <skip> - <issueId value="MC-30111"/> - </skip> </annotations> <before> - <createData entity="SimpleSubCategory" stepKey="simplecategory"/> - <createData entity="SimpleProduct" stepKey="simpleproduct1"> - <requiredEntity createDataKey="simplecategory"/> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + <createData entity="SimpleProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> </createData> - <createData entity="Simple_US_Customer" stepKey="simpleuscustomer"/> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> </before> <after> - <!--Clear filters--> - <amOnPage url="{{AdminCustomerPage.url}}" stepKey="navigateToCustomers"/> - <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearExistingCustomerFilters"/> - - <actionGroup ref="logout" stepKey="logout"/> - <deleteData createDataKey="simpleproduct1" stepKey="deleteProduct1"/> - <deleteData createDataKey="simplecategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteSimpleCategory"/> + <deleteData createDataKey="createCustomer" stepKey="deleteUsCustomer"/> + <actionGroup ref="AdminClearCustomersFiltersActionGroup" stepKey="resetCustomerFilters"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> </after> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> - <argument name="Customer" value="$$simpleuscustomer$$" /> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="storefrontCustomerLogin"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="navigateToCategoryPage"> + <argument name="category" value="$$createCategory$$"/> </actionGroup> - <amOnPage url="{{StorefrontCategoryPage.url($$simplecategory.name$$)}}" stepKey="onCategoryPage"/> <waitForPageLoad stepKey="waitForCatalogPageLoad"/> - <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverProduct"/> - <click selector="{{StorefrontCategoryMainSection.AddToCartBtn}}" stepKey="addToCart"/> - <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" time="30" stepKey="waitForProductAdded"/> - <see selector="{{StorefrontCategoryMainSection.SuccessMsg}}" userInput="You added $$simpleproduct1.name$$ to your shopping cart." stepKey="seeAddedToCartMessage"/> - <see selector="{{StorefrontMinicartSection.quantity}}" userInput="1" stepKey="seeCartQuantity"/> - <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart" /> - <click stepKey="s35" selector="{{CheckoutShippingMethodsSection.firstShippingMethod}}"/> - <waitForElement stepKey="s36" selector="{{CheckoutShippingMethodsSection.next}}" time="30"/> - <click stepKey="s37" selector="{{CheckoutShippingMethodsSection.next}}" /> - <!-- Checkout select Check/Money Order payment --> - <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyPayment"/> - <waitForPageLoad stepKey="s39"/> - <waitForElement stepKey="s41" selector="{{CheckoutPaymentSection.placeOrder}}" time="30" /> - <see stepKey="s47" selector="{{CheckoutPaymentSection.billingAddress}}" userInput="{{US_Address_TX.street[0]}}" /> - <click stepKey="s49" selector="{{CheckoutPaymentSection.placeOrder}}" /> - <waitForPageLoad stepKey="s51"/> - <grabTextFrom stepKey="s53" selector="{{CheckoutSuccessMainSection.orderNumber22}}"/> - <see stepKey="s55" selector="{{CheckoutSuccessMainSection.success}}" userInput="Your order number is:" /> + <actionGroup ref="StorefrontAddCategoryProductToCartActionGroup" stepKey="addProductToCart"> + <argument name="product" value="$$createSimpleProduct$$"/> + <argument name="productCount" value="CONST.one"/> + </actionGroup> + + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> + <actionGroup ref="CheckoutSelectFlatRateShippingMethodActionGroup" stepKey="selectFlatRate"/> + <actionGroup ref="StorefrontCheckoutForwardFromShippingStepActionGroup" stepKey="goToReview"/> + <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyOrder"/> + <actionGroup ref="CheckoutPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"> + <argument name="orderNumberMessage" value="CONST.successCheckoutOrderNumberMessage"/> + <argument name="emailYouMessage" value="CONST.successCheckoutEmailYouMessage"/> + </actionGroup> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="orderNumber"/> - <amOnPage stepKey="s67" url="{{AdminOrdersPage.url}}"/> - <waitForPageLoad stepKey="s75"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearFiltersIfPresent"/> - <fillField stepKey="s77" selector="{{AdminOrdersGridSection.search}}" userInput="{$s53}" /> - <waitForPageLoad stepKey="s78"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <click stepKey="s81" selector="{{AdminOrdersGridSection.submitSearch22}}" /> - <waitForPageLoad stepKey="s831"/> - <click stepKey="s84" selector="{{AdminOrdersGridSection.firstRow}}" /> - <waitForPageLoad stepKey="waitForOrderToLoad"/> - <see stepKey="s85" selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" /> - <see stepKey="s87" selector="{{AdminOrderDetailsInformationSection.accountInformation}}" userInput="Customer" /> - <see stepKey="s89" selector="{{AdminOrderDetailsInformationSection.accountInformation}}" userInput="$$simpleuscustomer.email$$" /> - <see stepKey="s91" selector="{{AdminOrderDetailsInformationSection.billingAddress}}" userInput="{{US_Address_TX.street[0]}}" /> - <see stepKey="s93" selector="{{AdminOrderDetailsInformationSection.shippingAddress}}" userInput="{{US_Address_TX.street[0]}}" /> - <see stepKey="s95" selector="{{AdminOrderDetailsInformationSection.itemsOrdered}}" userInput="$$simpleproduct1.name$$" /> + <actionGroup ref="OpenOrderByIdActionGroup" stepKey="addFilterToGridAndOpenOrder"> + <argument name="orderId" value="{$orderNumber}"/> + </actionGroup> + + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="verifyOrderStatus"/> + <see selector="{{AdminOrderDetailsInformationSection.accountInformation}}" userInput="Customer" stepKey="verifyAccountInformation"/> + <see selector="{{AdminOrderDetailsInformationSection.accountInformation}}" userInput="$$createCustomer.email$$" stepKey="verifyCustomerEmail"/> + <see selector="{{AdminOrderDetailsInformationSection.billingAddress}}" userInput="{{US_Address_TX.street[0]}}" stepKey="verifyBillingAddress"/> + <see selector="{{AdminOrderDetailsInformationSection.shippingAddress}}" userInput="{{US_Address_TX.street[0]}}" stepKey="verifyShippingAddress"/> + <see selector="{{AdminOrderDetailsInformationSection.itemsOrdered}}" userInput="$$createSimpleProduct.name$$" stepKey="verifyProductName"/> + + <actionGroup ref="OpenEditCustomerFromAdminActionGroup" stepKey="openCustomerEditPage"> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> - <amOnPage stepKey="s96" url="{{AdminCustomerPage.url}}"/> - <waitForPageLoad stepKey="s97"/> - <waitForElementVisible selector="{{AdminCustomerFiltersSection.filtersButton}}" time="30" stepKey="waitFiltersButton"/> - <click stepKey="s98" selector="{{AdminCustomerFiltersSection.filtersButton}}"/> - <fillField stepKey="s99" selector="{{AdminCustomerFiltersSection.emailInput}}" userInput="$$simpleuscustomer.email$$"/> - <click stepKey="s100" selector="{{AdminCustomerFiltersSection.apply}}"/> - <click stepKey="s101" selector="{{AdminCustomerGridSection.firstRowEditLink}}"/> - <click stepKey="s102" selector="{{AdminEditCustomerInformationSection.orders}}"/> - <see stepKey="s103" selector="{{AdminEditCustomerOrdersSection.orderGrid}}" userInput="$$simpleuscustomer.firstname$$ $$simpleuscustomer.lastname$$" /> + <click selector="{{AdminEditCustomerInformationSection.orders}}" stepKey="navigateToOrdersTab"/> + <waitForElementVisible selector="{{AdminEditCustomerOrdersSection.orderGrid}}" stepKey="waitForOrdersGridVisible"/> + <see selector="{{AdminEditCustomerOrdersSection.orderGrid}}" userInput="$$createCustomer.firstname$$ $$createCustomer.lastname$$" stepKey="verifyOrder"/> </test> <test name="StorefrontCustomerCheckoutTestWithMultipleAddressesAndTaxRates"> <annotations> From a8f1ee7a56fcb13496b4ea70dd906c61d66685e9 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Thu, 16 Jan 2020 11:58:02 +0200 Subject: [PATCH 033/176] magento/magento2#25488: Composer update. --- composer.lock | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index b6d834610059a..d00a2c337df68 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "8d8e6b87c1f6ac98b3b7331eba9473f3", + "content-hash": "8ca9b4a6ea63c83444b1506f53d6c115", "packages": [ { "name": "braintree/braintree_php", @@ -88,16 +88,16 @@ }, { "name": "colinmollenhour/cache-backend-redis", - "version": "1.10.6", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/colinmollenhour/Cm_Cache_Backend_Redis.git", - "reference": "cc941a5f4cc017e11d3eab9061811ba9583ed6bf" + "reference": "389fb68de15660e39b055d149d31f3708b5d6cbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/colinmollenhour/Cm_Cache_Backend_Redis/zipball/cc941a5f4cc017e11d3eab9061811ba9583ed6bf", - "reference": "cc941a5f4cc017e11d3eab9061811ba9583ed6bf", + "url": "https://api.github.com/repos/colinmollenhour/Cm_Cache_Backend_Redis/zipball/389fb68de15660e39b055d149d31f3708b5d6cbc", + "reference": "389fb68de15660e39b055d149d31f3708b5d6cbc", "shasum": "" }, "require": { @@ -120,7 +120,7 @@ ], "description": "Zend_Cache backend using Redis with full support for tags.", "homepage": "https://github.com/colinmollenhour/Cm_Cache_Backend_Redis", - "time": "2018-09-24T16:02:07+00:00" + "time": "2019-03-03T04:04:49+00:00" }, { "name": "colinmollenhour/credis", @@ -2841,6 +2841,7 @@ "captcha", "zf" ], + "abandoned": "laminas/laminas-captcha", "time": "2019-06-18T09:32:52+00:00" }, { @@ -2894,6 +2895,7 @@ "code", "zf" ], + "abandoned": "laminas/laminas-code", "time": "2019-08-31T14:14:34+00:00" }, { @@ -2950,6 +2952,7 @@ "config", "zf2" ], + "abandoned": "laminas/laminas-config", "time": "2016-02-04T23:01:10+00:00" }, { @@ -3003,6 +3006,7 @@ "console", "zf" ], + "abandoned": "laminas/laminas-console", "time": "2019-02-04T19:48:22+00:00" }, { @@ -3053,6 +3057,7 @@ "crypt", "zf2" ], + "abandoned": "laminas/laminas-crypt", "time": "2016-02-03T23:46:30+00:00" }, { @@ -3111,6 +3116,7 @@ "db", "zf" ], + "abandoned": "laminas/laminas-db", "time": "2019-02-25T11:37:45+00:00" }, { @@ -3158,6 +3164,7 @@ "di", "zf2" ], + "abandoned": "laminas/laminas-di", "time": "2016-04-25T20:58:11+00:00" }, { @@ -3220,6 +3227,7 @@ "psr", "psr-7" ], + "abandoned": "laminas/laminas-diactoros", "time": "2019-08-06T17:53:53+00:00" }, { @@ -3265,6 +3273,7 @@ "escaper", "zf" ], + "abandoned": "laminas/laminas-escaper", "time": "2019-09-05T20:03:20+00:00" }, { @@ -3319,6 +3328,7 @@ "events", "zf2" ], + "abandoned": "laminas/laminas-eventmanager", "time": "2018-04-25T15:33:34+00:00" }, { @@ -3382,6 +3392,7 @@ "feed", "zf" ], + "abandoned": "laminas/laminas-feed", "time": "2019-03-05T20:08:49+00:00" }, { @@ -3447,6 +3458,7 @@ "filter", "zf" ], + "abandoned": "laminas/laminas-filter", "time": "2019-08-19T07:08:04+00:00" }, { @@ -3525,6 +3537,7 @@ "form", "zf" ], + "abandoned": "laminas/laminas-form", "time": "2019-10-04T10:46:36+00:00" }, { @@ -3580,6 +3593,7 @@ "zend", "zf" ], + "abandoned": "laminas/laminas-http", "time": "2019-02-19T18:58:14+00:00" }, { @@ -3640,6 +3654,7 @@ "hydrator", "zf" ], + "abandoned": "laminas/laminas-hydrator", "time": "2019-10-04T11:17:36+00:00" }, { @@ -3708,6 +3723,7 @@ "i18n", "zf" ], + "abandoned": "laminas/laminas-i18n", "time": "2019-09-30T12:04:37+00:00" }, { @@ -3765,6 +3781,7 @@ "inputfilter", "zf" ], + "abandoned": "laminas/laminas-inputfilter", "time": "2019-08-28T19:45:32+00:00" }, { @@ -3820,6 +3837,7 @@ "json", "zf2" ], + "abandoned": "laminas/laminas-json", "time": "2016-02-04T21:20:26+00:00" }, { @@ -3865,6 +3883,7 @@ "loader", "zf" ], + "abandoned": "laminas/laminas-loader", "time": "2019-09-04T19:38:14+00:00" }, { @@ -3935,6 +3954,7 @@ "logging", "zf" ], + "abandoned": "laminas/laminas-log", "time": "2019-08-23T21:28:18+00:00" }, { @@ -3997,6 +4017,7 @@ "mail", "zf" ], + "abandoned": "laminas/laminas-mail", "time": "2018-06-07T13:37:07+00:00" }, { @@ -4047,6 +4068,7 @@ "math", "zf2" ], + "abandoned": "laminas/laminas-math", "time": "2018-12-04T15:34:17+00:00" }, { @@ -4097,6 +4119,7 @@ "mime", "zf" ], + "abandoned": "laminas/laminas-mime", "time": "2019-10-16T19:30:37+00:00" }, { @@ -4156,6 +4179,7 @@ "modulemanager", "zf" ], + "abandoned": "laminas/laminas-modulemanager", "time": "2019-10-28T13:29:38+00:00" }, { @@ -4251,6 +4275,7 @@ "mvc", "zf2" ], + "abandoned": "laminas/laminas-mvc", "time": "2018-05-03T13:13:41+00:00" }, { @@ -4300,6 +4325,7 @@ "psr", "psr-7" ], + "abandoned": "laminas/laminas-psr7bridge", "time": "2016-05-10T21:44:39+00:00" }, { @@ -4357,6 +4383,7 @@ "serializer", "zf" ], + "abandoned": "laminas/laminas-serializer", "time": "2019-10-19T08:06:30+00:00" }, { @@ -4404,6 +4431,7 @@ "server", "zf" ], + "abandoned": "laminas/laminas-server", "time": "2019-10-16T18:27:05+00:00" }, { @@ -4456,6 +4484,7 @@ "servicemanager", "zf2" ], + "abandoned": "laminas/laminas-servicemanager", "time": "2018-06-22T14:49:54+00:00" }, { @@ -4523,6 +4552,7 @@ "session", "zf" ], + "abandoned": "laminas/laminas-session", "time": "2019-10-28T19:40:43+00:00" }, { @@ -4576,6 +4606,7 @@ "soap", "zf2" ], + "abandoned": "laminas/laminas-soap", "time": "2019-04-30T16:45:35+00:00" }, { @@ -4622,6 +4653,7 @@ "stdlib", "zf" ], + "abandoned": "laminas/laminas-stdlib", "time": "2018-08-28T21:34:05+00:00" }, { @@ -4670,6 +4702,7 @@ "text", "zf" ], + "abandoned": "laminas/laminas-text", "time": "2019-10-16T20:36:27+00:00" }, { @@ -4717,6 +4750,7 @@ "uri", "zf" ], + "abandoned": "laminas/laminas-uri", "time": "2019-10-07T13:35:33+00:00" }, { @@ -4790,6 +4824,7 @@ "validator", "zf" ], + "abandoned": "laminas/laminas-validator", "time": "2019-10-29T08:33:25+00:00" }, { @@ -4877,6 +4912,7 @@ "view", "zf" ], + "abandoned": "laminas/laminas-view", "time": "2019-10-11T21:10:04+00:00" } ], From fb90fd701cf37b24d9f678a74cc91488f27bee79 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 16 Jan 2020 16:00:35 +0200 Subject: [PATCH 034/176] MC-25108: MFTF Flakiness because of bad design - StoreFrontMyAccountWithMultishipmentTest --- .../Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml | 1 + ...ertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml | 4 ++++ .../Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml | 4 ++-- 3 files changed, 7 insertions(+), 2 deletions(-) rename app/code/Magento/{Multishipping => Sales}/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml (91%) diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml index 26a1892cb679e..dbc1ba980e9c7 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml @@ -16,6 +16,7 @@ <description value="Verify that shipping price on My account matches with shipping method prices after multiple addresses checkout (Order view page)"/> <severity value="CRITICAL"/> <testCaseId value="MC-28900"/> + <useCaseId value="MC-19303"/> <group value="catalog"/> <group value="sales"/> <group value="multishipping"/> diff --git a/app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml similarity index 91% rename from app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml rename to app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml index 9281cdf03a1ab..b5361363c489b 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml @@ -9,6 +9,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <actionGroup name="AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup"> + <annotations> + <description>Check that order grand total equals sum of all totals.</description> + </annotations> + <grabTextFrom selector="{{StorefrontSalesOrderSection.salesOrderPrice('subtotal')}}" stepKey="grabValueForSubtotal"/> <grabTextFrom selector="{{StorefrontSalesOrderSection.salesOrderPrice('shipping')}}" stepKey="grabValueForShippingHandling"/> <grabTextFrom selector="{{StorefrontSalesOrderSection.salesOrderPrice('grand_total')}}" stepKey="grabValueForGrandTotal"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml index 5b079891f657a..0964ef5811cec 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontCustomerOrdersGridSection"> - <element name="orderView" type="button" selector="//td[text()='{{orderNumber}}']/following-sibling::td[@class='col actions']/a[contains(@class, 'view')]" parameterized="true" timeout="30" /> - <element name="reorderBtn" type="button" selector="//td[text()='{{orderNumber}}']/following-sibling::td[@class='col actions']/a[contains(@class, 'order')]" parameterized="true" timeout="30" /> + <element name="orderView" type="button" selector="//td[contains(text(),'{{orderNumber}}')]/following-sibling::td[contains(@class,'col') and contains(@class,'actions')]/a[contains(@class, 'view')]" parameterized="true" timeout="30" /> + <element name="reorderBtn" type="button" selector="//td[contains(text(),'{{orderNumber}}')]/following-sibling::td[contains(@class,'col') and contains(@class,'actions')]/a[contains(@class, 'order')]" parameterized="true" timeout="30" /> </section> </sections> From ca69fd22d5d644b6d5347aae5ef57407dfd49bd4 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 16 Jan 2020 16:30:22 +0200 Subject: [PATCH 035/176] MC-23546: Child Configurable product does not save disabled status via API --- .../StorefrontQuickSearchConfigurableChildrenTest.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml index 03ce878ef4f9f..1169d053ec7c8 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml @@ -14,8 +14,8 @@ <title value="User should be able to use Quick Search to a configurable product's child products"/> <description value="Use Quick Search to find a configurable product with enabled/disable children"/> <severity value="MAJOR"/> - <testCaseId value="MC-14798"/> - <group value="CatalogSearch"/> + <testCaseId value="MC-28374"/> + <group value="catalogSearch"/> <group value="mtf_migrated"/> </annotations> <before> @@ -75,20 +75,19 @@ <magentoCLI command="indexer:reindex" stepKey="reindex"/> </before> <after> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> <deleteData createDataKey="createConfigurableProduct" stepKey="deleteConfigurableProduct"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </after> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePage"/> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> <argument name="phrase" value="$createConfigurableProduct.name$"/> </actionGroup> - <actionGroup ref="StorefrontQuickSearchCheckProductNameInGridActionGroup" stepKey="seeProductInGrid"> + <actionGroup ref="StorefrontQuickSearchSeeProductByNameActionGroup" stepKey="seeProductInGrid"> <argument name="productName" value="$createConfigurableProduct.name$"/> - <argument name="index" value="1"/> </actionGroup> <!-- Disable Child Product --> From 92816ab04db61666741ae9ab0986175068c46bee Mon Sep 17 00:00:00 2001 From: Fanis Strezos <fanis.strezos@dotdigital.com> Date: Thu, 16 Jan 2020 15:38:32 +0000 Subject: [PATCH 036/176] update getCustomer method in order class --- .../Magento/Sales/Api/Data/OrderInterface.php | 8 +++++++ app/code/Magento/Sales/Model/Order.php | 23 ++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Api/Data/OrderInterface.php b/app/code/Magento/Sales/Api/Data/OrderInterface.php index b45fddc7d7354..f699d24bd32cd 100644 --- a/app/code/Magento/Sales/Api/Data/OrderInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderInterface.php @@ -5,6 +5,8 @@ */ namespace Magento\Sales\Api\Data; +use Magento\Customer\Model\Customer; + /** * Order interface. * @@ -910,6 +912,12 @@ public function getCreatedAt(); */ public function setCreatedAt($createdAt); + /** + * Gets the customer from Order + * @return Customer + */ + public function getCustomer(); + /** * Gets the customer date-of-birth (DOB) for the order. * diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 89564f97ccf16..1d520574f21d7 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -6,6 +6,7 @@ namespace Magento\Sales\Model; use Magento\Config\Model\Config\Source\Nooptreq; +use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Directory\Model\Currency; use Magento\Framework\Api\AttributeValueFactory; use Magento\Framework\Api\SearchCriteriaBuilder; @@ -51,7 +52,6 @@ * @method bool hasCustomerNoteNotify() * @method bool hasForcedCanCreditmemo() * @method bool getIsInProcess() - * @method \Magento\Customer\Model\Customer getCustomer() * @method \Magento\Sales\Model\Order setSendEmail(bool $value) * @SuppressWarnings(PHPMD.ExcessivePublicCount) * @SuppressWarnings(PHPMD.TooManyFields) @@ -307,6 +307,11 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface */ private $scopeConfig; + /** + * @var CustomerRepositoryInterface + */ + private $_customerRepositoryInterface; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -340,6 +345,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface * @param OrderItemRepositoryInterface $itemRepository * @param SearchCriteriaBuilder $searchCriteriaBuilder * @param ScopeConfigInterface $scopeConfig + * @param CustomerRepositoryInterface $customerRepositoryInterface * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -366,6 +372,7 @@ public function __construct( \Magento\Sales\Model\ResourceModel\Order\Shipment\Track\CollectionFactory $trackCollectionFactory, \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $salesOrderCollectionFactory, PriceCurrencyInterface $priceCurrency, + CustomerRepositoryInterface $customerRepositoryInterface, \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productListFactory, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, @@ -403,6 +410,7 @@ public function __construct( $this->searchCriteriaBuilder = $searchCriteriaBuilder ?: ObjectManager::getInstance() ->get(SearchCriteriaBuilder::class); $this->scopeConfig = $scopeConfig ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class); + $this->_customerRepositoryInterface = $customerRepositoryInterface; parent::__construct( $context, @@ -562,6 +570,19 @@ public function getStore() return $this->_storeManager->getStore(); } + /** + * Returns Customer + * + * @return \Magento\Customer\Api\Data\CustomerInterface + * @throws LocalizedException + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function getCustomer() + { + $customerId = $this->getData(OrderInterface::CUSTOMER_ID); + return $this->_customerRepositoryInterface->getById($customerId); + } + /** * Retrieve order cancel availability * From 2481c0bd065488d75f23a7f3769a0c7bc2cfecc1 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Fri, 17 Jan 2020 11:06:00 +0200 Subject: [PATCH 037/176] MC-29047: Fix MFTF test --- ...ml => StorefrontOpenProductFromCategoryPageActionGroup.xml} | 2 +- ...yConfigurableProductChildAssignedToSeparateCategoryTest.xml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) rename app/code/Magento/Catalog/Test/Mftf/ActionGroup/{StorefrontCategoryPageOpenProductActionGroup.xml => StorefrontOpenProductFromCategoryPageActionGroup.xml} (91%) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryPageOpenProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenProductFromCategoryPageActionGroup.xml similarity index 91% rename from app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryPageOpenProductActionGroup.xml rename to app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenProductFromCategoryPageActionGroup.xml index 86ce7a602315d..39bffe006d987 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryPageOpenProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenProductFromCategoryPageActionGroup.xml @@ -7,7 +7,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="StorefrontCategoryPageOpenProductActionGroup"> + <actionGroup name="StorefrontOpenProductFromCategoryPageActionGroup"> <annotations> <description>Click on the provided product on category page.</description> </annotations> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml index 5f2fc5c8caca7..56e5bedc9eab1 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml @@ -17,6 +17,7 @@ <severity value="CRITICAL"/> <testCaseId value="MC-25651"/> <group value="configurable_product"/> + <group value="catalog"/> </annotations> <before> <!-- Create the category --> @@ -123,7 +124,7 @@ <actionGroup ref="StorefrontCheckProductIsMissingInCategoryProductsPageActionGroup" stepKey="dontSeeParentProduct"> <argument name="productName" value="$$createConfigProduct.name$$"/> </actionGroup> - <actionGroup ref="StorefrontCategoryPageOpenProductActionGroup" stepKey="openConfigChildProductFromCategoryPage"> + <actionGroup ref="StorefrontOpenProductFromCategoryPageActionGroup" stepKey="openConfigChildProductFromCategoryPage"> <argument name="productName" value="$$createConfigChildProduct1.name$$"/> </actionGroup> <actionGroup ref="AssertStorefrontProductDetailPageNameAndUrlActionGroup" stepKey="checkStorefrontConfigChildProductPage"> From 162622f66cba3dc7cb45a2162384df967edd6542 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 17 Jan 2020 12:50:05 +0200 Subject: [PATCH 038/176] MC-30510: [Integration] PaymentFailuresServiceTest::testHandlerWithCustomer is flaky --- .../Service/PaymentFailuresServiceTest.php | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php index 383af7968e047..c85408f21819a 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php @@ -7,10 +7,12 @@ namespace Magento\Sales\Model\Service; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Model\Quote; use Magento\Sales\Api\PaymentFailuresInterface; use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\MockObject\MockObject; /** * Tests \Magento\Sales\Api\PaymentFailuresInterface. @@ -28,10 +30,15 @@ class PaymentFailuresServiceTest extends \PHPUnit\Framework\TestCase private $quote; /** - * @var CartRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CartRepositoryInterface|MockObject */ private $cartRepositoryMock; + /** + * @var TimezoneInterface|MockObject + */ + private $localeDateMock; + /** * @inheritdoc */ @@ -42,11 +49,15 @@ protected function setUp() ->disableOriginalConstructor() ->setMethods(['get']) ->getMockForAbstractClass(); + $this->localeDateMock = $this->getMockBuilder(TimezoneInterface::class) + ->setMethods(['formatDateTime']) + ->getMockForAbstractClass(); $this->paymentFailures = Bootstrap::getObjectManager()->create( PaymentFailuresInterface::class, [ 'cartRepository' => $this->cartRepositoryMock, + 'localeDate' => $this->localeDateMock, ] ); } @@ -69,20 +80,19 @@ public function testHandlerWithCustomer(): void ->with($this->quote->getId()) ->willReturn($this->quote); + $dateAndTime = 'Nov 22, 2019, 1:00:00 AM'; + $this->localeDateMock->expects($this->atLeastOnce())->method('formatDateTime')->willReturn($dateAndTime); $this->paymentFailures->handle((int)$this->quote->getId(), $errorMessage->render()); $paymentReflection = new \ReflectionClass($this->paymentFailures); - $templateTimeMethod = $paymentReflection->getMethod('getLocaleDate'); - $templateTimeMethod->setAccessible(true); - $templateVarsMethod = $paymentReflection->getMethod('getTemplateVars'); $templateVarsMethod->setAccessible(true); $templateVars = $templateVarsMethod->invoke($this->paymentFailures, $this->quote, $errorMessage, $checkoutType); $expectedVars = [ - 'reason' => $errorMessage, + 'reason' => $errorMessage->render(), 'checkoutType' => $checkoutType, - 'dateAndTime' => $templateTimeMethod->invoke($this->paymentFailures), + 'dateAndTime' => $dateAndTime, 'customer' => 'John Smith', 'customerEmail' => 'aaa@aaa.com', 'paymentMethod' => 'Some Title Of The Method', From d6eff7b04bbbfd20fbb71a793daef5c93edb998e Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Fri, 17 Jan 2020 16:53:44 +0200 Subject: [PATCH 039/176] MC-24168: Fix Skipped MFTF Tests From MC-17140: MAGETWO-95175, MAGETWO-97001, MAGETWO-98189 --- .../Catalog/Test/Mftf/Data/ConstData.xml | 2 + .../Section/AdminCategoryProductsSection.xml | 4 +- ...ateCategoryProductUrlRewriteConfigData.xml | 22 +++ ...OpenCreditMemoFromOrderPageActionGroup.xml | 20 +++ ...minOpenInvoiceFromOrderPageActionGroup.xml | 20 +++ ...inOpenShipmentFromOrderPageActionGroup.xml | 20 +++ ...eateCreditMemoFromOrderPageActionGroup.xml | 19 +++ ...rtAdminCreditMemoGrandTotalActionGroup.xml | 21 +++ .../Section/AdminOrderShipmentsTabSection.xml | 3 +- ...axRuleCustomProductTaxClassActionGroup.xml | 31 ++++ .../Tax/Test/Mftf/Data/TaxConfigData.xml | 6 + .../Mftf/Section/AdminTaxRulesSection.xml | 1 + .../Test/AdminCheckCreditMemoTotalsTest.xml | 91 +++++++++++ .../Mftf/Test/CheckCreditMemoTotalsTest.xml | 148 ------------------ 14 files changed, 258 insertions(+), 150 deletions(-) create mode 100644 app/code/Magento/CatalogUrlRewrite/Test/Mftf/Data/GenerateCategoryProductUrlRewriteConfigData.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenCreditMemoFromOrderPageActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenInvoiceFromOrderPageActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenShipmentFromOrderPageActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminStartToCreateCreditMemoFromOrderPageActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminCreditMemoGrandTotalActionGroup.xml create mode 100644 app/code/Magento/Tax/Test/Mftf/ActionGroup/AdminCreateTaxRuleCustomProductTaxClassActionGroup.xml create mode 100644 app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml delete mode 100644 app/code/Magento/Tax/Test/Mftf/Test/CheckCreditMemoTotalsTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml index d09880f14afbf..f44bfb217d0ae 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml @@ -16,5 +16,7 @@ <entity name="prodNameWithSpecChars"> <data key="trademark">"Pursuit Lumaflex™ Tone Band"</data> <data key="skumark">"x™"</data> + <data key="trademark_without_quotes">Pursuit Lumaflex™ Tone Band</data> + <data key="skumark_without_quotes">x™</data> </entity> </entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml index 8a993a74a58d1..d89d9a5bd43c0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml @@ -12,5 +12,7 @@ <element name="sectionHeader" type="button" selector="div[data-index='assign_products']" timeout="30"/> <element name="addProducts" type="button" selector="#catalog_category_add_product_tabs" timeout="30"/> <element name="addProductsDisabled" type="button" selector="#catalog_category_add_product_tabs[disabled]" timeout="30"/> + <element name="productsInCategorySectionTitle" type="text" selector="div[data-index='assign_products'] .fieldset-wrapper-title" timeout="10"/> + <element name="productsInCategorySectionBody" type="text" selector="div[data-index='assign_products'] .admin__fieldset-wrapper-content"/> </section> -</sections> \ No newline at end of file +</sections> diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Data/GenerateCategoryProductUrlRewriteConfigData.xml b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Data/GenerateCategoryProductUrlRewriteConfigData.xml new file mode 100644 index 0000000000000..10d2213b64717 --- /dev/null +++ b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Data/GenerateCategoryProductUrlRewriteConfigData.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="EnableGenerateCategoryProductUrlRewritesConfigData"> + <!-- Default value --> + <data key="path">catalog/seo/generate_category_product_rewrites</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisableGenerateCategoryProductUrlRewritesConfigData"> + <data key="path">catalog/seo/generate_category_product_rewrites</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> +</entities> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenCreditMemoFromOrderPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenCreditMemoFromOrderPageActionGroup.xml new file mode 100644 index 0000000000000..fab25c7f40681 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenCreditMemoFromOrderPageActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenCreditMemoFromOrderPageActionGroup"> + <annotations> + <description>Admin open creditmemo from order</description> + </annotations> + <conditionalClick selector="{{AdminOrderDetailsOrderViewSection.creditMemos}}" dependentSelector="{{AdminOrderCreditMemosTabSection.viewGridRow('1')}}" visible="false" stepKey="openCreditMemosTab"/> + <waitForElementVisible selector="{{AdminCreditMemoTotalSection.viewMemo}}" stepKey="waitForCreditMemosTabOpened"/> + <click selector="{{AdminOrderCreditMemosTabSection.viewGridRow('1')}}" stepKey="viewMemo"/> + <waitForPageLoad stepKey="waitForCreditMemoOpened"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenInvoiceFromOrderPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenInvoiceFromOrderPageActionGroup.xml new file mode 100644 index 0000000000000..ec4352c15e1a8 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenInvoiceFromOrderPageActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenInvoiceFromOrderPageActionGroup"> + <annotations> + <description>Admin open invoice from order</description> + </annotations> + <conditionalClick selector="{{AdminOrderDetailsOrderViewSection.invoices}}" dependentSelector="{{AdminOrderInvoicesTabSection.viewInvoice}}" visible="false" stepKey="openInvoicesTab"/> + <waitForElementVisible selector="{{AdminOrderInvoicesTabSection.viewInvoice}}" stepKey="waitForInvocesTabOpened"/> + <click selector="{{AdminOrderInvoicesTabSection.viewGridRow('1')}}" stepKey="viewInvoice"/> + <waitForPageLoad stepKey="waitForInvoiceOpened"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenShipmentFromOrderPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenShipmentFromOrderPageActionGroup.xml new file mode 100644 index 0000000000000..1ed31b93cb075 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenShipmentFromOrderPageActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenShipmentFromOrderPageActionGroup"> + <annotations> + <description>Admin open shipment from order</description> + </annotations> + <conditionalClick selector="{{AdminOrderDetailsOrderViewSection.shipments}}" dependentSelector="{{AdminOrderShipmentsTabSection.viewShipment}}" visible="false" stepKey="openShipmentsTab"/> + <waitForElementVisible selector="{{AdminOrderShipmentsTabSection.viewShipment}}" stepKey="waitForShipmentTabOpened"/> + <click selector="{{AdminOrderShipmentsTabSection.viewGridRow('1')}}" stepKey="viewShipment"/> + <waitForPageLoad stepKey="waitForShipmentOpened"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminStartToCreateCreditMemoFromOrderPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminStartToCreateCreditMemoFromOrderPageActionGroup.xml new file mode 100644 index 0000000000000..e5c29ac33294e --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminStartToCreateCreditMemoFromOrderPageActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminStartToCreateCreditMemoFromOrderPageActionGroup"> + <annotations> + <description>Admin start to create credit memo from order</description> + </annotations> + <click selector="{{AdminOrderDetailsMainActionsSection.creditMemo}}" stepKey="clickCreditMemo"/> + <waitForElementVisible selector="{{AdminHeaderSection.pageTitle}}" stepKey="waitForPageTitle"/> + <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Memo" stepKey="seeNewMemoPageTitle"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminCreditMemoGrandTotalActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminCreditMemoGrandTotalActionGroup.xml new file mode 100644 index 0000000000000..f318e76ce74a8 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminCreditMemoGrandTotalActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertAdminCreditMemoGrandTotalActionGroup"> + <annotations> + <description>Admin assert creditmemo grant total sum</description> + </annotations> + <arguments> + <argument name="expectedGrandTotal" type="string" defaultValue="$123.00"/> + </arguments> + <grabTextFrom selector="{{AdminCreditMemoTotalSection.grandTotal}}" stepKey="getGrandTotal"/> + <assertEquals expected='{{expectedGrandTotal}}' actualType="variable" expectedType="string" actual="getGrandTotal" stepKey="assertGrandTotalValue"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml index e471fcfe18114..66bea45b83f3d 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml @@ -18,5 +18,6 @@ <element name="shipmentId" type="input" selector="//div[@id='sales_order_view_tabs_order_shipments_content']//input[@name='increment_id']" timeout="30"/> <element name="totalQtyFrom" type="input" selector="[name='total_qty[from]']" timeout="30"/> <element name="totalQtyTo" type="input" selector="[name='total_qty[to]']" timeout="30"/> + <element name="viewShipment" type="button" selector="#sales_order_view_tabs_order_shipments_content div.admin__data-grid-wrap a.action-menu-item" timeout="30"/> </section> -</sections> \ No newline at end of file +</sections> diff --git a/app/code/Magento/Tax/Test/Mftf/ActionGroup/AdminCreateTaxRuleCustomProductTaxClassActionGroup.xml b/app/code/Magento/Tax/Test/Mftf/ActionGroup/AdminCreateTaxRuleCustomProductTaxClassActionGroup.xml new file mode 100644 index 0000000000000..377985a81af37 --- /dev/null +++ b/app/code/Magento/Tax/Test/Mftf/ActionGroup/AdminCreateTaxRuleCustomProductTaxClassActionGroup.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateTaxRuleCustomProductTaxClassActionGroup"> + <annotations> + <description>Admin create tax rule with custom tax rate and product tax class</description> + </annotations> + <arguments> + <argument name="taxRuleCode" type="string" defaultValue="{{defaultTaxRule.code}}"/> + <argument name="taxRateCode" type="string" defaultValue="{{US_NY_Rate_1.code}}"/> + <argument name="productTaxClassName" type="string" defaultValue="NewTaxClass"/> + </arguments> + <amOnPage url="{{AdminNewTaxRulePage.url}}" stepKey="goNewTaxRulePage"/> + <waitForPageLoad stepKey="waitForNewTaxRulePageLoaded"/> + <fillField selector="{{AdminTaxRulesSection.ruleName}}" userInput="{{taxRuleCode}}" stepKey="fillRuleName"/> + <click selector="{{AdminTaxRulesSection.selectTaxRate(taxRateCode)}}" stepKey="selectTaxRate"/> + <click selector="{{AdminTaxRuleFormSection.additionalSettings}}" stepKey="clickAdditionalSettings"/> + <click selector="{{AdminTaxRulesSection.selectProductTaxClass(taxableGoodsTaxClass.class_name)}}" stepKey="unSelectTaxClass"/> + <click selector="{{AdminTaxRulesSection.selectProductTaxClass(productTaxClassName)}}" stepKey="selectProductTaxClass"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSave"/> + <waitForElementVisible selector="{{AdminMessagesSection.successMessage}}" stepKey="waitForSuccessMessage"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="You saved the tax rule." stepKey="verifyRuleSaved"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Tax/Test/Mftf/Data/TaxConfigData.xml b/app/code/Magento/Tax/Test/Mftf/Data/TaxConfigData.xml index 4edf005c2fc2b..ad92bae51d429 100644 --- a/app/code/Magento/Tax/Test/Mftf/Data/TaxConfigData.xml +++ b/app/code/Magento/Tax/Test/Mftf/Data/TaxConfigData.xml @@ -57,4 +57,10 @@ <entity name="EmptyField" type="taxPostCodeEmpty"> <data key="value"/> </entity> + <entity name="DefaultProductTaxClass"> + <!-- Default value --> + <data key="path">tax/classes/default_product_tax_class</data> + <data key="label">Yes</data> + <data key="value">2</data> + </entity> </entities> diff --git a/app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml b/app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml index 7f721d4079c27..c69d555d5177a 100644 --- a/app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml +++ b/app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml @@ -35,5 +35,6 @@ <element name="taxRateMultiSelectItems" type="block" selector=".mselect-list-item"/> <element name="taxRateNumber" type="button" selector="//div[@data-ui-id='tax-rate-form-fieldset-element-form-field-tax-rate']//div[@class='mselect-items-wrapper']//label[{{var}}]" parameterized="true"/> <element name="selectTaxRate" type="input" selector="//span[text()='{{taxCode}}']" parameterized="true"/> + <element name="selectProductTaxClass" type="input" selector="//div[contains(@class, 'field-tax_product_class')]//*[contains(@class, 'mselect-list-item') and contains(.,'{{taxClass}}')]" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml new file mode 100644 index 0000000000000..39e6e316dd486 --- /dev/null +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCheckCreditMemoTotalsTest"> + <annotations> + <features value="Tax"/> + <stories value="Credit memo entity"/> + <title value="Checking Credit memo Totals"/> + <description value="Checking Credit memo Totals"/> + <severity value="MAJOR"/> + <testCaseId value="MC-6159"/> + <group value="tax"/> + <group value="sales"/> + </annotations> + <before> + <!-- Create productTaxClass --> + <createData entity="productTaxClass" stepKey="createProductTaxClass"/> + <!--Set configs--> + <magentoCLI command="config:set {{DisableGenerateCategoryProductUrlRewritesConfigData.path}} {{DisableGenerateCategoryProductUrlRewritesConfigData.value}}" stepKey="disableGenerateUrlRewrite"/> + <magentoCLI command="config:set {{DefaultProductTaxClass.path}} $createProductTaxClass.return$" stepKey="setDefaultProductTaxClass"/> + <!--Create category and product--> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="_defaultProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + <field key="productTaxClass">$createProductTaxClass.taxClass[class_name]$</field> + </createData> + <!--Create customer--> + <createData entity="Simple_US_Customer_NY" stepKey="createCustomer"/> + <!--Login as admin--> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!--Create tax rule--> + <actionGroup ref="AdminCreateTaxRuleCustomProductTaxClassActionGroup" stepKey="createTaxRuleCustomProductTaxClass"> + <argument name="productTaxClassName" value="$createProductTaxClass.taxClass[class_name]$"/> + </actionGroup> + </before> + <after> + <!--Set configs--> + <magentoCLI command="config:set {{EnableGenerateCategoryProductUrlRewritesConfigData.path}} {{EnableGenerateCategoryProductUrlRewritesConfigData.value}}" stepKey="enableGenerateUrlRewrite"/> + <magentoCLI command="config:set {{DefaultProductTaxClass.path}} {{DefaultProductTaxClass.value}}" stepKey="setDefaultProductTaxClass"/> + <!--Delete category and product--> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <!--Delete customer--> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <!-- Reset admin order filter --> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderFilters"/> + <!-- Go to the tax rule page and delete the row we created--> + <amOnPage url="{{AdminTaxRuleGridPage.url}}" stepKey="goToTaxRulesPage"/> + <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deleteRule"> + <argument name="name" value="{{defaultTaxRule.code}}"/> + <argument name="searchInput" value="{{AdminSecondaryGridSection.taxIdentifierSearch}}"/> + </actionGroup> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearTaxRuleFilter"/> + <!-- Delete Tax Class --> + <deleteData createDataKey="createProductTaxClass" stepKey="deleteProductTaxClass"/> + <!--Logout--> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + </after> + <!--Create new order--> + <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="createNewOrder"> + <argument name="customer" value="Simple_US_Customer_NY"/> + </actionGroup> + <!--Add product to order--> + <actionGroup ref="AddSimpleProductToOrderActionGroup" stepKey="addSimpleProductToOrder"> + <argument name="product" value="$createSimpleProduct$"/> + </actionGroup> + <!--Set shipping method--> + <actionGroup ref="OrderSelectFlatRateShippingActionGroup" stepKey="orderSelectFlatRateShipping"/> + <!--Submit order--> + <actionGroup ref="AdminSubmitOrderActionGroup" stepKey="submitOrder"/> + <!--Create order invoice--> + <actionGroup ref="StartCreateInvoiceFromOrderPageActionGroup" stepKey="startCreateInvoice"/> + <actionGroup ref="SubmitInvoiceActionGroup" stepKey="submitInvoice"/> + <!--Create Credit Memo--> + <actionGroup ref="AdminStartToCreateCreditMemoFromOrderPageActionGroup" stepKey="startCreatingCreditMemo"/> + <fillField selector="{{AdminCreditMemoTotalSection.refundShipping}}" userInput="0" stepKey="setRefundShipping"/> + <actionGroup ref="UpdateCreditMemoTotalsActionGroup" stepKey="updateTotals"/> + <actionGroup ref="SubmitCreditMemoActionGroup" stepKey="submitCreditMemo"/> + <actionGroup ref="AdminOpenCreditMemoFromOrderPageActionGroup" stepKey="openCreditMemoFromOrderPageActionGroup"/> + <actionGroup ref="AssertAdminCreditMemoGrandTotalActionGroup" stepKey="assertGrandTotal"> + <argument name="expectedGrandTotal" value="$133.30"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/CheckCreditMemoTotalsTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/CheckCreditMemoTotalsTest.xml deleted file mode 100644 index e7964a2dd29eb..0000000000000 --- a/app/code/Magento/Tax/Test/Mftf/Test/CheckCreditMemoTotalsTest.xml +++ /dev/null @@ -1,148 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="CheckCreditMemoTotalsTest"> - <annotations> - <features value="Tax"/> - <stories value="MAGETWO-91769 - Credit Memo - Wrong tax calculation! #10982"/> - <title value="Checking Credit memo Totals"/> - <description value="Checking Credit memo Totals"/> - <severity value="MAJOR"/> - <testCaseId value="MAGETWO-95175"/> - <group value="creditMemo"/> - <group value="tax"/> - <skip> - <issueId value="MC-17140"/> - </skip> - </annotations> - <before> - <!--Create category and product--> - <createData entity="_defaultCategory" stepKey="createCategory"/> - <createData entity="_defaultProduct" stepKey="createSimpleProduct"> - <requiredEntity createDataKey="createCategory"/> - </createData> - <!--Create customer--> - <createData entity="Simple_US_Customer_NY" stepKey="createCustomer"/> - <!--Login as admin--> - <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> - <!--Create tax rule and tax rate--> - <amOnPage url="{{AdminTaxRuleGridPage.url}}" stepKey="goToTaxRulePage"/> - <waitForPageLoad stepKey="waitForTaxRatePage"/> - <click stepKey="addNewTaxRate" selector="{{AdminGridMainControls.add}}"/> - <fillField stepKey="fillRuleName" selector="{{AdminTaxRulesSection.ruleName}}" userInput="SampleRule"/> - <actionGroup ref="addCustomTaxRate" stepKey="addCustomTaxRate"> - <argument name="taxCode" value="SimpleTaxNY"/> - </actionGroup> - <click stepKey="expandAdditionalSettings" selector="{{AdminProductTaxClassSection.additionalSettings}}"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <click selector="{{AdminProductTaxClassSection.productTaxClass}}" stepKey="ClickToAddTaxClass"/> - <fillField selector="{{AdminProductTaxClassSection.TaxClassName}}" userInput="NewTaxClass" stepKey="setName"/> - <click selector="{{AdminProductTaxClassSection.confirm}}" stepKey="ClickToDone"/> - <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> - <waitForPageLoad stepKey="waitForTaxRatePage1"/> - <see userInput="You saved the tax rule." stepKey="VerifyRuleSaved"/> - <!--Search and edit product to add new created tax rule--> - <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> - <argument name="product" value="$$createSimpleProduct$$"/> - </actionGroup> - <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="OpenEditProductOnBackend"> - <argument name="product" value="$$createSimpleProduct$$"/> - </actionGroup> - <waitForPageLoad stepKey="waitForPageLoad2"/> - <selectOption selector="{{AdminProductFormActionSection.selectTaxClass}}" userInput="NewTaxClass" stepKey="SetNewTaxClass" /> - <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveProduct"/> - <!--Set configs--> - <amOnPage url="{{AdminTaxConfigurationPage.url}}" stepKey="goToTaxConfigPage"/> - <conditionalClick stepKey="clickOrdersInvoicesCreditSales" selector="{{AdminConfigureTaxSection.taxClasses}}" dependentSelector="{{AdminConfigureTaxSection.taxClassesCondition}}" visible="false"/> - <click selector="{{AdminConfigureTaxSection.useSystemValue}}" stepKey="UncheckUseSystemValue"/> - <selectOption selector="{{AdminConfigureTaxSection.productTaxClass}}" userInput="NewTaxClass" stepKey="selectClass"/> - <click selector="{{AdminConfigureTaxSection.save}}" stepKey="saveConfig"/> - <!--flash cache--> - <magentoCLI command="cache:flush" stepKey="flushCache"/> - </before> - <after> - <!--Delete category and product--> - <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <!--Delete customer--> - <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <!-- Reset admin order filter --> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderFilters"/> - <!--Roll Back configuration--> - <amOnPage url="{{AdminTaxConfigurationPage.url}}" stepKey="goToTaxConfigPage"/> - <conditionalClick stepKey="clickOrdersInvoicesCreditSales" selector="{{AdminConfigureTaxSection.taxClasses}}" dependentSelector="{{AdminConfigureTaxSection.taxClassesCondition}}" visible="false"/> - <selectOption selector="{{AdminConfigureTaxSection.productTaxClass}}" userInput="Taxable Goods" stepKey="selectClass"/> - <click selector="{{AdminConfigureTaxSection.save}}" stepKey="saveConfig"/> - <!-- Go to the tax rule page and delete the row we created--> - <amOnPage url="{{AdminTaxRuleGridPage.url}}" stepKey="goToTaxRulesPage"/> - <waitForPageLoad stepKey="waitForRulesPage"/> - <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deleteRule"> - <argument name="name" value="SampleRule"/> - <argument name="searchInput" value="{{AdminSecondaryGridSection.taxIdentifierSearch}}"/> - </actionGroup> - <!-- Go to the tax rate page --> - <amOnPage url="{{AdminTaxRateGridPage.url}}" stepKey="goToTaxRatesPage"/> - <waitForPageLoad stepKey="waitForRatesPage"/> - <!-- Delete tax rate that were created --> - <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deleteNYRate"> - <argument name="name" value="{{SimpleTaxNY.state}}"/> - <argument name="searchInput" value="{{AdminSecondaryGridSection.taxIdentifierSearch}}"/> - </actionGroup> - <actionGroup ref="DeleteProductTaxClassActionGroup" stepKey="deleteFirstProductTaxClass"> - <argument name="taxClassName" value="NewTaxClass"/> - </actionGroup> - <!--logout--> - <actionGroup ref="logout" stepKey="logout"/> - </after> - <!--Create new order--> - <actionGroup stepKey="CreateNewOrder" ref="NavigateToNewOrderPageExistingCustomerActionGroup"> - <argument name="customer" value="Simple_US_Customer_NY"/> - </actionGroup> - <!--Add product to order--> - <click stepKey="clickToAddProduct" selector="{{AdminOrderFormItemsSection.addProducts}}"/> - <waitForPageLoad stepKey="waitForProductsOpened"/> - <checkOption selector="{{AdminOrderFormItemsSection.rowCheck('1')}}" stepKey="selectProduct"/> - <click selector="{{AdminOrderFormItemsSection.addSelected}}" stepKey="clickAddSelectedProducts"/> - <waitForPageLoad stepKey="waitForPageLoad3"/> - <!--Set shipping method--> - <actionGroup stepKey="OrderSelectFlatRateShippingActionGroup" ref="OrderSelectFlatRateShippingActionGroup"/> - <!--Submit order--> - <click stepKey="SubmitOrder" selector="{{AdminOrderFormActionSection.SubmitOrder}}"/> - <waitForPageLoad stepKey="waitForPageLoad4"/> - <grabTextFrom stepKey="getOrderId" selector="|Order # (\d+)|"/> - <!--Open new created order--> - <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> - <waitForPageLoad stepKey="waitForPageLoad5"/> - <actionGroup ref="FilterOrderGridByIdActionGroup" stepKey="filterOrderGridById"> - <argument name="orderId" value="$getOrderId"/> - </actionGroup> - <!--Create order invoice--> - <click selector="{{AdminDataGridTableSection.rowViewAction('1')}}" stepKey="clickCreatedOrderInGrid"/> - <click selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="clickInvoiceAction"/> - <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Invoice" stepKey="seePageNameNewInvoicePage"/> - <click selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="clickSubmitInvoice"/> - <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The invoice has been created." stepKey="seeInvoiceCreateSuccess"/> - <see selector="{{AdminInvoiceOrderInformationSection.orderStatus}}" userInput="Processing" stepKey="seeOrderProcessing"/> - <!--Create Credit Memo--> - <click selector="{{AdminOrderDetailsMainActionsSection.creditMemo}}" stepKey="clickCreditMemoAction"/> - <fillField selector="{{AdminCreditMemoTotalSection.refundShipping}}" userInput="0" stepKey="setRefundShipping"/> - <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Memo" stepKey="seeNewMemoInPageTitle"/> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> - <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="You created the credit memo." stepKey="seeCreditMemoSuccess"/> - <click selector="{{AdminCreditMemoTotalSection.creditMemoItem}}" stepKey="goToCreatedCreditMemo"/> - <waitForPageLoad stepKey="waitForPageLoad6"/> - <!--View created memo and verify tax for product--> - <click selector="{{AdminCreditMemoTotalSection.viewMemo}}" stepKey="ViewMemo"/> - <waitForPageLoad stepKey="waitForPageLoad7"/> - <grabTextFrom selector="{{AdminCreditMemoTotalSection.grandTotal}}" stepKey="getGrandTotal"/> - <assertEquals expected='$123.00' expectedType="string" actual="($getGrandTotal)" stepKey="assertGrandTotalValue"/> - - </test> -</tests> From 8d1102571a8631fcef97f4896101e7b12f52f51d Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 20 Jan 2020 10:16:58 +0200 Subject: [PATCH 040/176] MC-24256: [Integration Test] Export Customers Main File with multiple websites --- .../import_export/customers_with_websites.php | 18 ++++++++++++++++++ .../customers_with_websites_rollback.php | 9 +++++++++ .../Model/Export/CustomerTest.php | 14 ++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites.php b/dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites.php new file mode 100644 index 0000000000000..3ee6530063dbd --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Customer\Api\CustomerRepositoryInterface; + +require __DIR__ . '/customers.php'; +require __DIR__ . '/../../../Store/_files/website.php'; + +$objectManager = Bootstrap::getObjectManager(); +$repository = $objectManager->create(CustomerRepositoryInterface::class); +$customer = $repository->get('customer@example.com'); +$customer->setWebsiteId($website->getId()); +$repository->save($customer); diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites_rollback.php b/dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites_rollback.php new file mode 100644 index 0000000000000..09858172126f5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites_rollback.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +include __DIR__ . '/customers_rollback.php'; +include __DIR__ . '/../../../Store/_files/website_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php index 884a4a38ebe0f..9a178aafb0aee 100644 --- a/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php +++ b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php @@ -75,6 +75,20 @@ public function testExport() $this->checkExportData($lines, $expectedAttributes); } + /** + * Export with Multi Websites "Customer Main File". + * + * @magentoDataFixture Magento/Customer/_files/import_export/customers_with_websites.php + * @return void + */ + public function testExportWithMultiWebsites(): void + { + $this->processCustomerAttribute(); + $expectedAttributes = $this->getExpectedAttributes(); + $lines = $this->export($expectedAttributes); + $this->checkExportData($lines, $expectedAttributes); + } + /** * Return attributes which should be exported. * From a1212509c813239ef8ab0236d623414831bbac12 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Mon, 20 Jan 2020 12:37:34 +0200 Subject: [PATCH 041/176] cover changes with jasmine test --- .../Magento/Ui/base/js/modal/modal.test.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js index 8b00ecd3a2aed..ddf9c82bd1886 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js @@ -10,18 +10,34 @@ define([ 'use strict'; describe('ui/js/modal/modal', function () { - var element = $('<div>some element</div>'), + + var element = $('<div>Element</div>'), modal = element.modal({}).data('mage-modal'); + $(element).append('<h1 class="modal-title"' + + ' data-role="title">Title</h1>' + + '<span class="modal-subtitle"' + + ' data-role="subTitle"></span>'); + it('Check for modal definition', function () { expect(modal).toBeDefined(); }); + it('Show/hide function check', function () { expect(element.trigger('openModal')).toBe(element); expect(element.trigger('closeModal')).toBe(element); }); + it('Integration: modal created on page', function () { expect($(modal).length).toEqual(1); }); + + it('Verify stTitle() method set title', function () { + var newTitle = 'New modal title'; + + modal.setTitle(newTitle); + expect($(modal.options.modalTitle).text()).toBe(newTitle); + expect($(modal.options.modalTitle).find(modal.options.modalSubTitle).length).toBe(1); + }); }); }); From fcce5b8592f884bec431767d903150137a1a6c6e Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Mon, 20 Jan 2020 13:03:54 +0200 Subject: [PATCH 042/176] fix typo --- .../tests/app/code/Magento/Ui/base/js/modal/modal.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js index ddf9c82bd1886..ccfad86c6cfb0 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js @@ -32,12 +32,12 @@ define([ expect($(modal).length).toEqual(1); }); - it('Verify stTitle() method set title', function () { + it('Verify setTitle() method set title', function () { var newTitle = 'New modal title'; modal.setTitle(newTitle); - expect($(modal.options.modalTitle).text()).toBe(newTitle); - expect($(modal.options.modalTitle).find(modal.options.modalSubTitle).length).toBe(1); + expect($(modal.options.modalTitle).text()).toContain(newTitle); + expect($(modal.options.modalTitle).find(modal.options.modalSubTitle).length).toBe(2); }); }); }); From e99457737d2e028fc8206056ea1f464f4278ad21 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Mon, 20 Jan 2020 15:36:18 +0200 Subject: [PATCH 043/176] MC-23546: Child Configurable product does not save disabled status via API --- .../Mftf/Test/SearchEntityResultsTest.xml | 97 ------------------- 1 file changed, 97 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml index c289fc7868a10..7648b59aaefe8 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml @@ -603,101 +603,4 @@ <argument name="value" value="$simpleProduct1.name$"/> </actionGroup> </test> - - <test name="QuickSearchConfigurableChildren"> - <annotations> - <stories value="Search Product on Storefront"/> - <title value="Deprecated. User should be able to use Quick Search to a configurable product's child products"/> - <description value="Use Quick Search to find a configurable product with enabled/disable children"/> - <severity value="MAJOR"/> - <testCaseId value="MC-14798"/> - <group value="CatalogSearch"/> - <group value="mtf_migrated"/> - <skip> - <issueId value="DEPRECATED">Use StorefrontQuickSearchConfigurableChildrenTest instead.</issueId> - </skip> - </annotations> - <before> - <!-- Create the category --> - <createData entity="ApiCategory" stepKey="createCategory"/> - - <!-- Create blank AttributeSet--> - <createData entity="CatalogAttributeSet" stepKey="attributeSet"/> - - <!-- Create an attribute with two options to be used in the first child product --> - <createData entity="hiddenDropdownAttributeWithOptions" stepKey="createConfigProductAttribute"/> - <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </createData> - - <!-- Assign attribute to set --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <actionGroup ref="goToAttributeGridPage" stepKey="goToPage"/> - <actionGroup ref="GoToAttributeSetByNameActionGroup" stepKey="goToSet"> - <argument name="name" value="$attributeSet.attribute_set_name$"/> - </actionGroup> - <actionGroup ref="AssignAttributeToGroupActionGroup" stepKey="assignToAttributeSetAndGroup"> - <argument name="group" value="Product Details"/> - <argument name="attribute" value="$createConfigProductAttribute.attribute_code$"/> - </actionGroup> - <actionGroup ref="SaveAttributeSetActionGroup" stepKey="savePage"/> - - <!-- Get the first option of the attribute we created --> - <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </getData> - - <!-- Create a simple product,give it the attributeSet and attribute with the first option --> - <createData entity="ApiSimpleOneHidden" stepKey="createConfigChildProduct1"> - <field key="attribute_set_id">$attributeSet.attribute_set_id$</field> - <requiredEntity createDataKey="createConfigProductAttribute"/> - <requiredEntity createDataKey="getConfigAttributeOption1"/> - </createData> - <updateData entity="ApiSimpleProductUpdateDescription" stepKey="updateSimpleProduct1" createDataKey="createConfigChildProduct1"/> - - <!-- Create the configurable product, give it the attributeSet and add it to the category --> - <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> - <field key="attribute_set_id">$attributeSet.attribute_set_id$</field> - <requiredEntity createDataKey="createCategory"/> - </createData> - <!-- Create the configurable product --> - <createData entity="ConfigurableProductOneOption" stepKey="createConfigProductOption"> - <requiredEntity createDataKey="createConfigProduct"/> - <requiredEntity createDataKey="createConfigProductAttribute"/> - <requiredEntity createDataKey="getConfigAttributeOption1"/> - </createData> - <!-- Add the first simple product to the configurable product --> - <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> - <requiredEntity createDataKey="createConfigProduct"/> - <requiredEntity createDataKey="createConfigChildProduct1"/> - </createData> - - <!-- Perform reindex and flush cache --> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> - </before> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToFrontPage"/> - <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> - <argument name="phrase" value="$createConfigProduct.name$"/> - </actionGroup> - <actionGroup ref="StorefrontQuickSearchCheckProductNameInGridActionGroup" stepKey="seeProductInGrid"> - <argument name="productName" value="$createConfigProduct.name$"/> - <argument name="index" value="1"/> - </actionGroup> - - <!-- Disable Child Product --> - <actionGroup ref="GoToProductPageViaIDActionGroup" stepKey="goToChildProduct"> - <argument name="productId" value="$createConfigChildProduct1.id$"/> - </actionGroup> - <actionGroup ref="ToggleProductEnabledActionGroup" stepKey="disableProduct"/> - <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> - - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToFrontPageAgain"/> - <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefrontAgain"> - <argument name="phrase" value="$createConfigProduct.name$"/> - </actionGroup> - <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGridActionGroup" stepKey="dontSeeProductAnymore"> - <argument name="productName" value="$createConfigProduct.name$"/> - </actionGroup> - </test> </tests> From 030172abae997b093b74eb76179da676b5762af0 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Wed, 22 Jan 2020 11:53:53 +0200 Subject: [PATCH 044/176] MC-24168: Fix Skipped MFTF Tests From MC-17140: MAGETWO-95175, MAGETWO-97001, MAGETWO-98189 --- .../Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml index 39e6e316dd486..dfed39e861f05 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml @@ -15,7 +15,7 @@ <title value="Checking Credit memo Totals"/> <description value="Checking Credit memo Totals"/> <severity value="MAJOR"/> - <testCaseId value="MC-6159"/> + <testCaseId value="MC-25752"/> <group value="tax"/> <group value="sales"/> </annotations> @@ -23,7 +23,6 @@ <!-- Create productTaxClass --> <createData entity="productTaxClass" stepKey="createProductTaxClass"/> <!--Set configs--> - <magentoCLI command="config:set {{DisableGenerateCategoryProductUrlRewritesConfigData.path}} {{DisableGenerateCategoryProductUrlRewritesConfigData.value}}" stepKey="disableGenerateUrlRewrite"/> <magentoCLI command="config:set {{DefaultProductTaxClass.path}} $createProductTaxClass.return$" stepKey="setDefaultProductTaxClass"/> <!--Create category and product--> <createData entity="_defaultCategory" stepKey="createCategory"/> @@ -42,7 +41,6 @@ </before> <after> <!--Set configs--> - <magentoCLI command="config:set {{EnableGenerateCategoryProductUrlRewritesConfigData.path}} {{EnableGenerateCategoryProductUrlRewritesConfigData.value}}" stepKey="enableGenerateUrlRewrite"/> <magentoCLI command="config:set {{DefaultProductTaxClass.path}} {{DefaultProductTaxClass.value}}" stepKey="setDefaultProductTaxClass"/> <!--Delete category and product--> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> From a55547993a584ee9452fb0c7331364f495b2a067 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Wed, 22 Jan 2020 12:04:44 +0200 Subject: [PATCH 045/176] MC-24243: [MFTF test] Automate by MFTF test MC-27569 "Storefront product grid UI updates on Desktop" --- ...lsAreNotVisibleWithoutHoverActionGroup.xml | 19 ++++ ...ctControlsAreVisibleOnHoverActionGroup.xml | 19 ++++ ...refrontNavigateCategoryPageActionGroup.xml | 1 + .../Section/StorefrontCategoryMainSection.xml | 4 + ...ogProductsListWidgetOptionsActionGroup.xml | 33 +++++++ .../Mftf/Section/CatalogWidgetSection.xml | 1 + ...frontProductGridUIUpdatesOnDesktopTest.xml | 95 +++++++++++++++++++ .../AdminClickInsertWidgetActionGroup.xml | 19 ++++ ...nsertWidgetToCmsPageContentActionGroup.xml | 25 +++++ ...ddToWishListIconIsClickableActionGroup.xml | 23 +++++ 10 files changed, 239 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml create mode 100644 app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml create mode 100644 app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminInsertWidgetToCmsPageContentActionGroup.xml create mode 100644 app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml new file mode 100644 index 0000000000000..8d18c49d6a624 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup"> + <annotations> + <description>Validate that the Product Controls Are Not Visible On Category Page Without Hover on Product</description> + </annotations> + + <dontSeeElement selector="{{StorefrontCategoryMainSection.addToCartButtonProductInfoHover}}" stepKey="assertAddToCartButtonElementIsNotVisible"/> + <dontSeeElement selector="{{StorefrontCategoryMainSection.toWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsNotVisible"/> + <dontSeeElement selector="{{StorefrontCategoryMainSection.toCompareIconProductInfoHover}}" stepKey="assertAddToCompareIconIsNotVisible"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml new file mode 100644 index 0000000000000..9c26dcecf726a --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontProductControlsAreVisibleOnHoverActionGroup"> + <annotations> + <description>Validate that the Product Controls Are Visible on Category Page on Hover on Product</description> + </annotations> + + <seeElement selector="{{StorefrontCategoryMainSection.addToCartButtonProductInfoHover}}" stepKey="assertAddToCartButtonElementIsVisible"/> + <seeElement selector="{{StorefrontCategoryMainSection.toWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsVisible"/> + <seeElement selector="{{StorefrontCategoryMainSection.toCompareIconProductInfoHover}}" stepKey="assertAddToCompareIconIsVisible"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateCategoryPageActionGroup.xml index 39cb9ef1a63d4..dab5142c557ca 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateCategoryPageActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateCategoryPageActionGroup.xml @@ -13,5 +13,6 @@ </arguments> <!-- Open category page on storefront --> <amOnPage url="{{StorefrontCategoryPage.url(category.custom_attributes[url_key])}}" stepKey="navigateStorefrontCategoryPage"/> + <waitForPageLoad stepKey="waitForCategoryPageLoad"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml index 9a84f90edcfc0..8f2ba2016aea6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml @@ -17,6 +17,9 @@ <element name="ProductItemInfo" type="button" selector=".product-item-info"/> <element name="specifiedProductItemInfo" type="button" selector="//a[@class='product-item-link'][contains(text(), '{{var1}}')]" parameterized="true"/> <element name="AddToCartBtn" type="button" selector="button.action.tocart.primary"/> + <element name="addToCartButtonProductInfoHover" type="button" selector=".product-item-info:hover button.action.tocart.primary"/> + <element name="toWishListIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.towishlist"/> + <element name="toCompareIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.tocompare"/> <element name="addToCartProductBySku" type="button" selector="//form[@data-product-sku='{{productSku}}']//button[contains(@class, 'tocart')]" parameterized="true" /> <element name="SuccessMsg" type="button" selector="div.message-success"/> <element name="productCount" type="text" selector="#toolbar-amount"/> @@ -27,6 +30,7 @@ <element name="productLink" type="text" selector="a.product-item-link" timeout="30"/> <element name="productLinkByHref" type="text" selector="a.product-item-link[href$='{{var1}}.html']" parameterized="true"/> <element name="productPrice" type="text" selector=".price-final_price"/> + <element name="productPriceByName" type="text" selector="//div[@class='product-item-info']//a[contains(text(), '{{productName}}')]//..//..//span[@class='price']" parameterized="true"/> <element name="categoryImage" type="text" selector=".category-image"/> <element name="emptyProductMessage" type="block" selector=".message.info.empty>div"/> <element name="lineProductName" type="text" selector=".products.list.items.product-items li:nth-of-type({{line}}) .product-item-link" timeout="30" parameterized="true"/> diff --git a/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml b/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml new file mode 100644 index 0000000000000..a5b3078dbdcc4 --- /dev/null +++ b/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminFillCatalogProductsListWidgetCategoryActionGroup"> + <annotations> + <description>Fill Catalog Products List Widget Category.</description> + </annotations> + + <arguments> + <argument name="categoryName" type="string" defaultValue="{{_defaultCategory.name}}"/> + </arguments> + + <waitForElementVisible selector="{{WidgetSection.AddParam}}" stepKey="waitForAddParamElement"/> + <click selector="{{WidgetSection.AddParam}}" stepKey="clickOnAddParamElement"/> + <waitForElementVisible selector="{{WidgetSection.ConditionsDropdown}}" stepKey="waitForConditionsDropdownVisible"/> + <selectOption selector="{{WidgetSection.ConditionsDropdown}}" userInput="Category" stepKey="selectCategoryAsCondition"/> + <waitForElementVisible selector="{{WidgetSection.RuleParam}}" stepKey="waitForRuleParamElementVisible"/> + <click selector="{{WidgetSection.RuleParam}}" stepKey="clickToAddRuleParam"/> + <click selector="{{WidgetSection.Chooser}}" stepKey="clickToSelectFromList"/> + <waitForPageLoad stepKey="waitForPageLoadAfterSelectingRuleParam"/> + <waitForElementVisible selector="{{WidgetSection.PreCreateCategory(categoryName)}}" stepKey="waitForCategoryElementVisible"/> + <click selector="{{WidgetSection.PreCreateCategory(categoryName)}}" stepKey="selectCategoryFromArguments"/> + <click selector="{{AdminNewWidgetSection.applyParameter}}" stepKey="clickApplyButton"/> + <waitForElementNotVisible selector="{{InsertWidgetSection.categoryTreeWrapper}}" stepKey="waitForCategoryTreeIsNotVisible"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogWidget/Test/Mftf/Section/CatalogWidgetSection.xml b/app/code/Magento/CatalogWidget/Test/Mftf/Section/CatalogWidgetSection.xml index 855d325c9850c..66aa4252f4b5f 100644 --- a/app/code/Magento/CatalogWidget/Test/Mftf/Section/CatalogWidgetSection.xml +++ b/app/code/Magento/CatalogWidget/Test/Mftf/Section/CatalogWidgetSection.xml @@ -22,5 +22,6 @@ <element name="conditionOperator" type="button" selector="#conditions__1--{{arg3}}__operator" parameterized="true"/> <element name="checkElementStorefrontByPrice" type="button" selector="//*[@class='product-items widget-product-grid']//*[contains(text(),'${{arg4}}.00')]" parameterized="true"/> <element name="checkElementStorefrontByName" type="button" selector="//*[@class='product-items widget-product-grid']//*[@class='product-item'][{{productPosition}}]//a[contains(text(), '{{productName}}')]" parameterized="true"/> + <element name="categoryTreeWrapper" type="text" selector=".rule-chooser .tree.x-tree"/> </section> </sections> diff --git a/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml b/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml new file mode 100644 index 0000000000000..fde10352ab2ba --- /dev/null +++ b/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontProductGridUIUpdatesOnDesktopTest"> + <annotations> + <features value="Catalog"/> + <stories value="New products list widget"/> + <title value="Storefront product grid UI updates on Desktop"/> + <description value="Storefront product grid UI updates on Desktop"/> + <severity value="MAJOR"/> + <testCaseId value="MC-27569"/> + <group value="catalog"/> + <group value="WYSIWYGDisabled"/> + </annotations> + <before> + <!-- 1. Create multiple products and assign to a category. --> + <createData entity="ApiCategory" stepKey="createCategory"/> + <createData entity="ApiSimpleProduct" stepKey="createFirstSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ApiSimpleProduct" stepKey="createSecondSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ApiSimpleProduct" stepKey="createThirdSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ApiSimpleProduct" stepKey="createFourthSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <!-- 2. Create new CMS page and add "Catalog Product List" widget type via content >insert widget option --> + <createData entity="_emptyCmsPage" stepKey="createCmsPage"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <actionGroup ref="NavigateToCreatedCMSPageActionGroup" stepKey="navigateToCreatedCmsPage"> + <argument name="CMSPage" value="$createCmsPage$"/> + </actionGroup> + <actionGroup ref="AdminInsertWidgetToCmsPageContentActionGroup" stepKey="insertWidgetToCmsPageContentActionGroup"> + <argument name="widgetType" value="Catalog Products List"/> + </actionGroup> + <actionGroup ref="AdminFillCatalogProductsListWidgetCategoryActionGroup" stepKey="fillCatalogProductsListWidgetOptions"> + <argument name="categoryName" value="$createCategory.name$"/> + </actionGroup> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidgetButton"/> + <actionGroup ref="SaveCmsPageActionGroup" stepKey="clickSaveButton"/> + <!-- TODO: REMOVE AFTER FIX MC-29943 --> + <magentoCLI command="indexer:reindex" stepKey="performReindex"/> + </before> + <after> + <deleteData createDataKey="createFirstSimpleProduct" stepKey="deleteFirstSimpleProduct"/> + <deleteData createDataKey="createSecondSimpleProduct" stepKey="deleteSecondSimpleProduct"/> + <deleteData createDataKey="createThirdSimpleProduct" stepKey="deleteThirdSimpleProduct"/> + <deleteData createDataKey="createFourthSimpleProduct" stepKey="deleteFourthSimpleProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createCmsPage" stepKey="deleteCmsPage"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + </after> + <actionGroup ref="StorefrontGoToCMSPageActionGroup" stepKey="navigateAndOpenCreatedCmsPage"> + <argument name="identifier" value="$createCmsPage.identifier$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup" stepKey="assertProductControlsAreNotVisibleWithoutHoverOnCmsPage"/> + <seeElement selector="{{StorefrontCategoryMainSection.productLinkByHref($createFirstSimpleProduct.custom_attributes[url_key]$)}}" stepKey="assertProductName"/> + <seeElement selector="{{StorefrontCategoryMainSection.productPriceByName($createFirstSimpleProduct.name$)}}" stepKey="assertProductPrice"/> + <moveMouseOver selector="{{StorefrontCategoryProductSection.ProductInfoByName($createFirstSimpleProduct.name$)}}" stepKey="hoverProduct"/> + <actionGroup ref="AssertStorefrontProductControlsAreVisibleOnHoverActionGroup" stepKey="assertProductControlsAreVisibleOnHoverOnCmsPage"/> + <actionGroup ref="AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup" stepKey="assertAddToWishListIconIsClickable"/> + <actionGroup ref="StorefrontGoToCMSPageActionGroup" stepKey="navigateAndOpenCreatedCmsPageToVerifyAddToCompareIconIsClickable"> + <argument name="identifier" value="$createCmsPage.identifier$"/> + </actionGroup> + <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="assertAddToCompareIconIsClickable"> + <argument name="productVar" value="$createFirstSimpleProduct$"/> + </actionGroup> + <actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="navigateCategoryCreatedInPreconditions"> + <argument name="category" value="$createCategory$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup" stepKey="assertProductControlsAreNotVisibleWithoutHoverOnCategoryPage"/> + <seeElement selector="{{StorefrontCategoryMainSection.productLinkByHref($createFirstSimpleProduct.custom_attributes[url_key]$)}}" stepKey="assertProductNameOnCategoryPage"/> + <seeElement selector="{{StorefrontCategoryMainSection.productPriceByName($createFirstSimpleProduct.name$)}}" stepKey="assertProductPriceOnCategoryPage"/> + <moveMouseOver selector="{{StorefrontCategoryProductSection.ProductInfoByName($createFirstSimpleProduct.name$)}}" stepKey="hoverProductOnCategoryPage"/> + <actionGroup ref="AssertStorefrontProductControlsAreVisibleOnHoverActionGroup" stepKey="assertProductControlsAreVisibleOnHoverOnCategoryPage"/> + <actionGroup ref="AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup" stepKey="assertAddToWishListIconIsClickableOnCategoryPage"/> + <actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="navigateCategoryCreatedInPreconditionsToVerifyAddToCompareIconIsClickable"> + <argument name="category" value="$createCategory$"/> + </actionGroup> + <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="assertAddToCompareIconIsClickableOnCategoryPage"> + <argument name="productVar" value="$createFirstSimpleProduct$"/> + </actionGroup> + <actionGroup ref="StorefrontClearCompareActionGroup" stepKey="clearAllCompareProducts"/> + </test> +</tests> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml new file mode 100644 index 0000000000000..2ec329bf174b3 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminClickInsertWidgetActionGroup"> + <annotations> + <description>Click Insert Widget button.</description> + </annotations> + + <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidgetButton"/> + <waitForElementNotVisible selector="{{WidgetSection.InsertWidgetTitle}}" stepKey="waitForWidgetPopupDisappear"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminInsertWidgetToCmsPageContentActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminInsertWidgetToCmsPageContentActionGroup.xml new file mode 100644 index 0000000000000..734d8d98722b2 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminInsertWidgetToCmsPageContentActionGroup.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminInsertWidgetToCmsPageContentActionGroup"> + <annotations> + <description>Insert widget to CMS Page content field. You are on CMS edit page, content tab is expanded.</description> + </annotations> + + <arguments> + <argument name="widgetType" type="string" defaultValue="CMS Page Link"/> + </arguments> + <waitForElementVisible selector="{{CmsNewPagePageActionsSection.insertWidget}}" stepKey="waitForInsertWidgetElementVisible"/> + <click selector="{{CmsNewPagePageActionsSection.insertWidget}}" stepKey="clickOnInsertWidgetButton"/> + <waitForPageLoad stepKey="waitForPageLoadAfterClickOnInsertWidgetButton"/> + <waitForElementVisible selector="{{WidgetSection.InsertWidgetTitle}}" stepKey="waitForInsertWidgetTitle"/> + <selectOption selector="{{WidgetSection.WidgetType}}" userInput="{{widgetType}}" stepKey="selectWidgetType"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml new file mode 100644 index 0000000000000..77984a048c5ff --- /dev/null +++ b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup"> + <annotations> + <description>Assert AddToWishList icon is clickable</description> + </annotations> + + <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverProduct"/> + <click selector="{{StorefrontCategoryMainSection.toWishListIconProductInfoHover}}" stepKey="clickOnAddToWishListIcon"/> + <waitForPageLoad stepKey="waitForCustomerSignInPageLoad"/> + <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" stepKey="waitForErrorMessageIsVisible"/> + <see selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="You must login or register to add items to your wishlist." stepKey="assertErrorMessage"/> + <seeInCurrentUrl url="{{StorefrontCustomerSignInPage.url}}" stepKey="assertCustomerLoginPageUrl"/> + </actionGroup> +</actionGroups> From c9d5e8ef8e3b12f6483ec02e2bf561c2752b68d1 Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Wed, 22 Jan 2020 22:46:44 +0530 Subject: [PATCH 046/176] Error message to becached for grid data storage component --- app/code/Magento/Ui/view/base/web/js/grid/data-storage.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js b/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js index 547cdab16cdf1..aa9989251b656 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js @@ -188,7 +188,8 @@ define([ result = { items: this.getByIds(request.ids), - totalRecords: request.totalRecords + totalRecords: request.totalRecords, + errorMessage: request.errorMessage }; delay ? @@ -216,7 +217,8 @@ define([ this._requests.push({ ids: this.getIds(data.items), params: params, - totalRecords: data.totalRecords + totalRecords: data.totalRecords, + errorMessage: data.errorMessage }); return this; From 980f7c3788cddba48d9deae6c6ab29e5340d5ea6 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Thu, 23 Jan 2020 08:17:36 +0200 Subject: [PATCH 047/176] MC-29047: Fix MFTF test --- ...tCheckCategorySimpleProductActionGroup.xml | 2 - ...urableProductCategoryViewChildOnlyTest.xml | 129 ------------------ 2 files changed, 131 deletions(-) delete mode 100644 app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml index ef8d5e3a1212a..b8bc3197d1a11 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml @@ -19,9 +19,7 @@ <waitForElementVisible selector="{{StorefrontCategoryProductSection.ProductTitleByName(product.name)}}" stepKey="waitForProduct"/> <seeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName(product.name)}}" stepKey="assertProductName"/> <see userInput="${{product.price}}.00" selector="{{StorefrontCategoryProductSection.ProductPriceByName(product.name)}}" stepKey="AssertProductPrice"/> - <!-- @TODO: MAGETWO-80272 Move to Magento_Checkout --> <moveMouseOver selector="{{StorefrontCategoryProductSection.ProductInfoByName(product.name)}}" stepKey="moveMouseOverProduct"/> - <!-- @TODO: MAGETWO-80272 Move to Magento_Checkout --> <seeElement selector="{{StorefrontCategoryProductSection.ProductAddToCartByName(product.name)}}" stepKey="AssertAddToCart"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml deleted file mode 100644 index 6c9b985bf38f7..0000000000000 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml +++ /dev/null @@ -1,129 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="StorefrontConfigurableProductCategoryViewChildOnlyTest"> - <annotations> - <features value="ConfigurableProduct"/> - <stories value="View configurable product child in storefront"/> - <title value="DEPRECATED It should be possible to only view the child product of a configurable product"/> - <description value="Create configurable product, add to category such that only child variation is visible in category"/> - <severity value="CRITICAL"/> - <testCaseId value="MC-5832"/> - <group value="ConfigurableProduct"/> - <skip> - <issueId value="DEPRECATED">Use StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest instead</issueId> - </skip> - </annotations> - <before> - <!-- Create the category --> - <createData entity="ApiCategory" stepKey="createCategory"/> - <createData entity="ApiCategory" stepKey="secondCategory"/> - - <!-- Create an attribute with two options to be used in the first child product --> - <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> - <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </createData> - <createData entity="productAttributeOption2" stepKey="createConfigProductAttributeOption2"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </createData> - - <!-- Add the attribute we just created to default attribute set --> - <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </createData> - - <!-- Get the first option of the attribute we created --> - <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </getData> - - <!-- Get the second option of the attribute we created --> - <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getConfigAttributeOption2"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </getData> - - <!-- Create the configurable product and add it to the category --> - <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> - <requiredEntity createDataKey="createCategory"/> - </createData> - - <!-- Create a simple product and give it the attribute with the first option --> - <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - <requiredEntity createDataKey="getConfigAttributeOption1"/> - </createData> - - <!-- Create a simple product and give it the attribute with the second option --> - <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct2"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - <requiredEntity createDataKey="getConfigAttributeOption2"/> - </createData> - - <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> - <requiredEntity createDataKey="createConfigProduct"/> - <requiredEntity createDataKey="createConfigProductAttribute"/> - <requiredEntity createDataKey="getConfigAttributeOption1"/> - <requiredEntity createDataKey="getConfigAttributeOption2"/> - </createData> - - <!-- Add the first simple product to the configurable product --> - <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> - <requiredEntity createDataKey="createConfigProduct"/> - <requiredEntity createDataKey="createConfigChildProduct1"/> - </createData> - - <!-- Add the second simple product to the configurable product --> - <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild2"> - <requiredEntity createDataKey="createConfigProduct"/> - <requiredEntity createDataKey="createConfigChildProduct2"/> - </createData> - </before> - - <after> - <actionGroup ref="logout" stepKey="adminLogout"/> - <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> - <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> - <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> - <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> - <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> - <deleteData createDataKey="secondCategory" stepKey="deleteSecondCategory"/> - </after> - - <actionGroup ref="LoginAsAdmin" stepKey="login"/> - - <!-- Go to the product page for the first product --> - <amOnPage stepKey="goToProductGrid" url="{{ProductCatalogPage.url}}"/> - <waitForPageLoad stepKey="waitForProductGridLoad"/> - <actionGroup stepKey="searchForSimpleProduct" ref="FilterProductGridBySku2ActionGroup"> - <argument name="sku" value="$$createConfigChildProduct1.sku$$"/> - </actionGroup> - <actionGroup stepKey="openProductEditPage" ref="OpenProductForEditByClickingRowXColumnYInProductGridActionGroup"/> - <!-- Edit the visibility the first simple product --> - <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="Catalog, Search" stepKey="selectVisibilityCatalogSearch"/> - <!--Add to category--> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$secondCategory.name$$]" stepKey="addProductToCategory"/> - <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveProduct"/> - <seeElement selector="{{AdminProductMessagesSection.successMessage}}" stepKey="assertSaveMessageSuccess"/> - - <!-- Go to storefront to view child product --> - <amOnPage stepKey="goToStoreFront" url="{{StorefrontHomePage.url}}"/> - <waitForPageLoad stepKey="waitForStorefront"/> - <click selector="{{StorefrontHeaderSection.NavigationCategoryByName($$secondCategory.name$$)}}" stepKey="goToCategoryStorefront"/> - <waitForPageLoad stepKey="waitForStorefrontCategory"/> - <seeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName($$createConfigChildProduct1.name$$)}}" stepKey="seeChildProductInCategory"/> - <dontSeeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName($$createConfigChildProduct2.name$$)}}" stepKey="dontSeeOtherChildProduct"/> - <dontSeeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName($$createConfigProduct.name$$)}}" stepKey="dontSeeParentProduct"/> - <click selector="{{StorefrontCategoryProductSection.ProductTitleByName($$createConfigChildProduct1.name$$)}}" stepKey="clickProductName"/> - <waitForPageLoad stepKey="waitForProductPageLoad"/> - <seeInCurrentUrl url="$$createConfigChildProduct1.custom_attributes[url_key]$$" stepKey="seeProductPageIsAccessible"/> - <seeElement selector="{{StorefrontProductInfoMainSection.productName($$createConfigChildProduct1.name$$)}}" stepKey="seeProductNameOnProductPage"/> - </test> -</tests> From c93c1a0d0912202d1e81c6cfcacd15b0d691257e Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 23 Jan 2020 12:17:43 +0200 Subject: [PATCH 048/176] MC-23546: Child Configurable product does not save disabled status via API --- .../Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml index 1169d053ec7c8..44a4001f7b579 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml @@ -15,6 +15,7 @@ <description value="Use Quick Search to find a configurable product with enabled/disable children"/> <severity value="MAJOR"/> <testCaseId value="MC-28374"/> + <useCaseId value="MAGETWO-69181"/> <group value="catalogSearch"/> <group value="mtf_migrated"/> </annotations> From 8357cf80e7cde248c091bf7fef6934c40e47400a Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Fri, 24 Jan 2020 01:11:38 +0530 Subject: [PATCH 049/176] Jasmine test added for initConfig, getByIds, getRequestData, cacheRequest --- .../Ui/base/js/grid/data-storage.test.js | 125 +++++++++++++++++- 1 file changed, 124 insertions(+), 1 deletion(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js index 5f8bfc2c98cc2..454fc1280c548 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js @@ -12,7 +12,8 @@ define([ 'use strict'; describe('Magento_Ui/js/grid/data-storage', function () { - describe('costructor', function () { + + describe('constructor', function () { it('converts dataScope property to array', function () { var model = new DataStorage({ dataScope: 'magento' @@ -22,6 +23,77 @@ define([ }); }); + describe('"initConfig" method', function () { + + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined ', function () { + expect(model.hasOwnProperty('initConfig')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.initConfig; + + expect(type).toEqual('function'); + }); + + it('Check returned value if method called without arguments', function () { + expect(model.initConfig()).toBeDefined(); + }); + + it('Check returned value type if method called without arguments', function () { + var type = typeof model.initConfig(); + + expect(type).toEqual('object'); + }); + + it('Check this.dataScope property (is modify in initConfig method)', function () { + model.dataScope = null; + model.initConfig(); + expect(typeof model.dataScope).toEqual('object'); + }); + + it('Check this._requests property (is modify in initConfig method)', function () { + model._requests = null; + model.initConfig(); + expect(typeof model._requests).toEqual('object'); + }); + }); + + describe('"getByIds"', function() { + + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('check for defined', function() { + expect(model.hasOwnProperty('getByIds')).toBeDefined(); + }); + + it('check method type', function () { + expect(typeof model.getByIds).toEqual('function'); + }); + + it('Check returned value if method called with argument', function () { + var ids = [1,2,3]; + expect(model.getByIds(ids)).toBeDefined(); + }); + + it('check returned false if method called with argument', function() { + var ids = [1,2,3]; + var type = typeof model.getByIds(ids); + expect(type).toEqual('boolean'); + }); + + it('Return false', function() { + var ids = [1,2,3]; + expect(model.getByIds(ids)).toEqual('false'); + }); + + }); + describe('hasScopeChanged', function () { it('is function', function () { var model = new DataStorage({ @@ -72,5 +144,56 @@ define([ expect(model.hasScopeChanged(newParams)).toBeTruthy(); }); }); + describe('"getRequestData" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + it('Check for defined ', function () { + expect(model.hasOwnProperty('getRequestData')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.getRequestData; + + expect(type).toEqual('function'); + }); + + it('check "getRequestData" has been executed', function () { + var request = { + ids: [1,2,3] + }; + expect(model.getRequestData(request)).toBeTruthy(); + }); + }); + + describe('"cacheRequest" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + it('Check for defined ', function () { + expect(model.hasOwnProperty('cacheRequest')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.cacheRequest; + + expect(type).toEqual('function'); + }); + + it('check "cacheRequest" has been executed', function () { + var data = { + items: [1,2,3], + totalRecords: 3, + errorMessage: '' + }, + params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }; + expect(model.cacheRequest(data, params)).toBeTruthy(); + }); + }); }); }); From 585a7d51dfd2bcef817b0b836fbf579805595df0 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 24 Jan 2020 09:38:35 +0200 Subject: [PATCH 050/176] MC-25108: MFTF Flakiness because of bad design - StoreFrontMyAccountWithMultishipmentTest --- .../StorefrontOrderWithMultishippingTest.xml | 4 ++-- .../AdminOrderCheckStatusActionGroup.xml | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderCheckStatusActionGroup.xml diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml index dbc1ba980e9c7..ef63d55ccfe35 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml @@ -93,14 +93,14 @@ <argument name="orderId" value="{$getFirstOrderIdPlaceOrder}"/> </actionGroup> <!-- Check status --> - <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeFirstOrderPendingStatus"/> + <actionGroup ref="AdminOrderViewCheckStatusActionGroup" stepKey="seeFirstOrderPendingStatus"/> <actionGroup ref="AdminSalesOrderActionGroup" stepKey="validateOrderTotalsForFirstOrder"/> <!-- Go to order page --> <actionGroup ref="OpenOrderByIdActionGroup" stepKey="openSecondOrderPage"> <argument name="orderId" value="{$getSecondOrderIdPlaceOrder}"/> </actionGroup> <!-- Check status --> - <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeSecondOrderPendingStatus"/> + <actionGroup ref="AdminOrderViewCheckStatusActionGroup" stepKey="seeSecondOrderPendingStatus"/> <actionGroup ref="AdminSalesOrderActionGroup" stepKey="validateOrderTotalsForSecondOrder"/> </test> </tests> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderCheckStatusActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderCheckStatusActionGroup.xml new file mode 100644 index 0000000000000..f5d46d165efe5 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderCheckStatusActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOrderViewCheckStatusActionGroup"> + <annotations> + <description>Check order status on order view page.</description> + </annotations> + <arguments> + <argument name="status" type="string" defaultValue="Pending"/> + </arguments> + + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="{{status}}" stepKey="seeOrderStatus"/> + </actionGroup> +</actionGroups> From a17c2a51d226f810ddc5bf32a7b28b23b6b59ea2 Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Mon, 27 Jan 2020 01:10:23 +0530 Subject: [PATCH 051/176] More jasmine tests added --- .../Ui/base/js/grid/data-storage.test.js | 434 +++++++++++++++++- 1 file changed, 418 insertions(+), 16 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js index 454fc1280c548..f595020673ed7 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js @@ -62,13 +62,13 @@ define([ }); }); - describe('"getByIds"', function() { + describe('"getByIds" method', function () { var model = new DataStorage({ dataScope: 'magento' }); - it('check for defined', function() { + it('check for defined', function () { expect(model.hasOwnProperty('getByIds')).toBeDefined(); }); @@ -78,23 +78,198 @@ define([ it('Check returned value if method called with argument', function () { var ids = [1,2,3]; + expect(model.getByIds(ids)).toBeDefined(); }); - it('check returned false if method called with argument', function() { - var ids = [1,2,3]; - var type = typeof model.getByIds(ids); + it('check returned type if method called with argument', function () { + var ids = [1,2,3], + type = typeof model.getByIds(ids); + expect(type).toEqual('boolean'); }); - it('Return false', function() { + it('Return false if "getByIds" has been called', function () { + var ids = [1,2,3]; + + expect(model.getByIds(ids)).toEqual(false); + }); + + it('Return array if "getByIds" has been called', function () { + var ids = [1]; + + model = new DataStorage({ + dataScope: 'magento', + data: { + 1: { + id_field_name: 'entity_id', + entity_id: '1' + } + } + }); + + expect(typeof model.getByIds(ids)).toEqual('object'); + }); + + }); + + describe('"getIds" method', function () { + + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('check for defined', function () { + expect(model.hasOwnProperty('getIds')).toBeDefined(); + }); + + it('check method type', function () { + expect(typeof model.getIds).toEqual('function'); + }); + + it('check returned value if method called with argument', function () { var ids = [1,2,3]; - expect(model.getByIds(ids)).toEqual('false'); + + expect(model.getIds(ids)).toBeDefined(); + }); + + it('check returned type if method called with argument', function () { + var ids = [1,2,3], + type = typeof model.getIds(ids); + + expect(type).toEqual('object'); }); }); - describe('hasScopeChanged', function () { + describe('"getData" method', function () { + + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('check for defined', function () { + expect(model.hasOwnProperty('getData')).toBeDefined(); + }); + + it('check method type', function () { + expect(typeof model.getData).toEqual('function'); + }); + + it('check returned value if method called with argument', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }; + + expect(model.getData(params)).toBeDefined(); + }); + + it('check returned type if method called with argument', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }, + type = typeof model.getData(params); + + expect(type).toEqual('object'); + }); + + it('check "clearRequests" has been called', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }; + + spyOn(model, 'clearRequests'); + spyOn(model, 'hasScopeChanged').and.callFake(function () { + return true; + }); + model.getData(params); + expect(model.clearRequests).toHaveBeenCalled(); + }); + + it('check "getRequest" has been called', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }; + + spyOn(model, 'getRequest'); + spyOn(model, 'hasScopeChanged').and.callFake(function () { + return false; + }); + model.getData(params); + expect(model.getRequest).toHaveBeenCalled(); + }); + + it('Return "getRequestData" method', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }, + options = { + refresh: false + }; + + spyOn(model, 'getRequestData'); + spyOn(model, 'getRequest').and.callFake(function () { + return true; + }); + model.getData(params, options); + expect(model.getRequestData).toHaveBeenCalled(); + }); + + it('Return "requestData" method', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }, + options = { + refresh: true + }; + + spyOn(model, 'requestData'); + spyOn(model, 'getRequest').and.callFake(function () { + return false; + }); + model.getData(params, options); + expect(model.requestData).toHaveBeenCalled(); + }); + + }); + + describe('"hasScopeChanged" method', function () { it('is function', function () { var model = new DataStorage({ dataScope: '' @@ -144,10 +319,37 @@ define([ expect(model.hasScopeChanged(newParams)).toBeTruthy(); }); }); + + describe('"updateData" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined ', function () { + expect(model.hasOwnProperty('updateData')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.updateData; + + expect(type).toEqual('function'); + }); + + it('Check updateData has been called', function () { + var data = [{ + id_field_name: 'entity_id', + entity_id: '1' + }]; + + expect(model.updateData(data)).toBeTruthy(); + }); + }); + describe('"getRequestData" method', function () { var model = new DataStorage({ dataScope: 'magento' }); + it('Check for defined ', function () { expect(model.hasOwnProperty('getRequestData')).toBeDefined(); }); @@ -162,6 +364,7 @@ define([ var request = { ids: [1,2,3] }; + expect(model.getRequestData(request)).toBeTruthy(); }); }); @@ -170,6 +373,7 @@ define([ var model = new DataStorage({ dataScope: 'magento' }); + it('Check for defined ', function () { expect(model.hasOwnProperty('cacheRequest')).toBeDefined(); }); @@ -180,19 +384,217 @@ define([ expect(type).toEqual('function'); }); - it('check "cacheRequest" has been executed', function () { - var data = { - items: [1,2,3], - totalRecords: 3, - errorMessage: '' - }, - params = { + it('check "model._requests"', function () { + var params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }, + data = { + items: ['1','2','3'], + totalRecords: 3 + }; + + spyOn(model, 'removeRequest'); + spyOn(model, 'getIds').and.callFake(function () { + return ['1','2','3']; + }); + model.cacheRequest(data, params); + expect(typeof model._requests).toEqual('object'); + expect(model.getIds).toHaveBeenCalled(); + expect(model.removeRequest).not.toHaveBeenCalled(); + }); + + it('check "removeRequest" is executed', function () { + var params = { namespace: 'magento', search: '', sorting: {}, paging: {} + }, + data = { + items: ['1','2','3'], + totalRecords: 3 }; - expect(model.cacheRequest(data, params)).toBeTruthy(); + + spyOn(model, 'removeRequest'); + spyOn(model, 'getRequest').and.callFake(function () { + return true; + }); + spyOn(model, 'getIds').and.callFake(function () { + return ['1','2','3']; + }); + model.cacheRequest(data, params); + expect(typeof model._requests).toEqual('object'); + expect(model.getIds).toHaveBeenCalled(); + expect(model.removeRequest).toHaveBeenCalled(); + }); + }); + + describe('"clearRequests" method', function () { + + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined ', function () { + expect(model.hasOwnProperty('clearRequests')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.clearRequests; + + expect(type).toEqual('function'); + }); + + it('check "clearRequests" will empty _requests array', function () { + var params = { + namespace: 'magento', + search: 'magento', + filters: { + store_id: 1 + } + }; + + model = new DataStorage({ + dataScope: 'magento', + _requests: [] + }); + + model._requests.push({ + ids: ['1','2','3','4'], + params: params, + totalRecords: 4, + errorMessage: 'errorMessage' + }); + model.clearRequests(); + expect(model._requests).toEqual([]); + }); + }); + + describe('"removeRequest" method', function () { + + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined ', function () { + expect(model.hasOwnProperty('removeRequest')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.removeRequest; + + expect(type).toEqual('function'); + }); + + it('check "removeRequest" is defined', function () { + var params = { + namespace: 'magento', + search: 'magento', + filters: { + store_id: 1 + } + }, + request = [{ + ids: [1,2,3], + params: params, + totalRecords: 3, + errorMessage: 'errorMessage' + }]; + + expect(model.removeRequest(request)).toBeDefined(); + }); + }); + + describe('"wasRequested" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined ', function () { + expect(model.hasOwnProperty('wasRequested')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.wasRequested; + + expect(type).toEqual('function'); + }); + + it('Return false if getRequest method returns false', function () { + var params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }; + + model.wasRequested(params); + expect(model.wasRequested(params)).toBeFalsy(); + }); + }); + + describe('"onRequestComplete" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined ', function () { + expect(model.hasOwnProperty('onRequestComplete')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.onRequestComplete; + + expect(type).toEqual('function'); + }); + + it('Check "updateData" method has been called', function () { + var data = { + items: [{ + id_field_name: 'entity_id', + entity_id: '1' + }] + }, +params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }; + + spyOn(model, 'updateData').and.callFake(function () { + return data; + }); + model.onRequestComplete(params, data); + expect(model.updateData).toHaveBeenCalled(); + }); + + it('Check "cacheRequest" method has been called', function () { + var data = { + items: [{ + id_field_name: 'entity_id', + entity_id: '1' + }] + }, + params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }; + + model = new DataStorage({ + dataScope: 'magento', + cacheRequests: true + }); + spyOn(model, 'cacheRequest').and.callFake(function () { + return data; + }); + model.onRequestComplete(params, data); + expect(model.cacheRequest).toHaveBeenCalled(); }); }); }); From 55e2e64e98583cab40b79f97e9c515c439efbe28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Chitesh=40wagento=2Ecom=E2=80=9D?= <hitesh@wagento.com> Date: Mon, 27 Jan 2020 14:47:10 +0530 Subject: [PATCH 052/176] [fixed My Wish List Product not showing properly between >768px and <1023px] --- .../web/css/source/_module.less | 13 +++++++++++++ .../web/css/source/_module.less | 18 +++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less index 9cd0439c13956..b26abd2731131 100644 --- a/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less @@ -53,6 +53,17 @@ } } + .products-grid.wishlist { + .product-item { + margin-left: 2%; + padding: 5px; + width: calc(~'(100% - 4%) / 3'); + &:nth-child(3n + 1) { + margin-left: 0; + } + } + } + .account .table-wrapper .data.table.wishlist { .lib-table-bordered( @_table_type: horizontal @@ -185,6 +196,8 @@ .products-grid.wishlist { .product-item { border-bottom: 1px solid @secondary__color; + margin: 0; + width: 100%; &:first-child { border-top: 1px solid @secondary__color; } diff --git a/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less index 85e8aeb0b515c..0c4be4dcd6c00 100644 --- a/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less @@ -45,6 +45,17 @@ } } + .products-grid.wishlist { + .product-item { + margin-left: 2%; + padding: 5px; + width: calc(~'(100% - 4%) / 3'); + &:nth-child(3n + 1) { + margin-left: 0; + } + } + } + .account .table-wrapper .data.table.wishlist { .lib-table-bordered( @_table_type: horizontal @@ -183,7 +194,7 @@ } } .products-grid.wishlist { - .product-item-actions { + .product-item-actions { .action { &.edit, &.delete { @@ -216,7 +227,8 @@ .products-grid.wishlist { .product-item { border-bottom: 1px solid @secondary__color; - + margin: 0; + width: 100%; &:first-child { border-top: 1px solid @secondary__color; } @@ -253,7 +265,7 @@ &:last-child { margin-right: 0; } - + &.edit, &.delete { margin-top: 7px; From 6aeb8653333b0ec8ca926ac81a73b39e17b78467 Mon Sep 17 00:00:00 2001 From: Sergii Ivashchenko <serg.ivashchenko@gmail.com> Date: Mon, 27 Jan 2020 15:42:34 +0000 Subject: [PATCH 053/176] magento/magento2#25991: Reverted unnecessary changes --- .../Ui/view/base/web/js/grid/columns/image-preview.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/image-preview.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/image-preview.js index 5dd2b53ec54c6..0464788d155e2 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/image-preview.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/image-preview.js @@ -13,8 +13,6 @@ define([ defaults: { bodyTmpl: 'ui/grid/columns/image-preview', previewImageSelector: '[data-image-preview]', - masonrySelector: '.masonry-image-grid', - isListenerActive: false, visibleRecord: null, height: 0, displayedRecord: {}, @@ -48,6 +46,7 @@ define([ */ initialize: function () { this._super(); + $(document).on('keydown', this.handleKeyDown.bind(this)); return this; }, @@ -131,11 +130,6 @@ define([ show: function (record) { var img; - if (!this.isListenerActive) { - $(this.masonrySelector).on('keydown', this.handleKeyDown.bind(this)); - this.isListenerActive = true; - } - if (record._rowIndex === this.visibleRecord()) { this.hide(); From 95e9c5e03bdbe86f233ccd7fe522ae9fc88f181a Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Mon, 27 Jan 2020 13:51:34 -0600 Subject: [PATCH 054/176] MC-25265: Pagebuilder products list doesn't work with anchor category --- .../Catalog/Model/ResourceModel/Product/Collection.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index e31180d4ff6cf..afbe279045a38 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -2121,7 +2121,9 @@ private function getChildrenCategories(int $categoryId): array if (in_array($category['parent_id'], $categoryIds) && in_array($category['parent_id'], $anchorCategory)) { $categoryIds[] = (int)$category[$linkField]; - if ($category['is_anchor'] == 1) { + // Storefront approach is to treat non-anchor children of anchor category as anchors. + // Adding their's IDs to $anchorCategory for consistency. + if ($category['is_anchor'] == 1 || in_array($category['parent_id'], $anchorCategory)) { $anchorCategory[] = (int)$category[$linkField]; } } From 6fbdbbed12051bc306174e1f4f828c3e00ac2e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Chitesh=40wagento=2Ecom=E2=80=9D?= <hitesh@wagento.com> Date: Tue, 28 Jan 2020 13:08:36 +0530 Subject: [PATCH 055/176] [Applied changes as per suggession] --- .../web/css/source/_module.less | 19 ++++++++----------- .../web/css/source/_module.less | 19 ++++++++----------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less index b26abd2731131..20a026ac2af9c 100644 --- a/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less @@ -53,17 +53,6 @@ } } - .products-grid.wishlist { - .product-item { - margin-left: 2%; - padding: 5px; - width: calc(~'(100% - 4%) / 3'); - &:nth-child(3n + 1) { - margin-left: 0; - } - } - } - .account .table-wrapper .data.table.wishlist { .lib-table-bordered( @_table_type: horizontal @@ -139,6 +128,13 @@ .products-grid.wishlist { .product { &-item { + margin-left: 2%; + width: calc(~'(100% - 4%) / 3'); + + &:nth-child(3n + 1) { + margin-left: 0; + } + &-photo { display: block; margin-bottom: @indent__s; @@ -198,6 +194,7 @@ border-bottom: 1px solid @secondary__color; margin: 0; width: 100%; + &:first-child { border-top: 1px solid @secondary__color; } diff --git a/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less index 0c4be4dcd6c00..69342821e9b17 100644 --- a/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less @@ -45,17 +45,6 @@ } } - .products-grid.wishlist { - .product-item { - margin-left: 2%; - padding: 5px; - width: calc(~'(100% - 4%) / 3'); - &:nth-child(3n + 1) { - margin-left: 0; - } - } - } - .account .table-wrapper .data.table.wishlist { .lib-table-bordered( @_table_type: horizontal @@ -146,6 +135,13 @@ .products-grid.wishlist { .product { &-item { + margin-left: 2%; + width: calc(~'(100% - 4%) / 3'); + + &:nth-child(3n + 1) { + margin-left: 0; + } + &-photo { display: block; margin-bottom: @indent__s; @@ -229,6 +225,7 @@ border-bottom: 1px solid @secondary__color; margin: 0; width: 100%; + &:first-child { border-top: 1px solid @secondary__color; } From 00750f42d2404b63f2fad22e3510fd8a363d2838 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Tue, 28 Jan 2020 11:32:24 +0200 Subject: [PATCH 056/176] fix static --- .../Catalog/Model/CategoryLinkRepository.php | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index ae30efdee6e18..f8de9a37f4ed7 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -6,11 +6,19 @@ namespace Magento\Catalog\Model; -use Magento\Framework\Exception\InputException; +use Magento\Catalog\Api\CategoryLinkRepositoryInterface; +use Magento\Catalog\Api\CategoryListDeleteBySkuInterface; +use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\ResourceModel\Product; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Framework\Exception\InputException; -class CategoryLinkRepository implements \Magento\Catalog\Api\CategoryLinkRepositoryInterface, - \Magento\Catalog\Api\CategoryListDeleteBySkuInterface +/** + * @inheritdoc + */ +class CategoryLinkRepository implements CategoryLinkRepositoryInterface, CategoryListDeleteBySkuInterface { /** * @var CategoryRepository @@ -18,32 +26,32 @@ class CategoryLinkRepository implements \Magento\Catalog\Api\CategoryLinkReposit protected $categoryRepository; /** - * @var \Magento\Catalog\Api\ProductRepositoryInterface + * @var ProductRepositoryInterface */ protected $productRepository; /** - * @var \Magento\Catalog\Model\ResourceModel\Product + * @var Product */ private $productResource; /** - * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository - * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository - * @param \Magento\Catalog\Model\ResourceModel\Product $productResource + * @param CategoryRepositoryInterface $categoryRepository + * @param ProductRepositoryInterface $productRepository + * @param Product $productResource */ public function __construct( - \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository, - \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, - \Magento\Catalog\Model\ResourceModel\Product $productResource = null + CategoryRepositoryInterface $categoryRepository, + ProductRepositoryInterface $productRepository, + Product $productResource = null ) { $this->categoryRepository = $categoryRepository; $this->productRepository = $productRepository; - $this->productResource = $productResource ?? \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Catalog\Model\ResourceModel\Product::class); + $this->productResource = $productResource ?? ObjectManager::getInstance()->get(Product::class); } /** - * {@inheritdoc} + * @inheritdoc */ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink) { @@ -69,7 +77,7 @@ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $pro } /** - * {@inheritdoc} + * @inheritdoc */ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink) { @@ -77,7 +85,7 @@ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $p } /** - * {@inheritdoc} + * @inheritdoc */ public function deleteByIds($categoryId, $sku) { @@ -112,7 +120,7 @@ public function deleteByIds($categoryId, $sku) } /** - * {@inheritDoc} + * @inheritdoc */ public function deleteBySkus(int $categoryId, array $productSkuList): bool { From 1cb2bb63b1fd59b4fb2452330693d15fa39d3b03 Mon Sep 17 00:00:00 2001 From: Joan He <johe@magento.com> Date: Tue, 28 Jan 2020 19:56:33 -0600 Subject: [PATCH 057/176] B2B-319: Remove crons and queue consumers - remove purchase order convert to order --- .../Adminhtml/Order/Create/SaveTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/SaveTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/SaveTest.php index 6dba48092c400..2ac14fbdc68cc 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/SaveTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/SaveTest.php @@ -68,6 +68,14 @@ protected function setUp() */ public function testExecuteWithPaymentOperation() { + /** @var OrderService|MockObject $orderService */ + $orderService = $this->getMockBuilder(OrderService::class) + ->disableOriginalConstructor() + ->getMock(); + $orderService->method('place') + ->willThrowException(new LocalizedException(__('Transaction has been declined.'))); + $this->_objectManager->addSharedInstance($orderService, OrderService::class); + $quote = $this->getQuote('2000000001'); $session = $this->_objectManager->get(Quote::class); $session->setQuoteId($quote->getId()); @@ -82,14 +90,6 @@ public function testExecuteWithPaymentOperation() $this->getRequest()->setMethod(Http::METHOD_POST); $this->getRequest()->setPostValue(['order' => $data]); - /** @var OrderService|MockObject $orderService */ - $orderService = $this->getMockBuilder(OrderService::class) - ->disableOriginalConstructor() - ->getMock(); - $orderService->method('place') - ->willThrowException(new LocalizedException(__('Transaction has been declined.'))); - $this->_objectManager->addSharedInstance($orderService, OrderService::class); - $this->dispatch('backend/sales/order_create/save'); $this->assertSessionMessages( self::equalTo(['Transaction has been declined.']), From 5b3a1316eb450753d03abbbb5b7b4dbaffa8ced9 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Wed, 29 Jan 2020 11:55:00 +0200 Subject: [PATCH 058/176] magento/magento2#25249: fix static --- .../Unit/Model/CategoryLinkRepositoryTest.php | 173 ++++++++++++------ 1 file changed, 116 insertions(+), 57 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index 3e679fce64421..483eb8d6795bd 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -6,50 +6,71 @@ namespace Magento\Catalog\Test\Unit\Model; -use Magento\Framework\Exception\InputException; +use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Api\Data\CategoryProductLinkInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\CategoryLinkRepository; +use Magento\Catalog\Model\ResourceModel\Product; +use Magento\Catalog\Model\Category; +use Magento\Catalog\Model\Product as ProductModel; +/** + * Test for \Magento\Catalog\Model\CategoryLinkRepository + * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class CategoryLinkRepositoryTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Catalog\Model\CategoryLinkRepository + * @var CategoryLinkRepository */ protected $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CategoryRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $categoryRepositoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $productRepositoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CategoryProductLinkInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $productLinkMock; + /** + * @var Product|\PHPUnit_Framework_MockObject_MockObject + */ protected $productResourceMock; + /** + * Initialize required data + */ protected function setUp() { - - $this->productResourceMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product::class) + $this->productResourceMock = $this->getMockBuilder(Product::class) ->disableOriginalConstructor() ->setMethods(['getProductsIdsBySkus']) ->getMock(); - $this->categoryRepositoryMock = $this->createMock(\Magento\Catalog\Api\CategoryRepositoryInterface::class); - $this->productRepositoryMock = $this->createMock(\Magento\Catalog\Api\ProductRepositoryInterface::class); - $this->productLinkMock = $this->createMock(\Magento\Catalog\Api\Data\CategoryProductLinkInterface::class); - $this->model = new \Magento\Catalog\Model\CategoryLinkRepository( + $this->categoryRepositoryMock = $this->createMock(CategoryRepositoryInterface::class); + $this->productRepositoryMock = $this->createMock(ProductRepositoryInterface::class); + $this->productLinkMock = $this->createMock(CategoryProductLinkInterface::class); + $this->model = new CategoryLinkRepository( $this->categoryRepositoryMock, $this->productRepositoryMock, $this->productResourceMock ); } - public function testSave() + /** + * Assign a product to the category + * + * @return void + */ + public function testSave(): void { $categoryId = 42; $productId = 55; @@ -57,10 +78,10 @@ public function testSave() $sku = 'testSku'; $productPositions = [$productId => $productPosition]; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getPostedProducts', 'getProductsPosition', 'setPostedProducts', 'save'] ); - $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + $productMock = $this->createMock(ProductModel::class); $this->productLinkMock->expects($this->once())->method('getCategoryId')->willReturn($categoryId); $this->productLinkMock->expects($this->once())->method('getSku')->willReturn($sku); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) @@ -71,14 +92,16 @@ public function testSave() $this->productLinkMock->expects($this->once())->method('getPosition')->willReturn($productPosition); $categoryMock->expects($this->once())->method('setPostedProducts')->with($productPositions); $categoryMock->expects($this->once())->method('save'); + $this->assertTrue($this->model->save($this->productLinkMock)); } /** - * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not save product "55" with position 1 to category 42 + * Assign a product to the category with `CouldNotSaveException` + * + * @return void */ - public function testSaveWithCouldNotSaveException() + public function testSaveWithCouldNotSaveException(): void { $categoryId = 42; $productId = 55; @@ -86,10 +109,10 @@ public function testSaveWithCouldNotSaveException() $sku = 'testSku'; $productPositions = [$productId => $productPosition]; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); - $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + $productMock = $this->createMock(ProductModel::class); $this->productLinkMock->expects($this->once())->method('getCategoryId')->willReturn($categoryId); $this->productLinkMock->expects($this->once())->method('getSku')->willReturn($sku); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) @@ -101,20 +124,28 @@ public function testSaveWithCouldNotSaveException() $categoryMock->expects($this->once())->method('setPostedProducts')->with($productPositions); $categoryMock->expects($this->once())->method('getId')->willReturn($categoryId); $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); + + $this->expectExceptionMessage('Could not save product "55" with position 1 to category 42'); + $this->expectException(\Magento\Framework\Exception\CouldNotSaveException::class); $this->model->save($this->productLinkMock); } - public function testDeleteByIds() + /** + * Remove the product assignment from the category + * + * @return void + */ + public function testDeleteByIds(): void { - $categoryId = "42"; - $productSku = "testSku"; + $categoryId = 42; + $productSku = 'testSku'; $productId = 55; $productPositions = [55 => 1]; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); - $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + $productMock = $this->createMock(ProductModel::class); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) @@ -123,24 +154,26 @@ public function testDeleteByIds() $productMock->expects($this->once())->method('getId')->willReturn($productId); $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('save'); + $this->assertTrue($this->model->deleteByIds($categoryId, $productSku)); } /** - * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not save product "55" with position 1 to category 42 + * Delete the product assignment from the category with `CouldNotSaveException` + * + * @return void */ - public function testDeleteByIdsWithCouldNotSaveException() + public function testDeleteByIdsWithCouldNotSaveException(): void { - $categoryId = "42"; - $productSku = "testSku"; + $categoryId = 42; + $productSku = 'testSku'; $productId = 55; $productPositions = [55 => 1]; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); - $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + $productMock = $this->createMock(ProductModel::class); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) @@ -150,50 +183,61 @@ public function testDeleteByIdsWithCouldNotSaveException() $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('getId')->willReturn($categoryId); $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); + + $this->expectExceptionMessage('Could not save product "55" with position 1 to category 42'); + $this->expectException(\Magento\Framework\Exception\CouldNotSaveException::class); $this->model->deleteByIds($categoryId, $productSku); } /** - * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage The category doesn't contain the specified product. + * Delete the product assignment from the category with `InputException` + * + * @return void */ - public function testDeleteWithInputException() + public function testDeleteWithInputException(): void { - $categoryId = "42"; - $productSku = "testSku"; + $categoryId = 42; + $productSku = 'testSku'; $productId = 60; $productPositions = [55 => 1]; $this->productLinkMock->expects($this->once())->method('getCategoryId')->willReturn($categoryId); $this->productLinkMock->expects($this->once())->method('getSku')->willReturn($productSku); $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); - $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + $productMock = $this->createMock(ProductModel::class); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) ->willReturn($productMock); $categoryMock->expects($this->once())->method('getProductsPosition')->willReturn($productPositions); $productMock->expects($this->once())->method('getId')->willReturn($productId); - $categoryMock->expects($this->never())->method('save'); + + $this->expectExceptionMessage('The category doesn\'t contain the specified product.'); + $this->expectException(\Magento\Framework\Exception\InputException::class); $this->assertTrue($this->model->delete($this->productLinkMock)); } - public function testDelete() + /** + * Delete the product assignment from the category + * + * @return void + */ + public function testDelete(): void { - $categoryId = "42"; - $productSku = "testSku"; + $categoryId = 42; + $productSku = 'testSku'; $productId = 55; $productPositions = [55 => 1]; $this->productLinkMock->expects($this->once())->method('getCategoryId')->willReturn($categoryId); $this->productLinkMock->expects($this->once())->method('getSku')->willReturn($productSku); $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); - $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + $productMock = $this->createMock(ProductModel::class); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) @@ -202,17 +246,23 @@ public function testDelete() $productMock->expects($this->once())->method('getId')->willReturn($productId); $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('save'); + $this->assertTrue($this->model->delete($this->productLinkMock)); } - public function testDeleteBySkus() + /** + * Delete by products skus + * + * @return void + */ + public function testDeleteBySkus(): void { $categoryId = 42; - $productSku = "testSku"; + $productSku = 'testSku'; $productId = 55; $productPositions = [55 => 1]; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) @@ -222,38 +272,44 @@ public function testDeleteBySkus() $categoryMock->expects($this->once())->method('getProductsPosition')->willReturn($productPositions); $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('save'); + $this->assertTrue($this->model->deleteBySkus($categoryId, [$productSku])); } /** - * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage The category doesn't contain the specified products. + * Delete by products skus with `InputException` + * + * @return void */ - public function testDeleteBySkusWithInputException() + public function testDeleteBySkusWithInputException(): void { $categoryId = 42; - $productSku = "testSku"; + $productSku = 'testSku'; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); + + $this->expectExceptionMessage('The category doesn\'t contain the specified products.'); + $this->expectException(\Magento\Framework\Exception\InputException::class); $this->model->deleteBySkus($categoryId, [$productSku]); } /** - * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not save products "testSku" to category 42 + * Delete by products skus with `CouldNotSaveException` + * + * @return void */ - public function testDeleteSkusIdsWithCouldNotSaveException() + public function testDeleteSkusIdsWithCouldNotSaveException(): void { $categoryId = 42; - $productSku = "testSku"; + $productSku = 'testSku'; $productId = 55; $productPositions = [55 => 1]; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) @@ -264,6 +320,9 @@ public function testDeleteSkusIdsWithCouldNotSaveException() $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('getId')->willReturn($categoryId); $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); + + $this->expectExceptionMessage('Could not save products "testSku" to category 42'); + $this->expectException(\Magento\Framework\Exception\CouldNotSaveException::class); $this->assertTrue($this->model->deleteBySkus($categoryId, [$productSku])); } } From f6868655d7cfa3e5eec742a061da3f83b1037a36 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Wed, 29 Jan 2020 12:41:19 +0200 Subject: [PATCH 059/176] magento/magento2#25249: fix cs --- .../Unit/Model/CategoryLinkRepositoryTest.php | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index 483eb8d6795bd..8543d546b6a6b 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -9,10 +9,13 @@ use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Api\Data\CategoryProductLinkInterface; use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Catalog\Model\CategoryLinkRepository; -use Magento\Catalog\Model\ResourceModel\Product; use Magento\Catalog\Model\Category; +use Magento\Catalog\Model\CategoryLinkRepository; use Magento\Catalog\Model\Product as ProductModel; +use Magento\Catalog\Model\ResourceModel\Product; +use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Framework\Exception\InputException; +use PHPUnit_Framework_MockObject_MockObject as MockObject; /** * Test for \Magento\Catalog\Model\CategoryLinkRepository @@ -24,27 +27,27 @@ class CategoryLinkRepositoryTest extends \PHPUnit\Framework\TestCase /** * @var CategoryLinkRepository */ - protected $model; + private $model; /** - * @var CategoryRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CategoryRepositoryInterface|MockObject */ - protected $categoryRepositoryMock; + private $categoryRepositoryMock; /** - * @var ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ProductRepositoryInterface|MockObject */ - protected $productRepositoryMock; + private $productRepositoryMock; /** - * @var CategoryProductLinkInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CategoryProductLinkInterface|MockObject */ - protected $productLinkMock; + private $productLinkMock; /** - * @var Product|\PHPUnit_Framework_MockObject_MockObject + * @var Product|MockObject */ - protected $productResourceMock; + private $productResourceMock; /** * Initialize required data @@ -126,7 +129,7 @@ public function testSaveWithCouldNotSaveException(): void $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); $this->expectExceptionMessage('Could not save product "55" with position 1 to category 42'); - $this->expectException(\Magento\Framework\Exception\CouldNotSaveException::class); + $this->expectException(CouldNotSaveException::class); $this->model->save($this->productLinkMock); } @@ -185,7 +188,7 @@ public function testDeleteByIdsWithCouldNotSaveException(): void $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); $this->expectExceptionMessage('Could not save product "55" with position 1 to category 42'); - $this->expectException(\Magento\Framework\Exception\CouldNotSaveException::class); + $this->expectException(CouldNotSaveException::class); $this->model->deleteByIds($categoryId, $productSku); } @@ -216,7 +219,7 @@ public function testDeleteWithInputException(): void $categoryMock->expects($this->never())->method('save'); $this->expectExceptionMessage('The category doesn\'t contain the specified product.'); - $this->expectException(\Magento\Framework\Exception\InputException::class); + $this->expectException(InputException::class); $this->assertTrue($this->model->delete($this->productLinkMock)); } @@ -293,7 +296,7 @@ public function testDeleteBySkusWithInputException(): void ->willReturn($categoryMock); $this->expectExceptionMessage('The category doesn\'t contain the specified products.'); - $this->expectException(\Magento\Framework\Exception\InputException::class); + $this->expectException(InputException::class); $this->model->deleteBySkus($categoryId, [$productSku]); } @@ -322,7 +325,7 @@ public function testDeleteSkusIdsWithCouldNotSaveException(): void $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); $this->expectExceptionMessage('Could not save products "testSku" to category 42'); - $this->expectException(\Magento\Framework\Exception\CouldNotSaveException::class); + $this->expectException(CouldNotSaveException::class); $this->assertTrue($this->model->deleteBySkus($categoryId, [$productSku])); } } From 88aa6e2b785dc3fae30ac81447f90e67d63c4a20 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Wed, 29 Jan 2020 12:41:44 +0200 Subject: [PATCH 060/176] MC-24243: [MFTF test] Automate by MFTF test MC-27569 "Storefront product grid UI updates on Desktop" --- ...tProductControlsAreNotVisibleWithoutHoverActionGroup.xml | 4 ++-- ...torefrontProductControlsAreVisibleOnHoverActionGroup.xml | 4 ++-- .../Test/Mftf/Section/StorefrontCategoryMainSection.xml | 6 +++--- ...minFillCatalogProductsListWidgetCategoryActionGroup.xml} | 2 +- .../Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml | 2 -- .../Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml | 2 +- ...AddToWishListIconIsClickableForGuestUserActionGroup.xml} | 4 ++-- 7 files changed, 11 insertions(+), 13 deletions(-) rename app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/{AdminFillCatalogProductsListWidgetOptionsActionGroup.xml => AdminFillCatalogProductsListWidgetCategoryActionGroup.xml} (96%) rename app/code/Magento/Wishlist/Test/Mftf/ActionGroup/{AssertStorefrontAddToWishListIconIsClickableActionGroup.xml => AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml} (81%) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml index 8d18c49d6a624..226bb8468d62e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml @@ -13,7 +13,7 @@ </annotations> <dontSeeElement selector="{{StorefrontCategoryMainSection.addToCartButtonProductInfoHover}}" stepKey="assertAddToCartButtonElementIsNotVisible"/> - <dontSeeElement selector="{{StorefrontCategoryMainSection.toWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsNotVisible"/> - <dontSeeElement selector="{{StorefrontCategoryMainSection.toCompareIconProductInfoHover}}" stepKey="assertAddToCompareIconIsNotVisible"/> + <dontSeeElement selector="{{StorefrontCategoryMainSection.addToWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsNotVisible"/> + <dontSeeElement selector="{{StorefrontCategoryMainSection.addToCompareIconProductInfoHover}}" stepKey="assertAddToCompareIconIsNotVisible"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml index 9c26dcecf726a..60d56df04bd2f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml @@ -13,7 +13,7 @@ </annotations> <seeElement selector="{{StorefrontCategoryMainSection.addToCartButtonProductInfoHover}}" stepKey="assertAddToCartButtonElementIsVisible"/> - <seeElement selector="{{StorefrontCategoryMainSection.toWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsVisible"/> - <seeElement selector="{{StorefrontCategoryMainSection.toCompareIconProductInfoHover}}" stepKey="assertAddToCompareIconIsVisible"/> + <seeElement selector="{{StorefrontCategoryMainSection.addToWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsVisible"/> + <seeElement selector="{{StorefrontCategoryMainSection.addToCompareIconProductInfoHover}}" stepKey="assertAddToCompareIconIsVisible"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml index 8f2ba2016aea6..e6fc804fcf90c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml @@ -18,8 +18,8 @@ <element name="specifiedProductItemInfo" type="button" selector="//a[@class='product-item-link'][contains(text(), '{{var1}}')]" parameterized="true"/> <element name="AddToCartBtn" type="button" selector="button.action.tocart.primary"/> <element name="addToCartButtonProductInfoHover" type="button" selector=".product-item-info:hover button.action.tocart.primary"/> - <element name="toWishListIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.towishlist"/> - <element name="toCompareIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.tocompare"/> + <element name="addToWishListIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.towishlist"/> + <element name="addToCompareIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.tocompare"/> <element name="addToCartProductBySku" type="button" selector="//form[@data-product-sku='{{productSku}}']//button[contains(@class, 'tocart')]" parameterized="true" /> <element name="SuccessMsg" type="button" selector="div.message-success"/> <element name="productCount" type="text" selector="#toolbar-amount"/> @@ -30,7 +30,7 @@ <element name="productLink" type="text" selector="a.product-item-link" timeout="30"/> <element name="productLinkByHref" type="text" selector="a.product-item-link[href$='{{var1}}.html']" parameterized="true"/> <element name="productPrice" type="text" selector=".price-final_price"/> - <element name="productPriceByName" type="text" selector="//div[@class='product-item-info']//a[contains(text(), '{{productName}}')]//..//..//span[@class='price']" parameterized="true"/> + <element name="productPriceByName" type="text" selector="//div[contains(@class, 'product-item-info')]//a[contains(text(), '{{productName}}')]//..//..//span[contains(@class, 'price')]" parameterized="true"/> <element name="categoryImage" type="text" selector=".category-image"/> <element name="emptyProductMessage" type="block" selector=".message.info.empty>div"/> <element name="lineProductName" type="text" selector=".products.list.items.product-items li:nth-of-type({{line}}) .product-item-link" timeout="30" parameterized="true"/> diff --git a/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml b/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetCategoryActionGroup.xml similarity index 96% rename from app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml rename to app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetCategoryActionGroup.xml index a5b3078dbdcc4..ecc5780da0e02 100644 --- a/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml +++ b/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetCategoryActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminFillCatalogProductsListWidgetCategoryActionGroup"> <annotations> - <description>Fill Catalog Products List Widget Category.</description> + <description>Fill catalog products list widget category.</description> </annotations> <arguments> diff --git a/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml b/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml index fde10352ab2ba..f1753f4c0b649 100644 --- a/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml +++ b/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml @@ -48,8 +48,6 @@ </actionGroup> <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidgetButton"/> <actionGroup ref="SaveCmsPageActionGroup" stepKey="clickSaveButton"/> - <!-- TODO: REMOVE AFTER FIX MC-29943 --> - <magentoCLI command="indexer:reindex" stepKey="performReindex"/> </before> <after> <deleteData createDataKey="createFirstSimpleProduct" stepKey="deleteFirstSimpleProduct"/> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml index 2ec329bf174b3..c221dd62cd7f6 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminClickInsertWidgetActionGroup"> <annotations> - <description>Click Insert Widget button.</description> + <description>Click "Insert Widget" button in the opened widget popup</description> </annotations> <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidgetButton"/> diff --git a/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml similarity index 81% rename from app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml rename to app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml index 77984a048c5ff..6d2bda0cb9e0b 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml @@ -10,11 +10,11 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup"> <annotations> - <description>Assert AddToWishList icon is clickable</description> + <description>Assert "Add to Wish List" icon is clickable in category product listing</description> </annotations> <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverProduct"/> - <click selector="{{StorefrontCategoryMainSection.toWishListIconProductInfoHover}}" stepKey="clickOnAddToWishListIcon"/> + <click selector="{{StorefrontCategoryMainSection.addToWishListIconProductInfoHover}}" stepKey="clickOnAddToWishListIcon"/> <waitForPageLoad stepKey="waitForCustomerSignInPageLoad"/> <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" stepKey="waitForErrorMessageIsVisible"/> <see selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="You must login or register to add items to your wishlist." stepKey="assertErrorMessage"/> From 56daae0ce5f2b0805683786b54c1a65c26fc2e28 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 30 Jan 2020 12:01:59 +0200 Subject: [PATCH 061/176] Cover cjanges with jasmine test --- .../js/grid/columns/image-preview.test.js | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js index b5c6e75248bfa..e40a64c9c9c17 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js @@ -46,5 +46,37 @@ define([ }); }); + + describe('handleKeyDown method', function () { + it('veify record changed on key down', function () { + var recordMock = { + _rowIndex: 2 + }, + secondRecordMock = { + _rowIndex: 1, + rowNumber: 1 + }, + elementMock = { + keyCode: 37 + }, + masonryMock = { + shows: jasmine.createSpy().and.returnValue([]), + rows: jasmine.createSpy().and.returnValue({ + 1: secondRecordMock + }) + + }, + imageMock = document.createElement('img'); + + spyOn($.fn, 'get').and.returnValue(imageMock); + imagePreview.visibleRecord = jasmine.createSpy().and.returnValue(2); + imagePreview.displayedRecord = ko.observable(); + imagePreview.displayedRecord(recordMock); + imagePreview.masonry = jasmine.createSpy().and.returnValue(masonryMock); + imagePreview.handleKeyDown(elementMock); + expect(imagePreview.displayedRecord()._rowIndex).toBe(secondRecordMock._rowIndex); + }); + + }); }); }); From edc16d5f70dfd1ea3b0223834c657b7ab576826f Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 30 Jan 2020 12:53:16 +0200 Subject: [PATCH 062/176] Destroy spy after test --- .../Magento/Ui/base/js/grid/columns/image-preview.test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js index e40a64c9c9c17..38c7003f08838 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js @@ -66,7 +66,8 @@ define([ }) }, - imageMock = document.createElement('img'); + imageMock = document.createElement('img'), + originMock = $.fn.get; spyOn($.fn, 'get').and.returnValue(imageMock); imagePreview.visibleRecord = jasmine.createSpy().and.returnValue(2); @@ -75,6 +76,7 @@ define([ imagePreview.masonry = jasmine.createSpy().and.returnValue(masonryMock); imagePreview.handleKeyDown(elementMock); expect(imagePreview.displayedRecord()._rowIndex).toBe(secondRecordMock._rowIndex); + $.fn.get = originMock; }); }); From 711895a6e866e1b996e82d51520984587179baeb Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Thu, 30 Jan 2020 15:13:09 +0200 Subject: [PATCH 063/176] MC-24243: [MFTF test] Automate by MFTF test MC-27569 "Storefront product grid UI updates on Desktop" --- .../Test/Mftf/Section/StorefrontCategoryMainSection.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml index e6fc804fcf90c..82b622fbac818 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml @@ -17,9 +17,9 @@ <element name="ProductItemInfo" type="button" selector=".product-item-info"/> <element name="specifiedProductItemInfo" type="button" selector="//a[@class='product-item-link'][contains(text(), '{{var1}}')]" parameterized="true"/> <element name="AddToCartBtn" type="button" selector="button.action.tocart.primary"/> - <element name="addToCartButtonProductInfoHover" type="button" selector=".product-item-info:hover button.action.tocart.primary"/> - <element name="addToWishListIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.towishlist"/> - <element name="addToCompareIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.tocompare"/> + <element name="addToCartButtonProductInfoHover" type="button" selector=".product-item-info:hover button.action.tocart.primary" timeout="30"/> + <element name="addToWishListIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.towishlist" timeout="30"/> + <element name="addToCompareIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.tocompare" timeout="30"/> <element name="addToCartProductBySku" type="button" selector="//form[@data-product-sku='{{productSku}}']//button[contains(@class, 'tocart')]" parameterized="true" /> <element name="SuccessMsg" type="button" selector="div.message-success"/> <element name="productCount" type="text" selector="#toolbar-amount"/> @@ -30,7 +30,7 @@ <element name="productLink" type="text" selector="a.product-item-link" timeout="30"/> <element name="productLinkByHref" type="text" selector="a.product-item-link[href$='{{var1}}.html']" parameterized="true"/> <element name="productPrice" type="text" selector=".price-final_price"/> - <element name="productPriceByName" type="text" selector="//div[contains(@class, 'product-item-info')]//a[contains(text(), '{{productName}}')]//..//..//span[contains(@class, 'price')]" parameterized="true"/> + <element name="productPriceByName" type="text" selector="//div[contains(@class, 'product-item-info')]//a[contains(text(), '{{productName}}')]//parent::strong//parent::div//span[contains(@class, 'price')]" parameterized="true"/> <element name="categoryImage" type="text" selector=".category-image"/> <element name="emptyProductMessage" type="block" selector=".message.info.empty>div"/> <element name="lineProductName" type="text" selector=".products.list.items.product-items li:nth-of-type({{line}}) .product-item-link" timeout="30" parameterized="true"/> From 79963bb6e690de198aa530d2d79d6ec725eb374a Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Thu, 30 Jan 2020 18:22:35 +0200 Subject: [PATCH 064/176] MC-24243: [MFTF test] Automate by MFTF test MC-27569 "Storefront product grid UI updates on Desktop" --- .../Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml | 2 +- ...frontAddToWishListIconIsClickableForGuestUserActionGroup.xml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml index 82b622fbac818..6b67f5609f7f0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml @@ -30,7 +30,7 @@ <element name="productLink" type="text" selector="a.product-item-link" timeout="30"/> <element name="productLinkByHref" type="text" selector="a.product-item-link[href$='{{var1}}.html']" parameterized="true"/> <element name="productPrice" type="text" selector=".price-final_price"/> - <element name="productPriceByName" type="text" selector="//div[contains(@class, 'product-item-info')]//a[contains(text(), '{{productName}}')]//parent::strong//parent::div//span[contains(@class, 'price')]" parameterized="true"/> + <element name="productPriceByName" type="text" selector="//a[contains(text(), '{{productName}}')]//ancestor::div[contains(@class, 'product-item-info')]//span[contains(@class, 'price')]" parameterized="true"/> <element name="categoryImage" type="text" selector=".category-image"/> <element name="emptyProductMessage" type="block" selector=".message.info.empty>div"/> <element name="lineProductName" type="text" selector=".products.list.items.product-items li:nth-of-type({{line}}) .product-item-link" timeout="30" parameterized="true"/> diff --git a/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml index 6d2bda0cb9e0b..690b6b8bc2b59 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml @@ -15,7 +15,6 @@ <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverProduct"/> <click selector="{{StorefrontCategoryMainSection.addToWishListIconProductInfoHover}}" stepKey="clickOnAddToWishListIcon"/> - <waitForPageLoad stepKey="waitForCustomerSignInPageLoad"/> <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" stepKey="waitForErrorMessageIsVisible"/> <see selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="You must login or register to add items to your wishlist." stepKey="assertErrorMessage"/> <seeInCurrentUrl url="{{StorefrontCustomerSignInPage.url}}" stepKey="assertCustomerLoginPageUrl"/> From 292905baa80f5567209a8e6322c86b2bb3a874ff Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 30 Jan 2020 18:08:30 -0600 Subject: [PATCH 065/176] MC-30908: \Magento\Test\Php\LiveCodeTest checks added files incorrectly --- dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php index 8ccda77a25191..b7717492fd124 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php @@ -142,7 +142,7 @@ private static function getAddedFilesList($changedFilesBaseDir) function () { // if no list files, probably, this is the dev environment // phpcs:ignore Generic.PHP.NoSilencedErrors,Magento2.Security.InsecureFunction - @exec('git diff --cached --name-only', $addedFiles); + @exec('git diff --cached --name-only --diff-filter=A', $addedFiles); return $addedFiles; } ); From 996406f506557ecb49ae0951ca1d9c20043a2b92 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 31 Jan 2020 08:56:07 +0200 Subject: [PATCH 066/176] MC-30281: [2.4] Fix and unskip StorefrontSortingByPriceForConfigurableProductWithCatalogRuleAppliedTest --- ...logPriceRuleAddSkuConditionActionGroup.xml | 28 +++++ ...ConfigurableWithCatalogRuleAppliedTest.xml | 105 +++++++++--------- 2 files changed, 83 insertions(+), 50 deletions(-) create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCatalogPriceRuleAddSkuConditionActionGroup.xml diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCatalogPriceRuleAddSkuConditionActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCatalogPriceRuleAddSkuConditionActionGroup.xml new file mode 100644 index 0000000000000..2c4e3ddb648e0 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCatalogPriceRuleAddSkuConditionActionGroup.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCatalogPriceRuleAddSkuConditionActionGroup"> + <annotations> + <description>Create new product SKU based condition in Catalog Price Rule form.</description> + </annotations> + <arguments> + <argument name="productSku" type="string" defaultValue="{{ApiSimpleTwo.sku}}"/> + </arguments> + + <conditionalClick selector="{{AdminNewCatalogPriceRule.conditionsTabTitle}}" dependentSelector="{{AdminNewCatalogPriceRule.conditionsTabBody}}" visible="false" stepKey="openConditionsSectionIfNeeded"/> + <scrollTo selector="{{AdminNewCatalogPriceRule.conditionsTabTitle}}" stepKey="scrollToConditionsFieldset"/> + <waitForElementVisible selector="{{AdminNewCatalogPriceRuleConditions.newCondition}}" stepKey="waitForNewConditionButton"/> + <click selector="{{AdminNewCatalogPriceRuleConditions.newCondition}}" stepKey="clickAddNewConditionButton"/> + <selectOption selector="{{AdminNewCatalogPriceRuleConditions.conditionSelect('1')}}" userInput="Magento\CatalogRule\Model\Rule\Condition\Product|sku" stepKey="selectConditionTypeSku"/> + <waitForPageLoad stepKey="waitConditionFormRefresh"/> + <click selector="{{AdminNewCatalogPriceRuleConditions.targetEllipsis('1')}}" stepKey="clickEllipsis"/> + <fillField selector="{{AdminNewCatalogPriceRuleConditions.targetInput('1', '1')}}" userInput="{{productSku}}" stepKey="fillProductSku"/> + <click selector="{{AdminNewCatalogPriceRuleConditions.applyButton('1', '1')}}" stepKey="clickApply"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml index 7828478bc963e..02700b2fd7c85 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml @@ -8,15 +8,18 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="StorefrontSortingByPriceForConfigurableProductWithCatalogRuleAppliedTest"> + <test name="StorefrontCheckSortingByPriceForConfigurableWithCatalogRuleAppliedTest"> <annotations> <features value="ConfigurableProduct"/> - <stories value="View soting by price in storefront"/> - <title value="Sorting by price for Configurable with Catalog Rule applied"/> + <stories value="Check sorting by price on storefront"/> + <title value="Check sorting by price for Configurable product with Catalog Rule applied"/> <description value="Sort by price should be correct if the apply Catalog Rule to child product of configurable product"/> <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-69988"/> - <group value="configurable_product"/> + <testCaseId value="MC-11926"/> + <useCaseId value="MAGETWO-66688"/> + <group value="catalog"/> + <group value="catalogRule"/> + <group value="configurableProduct"/> </annotations> <before> <createData entity="ApiCategory" stepKey="createCategory"/> @@ -28,63 +31,63 @@ <requiredEntity createDataKey="createCategory"/> <field key="price">10.00</field> </createData> - <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <createData entity="ApiConfigurableProduct" stepKey="createConfigurableProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> - <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigurableProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigurableProductAttributeOption1"> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </createData> - <createData entity="productAttributeOption2" stepKey="createConfigProductAttributeOption2"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption2" stepKey="createConfigurableProductAttributeOption2"> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </createData> - <createData entity="productAttributeOption3" stepKey="createConfigProductAttributeOption3"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption3" stepKey="createConfigurableProductAttributeOption3"> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </createData> <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </createData> <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </getData> <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getConfigAttributeOption2"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </getData> <getData entity="ProductAttributeOptionGetter" index="3" stepKey="getConfigAttributeOption3"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </getData> <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> <requiredEntity createDataKey="getConfigAttributeOption1"/> <field key="price">15.00</field> </createData> <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct2"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> <requiredEntity createDataKey="getConfigAttributeOption2"/> <field key="price">20.00</field> </createData> <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct3"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> <requiredEntity createDataKey="getConfigAttributeOption3"/> <field key="price">25.00</field> </createData> - <createData entity="ConfigurableProductThreeOptions" stepKey="createConfigProductOption"> - <requiredEntity createDataKey="createConfigProduct"/> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <createData entity="ConfigurableProductThreeOptions" stepKey="createConfigurableProductOption"> + <requiredEntity createDataKey="createConfigurableProduct"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> <requiredEntity createDataKey="getConfigAttributeOption1"/> <requiredEntity createDataKey="getConfigAttributeOption2"/> <requiredEntity createDataKey="getConfigAttributeOption3"/> </createData> - <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> - <requiredEntity createDataKey="createConfigProduct"/> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigurableProductAddChild1"> + <requiredEntity createDataKey="createConfigurableProduct"/> <requiredEntity createDataKey="createConfigChildProduct1"/> </createData> - <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild2"> - <requiredEntity createDataKey="createConfigProduct"/> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigurableProductAddChild2"> + <requiredEntity createDataKey="createConfigurableProduct"/> <requiredEntity createDataKey="createConfigChildProduct2"/> </createData> - <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild3"> - <requiredEntity createDataKey="createConfigProduct"/> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigurableProductAddChild3"> + <requiredEntity createDataKey="createConfigurableProduct"/> <requiredEntity createDataKey="createConfigChildProduct3"/> </createData> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> @@ -95,8 +98,8 @@ <actionGroup ref="ChangeUseForPromoRuleConditionsProductAttributeActionGroup" stepKey="changeUseForPromoRuleConditionsProductAttributeToYes"> <argument name="option" value="Yes"/> </actionGroup> - <magentoCLI command="indexer:reindex" stepKey="reindex1"/> - <magentoCLI command="cache:flush" stepKey="flushCache1"/> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllRules"/> + <magentoCLI command="indexer:reindex" stepKey="reindexIndices"/> </before> <after> @@ -106,8 +109,8 @@ <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigChildProduct3" stepKey="deleteConfigChildProduct3"/> - <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> - <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + <deleteData createDataKey="createConfigurableProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigurableProductAttribute" stepKey="deleteConfigProductAttribute"/> <!--SKU Product Attribute is disable for Promo Rule Conditions--> <actionGroup ref="NavigateToEditProductAttributeActionGroup" stepKey="navigateToSkuProductAttribute"> @@ -116,7 +119,12 @@ <actionGroup ref="ChangeUseForPromoRuleConditionsProductAttributeActionGroup" stepKey="changeUseForPromoRuleConditionsProductAttributeToNo"> <argument name="option" value="No"/> </actionGroup> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllRules"/> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + + <!-- TODO: Remove this and change to CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> + <!-- Need reindex because creating new product attributes break some indices and this may affect other tests in testsuite --> + <magentoCLI command="indexer:reindex" stepKey="reindexIndices"/> </after> <!--Open category with products and Sort by price desc--> @@ -127,20 +135,24 @@ <argument name="sortBy" value="price"/> <argument name="sort" value="desc"/> </actionGroup> - <see selector="{{StorefrontCategoryMainSection.lineProductName('1')}}" userInput="$$createConfigProduct.name$$" stepKey="seeConfigurableProduct"/> + <see selector="{{StorefrontCategoryMainSection.lineProductName('1')}}" userInput="$$createConfigurableProduct.name$$" stepKey="seeConfigurableProduct"/> <see selector="{{StorefrontCategoryMainSection.lineProductName('2')}}" userInput="$$createSimpleProduct2.name$$" stepKey="seeSimpleProductTwo"/> <see selector="{{StorefrontCategoryMainSection.lineProductName('3')}}" userInput="$$createSimpleProduct.name$$" stepKey="seeSimpleProduct"/> <!--Create and apply catalog price rule--> - <actionGroup ref="NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup" stepKey="createCatalogPriceRule"> - <argument name="catalogRule" value="CatalogRuleByPercentWith96Amount" /> - <argument name="productSku" value="$$createConfigChildProduct3.sku$$" /> + <actionGroup ref="AdminOpenNewCatalogPriceRuleFormPageActionGroup" stepKey="startCreatingCatalogPriceRule"/> + <actionGroup ref="AdminCatalogPriceRuleFillMainInfoActionGroup" stepKey="fillMainInfoForCatalogPriceRule"> + <argument name="groups" value="'NOT LOGGED IN'"/> </actionGroup> - <actionGroup ref="SelectNotLoggedInCustomerGroupActionGroup" stepKey="selectNotLoggedInCustomerGroup"/> - <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="clickSaveAndApplyRules"/> - - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> + <actionGroup ref="AdminCatalogPriceRuleAddSkuConditionActionGroup" stepKey="addProductSkuBasedCondition"> + <argument name="productSku" value="$createConfigChildProduct3.sku$"/> + </actionGroup> + <actionGroup ref="AdminCatalogPriceRuleFillActionsActionGroup" stepKey="fillActionsForCatalogPriceRule"> + <argument name="apply" value="{{CatalogRuleByPercentWith96Amount.simple_action}}"/> + <argument name="discountAmount" value="{{CatalogRuleByPercentWith96Amount.discount_amount}}"/> + </actionGroup> + <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> + <actionGroup ref="AdminReindexAndFlushCache" stepKey="reindexAndFlushCache"/> <!--Reopen category with products and Sort by price desc--> <actionGroup ref="GoToStorefrontCategoryPageByParametersActionGroup" stepKey="goToStorefrontCategoryPage2"> @@ -152,13 +164,6 @@ </actionGroup> <see selector="{{StorefrontCategoryMainSection.lineProductName('1')}}" userInput="$$createSimpleProduct2.name$$" stepKey="seeSimpleProductTwo2"/> <see selector="{{StorefrontCategoryMainSection.lineProductName('2')}}" userInput="$$createSimpleProduct.name$$" stepKey="seeSimpleProduct2"/> - <see selector="{{StorefrontCategoryMainSection.lineProductName('3')}}" userInput="$$createConfigProduct.name$$" stepKey="seeConfigurableProduct2"/> - - <!-- Delete the rule --> - <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToPriceRulePage"/> - <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule"> - <argument name="name" value="{{CatalogRuleByPercentWith96Amount.name}}"/> - <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> - </actionGroup> + <see selector="{{StorefrontCategoryMainSection.lineProductName('3')}}" userInput="$$createConfigurableProduct.name$$" stepKey="seeConfigurableProduct2"/> </test> </tests> From b1d99e54dd9d9ca0881db11c8e9ca6a04a50b268 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Fri, 31 Jan 2020 11:25:19 +0200 Subject: [PATCH 067/176] Cover test to change --- ...sales_email_order_creditmemo_renderers.xml | 5 +- .../Email/Items/CreditMemo/GroupedTest.php | 60 +++++++++++++++++ .../creditmemo_with_grouped_product.php | 36 ++++++++++ ...editmemo_with_grouped_product_rollback.php | 18 +++++ .../_files/order_with_grouped_product.php | 65 +++++++++++++++++++ .../order_with_grouped_product_rollback.php | 8 +++ 6 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/GroupedTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product_rollback.php diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml index 95fe2f37044c7..2e64b3047cbbb 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml @@ -8,10 +8,7 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="Email Creditmemo Items List" design_abstraction="custom"> <body> <referenceBlock name="sales.email.order.creditmemo.renderers"> - <block class="Magento\GroupedProduct\Block\Order\Email\Items\CreditMemo\Grouped" - name="sales.email.order.creditmemo.renderers.grouped" - as="grouped" - template="Magento_Sales::email/items/creditmemo/default.phtml"/> + <block class="Magento\GroupedProduct\Block\Order\Email\Items\CreditMemo\Grouped" name="sales.email.order.creditmemo.renderers.grouped" as="grouped" template="Magento_Sales::email/items/creditmemo/default.phtml"/> </referenceBlock> </body> </page> diff --git a/dev/tests/integration/testsuite/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/GroupedTest.php b/dev/tests/integration/testsuite/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/GroupedTest.php new file mode 100644 index 0000000000000..8856356227ed9 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/GroupedTest.php @@ -0,0 +1,60 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GroupedProduct\Block\Order\Email\Items\CreditMemo; + +use Magento\Sales\Block\Order\Email\Items\DefaultItems; +use Magento\Sales\Model\Order\Creditmemo; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Verify grouped product block will output correct data. + * + * @magentoAppArea frontend + */ +class GroupedTest extends TestCase +{ + /** + * Test subject. + * + * @var Grouped + */ + private $block; + + /** + * @var CreditMemo + */ + private $creditMemo; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->block = Bootstrap::getObjectManager()->get(Grouped::class); + $this->creditMemo = Bootstrap::getObjectManager()->get(CreditMemo::class); + } + + /** + * Verify, grouped block will output correct product sku and name. + * + * @magentoDataFixture Magento/Sales/_files/creditmemo_with_grouped_product.php + */ + public function testToHtml() + { + $creditMemo = $this->creditMemo->load('100000002', 'increment_id'); + $creditMemoItem = $creditMemo->getItemsCollection()->getFirstItem(); + $priceBlock = Bootstrap::getObjectManager()->create(DefaultItems::class); + $this->block->setTemplate('Magento_Sales::email/items/creditmemo/default.phtml'); + $this->block->setItem($creditMemoItem); + $this->block->getLayout()->setBlock('item_price', $priceBlock); + $output = $this->block->toHtml(); + self::assertContains('SKU: simple_11', $output); + self::assertContains('"product-name">Simple 11', $output); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product.php b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product.php new file mode 100644 index 0000000000000..5f5f534ae2cee --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Sales\Model\Order\Creditmemo; +use Magento\Sales\Model\Order\Creditmemo\Item; +use Magento\Sales\Model\Order\CreditmemoFactory; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/order_with_grouped_product.php'; + +$objectManager = Bootstrap::getObjectManager(); + +$creditmemoFactory = $objectManager->get(CreditmemoFactory::class); +$creditmemo = $creditmemoFactory->createByOrder($order, $order->getData()); +$creditmemo->setOrder($order); +$creditmemo->setState(Creditmemo::STATE_OPEN); +$creditmemo->setIncrementId('100000002'); +$creditmemo->save(); + +$orderItem = current($order->getAllItems()); +$orderItem->setName('Test item') + ->setQtyRefunded(1) + ->setQtyInvoiced(10) + ->setOriginalPrice(20); + +$creditItem = $objectManager->get(Item::class); +$creditItem->setCreditmemo($creditmemo) + ->setName('Creditmemo item') + ->setOrderItemId($orderItem->getId()) + ->setQty(1) + ->setPrice(20) + ->save(); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product_rollback.php new file mode 100644 index 0000000000000..c8420f8a252ca --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product_rollback.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Sales\Model\Order\Creditmemo; +use Magento\Sales\Model\ResourceModel\Order\Creditmemo\Collection; +use Magento\TestFramework\Helper\Bootstrap; + +require 'default_rollback.php'; + +/** @var $creditmemo Creditmemo */ +$creditmemoCollection = Bootstrap::getObjectManager()->create(Collection::class); +foreach ($creditmemoCollection as $creditmemo) { + $creditmemo->delete(); +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product.php new file mode 100644 index 0000000000000..0cdc2d10e6f06 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product.php @@ -0,0 +1,65 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Address as OrderAddress; +use Magento\Sales\Model\Order\Item as OrderItem; +use Magento\Sales\Model\Order\Payment; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +require 'default_rollback.php'; +require __DIR__ . '/../../../Magento/GroupedProduct/_files/product_grouped_with_simple.php'; +$addressData = include __DIR__ . '/address_data.php'; + +$objectManager = Bootstrap::getObjectManager(); +$billingAddress = $objectManager->create(OrderAddress::class, ['data' => $addressData]); +$billingAddress->setAddressType('billing'); + +$shippingAddress = clone $billingAddress; +$shippingAddress->setId(null)->setAddressType('shipping'); + +$payment = $objectManager->create(Payment::class); +$payment->setMethod('checkmo') + ->setAdditionalInformation('last_trans_id', '11122') + ->setAdditionalInformation( + 'metadata', + [ + 'type' => 'free', + 'fraudulent' => false, + ] + ); +$product = $objectManager->get(ProductRepositoryInterface::class)->get('simple_11'); +$orderItem = $objectManager->create(OrderItem::class); +$orderItem->setProductId($product->getId()) + ->setQtyOrdered(2) + ->setBasePrice($product->getPrice()) + ->setPrice($product->getPrice()) + ->setRowTotal($product->getPrice()) + ->setProductType('grouped') + ->setName($product->getName()) + ->setSku($product->getSku()); + +$order = $objectManager->create(Order::class); +$order->setIncrementId('100000002') + ->setState(Order::STATE_PROCESSING) + ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_PROCESSING)) + ->setSubtotal(100) + ->setGrandTotal(100) + ->setBaseSubtotal(100) + ->setBaseGrandTotal(100) + ->setCustomerIsGuest(true) + ->setCustomerEmail('customer@null.com') + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setStoreId($objectManager->get(StoreManagerInterface::class)->getStore()->getId()) + ->addItem($orderItem) + ->setPayment($payment); +$orderRepository = $objectManager->create(OrderRepositoryInterface::class); +$orderRepository->save($order); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product_rollback.php new file mode 100644 index 0000000000000..1fb4b4636ab29 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product_rollback.php @@ -0,0 +1,8 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +require 'default_rollback.php'; From 98d319b3f5c9f170da5ffca234cac212973b3817 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 31 Jan 2020 15:10:24 +0200 Subject: [PATCH 068/176] MC-30281: [2.4] Fix and unskip StorefrontSortingByPriceForConfigurableProductWithCatalogRuleAppliedTest --- ...ngByPriceForConfigurableWithCatalogRuleAppliedTest.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml index 02700b2fd7c85..85f35703592c1 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml @@ -99,7 +99,8 @@ <argument name="option" value="Yes"/> </actionGroup> <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllRules"/> - <magentoCLI command="indexer:reindex" stepKey="reindexIndices"/> + <!-- TODO: Replace this with CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> + <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext catalog_category_product" stepKey="reindexIndices"/> </before> <after> @@ -122,9 +123,8 @@ <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllRules"/> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> - <!-- TODO: Remove this and change to CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> - <!-- Need reindex because creating new product attributes break some indices and this may affect other tests in testsuite --> - <magentoCLI command="indexer:reindex" stepKey="reindexIndices"/> + <!-- TODO: Replace this with CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> + <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext catalog_category_product" stepKey="reindexIndices"/> </after> <!--Open category with products and Sort by price desc--> From 1c6a7a3518343991909fa9605d173f9de1f1fb42 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Fri, 31 Jan 2020 23:11:23 +0100 Subject: [PATCH 069/176] #CoreReview Fix backward compatibility --- .../Block/Product/ProductsList.php | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php b/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php index 4a75c806aa37b..2175889ce84e8 100644 --- a/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php +++ b/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php @@ -8,6 +8,7 @@ use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Block\Product\AbstractProduct; +use Magento\Catalog\Block\Product\Context; use Magento\Catalog\Block\Product\Widget\Html\Pager; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Visibility; @@ -16,7 +17,7 @@ use Magento\Catalog\Pricing\Price\FinalPrice; use Magento\CatalogWidget\Model\Rule; use Magento\Framework\App\ActionInterface; -use Magento\Framework\App\Http\Context; +use Magento\Framework\App\Http\Context as HttpContext; use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject\IdentityInterface; use Magento\Framework\Exception\LocalizedException; @@ -27,7 +28,7 @@ use Magento\Framework\View\LayoutFactory; use Magento\Framework\View\LayoutInterface; use Magento\Rule\Model\Condition\Combine; -use Magento\Rule\Model\Condition\Sql\Builder; +use Magento\Rule\Model\Condition\Sql\Builder as SqlBuilder; use Magento\Widget\Block\BlockInterface; use Magento\Widget\Helper\Conditions; @@ -69,7 +70,7 @@ class ProductsList extends AbstractProduct implements BlockInterface, IdentityIn protected $pager; /** - * @var Context + * @var HttpContext */ protected $httpContext; @@ -88,7 +89,7 @@ class ProductsList extends AbstractProduct implements BlockInterface, IdentityIn protected $productCollectionFactory; /** - * @var Builder + * @var SqlBuilder */ protected $sqlBuilder; @@ -135,34 +136,34 @@ class ProductsList extends AbstractProduct implements BlockInterface, IdentityIn private $categoryRepository; /** - * @param \Magento\Catalog\Block\Product\Context $context + * @param Context $context * @param CollectionFactory $productCollectionFactory * @param Visibility $catalogProductVisibility - * @param Context $httpContext - * @param Builder $sqlBuilder + * @param HttpContext $httpContext + * @param SqlBuilder $sqlBuilder * @param Rule $rule * @param Conditions $conditionsHelper - * @param CategoryRepositoryInterface $categoryRepository * @param array $data * @param Json|null $json * @param LayoutFactory|null $layoutFactory * @param EncoderInterface|null $urlEncoder + * @param CategoryRepositoryInterface|null $categoryRepository * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( - \Magento\Catalog\Block\Product\Context $context, + Context $context, CollectionFactory $productCollectionFactory, Visibility $catalogProductVisibility, - Context $httpContext, - Builder $sqlBuilder, + HttpContext $httpContext, + SqlBuilder $sqlBuilder, Rule $rule, Conditions $conditionsHelper, - CategoryRepositoryInterface $categoryRepository, array $data = [], Json $json = null, LayoutFactory $layoutFactory = null, - EncoderInterface $urlEncoder = null + EncoderInterface $urlEncoder = null, + CategoryRepositoryInterface $categoryRepository = null ) { $this->productCollectionFactory = $productCollectionFactory; $this->catalogProductVisibility = $catalogProductVisibility; @@ -173,7 +174,8 @@ public function __construct( $this->json = $json ?: ObjectManager::getInstance()->get(Json::class); $this->layoutFactory = $layoutFactory ?: ObjectManager::getInstance()->get(LayoutFactory::class); $this->urlEncoder = $urlEncoder ?: ObjectManager::getInstance()->get(EncoderInterface::class); - $this->categoryRepository = $categoryRepository; + $this->categoryRepository = $categoryRepository ?? ObjectManager::getInstance() + ->get(CategoryRepositoryInterface::class); parent::__construct( $context, $data From 5000cd9aa766448ad3a9812052474f75beb96604 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Fri, 31 Jan 2020 23:19:46 +0100 Subject: [PATCH 070/176] #CoreReview Improve test readability with const STUB and extracting assertions, using Phrase placeholder --- .../DeleteCategoryWithEnabledFlatTest.php | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Delete/DeleteCategoryWithEnabledFlatTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Delete/DeleteCategoryWithEnabledFlatTest.php index 357b7247412d9..efa19b98d077f 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Delete/DeleteCategoryWithEnabledFlatTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Delete/DeleteCategoryWithEnabledFlatTest.php @@ -24,6 +24,8 @@ */ class DeleteCategoryWithEnabledFlatTest extends AbstractBackendController { + const STUB_CATEGORY_ID = 333; + /** * @var IndexerRegistry */ @@ -79,13 +81,16 @@ protected function tearDown() */ public function testDeleteCategory(): void { - $this->assertEquals(1, $this->getFlatCategoryCollectionSizeByCategoryId(333)); - $this->getRequest()->setMethod(HttpRequest::METHOD_POST); - $this->getRequest()->setPostValue(['id' => 333]); - $this->dispatch('backend/catalog/category/delete'); + // Given + $this->assertEquals(1, $this->getFlatCategoryCollectionSizeByCategoryId(self::STUB_CATEGORY_ID)); + + // When + $this->sendDeleteCategoryRequest(self::STUB_CATEGORY_ID); + + // Then $this->assertSessionMessages($this->equalTo([(string)__('You deleted the category.')])); - $this->assertEquals(0, $this->getFlatCategoryCollectionSizeByCategoryId(333)); - $this->checkCategoryIsDeleted(333); + $this->assertEquals(0, $this->getFlatCategoryCollectionSizeByCategoryId(self::STUB_CATEGORY_ID)); + $this->checkCategoryIsDeleted(self::STUB_CATEGORY_ID); } /** @@ -106,10 +111,26 @@ private function getFlatCategoryCollectionSizeByCategoryId(int $categoryId): int * Assert that category is deleted. * * @param int $categoryId + * @return void */ private function checkCategoryIsDeleted(int $categoryId): void { - $this->expectExceptionObject(new NoSuchEntityException(__("No such entity with id = {$categoryId}"))); + $this->expectExceptionObject( + new NoSuchEntityException(__("No such entity with id = %entityId", ['entityId' => $categoryId])) + ); $this->categoryRepository->get($categoryId); } + + /** + * Method passes the request to Backend to remove given category. + * + * @param int $categoryId + * @return void + */ + private function sendDeleteCategoryRequest(int $categoryId): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue(['id' => $categoryId]); + $this->dispatch('backend/catalog/category/delete'); + } } From e943bda91d0b03a0fc67fb78b82254986796396c Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Sat, 1 Feb 2020 12:25:23 +1030 Subject: [PATCH 071/176] #26622 - Check quote item for parentItem instead of parentItemId, as the latter is only set in beforeSave function. --- app/code/Magento/SalesRule/Model/Validator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php index dad35165051ce..addfd6107f600 100644 --- a/app/code/Magento/SalesRule/Model/Validator.php +++ b/app/code/Magento/SalesRule/Model/Validator.php @@ -383,7 +383,7 @@ public function initTotals($items, Address $address) foreach ($items as $item) { //Skipping child items to avoid double calculations - if ($item->getParentItemId()) { + if ($item->getParentItem()) { continue; } if (!$rule->getActions()->validate($item)) { From 7fafb2d13517705d86ca0c65cfa52d52bd1c5c40 Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Sat, 1 Feb 2020 17:41:26 +0530 Subject: [PATCH 072/176] More method cover with jasmine tests --- .../Ui/base/js/grid/data-storage.test.js | 133 +++++++++++++++++- 1 file changed, 129 insertions(+), 4 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js index f595020673ed7..163466ebe9175 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js @@ -6,9 +6,11 @@ /*eslint max-nested-callbacks: 0*/ /*jscs:disable requireCamelCaseOrUpperCaseIdentifiers*/ define([ + 'jquery', 'mageUtils', + 'underscore', 'Magento_Ui/js/grid/data-storage' -], function (utils, DataStorage) { +], function ($, utils, _, DataStorage) { 'use strict'; describe('Magento_Ui/js/grid/data-storage', function () { @@ -322,7 +324,12 @@ define([ describe('"updateData" method', function () { var model = new DataStorage({ - dataScope: 'magento' + dataScope: 'magento', + requestConfig: { + url: 'magento.com', + method: 'GET', + dataType: 'json' + } }); it('Check for defined ', function () { @@ -345,6 +352,83 @@ define([ }); }); + describe('"requestData" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined', function () { + expect(model.hasOwnProperty('requestData')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.requestData; + + expect(type).toEqual('function'); + }); + + it('Check Ajax request', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }, + query = utils.copy(params); + + spyOn(model, 'onRequestComplete'); + spyOn($, 'ajax').and.callFake(function () { + return { + /** + * Success result for ajax request + */ + done: function () { + model.onRequestComplete(model, query); + } + }; + }); + model.requestData(params); + expect($.ajax).toHaveBeenCalled(); + expect(model.onRequestComplete).toHaveBeenCalled(); + }); + }); + + describe('"getRequest" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined', function () { + expect(model.hasOwnProperty('getRequest')).toBeDefined(); + }); + + it('Check method', function () { + var type = typeof model.getRequest; + + expect(type).toEqual('function'); + }); + + it('check "getRequest" has been executed', function () { + var params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }; + + model._requests.push({ + ids: ['1'], + params: params, + totalRecords: 1, + errorMessage: '' + }); + expect(model.getRequest(params)).toBeTruthy(); + }); + }); + describe('"getRequestData" method', function () { var model = new DataStorage({ dataScope: 'magento' @@ -367,6 +451,45 @@ define([ expect(model.getRequestData(request)).toBeTruthy(); }); + + it('check "getByIds" has been executed', function () { + var request = { + ids: [1,2,3] + }; + + spyOn(model, 'getByIds'); + model.getRequestData(request); + expect(model.getByIds).toHaveBeenCalled(); + }); + + it('check "delay" function has been executed', function () { + var request = { + ids: [1,2,3], + totalRecords: 3, + errorMessage: '' + }; + + spyOn(_, 'delay'); + model.getRequestData(request); + expect(_.delay).toHaveBeenCalled(); + }); + + it('check "delay" function has not been executed', function () { + var request = { + ids: [1,2,3], + totalRecords: 3, + errorMessage: '' + }; + + model = new DataStorage({ + dataScope: 'magento', + cachedRequestDelay: 0 + }); + + spyOn(_, 'delay'); + model.getRequestData(request); + expect(_.delay).not.toHaveBeenCalled(); + }); }); describe('"cacheRequest" method', function () { @@ -531,7 +654,9 @@ define([ paging: {} }; - model.wasRequested(params); + spyOn(model, 'getRequest').and.callFake(function () { + return false; + }); expect(model.wasRequested(params)).toBeFalsy(); }); }); @@ -558,7 +683,7 @@ define([ entity_id: '1' }] }, -params = { + params = { namespace: 'magento', search: '', sorting: {}, From 9de1e591300d8b77a7aeeffda2c3c01ab4763e55 Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Sat, 1 Feb 2020 23:27:22 +0530 Subject: [PATCH 073/176] Fixed static tests --- .../code/Magento/Ui/base/js/grid/data-storage.test.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js index 163466ebe9175..02d303782a9d5 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js @@ -480,12 +480,10 @@ define([ totalRecords: 3, errorMessage: '' }; - - model = new DataStorage({ - dataScope: 'magento', - cachedRequestDelay: 0 - }); - + model = new DataStorage({ + dataScope: 'magento', + cachedRequestDelay: 0 + }); spyOn(_, 'delay'); model.getRequestData(request); expect(_.delay).not.toHaveBeenCalled(); From 4e2662f9f2d863d2c657bd4c3a4d8b7263a8933a Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Mon, 3 Feb 2020 10:01:44 +0200 Subject: [PATCH 074/176] MC-30864: Payflow link payment method allways returns message: Your paiment has been declined --- app/code/Magento/Paypal/Model/Payflowlink.php | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Paypal/Model/Payflowlink.php b/app/code/Magento/Paypal/Model/Payflowlink.php index 690e09ffd8770..f16b117daf56e 100644 --- a/app/code/Magento/Paypal/Model/Payflowlink.php +++ b/app/code/Magento/Paypal/Model/Payflowlink.php @@ -36,7 +36,7 @@ class Payflowlink extends \Magento\Paypal\Model\Payflowpro * * @var string */ - protected $_code = \Magento\Paypal\Model\Config::METHOD_PAYFLOWLINK; + protected $_code = Config::METHOD_PAYFLOWLINK; /** * @var string @@ -116,6 +116,11 @@ class Payflowlink extends \Magento\Paypal\Model\Payflowpro */ private $mathRandom; + /** + * @var \Magento\Framework\App\RequestInterface + */ + private $_requestHttp; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -237,8 +242,8 @@ public function isActive($storeId = null) public function initialize($paymentAction, $stateObject) { switch ($paymentAction) { - case \Magento\Paypal\Model\Config::PAYMENT_ACTION_AUTH: - case \Magento\Paypal\Model\Config::PAYMENT_ACTION_SALE: + case Config::PAYMENT_ACTION_AUTH: + case Config::PAYMENT_ACTION_SALE: $payment = $this->getInfoInstance(); /** @var Order $order */ $order = $payment->getOrder(); @@ -345,6 +350,7 @@ protected function _processOrder(\Magento\Sales\Model\Order $order) $payment->registerAuthorizationNotification($payment->getBaseAmountAuthorized()); break; case self::TRXTYPE_SALE: + $order->setState(Order::STATE_PROCESSING); $payment->registerCaptureNotification($payment->getBaseAmountAuthorized()); break; default: @@ -500,14 +506,12 @@ public function buildBasicRequest() */ protected function _getTrxTokenType() { - switch ($this->getConfigData('payment_action')) { - case \Magento\Paypal\Model\Config::PAYMENT_ACTION_AUTH: - return self::TRXTYPE_AUTH_ONLY; - case \Magento\Paypal\Model\Config::PAYMENT_ACTION_SALE: - return self::TRXTYPE_SALE; - default: - break; - } + $tokenTypes = [ + Config::PAYMENT_ACTION_AUTH => self::TRXTYPE_AUTH_ONLY, + Config::PAYMENT_ACTION_SALE => self::TRXTYPE_SALE + ]; + + return $tokenTypes[$this->getConfigData('payment_action')] ?? ''; } /** From fab00b6bcc6c2cd537f038a952ee1b12e6f3a975 Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Mon, 3 Feb 2020 10:39:31 +0200 Subject: [PATCH 075/176] MC-29999: A site with optional telephone will sometimes require one --- .../Model/Address/Validator/General.php | 15 +++++ app/code/Magento/Eav/Model/Config.php | 28 +++++---- .../Model/CustomerAddressAttributeTest.php | 63 +++++++++++++++++++ 3 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/CustomerAddressAttributeTest.php diff --git a/app/code/Magento/Customer/Model/Address/Validator/General.php b/app/code/Magento/Customer/Model/Address/Validator/General.php index 7cbb6ef1ab623..4888cd227db48 100644 --- a/app/code/Magento/Customer/Model/Address/Validator/General.php +++ b/app/code/Magento/Customer/Model/Address/Validator/General.php @@ -5,6 +5,7 @@ */ namespace Magento\Customer\Model\Address\Validator; +use Magento\Customer\Api\AddressMetadataInterface; use Magento\Customer\Model\Address\AbstractAddress; use Magento\Customer\Model\Address\ValidatorInterface; @@ -87,6 +88,7 @@ private function checkRequiredFields(AbstractAddress $address) */ private function checkOptionalFields(AbstractAddress $address) { + $this->reloadAddressAttributes($address); $errors = []; if ($this->isTelephoneRequired() && !\Zend_Validate::is($address->getTelephone(), 'NotEmpty') @@ -148,4 +150,17 @@ private function isFaxRequired() { return $this->eavConfig->getAttribute('customer_address', 'fax')->getIsRequired(); } + + /** + * Reload address attributes for the certain store + * + * @param AbstractAddress $address + * @return void + */ + private function reloadAddressAttributes(AbstractAddress $address): void + { + $attributeSetId = $address->getAttributeSetId() ?: AddressMetadataInterface::ATTRIBUTE_SET_ID_ADDRESS; + $address->setData('attribute_set_id', $attributeSetId); + $this->eavConfig->getEntityAttributes(AddressMetadataInterface::ENTITY_TYPE_ADDRESS, $address); + } } diff --git a/app/code/Magento/Eav/Model/Config.php b/app/code/Magento/Eav/Model/Config.php index 20126d5146c35..68dd68b59e8ee 100644 --- a/app/code/Magento/Eav/Model/Config.php +++ b/app/code/Magento/Eav/Model/Config.php @@ -245,8 +245,8 @@ private function loadAttributes($entityTypeCode) /** * Associate object with identifier * - * @param mixed $obj - * @param mixed $id + * @param mixed $obj + * @param mixed $id * @return void * @codeCoverageIgnore */ @@ -271,8 +271,8 @@ private function saveAttribute(AbstractAttribute $attribute, $entityTypeCode, $a /** * Specify reference for entity type id * - * @param int $id - * @param string $code + * @param int $id + * @param string $code * @return $this * @codeCoverageIgnore */ @@ -296,9 +296,9 @@ protected function _getEntityTypeReference($id) /** * Specify reference between entity attribute id and attribute code * - * @param int $id - * @param string $code - * @param string $entityTypeCode + * @param int $id + * @param string $code + * @param string $entityTypeCode * @return $this */ protected function _addAttributeReference($id, $code, $entityTypeCode) @@ -522,9 +522,9 @@ public function getAttributes($entityType) /** * Get attribute by code for entity type * - * @param mixed $entityType - * @param mixed $code - * @return AbstractAttribute + * @param mixed $entityType + * @param mixed $code + * @return AbstractAttribute * @throws LocalizedException */ public function getAttribute($entityType, $code) @@ -737,8 +737,8 @@ public function getEntityAttributeCodes($entityType, $object = null) /** * Get all entity type attributes * - * @param int|string|Type $entityType - * @param \Magento\Framework\DataObject|null $object + * @param int|string|Type $entityType + * @param \Magento\Framework\DataObject|null $object * @return AbstractAttribute[] * * @SuppressWarnings(PHPMD.CyclomaticComplexity) @@ -822,6 +822,10 @@ protected function _createAttribute($entityType, $attributeData) $fullAttributeData = array_key_exists('is_required', $attributeData); if ($existsFullAttribute || (!$existsFullAttribute && !$fullAttributeData)) { + $scopeIsRequired = $attributeData['scope_is_required'] ?? null; + if ($scopeIsRequired !== null) { + $attribute->setData('scope_is_required', $scopeIsRequired); + } return $attribute; } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerAddressAttributeTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerAddressAttributeTest.php new file mode 100644 index 0000000000000..866fd2c97207e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerAddressAttributeTest.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model; + +use Magento\Customer\Model\Metadata\AddressMetadata; +use Magento\Eav\Model\Config; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +class CustomerAddressAttributeTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var Config + */ + private $config; + + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->config = $objectManager->get(Config::class); + $this->storeManager = $objectManager->get(StoreManagerInterface::class); + } + + /** + * Tests cached scope_is_required attribute value for a certain website + * + * @return void + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + */ + public function testGetScopeIsRequiredAttributeValueFromCache(): void + { + $attributeCode = 'telephone'; + $entityType = AddressMetadata::ENTITY_TYPE_ADDRESS; + $attribute = $this->config->getAttribute($entityType, $attributeCode); + $currentStore = $this->storeManager->getStore(); + $secondWebsite = $this->storeManager->getWebsite('test'); + $attribute->setWebsite($secondWebsite->getId()); + $attribute->setData('scope_is_required', '0'); + $attribute->save(); + $this->config->getAttribute($entityType, $attributeCode); + $this->storeManager->setCurrentStore('fixture_second_store'); + try { + $this->config->getEntityAttributes($attribute->getEntityTypeId(), $attribute); + $scopeAttribute = $this->config->getAttribute($entityType, $attributeCode); + $this->assertEquals(0, $scopeAttribute->getIsRequired()); + } finally { + $this->storeManager->setCurrentStore($currentStore); + } + } +} From 587f3ce03d4f9766d98d1cbe0207ba1f355e731f Mon Sep 17 00:00:00 2001 From: Pratik Mehta <pratik@seepossible.com> Date: Mon, 3 Feb 2020 14:20:34 +0530 Subject: [PATCH 076/176] Comment add in translate. --- app/code/Magento/Backend/etc/adminhtml/system.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Backend/etc/adminhtml/system.xml b/app/code/Magento/Backend/etc/adminhtml/system.xml index 65744e56d94ac..91feb4b5167ad 100644 --- a/app/code/Magento/Backend/etc/adminhtml/system.xml +++ b/app/code/Magento/Backend/etc/adminhtml/system.xml @@ -115,7 +115,7 @@ <label>Enable Template Path Hints for Storefront</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> - <field id="template_hints_storefront_show_with_parameter" translate="label" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> + <field id="template_hints_storefront_show_with_parameter" translate="label comment" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Enable Hints for Storefront with URL Parameter</label> <depends> <field id="*/*/template_hints_storefront">1</field> @@ -123,7 +123,7 @@ <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> <comment>Use URL parameter to enable template path hints for Storefront</comment> </field> - <field id="template_hints_parameter_value" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> + <field id="template_hints_parameter_value" translate="label comment" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Parameter Value</label> <depends> <field id="*/*/template_hints_storefront">1</field> From 49cfa49da66cc6baf446b8e34b516377a1f85348 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 3 Feb 2020 10:54:02 +0200 Subject: [PATCH 077/176] MC-30281: [2.4] Fix and unskip StorefrontSortingByPriceForConfigurableProductWithCatalogRuleAppliedTest --- .../Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml | 2 +- ...SortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml b/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml index be0fdb2e0b419..8be6b809aa77b 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml @@ -63,7 +63,7 @@ <element name="targetEllipsisSelect" type="select" selector="select#conditions__{{var1}}--{{var2}}__value" parameterized="true" timeout="30"/> <element name="targetSelect" type="select" selector="//ul[@id='conditions__{{var}}__children']//select" parameterized="true" timeout="30"/> <element name="targetInput" type="input" selector="input#conditions__{{var1}}--{{var2}}__value" parameterized="true"/> - <element name="applyButton" type="button" selector="#conditions__{{var1}}__children li:nth-of-type({{var2}}) a.rule-param-apply" parameterized="true"/> + <element name="applyButton" type="button" selector="#conditions__{{var1}}__children li:nth-of-type({{var2}}) a.rule-param-apply" parameterized="true" timeout="30"/> <element name="condition" type="text" selector="//span[@class='rule-param']/a[text()='{{condition}}']" parameterized="true"/> <element name="activeOperatorSelect" type="select" selector=".rule-param-edit select[name*='[operator]']"/> <element name="activeValueInput" type="input" selector=".rule-param-edit [name*='[value]']"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml index 85f35703592c1..4e8274203365c 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml @@ -152,7 +152,8 @@ <argument name="discountAmount" value="{{CatalogRuleByPercentWith96Amount.discount_amount}}"/> </actionGroup> <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> - <actionGroup ref="AdminReindexAndFlushCache" stepKey="reindexAndFlushCache"/> + <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext catalog_category_product catalog_product_price catalogrule_rule" stepKey="reindexIndices"/> + <magentoCLI command="cache:clean" arguments="full_page block_html" stepKey="flushCache"/> <!--Reopen category with products and Sort by price desc--> <actionGroup ref="GoToStorefrontCategoryPageByParametersActionGroup" stepKey="goToStorefrontCategoryPage2"> From 0e7063ab0a6ed3458f04a1c31588e130a7699dba Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 3 Feb 2020 11:07:26 +0200 Subject: [PATCH 078/176] MC-30281: [2.4] Fix and unskip StorefrontSortingByPriceForConfigurableProductWithCatalogRuleAppliedTest --- ...tSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml index 4e8274203365c..15df342ca47a8 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml @@ -153,7 +153,7 @@ </actionGroup> <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext catalog_category_product catalog_product_price catalogrule_rule" stepKey="reindexIndices"/> - <magentoCLI command="cache:clean" arguments="full_page block_html" stepKey="flushCache"/> + <magentoCLI command="cache:clean" arguments="full_page" stepKey="flushCache"/> <!--Reopen category with products and Sort by price desc--> <actionGroup ref="GoToStorefrontCategoryPageByParametersActionGroup" stepKey="goToStorefrontCategoryPage2"> From c85ff66064bd8aaf9673ffaa7057ee86b32c67b6 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 3 Feb 2020 12:14:44 +0200 Subject: [PATCH 079/176] MC-30164: [FT] [MFTF] [2.4] Fix flaky test AssignProductsToCategoryBySKUsTest (MC-172) --- ...enProductsInCategorySectionActionGroup.xml | 20 ++++++++++++++ .../AdminSaveCategoryFormActionGroup.xml | 21 +++++++++++++++ ...tCategorySimpleProductShownActionGroup.xml | 26 +++++++++++++++++++ .../SaveCategoryFormActionGroup.xml | 6 ++--- .../Section/AdminCategoryProductsSection.xml | 7 +++-- 5 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryPageOpenProductsInCategorySectionActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSaveCategoryFormActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontCategorySimpleProductShownActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryPageOpenProductsInCategorySectionActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryPageOpenProductsInCategorySectionActionGroup.xml new file mode 100644 index 0000000000000..67c68e03fcfa1 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryPageOpenProductsInCategorySectionActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCategoryPageOpenProductsInCategorySectionActionGroup"> + <annotations> + <description>Open 'Products in Category' section on category edit page in Admin.</description> + </annotations> + + <conditionalClick selector="{{AdminCategoryProductsSection.sectionHeader}}" dependentSelector="{{AdminCategoryProductsSection.sectionBody}}" visible="false" stepKey="openSectionIfHidden" /> + <scrollTo selector="{{AdminCategoryProductsSection.sectionHeader}}" stepKey="scrollToSection" /> + <waitForPageLoad stepKey="waitSectionFullyLoaded"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSaveCategoryFormActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSaveCategoryFormActionGroup.xml new file mode 100644 index 0000000000000..564033f459dc9 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSaveCategoryFormActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminSaveCategoryFormActionGroup"> + <annotations> + <description>Save category edit form in Admin and check success message.</description> + </annotations> + + <seeInCurrentUrl url="{{AdminCategoryPage.url}}" stepKey="seeOnCategoryPage"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="saveCategory"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessageAppears"/> + <see userInput="You saved the category." selector="{{AdminMessagesSection.success}}" stepKey="assertSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontCategorySimpleProductShownActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontCategorySimpleProductShownActionGroup.xml new file mode 100644 index 0000000000000..a2940708eeb84 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontCategorySimpleProductShownActionGroup.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Check simple product on the category page --> + <actionGroup name="AssertStorefrontCategorySimpleProductShownActionGroup"> + <annotations> + <description>Validate that the provided Simple Product is present and correct on a Category page.</description> + </annotations> + <arguments> + <argument name="productName" type="string" defaultValue="{{ApiSimpleOne.name}}"/> + <argument name="productPrice" type="string" defaultValue="{{ApiSimpleOne.price}}"/> + </arguments> + + <waitForElementVisible selector="{{StorefrontCategoryProductSection.ProductTitleByName(productName)}}" stepKey="waitForProduct"/> + <seeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName(productName)}}" stepKey="assertProductName"/> + <see userInput="${{productPrice}}" selector="{{StorefrontCategoryProductSection.ProductPriceByName(productName)}}" stepKey="assertProductPrice"/> + <moveMouseOver selector="{{StorefrontCategoryProductSection.ProductInfoByName(productName)}}" stepKey="moveMouseOverProduct"/> + <seeElement selector="{{StorefrontCategoryProductSection.ProductAddToCartByName(productName)}}" stepKey="assertAddToCartButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SaveCategoryFormActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SaveCategoryFormActionGroup.xml index ff6afb4aaf0e9..19f11a2402f56 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SaveCategoryFormActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SaveCategoryFormActionGroup.xml @@ -10,11 +10,11 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="SaveCategoryFormActionGroup"> <annotations> - <description>Requires navigation to the Category creation/edit page. Checks that the url contains the AdminCategoryPage url. Saves the Category.</description> + <description>DEPRECATED. Use AdminSaveCategoryFormActionGroup instead. Requires navigation to the Category creation/edit page. Checks that the url contains the AdminCategoryPage url. Saves the Category.</description> </annotations> <seeInCurrentUrl url="{{AdminCategoryPage.url}}" stepKey="seeOnCategoryPage"/> - <click selector="{{AdminCategoryMainActionsSection.SaveButton}}" stepKey="saveCategory"/> - <seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="assertSuccess"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="saveCategory"/> + <seeElement selector="{{AdminMessagesSection.success}}" stepKey="assertSuccess"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml index 8a993a74a58d1..1627fb9512e64 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml @@ -9,8 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminCategoryProductsSection"> - <element name="sectionHeader" type="button" selector="div[data-index='assign_products']" timeout="30"/> - <element name="addProducts" type="button" selector="#catalog_category_add_product_tabs" timeout="30"/> - <element name="addProductsDisabled" type="button" selector="#catalog_category_add_product_tabs[disabled]" timeout="30"/> + <element name="sectionHeader" type="button" selector="div[data-index='assign_products'] .fieldset-wrapper-title" timeout="30"/> + <element name="sectionBody" type="button" selector="div[data-index='assign_products'] .admin__fieldset-wrapper-content" timeout="30"/> </section> -</sections> \ No newline at end of file +</sections> From da4d7b43f3f18407cfab5134070cc2b302ce6f89 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 3 Feb 2020 12:34:19 +0200 Subject: [PATCH 080/176] MC-29943: [FT] Test StorefrontOrderPagerDisplayedTest fails on Jenkins --- ...ssignProductAttributeToAttributeSetTest.xml | 3 +++ .../Test/AdminChangeProductAttributeSet.xml | 3 +++ ...roductPriceWithDisabledChildProductTest.xml | 3 +++ ...stomAttributeValuesAfterProductSaveTest.xml | 3 +++ .../Test/AdminCreateAttributeSetEntityTest.xml | 3 +++ ...sibleInStorefrontAdvancedSearchFormTest.xml | 3 +++ ...sibleInStorefrontAdvancedSearchFormTest.xml | 3 +++ .../AdminCreateNewGroupForAttributeSetTest.xml | 3 +++ ...dminDeleteConfigurableChildProductsTest.xml | 3 +++ ...ownProductAttributeFromAttributeSetTest.xml | 3 +++ .../Test/AdminDeleteProductAttributeTest.xml | 3 +++ ...eldProductAttributeFromAttributeSetTest.xml | 3 +++ ...AdminNavigateMultipleUpSellProductsTest.xml | 3 +++ ...oductGridFilteringByCustomAttributeTest.xml | 3 +++ ...leForProductOptionsWithoutTierPriceTest.xml | 3 +++ ...ignProductAttributeFromAttributeSetTest.xml | 3 +++ ...eUsedInConfigurableProductAttributeTest.xml | 3 +++ ...nchorIsVisibleOnViewportOnceClickedTest.xml | 3 +++ ...StorefrontProductWithEmptyAttributeTest.xml | 3 +++ ...ntProductsCompareWithEmptyAttributeTest.xml | 3 +++ .../Mftf/Test/AdminExportBundleProductTest.xml | 3 +++ ...ImportConfigurableProductWithImagesTest.xml | 3 +++ ...nfigurableProductsWithCustomOptionsTest.xml | 3 +++ ...figurableProductsWithAssignedImagesTest.xml | 3 +++ ...rableProductAssignedToCustomWebsiteTest.xml | 3 +++ ...atedProductToConfigurableOutOfStockTest.xml | 17 ++++++++++------- ...onfigurableProductWithSpecialPricesTest.xml | 3 +++ .../AdminDeleteCatalogPriceRuleEntityTest.xml | 3 +++ ...yCatalogPriceRuleByProductAttributeTest.xml | 3 +++ ...RuleForSimpleAndConfigurableProductTest.xml | 3 +++ ...eProductWithAssignedSimpleProducts2Test.xml | 3 +++ ...leProductWithAssignedSimpleProductsTest.xml | 3 +++ ...eForConfigurableProductWithOptions2Test.xml | 3 +++ ...leForConfigurableProductWithOptionsTest.xml | 3 +++ .../Test/Mftf/Test/SearchEntityResultsTest.xml | 7 +++++++ ...ConfigurableProductFromShoppingCartTest.xml | 3 +++ .../OnePageCheckoutWithAllProductTypesTest.xml | 3 +++ ...ddConfigurableProductToShoppingCartTest.xml | 3 +++ ...ontCheckoutWithSpecialPriceProductsTest.xml | 3 +++ ...igurableProductFromMiniShoppingCartTest.xml | 3 +++ ...stCheckoutUsingFreeShippingAndTaxesTest.xml | 3 +++ .../AdminAddDefaultImageConfigurableTest.xml | 3 +++ ...ableProductAttributeValueUniquenessTest.xml | 3 +++ ...nCheckResultsOfColorAndOtherFiltersTest.xml | 3 +++ ...inCheckValidatorConfigurableProductTest.xml | 3 +++ .../AdminConfigurableProductDeleteTest.xml | 6 ++++++ .../AdminConfigurableProductLongSkuTest.xml | 3 +++ .../AdminConfigurableProductOutOfStockTest.xml | 9 +++++++++ .../AdminConfigurableProductSearchTest.xml | 6 ++++++ ...nConfigurableProductUpdateAttributeTest.xml | 6 ++++++ .../AdminConfigurableProductUpdateTest.xml | 6 ++++++ ...ProductWithDisabledChildrenProductsTest.xml | 3 +++ ...CreateConfigurableProductWithImagesTest.xml | 3 +++ ...reeProductDisplayOutOfStockProductsTest.xml | 3 +++ ...roductDontDisplayOutOfStockProductsTest.xml | 3 +++ ...rableProductWithTierPriceForOneItemTest.xml | 3 +++ .../AdminProductTypeSwitchingOnEditingTest.xml | 6 ++++++ .../Mftf/Test/AdminRelatedProductsTest.xml | 3 +++ ...AdminRemoveDefaultImageConfigurableTest.xml | 2 ++ .../AdvanceCatalogSearchConfigurableTest.xml | 16 ++++++++++++++++ ...ableProductPriceAdditionalStoreViewTest.xml | 2 ++ .../Mftf/Test/EndToEndB2CGuestUserTest.xml | 6 ++++++ .../Mftf/Test/EndToEndB2CLoggedInUserTest.xml | 3 +++ ...oductsListWidgetConfigurableProductTest.xml | 5 ++++- ...AvailableToConfigureDisabledProductTest.xml | 3 +++ ...ogSearchConfigurableBySkuWithHyphenTest.xml | 4 ++++ ...gurableProductCategoryViewChildOnlyTest.xml | 3 +++ ...frontConfigurableProductChildSearchTest.xml | 3 +++ ...torefrontConfigurableProductDetailsTest.xml | 3 +++ ...rConfigurableWithCatalogRuleAppliedTest.xml | 3 +++ ...onfigurableProductLayeredNavigationTest.xml | 3 +++ .../StorefrontClearAllCompareProductsTest.xml | 6 +++++- ...butesChangedValueToEmptyAfterImportTest.xml | 3 +++ .../CliRunReindexUsingCronJobsActionGroup.xml | 18 ++++++++++++++++++ ...thMapAssignedConfigProductIsCorrectTest.xml | 3 +++ ...refrontGuestCheckoutDisabledProductTest.xml | 3 +++ ...rableProductToOrderFromShoppingCartTest.xml | 3 +++ ...derWithCheckMoneyOrderPaymentMethodTest.xml | 3 +++ ...CreateCreditMemoConfigurableProductTest.xml | 3 +++ ...AdminSubmitConfigurableProductOrderTest.xml | 3 +++ .../CreateOrderFromEditCustomerPageTest.xml | 3 +++ ...urableProductsInComparedOnOrderPageTest.xml | 3 +++ ...deredConfigurableProductOnOrderPageTest.xml | 3 +++ ...iewedConfigurableProductOnOrderPageTest.xml | 3 +++ .../Test/StorefrontPrintOrderGuestTest.xml | 3 +++ ...CartPriceRuleForConfigurableProductTest.xml | 5 ++++- .../Mftf/Test/AdminCreateImageSwatchTest.xml | 3 +++ ...leteConfigurableProductFromWishlistTest.xml | 3 +++ 88 files changed, 330 insertions(+), 10 deletions(-) create mode 100644 app/code/Magento/Indexer/Test/Mftf/ActionGroup/CliRunReindexUsingCronJobsActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml index 41b358bbf760e..bcb8af7209d8f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml @@ -33,6 +33,9 @@ <after> <deleteData createDataKey="attribute" stepKey="deleteAttribute"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to default attribute set edit page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml index 95620bf75b6d0..cdb9a0a8b75d0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml @@ -47,6 +47,9 @@ <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <actionGroup ref="ClearProductsFilterActionGroup" stepKey="clearProductsFilter"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckConfigurableProductPriceWithDisabledChildProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckConfigurableProductPriceWithDisabledChildProductTest.xml index b4381a674827d..6a3ff738f1846 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckConfigurableProductPriceWithDisabledChildProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckConfigurableProductPriceWithDisabledChildProductTest.xml @@ -118,6 +118,9 @@ <deleteData createDataKey="createConfigChildProduct3" stepKey="deleteConfigChildProduct3"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteAttribute"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Open Product in Store Front Page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml index 7c6f6ab66f63d..4aa9474aba6fe 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml @@ -43,6 +43,9 @@ <deleteData createDataKey="createMultiSelectProductAttribute" stepKey="deleteMultiSelectProductAttribute"/> <!-- Logout from Admin page --> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Open created product for edit --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAttributeSetEntityTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAttributeSetEntityTest.xml index 51518dffaf87e..8f06565c147fa 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAttributeSetEntityTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAttributeSetEntityTest.xml @@ -26,6 +26,9 @@ <after> <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="goToAttributeSets"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml index 557f0768c98a3..166af767be142 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml @@ -35,6 +35,9 @@ </before> <after> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Filter product attribute set by attribute set name --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateMultipleSelectProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateMultipleSelectProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml index 6bfd012bc88b2..56a6a869d8d35 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateMultipleSelectProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateMultipleSelectProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml @@ -41,6 +41,9 @@ <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Filter product attribute set by attribute set name --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml index a105f343d3e21..41662e4748193 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml @@ -28,6 +28,9 @@ <after> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Navigate to Stores > Attributes > Attribute Set --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteConfigurableChildProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteConfigurableChildProductsTest.xml index 4a305b8dfec75..04a4eff0a26d4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteConfigurableChildProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteConfigurableChildProductsTest.xml @@ -82,6 +82,9 @@ <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteAttribute"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Open Product in Store Front Page --> <amOnPage url="$$createConfigProduct.sku$$.html" stepKey="openProductInStoreFront"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteDropdownProductAttributeFromAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteDropdownProductAttributeFromAttributeSetTest.xml index 3abe68a503b57..58e60da3bdac5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteDropdownProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteDropdownProductAttributeFromAttributeSetTest.xml @@ -29,6 +29,9 @@ <!--Delete Created Data --> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Open Product Attribute Set Page --> <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="goToAttributeSets"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml index 4060182a9bace..d72806cb0991d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml @@ -23,6 +23,9 @@ </before> <after> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="OpenProductAttributeFromSearchResultInGridActionGroup" stepKey="openProductAttributeFromSearchResultInGrid"> <argument name="productAttributeCode" value="$$createProductAttribute.attribute_code$$"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml index 4f05c364fda0e..e12bac55d8bc8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml @@ -32,6 +32,9 @@ <!--Delete cteated Data --> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimplaeProduct"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Open Product Attribute Set Page --> <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="goToAttributeSets"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminNavigateMultipleUpSellProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminNavigateMultipleUpSellProductsTest.xml index 5dd8b2e430941..7bfe3ae50c58b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminNavigateMultipleUpSellProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminNavigateMultipleUpSellProductsTest.xml @@ -90,6 +90,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deletecreateConfigChildProduct2"/> <deleteData createDataKey="createConfigChildProduct1" stepKey="deletecreateConfigChildProduct1"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Open Product Index Page--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByCustomAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByCustomAttributeTest.xml index 6f65865924bad..a4986117380ff 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByCustomAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByCustomAttributeTest.xml @@ -90,6 +90,9 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="NavigateToAndResetProductGridToDefaultViewAfterTest"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> <waitForPageLoad stepKey="waitForProductGridPageLoad"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml index 4bcb82372e801..7f62dd14a4f32 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml @@ -83,6 +83,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Go to storefront product page an check price box css--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml index 44b4e60973907..c508e3ae94d67 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml @@ -37,6 +37,9 @@ <deleteData createDataKey="attribute" stepKey="deleteAttribute"/> <magentoCLI command="cron:run --group=index" stepKey="runCron"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Assert attribute presence in storefront product additional information --> <amOnPage url="/$$product.custom_attributes[url_key]$$.html" stepKey="onProductPage1"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/DeleteUsedInConfigurableProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/DeleteUsedInConfigurableProductAttributeTest.xml index 0daf8361ef9d1..0d382798a6266 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/DeleteUsedInConfigurableProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/DeleteUsedInConfigurableProductAttributeTest.xml @@ -73,6 +73,9 @@ <!-- Logout --> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to Stores > Attributes > Products. Search and select the product attribute that was used to create the configurable product--> <actionGroup ref="OpenProductAttributeFromSearchResultInGridActionGroup" stepKey="openProductAttributeFromSearchResultInGrid"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontEnsureThatAccordionAnchorIsVisibleOnViewportOnceClickedTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontEnsureThatAccordionAnchorIsVisibleOnViewportOnceClickedTest.xml index 30461a30e53cb..2695c0f07f19e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontEnsureThatAccordionAnchorIsVisibleOnViewportOnceClickedTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontEnsureThatAccordionAnchorIsVisibleOnViewportOnceClickedTest.xml @@ -69,6 +69,9 @@ <deleteData createDataKey="createThirdAttribute" stepKey="deleteThirdAttribute"/> <deleteData createDataKey="createFourthAttribute" stepKey="deleteFourthAttribute"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Edit the product and set those attributes values --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductWithEmptyAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductWithEmptyAttributeTest.xml index db693b7229b17..7ba8f26ba1c05 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductWithEmptyAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductWithEmptyAttributeTest.xml @@ -29,6 +29,9 @@ <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="amOnAttributeSetPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml index d7f98c4cdd307..3aa12a7268593 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml @@ -33,6 +33,9 @@ <deleteData createDataKey="createSimpleProduct1" stepKey="deleteSimpleProduct1"/> <deleteData createDataKey="createSimpleProduct2" stepKey="deleteSimpleProduct2"/> <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="amOnAttributeSetPage"/> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml index 369805a94dd84..7fb4d8b025b07 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml @@ -107,6 +107,9 @@ </actionGroup> <!-- Log out --> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to export page --> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportImportConfigurableProductWithImagesTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportImportConfigurableProductWithImagesTest.xml index 642bbfc0453c5..c27a1716e84e5 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportImportConfigurableProductWithImagesTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportImportConfigurableProductWithImagesTest.xml @@ -153,6 +153,9 @@ <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetProductGridColumnsInitial"/> <!-- Admin logout--> <actionGroup ref="logout" stepKey="adminLogout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to System > Export --> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleAndConfigurableProductsWithCustomOptionsTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleAndConfigurableProductsWithCustomOptionsTest.xml index 397c1ee57e7f5..a55e92d64ce00 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleAndConfigurableProductsWithCustomOptionsTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleAndConfigurableProductsWithCustomOptionsTest.xml @@ -95,6 +95,9 @@ </actionGroup> <!-- Log out --> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to export page --> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml index e00346654ecf4..7131fe41ea5ec 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml @@ -111,6 +111,9 @@ </actionGroup> <!-- Log out --> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to export page --> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAssignedToMainWebsiteAndConfigurableProductAssignedToCustomWebsiteTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAssignedToMainWebsiteAndConfigurableProductAssignedToCustomWebsiteTest.xml index 04be8f3ae823e..ea27d61e3b00c 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAssignedToMainWebsiteAndConfigurableProductAssignedToCustomWebsiteTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAssignedToMainWebsiteAndConfigurableProductAssignedToCustomWebsiteTest.xml @@ -96,6 +96,9 @@ </actionGroup> <!-- Log out --> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to export page --> diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/Test/AssociatedProductToConfigurableOutOfStockTest.xml b/app/code/Magento/CatalogInventory/Test/Mftf/Test/AssociatedProductToConfigurableOutOfStockTest.xml index 8458fcf3b94e0..07354d0b4c89f 100644 --- a/app/code/Magento/CatalogInventory/Test/Mftf/Test/AssociatedProductToConfigurableOutOfStockTest.xml +++ b/app/code/Magento/CatalogInventory/Test/Mftf/Test/AssociatedProductToConfigurableOutOfStockTest.xml @@ -80,13 +80,16 @@ </before> <after> - <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> - <deleteData createDataKey="simplecategory" stepKey="deleteSimpleCategory"/> - <deleteData createDataKey="createSimpleUsCustomer" stepKey="deleteCustomer"/> - <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> - <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> - <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> - </after> + <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="simplecategory" stepKey="deleteSimpleCategory"/> + <deleteData createDataKey="createSimpleUsCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> + <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> + </after> <!-- Login as a customer --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signUpNewUser"> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml index d99ebac94fbec..453c64a32ce32 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml @@ -92,6 +92,9 @@ <deleteData createDataKey="createSecondConfigChildProduct" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Add special prices for products --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml index 02d998870fb65..d5efaec971bba 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml @@ -182,6 +182,9 @@ <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute1" stepKey="deleteConfigProductAttribute1"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Delete the simple product and catalog price rule --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml index 1615985370182..c3cb4d6180f18 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml @@ -105,6 +105,9 @@ <click stepKey="resetFilters" selector="{{AdminSecondaryGridSection.resetFilters}}"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Add values to your attribute ( ex: red , green) --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml index 1950f060790d7..9477f5cbed87e 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml @@ -99,6 +99,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Begin creating a new catalog price rule --> <actionGroup ref="NewCatalogPriceRuleByUIWithConditionIsCategoryActionGroup" stepKey="newCatalogPriceRuleByUIWithConditionIsCategory"> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts2Test.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts2Test.xml index 8b72b7616b6ff..80ff2a447052c 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts2Test.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts2Test.xml @@ -172,6 +172,9 @@ <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> <!-- Admin log out --> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create catalog price rule --> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml index c110daee35428..ea0d8e01d540f 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml @@ -176,6 +176,9 @@ <!-- Admin log out --> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create price rule --> <actionGroup ref="NewCatalogPriceRuleByUIActionGroup" stepKey="createPriceRule"> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptions2Test.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptions2Test.xml index bc6c89f2f1155..2a5786b38107f 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptions2Test.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptions2Test.xml @@ -106,6 +106,9 @@ <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create price rule for first configurable product option --> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml index 05f30fd6fcbde..c077719dfa80b 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml @@ -123,6 +123,9 @@ <!-- Log out --> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create price rule for first configurable product option --> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml index cc6f202272e3b..59ca14680fb13 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml @@ -676,6 +676,13 @@ <magentoCLI command="indexer:reindex" stepKey="reindex"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> + <after> + <deleteData createDataKey="attributeSet" stepKey="deleteAttributeSet"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> + </after> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToFrontPage"/> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> <argument name="phrase" value="$createConfigProduct.name$"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/DeleteConfigurableProductFromShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/DeleteConfigurableProductFromShoppingCartTest.xml index 891f647e3d5ef..9d092b4b84a3c 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/DeleteConfigurableProductFromShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/DeleteConfigurableProductFromShoppingCartTest.xml @@ -60,6 +60,9 @@ <!-- Delete category --> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Add configurable product to the cart --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml index 797172de5de45..4a4428712ac9d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml @@ -111,6 +111,9 @@ <!-- Logout customer --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogoutStorefront"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Add Simple Product to cart --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml index e716ba294f578..7d91b13b7b833 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml @@ -120,6 +120,9 @@ <deleteData createDataKey="createConfigProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Add Configurable Product to the cart --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml index a9db81620d329..3f286df8337de 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml @@ -102,6 +102,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Open Product page in StoreFront and assert product and price range --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromMiniShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromMiniShoppingCartTest.xml index 34264e5982651..d302289b27f19 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromMiniShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromMiniShoppingCartTest.xml @@ -72,6 +72,9 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Add Configurable Product to the cart --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml index b800ef758d65e..e544cbb497f2d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml @@ -109,6 +109,9 @@ <createData entity="DefaultShippingMethodsConfig" stepKey="defaultShippingMethodsConfig"/> <createData entity="DefaultMinimumOrderAmount" stepKey="defaultMinimumOrderAmount"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create a Tax Rule --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddDefaultImageConfigurableTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddDefaultImageConfigurableTest.xml index 2f9347157ef33..a10545ba415fe 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddDefaultImageConfigurableTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddDefaultImageConfigurableTest.xml @@ -89,6 +89,9 @@ <deleteData createDataKey="baseConfigProductHandle" stepKey="deleteConfig"/> <deleteData createDataKey="categoryHandle" stepKey="deleteCategory"/> <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="productIndexPage"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml index 98cb03916bdab..4288684e53d27 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml @@ -34,6 +34,9 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProductAttribute" stepKey="deleteAttribute"/> <actionGroup ref="logout" stepKey="logOut"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create configurable product--> <comment userInput="Create configurable product" stepKey="createConfProd"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckResultsOfColorAndOtherFiltersTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckResultsOfColorAndOtherFiltersTest.xml index fabd4a2c253b6..0b3d013660b6e 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckResultsOfColorAndOtherFiltersTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckResultsOfColorAndOtherFiltersTest.xml @@ -110,6 +110,9 @@ <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductsGridFilter"/> <!-- Log out --> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create three configurable products with options --> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckValidatorConfigurableProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckValidatorConfigurableProductTest.xml index 5bdccf15b19d3..92a6dcad27b30 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckValidatorConfigurableProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckValidatorConfigurableProductTest.xml @@ -44,6 +44,9 @@ <argument name="ProductAttribute" value="productDropDownAttribute"/> </actionGroup> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Find the product that we just created using the product grid --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductDeleteTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductDeleteTest.xml index 83e428b454c46..68afa17c4d539 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductDeleteTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductDeleteTest.xml @@ -70,6 +70,9 @@ <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- assert product visible in storefront --> @@ -225,6 +228,9 @@ <deleteData createDataKey="createConfigChildProduct6" stepKey="deleteConfigChildProduct6"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Search for prefix of the 3 products we created via api --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductLongSkuTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductLongSkuTest.xml index baea299581052..fc1f6dad36345 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductLongSkuTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductLongSkuTest.xml @@ -53,6 +53,9 @@ <!--Clean up category--> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="logout" stepKey="adminLogout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create a configurable product with long name and sku--> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductOutOfStockTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductOutOfStockTest.xml index 6bba4aa6b43ce..48a33bfd14d9c 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductOutOfStockTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductOutOfStockTest.xml @@ -83,6 +83,9 @@ <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Check to make sure that the configurable product shows up as in stock --> @@ -204,6 +207,9 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Check to make sure that the configurable product shows up as in stock --> @@ -306,6 +312,9 @@ <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Check to make sure that the configurable product shows up as in stock --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductSearchTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductSearchTest.xml index 889ca5b24b242..a73a7082502d8 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductSearchTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductSearchTest.xml @@ -73,6 +73,9 @@ <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="goToProductList"/> @@ -152,6 +155,9 @@ <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="goToProductList"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateAttributeTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateAttributeTest.xml index c437b39a405cd..e95a73dcebba0 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateAttributeTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateAttributeTest.xml @@ -105,6 +105,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createModifiableProductAttribute" stepKey="deleteModifiableProductAttribute"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Get the current option of the attribute before it was changed --> @@ -221,6 +224,9 @@ <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Find the product that we just created using the product grid --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateTest.xml index da0c5a65f944d..1eb1d8df6030c 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateTest.xml @@ -145,6 +145,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--check storefront for both options--> @@ -238,6 +241,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--check storefront for both options--> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithDisabledChildrenProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithDisabledChildrenProductsTest.xml index f64ba4a63cec9..d3db180cb7999 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithDisabledChildrenProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithDisabledChildrenProductsTest.xml @@ -54,6 +54,9 @@ <!-- Log out --> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithImagesTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithImagesTest.xml index b448131e75f15..37d5d515bb9e0 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithImagesTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithImagesTest.xml @@ -57,6 +57,9 @@ <!-- Log out --> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDisplayOutOfStockProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDisplayOutOfStockProductsTest.xml index 1c6908818b4da..299fbca412fac 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDisplayOutOfStockProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDisplayOutOfStockProductsTest.xml @@ -77,6 +77,9 @@ <!-- Log out --> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDontDisplayOutOfStockProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDontDisplayOutOfStockProductsTest.xml index 1b7fc2c153208..0aa0f22d6af2e 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDontDisplayOutOfStockProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDontDisplayOutOfStockProductsTest.xml @@ -76,6 +76,9 @@ <!-- Log out --> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTierPriceForOneItemTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTierPriceForOneItemTest.xml index e67788d5e7bb0..a2cd949a77d13 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTierPriceForOneItemTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTierPriceForOneItemTest.xml @@ -65,6 +65,9 @@ <!-- Log out --> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml index f1535d62861ac..f441579a6ef42 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml @@ -44,6 +44,9 @@ </actionGroup> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductFilters"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Add configurations to product--> <comment userInput="Add configurations to product" stepKey="commentAddConfigs"/> @@ -148,6 +151,9 @@ </actionGroup> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductFilters"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Add configurations to product--> <comment userInput="Add configurations to product" stepKey="commentAddConfigurations"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRelatedProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRelatedProductsTest.xml index 710430cf123dc..d764876d3b5cc 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRelatedProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRelatedProductsTest.xml @@ -89,6 +89,9 @@ <deleteData createDataKey="baseConfigProductHandle" stepKey="deleteConfig"/> <deleteData createDataKey="categoryHandle" stepKey="deleteCategory"/> <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <comment userInput="Filter and edit simple product 1" stepKey="filterAndEditComment1"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRemoveDefaultImageConfigurableTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRemoveDefaultImageConfigurableTest.xml index 0cc73f117aaad..e0c4fda005666 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRemoveDefaultImageConfigurableTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRemoveDefaultImageConfigurableTest.xml @@ -89,6 +89,8 @@ <deleteData createDataKey="baseConfigProductHandle" stepKey="deleteConfig"/> <deleteData createDataKey="categoryHandle" stepKey="deleteCategory"/> <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductAttribute"/> + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="productIndexPage"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdvanceCatalogSearchConfigurableTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdvanceCatalogSearchConfigurableTest.xml index 0370280309272..05a9222eacaf9 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdvanceCatalogSearchConfigurableTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdvanceCatalogSearchConfigurableTest.xml @@ -82,6 +82,10 @@ <deleteData createDataKey="simple2Handle" stepKey="deleteSimple2" before="delete"/> <deleteData createDataKey="childProductHandle1" stepKey="deleteChildProduct1" before="delete"/> <deleteData createDataKey="childProductHandle2" stepKey="deleteChildProduct2" before="delete"/> + <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductDropDownAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> </test> <test name="AdvanceCatalogSearchConfigurableBySkuTest" extends="AdvanceCatalogSearchSimpleProductBySkuTest"> @@ -158,6 +162,10 @@ <deleteData createDataKey="simple2Handle" stepKey="deleteSimple2" before="delete"/> <deleteData createDataKey="childProductHandle1" stepKey="deleteChildProduct1" before="delete"/> <deleteData createDataKey="childProductHandle2" stepKey="deleteChildProduct2" before="delete"/> + <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductDropDownAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> </test> <test name="AdvanceCatalogSearchConfigurableByDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByDescriptionTest"> @@ -234,6 +242,10 @@ <deleteData createDataKey="simple2Handle" stepKey="deleteSimple2" before="delete"/> <deleteData createDataKey="childProductHandle1" stepKey="deleteChildProduct1" before="delete"/> <deleteData createDataKey="childProductHandle2" stepKey="deleteChildProduct2" before="delete"/> + <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductDropDownAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> </test> <test name="AdvanceCatalogSearchConfigurableByShortDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByShortDescriptionTest"> @@ -310,6 +322,10 @@ <deleteData createDataKey="simple2Handle" stepKey="deleteSimple2" before="delete"/> <deleteData createDataKey="childProductHandle1" stepKey="deleteChildProduct1" before="delete"/> <deleteData createDataKey="childProductHandle2" stepKey="deleteChildProduct2" before="delete"/> + <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductDropDownAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> </test> </tests> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml index 124f0eea2e77a..7bb8661627b8c 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml @@ -78,6 +78,8 @@ <argument name="websiteName" value="Second Website"/> </actionGroup> <actionGroup ref="logout" stepKey="adminLogout"/> + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="EnableWebUrlOptionsActionGroup" stepKey="addStoreCodeToUrls"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CGuestUserTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CGuestUserTest.xml index 59bb7f53f0aa8..a4904c67e0ef8 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CGuestUserTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CGuestUserTest.xml @@ -73,6 +73,9 @@ <!--<deleteData createDataKey="createConfigProductImage" stepKey="deleteConfigProductImage"/>--> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Verify Configurable Product in checkout cart items --> @@ -282,6 +285,9 @@ <!--<deleteData createDataKey="createConfigProductImage" stepKey="deleteConfigProductImage"/>--> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Verify Configurable Product in checkout cart items --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml index dd0673563838e..3d797e62c806a 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml @@ -73,6 +73,9 @@ <!--<deleteData createDataKey="createConfigProductImage" stepKey="deleteConfigProductImage"/>--> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Verify Configurable Product in checkout cart items --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NewProductsListWidgetConfigurableProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NewProductsListWidgetConfigurableProductTest.xml index eadc7dadaf708..5caba34def165 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NewProductsListWidgetConfigurableProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NewProductsListWidgetConfigurableProductTest.xml @@ -70,6 +70,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- A Cms page containing the New Products Widget gets created here via extends --> @@ -88,4 +91,4 @@ <waitForPageLoad stepKey="waitForCmsPage"/> <see selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" userInput="$$createConfigProduct.name$$" stepKey="seeProductName"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml index 5224cc6a9cced..0e46027a69378 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml @@ -103,6 +103,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCustomer" stepKey="deleteCreatedCustomer"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Disable child product --> <comment userInput="Disable child product" stepKey="disableChildProduct"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontAdvanceCatalogSearchConfigurableBySkuWithHyphenTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontAdvanceCatalogSearchConfigurableBySkuWithHyphenTest.xml index a8e982475253f..020e5dbbdfc77 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontAdvanceCatalogSearchConfigurableBySkuWithHyphenTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontAdvanceCatalogSearchConfigurableBySkuWithHyphenTest.xml @@ -83,6 +83,10 @@ <deleteData createDataKey="simple2Handle" stepKey="deleteSimple2" before="delete"/> <deleteData createDataKey="childProductHandle1" stepKey="deleteChildProduct1" before="delete"/> <deleteData createDataKey="childProductHandle2" stepKey="deleteChildProduct2" before="delete"/> + <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductDropDownAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> </test> </tests> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml index 9d7807c543def..1d699e01db9d0 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml @@ -95,6 +95,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> <deleteData createDataKey="secondCategory" stepKey="deleteSecondCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="login"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductChildSearchTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductChildSearchTest.xml index 294ab9fd0664d..a0f3689b9c170 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductChildSearchTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductChildSearchTest.xml @@ -140,6 +140,9 @@ <deleteData createDataKey="createConfigProductAttributeMultiSelect" stepKey="deleteConfigProductAttributeMultiSelect"/> <deleteData createDataKey="createConfigProductAttributeSelect" stepKey="deleteConfigProductAttributeSelect"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Quick search the storefront for the first attribute option --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductDetailsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductDetailsTest.xml index 42b9dfc92760a..5d5481938f404 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductDetailsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductDetailsTest.xml @@ -220,6 +220,9 @@ <deleteData createDataKey="createSecondAttribute" stepKey="deleteSecondAttribute"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> <actionGroup ref="logout" stepKey="adminLogout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openProductIndexPage"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml index 7828478bc963e..cf7adafa82020 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml @@ -117,6 +117,9 @@ <argument name="option" value="No"/> </actionGroup> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Open category with products and Sort by price desc--> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVerifyConfigurableProductLayeredNavigationTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVerifyConfigurableProductLayeredNavigationTest.xml index 3ebd9d6ef5367..adaa302a23a52 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVerifyConfigurableProductLayeredNavigationTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVerifyConfigurableProductLayeredNavigationTest.xml @@ -117,6 +117,9 @@ <deleteData createDataKey="createConfigChildProduct3" stepKey="deleteConfigChildProduct3"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteAttribute"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Open Product Index Page and Filter First Child product --> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml index 40b05153f1a74..8651c9b4db62e 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml @@ -18,7 +18,7 @@ <group value="catalog"/> <group value="mtf_migrated"/> </annotations> - + <before> <magentoCLI stepKey="addDownloadableDomain" command="downloadable:domains:add static.magento.com"/> <!-- Create Simple Customer --> @@ -124,6 +124,10 @@ <deleteData createDataKey="createBundleProduct1" stepKey="deleteBundleProduct1"/> <deleteData createDataKey="createGroupedProduct1" stepKey="deleteGroupedProduct1"/> <deleteData createDataKey="createDownloadableProduct1" stepKey="deleteDownloadableProduct1"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer1"> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckThatSomeAttributesChangedValueToEmptyAfterImportTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckThatSomeAttributesChangedValueToEmptyAfterImportTest.xml index 6a2f6ca60acf4..f5e8c91c31950 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckThatSomeAttributesChangedValueToEmptyAfterImportTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckThatSomeAttributesChangedValueToEmptyAfterImportTest.xml @@ -42,6 +42,9 @@ <!--Delete attribute--> <deleteData createDataKey="productAttribute" stepKey="deleteProductAttribute"/> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create product--> <actionGroup ref="GoToSpecifiedCreateProductPageActionGroup" stepKey="openProductFillForm"/> diff --git a/app/code/Magento/Indexer/Test/Mftf/ActionGroup/CliRunReindexUsingCronJobsActionGroup.xml b/app/code/Magento/Indexer/Test/Mftf/ActionGroup/CliRunReindexUsingCronJobsActionGroup.xml new file mode 100644 index 0000000000000..9dc7547db40d6 --- /dev/null +++ b/app/code/Magento/Indexer/Test/Mftf/ActionGroup/CliRunReindexUsingCronJobsActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="CliRunReindexUsingCronJobsActionGroup"> + <annotations> + <description>Run cron 'index' group which reindex all invalidated indices.</description> + </annotations> + + <magentoCLI command="cron:run" arguments="--group='index'" stepKey="firstRunToScheduleJobs"/> + <magentoCLI command="cron:run" arguments="--group='index'" stepKey="secondRunToExecuteJobs"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml index ccb724e8bf199..29f14185a0518 100644 --- a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml +++ b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml @@ -105,6 +105,9 @@ <createData entity="MsrpDisableMAP" stepKey="disableMAP"/> <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Set Manufacturer's Suggested Retail Price to products--> diff --git a/app/code/Magento/Quote/Test/Mftf/Test/StorefrontGuestCheckoutDisabledProductTest.xml b/app/code/Magento/Quote/Test/Mftf/Test/StorefrontGuestCheckoutDisabledProductTest.xml index 6e31214b0dddf..020b495dc42a2 100644 --- a/app/code/Magento/Quote/Test/Mftf/Test/StorefrontGuestCheckoutDisabledProductTest.xml +++ b/app/code/Magento/Quote/Test/Mftf/Test/StorefrontGuestCheckoutDisabledProductTest.xml @@ -87,6 +87,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductListing"/> <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetGridToDefaultKeywordSearch"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Step 1: Add simple product to shopping cart --> <amOnPage url="{{StorefrontProductPage.url($$createSimpleProduct.name$$)}}" stepKey="amOnSimpleProductPage"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml index 6d9f35efc7903..df3a1a2b91219 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml @@ -72,6 +72,9 @@ <!-- Delete category --> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Login as customer --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml index b303364bbf324..5883d044e95a0 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml @@ -108,6 +108,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create new customer order --> <comment userInput="Create new customer order" stepKey="createNewCustomerOrderComment"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoConfigurableProductTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoConfigurableProductTest.xml index 2a841b04bd647..766839a50a862 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoConfigurableProductTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoConfigurableProductTest.xml @@ -98,6 +98,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create Order --> <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="navigateToNewOrderPage"> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitConfigurableProductOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitConfigurableProductOrderTest.xml index 65bba7512e228..dc269ff7a2f98 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitConfigurableProductOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitConfigurableProductOrderTest.xml @@ -131,6 +131,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> </test> </tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml index 0fcfa483f1adf..5d017cc0caab8 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml @@ -90,6 +90,9 @@ <amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomerIndexPage"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearCustomerGridFilter"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Filter and Open the customer edit page --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml index 980d5cc82b93d..27b0952781250 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml @@ -101,6 +101,9 @@ <!-- Delete category --> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Login as customer --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml index b3c3f045f0d59..65c631b95f5c2 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml @@ -66,6 +66,9 @@ <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedConfigurableProductOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedConfigurableProductOnOrderPageTest.xml index aed7447050e5f..c7c08914fea4b 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedConfigurableProductOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedConfigurableProductOnOrderPageTest.xml @@ -80,6 +80,9 @@ <!-- Change configuration --> <magentoCLI command="config:set reports/options/enabled 0" stepKey="disableReportModule"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Login as customer --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml index 31f3449866984..4369fa8a94101 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml @@ -226,6 +226,9 @@ <deleteData createDataKey="createCartPriceRule" stepKey="deleteCartPriceRule"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="AdminSubmitOrderActionGroup" stepKey="submitOrder"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml index ec9246f7c33bd..6db1c4f96796f 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml @@ -86,7 +86,10 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create the rule --> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml index 8a2683af83dc1..9666fd4211491 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml @@ -25,6 +25,9 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Begin creating a new product attribute of type "Image Swatch" --> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromWishlistTest.xml index 6a718ebdfcf0f..bb0a3c40c21f1 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromWishlistTest.xml @@ -118,6 +118,9 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- 1. Login as a customer --> From 873bdcab4150035ed3cd76d656881b13a60f7aa8 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Mon, 3 Feb 2020 12:47:27 +0200 Subject: [PATCH 081/176] MC-30789: GTM is not trigged without Page Reload --- app/code/Magento/Cookie/view/frontend/web/js/notices.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Cookie/view/frontend/web/js/notices.js b/app/code/Magento/Cookie/view/frontend/web/js/notices.js index 2c4a070130804..9c51a49187c32 100644 --- a/app/code/Magento/Cookie/view/frontend/web/js/notices.js +++ b/app/code/Magento/Cookie/view/frontend/web/js/notices.js @@ -30,6 +30,7 @@ define([ if ($.mage.cookies.get(this.options.cookieName)) { this.element.hide(); + $(document).trigger('ga:init'); } else { window.location.href = this.options.noCookiesUrl; } From 7e54c0b5b845a10f550b3fed58c66c2b49968786 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 3 Feb 2020 15:32:41 +0200 Subject: [PATCH 082/176] MC-30720: [MFTF] [2.4] Fix flaky test AdminMoveAnchoredCategoryTest (MAGETWO-76273) --- .../Test/AdminMoveAnchoredCategoryTest.xml | 91 ++++++++++--------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml index f178d55b97fca..55c20cac593ef 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml @@ -16,9 +16,6 @@ <severity value="CRITICAL"/> <testCaseId value="MAGETWO-76273"/> <group value="category"/> - <skip> - <issueId value="MC-30720"/> - </skip> </annotations> <before> <createData entity="SimpleSubCategory" stepKey="simpleSubCategoryOne"/> @@ -32,95 +29,101 @@ <createData entity="_defaultProduct" stepKey="productTwo"> <requiredEntity createDataKey="simpleSubCategoryOne"/> </createData> - <magentoCLI command="cron:run --group=index" stepKey="runIndexerCron"/> + + <!-- TODO: Replace this with CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> + <magentoCLI command="cron:run" arguments="--group='index'" stepKey="firstRunToScheduleJobs"/> + <magentoCLI command="cron:run" arguments="--group='index'" stepKey="secondRunToExecuteJobs"/> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> + <after> - <actionGroup ref="logout" stepKey="logoutAdminUserAfterTest"/> <deleteData createDataKey="productOne" stepKey="deleteProductOne"/> <deleteData createDataKey="productTwo" stepKey="deleteProductTwo"/> <deleteData createDataKey="simpleSubCategoryWithParent" stepKey="deleteSubcategoryWithParent"/> <deleteData createDataKey="simpleSubCategoryTwo" stepKey="deleteSubcategoryTwo"/> + <actionGroup ref="logout" stepKey="logoutAdminUserAfterTest"/> </after> + <!--Move category one to category two--> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="navigateToAdminCategoryPage"/> <waitForPageLoad stepKey="waitForAdminCategoryPageLoad1"/> <actionGroup ref="MoveCategoryActionGroup" stepKey="moveSimpleSubCategoryOneToSimpleSubCategoryTwo"> - <argument name="childCategory" value="$$simpleSubCategoryOne.name$$"/> - <argument name="parentCategory" value="$$simpleSubCategoryTwo.name$$"/> + <argument name="childCategory" value="$simpleSubCategoryOne.name$"/> + <argument name="parentCategory" value="$simpleSubCategoryTwo.name$"/> </actionGroup> <!--Verify that navigation menu categories level is correct--> - <amOnPage url="/" stepKey="amOnStorefrontPage1"/> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="openHomePageFirst"/> <waitForPageLoad stepKey="waitForPageToLoadAfterHomePageOpened1"/> - <seeElement selector="{{StorefrontNavigationSection.topCategory($$simpleSubCategoryTwo.name$$)}}" stepKey="verifyThatTopCategoryIsSubCategoryTwo"/> - <moveMouseOver selector="{{StorefrontNavigationSection.topCategory($$simpleSubCategoryTwo.name$$)}}" stepKey="mouseOverSubCategoryTwo"/> + <seeElement selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryTwo.name$)}}" stepKey="verifyThatTopCategoryIsSubCategoryTwo"/> + <moveMouseOver selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryTwo.name$)}}" stepKey="mouseOverSubCategoryTwo"/> <waitForAjaxLoad stepKey="waitForAjaxOnMouseOverSubCategoryTwo"/> - <seeElement selector="{{StorefrontNavigationSection.subCategory($$simpleSubCategoryOne.name$$)}}" stepKey="verifyThatFirstLevelIsSubCategoryOne"/> - <moveMouseOver selector="{{StorefrontNavigationSection.subCategory($$simpleSubCategoryOne.name$$)}}" stepKey="mouseOverSubCategoryOne"/> + <seeElement selector="{{StorefrontNavigationSection.subCategory($simpleSubCategoryOne.name$)}}" stepKey="verifyThatFirstLevelIsSubCategoryOne"/> + <moveMouseOver selector="{{StorefrontNavigationSection.subCategory($simpleSubCategoryOne.name$)}}" stepKey="mouseOverSubCategoryOne"/> <waitForAjaxLoad stepKey="waitForAjaxOnMouseOverSubCategoryOne"/> - <seeElement selector="{{StorefrontNavigationSection.subCategory($$simpleSubCategoryWithParent.name$$)}}" stepKey="verifyThatSecondLevelIsSubCategoryWithParent1"/> + <seeElement selector="{{StorefrontNavigationSection.subCategory($simpleSubCategoryWithParent.name$)}}" stepKey="verifyThatSecondLevelIsSubCategoryWithParent1"/> <!--Open category one via navigation menu. Verify that subcategory is shown in layered navigation--> - <click selector="{{StorefrontNavigationSection.subCategory($$simpleSubCategoryOne.name$$)}}" stepKey="openSimpleSubCategoryOneByNavigationMenu1"/> + <click selector="{{StorefrontNavigationSection.subCategory($simpleSubCategoryOne.name$)}}" stepKey="openSimpleSubCategoryOneByNavigationMenu1"/> <actionGroup ref="CheckItemInLayeredNavigationActionGroup" stepKey="verifySimpleSubCategoryWithParentInLayeredNavigation1"> <argument name="itemType" value="Category"/> - <argument name="itemName" value="$$simpleSubCategoryWithParent.name$$"/> + <argument name="itemName" value="$simpleSubCategoryWithParent.name$"/> </actionGroup> <!--Open category one by direct URL. Verify simple product is visible on it. Open this product and perform assertions--> <actionGroup ref="OpenProductFromCategoryPageActionGroup" stepKey="openFirstProductFromSubCategoryOneCategoryPage1"> - <argument name="category" value="$$simpleSubCategoryOne$$"/> - <argument name="product" value="$$productOne$$"/> + <argument name="category" value="$simpleSubCategoryOne$"/> + <argument name="product" value="$productOne$"/> </actionGroup> <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="Home" stepKey="seeHomePageInBreadcrumbs1"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryTwo.name$$" stepKey="seeSubCategoryTwoInBreadcrumbsOnSubCategoryOne"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryOne.name$$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryOne1"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$productOne.name$$" stepKey="seeProductInBreadcrumbsOnSubCategoryOne1"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryTwo.name$" stepKey="seeSubCategoryTwoInBreadcrumbsOnSubCategoryOne"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryOne.name$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryOne1"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$productOne.name$" stepKey="seeProductInBreadcrumbsOnSubCategoryOne1"/> <!--Open category two by direct URL. Verify simple product is visible on it. Open this product and perform assertions--> <actionGroup ref="OpenProductFromCategoryPageActionGroup" stepKey="openFirstProductFromSubCategoryWithParentCategoryPage"> - <argument name="category" value="$$simpleSubCategoryWithParent$$"/> - <argument name="product" value="$$productOne$$"/> + <argument name="category" value="$simpleSubCategoryWithParent$"/> + <argument name="product" value="$productOne$"/> </actionGroup> <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="Home" stepKey="seeHomePageInBreadcrumbsOnSubCategoryWithParent"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryTwo.name$$" stepKey="seeSubCategoryTwoInBreadcrumbsOnSubCategoryWithParent"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryOne.name$$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryWithParent"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryOne.name$$" stepKey="seeSubCategoryWithParentInBreadcrumbsOnSubCategoryWithParent"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$productOne.name$$" stepKey="seeProductInBreadcrumbsOnSubCategoryWithParent"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryTwo.name$" stepKey="seeSubCategoryTwoInBreadcrumbsOnSubCategoryWithParent"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryOne.name$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryWithParent"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryOne.name$" stepKey="seeSubCategoryWithParentInBreadcrumbsOnSubCategoryWithParent"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$productOne.name$" stepKey="seeProductInBreadcrumbsOnSubCategoryWithParent"/> <!--Move category one to the same level as category two--> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="navigateToAdminCategoryPage2"/> <waitForPageLoad stepKey="waitForAdminCategoryPageLoad2"/> <actionGroup ref="MoveCategoryActionGroup" stepKey="moveSimpleSubCategoryOneToDefaultCategory"> - <argument name="childCategory" value="$$simpleSubCategoryOne.name$$"/> + <argument name="childCategory" value="$simpleSubCategoryOne.name$"/> <argument name="parentCategory" value="Default Category"/> </actionGroup> <!--Verify that navigation menu categories level is correct--> - <amOnPage url="/" stepKey="amOnStorefrontPage2"/> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="openHomePageSecond"/> <waitForPageLoad stepKey="waitForPageToLoadAfterHomePageOpened2"/> - <seeElement selector="{{StorefrontNavigationSection.topCategory($$simpleSubCategoryOne.name$$)}}" stepKey="verifyThatSubCategoryOneIsTopCategory"/> - <seeElement selector="{{StorefrontNavigationSection.topCategory($$simpleSubCategoryTwo.name$$)}}" stepKey="verifyThatSubCategoryTwoIsTopCategory"/> - <moveMouseOver selector="{{StorefrontNavigationSection.topCategory($$simpleSubCategoryOne.name$$)}}" stepKey="mouseOverTopSubCategoryOne"/> + <seeElement selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryOne.name$)}}" stepKey="verifyThatSubCategoryOneIsTopCategory"/> + <seeElement selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryTwo.name$)}}" stepKey="verifyThatSubCategoryTwoIsTopCategory"/> + <moveMouseOver selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryOne.name$)}}" stepKey="mouseOverTopSubCategoryOne"/> <waitForAjaxLoad stepKey="waitForAjaxOnMouseOverTopSubCategoryOne"/> - <seeElement selector="{{StorefrontNavigationSection.subCategory($$simpleSubCategoryWithParent.name$$)}}" stepKey="verifyThatSecondLevelIsSubCategoryWithParent2"/> + <seeElement selector="{{StorefrontNavigationSection.subCategory($simpleSubCategoryWithParent.name$)}}" stepKey="verifyThatSecondLevelIsSubCategoryWithParent2"/> <!--Open category one via navigation menu. Verify that subcategory is shown in layered navigation--> - <click selector="{{StorefrontNavigationSection.topCategory($$simpleSubCategoryOne.name$$)}}" stepKey="openSimpleSubCategoryOneByNavigationMenu2"/> + <click selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryOne.name$)}}" stepKey="openSimpleSubCategoryOneByNavigationMenu2"/> <actionGroup ref="CheckItemInLayeredNavigationActionGroup" stepKey="verifySimpleSubCategoryWithParentInLayeredNavigation2"> <argument name="itemType" value="Category"/> - <argument name="itemName" value="$$simpleSubCategoryWithParent.name$$"/> + <argument name="itemName" value="$simpleSubCategoryWithParent.name$"/> </actionGroup> <!--Open category one by direct URL. Verify simple product is visible on it. Open this product and perform assertions--> <actionGroup ref="OpenProductFromCategoryPageActionGroup" stepKey="openFirstProductFromSubCategoryOneCategoryPage2"> - <argument name="category" value="$$simpleSubCategoryOne$$"/> - <argument name="product" value="$$productOne$$"/> + <argument name="category" value="$simpleSubCategoryOne$"/> + <argument name="product" value="$productOne$"/> </actionGroup> <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="Home" stepKey="seeHomePageInBreadcrumbs2"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryOne.name$$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryOne2"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$productOne.name$$" stepKey="seeProductInBreadcrumbsOnSubCategoryOne2"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryOne.name$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryOne2"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$productOne.name$" stepKey="seeProductInBreadcrumbsOnSubCategoryOne2"/> <!--Open category subcategory by direct URL. Verify simple product is visible on it. Open this product and perform assertions--> <actionGroup ref="OpenProductFromCategoryPageActionGroup" stepKey="openFirstProductFromSubCategoryOneCategoryPage3"> - <argument name="category" value="$$simpleSubCategoryWithParent$$"/> - <argument name="product" value="$$productOne$$"/> + <argument name="category" value="$simpleSubCategoryWithParent$"/> + <argument name="product" value="$productOne$"/> </actionGroup> <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="Home" stepKey="seeHomePageInBreadcrumbs3"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryOne.name$$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryOne3"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryOne.name$$" stepKey="seeSubCategoryWithParentInBreadcrumbsOnSubCategoryWithParent3"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$productOne.name$$" stepKey="seeProductInBreadcrumbsOnSubCategoryOne3"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryOne.name$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryOne3"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryOne.name$" stepKey="seeSubCategoryWithParentInBreadcrumbsOnSubCategoryWithParent3"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$productOne.name$" stepKey="seeProductInBreadcrumbsOnSubCategoryOne3"/> </test> </tests> From 46c9d2371c96b3c0e7dc94b961fe48f4c8362982 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 3 Feb 2020 16:40:14 +0200 Subject: [PATCH 083/176] MC-30166: [FT] [MFTF] [2.4] Fix flaky test UpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest (MC-6504) --- ...AdvancedPricingAddTierPriceActionGroup.xml | 34 ++++ ...mCloseAdvancedPricingDialogActionGroup.xml | 19 ++ ...rmDoneAdvancedPricingDialogActionGroup.xml | 19 ++ ...rmOpenAdvancedPricingDialogActionGroup.xml | 20 ++ ...vancedPricingCheckTierPriceActionGroup.xml | 32 ++++ .../ProductSetAdvancedPricingActionGroup.xml | 2 +- .../SetProductUrlKeyByStringActionGroup.xml | 2 +- ...AdminProductFormAdvancedPricingSection.xml | 8 + ...eInStockVisibleInCategoryAndSearchTest.xml | 176 ++++++++---------- 9 files changed, 207 insertions(+), 105 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml new file mode 100644 index 0000000000000..f823db0a86548 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminProductFormAdvancedPricingAddTierPriceActionGroup"> + <annotations> + <description>Add new tier price on Advanced Pricing dialog on the Admin Product creation/edit page.</description> + </annotations> + <arguments> + <argument name="website" type="string" defaultValue="All Websites [USD]"/> + <argument name="customerGroup" type="string" defaultValue="ALL GROUPS"/> + <argument name="quantity" type="string" defaultValue="1"/> + <argument name="priceType" type="string" defaultValue="Fixed"/> + <argument name="amount" type="string" defaultValue="10"/> + </arguments> + + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="waitForGroupPriceAddButtonAppears"/> + <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="clickCustomerGroupPriceAddButton"/> + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceWebsite}}" stepKey="waitForPriceWebsiteInputAppears"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceWebsite}}" userInput="{{website}}" stepKey="selectWebsite"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceCustomerGroup}}" userInput="{{customerGroup}}" stepKey="selectCustomerGroup"/> + <fillField selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceQty}}" userInput="{{quantity}}" stepKey="fillQuantity"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceType}}" userInput="{{priceType}}" stepKey="selectPriceType"/> + <executeJS function="return '{{priceType}}' == 'Discount' ? "{{AdminProductFormAdvancedPricingSection.lastTierPriceDiscountAmount}}" : "{{AdminProductFormAdvancedPricingSection.lastTierPriceFixedAmount}}"" stepKey="priceAmountSelector"/> + <waitForElementVisible selector="{$priceAmountSelector}" stepKey="waitPriceAmountFieldAppers"/> + <fillField selector="{$priceAmountSelector}" userInput="{{amount}}" stepKey="fillPriceAmount"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml new file mode 100644 index 0000000000000..03c98c1cb17b7 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminProductFormCloseAdvancedPricingDialogActionGroup"> + <annotations> + <description>Close Advanced Pricing dialog from product form.</description> + </annotations> + + <scrollToTopOfPage stepKey="scrollToTopOfThePage"/> + <click selector="{{AdminProductFormAdvancedPricingSection.advancedPricingCloseButton}}" stepKey="clickCloseButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml new file mode 100644 index 0000000000000..10f2d32799200 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminProductFormDoneAdvancedPricingDialogActionGroup"> + <annotations> + <description>Done Advanced Pricing dialog from product form.</description> + </annotations> + + <scrollToTopOfPage stepKey="scrollToTopOfThePage"/> + <click selector="{{AdminProductFormAdvancedPricingSection.doneButton}}" stepKey="clickDoneButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml new file mode 100644 index 0000000000000..1c96ce3469485 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminProductFormOpenAdvancedPricingDialogActionGroup"> + <annotations> + <description>Open Advanced Pricing dialog from product form.</description> + </annotations> + + <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink"/> + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.modalTitle}}" stepKey="waitForModalTitleAppears"/> + <see selector="{{AdminProductFormAdvancedPricingSection.modalTitle}}" userInput="Advanced Pricing" stepKey="checkModalTitle"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml new file mode 100644 index 0000000000000..42aee90882400 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup"> + <annotations> + <description>Check AdvancedPricing tier price row.</description> + </annotations> + <arguments> + <argument name="rowNumber" type="string" defaultValue="0"/> + <argument name="website" type="string" defaultValue="All Websites [USD]"/> + <argument name="customerGroup" type="string" defaultValue="ALL GROUPS"/> + <argument name="quantity" type="string" defaultValue="1"/> + <argument name="priceType" type="string" defaultValue="Fixed"/> + <argument name="amount" type="string" defaultValue="10"/> + </arguments> + + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect(rowNumber)}}" stepKey="waitForPricesGridAppears"/> + <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect(rowNumber)}}" userInput="{{website}}" stepKey="seeWebsite"/> + <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect(rowNumber)}}" userInput="{{customerGroup}}" stepKey="seeCustomerGroup"/> + <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput(rowNumber)}}" userInput="{{quantity}}" stepKey="seeQuantity"/> + <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceValueTypeSelect(rowNumber)}}" userInput="{{priceType}}" stepKey="seePriceType"/> + <executeJS function="return '{{priceType}}' == 'Discount' ? "{{AdminProductFormAdvancedPricingSection.productTierPricePercentageValuePriceInput(rowNumber)}}" : "{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput(rowNumber)}}"" stepKey="priceAmountSelector"/> + <seeInField selector="{$priceAmountSelector}" userInput="{{amount}}" stepKey="seePriceAmount"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/ProductSetAdvancedPricingActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/ProductSetAdvancedPricingActionGroup.xml index 95bda64202159..0f7145b607f6e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/ProductSetAdvancedPricingActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/ProductSetAdvancedPricingActionGroup.xml @@ -21,7 +21,7 @@ </arguments> <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickOnAdvancedPricingButton"/> - <waitForElement selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="waitForCustomerGroupPriceAddButton"/> + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="waitForCustomerGroupPriceAddButton"/> <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="addCustomerGroupAllGroupsQty1PriceDiscountAnd10percent"/> <waitForElement selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" stepKey="waitForSelectCustomerGroupNameAttribute2"/> <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect('0')}}" userInput="{{website}}" stepKey="selectProductWebsiteValue"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SetProductUrlKeyByStringActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SetProductUrlKeyByStringActionGroup.xml index d4c654523a40b..1882063081f04 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SetProductUrlKeyByStringActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SetProductUrlKeyByStringActionGroup.xml @@ -16,7 +16,7 @@ <argument name="urlKey" type="string"/> </arguments> - <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="openSeoSection"/> + <conditionalClick selector="{{AdminProductSEOSection.sectionHeader}}" dependentSelector="{{AdminProductSEOSection.urlKeyInput}}" visible="false" stepKey="openSeoSection"/> <fillField userInput="{{urlKey}}" selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="fillUrlKey"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml index 77b89a07fb76a..91ac52a91a4c4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml @@ -25,5 +25,13 @@ <element name="msrp" type="input" selector="//input[@name='product[msrp]']" timeout="30"/> <element name="msrpType" type="select" selector="//select[@name='product[msrp_display_actual_price_type]']" timeout="30"/> <element name="save" type="button" selector="#save-button" timeout="30"/> + <element name="modalTitle" type="text" selector="aside.product_form_product_form_advanced_pricing_modal h1.modal-title"/> + <!-- Last row tier price elements--> + <element name="lastTierPriceWebsite" type="select" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[website_id]']"/> + <element name="lastTierPriceCustomerGroup" type="select" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[cust_group]']"/> + <element name="lastTierPriceQty" type="input" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[price_qty]']"/> + <element name="lastTierPriceType" type="select" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[value_type]']"/> + <element name="lastTierPriceFixedAmount" type="input" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[price]']"/> + <element name="lastTierPriceDiscountAmount" type="input" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[percentage_value]']"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml index 04110dbd73a4c..ea331bfc97db2 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml @@ -8,7 +8,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="UpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest"> + <test name="AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest"> <annotations> <stories value="Update Virtual Product"/> <title value="Update Virtual Product with Tier Price (In Stock) Visible in Category and Search"/> @@ -17,147 +17,117 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-30166"/> - </skip> </annotations> <before> - <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> <createData entity="SimpleSubCategory" stepKey="initialCategoryEntity"/> <createData entity="defaultVirtualProduct" stepKey="initialVirtualProduct"> <requiredEntity createDataKey="initialCategoryEntity"/> </createData> <createData entity="SimpleSubCategory" stepKey="categoryEntity"/> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- TODO: Replace this with CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> + <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext catalog_category_product" stepKey="reindexIndices"/> </before> + <after> + <deleteData createDataKey="initialCategoryEntity" stepKey="deleteInitialCategory"/> + <deleteData createDataKey="categoryEntity" stepKey="deleteCategory" /> <actionGroup ref="DeleteProductUsingProductGridActionGroup" stepKey="deleteVirtualProduct"> <argument name="product" value="updateVirtualProductTierPriceInStock"/> </actionGroup> - <deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/> - <deleteData stepKey="deleteSimpleSubCategory2" createDataKey="categoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </after> - <!-- Search default virtual product in the grid --> - <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage1"/> - <waitForPageLoad stepKey="waitForProductCatalogPage1"/> - <conditionalClick selector="{{AdminProductGridFilterSection.clearAll}}" dependentSelector="{{AdminProductGridFilterSection.clearAll}}" visible="true" stepKey="clickClearAllFilter" /> - <fillField selector="{{AdminProductGridFilterSection.keywordSearch}}" userInput="$$initialVirtualProduct.name$$" stepKey="fillVirtualProductNameInKeywordSearch"/> - <click selector="{{AdminProductGridFilterSection.keywordSearchButton}}" stepKey="clickKeywordSearchButton"/> - <waitForPageLoad stepKey="waitForProductSearch"/> - <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowToVerifyCreatedVirtualProduct"/> - <waitForPageLoad stepKey="waitUntilProductIsOpened"/> + <actionGroup ref="FilterAndSelectProductActionGroup" stepKey="openProductEditPageBySKU"> + <argument name="productSku" value="$initialVirtualProduct.sku$"/> + </actionGroup> <!-- Update virtual product with tier price --> - <fillField selector="{{AdminProductFormSection.productName}}" userInput="{{updateVirtualProductTierPriceInStock.name}}" stepKey="fillProductName"/> - <fillField selector="{{AdminProductFormSection.productSku}}" userInput="{{updateVirtualProductTierPriceInStock.sku}}" stepKey="fillProductSku"/> - <fillField selector="{{AdminProductFormSection.productPrice}}" userInput="{{updateVirtualProductTierPriceInStock.price}}" stepKey="fillProductPrice"/> + <actionGroup ref="FillMainProductFormNoWeightActionGroup" stepKey="fillNewProductData"> + <argument name="product" value="updateVirtualProductTierPriceInStock"/> + </actionGroup> <!-- Press enter to validate advanced pricing link --> <pressKey selector="{{AdminProductFormSection.productPrice}}" parameterArray="[\Facebook\WebDriver\WebDriverKeys::ENTER]" stepKey="pressEnterKey"/> - <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink"/> - <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="clickCustomerGroupPriceAddButton"/> - <scrollTo selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput('0')}}" x="50" y="0" stepKey="scrollToProductTierPriceQuantityInputTextBox"/> - <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect('0')}}" userInput="{{tierPriceOnVirtualProduct.website}}" stepKey="selectProductTierPriceWebsiteInput"/> - <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" userInput="{{tierPriceOnVirtualProduct.customer_group}}" stepKey="selectProductTierPriceCustomerGroupInput"/> - <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput('0')}}" userInput="{{tierPriceOnVirtualProduct.qty}}" stepKey="fillProductTierPriceQuantityInput"/> - <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput('0')}}" userInput="{{tierPriceOnVirtualProduct.price}}" stepKey="selectProductTierPriceFixedPrice"/> - <click selector="{{AdminProductFormAdvancedPricingSection.doneButton}}" stepKey="clickDoneButton"/> + <actionGroup ref="AdminProductFormOpenAdvancedPricingDialogActionGroup" stepKey="openAdvancedPricingDialog"/> + <actionGroup ref="AdminProductFormAdvancedPricingAddTierPriceActionGroup" stepKey="addTierPrice"> + <argument name="website" value="{{tierPriceOnVirtualProduct.website}}"/> + <argument name="customerGroup" value="{{tierPriceOnVirtualProduct.customer_group}}"/> + <argument name="quantity" value="{{tierPriceOnVirtualProduct.qty}}"/> + <argument name="priceType" value="Fixed"/> + <argument name="amount" value="{{tierPriceOnVirtualProduct.price}}"/> + </actionGroup> + <actionGroup ref="AdminProductFormDoneAdvancedPricingDialogActionGroup" stepKey="doneAdvancedPricingModal"/> <selectOption selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{updateVirtualProductTierPriceInStock.productTaxClass}}" stepKey="selectProductStockClass"/> - <fillField selector="{{AdminProductFormSection.productQuantity}}" userInput="{{updateVirtualProductTierPriceInStock.quantity}}" stepKey="fillProductQuantity"/> - <selectOption selector="{{AdminProductFormSection.stockStatus}}" userInput="{{updateVirtualProductTierPriceInStock.status}}" stepKey="selectStockStatusInStock"/> - <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> - <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> - <waitForPageLoad stepKey="waitForCategory1"/> - <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> - <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> - <waitForPageLoad stepKey="waitForCategory2"/> - <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> - <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> + <actionGroup ref="RemoveCategoryFromProductActionGroup" stepKey="unselectInitialCategory"> + <argument name="categoryName" value="$initialCategoryEntity.name$"/> + </actionGroup> + <actionGroup ref="SetCategoryByNameActionGroup" stepKey="setNewCategory"> + <argument name="categoryName" value="$categoryEntity.name$"/> + </actionGroup> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{updateVirtualProductTierPriceInStock.visibility}}" stepKey="selectVisibility"/> - <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection"/> - <fillField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{updateVirtualProductTierPriceInStock.urlKey}}" stepKey="fillUrlKey"/> - <scrollToTopOfPage stepKey="scrollToTopOfAdminProductFormSection"/> - <click selector="{{AdminProductFormSection.save}}" stepKey="clickSaveButton"/> - <waitForPageLoad stepKey="waitForVirtualProductSaved"/> - <!-- Verify we see success message --> - <see selector="{{AdminProductFormSection.successMessage}}" userInput="You saved the product." stepKey="seeAssertVirtualProductSaveSuccessMessage"/> + <actionGroup ref="SetProductUrlKeyByStringActionGroup" stepKey="updateUrlKey"> + <argument name="urlKey" value="{{updateVirtualProductTierPriceInStock.urlKey}}"/> + </actionGroup> + <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProductAndCheckSuccessMessage"/> <!-- Search updated virtual product(from above step) in the grid --> - <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPageToSearchUpdatedVirtualProduct"/> - <waitForPageLoad stepKey="waitForProductCatalogPageToLoad"/> - <conditionalClick selector="{{AdminProductGridFilterSection.clearAll}}" dependentSelector="{{AdminProductGridFilterSection.clearAll}}" visible="true" stepKey="clickClearAll"/> - <click selector="{{AdminProductGridFilterSection.filters}}" stepKey="clickFiltersButton"/> - <fillField selector="{{AdminProductGridFilterSection.nameFilter}}" userInput="{{updateVirtualProductTierPriceInStock.name}}" stepKey="fillVirtualProductNameInNameFilter"/> - <fillField selector="{{AdminProductGridFilterSection.skuFilter}}" userInput="{{updateVirtualProductTierPriceInStock.sku}}" stepKey="fillVirtualProductSku"/> - <click selector="{{AdminProductGridFilterSection.applyFilters}}" stepKey="clickApplyFiltersButton"/> - <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowToVerifyUpdatedVirtualProductVisibleInGrid"/> - <waitForPageLoad stepKey="waitUntilVirtualProductPageIsOpened"/> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> + <argument name="product" value="updateVirtualProductTierPriceInStock"/> + </actionGroup> <!-- Verify customer see updated virtual product with tier price(from the above step) in the product form page --> - <seeInField selector="{{AdminProductFormSection.productName}}" userInput="{{updateVirtualProductTierPriceInStock.name}}" stepKey="seeProductName"/> - <seeInField selector="{{AdminProductFormSection.productSku}}" userInput="{{updateVirtualProductTierPriceInStock.sku}}" stepKey="seeProductSku"/> - <seeInField selector="{{AdminProductFormSection.productPrice}}" userInput="{{updateVirtualProductTierPriceInStock.price}}" stepKey="seeProductPrice"/> - <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink1"/> - <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect('0')}}" userInput="{{tierPriceOnVirtualProduct.website}}" stepKey="seeProductTierPriceWebsiteInput"/> - <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" userInput="{{tierPriceOnVirtualProduct.customer_group}}" stepKey="seeProductTierPriceCustomerGroupInput"/> - <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput('0')}}" userInput="{{tierPriceOnVirtualProduct.qty}}" stepKey="seeProductTierPriceQuantityInput"/> - <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput('0')}}" userInput="{{tierPriceOnVirtualProduct.price}}" stepKey="seeProductTierPriceFixedPrice"/> - <click selector="{{AdminProductFormAdvancedPricingSection.advancedPricingCloseButton}}" stepKey="clickAdvancedPricingCloseButton"/> + <actionGroup ref="AssertProductInfoOnEditPageActionGroup" stepKey="verifyProductInAdminEditForm"> + <argument name="product" value="updateVirtualProductTierPriceInStock"/> + </actionGroup> + <actionGroup ref="AdminProductFormOpenAdvancedPricingDialogActionGroup" stepKey="openAdvancedPricingDialogAgain"/> + <actionGroup ref="AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup" stepKey="checkTierPrice"> + <argument name="rowNumber" value="0"/> + <argument name="website" value="{{tierPriceOnVirtualProduct.website}}"/> + <argument name="customerGroup" value="{{tierPriceOnVirtualProduct.customer_group}}"/> + <argument name="quantity" value="{{tierPriceOnVirtualProduct.qty}}"/> + <argument name="priceType" value="Fixed"/> + <argument name="amount" value="{{tierPriceOnVirtualProduct.price}}"/> + </actionGroup> + <actionGroup ref="AdminProductFormCloseAdvancedPricingDialogActionGroup" stepKey="closeAdvancedPricingModal"/> <seeInField selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{updateVirtualProductTierPriceInStock.productTaxClass}}" stepKey="seeProductTaxClass"/> - <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="{{updateVirtualProductTierPriceInStock.quantity}}" stepKey="seeProductQuantity"/> - <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="{{updateVirtualProductTierPriceInStock.status}}" stepKey="seeProductStockStatus"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> <grabMultiple selector="{{AdminProductFormSection.selectMultipleCategories}}" stepKey="selectedCategories" /> <assertEquals stepKey="assertSelectedCategories"> <actualResult type="variable">selectedCategories</actualResult> - <expectedResult type="array">[$$categoryEntity.name$$]</expectedResult> + <expectedResult type="array">[$categoryEntity.name$]</expectedResult> </assertEquals> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneOnCategorySelect"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{updateVirtualProductTierPriceInStock.visibility}}" stepKey="seeVisibility"/> - <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> - <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> + + <conditionalClick selector="{{AdminProductSEOSection.sectionHeader}}" dependentSelector="{{AdminProductSEOSection.useDefaultUrl}}" visible="false" stepKey="openSearchEngineOptimizationSection"/> + <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="scrollToAdminProductSEOSection"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{updateVirtualProductTierPriceInStock.urlKey}}" stepKey="seeUrlKey"/> <!--Verify customer see updated virtual product link on category page --> - <amOnPage url="{{StorefrontCategoryPage.url($$categoryEntity.name$$)}}" stepKey="openCategoryPage"/> - <waitForPageLoad stepKey="waitForCategoryPageLoad"/> - <see selector="{{StorefrontCategoryMainSection.productLink}}" userInput="{{updateVirtualProductTierPriceInStock.name}}" stepKey="seeVirtualProductLinkOnCategoryPage"/> + <actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="openCategoryPageOnFrontend"> + <argument name="category" value="$categoryEntity$"/> + </actionGroup> + <actionGroup ref="AssertProductOnCategoryPageActionGroup" stepKey="checkProductOnCategoryPage"> + <argument name="product" value="updateVirtualProductTierPriceInStock"/> + </actionGroup> <!--Verify customer see updated virtual product with tier price on product storefront page --> - <amOnPage url="{{StorefrontProductPage.url(updateVirtualProductTierPriceInStock.urlKey)}}" stepKey="goToProductPage"/> - <waitForPageLoad stepKey="waitForStorefrontProductPageLoad"/> - <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{updateVirtualProductTierPriceInStock.name}}" stepKey="seeVirtualProductNameOnStoreFrontPage"/> - <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="{{updateVirtualProductTierPriceInStock.price}}" stepKey="seeVirtualProductPriceOnStoreFrontPage"/> - <see selector="{{StorefrontProductInfoMainSection.productSku}}" userInput="{{updateVirtualProductTierPriceInStock.sku}}" stepKey="seeVirtualProductSku"/> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productStockStatus}}" stepKey="productStockAvailableStatus"/> - <assertEquals stepKey="assertStockAvailableOnProductPage"> - <expectedResult type="string">{{updateVirtualProductTierPriceInStock.storefrontStatus}}</expectedResult> - <actualResult type="variable">productStockAvailableStatus</actualResult> - </assertEquals> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="productPriceAmount"/> - <assertEquals stepKey="assertOldPriceTextOnProductPage"> - <expectedResult type="string">${{updateVirtualProductTierPriceInStock.price}}</expectedResult> - <actualResult type="variable">productPriceAmount</actualResult> - </assertEquals> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.tierPriceText}}" stepKey="tierPriceText"/> - <assertEquals stepKey="assertTierPriceTextOnProductPage"> - <expectedResult type="string">Buy {{tierPriceOnVirtualProduct.qty}} for ${{tierPriceOnVirtualProduct.price}} each and save 38%</expectedResult> - <actualResult type="variable">tierPriceText</actualResult> - </assertEquals> + <actionGroup ref="AssertProductInStorefrontProductPageActionGroup" stepKey="verifyProductOnFrontend"> + <argument name="product" value="updateVirtualProductTierPriceInStock"/> + </actionGroup> + <see selector="{{StorefrontProductInfoMainSection.productStockStatus}}" userInput="{{updateVirtualProductTierPriceInStock.storefrontStatus}}" stepKey="assertStockAvailableOnProductPage"/> + <see selector="{{StorefrontProductInfoMainSection.tierPriceText}}" userInput="Buy {{tierPriceOnVirtualProduct.qty}} for ${{tierPriceOnVirtualProduct.price}} each and save 38%" stepKey="assertTierPriceTextOnProductPage"/> <!--Verify customer see updated virtual product link on magento storefront page and is searchable by sku --> - <amOnPage url="{{StorefrontProductPage.url(updateVirtualProductTierPriceInStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> - <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{updateVirtualProductTierPriceInStock.sku}}" stepKey="fillVirtualProductName"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{updateVirtualProductTierPriceInStock.name}}" stepKey="seeVirtualProductName"/> - <grabTextFrom selector="{{StorefrontQuickSearchResultsSection.asLowAsLabel}}" stepKey="tierPriceTextOnStorefrontPage"/> - <assertEquals stepKey="assertTierPriceTextOnCategoryPage"> - <expectedResult type="string">As low as ${{tierPriceOnVirtualProduct.price}}</expectedResult> - <actualResult type="variable">tierPriceTextOnStorefrontPage</actualResult> - </assertEquals> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchProductBySku"> + <argument name="phrase" value="{{updateVirtualProductTierPriceInStock.sku}}"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByNameActionGroup" stepKey="checkProductInSearchResults"> + <argument name="productName" value="{{updateVirtualProductTierPriceInStock.name}}"/> + </actionGroup> + <see selector="{{StorefrontQuickSearchResultsSection.asLowAsLabel}}" userInput="As low as ${{tierPriceOnVirtualProduct.price}}" stepKey="assertTierPriceTextOnCategoryPage"/> </test> </tests> From c1a8ead92f47832dbac42762cbcd47fdcf82fde7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= <bartlomiejszubert@gmail.com> Date: Mon, 3 Feb 2020 23:46:41 +0100 Subject: [PATCH 084/176] Move additional dependencies from private getters to constructor - Magento_PageCache --- .../PageCache/Observer/FlushAllCache.php | 53 ++++---- .../PageCache/Observer/FlushCacheByTags.php | 78 +++++------- .../Test/Unit/Observer/FlushAllCacheTest.php | 86 ++++++++----- .../Unit/Observer/FlushCacheByTagsTest.php | 118 ++++++++++-------- 4 files changed, 187 insertions(+), 148 deletions(-) diff --git a/app/code/Magento/PageCache/Observer/FlushAllCache.php b/app/code/Magento/PageCache/Observer/FlushAllCache.php index 0a45ebf265715..aca9fc5e2a8c0 100644 --- a/app/code/Magento/PageCache/Observer/FlushAllCache.php +++ b/app/code/Magento/PageCache/Observer/FlushAllCache.php @@ -1,18 +1,25 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\PageCache\Observer; -use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\PageCache\Cache; +use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; +use Magento\PageCache\Model\Cache\Type; +use Magento\PageCache\Model\Config; +/** + * Observer used to flush all caches with built-in full page cache + */ class FlushAllCache implements ObserverInterface { /** - * @var \Magento\Framework\App\PageCache\Cache + * @var Cache * * @deprecated 100.1.0 */ @@ -21,48 +28,42 @@ class FlushAllCache implements ObserverInterface /** * Application config object * - * @var \Magento\PageCache\Model\Config + * @var Config */ protected $_config; /** - * @var \Magento\PageCache\Model\Cache\Type + * @var Type */ private $fullPageCache; /** - * @param \Magento\PageCache\Model\Config $config - * @param \Magento\Framework\App\PageCache\Cache $cache + * @param Config $config + * @param Cache $cache + * @param Type $fullPageCache */ - public function __construct(\Magento\PageCache\Model\Config $config, \Magento\Framework\App\PageCache\Cache $cache) - { + public function __construct( + Config $config, + Cache $cache, + Type $fullPageCache + ) { $this->_config = $config; $this->_cache = $cache; + $this->fullPageCache = $fullPageCache; } /** * Flash Built-In cache - * @param \Magento\Framework\Event\Observer $observer + * + * @param Observer $observer + * * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function execute(\Magento\Framework\Event\Observer $observer) - { - if ($this->_config->getType() == \Magento\PageCache\Model\Config::BUILT_IN) { - $this->getCache()->clean(); - } - } - - /** - * TODO: Workaround to support backwards compatibility, will rework to use Dependency Injection in MAGETWO-49547 - * - * @return \Magento\PageCache\Model\Cache\Type - */ - private function getCache() + public function execute(Observer $observer) { - if (!$this->fullPageCache) { - $this->fullPageCache = ObjectManager::getInstance()->get(\Magento\PageCache\Model\Cache\Type::class); + if ($this->_config->getType() == Config::BUILT_IN) { + $this->fullPageCache->clean(); } - return $this->fullPageCache; } } diff --git a/app/code/Magento/PageCache/Observer/FlushCacheByTags.php b/app/code/Magento/PageCache/Observer/FlushCacheByTags.php index 8ce26f7d31781..778557ee0dd2f 100644 --- a/app/code/Magento/PageCache/Observer/FlushCacheByTags.php +++ b/app/code/Magento/PageCache/Observer/FlushCacheByTags.php @@ -1,18 +1,27 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\PageCache\Observer; -use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\Cache\Tag\Resolver; +use Magento\Framework\App\PageCache\Cache; +use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; +use Magento\PageCache\Model\Cache\Type; +use Magento\PageCache\Model\Config; +use Zend_Cache; +/** + * Observer used to cache by tags when using built-in full page cache + */ class FlushCacheByTags implements ObserverInterface { /** - * @var \Magento\Framework\App\PageCache\Cache + * @var Cache * * @deprecated 100.1.0 */ @@ -21,78 +30,59 @@ class FlushCacheByTags implements ObserverInterface /** * Application config object * - * @var \Magento\PageCache\Model\Config + * @var Config */ protected $_config; /** - * @var \Magento\PageCache\Model\Cache\Type + * @var Type */ private $fullPageCache; /** * Invalidation tags resolver * - * @var \Magento\Framework\App\Cache\Tag\Resolver + * @var Resolver */ private $tagResolver; /** - * @param \Magento\PageCache\Model\Config $config - * @param \Magento\Framework\App\PageCache\Cache $cache + * @param Config $config + * @param Cache $cache + * @param Type $fullPageCache + * @param Resolver $tagResolver */ - public function __construct(\Magento\PageCache\Model\Config $config, \Magento\Framework\App\PageCache\Cache $cache) - { + public function __construct( + Config $config, + Cache $cache, + Type $fullPageCache, + Resolver $tagResolver + ) { $this->_config = $config; $this->_cache = $cache; + $this->fullPageCache = $fullPageCache; + $this->tagResolver = $tagResolver; } /** - * If Built-In caching is enabled it collects array of tags - * of incoming object and asks to clean cache. + * If Built-In caching is enabled it collects array of tags of incoming object and asks to clean cache. + * + * @param Observer $observer * - * @param \Magento\Framework\Event\Observer $observer * @return void */ - public function execute(\Magento\Framework\Event\Observer $observer) + public function execute(Observer $observer) { - if ($this->_config->getType() == \Magento\PageCache\Model\Config::BUILT_IN && $this->_config->isEnabled()) { + if ($this->_config->getType() == Config::BUILT_IN && $this->_config->isEnabled()) { $object = $observer->getEvent()->getObject(); if (!is_object($object)) { return; } - $tags = $this->getTagResolver()->getTags($object); + $tags = $this->tagResolver->getTags($object); if (!empty($tags)) { - $this->getCache()->clean(\Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, array_unique($tags)); + $this->fullPageCache->clean(Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, array_unique($tags)); } } } - - /** - * TODO: Workaround to support backwards compatibility, will rework to use Dependency Injection in MAGETWO-49547 - * - * - * @return \Magento\PageCache\Model\Cache\Type - */ - private function getCache() - { - if (!$this->fullPageCache) { - $this->fullPageCache = ObjectManager::getInstance()->get(\Magento\PageCache\Model\Cache\Type::class); - } - return $this->fullPageCache; - } - - /** - * @deprecated 100.1.2 - * @return \Magento\Framework\App\Cache\Tag\Resolver - */ - private function getTagResolver() - { - if ($this->tagResolver === null) { - $this->tagResolver = \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Framework\App\Cache\Tag\Resolver::class); - } - return $this->tagResolver; - } } diff --git a/app/code/Magento/PageCache/Test/Unit/Observer/FlushAllCacheTest.php b/app/code/Magento/PageCache/Test/Unit/Observer/FlushAllCacheTest.php index 27e1da5a9f144..a0fa99035c8b0 100644 --- a/app/code/Magento/PageCache/Test/Unit/Observer/FlushAllCacheTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Observer/FlushAllCacheTest.php @@ -1,48 +1,61 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\PageCache\Test\Unit\Observer; -class FlushAllCacheTest extends \PHPUnit\Framework\TestCase -{ - /** @var \Magento\PageCache\Observer\FlushAllCache */ - private $_model; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\PageCache\Model\Cache\Type; +use Magento\PageCache\Model\Config; +use Magento\PageCache\Observer\FlushAllCache; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\PageCache\Model\Config */ - private $_configMock; +/** + * Test class for \Magento\PageCache\Observer\FlushAllCache + */ +class FlushAllCacheTest extends TestCase +{ + /** + * @var FlushAllCache + */ + private $model; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\PageCache\Cache */ - private $_cacheMock; + /** + * @var Config|MockObject + */ + private $configMock; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Event\Observer */ + /** + * @var Observer|MockObject + */ private $observerMock; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\PageCache\Model\Cache\Type */ + /** + * @var Type|MockObject + */ private $fullPageCacheMock; /** - * Set up all mocks and data for test + * @inheritDoc */ protected function setUp() { - $this->_configMock = $this->createPartialMock(\Magento\PageCache\Model\Config::class, ['getType', 'isEnabled']); - $this->_cacheMock = $this->createPartialMock(\Magento\Framework\App\PageCache\Cache::class, ['clean']); - $this->fullPageCacheMock = $this->createPartialMock(\Magento\PageCache\Model\Cache\Type::class, ['clean']); - $this->observerMock = $this->createMock(\Magento\Framework\Event\Observer::class); + $this->configMock = $this->createPartialMock(Config::class, ['getType', 'isEnabled']); + $this->fullPageCacheMock = $this->createPartialMock(Type::class, ['clean']); + $this->observerMock = $this->createMock(Observer::class); - $this->_model = new \Magento\PageCache\Observer\FlushAllCache( - $this->_configMock, - $this->_cacheMock + $objectManager = new ObjectManager($this); + $this->model = $objectManager->getObject( + FlushAllCache::class, + [ + 'config' => $this->configMock, + 'fullPageCache' => $this->fullPageCacheMock + ] ); - - $reflection = new \ReflectionClass(\Magento\PageCache\Observer\FlushAllCache::class); - $reflectionProperty = $reflection->getProperty('fullPageCache'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($this->_model, $this->fullPageCacheMock); } /** @@ -50,15 +63,32 @@ protected function setUp() */ public function testExecute() { - $this->_configMock->expects( + $this->configMock->expects( $this->once() )->method( 'getType' - )->will( - $this->returnValue(\Magento\PageCache\Model\Config::BUILT_IN) + )->willReturn( + Config::BUILT_IN ); $this->fullPageCacheMock->expects($this->once())->method('clean'); - $this->_model->execute($this->observerMock); + $this->model->execute($this->observerMock); + } + + /** + * Test case for flushing all the cache with varnish enabled + */ + public function testExecuteWithVarnish() + { + $this->configMock->expects( + $this->once() + )->method( + 'getType' + )->willReturn( + Config::VARNISH + ); + + $this->fullPageCacheMock->expects($this->never())->method('clean'); + $this->model->execute($this->observerMock); } } diff --git a/app/code/Magento/PageCache/Test/Unit/Observer/FlushCacheByTagsTest.php b/app/code/Magento/PageCache/Test/Unit/Observer/FlushCacheByTagsTest.php index 8019c6b2e810f..cc3df162fd35a 100644 --- a/app/code/Magento/PageCache/Test/Unit/Observer/FlushCacheByTagsTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Observer/FlushCacheByTagsTest.php @@ -1,51 +1,66 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\PageCache\Test\Unit\Observer; -class FlushCacheByTagsTest extends \PHPUnit\Framework\TestCase -{ - /** @var \Magento\PageCache\Observer\FlushCacheByTags */ - protected $_model; +use Magento\Framework\App\Cache\Tag\Resolver; +use Magento\Framework\Event; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\PageCache\Model\Cache\Type; +use Magento\PageCache\Model\Config; +use Magento\PageCache\Observer\FlushCacheByTags; +use Magento\Store\Model\Store; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\PageCache\Model\Config */ - protected $_configMock; +/** + * Test class for \Magento\PageCache\Observer\FlushCacheByTags + */ +class FlushCacheByTagsTest extends TestCase +{ + /** + * @var FlushCacheByTags + */ + private $model; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\PageCache\Cache */ - protected $_cacheMock; + /** + * @var Config|MockObject + */ + private $configMock; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\PageCache\Model\Cache\Type */ + /** + * @var Type|MockObject + */ private $fullPageCacheMock; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\Cache\Tag\Resolver */ - private $tagResolver; + /** + * @var Resolver|MockObject + */ + private $tagResolverMock; /** - * Set up all mocks and data for test + * @inheritDoc */ protected function setUp() { - $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->_configMock = $this->createPartialMock(\Magento\PageCache\Model\Config::class, ['getType', 'isEnabled']); - $this->_cacheMock = $this->createPartialMock(\Magento\Framework\App\PageCache\Cache::class, ['clean']); - $this->fullPageCacheMock = $this->createPartialMock(\Magento\PageCache\Model\Cache\Type::class, ['clean']); - - $this->_model = new \Magento\PageCache\Observer\FlushCacheByTags( - $this->_configMock, - $this->_cacheMock + $this->configMock = $this->createPartialMock(Config::class, ['getType', 'isEnabled']); + $this->fullPageCacheMock = $this->createPartialMock(Type::class, ['clean']); + + $this->tagResolverMock = $this->createMock(Resolver::class); + + $objectManager = new ObjectManager($this); + $this->model = $objectManager->getObject( + FlushCacheByTags::class, + [ + 'config' => $this->configMock, + 'fullPageCache' => $this->fullPageCacheMock, + 'tagResolver' => $this->tagResolverMock + ] ); - - $this->tagResolver = $this->createMock(\Magento\Framework\App\Cache\Tag\Resolver::class); - - $helper->setBackwardCompatibleProperty($this->_model, 'tagResolver', $this->tagResolver); - $reflection = new \ReflectionClass(\Magento\PageCache\Observer\FlushCacheByTags::class); - $reflectionProperty = $reflection->getProperty('fullPageCache'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($this->_model, $this->fullPageCacheMock); } /** @@ -56,28 +71,28 @@ protected function setUp() */ public function testExecute($cacheState) { - $this->_configMock->expects($this->any())->method('isEnabled')->will($this->returnValue($cacheState)); - $observerObject = $this->createMock(\Magento\Framework\Event\Observer::class); - $observedObject = $this->createMock(\Magento\Store\Model\Store::class); + $this->configMock->method('isEnabled')->willReturn($cacheState); + $observerObject = $this->createMock(Observer::class); + $observedObject = $this->createMock(Store::class); if ($cacheState) { $tags = ['cache_1', 'cache_group']; $expectedTags = ['cache_1', 'cache_group']; - $eventMock = $this->createPartialMock(\Magento\Framework\Event::class, ['getObject']); - $eventMock->expects($this->once())->method('getObject')->will($this->returnValue($observedObject)); - $observerObject->expects($this->once())->method('getEvent')->will($this->returnValue($eventMock)); - $this->_configMock->expects($this->once()) + $eventMock = $this->createPartialMock(Event::class, ['getObject']); + $eventMock->expects($this->once())->method('getObject')->willReturn($observedObject); + $observerObject->expects($this->once())->method('getEvent')->willReturn($eventMock); + $this->configMock->expects($this->once()) ->method('getType') - ->willReturn(\Magento\PageCache\Model\Config::BUILT_IN); - $this->tagResolver->expects($this->once())->method('getTags')->will($this->returnValue($tags)); + ->willReturn(Config::BUILT_IN); + $this->tagResolverMock->expects($this->once())->method('getTags')->willReturn($tags); $this->fullPageCacheMock->expects($this->once()) ->method('clean') ->with(\Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, $this->equalTo($expectedTags)); } - $result = $this->_model->execute($observerObject); + $result = $this->model->execute($observerObject); $this->assertNull($result); } @@ -92,28 +107,31 @@ public function flushCacheByTagsDataProvider() ]; } + /** + * Test case for cache invalidation with empty tags + */ public function testExecuteWithEmptyTags() { - $this->_configMock->expects($this->any())->method('isEnabled')->will($this->returnValue(true)); - $observerObject = $this->createMock(\Magento\Framework\Event\Observer::class); - $observedObject = $this->createMock(\Magento\Store\Model\Store::class); + $this->configMock->method('isEnabled')->willReturn(true); + $observerObject = $this->createMock(Observer::class); + $observedObject = $this->createMock(Store::class); $tags = []; - $eventMock = $this->createPartialMock(\Magento\Framework\Event::class, ['getObject']); - $eventMock->expects($this->once())->method('getObject')->will($this->returnValue($observedObject)); - $observerObject->expects($this->once())->method('getEvent')->will($this->returnValue($eventMock)); - $this->_configMock->expects( + $eventMock = $this->createPartialMock(Event::class, ['getObject']); + $eventMock->expects($this->once())->method('getObject')->willReturn($observedObject); + $observerObject->expects($this->once())->method('getEvent')->willReturn($eventMock); + $this->configMock->expects( $this->once() )->method( 'getType' - )->will( - $this->returnValue(\Magento\PageCache\Model\Config::BUILT_IN) + )->willReturn( + Config::BUILT_IN ); - $this->tagResolver->expects($this->once())->method('getTags')->will($this->returnValue($tags)); + $this->tagResolverMock->expects($this->once())->method('getTags')->willReturn($tags); $this->fullPageCacheMock->expects($this->never())->method('clean'); - $this->_model->execute($observerObject); + $this->model->execute($observerObject); } } From 28026b0a7ae03c154ca31d92b3d39145c09efd4f Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Tue, 4 Feb 2020 09:51:01 +0200 Subject: [PATCH 085/176] MC-31041: Order API response GiftCard Code not coming in API response --- app/code/Magento/Sales/Model/Order/ProductOption.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Sales/Model/Order/ProductOption.php b/app/code/Magento/Sales/Model/Order/ProductOption.php index dc9ec42e27e60..9a4f847b135e7 100644 --- a/app/code/Magento/Sales/Model/Order/ProductOption.php +++ b/app/code/Magento/Sales/Model/Order/ProductOption.php @@ -59,6 +59,7 @@ public function add(OrderItemInterface $orderItem): void { /** @var DataObject $request */ $request = $orderItem->getBuyRequest(); + $request->setProductOptions($orderItem->getProductOptions()); $productType = $orderItem->getProductType(); if (isset($this->processorPool[$productType]) From 711ae3620b334934210098263292dd18c8e5715b Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 4 Feb 2020 10:41:54 +0200 Subject: [PATCH 086/176] MC-30281: [2.4] Fix and unskip StorefrontSortingByPriceForConfigurableProductWithCatalogRuleAppliedTest --- .../Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml | 3 ++- .../NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup.xml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml index e0d02a280bf6c..d20798aef4838 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml @@ -11,7 +11,8 @@ <!-- action group to create a new catalog price rule giving a catalogRule entity --> <actionGroup name="NewCatalogPriceRuleByUIActionGroup"> <annotations> - <description>Goes to the Catalog Price Rule grid. Clicks on Add. Fills in the provided Catalog Rule details.</description> + <description>DEPRECATED. Please use set of AG: AdminOpenNewCatalogPriceRuleFormPageActionGroup, AdminCatalogPriceRuleFillMainInfoActionGroup, AdminCatalogPriceRuleFillActionsActionGroup, AdminCatalogPriceRuleSaveAndApplyActionGroup + Goes to the Catalog Price Rule grid. Clicks on Add. Fills in the provided Catalog Rule details.</description> </annotations> <arguments> <argument name="catalogRule" defaultValue="_defaultCatalogRule"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup.xml index 9d25ffa948ad1..217a7519defa7 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup.xml @@ -10,7 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup" extends="NewCatalogPriceRuleByUIActionGroup"> <annotations> - <description>EXTENDS: newCatalogPriceRuleByUI. Add a Catalog Price Rule Condition based on the provided SKU.</description> + <description>DEPRECATED. Please use set of AG: AdminOpenNewCatalogPriceRuleFormPageActionGroup, AdminCatalogPriceRuleFillMainInfoActionGroup, AdminCatalogPriceRuleFillActionsActionGroup, AdminCatalogPriceRuleAddSkuConditionActionGroup, AdminCatalogPriceRuleSaveAndApplyActionGroup + EXTENDS: newCatalogPriceRuleByUI. Add a Catalog Price Rule Condition based on the provided SKU.</description> </annotations> <arguments> <argument name="productSku"/> From 199afbff8651b267ba52a3536784e22cc37979f6 Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Tue, 4 Feb 2020 20:49:46 +1030 Subject: [PATCH 087/176] #26622 - Change to check for both parentItemId and parentItem --- app/code/Magento/SalesRule/Model/Validator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php index addfd6107f600..f05ad1eaba7fd 100644 --- a/app/code/Magento/SalesRule/Model/Validator.php +++ b/app/code/Magento/SalesRule/Model/Validator.php @@ -383,7 +383,7 @@ public function initTotals($items, Address $address) foreach ($items as $item) { //Skipping child items to avoid double calculations - if ($item->getParentItem()) { + if ($item->getParentItemId() || $item->getParentItem()) { continue; } if (!$rule->getActions()->validate($item)) { From 90c354044003d9d870f2ab52dbf0cf07ddde44b7 Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Tue, 4 Feb 2020 20:54:02 +1030 Subject: [PATCH 088/176] #26622 - Update test to check combinations of parentItemId and parentItem --- .../SalesRule/Test/Unit/Model/ValidatorTest.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php index e86068946ca78..93f46bc42db5a 100644 --- a/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php +++ b/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php @@ -346,11 +346,14 @@ public function testInitTotalsCanApplyDiscount() 'getDiscountCalculationPrice', 'getBaseDiscountCalculationPrice', 'getCalculationPrice', - 'getParentItemId' + 'getParentItemId', + 'getParentItem' ] ); $item2 = clone $item1; - $items = [$item1, $item2]; + $item3 = clone $item1; + $item4 = clone $item1; + $items = [$item1, $item2, $item3, $item4]; $rule->expects($this->any()) ->method('getSimpleAction') @@ -368,11 +371,21 @@ public function testInitTotalsCanApplyDiscount() $validator->expects($this->at(1))->method('isValid')->with($item2)->willReturn(true); $item1->expects($this->any())->method('getParentItemId')->willReturn(false); + $item1->expects($this->any())->method('getParentItem')->willReturn(false); $item1->expects($this->never())->method('getDiscountCalculationPrice'); $item1->expects($this->never())->method('getBaseDiscountCalculationPrice'); $item2->expects($this->any())->method('getParentItemId')->willReturn(false); + $item2->expects($this->any())->method('getParentItem')->willReturn(false); $item2->expects($this->any())->method('getDiscountCalculationPrice')->willReturn(50); $item2->expects($this->once())->method('getBaseDiscountCalculationPrice')->willReturn(50); + $item3->expects($this->any())->method('getParentItemId')->willReturn(false); + $item3->expects($this->any())->method('getParentItem')->willReturn(true); + $item3->expects($this->never())->method('getDiscountCalculationPrice'); + $item3->expects($this->never())->method('getBaseDiscountCalculationPrice'); + $item4->expects($this->any())->method('getParentItemId')->willReturn(true); + $item4->expects($this->any())->method('getParentItem')->willReturn(false); + $item4->expects($this->never())->method('getDiscountCalculationPrice'); + $item4->expects($this->never())->method('getBaseDiscountCalculationPrice'); $this->utility->expects($this->once())->method('getItemQty')->willReturn(1); $this->utility->expects($this->any())->method('canProcessRule')->willReturn(true); From 6cd172ffcc91c63ba3ddf7ed5c037287c552d956 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 4 Feb 2020 15:09:02 +0200 Subject: [PATCH 089/176] MC-30720: [MFTF] [2.4] Fix flaky test AdminMoveAnchoredCategoryTest (MAGETWO-76273) --- .../Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml index 55c20cac593ef..7261df8765dc5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml @@ -14,7 +14,8 @@ <title value="Admin should be able to move a category via categories tree and changes should be applied on frontend without a forced cache cleaning"/> <description value="Admin should be able to move a category via categories tree and changes should be applied on frontend without a forced cache cleaning"/> <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-76273"/> + <testCaseId value="MC-10022"/> + <useCaseId value="MAGETWO-89248"/> <group value="category"/> </annotations> <before> @@ -41,6 +42,7 @@ <deleteData createDataKey="productOne" stepKey="deleteProductOne"/> <deleteData createDataKey="productTwo" stepKey="deleteProductTwo"/> <deleteData createDataKey="simpleSubCategoryWithParent" stepKey="deleteSubcategoryWithParent"/> + <deleteData createDataKey="simpleSubCategoryOne" stepKey="deleteSubcategoryOne"/> <deleteData createDataKey="simpleSubCategoryTwo" stepKey="deleteSubcategoryTwo"/> <actionGroup ref="logout" stepKey="logoutAdminUserAfterTest"/> </after> From 4b2ef0801bce602e2686d167b7ea153e22227b80 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 4 Feb 2020 16:13:07 +0200 Subject: [PATCH 090/176] MC-29943: [FT] Test StorefrontOrderPagerDisplayedTest fails on Jenkins --- ...roductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml | 2 ++ .../Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml | 1 + ...AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml | 1 + 3 files changed, 4 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml index 166af767be142..00e0758f6e70b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml @@ -34,6 +34,8 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> + <deleteData createDataKey="attribute" stepKey="deleteProductAttribute"/> + <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <actionGroup ref="logout" stepKey="logout"/> <!-- Reindex invalidated indices after product attribute has been created/deleted --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml index 41662e4748193..12d4f825c3764 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml @@ -27,6 +27,7 @@ </before> <after> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <actionGroup ref="logout" stepKey="logout"/> <!-- Reindex invalidated indices after product attribute has been created/deleted --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml index e12bac55d8bc8..ebdc6588da2f7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml @@ -31,6 +31,7 @@ <after> <!--Delete cteated Data --> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimplaeProduct"/> + <deleteData createDataKey="attribute" stepKey="deleteAddedAttribute"/> <actionGroup ref="logout" stepKey="logout"/> <!-- Reindex invalidated indices after product attribute has been created/deleted --> From 3fdeb7f64b00727a939f02612602e8b0f1f2af43 Mon Sep 17 00:00:00 2001 From: Nikita Sarychev <sarron80@yandex.ru> Date: Tue, 4 Feb 2020 20:29:55 +0300 Subject: [PATCH 091/176] fix Unit test case and add throw exception into method declaration --- .../Catalog/Api/CategoryListDeleteBySkuInterface.php | 3 ++- .../Test/Unit/Model/CategoryLinkRepositoryTest.php | 9 ++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php index e4fefd19d78b7..8555bad53a3ad 100644 --- a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php @@ -16,10 +16,11 @@ interface CategoryListDeleteBySkuInterface * Delete by skus list * * @param int $categoryId - * @param array $productSkuList + * @param string[] $productSkuList * @return bool * * @throws \Magento\Framework\Exception\CouldNotSaveException + * @throws \Magento\Framework\Exception\NoSuchEntityException * @throws \Magento\Framework\Exception\InputException */ public function deleteBySkus(int $categoryId, array $productSkuList): bool; diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index 8543d546b6a6b..909b952078b58 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -261,9 +261,8 @@ public function testDelete(): void public function testDeleteBySkus(): void { $categoryId = 42; - $productSku = 'testSku'; - $productId = 55; - $productPositions = [55 => 1]; + $productSkus = ['testSku', 'testSku1', 'testSku2', 'testSku3']; + $productPositions = [55 => 1, 56 => 2, 57 => 3, 58 => 4]; $categoryMock = $this->createPartialMock( Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] @@ -271,12 +270,12 @@ public function testDeleteBySkus(): void $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); $this->productResourceMock->expects($this->once())->method('getProductsIdsBySkus') - ->willReturn(['testSku' => $productId]); + ->willReturn(['testSku' => 55, 'testSku1' => 56, 'testSku2' => 57, 'testSku3' => 58]); $categoryMock->expects($this->once())->method('getProductsPosition')->willReturn($productPositions); $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('save'); - $this->assertTrue($this->model->deleteBySkus($categoryId, [$productSku])); + $this->assertTrue($this->model->deleteBySkus($categoryId, $productSkus)); } /** From 92b3468b3c0f31cb9d700ab79bd6b1cf9dd9db3f Mon Sep 17 00:00:00 2001 From: Nikita Sarychev <sarron80@yandex.ru> Date: Tue, 4 Feb 2020 21:06:32 +0300 Subject: [PATCH 092/176] mend --- .../Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php index 8555bad53a3ad..62eba5987c35d 100644 --- a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php @@ -15,7 +15,7 @@ interface CategoryListDeleteBySkuInterface /** * Delete by skus list * - * @param int $categoryId + * @param int $categoryId * @param string[] $productSkuList * @return bool * From 5f4cc5f6f81776db4419be934c1a3afd159fd38e Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Wed, 5 Feb 2020 10:30:49 +1030 Subject: [PATCH 093/176] #26622 - Reduce cyclomatic complexity of initTotals function --- .../Magento/SalesRule/Model/Validator.php | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php index f05ad1eaba7fd..913c77655b946 100644 --- a/app/code/Magento/SalesRule/Model/Validator.php +++ b/app/code/Magento/SalesRule/Model/Validator.php @@ -383,13 +383,7 @@ public function initTotals($items, Address $address) foreach ($items as $item) { //Skipping child items to avoid double calculations - if ($item->getParentItemId() || $item->getParentItem()) { - continue; - } - if (!$rule->getActions()->validate($item)) { - continue; - } - if (!$this->canApplyDiscount($item)) { + if (!$this->isValidItemForRule($item, $rule)) { continue; } $qty = $this->validatorUtility->getItemQty($item, $rule); @@ -409,6 +403,32 @@ public function initTotals($items, Address $address) return $this; } + /** + * Determine if quote item is valid for a given sales rule + * @param AbstractItem $item + * @param Rule $rule + * @return bool + */ + protected function isValidItemForRule( + AbstractItem $item, + Rule $rule + ) { + /** @var AbstractItem $item */ + if ($item->getParentItemId()) { + return false; + } + if ($item->getParentItem()) { + return false; + } + if (!$rule->getActions()->validate($item)) { + return false; + } + if (!$this->canApplyDiscount($item)) { + return false; + } + return true; + } + /** * Return item price * From 0e9c4ef9d7d541f8dba35052731f8d2d152fe4f7 Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Wed, 5 Feb 2020 10:31:21 +1030 Subject: [PATCH 094/176] #26622 - Update class description to fix failing static test --- app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php index 93f46bc42db5a..30b198e5b9199 100644 --- a/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php +++ b/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php @@ -13,7 +13,7 @@ use PHPUnit\Framework\MockObject\MockObject; /** - * Class ValidatorTest + * Tests for Magento\SalesRule\Model\Validator * @@SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ValidatorTest extends \PHPUnit\Framework\TestCase From 2c961afa3170257c4bed3c26d0d57d42d5445035 Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Wed, 5 Feb 2020 11:16:57 +1030 Subject: [PATCH 095/176] #26622 - Fix code style --- app/code/Magento/SalesRule/Model/Validator.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php index 913c77655b946..8292e9c313b66 100644 --- a/app/code/Magento/SalesRule/Model/Validator.php +++ b/app/code/Magento/SalesRule/Model/Validator.php @@ -405,6 +405,7 @@ public function initTotals($items, Address $address) /** * Determine if quote item is valid for a given sales rule + * * @param AbstractItem $item * @param Rule $rule * @return bool From 49e67f49655adac4e191236b764c67fccd9e3e29 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Wed, 5 Feb 2020 09:25:20 +0200 Subject: [PATCH 096/176] MC-30789: GTM is not trigged without Page Reload --- app/code/Magento/Cookie/view/frontend/web/js/notices.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Cookie/view/frontend/web/js/notices.js b/app/code/Magento/Cookie/view/frontend/web/js/notices.js index 9c51a49187c32..d61f8f9d32523 100644 --- a/app/code/Magento/Cookie/view/frontend/web/js/notices.js +++ b/app/code/Magento/Cookie/view/frontend/web/js/notices.js @@ -30,7 +30,7 @@ define([ if ($.mage.cookies.get(this.options.cookieName)) { this.element.hide(); - $(document).trigger('ga:init'); + $(document).trigger('user:allowed:save:cookie'); } else { window.location.href = this.options.noCookiesUrl; } From 8e45388870b322fc7ea16e23e80ca58abc332599 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 5 Feb 2020 11:12:45 +0200 Subject: [PATCH 097/176] MC-29943: [FT] Test StorefrontOrderPagerDisplayedTest fails on Jenkins --- .../AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml index ebdc6588da2f7..e12bac55d8bc8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml @@ -31,7 +31,6 @@ <after> <!--Delete cteated Data --> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimplaeProduct"/> - <deleteData createDataKey="attribute" stepKey="deleteAddedAttribute"/> <actionGroup ref="logout" stepKey="logout"/> <!-- Reindex invalidated indices after product attribute has been created/deleted --> From 427a4ad298210ed5287044cd49c51391daa0af65 Mon Sep 17 00:00:00 2001 From: Fanis Strezos <fanis.strezos@dotdigital.com> Date: Wed, 5 Feb 2020 09:43:51 +0000 Subject: [PATCH 098/176] Update dockblocks to return null --- .../Magento/Sales/Api/Data/OrderInterface.php | 8 ------- app/code/Magento/Sales/Model/Order.php | 23 +------------------ 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/app/code/Magento/Sales/Api/Data/OrderInterface.php b/app/code/Magento/Sales/Api/Data/OrderInterface.php index f699d24bd32cd..b45fddc7d7354 100644 --- a/app/code/Magento/Sales/Api/Data/OrderInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderInterface.php @@ -5,8 +5,6 @@ */ namespace Magento\Sales\Api\Data; -use Magento\Customer\Model\Customer; - /** * Order interface. * @@ -912,12 +910,6 @@ public function getCreatedAt(); */ public function setCreatedAt($createdAt); - /** - * Gets the customer from Order - * @return Customer - */ - public function getCustomer(); - /** * Gets the customer date-of-birth (DOB) for the order. * diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 1d520574f21d7..0a727b7560396 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -6,7 +6,6 @@ namespace Magento\Sales\Model; use Magento\Config\Model\Config\Source\Nooptreq; -use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Directory\Model\Currency; use Magento\Framework\Api\AttributeValueFactory; use Magento\Framework\Api\SearchCriteriaBuilder; @@ -52,6 +51,7 @@ * @method bool hasCustomerNoteNotify() * @method bool hasForcedCanCreditmemo() * @method bool getIsInProcess() + * @method \Magento\Customer\Model\Customer|null getCustomer() * @method \Magento\Sales\Model\Order setSendEmail(bool $value) * @SuppressWarnings(PHPMD.ExcessivePublicCount) * @SuppressWarnings(PHPMD.TooManyFields) @@ -307,11 +307,6 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface */ private $scopeConfig; - /** - * @var CustomerRepositoryInterface - */ - private $_customerRepositoryInterface; - /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -345,7 +340,6 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface * @param OrderItemRepositoryInterface $itemRepository * @param SearchCriteriaBuilder $searchCriteriaBuilder * @param ScopeConfigInterface $scopeConfig - * @param CustomerRepositoryInterface $customerRepositoryInterface * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -372,7 +366,6 @@ public function __construct( \Magento\Sales\Model\ResourceModel\Order\Shipment\Track\CollectionFactory $trackCollectionFactory, \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $salesOrderCollectionFactory, PriceCurrencyInterface $priceCurrency, - CustomerRepositoryInterface $customerRepositoryInterface, \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productListFactory, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, @@ -410,7 +403,6 @@ public function __construct( $this->searchCriteriaBuilder = $searchCriteriaBuilder ?: ObjectManager::getInstance() ->get(SearchCriteriaBuilder::class); $this->scopeConfig = $scopeConfig ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class); - $this->_customerRepositoryInterface = $customerRepositoryInterface; parent::__construct( $context, @@ -570,19 +562,6 @@ public function getStore() return $this->_storeManager->getStore(); } - /** - * Returns Customer - * - * @return \Magento\Customer\Api\Data\CustomerInterface - * @throws LocalizedException - * @throws \Magento\Framework\Exception\NoSuchEntityException - */ - public function getCustomer() - { - $customerId = $this->getData(OrderInterface::CUSTOMER_ID); - return $this->_customerRepositoryInterface->getById($customerId); - } - /** * Retrieve order cancel availability * From c8baed5750f705531e75573ac8a1977dd6fe7d5f Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Wed, 5 Feb 2020 13:57:49 +0200 Subject: [PATCH 099/176] MC-30963: [Magento Cloud] CMS blocks with identical identifiers --- .../Magento/Cms/Model/ResourceModel/Block.php | 17 +++++------------ .../Test/Mftf/Test/CheckStaticBlocksTest.xml | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/Cms/Model/ResourceModel/Block.php b/app/code/Magento/Cms/Model/ResourceModel/Block.php index 30e817713755c..1324b9bd127e9 100644 --- a/app/code/Magento/Cms/Model/ResourceModel/Block.php +++ b/app/code/Magento/Cms/Model/ResourceModel/Block.php @@ -185,13 +185,9 @@ public function getIsUniqueBlockToStores(AbstractModel $object) $entityMetadata = $this->metadataPool->getMetadata(BlockInterface::class); $linkField = $entityMetadata->getLinkField(); - $stores = (array)$object->getData('store_id'); - $isDefaultStore = $this->_storeManager->isSingleStoreMode() - || array_search(Store::DEFAULT_STORE_ID, $stores) !== false; - - if (!$isDefaultStore) { - $stores[] = Store::DEFAULT_STORE_ID; - } + $stores = $this->_storeManager->isSingleStoreMode() + ? [Store::DEFAULT_STORE_ID] + : (array)$object->getData('store_id'); $select = $this->getConnection()->select() ->from(['cb' => $this->getMainTable()]) @@ -200,11 +196,8 @@ public function getIsUniqueBlockToStores(AbstractModel $object) 'cb.' . $linkField . ' = cbs.' . $linkField, [] ) - ->where('cb.identifier = ? ', $object->getData('identifier')); - - if (!$isDefaultStore) { - $select->where('cbs.store_id IN (?)', $stores); - } + ->where('cb.identifier = ? ', $object->getData('identifier')) + ->where('cbs.store_id IN (?)', $stores); if ($object->getId()) { $select->where('cb.' . $entityMetadata->getIdentifierField() . ' <> ?', $object->getId()); diff --git a/app/code/Magento/Cms/Test/Mftf/Test/CheckStaticBlocksTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/CheckStaticBlocksTest.xml index e6ab1c130606b..385616dcca9b9 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/CheckStaticBlocksTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/CheckStaticBlocksTest.xml @@ -56,12 +56,23 @@ <seeInCurrentUrl url="cms/block/new" stepKey="VerifyNewBlockPageIsOpened1"/> <!--Add new BLock with the same data--> <actionGroup ref="FillOutBlockContent" stepKey="FillOutBlockContent1"/> - <selectOption selector="{{BlockNewPageBasicFieldsSection.storeView}}" userInput="Default Store View" stepKey="selectDefaultStoreView" /> - <selectOption selector="{{BlockNewPageBasicFieldsSection.storeView}}" userInput="{{customStore.name}}" stepKey="selectSecondStoreView1" /> <click selector="{{BlockNewPagePageActionsSection.saveBlock}}" stepKey="ClickToSaveBlock1"/> <waitForPageLoad stepKey="waitForPageLoad6"/> <!--Verify that corresponding message is displayed--> <see userInput="A block identifier with the same properties already exists in the selected store." stepKey="VerifyBlockIsSaved1"/> + <!--Click to go back and add new block--> + <click selector="{{BlockNewPagePageActionsSection.back}}" stepKey="ClickToGoBack1"/> + <waitForPageLoad stepKey="waitForPageLoad7"/> + <click selector="{{BlockPageActionsSection.addNewBlock}}" stepKey="ClickToAddNewBlock2"/> + <waitForPageLoad stepKey="waitForPageLoad8"/> + <seeInCurrentUrl url="cms/block/new" stepKey="VerifyNewBlockPageIsOpened2"/> + <!--Add new BLock with the same data for another store view--> + <actionGroup ref="FillOutBlockContent" stepKey="FillOutBlockContent2"/> + <selectOption selector="{{BlockNewPageBasicFieldsSection.storeView}}" userInput="Default Store View" stepKey="selectDefaultStoreView" /> + <selectOption selector="{{BlockNewPageBasicFieldsSection.storeView}}" userInput="{{customStore.name}}" stepKey="selectSecondStoreView1" /> + <click selector="{{BlockNewPagePageActionsSection.saveBlock}}" stepKey="ClickToSaveBlock2"/> + <waitForPageLoad stepKey="waitForPageLoad9"/> + <see userInput="You saved the block." stepKey="VerifyBlockIsSaved2"/> <after> <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="DeleteWebsite"> From 9f9331f8ff926f3be71a56feb26e9a24a49413dc Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 5 Feb 2020 14:59:29 +0200 Subject: [PATCH 100/176] MC-30682: [FT] [MFTF] [2.4] Fix flaky test AdminCreateVirtualProductWithTierPriceForGeneralGroupTest (MC-6033) --- ...AdvancedPricingAddTierPriceActionGroup.xml | 34 ++++ ...mCloseAdvancedPricingDialogActionGroup.xml | 19 +++ ...rmDoneAdvancedPricingDialogActionGroup.xml | 19 +++ ...rmOpenAdvancedPricingDialogActionGroup.xml | 20 +++ ...vancedPricingCheckTierPriceActionGroup.xml | 32 ++++ .../SetProductUrlKeyByStringActionGroup.xml | 2 +- .../Catalog/Test/Mftf/Data/ProductData.xml | 1 + ...AdminProductFormAdvancedPricingSection.xml | 8 + ...roductWithTierPriceForGeneralGroupTest.xml | 157 ++++++++---------- 9 files changed, 200 insertions(+), 92 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml new file mode 100644 index 0000000000000..f823db0a86548 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminProductFormAdvancedPricingAddTierPriceActionGroup"> + <annotations> + <description>Add new tier price on Advanced Pricing dialog on the Admin Product creation/edit page.</description> + </annotations> + <arguments> + <argument name="website" type="string" defaultValue="All Websites [USD]"/> + <argument name="customerGroup" type="string" defaultValue="ALL GROUPS"/> + <argument name="quantity" type="string" defaultValue="1"/> + <argument name="priceType" type="string" defaultValue="Fixed"/> + <argument name="amount" type="string" defaultValue="10"/> + </arguments> + + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="waitForGroupPriceAddButtonAppears"/> + <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="clickCustomerGroupPriceAddButton"/> + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceWebsite}}" stepKey="waitForPriceWebsiteInputAppears"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceWebsite}}" userInput="{{website}}" stepKey="selectWebsite"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceCustomerGroup}}" userInput="{{customerGroup}}" stepKey="selectCustomerGroup"/> + <fillField selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceQty}}" userInput="{{quantity}}" stepKey="fillQuantity"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceType}}" userInput="{{priceType}}" stepKey="selectPriceType"/> + <executeJS function="return '{{priceType}}' == 'Discount' ? "{{AdminProductFormAdvancedPricingSection.lastTierPriceDiscountAmount}}" : "{{AdminProductFormAdvancedPricingSection.lastTierPriceFixedAmount}}"" stepKey="priceAmountSelector"/> + <waitForElementVisible selector="{$priceAmountSelector}" stepKey="waitPriceAmountFieldAppers"/> + <fillField selector="{$priceAmountSelector}" userInput="{{amount}}" stepKey="fillPriceAmount"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml new file mode 100644 index 0000000000000..03c98c1cb17b7 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminProductFormCloseAdvancedPricingDialogActionGroup"> + <annotations> + <description>Close Advanced Pricing dialog from product form.</description> + </annotations> + + <scrollToTopOfPage stepKey="scrollToTopOfThePage"/> + <click selector="{{AdminProductFormAdvancedPricingSection.advancedPricingCloseButton}}" stepKey="clickCloseButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml new file mode 100644 index 0000000000000..10f2d32799200 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminProductFormDoneAdvancedPricingDialogActionGroup"> + <annotations> + <description>Done Advanced Pricing dialog from product form.</description> + </annotations> + + <scrollToTopOfPage stepKey="scrollToTopOfThePage"/> + <click selector="{{AdminProductFormAdvancedPricingSection.doneButton}}" stepKey="clickDoneButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml new file mode 100644 index 0000000000000..1c96ce3469485 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminProductFormOpenAdvancedPricingDialogActionGroup"> + <annotations> + <description>Open Advanced Pricing dialog from product form.</description> + </annotations> + + <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink"/> + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.modalTitle}}" stepKey="waitForModalTitleAppears"/> + <see selector="{{AdminProductFormAdvancedPricingSection.modalTitle}}" userInput="Advanced Pricing" stepKey="checkModalTitle"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml new file mode 100644 index 0000000000000..42aee90882400 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup"> + <annotations> + <description>Check AdvancedPricing tier price row.</description> + </annotations> + <arguments> + <argument name="rowNumber" type="string" defaultValue="0"/> + <argument name="website" type="string" defaultValue="All Websites [USD]"/> + <argument name="customerGroup" type="string" defaultValue="ALL GROUPS"/> + <argument name="quantity" type="string" defaultValue="1"/> + <argument name="priceType" type="string" defaultValue="Fixed"/> + <argument name="amount" type="string" defaultValue="10"/> + </arguments> + + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect(rowNumber)}}" stepKey="waitForPricesGridAppears"/> + <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect(rowNumber)}}" userInput="{{website}}" stepKey="seeWebsite"/> + <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect(rowNumber)}}" userInput="{{customerGroup}}" stepKey="seeCustomerGroup"/> + <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput(rowNumber)}}" userInput="{{quantity}}" stepKey="seeQuantity"/> + <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceValueTypeSelect(rowNumber)}}" userInput="{{priceType}}" stepKey="seePriceType"/> + <executeJS function="return '{{priceType}}' == 'Discount' ? "{{AdminProductFormAdvancedPricingSection.productTierPricePercentageValuePriceInput(rowNumber)}}" : "{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput(rowNumber)}}"" stepKey="priceAmountSelector"/> + <seeInField selector="{$priceAmountSelector}" userInput="{{amount}}" stepKey="seePriceAmount"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SetProductUrlKeyByStringActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SetProductUrlKeyByStringActionGroup.xml index d4c654523a40b..1882063081f04 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SetProductUrlKeyByStringActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SetProductUrlKeyByStringActionGroup.xml @@ -16,7 +16,7 @@ <argument name="urlKey" type="string"/> </arguments> - <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="openSeoSection"/> + <conditionalClick selector="{{AdminProductSEOSection.sectionHeader}}" dependentSelector="{{AdminProductSEOSection.urlKeyInput}}" visible="false" stepKey="openSeoSection"/> <fillField userInput="{{urlKey}}" selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="fillUrlKey"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 46bb6e527608f..bc04b3b1dcd0b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -756,6 +756,7 @@ <data key="status">In Stock</data> <data key="visibility">Catalog, Search</data> <data key="urlKey" unique="suffix">virtual-product</data> + <data key="storefrontStatus">IN STOCK</data> <data key="type_id">virtual</data> </entity> <entity name="virtualProductCustomImportOptions" type="product"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml index 77b89a07fb76a..91ac52a91a4c4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml @@ -25,5 +25,13 @@ <element name="msrp" type="input" selector="//input[@name='product[msrp]']" timeout="30"/> <element name="msrpType" type="select" selector="//select[@name='product[msrp_display_actual_price_type]']" timeout="30"/> <element name="save" type="button" selector="#save-button" timeout="30"/> + <element name="modalTitle" type="text" selector="aside.product_form_product_form_advanced_pricing_modal h1.modal-title"/> + <!-- Last row tier price elements--> + <element name="lastTierPriceWebsite" type="select" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[website_id]']"/> + <element name="lastTierPriceCustomerGroup" type="select" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[cust_group]']"/> + <element name="lastTierPriceQty" type="input" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[price_qty]']"/> + <element name="lastTierPriceType" type="select" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[value_type]']"/> + <element name="lastTierPriceFixedAmount" type="input" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[price]']"/> + <element name="lastTierPriceDiscountAmount" type="input" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[percentage_value]']"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml index 4c3d519106389..e4e52272e5935 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminCreateVirtualProductWithTierPriceForGeneralGroupTest"> <annotations> + <features value="Catalog"/> <stories value="Create virtual product"/> <title value="Create virtual product with tier price for General group"/> <description value="Test log in to Create virtual product and Create virtual product with tier price for General group"/> @@ -17,122 +18,96 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-30682"/> - </skip> </annotations> <before> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <createData entity="SimpleSubCategory" stepKey="categoryEntity"/> <createData entity="Simple_US_CA_Customer" stepKey="customer" /> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> + <deleteData stepKey="deleteSimpleSubCategory" createDataKey="categoryEntity"/> + <deleteData stepKey="deleteCustomer" createDataKey="customer"/> <actionGroup ref="DeleteProductUsingProductGridActionGroup" stepKey="deleteVirtualProduct"> <argument name="product" value="virtualProductGeneralGroup"/> </actionGroup> - <deleteData stepKey="deleteSimpleSubCategory" createDataKey="categoryEntity"/> - <deleteData stepKey="deleteCustomer" createDataKey="customer"/> - <actionGroup ref="logout" stepKey="logout"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessageAppears"/> + <see selector="{{AdminMessagesSection.success}}" userInput="A total of 1 record(s) have been deleted." stepKey="seeSuccessMessage"/> + <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearFiltersAfter"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </after> - <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage"/> - <waitForPageLoad stepKey="waitForProductCatalogPage"/> - <click selector="{{AdminProductGridActionSection.addProductToggle}}" stepKey="clickAddProductToggle"/> - <waitForPageLoad stepKey="waitForProductToggleToSelectProduct"/> - <click selector="{{AdminProductGridActionSection.addVirtualProduct}}" stepKey="clickVirtualProduct"/> - - <!-- Create virtual product with tier price for general group --> - <fillField selector="{{AdminProductFormSection.productName}}" userInput="{{virtualProductGeneralGroup.name}}" stepKey="fillProductName"/> - <fillField selector="{{AdminProductFormSection.productSku}}" userInput="{{virtualProductGeneralGroup.sku}}" stepKey="fillProductSku"/> - <fillField selector="{{AdminProductFormSection.productPrice}}" userInput="{{virtualProductGeneralGroup.price}}" stepKey="fillProductPrice"/> - <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink"/> - <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="clickCustomerGroupPriceAddButton"/> - <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect('0')}}" userInput="{{tierPriceOnGeneralGroup.website}}" stepKey="selectProductTierPriceWebsite"/> - <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" userInput="{{tierPriceOnGeneralGroup.customer_group}}" stepKey="selectProductTierPriceGroup"/> - <scrollTo selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput('0')}}" x="50" y="0" stepKey="scrollToProductTierPriceQuantityInputTextBox"/> - <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput('0')}}" userInput="{{tierPriceOnGeneralGroup.qty}}" stepKey="fillProductTierPriceQuantityInput"/> - <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput('0')}}" userInput="{{tierPriceOnGeneralGroup.price}}" stepKey="fillProductTierPriceFixedPrice"/> - <click selector="{{AdminProductFormAdvancedPricingSection.doneButton}}" stepKey="clickDoneButton"/> - <selectOption selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{virtualProductGeneralGroup.productTaxClass}}" stepKey="selectProductTaxClass"/> - <fillField selector="{{AdminProductFormSection.productQuantity}}" userInput="{{virtualProductGeneralGroup.quantity}}" stepKey="fillProductQuantity"/> - <click selector="{{AdminProductFormSection.productStockStatus}}" stepKey="clickProductStockStatus"/> - <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> - <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> - <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> - <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> + <!-- Create virtual product--> + <amOnPage url="{{AdminProductCreatePage.url(AddToDefaultSet.attributeSetId,'virtual')}}" stepKey="openVirtualProductCreatePage"/> + <actionGroup ref="FillMainProductFormNoWeightActionGroup" stepKey="fillNewProductData"> + <argument name="product" value="virtualProductGeneralGroup"/> + </actionGroup> + <actionGroup ref="AdminProductFormOpenAdvancedPricingDialogActionGroup" stepKey="openAdvancedPricingDialog"/> + <actionGroup ref="AdminProductFormAdvancedPricingAddTierPriceActionGroup" stepKey="addTierPrice"> + <argument name="website" value="{{tierPriceOnGeneralGroup.website}}"/> + <argument name="customerGroup" value="{{tierPriceOnGeneralGroup.customer_group}}"/> + <argument name="quantity" value="{{tierPriceOnGeneralGroup.qty}}"/> + <argument name="priceType" value="Fixed"/> + <argument name="amount" value="{{tierPriceOnGeneralGroup.price}}"/> + </actionGroup> + <actionGroup ref="AdminProductFormDoneAdvancedPricingDialogActionGroup" stepKey="doneAdvancedPricingModal"/> + <selectOption selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{virtualProductGeneralGroup.productTaxClass}}" stepKey="selectProductStockClass"/> + <actionGroup ref="SetCategoryByNameActionGroup" stepKey="setNewCategory"> + <argument name="categoryName" value="$categoryEntity.name$"/> + </actionGroup> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{virtualProductGeneralGroup.visibility}}" stepKey="selectVisibility"/> - <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSectionHeader"/> - <fillField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{virtualProductGeneralGroup.urlKey}}" stepKey="fillUrlKeyInput"/> - <scrollToTopOfPage stepKey="scrollToTopOfAdminProductFormSection"/> - <click selector="{{AdminProductFormSection.save}}" stepKey="clickSaveButton"/> - <waitForPageLoad stepKey="waitForVirtualProductSaved"/> - - <!-- Verify we see success message --> - <see selector="{{AdminProductFormSection.successMessage}}" userInput="You saved the product." stepKey="seeAssertVirtualProductSuccessMessage"/> + <actionGroup ref="SetProductUrlKeyByStringActionGroup" stepKey="updateUrlKey"> + <argument name="urlKey" value="{{virtualProductGeneralGroup.urlKey}}"/> + </actionGroup> + <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProductAndCheckSuccessMessage"/> - <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage1"/> - <waitForPageLoad stepKey="waitForProductCatalogPage1"/> - <conditionalClick selector="{{AdminProductGridFilterSection.clearAll}}" dependentSelector="{{AdminProductGridFilterSection.clearAll}}" visible="true" stepKey="checkRetailCustomerTaxClass" /> - <fillField selector="{{AdminProductGridFilterSection.keywordSearch}}" userInput="{{virtualProductGeneralGroup.name}}" stepKey="fillVirtualProductName"/> - <click selector="{{AdminProductGridFilterSection.keywordSearchButton}}" stepKey="clickKeywordSearchButton"/> - <waitForPageLoad stepKey="waitForProductSearch"/> - <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowToVerifyCreatedVirtualProduct"/> - <waitForPageLoad stepKey="waitUntilProductIsOpened"/> + <!-- Search created virtual product(from above steps) in the grid --> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> + <argument name="product" value="virtualProductGeneralGroup"/> + </actionGroup> - <!-- Verify we see created virtual product with tier price for general group(from the above step) in the product form page --> - <seeInField selector="{{AdminProductFormSection.productName}}" userInput="{{virtualProductGeneralGroup.name}}" stepKey="seeProductName"/> - <seeInField selector="{{AdminProductFormSection.productSku}}" userInput="{{virtualProductGeneralGroup.sku}}" stepKey="seeProductSku"/> - <seeInField selector="{{AdminProductFormSection.productPrice}}" userInput="{{virtualProductGeneralGroup.price}}" stepKey="seeProductPrice"/> - <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink1"/> - <seeOptionIsSelected selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect('0')}}" userInput="{{tierPriceOnGeneralGroup.website}}" stepKey="seeProductTierPriceWebsite"/> - <seeOptionIsSelected selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" userInput="{{tierPriceOnGeneralGroup.customer_group}}" stepKey="seeProductTierPriceGroup"/> - <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput('0')}}" userInput="{{tierPriceOnGeneralGroup.qty}}" stepKey="seeProductTierPriceQuantityInput"/> - <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput('0')}}" userInput="{{tierPriceOnGeneralGroup.price}}" stepKey="seeProductTierPriceFixedPrice"/> - <click selector="{{AdminProductFormAdvancedPricingSection.advancedPricingCloseButton}}" stepKey="clickAdvancedPricingCloseButton"/> + <!-- Verify customer see created virtual product with tier price in the product form page --> + <actionGroup ref="AssertProductInfoOnEditPageActionGroup" stepKey="verifyProductInAdminEditForm"> + <argument name="product" value="virtualProductGeneralGroup"/> + </actionGroup> + <actionGroup ref="AdminProductFormOpenAdvancedPricingDialogActionGroup" stepKey="openAdvancedPricingDialogAgain"/> + <actionGroup ref="AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup" stepKey="checkTierPrice"> + <argument name="rowNumber" value="0"/> + <argument name="website" value="{{tierPriceOnGeneralGroup.website}}"/> + <argument name="customerGroup" value="{{tierPriceOnGeneralGroup.customer_group}}"/> + <argument name="quantity" value="{{tierPriceOnGeneralGroup.qty}}"/> + <argument name="priceType" value="Fixed"/> + <argument name="amount" value="{{tierPriceOnGeneralGroup.price}}"/> + </actionGroup> + <actionGroup ref="AdminProductFormCloseAdvancedPricingDialogActionGroup" stepKey="closeAdvancedPricingModal"/> <seeInField selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{virtualProductGeneralGroup.productTaxClass}}" stepKey="seeProductTaxClass"/> - <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="{{virtualProductGeneralGroup.quantity}}" stepKey="seeProductQuantity"/> - <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="{{virtualProductGeneralGroup.status}}" stepKey="seeProductStockStatus"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> - <grabMultiple selector="{{AdminProductFormSection.selectMultipleCategories}}" stepKey="selectedCategories" /> + <grabMultiple selector="{{AdminProductFormSection.selectMultipleCategories}}" stepKey="selectedCategories"/> <assertEquals stepKey="assertSelectedCategories"> <actualResult type="variable">selectedCategories</actualResult> - <expectedResult type="array">[$$categoryEntity.name$$]</expectedResult> + <expectedResult type="array">[$categoryEntity.name$]</expectedResult> </assertEquals> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneOnCategorySelect"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{virtualProductGeneralGroup.visibility}}" stepKey="seeVisibility"/> - <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> - <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> + <conditionalClick selector="{{AdminProductSEOSection.sectionHeader}}" dependentSelector="{{AdminProductSEOSection.useDefaultUrl}}" visible="false" stepKey="openSearchEngineOptimizationSection"/> + <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="scrollToAdminProductSEOSection"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{virtualProductGeneralGroup.urlKey}}" stepKey="seeUrlKey"/> - <!--Verify customer see created virtual product on category page --> - <amOnPage url="{{StorefrontCategoryPage.url($$categoryEntity.name$$)}}" stepKey="openCategoryPage"/> - <waitForPageLoad stepKey="waitForCategoryPageToLoad"/> - <see selector="{{StorefrontCategoryMainSection.productLink}}" userInput="{{virtualProductGeneralGroup.name}}" stepKey="seeVirtualProductNameOnCategoryPage"/> + <!--Verify customer see created virtual product link on category page --> + <actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="openCategoryPageOnFrontend"> + <argument name="category" value="$categoryEntity$"/> + </actionGroup> + <actionGroup ref="AssertProductOnCategoryPageActionGroup" stepKey="checkProductOnCategoryPage"> + <argument name="product" value="virtualProductGeneralGroup"/> + </actionGroup> - <!-- Verify customer see created virtual product with tier price for general group(from above step) in storefront page with customer --> + <!--Verify customer see updated virtual product with tier price on product storefront page --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer"> - <argument name="Customer" value="$$customer$$" /> + <argument name="Customer" value="$customer$" /> </actionGroup> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefront"/> - <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{virtualProductGeneralGroup.name}}" stepKey="fillVirtualProductNameInSearchTextBox"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{virtualProductGeneralGroup.name}}" stepKey="seeVirtualProductName"/> - <grabTextFrom selector="{{StorefrontQuickSearchResultsSection.asLowAsLabel}}" stepKey="tierPriceTextOnStorefrontPage"/> - - <!-- Verify customer see created virtual product with tier price --> - <assertEquals stepKey="assertTierPriceTextOnCategoryPage"> - <expectedResult type="string">As low as ${{tierPriceOnGeneralGroup.price}}</expectedResult> - <actualResult type="variable">tierPriceTextOnStorefrontPage</actualResult> - </assertEquals> - <click selector="{{StorefrontQuickSearchResultsSection.productLink}}" stepKey="openSearchedProduct"/> - <waitForPageLoad stepKey="waitForProductPageToBeLoaded"/> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.tierPriceText}}" stepKey="tierPriceText"/> - <assertEquals stepKey="assertTierPriceTextOnProductPage"> - <expectedResult type="string">Buy {{tierPriceOnGeneralGroup.qty}} for ${{tierPriceOnGeneralGroup.price}} each and save 20%</expectedResult> - <actualResult type="variable">tierPriceText</actualResult> - </assertEquals> + <actionGroup ref="AssertProductInStorefrontProductPageActionGroup" stepKey="verifyProductOnFrontend"> + <argument name="product" value="virtualProductGeneralGroup"/> + </actionGroup> + <see selector="{{StorefrontProductInfoMainSection.productStockStatus}}" userInput="{{virtualProductGeneralGroup.storefrontStatus}}" stepKey="assertStockAvailableOnProductPage"/> + <see selector="{{StorefrontProductInfoMainSection.tierPriceText}}" userInput="Buy {{tierPriceOnGeneralGroup.qty}} for ${{tierPriceOnGeneralGroup.price}} each and save 20%" stepKey="assertTierPriceTextOnProductPage"/> </test> </tests> From 10363f51cf0b90f99e242601ad0a548bb787c02b Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Wed, 5 Feb 2020 16:25:50 +0200 Subject: [PATCH 101/176] Unit test for \Magento\Captcha\Observer\ResetAttemptForBackendObserver and \Magento\Captcha\Observer\ResetAttemptForFrontendObserver --- .../ResetAttemptForBackendObserverTest.php | 53 +++++++++++++++++++ .../ResetAttemptForFrontendObserverTest.php | 52 ++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php create mode 100644 app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php new file mode 100644 index 0000000000000..b7a0c9534598d --- /dev/null +++ b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Captcha\Test\Unit\Observer; + +use Magento\Captcha\Model\ResourceModel\Log; +use Magento\Captcha\Model\ResourceModel\LogFactory; +use Magento\Captcha\Observer\ResetAttemptForBackendObserver; +use Magento\Framework\Event; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for \Magento\Captcha\Observer\ResetAttemptForBackendObserver + */ +class ResetAttemptForBackendObserverTest extends TestCase +{ + /** + * Test that the method resets attempts for Backend + */ + public function testExecuteExpectsDeleteUserAttemptsCalled() + { + $logMock = $this->createMock(Log::class); + $logMock->expects($this->once())->method('deleteUserAttempts'); + + $resLogFactoryMock = $this->createMock(LogFactory::class); + $resLogFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($logMock); + + /** @var MockObject|Observer $eventObserverMock */ + $eventObserverMock = $this->createPartialMock(Observer::class, ['getUser']); + $eventMock = $this->createMock(Event::class); + $eventObserverMock->expects($this->once()) + ->method('getUser') + ->willReturn($eventMock); + + $objectManager = new ObjectManagerHelper($this); + /** @var ResetAttemptForBackendObserver $observer */ + $observer = $objectManager->getObject( + ResetAttemptForBackendObserver::class, + ['resLogFactory' => $resLogFactoryMock] + ); + $observer->execute($eventObserverMock); + } +} diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php new file mode 100644 index 0000000000000..f83341eb8680d --- /dev/null +++ b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Captcha\Test\Unit\Observer; + +use Magento\Captcha\Model\ResourceModel\Log; +use Magento\Captcha\Model\ResourceModel\LogFactory; +use Magento\Captcha\Observer\ResetAttemptForFrontendObserver; +use Magento\Customer\Model\Customer; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for \Magento\Captcha\Observer\ResetAttemptForFrontendObserver + */ +class ResetAttemptForFrontendObserverTest extends TestCase +{ + /** + * Test that the method resets attempts for Frontend + */ + public function testExecuteExpectsDeleteUserAttemptsCalled() + { + $logMock = $this->createMock(Log::class); + $logMock->expects($this->once())->method('deleteUserAttempts'); + + $resLogFactoryMock = $this->createMock(LogFactory::class); + $resLogFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($logMock); + + /** @var MockObject|Observer $eventObserverMock */ + $eventObserverMock = $this->createPartialMock(Observer::class, ['getModel']); + $eventObserverMock->expects($this->once()) + ->method('getModel') + ->willReturn($this->createMock(Customer::class)); + + $objectManager = new ObjectManagerHelper($this); + /** @var ResetAttemptForFrontendObserver $observer */ + $observer = $objectManager->getObject( + ResetAttemptForFrontendObserver::class, + ['resLogFactory' => $resLogFactoryMock] + ); + $observer->execute($eventObserverMock); + } +} From f3c8d794eef3621f7a2081376b94c9c36d77c89f Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Wed, 5 Feb 2020 18:37:21 +0200 Subject: [PATCH 102/176] MC-31083: [FT] [MFTF] Fix test AdminCreateImageSwatchTest - delete created swatch attribute in after --- ...leteProductAttributeByLabelActionGroup.xml | 31 +++++++++++++++++++ ...leteProductAttributeByLabelActionGroup.xml | 2 +- .../Mftf/Test/AdminCreateImageSwatchTest.xml | 8 ++++- 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml new file mode 100644 index 0000000000000..7898fae279eaf --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminDeleteProductAttributeByLabelActionGroup"> + <annotations> + <description>Goes to the Admin Product Attributes grid page. Filters the grid for the provided Product Attribute (Label). Deletes the Product Attribute from the grid. Validates that the Success Message is present.</description> + </annotations> + <arguments> + <argument name="productAttributeLabel" type="string"/> + </arguments> + + <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid"/> + <waitForPageLoad stepKey="waitForProductAttributeGridPageLoad"/> + <fillField selector="{{AdminProductAttributeGridSection.attributeLabelFilter}}" userInput="{{productAttributeLabel}}" stepKey="setAttributeLabelFilter"/> + <click selector="{{AdminProductAttributeGridSection.Search}}" stepKey="searchForAttributeLabelFromTheGrid"/> + <click selector="{{AdminProductAttributeGridSection.FirstRow}}" stepKey="clickOnAttributeRow"/> + <click selector="{{AttributePropertiesSection.DeleteAttribute}}" stepKey="clickOnDeleteAttributeButton"/> + <waitForElementVisible selector="{{ModalConfirmationSection.modalContent}}" stepKey="waitForConfirmationPopUpVisible"/> + <click selector="{{ModalConfirmationSection.OkButton}}" stepKey="clickOnConfirmationButton"/> + <waitForPageLoad stepKey="waitForAttributeGridPageLoad"/> + <waitForElementVisible selector="{{AdminProductMessagesSection.successMessage}}" stepKey="waitForSuccessMessageVisible"/> + <see selector="{{AdminProductMessagesSection.successMessage}}" userInput="You deleted the product attribute." stepKey="seeAttributeDeleteSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/DeleteProductAttributeByLabelActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/DeleteProductAttributeByLabelActionGroup.xml index fb78909eab0b6..15c3d55fb9382 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/DeleteProductAttributeByLabelActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/DeleteProductAttributeByLabelActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="DeleteProductAttributeByLabelActionGroup"> <annotations> - <description>Goes to the Admin Product Attributes grid page. Filters the grid for the provided Product Attribute (Label). Deletes the Product Attribute from the grid. Validates that the Success Message is present.</description> + <description>DEPRECATED. Please use AdminDeleteProductAttributeByLabelActionGroup instead. Goes to the Admin Product Attributes grid page. Filters the grid for the provided Product Attribute (Label). Deletes the Product Attribute from the grid. Validates that the Success Message is present.</description> </annotations> <arguments> <argument name="ProductAttribute"/> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml index 8a2683af83dc1..34eaa2f34ba17 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml @@ -24,7 +24,13 @@ </before> <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct"> + <argument name="sku" value="{{BaseConfigurableProduct.sku}}"/> + </actionGroup> + <actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteProductAttribute"> + <argument name="productAttributeLabel" value="{{ProductAttributeFrontendLabel.label}}"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </after> <!-- Begin creating a new product attribute of type "Image Swatch" --> From 4e1bfdeda9d7da91509a3f738e881ad92614a577 Mon Sep 17 00:00:00 2001 From: Adarsh Manickam <adarsh.apple@icloud.com> Date: Wed, 5 Feb 2020 18:51:18 +0530 Subject: [PATCH 103/176] Deprecated redundant class --- .../Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php index 4dbc10308f3be..c6b40800d5160 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php @@ -17,8 +17,10 @@ use Magento\Framework\DataObject; /** - * Class ShipmentSender + * Class for shipment email notification sender * + * @deprecated since this class works only with the concrete model and no data interface + * @see \Magento\Sales\Model\Order\Shipment\Sender\EmailSender * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ShipmentSender extends Sender From 0f041810595f18e7d6909ec9a6b0c1897efb7f8f Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Fri, 24 Jan 2020 14:40:56 -0600 Subject: [PATCH 104/176] MQE-1965: Paypal test leveraging AWS Secrets Manager - PayPalSmartButtonInCheckoutPage Unskipped and fixed selectors to test AWS Secret Manager CI --- .../StorefrontPayOrderOnPayPalCheckoutActionGroup.xml | 1 + .../Mftf/Section/PayPalExpressCheckoutConfigSection.xml | 8 ++++---- .../StorefrontPaypalSmartButtonInCheckoutPageTest.xml | 3 --- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayOrderOnPayPalCheckoutActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayOrderOnPayPalCheckoutActionGroup.xml index 392014d876e46..b7ebf7dab1c8b 100644 --- a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayOrderOnPayPalCheckoutActionGroup.xml +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayOrderOnPayPalCheckoutActionGroup.xml @@ -16,6 +16,7 @@ <argument name="productName" type="string"/> </arguments> <click selector="{{PayPalPaymentSection.cartIcon}}" stepKey="openCart"/> + <waitForPageLoad stepKey="waitForCartLoad"/> <seeElement selector="{{PayPalPaymentSection.itemName(productName)}}" stepKey="seeProductName"/> <click selector="{{PayPalPaymentSection.PayPalSubmitBtn}}" stepKey="clickPayPalSubmitBtn"/> <switchToPreviousTab stepKey="switchToPreviousTab"/> diff --git a/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection.xml b/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection.xml index af68a7611cd1d..a1610926b3f36 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection.xml @@ -57,10 +57,10 @@ <element name="email" type="input" selector="//input[contains(@name, 'email') and not(contains(@style, 'display:none'))]"/> <element name="password" type="input" selector="//input[contains(@name, 'password') and not(contains(@style, 'display:none'))]"/> <element name="loginBtn" type="input" selector="button#btnLogin"/> - <element name="reviewUserInfo" type="text" selector="#reviewUserInfo"/> - <element name="cartIcon" type="text" selector="#transactionCart"/> - <element name="itemName" type="text" selector="//span[@title='{{productName}}']" parameterized="true"/> - <element name="PayPalSubmitBtn" type="text" selector="//input[@type='submit']"/> + <element name="reviewUserInfo" type="text" selector="[data-testid=personalized-banner-content]"/> + <element name="cartIcon" type="text" selector="[data-testid='header-show-cart-dropdown-btn']"/> + <element name="itemName" type="text" selector="//p[contains(@class,'CartDropdown_line') and text()='{{productName}}']" parameterized="true"/> + <element name="PayPalSubmitBtn" type="text" selector="#payment-submit-btn"/> <element name="nextButton" type="button" selector="#btnNext"/> <element name="continueButton" type="button" selector=".continueButton"/> </section> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml index 6adba94e96890..fea1cf3966b99 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml @@ -16,9 +16,6 @@ <description value="Users are able to place order using Paypal Smart Button"/> <severity value="CRITICAL"/> <testCaseId value="MC-13690"/> - <skip> - <issueId value="DEVOPS-3311"/> - </skip> <group value="paypal"/> </annotations> <before> From dc12da03725effe3acc36ce223351338dc017b88 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Wed, 5 Feb 2020 14:42:52 -0600 Subject: [PATCH 105/176] MQE-1987: Bump MFTF version and deliver Magento branches 2.6.0 version bump + paypal test --- composer.json | 2 +- composer.lock | 170 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 159 insertions(+), 13 deletions(-) diff --git a/composer.json b/composer.json index 9cbbf1689738f..577987067dc76 100644 --- a/composer.json +++ b/composer.json @@ -88,7 +88,7 @@ "friendsofphp/php-cs-fixer": "~2.14.0", "lusitanian/oauth": "~0.8.10", "magento/magento-coding-standard": "*", - "magento/magento2-functional-testing-framework": "2.5.4", + "magento/magento2-functional-testing-framework": "2.6.0", "pdepend/pdepend": "2.5.2", "phpcompatibility/php-compatibility": "^9.3", "phpmd/phpmd": "@stable", diff --git a/composer.lock b/composer.lock index 5b94f60fa80a9..dd59126b96caa 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "988eebffd81167973e4a51d7efd5be46", + "content-hash": "27452593216dfff37ed2a7f2aea0237c", "packages": [ { "name": "braintree/braintree_php", @@ -830,6 +830,7 @@ } ], "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", + "abandoned": true, "time": "2018-07-31T13:22:33+00:00" }, { @@ -880,6 +881,7 @@ "Guzzle", "stream" ], + "abandoned": true, "time": "2014-10-12T19:18:40+00:00" }, { @@ -5197,6 +5199,90 @@ ], "time": "2017-11-03T13:08:21+00:00" }, + { + "name": "aws/aws-sdk-php", + "version": "3.133.8", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "c564fcccd5fc7b5e8514d1cbe35558be1e3a11cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/c564fcccd5fc7b5e8514d1cbe35558be1e3a11cd", + "reference": "c564fcccd5fc7b5e8514d1cbe35558be1e3a11cd", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^5.3.3|^6.2.1|^7.0", + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4.1", + "mtdowling/jmespath.php": "^2.5", + "php": ">=5.5" + }, + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "nette/neon": "^2.3", + "phpunit/phpunit": "^4.8.35|^5.4.3", + "psr/cache": "^1.0", + "psr/simple-cache": "^1.0", + "sebastian/comparator": "^1.2.3" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Aws\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "time": "2020-02-05T19:12:47+00:00" + }, { "name": "behat/gherkin", "version": "v4.6.0", @@ -7356,26 +7442,29 @@ }, { "name": "magento/magento2-functional-testing-framework", - "version": "2.5.4", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/magento/magento2-functional-testing-framework.git", - "reference": "4f482ce22a755a812b76f81020ae71d502f9d043" + "reference": "3609f4fa57c6e9a2ee7c3d3b7c0f02e9becd8262" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/4f482ce22a755a812b76f81020ae71d502f9d043", - "reference": "4f482ce22a755a812b76f81020ae71d502f9d043", + "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/3609f4fa57c6e9a2ee7c3d3b7c0f02e9becd8262", + "reference": "3609f4fa57c6e9a2ee7c3d3b7c0f02e9becd8262", "shasum": "" }, "require": { "allure-framework/allure-codeception": "~1.3.0", + "aws/aws-sdk-php": "^3.132", "codeception/codeception": "~2.4.5", "composer/composer": "^1.4", "consolidation/robo": "^1.0.0", "csharpru/vault-php": "~3.5.3", "csharpru/vault-php-guzzle6-transport": "^2.0", "ext-curl": "*", + "ext-json": "*", + "ext-openssl": "*", "flow/jsonpath": ">0.2", "fzaninotto/faker": "^1.6", "monolog/monolog": "^1.0", @@ -7430,7 +7519,7 @@ "magento", "testing" ], - "time": "2019-12-12T20:14:00+00:00" + "time": "2020-02-05T15:53:02+00:00" }, { "name": "mikey179/vfsstream", @@ -7478,6 +7567,63 @@ "homepage": "http://vfs.bovigo.org/", "time": "2019-10-30T15:31:00+00:00" }, + { + "name": "mtdowling/jmespath.php", + "version": "2.5.0", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "52168cb9472de06979613d365c7f1ab8798be895" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/52168cb9472de06979613d365c7f1ab8798be895", + "reference": "52168cb9472de06979613d365c7f1ab8798be895", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "symfony/polyfill-mbstring": "^1.4" + }, + "require-dev": { + "composer/xdebug-handler": "^1.2", + "phpunit/phpunit": "^4.8.36|^7.5.15" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "JmesPath\\": "src/" + }, + "files": [ + "src/JmesPath.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "time": "2019-12-30T18:03:34+00:00" + }, { "name": "mustache/mustache", "version": "v2.13.0", @@ -8063,20 +8209,20 @@ "authors": [ { "name": "Manuel Pichler", + "role": "Project Founder", "email": "github@manuel-pichler.de", - "homepage": "https://github.com/manuelpichler", - "role": "Project Founder" + "homepage": "https://github.com/manuelpichler" }, { "name": "Marc Würth", + "role": "Project Maintainer", "email": "ravage@bluewin.ch", - "homepage": "https://github.com/ravage84", - "role": "Project Maintainer" + "homepage": "https://github.com/ravage84" }, { "name": "Other contributors", - "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", - "role": "Contributors" + "role": "Contributors", + "homepage": "https://github.com/phpmd/phpmd/graphs/contributors" } ], "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", From f8bcd47e0959bf34b1f2f01712c0488e0939e881 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Thu, 6 Feb 2020 09:05:09 +0200 Subject: [PATCH 106/176] Update getCustomer method in order class Fix static test --- app/code/Magento/Sales/Model/Order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 0a727b7560396..8a760065439d6 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -1326,7 +1326,7 @@ public function getTrackingNumbers() */ public function getShippingMethod($asObject = false) { - $shippingMethod = parent::getShippingMethod(); + $shippingMethod = $this->getData('shipping_method'); if (!$asObject || !$shippingMethod) { return $shippingMethod; } else { From 80c737a7287439876f73ab90c7fce7e1a5a43877 Mon Sep 17 00:00:00 2001 From: Fanis Strezos <fanis.strezos@dotdigital.com> Date: Thu, 6 Feb 2020 09:27:53 +0000 Subject: [PATCH 107/176] roll back changes --- app/code/Magento/Sales/Model/Order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 8a760065439d6..0a727b7560396 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -1326,7 +1326,7 @@ public function getTrackingNumbers() */ public function getShippingMethod($asObject = false) { - $shippingMethod = $this->getData('shipping_method'); + $shippingMethod = parent::getShippingMethod(); if (!$asObject || !$shippingMethod) { return $shippingMethod; } else { From 5a1f48e1cc590a9605c0ae82844e89a9b74e84f6 Mon Sep 17 00:00:00 2001 From: Fanis Strezos <fanis.strezos@dotdigital.com> Date: Thu, 6 Feb 2020 09:44:35 +0000 Subject: [PATCH 108/176] Revert "Update getCustomer method in order class" This reverts commit f8bcd47e0959bf34b1f2f01712c0488e0939e881. --- app/code/Magento/Sales/Model/Order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 8a760065439d6..0a727b7560396 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -1326,7 +1326,7 @@ public function getTrackingNumbers() */ public function getShippingMethod($asObject = false) { - $shippingMethod = $this->getData('shipping_method'); + $shippingMethod = parent::getShippingMethod(); if (!$asObject || !$shippingMethod) { return $shippingMethod; } else { From 3ca45d8efa0a2a79c207451428b845d34c1addc8 Mon Sep 17 00:00:00 2001 From: Fanis Strezos <fanis.strezos@dotdigital.com> Date: Thu, 6 Feb 2020 09:46:51 +0000 Subject: [PATCH 109/176] Revert "roll back changes" This reverts commit 80c737a7287439876f73ab90c7fce7e1a5a43877. --- app/code/Magento/Sales/Model/Order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 0a727b7560396..8a760065439d6 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -1326,7 +1326,7 @@ public function getTrackingNumbers() */ public function getShippingMethod($asObject = false) { - $shippingMethod = parent::getShippingMethod(); + $shippingMethod = $this->getData('shipping_method'); if (!$asObject || !$shippingMethod) { return $shippingMethod; } else { From 0471a013302ebbd14163c6de55e6e9f008dabffa Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 6 Feb 2020 12:11:20 +0200 Subject: [PATCH 110/176] MC-30682: [FT] [MFTF] [2.4] Fix flaky test AdminCreateVirtualProductWithTierPriceForGeneralGroupTest (MC-6033) --- ...eateVirtualProductWithTierPriceForGeneralGroupTest.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml index e4e52272e5935..b2ddaac65d070 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml @@ -25,8 +25,8 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <deleteData stepKey="deleteSimpleSubCategory" createDataKey="categoryEntity"/> - <deleteData stepKey="deleteCustomer" createDataKey="customer"/> + <deleteData createDataKey="categoryEntity" stepKey="deleteSimpleSubCategory"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <actionGroup ref="DeleteProductUsingProductGridActionGroup" stepKey="deleteVirtualProduct"> <argument name="product" value="virtualProductGeneralGroup"/> </actionGroup> @@ -50,7 +50,7 @@ <argument name="amount" value="{{tierPriceOnGeneralGroup.price}}"/> </actionGroup> <actionGroup ref="AdminProductFormDoneAdvancedPricingDialogActionGroup" stepKey="doneAdvancedPricingModal"/> - <selectOption selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{virtualProductGeneralGroup.productTaxClass}}" stepKey="selectProductStockClass"/> + <selectOption selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{virtualProductGeneralGroup.productTaxClass}}" stepKey="selectProductTaxClass"/> <actionGroup ref="SetCategoryByNameActionGroup" stepKey="setNewCategory"> <argument name="categoryName" value="$categoryEntity.name$"/> </actionGroup> @@ -61,7 +61,7 @@ <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProductAndCheckSuccessMessage"/> <!-- Search created virtual product(from above steps) in the grid --> - <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForVirtualProduct"> <argument name="product" value="virtualProductGeneralGroup"/> </actionGroup> From 999fe16ae5ce78bff55a9c71f186cea70fedf128 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 6 Feb 2020 12:59:00 +0200 Subject: [PATCH 111/176] MC-30384: [2.4] Test StorefrontInactiveCatalogRuleTest fails on Jenkins (MC-79) --- .../StorefrontInactiveCatalogRuleTest.xml | 62 +++++++++---------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml index 3423baf7970eb..32cdb4869ddde 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml @@ -16,55 +16,53 @@ <description value="Customer should not see the catalog price rule promotion if status is inactive"/> <severity value="CRITICAL"/> <testCaseId value="MC-79"/> - <group value="CatalogRule"/> - <skip> - <issueId value="MC-30384"/> - </skip> + <group value="catalogRule"/> </annotations> + <before> - <actionGroup ref="LoginAsAdmin" stepKey="login"/> <createData entity="ApiCategory" stepKey="createCategory"/> <createData entity="ApiSimpleProduct" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <actionGroup stepKey="createNewPriceRule" ref="NewCatalogPriceRuleByUIActionGroup"/> - <actionGroup stepKey="selectLoggedInCustomers" ref="SelectNotLoggedInCustomerGroupActionGroup"/> - <scrollToTopOfPage stepKey="scrollToTop"/> - <click stepKey="setInactive" selector="{{AdminCategoryBasicFieldSection.enableCategoryLabel}}"/> - <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="saveAndApply"/> - <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="seeSuccess"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> - <!-- Perform reindex and flush cache --> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> + <actionGroup ref="AdminOpenNewCatalogPriceRuleFormPageActionGroup" stepKey="startCreatingFirstPriceRule"/> + <actionGroup ref="AdminCatalogPriceRuleFillMainInfoActionGroup" stepKey="fillMainInfoForFirstPriceRule"> + <argument name="active" value="0"/> + <argument name="groups" value="'NOT LOGGED IN'"/> + </actionGroup> + <actionGroup ref="AdminCatalogPriceRuleFillActionsActionGroup" stepKey="fillActionsForThirdPriceRule"/> + <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="saveAndApplyFirstPriceRule"/> + <!-- Perform reindex --> + <magentoCLI command="indexer:reindex" arguments="catalogrule_rule" stepKey="reindex"/> </before> + <after> <deleteData createDataKey="createProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <amOnPage url="admin/catalog_rule/promo_catalog/" stepKey="goToPriceRulePage"/> - <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule"> - <argument name="name" value="{{_defaultCatalogRule.name}}"/> - <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> - </actionGroup> - <amOnPage url="{{AdminLogoutPage.url}}" stepKey="logout"/> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </after> <!-- Verify price is not discounted on category page --> - <amOnPage url="$$createCategory.name$$.html" stepKey="goToCategory"/> - <waitForPageLoad stepKey="waitForCategory"/> - <see selector="{{StorefrontCategoryProductSection.ProductPriceByNumber('1')}}" userInput="$$createProduct.price$$" stepKey="seePrice1"/> + <amOnPage url="{{StorefrontCategoryPage.url($createCategory.custom_attributes[url_key]$)}}" stepKey="openCategoryPageOnFrontend"/> + <waitForPageLoad stepKey="waitForCategoryPageLoaded"/> + <see selector="{{StorefrontCategoryProductSection.ProductPriceByNumber('1')}}" userInput="$$createProduct.price$$" stepKey="seeProductPriceOnCategoryPage"/> <!-- Verify price is not discounted on the product page --> - <amOnPage url="$$createProduct.sku$$.html" stepKey="goToProduct"/> - <waitForPageLoad stepKey="waitForProduct"/> - <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="$$createProduct.price$$" stepKey="seePrice2"/> + <amOnPage url="{{StorefrontProductPage.url($createProduct.custom_attributes[url_key]$)}}" stepKey="openProductPageOnFrontend"/> + <waitForPageLoad stepKey="waitForProductPageLoaded"/> + <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="$createProduct.price$" stepKey="seePriceOnProductPage"/> <!-- Verify price is not discounted in the cart --> - <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addToCart"/> - <waitForPageLoad stepKey="waitForCart"/> - <waitForElementVisible selector="{{StorefrontMessagesSection.success}}" stepKey="waitForSuccessMessage"/> - <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCheckout"/> - <waitForPageLoad stepKey="waitForCheckout"/> - <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$$createProduct.price$$" stepKey="seePrice3"/> + <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addToCartFromStorefrontProductPage"> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> + + <actionGroup ref="StorefrontOpenCartPageActionGroup" stepKey="openCartPage" /> + <waitForElementVisible selector="{{CheckoutCartSummarySection.subtotal}}" stepKey="waitForSubtotalAppears"/> + <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$createProduct.price$" stepKey="seeProductPriceOnCartPage"/> </test> </tests> From 2f591a8805a03ca0479724a695baeb67586a2e59 Mon Sep 17 00:00:00 2001 From: Adarsh Manickam <adarsh.apple@icloud.com> Date: Thu, 6 Feb 2020 18:33:59 +0530 Subject: [PATCH 112/176] Deprecated associated test class --- .../Unit/Model/Order/Email/Sender/ShipmentSenderTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php index dc6fc53e5ec43..dcd80646b168c 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php @@ -8,7 +8,10 @@ use Magento\Sales\Model\Order\Email\Sender\ShipmentSender; /** - * Test for Magento\Sales\Model\Order\Email\Sender\ShipmentSender class. + * Test for Magento\Sales\Model\Order\Email\Sender\ShipmentSender class + * + * @deprecated since ShipmentSender is deprecated + * @see \Magento\Sales\Model\Order\Email\Sender\ShipmentSender */ class ShipmentSenderTest extends AbstractSenderTest { From c3ba2ce2468e04ed87f11c8a2cbac7732ef1fe40 Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Thu, 6 Feb 2020 23:26:35 +0530 Subject: [PATCH 113/176] improve test names --- .../app/code/Magento/Ui/base/js/grid/data-storage.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js index 02d303782a9d5..ade7d09797139 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js @@ -225,7 +225,7 @@ define([ expect(model.getRequest).toHaveBeenCalled(); }); - it('Return "getRequestData" method', function () { + it('it returns cached request data if a cached request exists and no refresh option is provided', function () { var params = { namespace: 'magento', search: '', @@ -247,7 +247,7 @@ define([ expect(model.getRequestData).toHaveBeenCalled(); }); - it('Return "requestData" method', function () { + it('if refresh option is true so it will ignore cache and execute the requestData function', function () { var params = { namespace: 'magento', search: '', From 75b03e05c592075cf0619e419ac54d8bf62e34af Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Fri, 7 Feb 2020 08:41:55 +1030 Subject: [PATCH 114/176] #26622 - Remove unnecessary new lines and variable declaration, and make function private --- app/code/Magento/SalesRule/Model/Validator.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php index 8292e9c313b66..cdaac97fe6fb5 100644 --- a/app/code/Magento/SalesRule/Model/Validator.php +++ b/app/code/Magento/SalesRule/Model/Validator.php @@ -410,11 +410,8 @@ public function initTotals($items, Address $address) * @param Rule $rule * @return bool */ - protected function isValidItemForRule( - AbstractItem $item, - Rule $rule - ) { - /** @var AbstractItem $item */ + private function isValidItemForRule(AbstractItem $item, Rule $rule) + { if ($item->getParentItemId()) { return false; } From a037edfe8c14675a89e5e2f6839bf401ac9e253c Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Fri, 7 Feb 2020 08:43:05 +1030 Subject: [PATCH 115/176] #26622 - Fix return values of mock object functions --- .../SalesRule/Test/Unit/Model/ValidatorTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php index 30b198e5b9199..946963dd8d234 100644 --- a/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php +++ b/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php @@ -370,20 +370,20 @@ public function testInitTotalsCanApplyDiscount() $validator->expects($this->at(0))->method('isValid')->with($item1)->willReturn(false); $validator->expects($this->at(1))->method('isValid')->with($item2)->willReturn(true); - $item1->expects($this->any())->method('getParentItemId')->willReturn(false); - $item1->expects($this->any())->method('getParentItem')->willReturn(false); + $item1->expects($this->any())->method('getParentItemId')->willReturn(null); + $item1->expects($this->any())->method('getParentItem')->willReturn(null); $item1->expects($this->never())->method('getDiscountCalculationPrice'); $item1->expects($this->never())->method('getBaseDiscountCalculationPrice'); - $item2->expects($this->any())->method('getParentItemId')->willReturn(false); - $item2->expects($this->any())->method('getParentItem')->willReturn(false); + $item2->expects($this->any())->method('getParentItemId')->willReturn(null); + $item2->expects($this->any())->method('getParentItem')->willReturn(null); $item2->expects($this->any())->method('getDiscountCalculationPrice')->willReturn(50); $item2->expects($this->once())->method('getBaseDiscountCalculationPrice')->willReturn(50); - $item3->expects($this->any())->method('getParentItemId')->willReturn(false); - $item3->expects($this->any())->method('getParentItem')->willReturn(true); + $item3->expects($this->any())->method('getParentItemId')->willReturn(null); + $item3->expects($this->any())->method('getParentItem')->willReturn($item1); $item3->expects($this->never())->method('getDiscountCalculationPrice'); $item3->expects($this->never())->method('getBaseDiscountCalculationPrice'); - $item4->expects($this->any())->method('getParentItemId')->willReturn(true); - $item4->expects($this->any())->method('getParentItem')->willReturn(false); + $item4->expects($this->any())->method('getParentItemId')->willReturn(12345); + $item4->expects($this->any())->method('getParentItem')->willReturn(null); $item4->expects($this->never())->method('getDiscountCalculationPrice'); $item4->expects($this->never())->method('getBaseDiscountCalculationPrice'); $this->utility->expects($this->once())->method('getItemQty')->willReturn(1); From eeaadb82cea7c7d32e42ad434496eb124bc504f3 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Fri, 7 Feb 2020 10:40:11 +0200 Subject: [PATCH 116/176] MC-24236: [MFTF Test] Unskip MFTF test MC-13607 "Verify that Catalog Price Rule and Customer Group Membership are persisted under long-term cookie" --- ...tProductPriceInCategoryPageActionGroup.xml | 26 ++++++ ...tSpecialPriceInCategoryPageActionGroup.xml | 21 +++++ .../StorefrontCategoryProductSection.xml | 2 +- ...hipArePersistedUnderLongTermCookieTest.xml | 90 +++++++++++-------- ...AssertDefaultWelcomeMessageActionGroup.xml | 20 +++++ .../StorefrontCustomerLogoutActionGroup.xml | 4 +- 6 files changed, 124 insertions(+), 39 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml new file mode 100644 index 0000000000000..e6eb475153f1f --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontProductPriceInCategoryPageActionGroup"> + <annotations> + <description>Goes to Storefront Category page for the provided Category. Validates that the Product price is present and correct.</description> + </annotations> + <arguments> + <argument name="categoryUrl" type="string" defaultValue="{{SimpleRootSubCategory.url_key}}"/> + <argument name="productName" type="string" defaultValue="{{productWithHTMLEntityOne.name}}"/> + <argument name="productPrice" type="string" defaultValue="{{productWithHTMLEntityOne.price}}"/> + </arguments> + + <!-- Go to storefront category page, assert product visibility --> + <amOnPage url="{{StorefrontCategoryPage.url(categoryUrl)}}" stepKey="navigateToCategoryPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <see userInput="{{productPrice}}" selector="{{StorefrontCategoryProductSection.ProductPriceByName(productName)}}" stepKey="assertProductPrice"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml new file mode 100644 index 0000000000000..17c9e43e15fa7 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertStorefrontProductSpecialPriceInCategoryPageActionGroup" extends="AssertStorefrontProductPriceInCategoryPageActionGroup"> + <annotations> + <description>Goes to Storefront Category page for the provided Category. Validates that the Product price is present and correct.</description> + </annotations> + <arguments> + <argument name="productSpecialPrice" type="string" defaultValue="{{updateVirtualProductSpecialPrice.special_price}}"/> + </arguments> + + <see userInput="{{productSpecialPrice}}" selector="{{StorefrontCategoryProductSection.ProductCatalogRuleSpecialPriceTitleByName(productName)}}" after="assertProductPrice" stepKey="assertProductSpecialPrice"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml index 4114d64eb39af..9ee019c9e934e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml @@ -21,7 +21,7 @@ <element name="ProductTitleByName" type="button" selector="//main//li//a[contains(text(), '{{var1}}')]" parameterized="true"/> <element name="ProductPriceByName" type="text" selector="//main//li[.//a[contains(text(), '{{var1}}')]]//span[@class='price']" parameterized="true"/> - <element name="ProductCatalogRuleSpecialPriceTitleByName" type="text" selector="//div[descendant::*[contains(text(), '{{var1}}')]]//*[contains(@class, 'special-price')]" parameterized="true"/> + <element name="ProductCatalogRuleSpecialPriceTitleByName" type="text" selector="//main//li[.//a[contains(text(), '{{productName}}')]]//span[@data-price-type='finalPrice']/span" parameterized="true"/> <element name="ProductCatalogRulePriceTitleByName" type="text" selector="//div[descendant::*[contains(text(), '{{var1}}')]]//*[contains(@class, 'price-label')]" parameterized="true"/> <element name="ProductImageByName" type="text" selector="//main//li[.//a[contains(text(), '{{var1}}')]]//img[@class='product-image-photo']" parameterized="true"/> <element name="ProductImageBySrc" type="text" selector=".products-grid img[src*='{{pattern}}']" parameterized="true"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml index 86d3dccba7595..9bae928c66426 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml @@ -15,71 +15,89 @@ <title value="Verify that Catalog Price Rule and Customer Group Membership are persisted under long-term cookie"/> <description value="Verify that Catalog Price Rule and Customer Group Membership are persisted under long-term cookie"/> <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-69455"/> + <testCaseId value="MC-27571"/> <group value="persistent"/> </annotations> <before> - <createData entity="PersistentConfigEnabled" stepKey="enablePersistent"/> - <createData entity="PersistentLogoutClearDisable" stepKey="persistentLogoutClearDisable"/> + + <createData entity="PersistentConfigSettings" stepKey="enablePersistent"/> <createData entity="_defaultCategory" stepKey="createCategory"/> - <createData entity="_defaultProduct" stepKey="createProduct"> + <createData entity="productWithHTMLEntityOne" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> - <field key="price">50</field> </createData> <createData entity="Simple_US_Customer" stepKey="createCustomer"> <field key="group_id">1</field> </createData> - <actionGroup ref="LoginAsAdmin" stepKey="login"/> + <!--Delete all Catalog Price Rule if exist--> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + + <!--Create Catalog Rule--> - <actionGroup ref="NewCatalogPriceRuleByUIWithConditionIsCategoryActionGroup" stepKey="createCatalogPriceRule"> - <argument name="catalogRule" value="_defaultCatalogRule"/> - <argument name="categoryId" value="$$createCategory.id$$"/> + <actionGroup ref="AdminOpenNewCatalogPriceRuleFormPageActionGroup" stepKey="startCreatingFirstPriceRule"/> + <actionGroup ref="AdminCatalogPriceRuleFillMainInfoActionGroup" stepKey="fillMainInfoForFirstPriceRule"> + <argument name="groups" value="'General'"/> </actionGroup> - <actionGroup ref="SelectGeneralCustomerGroupActionGroup" stepKey="selectCustomerGroup"/> - <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="clickSaveAndApplyRules"/> - <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="assertSuccess"/> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> + <actionGroup ref="AdminFillCatalogRuleConditionActionGroup" stepKey="createCatalogPriceRule"> + <argument name="conditionValue" value="$createCategory.id$"/> + </actionGroup> + <actionGroup ref="AdminCatalogPriceRuleFillActionsActionGroup" stepKey="fillActionsForThirdPriceRule"/> + <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="clickSaveAndApplyRule"/> + + <!-- Perform reindex --> + <magentoCLI command="indexer:reindex" arguments="catalogrule_rule" stepKey="reindex"/> </before> <after> - <!-- Delete the rule --> - <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToCatalogPriceRulePage"/> - <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule"> - <argument name="name" value="{{_defaultCatalogRule.name}}"/> - <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> - </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> <createData entity="PersistentConfigDefault" stepKey="setDefaultPersistentState"/> <createData entity="PersistentLogoutClearEnabled" stepKey="persistentLogoutClearEnabled"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <!-- Delete the rule --> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + <actionGroup ref="logout" stepKey="logout"/> </after> <!--Go to category and check price--> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage"/> - <see selector="{{StorefrontCategoryProductSection.ProductPriceByNumber('1')}}" userInput="$$createProduct.price$$" stepKey="checkPriceSimpleProduct"/> + <actionGroup ref="AssertStorefrontProductPriceInCategoryPageActionGroup" stepKey="assertProductPriceInCategoryPage"> + <argument name="categoryUrl" value="$createCategory.custom_attributes[url_key]$"/> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> <!--Login to storefront from customer and check price--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomer"> - <argument name="Customer" value="$$createCustomer$$"/> + <argument name="Customer" value="$createCustomer$"/> + </actionGroup> + <actionGroup ref="AssertCustomerWelcomeMessageActionGroup" stepKey="seeWelcomeMessageForJohnDoeCustomer"> + <argument name="customerFullName" value="{{Simple_Customer_Without_Address.fullname}}"/> </actionGroup> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage2"/> - <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome"/> - <see selector="{{StorefrontCategoryProductSection.ProductSpecialPriceByNumber('1')}}" userInput="45.00" stepKey="checkPriceSimpleProduct2"/> - <!--Click *Sign Out* and check the price of the Simple Product--> + <!--Go to category and check special price--> + <actionGroup ref="AssertStorefrontProductSpecialPriceInCategoryPageActionGroup" stepKey="assertProductSpecialPriceInCategoryPage"> + <argument name="categoryUrl" value="$createCategory.custom_attributes[url_key]$"/> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> + + + <!--Click *Sign Out*--> <actionGroup ref="StorefrontSignOutActionGroup" stepKey="storefrontSignOut"/> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage3"/> - <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome2"/> - <seeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkLinkNotYoy"/> - <see selector="{{StorefrontCategoryProductSection.ProductSpecialPriceByNumber('1')}}" userInput="45.00" stepKey="checkPriceSimpleProduct3"/> + <actionGroup ref="StorefrontAssertPersistentCustomerWelcomeMessageActionGroup" stepKey="seeWelcomeForJohnDoeCustomer"> + <argument name="customerFullName" value="{{Simple_Customer_Without_Address.fullname}}"/> + </actionGroup> + + <!--Go to category and check special price--> + <actionGroup ref="AssertStorefrontProductSpecialPriceInCategoryPageActionGroup" stepKey="assertProductSpecialPriceInCategoryPageAfterLogout"> + <argument name="categoryUrl" value="$createCategory.custom_attributes[url_key]$"/> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> <!--Click the *Not you?* link and check the price for Simple Product--> - <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickNext"/> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage4"/> - <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome3"/> - <see selector="{{StorefrontCategoryProductSection.ProductPriceByNumber('1')}}" userInput="$$createProduct.price$$" stepKey="checkPriceSimpleProduct4"/> + <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickNotYouLink"/> + <actionGroup ref="AssertDefaultWelcomeMessageActionGroup" stepKey="seeWelcomeMessageForJohnDoeCustomerAfterLogout"/> + <actionGroup ref="AssertStorefrontProductPriceInCategoryPageActionGroup" stepKey="assertProductPriceInCategoryPageAfterLogout"> + <argument name="categoryUrl" value="$createCategory.custom_attributes[url_key]$"/> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml new file mode 100644 index 0000000000000..05414fb8ebe20 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertDefaultWelcomeMessageActionGroup"> + <annotations> + <description>Validates that the Welcome message is present and correct and not you link absent.</description> + </annotations> + + <waitForPageLoad stepKey="waitForPageLoad"/> + <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="verifyDefaultMessage"/> + <dontSeeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkAbsenceLinkNotYou"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml index ed221350918a0..98a7f4c8d1544 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml @@ -24,7 +24,7 @@ <click selector="{{StoreFrontSignOutSection.customerAccount}}" stepKey="clickCustomerButton"/> <click selector="{{StoreFrontSignOutSection.signOut}}" stepKey="clickToSignOut"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <see userInput="You are signed out" stepKey="signOut"/> + <waitForText selector="{{StorefrontCMSPageSection.mainTitle}}" userInput="You are signed out" stepKey="signOut"/> + <waitForText selector="{{StorefrontCMSPageSection.mainTitle}}" userInput="Home Page" stepKey="waitForHomePageLoad"/> </actionGroup> </actionGroups> From ea007205d88951a93d4ba1fc6365a3b0858af6a6 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 7 Feb 2020 10:54:08 +0200 Subject: [PATCH 117/176] Add return type assertion --- .../Test/Unit/Observer/ResetAttemptForBackendObserverTest.php | 4 ++-- .../Unit/Observer/ResetAttemptForFrontendObserverTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php index b7a0c9534598d..b984daa8998f3 100644 --- a/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php +++ b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php @@ -28,7 +28,7 @@ class ResetAttemptForBackendObserverTest extends TestCase public function testExecuteExpectsDeleteUserAttemptsCalled() { $logMock = $this->createMock(Log::class); - $logMock->expects($this->once())->method('deleteUserAttempts'); + $logMock->expects($this->once())->method('deleteUserAttempts')->willReturnSelf(); $resLogFactoryMock = $this->createMock(LogFactory::class); $resLogFactoryMock->expects($this->once()) @@ -48,6 +48,6 @@ public function testExecuteExpectsDeleteUserAttemptsCalled() ResetAttemptForBackendObserver::class, ['resLogFactory' => $resLogFactoryMock] ); - $observer->execute($eventObserverMock); + $this->assertInstanceOf(Log::class, $observer->execute($eventObserverMock)); } } diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php index f83341eb8680d..11866c266845e 100644 --- a/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php +++ b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php @@ -28,7 +28,7 @@ class ResetAttemptForFrontendObserverTest extends TestCase public function testExecuteExpectsDeleteUserAttemptsCalled() { $logMock = $this->createMock(Log::class); - $logMock->expects($this->once())->method('deleteUserAttempts'); + $logMock->expects($this->once())->method('deleteUserAttempts')->willReturnSelf(); $resLogFactoryMock = $this->createMock(LogFactory::class); $resLogFactoryMock->expects($this->once()) @@ -47,6 +47,6 @@ public function testExecuteExpectsDeleteUserAttemptsCalled() ResetAttemptForFrontendObserver::class, ['resLogFactory' => $resLogFactoryMock] ); - $observer->execute($eventObserverMock); + $this->assertInstanceOf(Log::class, $observer->execute($eventObserverMock)); } } From 3f1789cefb3637ed90c93af8e2dd4bffe34e523d Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 7 Feb 2020 11:29:41 +0200 Subject: [PATCH 118/176] MC-30384: [2.4] Test StorefrontInactiveCatalogRuleTest fails on Jenkins (MC-79) --- .../Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml index 32cdb4869ddde..45b0c1bcaa5a0 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml @@ -59,8 +59,6 @@ <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addToCartFromStorefrontProductPage"> <argument name="productName" value="$createProduct.name$"/> </actionGroup> - <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> - <actionGroup ref="StorefrontOpenCartPageActionGroup" stepKey="openCartPage" /> <waitForElementVisible selector="{{CheckoutCartSummarySection.subtotal}}" stepKey="waitForSubtotalAppears"/> <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$createProduct.price$" stepKey="seeProductPriceOnCartPage"/> From 9d992d0cf9cf594f892422a5522fd7c83486784a Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 7 Feb 2020 12:30:48 +0200 Subject: [PATCH 119/176] refactoring, static test fixes --- .../Grid/Column/Renderer/AbstractRenderer.php | 6 +++- .../Gateway/Data/PaymentDataObjectTest.php | 34 ++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php index c58bcdf5108cb..415ce7c4c21fc 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php @@ -9,6 +9,9 @@ use Magento\Framework\DataObject; /** + * Produce html output using the given data source. + * + * phpcs:disable Magento2.Classes.AbstractApi * Backend grid item abstract renderer * @api * @SuppressWarnings(PHPMD.NumberOfChildren) @@ -53,7 +56,7 @@ public function getColumn() * Renders grid column * * @param DataObject $row - * @return string + * @return string */ public function render(DataObject $row) { @@ -90,6 +93,7 @@ protected function _getValue(DataObject $row) if (is_string($getter)) { return $row->{$getter}(); } elseif (is_callable($getter)) { + //phpcs:ignore Magento2.Functions.DiscouragedFunction return call_user_func($getter, $row); } return ''; diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php index e816533d59088..72c35a192119f 100644 --- a/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php @@ -5,45 +5,61 @@ */ namespace Magento\Payment\Test\Unit\Gateway\Data; -use Magento\Payment\Gateway\Data\PaymentDataObject; use Magento\Payment\Gateway\Data\OrderAdapterInterface; +use Magento\Payment\Gateway\Data\PaymentDataObject; use Magento\Payment\Model\InfoInterface; +use PHPUnit\Framework\MockObject\MockObject; /** - * Class PaymentDataObjectTest + * Tests for PaymentDataObject */ class PaymentDataObjectTest extends \PHPUnit\Framework\TestCase { - /** @var PaymentDataObject */ + /** + * @var PaymentDataObject + */ protected $model; /** - * @var OrderAdapterInterface|\PHPUnit_Framework_MockObject_MockObject + * @var OrderAdapterInterface|MockObject */ protected $orderMock; /** - * @var InfoInterface|\PHPUnit_Framework_MockObject_MockObject + * @var InfoInterface|\MockObject */ protected $paymentMock; + /** + * @inheritdoc + */ protected function setUp() { - $this->orderMock = $this->getMockBuilder(\Magento\Payment\Gateway\Data\OrderAdapterInterface::class) + $this->orderMock = $this->getMockBuilder(OrderAdapterInterface::class) ->getMockForAbstractClass(); - $this->paymentMock = $this->getMockBuilder(\Magento\Payment\Model\InfoInterface::class) + $this->paymentMock = $this->getMockBuilder(InfoInterface::class) ->getMockForAbstractClass(); $this->model = new PaymentDataObject($this->orderMock, $this->paymentMock); } - public function testGetOrder() + /** + * Verify can get order + * + * @return void + */ + public function testGetOrder(): void { $this->assertSame($this->orderMock, $this->model->getOrder()); } - public function testGetPayment() + /** + * Verify can get payment + * + * @return void + */ + public function testGetPayment(): void { $this->assertSame($this->paymentMock, $this->model->getPayment()); } From 7b99e510a4feaa5fdde059e4e87668a43e3d348c Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 7 Feb 2020 13:18:40 +0200 Subject: [PATCH 120/176] reafactoring, declare empty array variable --- app/code/Magento/Search/Block/Term.php | 31 ++++++++++++++++++-------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Search/Block/Term.php b/app/code/Magento/Search/Block/Term.php index 6dab372df3edc..5df68c240ddce 100644 --- a/app/code/Magento/Search/Block/Term.php +++ b/app/code/Magento/Search/Block/Term.php @@ -9,6 +9,8 @@ */ namespace Magento\Search\Block; +use Magento\Framework\DataObject; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\UrlFactory; use Magento\Framework\UrlInterface; use Magento\Framework\View\Element\Template; @@ -16,6 +18,8 @@ use Magento\Search\Model\ResourceModel\Query\CollectionFactory; /** + * Terms and conditions block + * * @api * @since 100.0.2 */ @@ -71,17 +75,17 @@ public function __construct( * Load terms and try to sort it by names * * @return $this - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws NoSuchEntityException */ protected function _loadTerms() { if (empty($this->_terms)) { $this->_terms = []; - $terms = $this->_queryCollectionFactory->create()->setPopularQueryFilter( - $this->_storeManager->getStore()->getId() - )->setPageSize( - 100 - )->load()->getItems(); + $terms = $this->_queryCollectionFactory->create() + ->setPopularQueryFilter($this->_storeManager->getStore()->getId()) + ->setPageSize(100) + ->load() + ->getItems(); if (count($terms) == 0) { return $this; @@ -91,6 +95,7 @@ protected function _loadTerms() $this->_minPopularity = end($terms)->getPopularity(); $range = $this->_maxPopularity - $this->_minPopularity; $range = $range == 0 ? 1 : $range; + $termKeys = []; foreach ($terms as $term) { if (!$term->getPopularity()) { continue; @@ -112,8 +117,10 @@ protected function _loadTerms() } /** + * Load and return terms + * * @return array - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws NoSuchEntityException */ public function getTerms() { @@ -122,10 +129,12 @@ public function getTerms() } /** - * @param \Magento\Framework\DataObject $obj + * Return search url + * + * @param DataObject $obj * @return string */ - public function getSearchUrl($obj) + public function getSearchUrl(DataObject $obj) { /** @var $url UrlInterface */ $url = $this->_urlFactory->create(); @@ -138,6 +147,8 @@ public function getSearchUrl($obj) } /** + * Return max popularity + * * @return int */ public function getMaxPopularity() @@ -146,6 +157,8 @@ public function getMaxPopularity() } /** + * Return min popularity + * * @return int */ public function getMinPopularity() From c58a7e3b74e61064988326a344252f52eb4c11bb Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 7 Feb 2020 13:21:02 +0200 Subject: [PATCH 121/176] small improvements --- app/code/Magento/Search/Block/Term.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/code/Magento/Search/Block/Term.php b/app/code/Magento/Search/Block/Term.php index 5df68c240ddce..69d180f79e680 100644 --- a/app/code/Magento/Search/Block/Term.php +++ b/app/code/Magento/Search/Block/Term.php @@ -41,15 +41,11 @@ class Term extends Template protected $_maxPopularity; /** - * Url factory - * * @var UrlFactory */ protected $_urlFactory; /** - * Query collection factory - * * @var CollectionFactory */ protected $_queryCollectionFactory; From 1e14f000e8b32a6a0a1101879b5632af1f733cfb Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 7 Feb 2020 13:51:51 +0200 Subject: [PATCH 122/176] revert param type --- app/code/Magento/Search/Block/Term.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Search/Block/Term.php b/app/code/Magento/Search/Block/Term.php index 69d180f79e680..9010e3e1dbbc1 100644 --- a/app/code/Magento/Search/Block/Term.php +++ b/app/code/Magento/Search/Block/Term.php @@ -130,7 +130,7 @@ public function getTerms() * @param DataObject $obj * @return string */ - public function getSearchUrl(DataObject $obj) + public function getSearchUrl($obj) { /** @var $url UrlInterface */ $url = $this->_urlFactory->create(); From 42d0c1a979ffc23d885b7ba074fb8221d21c9b20 Mon Sep 17 00:00:00 2001 From: "ivan.pletnyov" <ivan.pletnyov@transoftgroup.com> Date: Fri, 7 Feb 2020 14:04:39 +0200 Subject: [PATCH 123/176] MC-31256: Admin: Create/update/delete customer addresses --- .../Directory/Model/GetRegionIdByName.php | 54 +++ .../Model/Address/CreateAddressTest.php | 368 ++++++++++++++++++ .../Model/Address/DeleteAddressTest.php | 92 +++++ .../Model/Address/UpdateAddressTest.php | 294 ++++++++++++++ .../_files/customer_no_address_rollback.php | 30 ++ 5 files changed, 838 insertions(+) create mode 100644 dev/tests/integration/framework/Magento/TestFramework/Directory/Model/GetRegionIdByName.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/Address/DeleteAddressTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/customer_no_address_rollback.php diff --git a/dev/tests/integration/framework/Magento/TestFramework/Directory/Model/GetRegionIdByName.php b/dev/tests/integration/framework/Magento/TestFramework/Directory/Model/GetRegionIdByName.php new file mode 100644 index 0000000000000..f1e98cd4ea0bf --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Directory/Model/GetRegionIdByName.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestFramework\Directory\Model; + +use Magento\Directory\Model\RegionFactory; + +/** + * Return region ID by region default name and country code. + */ +class GetRegionIdByName +{ + /** + * @var RegionFactory + */ + private $regionFactory; + + /** + * @var array + */ + private $regionIdsCache; + + /** + * @param RegionFactory $regionFactory + */ + public function __construct( + RegionFactory $regionFactory + ) { + $this->regionFactory = $regionFactory; + } + + /** + * Get region ID from cache property if region id exist or load it. + * + * @param string $regionName + * @param string $countryId + * @return int|null + */ + public function execute(string $regionName, string $countryId): ?int + { + $cacheKey = "{$regionName}_{$countryId}"; + + if (!isset($this->regionIdsCache[$cacheKey])) { + $region = $this->regionFactory->create()->loadByName($regionName, $countryId); + $this->regionIdsCache[$cacheKey] = $region->getRegionId() ? (int)$region->getRegionId() : null; + } + + return $this->regionIdsCache[$cacheKey]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php new file mode 100644 index 0000000000000..ae65c32fe3f43 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php @@ -0,0 +1,368 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\Address; + +use Magento\Customer\Api\AddressRepositoryInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Api\Data\AddressInterface; +use Magento\Customer\Api\Data\AddressInterfaceFactory; +use Magento\Customer\Model\AddressRegistry; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Customer\Model\ResourceModel\Address; +use Magento\Framework\Exception\InputException; +use Magento\TestFramework\Directory\Model\GetRegionIdByName; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Assert that address was created as expected or address create throws expected error. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * + * @magentoDbIsolation enabled + */ +class CreateAddressTest extends TestCase +{ + /** + * Static customer address data. + */ + private const STATIC_CUSTOMER_ADDRESS_DATA = [ + AddressInterface::TELEPHONE => 3468676, + AddressInterface::POSTCODE => 75477, + AddressInterface::COUNTRY_ID => 'US', + 'custom_region_name' => 'Alabama', + AddressInterface::CITY => 'CityM', + AddressInterface::STREET => 'Green str, 67', + AddressInterface::LASTNAME => 'Smith', + AddressInterface::FIRSTNAME => 'John', + ]; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var GetRegionIdByName + */ + private $getRegionIdByName; + + /** + * @var AddressInterfaceFactory + */ + private $addressFactory; + + /** + * @var AddressRegistry + */ + private $addressRegistry; + + /** + * @var Address + */ + private $addressResource; + + /** + * @var CustomerRegistry + */ + private $customerRegistry; + + /** + * @var AddressRepositoryInterface + */ + private $addressRepository; + + /** + * @var CustomerRepositoryInterface + */ + private $customerRepository; + + /** + * @var int[] + */ + private $createdAddressesIds = []; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->getRegionIdByName = $this->objectManager->get(GetRegionIdByName::class); + $this->addressFactory = $this->objectManager->get(AddressInterfaceFactory::class); + $this->addressRegistry = $this->objectManager->get(AddressRegistry::class); + $this->addressResource = $this->objectManager->get(Address::class); + $this->customerRegistry = $this->objectManager->get(CustomerRegistry::class); + $this->addressRepository = $this->objectManager->get(AddressRepositoryInterface::class); + $this->customerRepository = $this->objectManager->get(CustomerRepositoryInterface::class); + parent::setUp(); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + foreach ($this->createdAddressesIds as $createdAddressesId) { + $this->addressRegistry->remove($createdAddressesId); + } + parent::tearDown(); + } + + /** + * Assert that default addresses properly created for customer. + * + * @magentoDataFixture Magento/Customer/_files/customer_no_address.php + * + * @dataProvider createDefaultAddressesDataProvider + * + * @param array $addressData + * @param bool $isShippingDefault + * @param bool $isBillingDefault + * @return void + */ + public function testCreateDefaultAddress( + array $addressData, + bool $isShippingDefault, + bool $isBillingDefault + ): void { + $customer = $this->customerRepository->get('customer5@example.com'); + $this->assertNull($customer->getDefaultShipping(), 'Customer already has default shipping address'); + $this->assertNull($customer->getDefaultBilling(), 'Customer already has default billing address'); + $address = $this->createAddress( + (int)$customer->getId(), + $addressData, + $isShippingDefault, + $isBillingDefault + ); + $expectedShipping = $isShippingDefault ? $address->getId() : null; + $expectedBilling = $isBillingDefault ? $address->getId() : null; + $customer = $this->customerRepository->get('customer5@example.com'); + $this->assertEquals($expectedShipping, $customer->getDefaultShipping()); + $this->assertEquals($expectedBilling, $customer->getDefaultBilling()); + } + + /** + * Data provider for create default or not default address. + * + * @return array + */ + public function createDefaultAddressesDataProvider(): array + { + return [ + 'any_addresses_are_default' => [self::STATIC_CUSTOMER_ADDRESS_DATA, false, false], + 'shipping_address_is_default' => [self::STATIC_CUSTOMER_ADDRESS_DATA, true, false], + 'billing_address_is_default' => [self::STATIC_CUSTOMER_ADDRESS_DATA, false, true], + 'all_addresses_are_default' => [self::STATIC_CUSTOMER_ADDRESS_DATA, true, true], + ]; + } + + /** + * Assert that address created successfully. + * + * @magentoDataFixture Magento/Customer/_files/customer_no_address.php + * + * @dataProvider createAddressesDataProvider + * + * @param array $addressData + * @param array $expectedData + * @return void + */ + public function testAddressCreatedWithProperData(array $addressData, array $expectedData): void + { + if (isset($expectedData['custom_region_name'])) { + $expectedData[AddressInterface::REGION_ID] = $this->getRegionIdByName->execute( + $expectedData['custom_region_name'], + $expectedData[AddressInterface::COUNTRY_ID] + ); + unset($expectedData['custom_region_name']); + } + $customer = $this->customerRepository->get('customer5@example.com'); + $createdAddressData = $this->createAddress((int)$customer->getId(), $addressData)->__toArray(); + foreach ($expectedData as $fieldCode => $expectedValue) { + $this->assertTrue(isset($createdAddressData[$fieldCode]), "Field $fieldCode wasn't found."); + $this->assertEquals($createdAddressData[$fieldCode], $expectedValue); + } + } + + /** + * Data provider for create address with proper data. + * + * @return array + */ + public function createAddressesDataProvider(): array + { + return [ + 'required_fields_valid_data' => [ + self::STATIC_CUSTOMER_ADDRESS_DATA, + [ + AddressInterface::TELEPHONE => 3468676, + AddressInterface::COUNTRY_ID => 'US', + AddressInterface::POSTCODE => 75477, + 'custom_region_name' => 'Alabama', + AddressInterface::FIRSTNAME => 'John', + AddressInterface::LASTNAME => 'Smith', + AddressInterface::STREET => ['Green str, 67'], + AddressInterface::CITY => 'CityM', + ], + ], + 'required_field_empty_postcode_for_uk' => [ + array_replace( + self::STATIC_CUSTOMER_ADDRESS_DATA, + [AddressInterface::POSTCODE => '', AddressInterface::COUNTRY_ID => 'GB'] + ), + [ + AddressInterface::COUNTRY_ID => 'GB', + AddressInterface::POSTCODE => null, + ], + ], + 'required_field_empty_region_id_for_ua' => [ + array_replace( + self::STATIC_CUSTOMER_ADDRESS_DATA, + [AddressInterface::REGION_ID => '', AddressInterface::COUNTRY_ID => 'UA'] + ), + [ + AddressInterface::COUNTRY_ID => 'UA', + AddressInterface::REGION => [ + 'region' => null, + 'region_code' => null, + 'region_id' => 0, + ], + ], + ], + 'required_field_street_as_array' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::STREET => ['', 'Green str, 67']]), + [AddressInterface::STREET => ['Green str, 67']], + ], + 'field_name_prefix' => [ + array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::PREFIX => 'My prefix']), + [AddressInterface::PREFIX => 'My prefix'], + ], + 'field_middle_name_initial' => [ + array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::MIDDLENAME => 'My middle name']), + [AddressInterface::MIDDLENAME => 'My middle name'], + ], + 'field_name_suffix' => [ + array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::SUFFIX => 'My suffix']), + [AddressInterface::SUFFIX => 'My suffix'], + ], + 'field_company_name' => [ + array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::COMPANY => 'My company']), + [AddressInterface::COMPANY => 'My company'], + ], + 'field_vat_number' => [ + array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::VAT_ID => 'My VAT number']), + [AddressInterface::VAT_ID => 'My VAT number'], + ], + ]; + } + + /** + * Assert that proper error message has thrown if address creating with wrong data. + * + * @magentoDataFixture Magento/Customer/_files/customer_no_address.php + * + * @dataProvider createWrongAddressesDataProvider + * + * @param array $addressData + * @param \Exception $expectException + * @return void + */ + public function testExceptionThrownDuringCreateAddress(array $addressData, \Exception $expectException): void + { + $customer = $this->customerRepository->get('customer5@example.com'); + $this->expectExceptionObject($expectException); + $this->createAddress((int)$customer->getId(), $addressData); + } + + /** + * Data provider for create address with wrong data. + * + * @return array + */ + public function createWrongAddressesDataProvider(): array + { + return [ + 'required_field_empty_telephone' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::TELEPHONE => '']), + InputException::requiredField('telephone'), + ], + 'required_field_empty_postcode_for_us' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::POSTCODE => '']), + InputException::requiredField('postcode'), + ], +// TODO: Uncomment this variation after fix issue https://jira.corp.magento.com/browse/MC-31031 +// 'required_field_empty_region_id_for_us' => [ +// array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::REGION_ID => '']), +// InputException::requiredField('regionId'), +// ], + 'required_field_empty_firstname' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::FIRSTNAME => '']), + InputException::requiredField('firstname'), + ], + 'required_field_empty_lastname' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::LASTNAME => '']), + InputException::requiredField('lastname'), + ], + 'required_field_empty_street_as_string' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::STREET => '']), + InputException::requiredField('street'), + ], + 'required_field_empty_street_as_array' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::STREET => []]), + InputException::requiredField('street'), + ], + 'required_field_empty_city' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::CITY => '']), + InputException::requiredField('city'), + ], +// TODO: Uncomment this variation after fix issue https://jira.corp.magento.com/browse/MC-31031 +// 'field_invalid_vat_number' => [ +// array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::VAT_ID => '/>.<*']), +// null// It need to create some error but currently magento doesn't has validation for this field., +// ], + ]; + } + + /** + * Create customer address with provided address data. + * + * @param int $customerId + * @param array $addressData + * @param bool $isDefaultShipping + * @param bool $isDefaultBilling + * @return AddressInterface + */ + private function createAddress( + int $customerId, + array $addressData, + bool $isDefaultShipping = false, + bool $isDefaultBilling = false + ): AddressInterface { + if (isset($addressData['custom_region_name'])) { + $addressData[AddressInterface::REGION_ID] = $this->getRegionIdByName->execute( + $addressData['custom_region_name'], + $addressData[AddressInterface::COUNTRY_ID] + ); + unset($addressData['custom_region_name']); + } + + $addressData['attribute_set_id'] = $this->addressResource->getEntityType()->getDefaultAttributeSetId(); + $address = $this->addressFactory->create(['data' => $addressData]); + $address->setCustomerId($customerId); + $address->setIsDefaultShipping($isDefaultShipping); + $address->setIsDefaultBilling($isDefaultBilling); + $address = $this->addressRepository->save($address); + $this->customerRegistry->remove($customerId); + $this->addressRegistry->remove($address->getId()); + $this->createdAddressesIds[] = (int)$address->getId(); + + return $address; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/DeleteAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/DeleteAddressTest.php new file mode 100644 index 0000000000000..fe5437e294fc6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/DeleteAddressTest.php @@ -0,0 +1,92 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\Address; + +use Magento\Customer\Api\AddressRepositoryInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Assert that address was deleted successfully. + * + * @magentoDbIsolation enabled + */ +class DeleteAddressTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var CustomerRegistry + */ + private $customerRegistry; + + /** + * @var AddressRepositoryInterface + */ + private $addressRepository; + + /** + * @var CustomerRepositoryInterface + */ + private $customerRepository; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->customerRegistry = $this->objectManager->get(CustomerRegistry::class); + $this->addressRepository = $this->objectManager->get(AddressRepositoryInterface::class); + $this->customerRepository = $this->objectManager->get(CustomerRepositoryInterface::class); + parent::setUp(); + } + + /** + * Assert that address deleted successfully. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @return void + */ + public function testDeleteDefaultAddress(): void + { + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertEquals(1, $customer->getDefaultShipping()); + $this->assertEquals(1, $customer->getDefaultBilling()); + $customerAddresses = $customer->getAddresses() ?? []; + foreach ($customerAddresses as $address) { + $this->addressRepository->delete($address); + } + $this->customerRegistry->remove($customer->getId()); + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertNull($customer->getDefaultShipping()); + $this->assertNull($customer->getDefaultBilling()); + } + + /** + * Assert that deleting non-existent address throws exception. + * + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage No such entity with addressId = 1 + * + * @return void + */ + public function testDeleteMissingAddress(): void + { + $this->addressRepository->deleteById(1); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php new file mode 100644 index 0000000000000..8867f269cdf37 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php @@ -0,0 +1,294 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\Address; + +use Magento\Customer\Api\AddressRepositoryInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Api\Data\AddressInterface; +use Magento\Customer\Model\AddressRegistry; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Customer\Model\ResourceModel\Address; +use Magento\Framework\Exception\InputException; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Assert that address was updated as expected or address update throws expected error. + * + * @magentoDbIsolation enabled + */ +class UpdateAddressTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var AddressRegistry + */ + private $addressRegistry; + + /** + * @var Address + */ + private $addressResource; + + /** + * @var CustomerRegistry + */ + private $customerRegistry; + + /** + * @var AddressRepositoryInterface + */ + private $addressRepository; + + /** + * @var CustomerRepositoryInterface + */ + private $customerRepository; + + /** + * @var int[] + */ + private $processedAddressesIds = []; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->addressRegistry = $this->objectManager->get(AddressRegistry::class); + $this->addressResource = $this->objectManager->get(Address::class); + $this->customerRegistry = $this->objectManager->get(CustomerRegistry::class); + $this->addressRepository = $this->objectManager->get(AddressRepositoryInterface::class); + $this->customerRepository = $this->objectManager->get(CustomerRepositoryInterface::class); + parent::setUp(); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + foreach ($this->processedAddressesIds as $createdAddressesId) { + $this->addressRegistry->remove($createdAddressesId); + } + parent::tearDown(); + } + + /** + * Assert that default addresses properly updated for customer. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @dataProvider updateAddressIsDefaultDataProvider + * + * @param bool $isShippingDefault + * @param bool $isBillingDefault + * @param int|null $expectedShipping + * @param int|null $expectedBilling + * @return void + */ + public function testUpdateAddressIsDefault( + bool $isShippingDefault, + bool $isBillingDefault, + ?int $expectedShipping, + ?int $expectedBilling + ): void { + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertEquals(1, $customer->getDefaultShipping()); + $this->assertEquals(1, $customer->getDefaultBilling()); + $this->processedAddressesIds[] = 1; + $address = $this->addressRepository->getById(1); + $address->setIsDefaultShipping($isShippingDefault); + $address->setIsDefaultBilling($isBillingDefault); + $this->addressRepository->save($address); + $this->customerRegistry->remove(1); + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertEquals($customer->getDefaultShipping(), $expectedShipping); + $this->assertEquals($customer->getDefaultBilling(), $expectedBilling); + } + + /** + * Data provider for update address as default billing or default shipping. + * + * @return array + */ + public function updateAddressIsDefaultDataProvider(): array + { + return [ + 'update_shipping_address_default' => [true, false, 1, null], + 'update_billing_address_default' => [false, true, null, 1], + ]; + } + + /** + * Assert that address updated successfully. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @dataProvider updateAddressesDataProvider + * + * @param array $updateData + * @param array $expectedData + * @return void + */ + public function testUpdateAddress(array $updateData, array $expectedData): void + { + $this->processedAddressesIds[] = 1; + $address = $this->addressRepository->getById(1); + foreach ($updateData as $setFieldName => $setValue) { + $address->setData($setFieldName, $setValue); + } + $updatedAddressData = $this->addressRepository->save($address)->__toArray(); + foreach ($expectedData as $getFieldName => $getValue) { + $this->assertTrue(isset($updatedAddressData[$getFieldName]), "Field $getFieldName wasn't found."); + $this->assertEquals($getValue, $updatedAddressData[$getFieldName]); + } + } + + /** + * Data provider for update address with proper data. + * + * @return array + */ + public function updateAddressesDataProvider(): array + { + return [ + 'required_field_telephone' => [ + [AddressInterface::TELEPHONE => 251512979595], + [AddressInterface::TELEPHONE => 251512979595], + ], + 'required_field_postcode' => [ + [AddressInterface::POSTCODE => 55425], + [AddressInterface::POSTCODE => 55425], + ], + 'required_field_empty_postcode_for_uk' => [ + [AddressInterface::COUNTRY_ID => 'GB', AddressInterface::POSTCODE => ''], + [AddressInterface::COUNTRY_ID => 'GB', AddressInterface::POSTCODE => null], + ], + 'required_field_empty_region_id_for_ua' => [ + [AddressInterface::COUNTRY_ID => 'UA', AddressInterface::REGION_ID => ''], + [ + AddressInterface::COUNTRY_ID => 'UA', + AddressInterface::REGION_ID => 0, + ], + ], + 'required_field_firstname' => [ + [AddressInterface::FIRSTNAME => 'Test firstname'], + [AddressInterface::FIRSTNAME => 'Test firstname'], + ], + 'required_field_lastname' => [ + [AddressInterface::LASTNAME => 'Test lastname'], + [AddressInterface::LASTNAME => 'Test lastname'], + ], + 'required_field_street_as_array' => [ + [AddressInterface::STREET => ['', 'Test str, 55']], + [AddressInterface::STREET => ['Test str, 55']], + ], + 'required_field_city' => [ + [AddressInterface::CITY => 'Test city'], + [AddressInterface::CITY => 'Test city'], + ], + 'field_name_prefix' => [ + [AddressInterface::PREFIX => 'My prefix'], + [AddressInterface::PREFIX => 'My prefix'], + ], + 'field_middle_name_initial' => [ + [AddressInterface::MIDDLENAME => 'My middle name'], + [AddressInterface::MIDDLENAME => 'My middle name'], + ], + 'field_name_suffix' => [ + [AddressInterface::SUFFIX => 'My suffix'], + [AddressInterface::SUFFIX => 'My suffix'], + ], + 'field_company_name' => [ + [AddressInterface::COMPANY => 'My company'], + [AddressInterface::COMPANY => 'My company'], + ], + 'field_vat_number' => [ + [AddressInterface::VAT_ID => 'My VAT number'], + [AddressInterface::VAT_ID => 'My VAT number'], + ], + ]; + } + + /** + * Assert that error message has thrown during process address update. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @dataProvider updateWrongAddressesDataProvider + * + * @param array $updateData + * @param \Exception $expectException + * @return void + */ + public function testExceptionThrownDuringUpdateAddress(array $updateData, \Exception $expectException): void + { + $this->processedAddressesIds[] = 1; + $address = $this->addressRepository->getById(1); + foreach ($updateData as $setFieldName => $setValue) { + $address->setData($setFieldName, $setValue); + } + $this->expectExceptionObject($expectException); + $this->addressRepository->save($address); + } + + /** + * Data provider for update address with proper data or with error. + * + * @return array + */ + public function updateWrongAddressesDataProvider(): array + { + return [ + 'required_field_empty_telephone' => [ + [AddressInterface::TELEPHONE => ''], + InputException::requiredField('telephone'), + ], + 'required_field_empty_postcode_for_us' => [ + [AddressInterface::POSTCODE => ''], + InputException::requiredField('postcode'), + ], +// TODO: Uncomment this variation after fix issue https://jira.corp.magento.com/browse/MC-31031 +// 'required_field_empty_region_id_for_us' => [ +// [AddressInterface::REGION_ID => ''], +// InputException::requiredField('regionId'), +// ], + 'required_field_empty_firstname' => [ + [AddressInterface::FIRSTNAME => ''], + InputException::requiredField('firstname'), + ], + 'required_field_empty_lastname' => [ + [AddressInterface::LASTNAME => ''], + InputException::requiredField('lastname'), + ], + 'required_field_empty_street_as_array' => [ + [AddressInterface::STREET => []], + InputException::requiredField('street'), + ], + 'required_field_empty_city' => [ + [AddressInterface::CITY => ''], + InputException::requiredField('city'), + ], +// TODO: Uncomment this variation after fix issue https://jira.corp.magento.com/browse/MC-31031 +// 'field_invalid_vat_number' => [ +// [AddressInterface::VAT_ID => '/>.<*'], +// null// It need to create some error but currently magento doesn't has validation for this field., +// ], + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_no_address_rollback.php b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_no_address_rollback.php new file mode 100644 index 0000000000000..9909856322e13 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_no_address_rollback.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +/** @var CustomerRegistry $customerRegistry */ +$customerRegistry = $objectManager->get(CustomerRegistry::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +try { + $customerRegistry->remove(5); + $customerRepository->deleteById(5); +} catch (NoSuchEntityException $e) { + //Customer already deleted. +} +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); From 63815dbdfe955e71ae6490e3bd993250e17e1d84 Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Fri, 7 Feb 2020 15:20:15 +0200 Subject: [PATCH 124/176] MC-31083: [FT] [MFTF] Fix test AdminCreateImageSwatchTest - delete created swatch attribute in after --- ...minDeleteProductAttributeByLabelActionGroup.xml | 12 ++++++------ .../Mftf/Data/AdminProductAttributeMessageData.xml | 14 ++++++++++++++ .../Test/Mftf/Test/AdminCreateImageSwatchTest.xml | 9 +++------ 3 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/Data/AdminProductAttributeMessageData.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml index 7898fae279eaf..21cc90ba4b4e8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml @@ -13,19 +13,19 @@ <description>Goes to the Admin Product Attributes grid page. Filters the grid for the provided Product Attribute (Label). Deletes the Product Attribute from the grid. Validates that the Success Message is present.</description> </annotations> <arguments> - <argument name="productAttributeLabel" type="string"/> + <argument name="productAttributeLabel" type="string" defaultValue="ProductAttributeFrontendLabel.label"/> </arguments> <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid"/> <waitForPageLoad stepKey="waitForProductAttributeGridPageLoad"/> + <click selector="{{AdminProductAttributeGridSection.ResetFilter}}" stepKey="resetFiltersOnGrid"/> <fillField selector="{{AdminProductAttributeGridSection.attributeLabelFilter}}" userInput="{{productAttributeLabel}}" stepKey="setAttributeLabelFilter"/> <click selector="{{AdminProductAttributeGridSection.Search}}" stepKey="searchForAttributeLabelFromTheGrid"/> <click selector="{{AdminProductAttributeGridSection.FirstRow}}" stepKey="clickOnAttributeRow"/> <click selector="{{AttributePropertiesSection.DeleteAttribute}}" stepKey="clickOnDeleteAttributeButton"/> - <waitForElementVisible selector="{{ModalConfirmationSection.modalContent}}" stepKey="waitForConfirmationPopUpVisible"/> - <click selector="{{ModalConfirmationSection.OkButton}}" stepKey="clickOnConfirmationButton"/> - <waitForPageLoad stepKey="waitForAttributeGridPageLoad"/> - <waitForElementVisible selector="{{AdminProductMessagesSection.successMessage}}" stepKey="waitForSuccessMessageVisible"/> - <see selector="{{AdminProductMessagesSection.successMessage}}" userInput="You deleted the product attribute." stepKey="seeAttributeDeleteSuccessMessage"/> + <waitForElementVisible selector="{{AdminConfirmationModalSection.message}}" stepKey="waitForConfirmationPopUpVisible"/> + <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="clickOnConfirmationButton"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessageVisible"/> + <see selector="{{AdminMessagesSection.success}}" userInput="{{ProductAttributeMessages.remove_success}}" stepKey="seeAttributeDeleteSuccessMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/AdminProductAttributeMessageData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/AdminProductAttributeMessageData.xml new file mode 100644 index 0000000000000..834abdad497b8 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Data/AdminProductAttributeMessageData.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="ProductAttributeMessages"> + <data key="remove_success">You deleted the product attribute.</data> + </entity> +</entities> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml index 34eaa2f34ba17..372df5bd3acee 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml @@ -30,6 +30,7 @@ <actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteProductAttribute"> <argument name="productAttributeLabel" value="{{ProductAttributeFrontendLabel.label}}"/> </actionGroup> + <actionGroup ref="NavigateToAndResetProductAttributeGridToDefaultViewActionGroup" stepKey="resetProductAttributeFilters"/> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </after> @@ -102,11 +103,7 @@ </assertContains> <!-- Create a configurable product to verify the storefront with --> - <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> - <waitForPageLoad time="30" stepKey="waitForProductGrid"/> - <actionGroup ref="GoToCreateProductPageActionGroup" stepKey="goToCreateConfigurableProduct"> - <argument name="product" value="BaseConfigurableProduct"/> - </actionGroup> + <amOnPage url="{{AdminProductCreatePage.url(BaseConfigurableProduct.attribute_set_id, BaseConfigurableProduct.type_id)}}" stepKey="goToCreateConfigurableProduct"/> <actionGroup ref="FillMainProductFormActionGroup" stepKey="fillProductForm"> <argument name="product" value="BaseConfigurableProduct"/> </actionGroup> @@ -150,7 +147,7 @@ </assertContains> <!-- Go to the product listing page and see text swatch options --> - <amOnPage url="$$createCategory.name$$.html" stepKey="goToCategoryPageStorefront"/> + <amOnPage url="$$createCategory.custom_attributes[url_key]$$.html" stepKey="goToCategoryPageStorefront"/> <waitForPageLoad stepKey="waitForProductListingPage"/> <!-- Verify the storefront --> From 17600435ec7aed34dc93fcbda71f3bf8a2e1db09 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 7 Feb 2020 15:37:28 +0200 Subject: [PATCH 125/176] cover changes with unit test --- .../Search/Test/Unit/Block/TermsTest.php | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 app/code/Magento/Search/Test/Unit/Block/TermsTest.php diff --git a/app/code/Magento/Search/Test/Unit/Block/TermsTest.php b/app/code/Magento/Search/Test/Unit/Block/TermsTest.php new file mode 100644 index 0000000000000..d2e7e94a65f8e --- /dev/null +++ b/app/code/Magento/Search/Test/Unit/Block/TermsTest.php @@ -0,0 +1,173 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Search\Test\Unit\Block; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Url; +use Magento\Framework\UrlFactory; +use Magento\Framework\View\Element\Template\Context; +use Magento\Search\Block\Term; +use Magento\Search\Model\Query; +use Magento\Search\Model\ResourceModel\Query\Collection; +use Magento\Search\Model\ResourceModel\Query\CollectionFactory; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManager; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Tests for Terms block + */ +class TermsTest extends TestCase +{ + /** + * @var Context|MockObject + */ + private $contextMock; + + /** + * @var CollectionFactory|MockObject + */ + private $collectionFactoryMock; + + /** + * @var UrlFactory|MockObject + */ + private $urlFactoryMock; + + /** + * @var Term + */ + private $termsModel; + + /** + * @var StoreManager + */ + private $storeManagerMock; + + /** + * @inheritdoc + */ + public function setUp() + { + $objectManager = new ObjectManager($this); + + $this->contextMock = $this->createMock(Context::class); + $this->collectionFactoryMock = $this->createMock(CollectionFactory::class); + $this->urlFactoryMock = $this->createMock(UrlFactory::class); + $this->storeManagerMock = $this->createMock(StoreManager::class); + + $this->contextMock->expects($this->once()) + ->method('getStoreManager') + ->willReturn($this->storeManagerMock); + $this->termsModel = $objectManager->getObject( + Term::class, + [ + 'context' => $this->contextMock, + '_queryCollectionFactory' => $this->collectionFactoryMock, + '_urlFactory' => $this->urlFactoryMock + ] + ); + } + + /** + * Verify terms + * + * @dataProvider termKeysProvider + * @param string $termKey + * @param bool $popularity + */ + public function testGetTerms(string $termKey, bool $popularity): void + { + $terms = $this->createMock(Collection::class); + $dataObjectMock = $this->getMockBuilder(Query::class) + ->disableOriginalConstructor() + ->setMethods(['getPopularity', 'getQueryText']) + ->getMock(); + $storeMock = $this->createMock(Store::class); + + $this->storeManagerMock->expects($this->once()) + ->method('getStore') + ->willReturn($storeMock); + $storeMock->expects($this->once()) + ->method('getId') + ->willReturn(1); + + $this->collectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($terms); + $terms->expects($this->once()) + ->method('setPopularQueryFilter') + ->willReturnSelf(); + $terms->expects($this->once()) + ->method('setPageSize') + ->willReturnSelf(); + $terms->expects($this->once()) + ->method('load') + ->willReturnSelf(); + $terms->expects($this->once()) + ->method('getItems') + ->willReturn([$dataObjectMock]); + $dataObjectMock->expects($this->exactly(!$popularity ? 3 : 4)) + ->method('getPopularity') + ->willReturn($popularity); + $dataObjectMock->expects($this->exactly(!$popularity ? 0 : 2)) + ->method('getQueryText') + ->willReturn($termKey); + + $this->assertEquals(!$popularity ? [] : [$termKey => $dataObjectMock], $this->termsModel->getTerms()); + } + + /** + * Verify get search Url + * + * @return void + */ + public function testGetSearchResult(): void + { + $urlMock = $this->getMockBuilder(Url::class) + ->disableOriginalConstructor() + ->setMethods(['setQueryParam', 'getUrl']) + ->getMock(); + + $dataObjectMock = $this->getMockBuilder(Query::class) + ->disableOriginalConstructor() + ->setMethods(['getPopularity', 'getQueryText']) + ->getMock(); + $this->urlFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($urlMock); + $dataObjectMock->expects($this->once()) + ->method('getQueryText') + ->willReturn('url'); + $urlMock->expects($this->once())->method('setQueryParam'); + $urlMock->expects($this->once()) + ->method('getUrl') + ->with('catalogsearch/result') + ->willReturn('url'); + + $this->assertEquals('url', $this->termsModel->getSearchUrl($dataObjectMock)); + } + + /** + * Terms data key provider + * + * @return array + */ + public function termKeysProvider(): array + { + return [ + [ + 'search', + true + ], + [ + '', + false + ] + ]; + } +} From d1f1ebaf34dab66e16acf52a4a0b135282399d1c Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 7 Feb 2020 15:42:35 +0200 Subject: [PATCH 126/176] remove unesscesary check --- app/code/Magento/Search/Block/Term.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/Search/Block/Term.php b/app/code/Magento/Search/Block/Term.php index 9010e3e1dbbc1..ed6a2c5215b54 100644 --- a/app/code/Magento/Search/Block/Term.php +++ b/app/code/Magento/Search/Block/Term.php @@ -100,9 +100,7 @@ protected function _loadTerms() $temp[$term->getQueryText()] = $term; $termKeys[] = $term->getQueryText(); } - if (empty($termKeys)) { - return $this; - } + natcasesort($termKeys); foreach ($termKeys as $termKey) { From aa344a181a41439623f5f9021052a1ac0b6c4750 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Fri, 7 Feb 2020 15:44:20 +0200 Subject: [PATCH 127/176] MC-31267: Storefront: Check bundle product regular price --- .../View/Type/BundleProductPriceTest.php | 172 ++++++++++++++++++ ...amic_bundle_product_multiselect_option.php | 97 ++++++++++ ...le_product_multiselect_option_rollback.php | 22 +++ .../Bundle/_files/multiple_products.php | 116 ++++++------ 4 files changed, 351 insertions(+), 56 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleProductPriceTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleProductPriceTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleProductPriceTest.php new file mode 100644 index 0000000000000..2a61a252e9313 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleProductPriceTest.php @@ -0,0 +1,172 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Block\Catalog\Product\View\Type; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Check bundle product prices. + * + * @magentoDbIsolation enabled + * @magentoAppIsolation disabled + * @magentoAppArea frontend + */ +class BundleProductPriceTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Registry */ + private $registry; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var SerializerInterface */ + private $json; + + /** @var Bundle */ + private $block; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Bundle::class); + $this->registry = $this->objectManager->get(Registry::class); + $this->json = $this->objectManager->get(SerializerInterface::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister('product'); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_multiselect_option.php + * + * @return void + */ + public function testDynamicBundleOptionPrices(): void + { + $expectedData = [ + 'options_prices' => [ + [ + 'oldPrice' => ['amount' => 10], + 'basePrice' => ['amount' => 10], + 'finalPrice' => ['amount' => 10], + ], + [ + 'oldPrice' => ['amount' => 20], + 'basePrice' => ['amount' => 20], + 'finalPrice' => ['amount' => 20], + ], + [ + 'oldPrice' => ['amount' => 30], + 'basePrice' => ['amount' => 30], + 'finalPrice' => ['amount' => 30], + ], + ], + 'bundle_prices' => [ + 'oldPrice' => ['amount' => 0], + 'basePrice' => ['amount' => 0], + 'finalPrice' => ['amount' => 0], + ] + ]; + $this->processBundlePriceView('bundle_product', $expectedData); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/product_with_multiple_options_1.php + * + * @return void + */ + public function testFixedBundleOptionPrices(): void + { + $expectedData = [ + 'options_prices' => [ + [ + 'oldPrice' => ['amount' => 2.75], + 'basePrice' => ['amount' => 2.75], + 'finalPrice' => ['amount' => 2.75], + ], + [ + 'oldPrice' => ['amount' => 6.75], + 'basePrice' => ['amount' => 6.75], + 'finalPrice' => ['amount' => 6.75], + ], + ], + 'bundle_prices' => [ + 'oldPrice' => ['amount' => 12.75], + 'basePrice' => ['amount' => 10], + 'finalPrice' => ['amount' => 10], + ] + ]; + $this->processBundlePriceView('bundle-product', $expectedData); + } + + /** + * @param string $productSku + * @param array $expectedData + * @return void + */ + private function processBundlePriceView(string $productSku, array $expectedData): void + { + $this->registerProduct($productSku); + $jsonConfig = $this->json->unserialize($this->block->getJsonConfig()); + $this->assertEquals($expectedData['bundle_prices'], $jsonConfig['prices']); + $this->assertOptionsConfig($expectedData['options_prices'], $jsonConfig); + } + + /** + * Assert options prices. + * + * @param array $expectedData + * @param array $actualData + * @return void + */ + private function assertOptionsConfig(array $expectedData, array $actualData): void + { + $optionConfig = $actualData['options'] ?? null; + $this->assertNotNull($optionConfig); + $optionConfig = reset($optionConfig); + foreach (array_values($optionConfig['selections']) as $key => $selection) { + $this->assertEquals($expectedData[$key], $selection['prices']); + } + } + + /** + * Register the product. + * + * @param string $productSku + * @return void + */ + private function registerProduct(string $productSku): void + { + $product = $this->productRepository->get($productSku); + $this->registry->unregister('product'); + $this->registry->register('product', $product); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option.php new file mode 100644 index 0000000000000..c9e2bfb74090b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option.php @@ -0,0 +1,97 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Api\Data\LinkInterfaceFactory; +use Magento\Bundle\Api\Data\OptionInterfaceFactory; +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\Data\ProductExtensionFactory; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; + +require __DIR__ . '/multiple_products.php'; + +/** @var ProductExtensionFactory $extensionAttributesFactory */ +$extensionAttributesFactory = $objectManager->get(ProductExtensionFactory::class); +/** @var OptionInterfaceFactory $optionFactory */ +$optionFactory = $objectManager->get(OptionInterfaceFactory::class); +/** @var LinkInterfaceFactory $linkFactory */ +$linkFactory = $objectManager->get(LinkInterfaceFactory::class); + +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$defaultWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle_product') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ] + ) + ->setSkuType(0) + ->setPriceView(0) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setWeightType(0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER) + ->setBundleOptionsData( + [ + [ + 'title' => 'Option 1', + 'default_title' => 'Option 1', + 'type' => 'multi', + 'required' => 1, + ], + ] + )->setBundleSelectionsData( + [ + [ + [ + 'product_id' => $product->getId(), + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_can_change_qty' => 1, + ], + [ + 'product_id' => $product2->getId(), + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_can_change_qty' => 1, + ], + [ + 'product_id' => $product3->getId(), + 'sku' => $product3->getSku(), + 'selection_qty' => 1, + 'selection_can_change_qty' => 1, + ], + ] + ] + ); + +$options = []; +foreach ($bundleProduct->getBundleOptionsData() as $key => $optionData) { + $option = $optionFactory->create(['data' => $optionData]); + $option->setSku($bundleProduct->getSku()); + $option->setOptionId(null); + $links = []; + foreach ($bundleProduct->getBundleSelectionsData()[$key] as $linkData) { + $link = $linkFactory->create(['data' => $linkData]); + $links[] = $link; + } + $option->setProductLinks($links); + $options[] = $option; +} +$extensionAttributes = $bundleProduct->getExtensionAttributes() ?: $extensionAttributesFactory->create(); +$extensionAttributes->setBundleProductOptions($options); +$bundleProduct->setExtensionAttributes($extensionAttributes); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option_rollback.php new file mode 100644 index 0000000000000..25ebbd14bfa39 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option_rollback.php @@ -0,0 +1,22 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/multiple_products_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $product = $productRepository->get('bundle_product', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php index 662b69c89bc6d..fa957a0bfd3f8 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php @@ -3,31 +3,44 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); -$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() - ->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Api\Data\ProductInterfaceFactory; +use Magento\Catalog\Model\Product\Type as ProductType; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Msrp\Model\Product\Attribute\Source\Type; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; -/** @var $product \Magento\Catalog\Model\Product */ -$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); -$product->isObjectNew(true); -$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductInterfaceFactory $productFactory */ +$productFactory = $objectManager->get(ProductInterfaceFactory::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(ProductRepositoryInterface::class); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$defaultWebsiteId = $websiteRepository->get('base')->getId(); +$product = $productFactory->create(); +$product->setTypeId(ProductType::TYPE_SIMPLE) ->setId(10) - ->setAttributeSetId(4) + ->setAttributeSetId($product->getDefaultAttributeSetId()) ->setName('Simple Product') ->setSku('simple1') - ->setTaxClassId('none') + ->setTaxClassId(0) ->setDescription('description') ->setShortDescription('short description') ->setOptionsContainer('container1') - ->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_IN_CART) + ->setMsrpDisplayActualPriceType(Type::TYPE_IN_CART) ->setPrice(10) ->setWeight(1) ->setMetaTitle('meta title') ->setMetaKeyword('meta keyword') ->setMetaDescription('meta description') - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setWebsiteIds([1]) + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setWebsiteIds([$defaultWebsiteId]) ->setCategoryIds([]) ->setStockData([ 'use_config_manage_stock' => 1, @@ -36,29 +49,27 @@ 'is_in_stock' => 1, 'manage_stock' => 1, ]); - $productRepository->save($product); -$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); -$product->isObjectNew(true); -$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) +$product2 = $productFactory->create(); +$product2->setTypeId(ProductType::TYPE_SIMPLE) ->setId(11) - ->setAttributeSetId(4) + ->setAttributeSetId($product2->getDefaultAttributeSetId()) ->setName('Simple Product2') ->setSku('simple2') - ->setTaxClassId('none') + ->setTaxClassId(0) ->setDescription('description') ->setShortDescription('short description') ->setOptionsContainer('container1') - ->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_ON_GESTURE) + ->setMsrpDisplayActualPriceType(Type::TYPE_ON_GESTURE) ->setPrice(20) ->setWeight(1) ->setMetaTitle('meta title') ->setMetaKeyword('meta keyword') ->setMetaDescription('meta description') - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_CATALOG) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setWebsiteIds([1]) + ->setVisibility(Visibility::VISIBILITY_IN_CATALOG) + ->setStatus(Status::STATUS_ENABLED) + ->setWebsiteIds([$defaultWebsiteId]) ->setCategoryIds([]) ->setStockData([ 'use_config_manage_stock' => 1, @@ -67,24 +78,22 @@ 'is_in_stock' => 1, 'manage_stock' => 1, ]); +$productRepository->save($product2); -$productRepository->save($product); - -$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); -$product->isObjectNew(true); -$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) +$product3 = $productFactory->create(); +$product3->setTypeId(ProductType::TYPE_SIMPLE) ->setId(12) - ->setAttributeSetId(4) + ->setAttributeSetId($product3->getDefaultAttributeSetId()) ->setName('Simple Product 3') ->setSku('simple3') - ->setTaxClassId('none') + ->setTaxClassId(0) ->setDescription('description') ->setShortDescription('short description') ->setPrice(30) ->setWeight(1) - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_CATALOG) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setWebsiteIds([1]) + ->setVisibility(Visibility::VISIBILITY_IN_CATALOG) + ->setStatus(Status::STATUS_ENABLED) + ->setWebsiteIds([$defaultWebsiteId]) ->setCategoryIds([]) ->setStockData([ 'use_config_manage_stock' => 1, @@ -93,29 +102,27 @@ 'is_in_stock' => 1, 'manage_stock' => 1, ]); +$productRepository->save($product3); -$productRepository->save($product); - -$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); -$product->isObjectNew(true); -$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) +$product4 = $productFactory->create(); +$product4->setTypeId(ProductType::TYPE_SIMPLE) ->setId(13) - ->setAttributeSetId(4) + ->setAttributeSetId($product4->getDefaultAttributeSetId()) ->setName('Simple Product 4') ->setSku('simple4') - ->setTaxClassId('none') + ->setTaxClassId(0) ->setDescription('description') ->setShortDescription('short description') ->setOptionsContainer('container1') - ->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_IN_CART) + ->setMsrpDisplayActualPriceType(Type::TYPE_IN_CART) ->setPrice(13) ->setWeight(12) ->setMetaTitle('meta title') ->setMetaKeyword('meta keyword') ->setMetaDescription('meta description') - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setWebsiteIds([1]) + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setWebsiteIds([$defaultWebsiteId]) ->setCategoryIds([]) ->setStockData([ 'use_config_manage_stock' => 1, @@ -124,29 +131,27 @@ 'is_in_stock' => 1, 'manage_stock' => 1, ]); +$productRepository->save($product4); -$productRepository->save($product); - -$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); -$product->isObjectNew(true); -$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) +$product5 = $productFactory->create(); +$product5->setTypeId(ProductType::TYPE_SIMPLE) ->setId(14) - ->setAttributeSetId(4) + ->setAttributeSetId($product5->getDefaultAttributeSetId()) ->setName('Simple Product 5') ->setSku('simple5') - ->setTaxClassId('none') + ->setTaxClassId(0) ->setDescription('description') ->setShortDescription('short description') ->setOptionsContainer('container1') - ->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_IN_CART) + ->setMsrpDisplayActualPriceType(Type::TYPE_IN_CART) ->setPrice(14) ->setWeight(10) ->setMetaTitle('meta title') ->setMetaKeyword('meta keyword') ->setMetaDescription('meta description') - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setWebsiteIds([1]) + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setWebsiteIds([$defaultWebsiteId]) ->setCategoryIds([]) ->setStockData([ 'use_config_manage_stock' => 1, @@ -155,5 +160,4 @@ 'is_in_stock' => 1, 'manage_stock' => 1, ]); - -$productRepository->save($product); +$productRepository->save($product5); From 0a816b9ae0395ba3706a2a9410ade663a779ad7c Mon Sep 17 00:00:00 2001 From: Mykhailo Matiola <mykhailo.matiola@transoftgroup.com> Date: Fri, 7 Feb 2020 15:57:48 +0200 Subject: [PATCH 128/176] MC-31260: Storefront: Create/update customer --- .../AccountManagement/CreateAccountTest.php | 177 ++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php new file mode 100644 index 0000000000000..03473e9247c51 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php @@ -0,0 +1,177 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\AccountManagement; + +use Magento\Customer\Api\AccountManagementInterface; +use Magento\Customer\Api\Data\CustomerInterface; +use Magento\Customer\Api\Data\CustomerInterfaceFactory; +use Magento\Framework\Api\DataObjectHelper; +use Magento\Framework\Exception\InputException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Math\Random; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Validator\Exception; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Tests for customer creation via customer account management service. + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + */ +class CreateAccountTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var AccountManagementInterface + */ + private $accountManagement; + + /** + * @var CustomerInterfaceFactory + */ + private $customerFactory; + + /** + * @var DataObjectHelper + */ + private $dataObjectHelper; + + /** + * @var array + */ + private $defaultCustomerData = [ + 'email' => 'customer@example.com', + 'firstname' => 'First name', + 'lastname' => 'Last name', + ]; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->accountManagement = $this->objectManager->get(AccountManagementInterface::class); + $this->customerFactory = $this->objectManager->get(CustomerInterfaceFactory::class); + $this->dataObjectHelper = $this->objectManager->create(DataObjectHelper::class); + parent::setUp(); + } + + /** + * @dataProvider createInvalidAccountDataProvider + * @param array $customerData + * @param string $password + * @param string $errorType + * @param string $errorMessage + * @return void + */ + public function testCreateAccountWithInvalidFields( + array $customerData, + string $password, + string $errorType, + array $errorMessage + ): void { + $data = array_merge($this->defaultCustomerData, $customerData); + $customerEntity = $this->customerFactory->create(); + $this->dataObjectHelper->populateWithArray($customerEntity, $data, CustomerInterface::class); + $this->expectException($errorType); + $this->expectExceptionMessage((string)__(...$errorMessage)); + $this->accountManagement->createAccount($customerEntity, $password); + } + + /** + * @return array + */ + public function createInvalidAccountDataProvider(): array + { + return [ + 'empty_firstname' => [ + 'customer_data' => ['firstname' => ''], + 'password' => '_aPassword1', + 'error_type' => Exception::class, + 'error_message' => ['"%1" is a required value.', 'First Name'], + ], + 'empty_lastname' => [ + 'customer_data' => ['lastname' => ''], + 'password' => '_aPassword1', + 'error_type' => Exception::class, + 'error_message' => ['"%1" is a required value.', 'Last Name'], + ], + 'empty_email' => [ + 'customer_data' => ['email' => ''], + 'password' => '_aPassword1', + 'error_type' => Exception::class, + 'error_message' => ['The customer email is missing. Enter and try again.'], + ], + 'invalid_email' => [ + 'customer_data' => ['email' => 'zxczxczxc'], + 'password' => '_aPassword1', + 'error_type' => Exception::class, + 'error_message' => ['"%1" is not a valid email address.', 'Email'], + ], + 'empty_password' => [ + 'customer_data' => [], + 'password' => '', + 'error_type' => InputException::class, + 'error_message' => ['The password needs at least 8 characters. Create a new password and try again.'], + ], + 'invalid_password_minimum_length' => [ + 'customer_data' => [], + 'password' => 'test', + 'error_type' => InputException::class, + 'error_message' => ['The password needs at least 8 characters. Create a new password and try again.'], + ], + 'invalid_password_maximum_length' => [ + 'customer_data' => [], + 'password' => $this->getRandomNumericString(257), + 'error_type' => InputException::class, + 'error_message' => ['Please enter a password with at most 256 characters.'], + ], + 'invalid_password_without_minimum_characters_classes' => [ + 'customer_data' => [], + 'password' => 'test_password', + 'error_type' => InputException::class, + 'error_message' => [ + 'Minimum of different classes of characters in password is %1.' + . ' Classes of characters: Lower Case, Upper Case, Digits, Special Characters.', + 3, + ], + ], + 'password_same_as_email' => [ + 'customer_data' => ['email' => 'test1@test.com'], + 'password' => 'test1@test.com', + 'error_type' => LocalizedException::class, + 'error_message' => [ + 'The password can\'t be the same as the email address. Create a new password and try again.', + ], + ], + ]; + } + + /** + * Returns random numeric string with given length. + * + * @param int $length + * @return string + */ + private function getRandomNumericString(int $length): string + { + $string = ''; + for ($i = 0; $i <= $length; $i++) { + $string .= Random::getRandomNumber(0, 9); + } + + return $string; + } +} From dec34b35139d773c24a59d3cfbe3e9786c30659e Mon Sep 17 00:00:00 2001 From: Mykhailo Matiola <mykhailo.matiola@transoftgroup.com> Date: Fri, 7 Feb 2020 16:01:59 +0200 Subject: [PATCH 129/176] MC-31269: Admin: Add/edit/delete custom options to configurable product --- .../Product/Save/CreateCustomOptionsTest.php | 10 ++++--- .../Product/Save/DeleteCustomOptionsTest.php | 10 ++++--- .../Product/Save/UpdateCustomOptionsTest.php | 10 ++++--- .../Product/Save/CreateCustomOptionsTest.php | 26 +++++++++++++++++++ .../Product/Save/DeleteCustomOptionsTest.php | 26 +++++++++++++++++++ .../Product/Save/UpdateCustomOptionsTest.php | 26 +++++++++++++++++++ 6 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php index f979bad9d0f76..a4631526bd4c5 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php @@ -19,9 +19,15 @@ * * @magentoAppArea adminhtml * @magentoDbIsolation enabled + * @magentoDataFixture Magento/Catalog/_files/product_without_options.php */ class CreateCustomOptionsTest extends AbstractBackendController { + /** + * @var string + */ + protected $productSku = 'simple'; + /** * @var ProductRepositoryInterface */ @@ -46,8 +52,6 @@ protected function setUp() /** * Test add to product custom option with type "field". * - * @magentoDataFixture Magento/Catalog/_files/product_without_options.php - * * @dataProvider productWithNewOptionsDataProvider * * @param array $productPostData @@ -57,7 +61,7 @@ protected function setUp() public function testSaveCustomOptionWithTypeField(array $productPostData): void { $this->getRequest()->setPostValue($productPostData); - $product = $this->productRepository->get('simple'); + $product = $this->productRepository->get($this->productSku); $this->getRequest()->setMethod(HttpRequest::METHOD_POST); $this->dispatch('backend/catalog/product/save/id/' . $product->getEntityId()); $this->assertSessionMessages( diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php index f1af6e6e41cff..6a4ff066f710d 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php @@ -21,9 +21,15 @@ * * @magentoAppArea adminhtml * @magentoDbIsolation enabled + * @magentoDataFixture Magento/Catalog/_files/product_without_options.php */ class DeleteCustomOptionsTest extends AbstractBackendController { + /** + * @var string + */ + protected $productSku = 'simple'; + /** * @var ProductRepositoryInterface */ @@ -54,8 +60,6 @@ protected function setUp() /** * Test delete custom option with type "field". * - * @magentoDataFixture Magento/Catalog/_files/product_without_options.php - * * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Option\DataProvider\Type\Field::getDataForCreateOptions * * @param array $optionData @@ -63,7 +67,7 @@ protected function setUp() */ public function testDeleteCustomOptionWithTypeField(array $optionData): void { - $product = $this->productRepository->get('simple'); + $product = $this->productRepository->get($this->productSku); /** @var ProductCustomOptionInterface $option */ $option = $this->optionRepositoryFactory->create(['data' => $optionData]); $option->setProductSku($product->getSku()); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php index a45c21444a5d7..1badf6a1a081a 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php @@ -22,9 +22,15 @@ * * @magentoAppArea adminhtml * @magentoDbIsolation enabled + * @magentoDataFixture Magento/Catalog/_files/product_without_options.php */ class UpdateCustomOptionsTest extends AbstractBackendController { + /** + * @var string + */ + protected $productSku = 'simple'; + /** * @var ProductRepositoryInterface */ @@ -55,8 +61,6 @@ protected function setUp() /** * Test add to product custom option with type "field". * - * @magentoDataFixture Magento/Catalog/_files/product_without_options.php - * * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Option\DataProvider\Type\Field::getDataForUpdateOptions * * @param array $optionData @@ -65,7 +69,7 @@ protected function setUp() */ public function testUpdateCustomOptionWithTypeField(array $optionData, array $updateData): void { - $product = $this->productRepository->get('simple'); + $product = $this->productRepository->get($this->productSku); /** @var ProductCustomOptionInterface|Option $option */ $option = $this->optionRepositoryFactory->create(['data' => $optionData]); $option->setProductSku($product->getSku()); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php new file mode 100644 index 0000000000000..20cfbda0ac920 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ConfigurableProduct\Controller\Adminhtml\Product\Save; + +use Magento\Catalog\Controller\Adminhtml\Product\Save\CreateCustomOptionsTest as SimpleProductOptionsTest; + +/** + * Base test cases for configurable product custom options with type "field". + * Option add via dispatch product controller action save with options data in POST data. + * + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ +class CreateCustomOptionsTest extends SimpleProductOptionsTest +{ + /** + * @var string + */ + protected $productSku = 'configurable'; +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php new file mode 100644 index 0000000000000..58b7f0e56fb0c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ConfigurableProduct\Controller\Adminhtml\Product\Save; + +use Magento\Catalog\Controller\Adminhtml\Product\Save\DeleteCustomOptionsTest as SimpleProductOptionsTest; + +/** + * Base test cases for delete configurable product custom option with type "field". + * Option deleting via product controller action save. + * + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ +class DeleteCustomOptionsTest extends SimpleProductOptionsTest +{ + /** + * @var string + */ + protected $productSku = 'configurable'; +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php new file mode 100644 index 0000000000000..ab0b03489cb92 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ConfigurableProduct\Controller\Adminhtml\Product\Save; + +use Magento\Catalog\Controller\Adminhtml\Product\Save\UpdateCustomOptionsTest as SimpleProductOptionsTest; + +/** + * Base test cases for update configurable product custom options with type "field". + * Option updating via dispatch product controller action save with updated options data in POST data. + * + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ +class UpdateCustomOptionsTest extends SimpleProductOptionsTest +{ + /** + * @var string + */ + protected $productSku = 'configurable'; +} From 4ff98439037e473340b7e31c340b3cf373aa0b71 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Fri, 7 Feb 2020 16:14:32 +0200 Subject: [PATCH 130/176] MC-24236: [MFTF Test] Unskip MFTF test MC-13607 "Verify that Catalog Price Rule and Customer Group Membership are persisted under long-term cookie" --- .../Test/Mftf/Section/StorefrontCategoryProductSection.xml | 2 +- ...stomerGroupMembershipArePersistedUnderLongTermCookieTest.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml index 9ee019c9e934e..12fd350612d7d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml @@ -21,7 +21,7 @@ <element name="ProductTitleByName" type="button" selector="//main//li//a[contains(text(), '{{var1}}')]" parameterized="true"/> <element name="ProductPriceByName" type="text" selector="//main//li[.//a[contains(text(), '{{var1}}')]]//span[@class='price']" parameterized="true"/> - <element name="ProductCatalogRuleSpecialPriceTitleByName" type="text" selector="//main//li[.//a[contains(text(), '{{productName}}')]]//span[@data-price-type='finalPrice']/span" parameterized="true"/> + <element name="ProductCatalogRuleSpecialPriceTitleByName" type="text" selector="//main//li[.//a[contains(text(), '{{productName}}')]]//span[@class='special-price']/span" parameterized="true"/> <element name="ProductCatalogRulePriceTitleByName" type="text" selector="//div[descendant::*[contains(text(), '{{var1}}')]]//*[contains(@class, 'price-label')]" parameterized="true"/> <element name="ProductImageByName" type="text" selector="//main//li[.//a[contains(text(), '{{var1}}')]]//img[@class='product-image-photo']" parameterized="true"/> <element name="ProductImageBySrc" type="text" selector=".products-grid img[src*='{{pattern}}']" parameterized="true"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml index 9bae928c66426..65a0e30e17b37 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml @@ -99,5 +99,6 @@ <argument name="categoryUrl" value="$createCategory.custom_attributes[url_key]$"/> <argument name="productName" value="$createProduct.name$"/> </actionGroup> + <dontSeeElement selector="{{StorefrontCategoryProductSection.ProductCatalogRuleSpecialPriceTitleByName($createProduct.name$)}}" stepKey="dontSeeSpecialPrice"/> </test> </tests> From 9b585ee2963994a56c4ca35fd80c8cb6d5c7fd44 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Fri, 7 Feb 2020 17:13:24 +0200 Subject: [PATCH 131/176] MC-30650: [Magento Cloud] Customer Creation - The store view is not in the associated website --- .../Test/CheckTierPricingOfProductsTest.xml | 2 + .../Controller/Adminhtml/Index/Save.php | 8 +- .../Customer/Model/AccountManagement.php | 24 +- .../Controller/Adminhtml/Index/SaveTest.php | 5 +- .../Test/Unit/Model/AccountManagementTest.php | 161 +++++++------- .../Unit/ViewModel/Customer/StoreTest.php | 210 ++++++++++++++++++ .../Customer/ViewModel/Customer/Store.php | 131 +++++++++++ .../view/base/ui_component/customer_form.xml | 8 +- .../web/js/lib/knockout/bindings/optgroup.js | 2 +- 9 files changed, 460 insertions(+), 91 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Unit/ViewModel/Customer/StoreTest.php create mode 100644 app/code/Magento/Customer/ViewModel/Customer/Store.php diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml index 4e0e8d03f59d5..f80cfed54c8f3 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml @@ -36,6 +36,7 @@ <createData entity="Simple_US_Customer" stepKey="customer"/> <!--Login as admin--> <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + <createData entity="CustomerAccountSharingGlobal" stepKey="setConfigCustomerAccountToGlobal"/> </before> <!--Create website, Sore adn Store View--> @@ -328,6 +329,7 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="DeleteWebsite"> <argument name="websiteName" value="secondWebsite"/> </actionGroup> + <createData entity="CustomerAccountSharingDefault" stepKey="setConfigCustomerAccountDefault"/> <actionGroup ref="logout" stepKey="logout"/> <!--Do reindex and flush cache--> diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php index b85b735ea9c4f..a65bfa5d77f9e 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php @@ -348,8 +348,14 @@ public function execute() ['customer' => $customer, 'request' => $this->getRequest()] ); - if (isset($customerData['sendemail_store_id'])) { + if (isset($customerData['sendemail_store_id']) && $customerData['sendemail_store_id'] !== false) { $customer->setStoreId($customerData['sendemail_store_id']); + try { + $this->customerAccountManagement->validateCustomerStoreIdByWebsiteId($customer); + } catch (LocalizedException $exception) { + throw new LocalizedException(__("The Store View selected for sending Welcome email from". + " is not related to the customer's associated website.")); + } } // Save customer diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 55da6a62f0625..e2d997ed445b8 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -872,7 +872,6 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash if ($customer->getId()) { $customer = $this->customerRepository->get($customer->getEmail()); $websiteId = $customer->getWebsiteId(); - if ($this->isCustomerInStore($websiteId, $customer->getStoreId())) { throw new InputException(__('This customer already exists in this store.')); } @@ -896,13 +895,10 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash $customer->setWebsiteId($websiteId); } + $this->validateCustomerStoreIdByWebsiteId($customer); + // Update 'created_in' value with actual store name if ($customer->getId() === null) { - $websiteId = $customer->getWebsiteId(); - if ($websiteId && !$this->isCustomerInStore($websiteId, $customer->getStoreId())) { - throw new LocalizedException(__('The store view is not in the associated website.')); - } - $storeName = $this->storeManager->getStore($customer->getStoreId())->getName(); $customer->setCreatedIn($storeName); } @@ -1144,6 +1140,22 @@ public function isCustomerInStore($customerWebsiteId, $storeId) return in_array($storeId, $ids); } + /** + * Validate customer store id by customer website id. + * + * @param CustomerInterface $customer + * @return bool + * @throws LocalizedException + */ + public function validateCustomerStoreIdByWebsiteId(CustomerInterface $customer) + { + if (!$this->isCustomerInStore($customer->getWebsiteId(), $customer->getStoreId())) { + throw new LocalizedException(__('The store view is not in the associated website.')); + } + + return true; + } + /** * Validate the Reset Password Token for a customer. * diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php index 2e729873961c0..51663861fc8d1 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php @@ -269,7 +269,7 @@ protected function setUp() ->getMock(); $this->managementMock = $this->getMockBuilder(AccountManagement::class) ->disableOriginalConstructor() - ->setMethods(['createAccount']) + ->setMethods(['createAccount', 'validateCustomerStoreIdByWebsiteId']) ->getMock(); $this->addressDataFactoryMock = $this->getMockBuilder(AddressInterfaceFactory::class) ->disableOriginalConstructor() @@ -522,6 +522,9 @@ public function testExecuteWithExistentCustomer() ->with('customer/*/edit', ['id' => $customerId, '_current' => true]) ->willReturn(true); + $this->managementMock->method('validateCustomerStoreIdByWebsiteId') + ->willReturn(true); + $this->assertEquals($redirectMock, $this->model->execute()); } diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 3c38cd0f7b4e2..2344e0c8bce02 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -329,7 +329,6 @@ public function testCreateAccountWithPasswordHashWithExistingCustomer() public function testCreateAccountWithPasswordHashWithCustomerWithoutStoreId() { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -359,9 +358,9 @@ public function testCreateAccountWithPasswordHashWithCustomerWithoutStoreId() $customer->expects($this->atLeastOnce()) ->method('getWebsiteId') ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) + $customer->expects($this->at(10)) ->method('getStoreId') - ->willReturn($storeId); + ->willReturn(1); $customer->expects($this->once()) ->method('setStoreId') ->with($defaultStoreId); @@ -378,9 +377,7 @@ public function testCreateAccountWithPasswordHashWithCustomerWithoutStoreId() ->method('get') ->with($customerEmail) ->willReturn($customer); - $this->share - ->expects($this->atLeastOnce()) - ->method('isWebsiteScope') + $this->share->method('isWebsiteScope') ->willReturn(true); $this->storeManager ->expects($this->atLeastOnce()) @@ -405,7 +402,6 @@ public function testCreateAccountWithPasswordHashWithCustomerWithoutStoreId() public function testCreateAccountWithPasswordHashWithLocalizedException() { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -419,8 +415,7 @@ public function testCreateAccountWithPasswordHashWithLocalizedException() ->method('getId') ->willReturn($defaultStoreId); $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->once()) - ->method('getStoreIds') + $website->method('getStoreIds') ->willReturn([1, 2, 3]); $website->expects($this->once()) ->method('getDefaultStore') @@ -435,9 +430,9 @@ public function testCreateAccountWithPasswordHashWithLocalizedException() $customer->expects($this->atLeastOnce()) ->method('getWebsiteId') ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) + $customer->expects($this->at(10)) ->method('getStoreId') - ->willReturn($storeId); + ->willReturn(1); $customer->expects($this->once()) ->method('setStoreId') ->with($defaultStoreId); @@ -454,9 +449,7 @@ public function testCreateAccountWithPasswordHashWithLocalizedException() ->method('get') ->with($customerEmail) ->willReturn($customer); - $this->share - ->expects($this->once()) - ->method('isWebsiteScope') + $this->share->method('isWebsiteScope') ->willReturn(true); $this->storeManager ->expects($this->atLeastOnce()) @@ -481,7 +474,6 @@ public function testCreateAccountWithPasswordHashWithLocalizedException() public function testCreateAccountWithPasswordHashWithAddressException() { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -498,8 +490,7 @@ public function testCreateAccountWithPasswordHashWithAddressException() ->method('getId') ->willReturn($defaultStoreId); $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->once()) - ->method('getStoreIds') + $website->method('getStoreIds') ->willReturn([1, 2, 3]); $website->expects($this->once()) ->method('getDefaultStore') @@ -514,9 +505,9 @@ public function testCreateAccountWithPasswordHashWithAddressException() $customer->expects($this->atLeastOnce()) ->method('getWebsiteId') ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) + $customer->expects($this->at(10)) ->method('getStoreId') - ->willReturn($storeId); + ->willReturn(1); $customer->expects($this->once()) ->method('setStoreId') ->with($defaultStoreId); @@ -533,9 +524,7 @@ public function testCreateAccountWithPasswordHashWithAddressException() ->method('get') ->with($customerEmail) ->willReturn($customer); - $this->share - ->expects($this->once()) - ->method('isWebsiteScope') + $this->share->method('isWebsiteScope') ->willReturn(true); $this->storeManager ->expects($this->atLeastOnce()) @@ -648,7 +637,6 @@ public function testCreateAccountWithPasswordHashWithNewCustomerAndLocalizedExce public function testCreateAccountWithoutPassword() { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -683,9 +671,8 @@ public function testCreateAccountWithoutPassword() $customer->expects($this->atLeastOnce()) ->method('getWebsiteId') ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) - ->method('getStoreId') - ->willReturn($storeId); + $customer->expects($this->at(10))->method('getStoreId') + ->willReturn(1); $customer->expects($this->once()) ->method('setStoreId') ->with($defaultStoreId); @@ -700,8 +687,7 @@ public function testCreateAccountWithoutPassword() ->method('get') ->with($customerEmail) ->willReturn($customer); - $this->share->expects($this->once()) - ->method('isWebsiteScope') + $this->share->method('isWebsiteScope') ->willReturn(true); $this->storeManager->expects($this->atLeastOnce()) ->method('getWebsite') @@ -861,7 +847,6 @@ public function testCreateAccountInputExceptionExtraLongPassword() public function testCreateAccountWithPassword() { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -940,9 +925,9 @@ public function testCreateAccountWithPassword() $customer->expects($this->atLeastOnce()) ->method('getWebsiteId') ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) + $customer->expects($this->at(11)) ->method('getStoreId') - ->willReturn($storeId); + ->willReturn(1); $customer->expects($this->once()) ->method('setStoreId') ->with($defaultStoreId); @@ -957,8 +942,7 @@ public function testCreateAccountWithPassword() ->method('get') ->with($customerEmail) ->willReturn($customer); - $this->share->expects($this->once()) - ->method('isWebsiteScope') + $this->share->method('isWebsiteScope') ->willReturn(true); $this->storeManager->expects($this->atLeastOnce()) ->method('getWebsite') @@ -1810,62 +1794,37 @@ public function dataProviderGetConfirmationStatus() /** * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Exception message */ - public function testCreateAccountWithPasswordHashForGuest() + public function testCreateAccountWithPasswordHashForGuestException() { $storeId = 1; - $storeName = 'store_name'; $websiteId = 1; $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) ->disableOriginalConstructor() ->getMock(); - $storeMock->expects($this->once()) - ->method('getId') + $storeMock->method('getId') ->willReturn($storeId); - $storeMock->expects($this->once()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $storeMock->expects($this->once()) - ->method('getName') - ->willReturn($storeName); - - $this->storeManager->expects($this->exactly(3)) - ->method('getStore') - ->willReturn($storeMock); + $this->storeManager->method('getStores') + ->willReturn([$storeMock]); $customerMock = $this->getMockBuilder(Customer::class) ->disableOriginalConstructor() ->getMock(); - $customerMock->expects($this->exactly(2)) - ->method('getId') - ->willReturn(null); - $customerMock->expects($this->exactly(3)) + $customerMock->expects($this->at(1)) ->method('getStoreId') - ->willReturn(null); - $customerMock->expects($this->exactly(3)) + ->willReturn($storeId); + $customerMock->expects($this->at(4)) + ->method('getStoreId') + ->willReturn($storeId); + $customerMock->expects($this->at(2)) ->method('getWebsiteId') - ->willReturn(null); - $customerMock->expects($this->once()) - ->method('setStoreId') - ->with($storeId) - ->willReturnSelf(); - $customerMock->expects($this->once()) - ->method('setWebsiteId') - ->with($websiteId) - ->willReturnSelf(); - $customerMock->expects($this->once()) - ->method('setCreatedIn') - ->with($storeName) - ->willReturnSelf(); - $customerMock->expects($this->once()) - ->method('getAddresses') - ->willReturn(null); - $customerMock->expects($this->once()) - ->method('setAddresses') - ->with(null) - ->willReturnSelf(); + ->willReturn($websiteId); + $customerMock->expects($this->at(5)) + ->method('getId') + ->willReturn(1); $this->customerRepository ->expects($this->once()) @@ -2030,7 +1989,6 @@ private function prepareDateTimeFactory() public function testCreateAccountUnexpectedValueException(): void { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -2048,8 +2006,7 @@ public function testCreateAccountUnexpectedValueException(): void ->method('getId') ->willReturn($defaultStoreId); $website = $this->createMock(\Magento\Store\Model\Website::class); - $website->expects($this->atLeastOnce()) - ->method('getStoreIds') + $website->method('getStoreIds') ->willReturn([1, 2, 3]); $website->expects($this->once()) ->method('getDefaultStore') @@ -2064,9 +2021,9 @@ public function testCreateAccountUnexpectedValueException(): void $customer->expects($this->atLeastOnce()) ->method('getWebsiteId') ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) + $customer->expects($this->at(10)) ->method('getStoreId') - ->willReturn($storeId); + ->willReturn(1); $customer->expects($this->once()) ->method('setStoreId') ->with($defaultStoreId); @@ -2080,8 +2037,7 @@ public function testCreateAccountUnexpectedValueException(): void ->method('get') ->with($customerEmail) ->willReturn($customer); - $this->share->expects($this->once()) - ->method('isWebsiteScope') + $this->share->method('isWebsiteScope') ->willReturn(true); $this->storeManager->expects($this->atLeastOnce()) ->method('getWebsite') @@ -2162,4 +2118,49 @@ public function testCreateAccountWithStoreNotInWebsite() ->willReturn($website); $this->accountManagement->createAccountWithPasswordHash($customerMock, $hash); } + + /** + * Test for validating customer store id by customer website id. + * + * @return void + */ + public function testValidateCustomerStoreIdByWebsiteId(): void + { + $customerMock = $this->getMockBuilder(CustomerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $customerMock->method('getWebsiteId')->willReturn(1); + $customerMock->method('getStoreId')->willReturn(1); + $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) + ->disableOriginalConstructor() + ->getMock(); + $storeMock->method('getId') + ->willReturn(1); + $this->storeManager->method('getStores') + ->willReturn([$storeMock]); + + $this->assertTrue($this->accountManagement->validateCustomerStoreIdByWebsiteId($customerMock)); + } + + /** + * Test for validating customer store id by customer website id with Exception + * + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage The store view is not in the associated website. + */ + public function testValidateCustomerStoreIdByWebsiteIdException(): void + { + $customerMock = $this->getMockBuilder(CustomerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) + ->disableOriginalConstructor() + ->getMock(); + $storeMock->method('getId') + ->willReturn(1); + $this->storeManager->method('getStores') + ->willReturn([$storeMock]); + + $this->assertTrue($this->accountManagement->validateCustomerStoreIdByWebsiteId($customerMock)); + } } diff --git a/app/code/Magento/Customer/Test/Unit/ViewModel/Customer/StoreTest.php b/app/code/Magento/Customer/Test/Unit/ViewModel/Customer/StoreTest.php new file mode 100644 index 0000000000000..2e34bcf7ab698 --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/ViewModel/Customer/StoreTest.php @@ -0,0 +1,210 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Customer\Test\Unit\ViewModel\Customer; + +use Magento\Customer\Model\Config\Share as ConfigShare; +use Magento\Framework\App\Request\DataPersistorInterface; +use Magento\Store\Model\StoreManagerInterface; +use PHPUnit\Framework\TestCase; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Customer\ViewModel\Customer\Store as CustomerStore; +use Magento\Store\Model\System\Store as SystemStore; +use Magento\Store\Model\Store; + +/** + * Test for customer's store view model + */ +class StoreTest extends TestCase +{ + /** @var ObjectManagerHelper */ + private $objectManagerHelper; + + /** + * @var CustomerStore + */ + private $customerStore; + + /** + * @var SystemStore + */ + private $systemStore; + + /** + * @var Store + */ + private $store; + + /** + * @var ConfigShare + */ + protected $configShare; + + /** + * @var StoreManagerInterface + */ + protected $storeManager; + + /** + * @var DataPersistorInterface + */ + private $dataPersistor; + + protected function setUp() + { + $this->systemStore = $this->createMock(SystemStore::class); + $this->store = $this->createMock(Store::class); + $this->configShare = $this->createMock(ConfigShare::class); + $this->storeManager = $this->createMock(StoreManagerInterface::class); + $this->dataPersistor = $this->createMock(DataPersistorInterface::class); + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->customerStore = $this->objectManagerHelper->getObject( + CustomerStore::class, + [ + 'systemStore' => $this->systemStore, + 'configShare' => $this->configShare, + 'storeManager' => $this->storeManager, + 'dataPersistor' => $this->dataPersistor + ] + ); + } + + /** + * Test that method return correct array of options + * + * @param array $options + * @param bool $isWebsiteScope + * @param bool $isCustomerDataInSession + * @dataProvider dataProviderOptionsArray + * @return void + */ + public function testToOptionArray(array $options, bool $isWebsiteScope, bool $isCustomerDataInSession): void + { + $this->configShare->method('isWebsiteScope') + ->willReturn($isWebsiteScope); + $this->store->method('getWebsiteId') + ->willReturn(1); + + if ($isCustomerDataInSession) { + $this->dataPersistor->method('get') + ->with('customer') + ->willReturn([ + 'account' => ['website_id' => '1'] + ]); + } else { + $this->storeManager->method('getDefaultStoreView') + ->willReturn($this->store); + } + + $this->systemStore->method('getStoreData') + ->willReturn($this->store); + $this->systemStore->method('getStoreValuesForForm') + ->willReturn([ + [ + 'label' => 'Main Website', + 'value' => [], + '__disableTmpl' => true, + ], + [ + 'label' => 'Main Website', + 'value' => [ + [ + 'label' => '    Default Store View', + 'value' => '1', + ] + ], + '__disableTmpl' => true, + ] + ]); + + $this->assertEquals($options, $this->customerStore->toOptionArray()); + } + + /** + * Data provider for testToOptionArray test + * + * @return array + */ + public function dataProviderOptionsArray(): array + { + return [ + [ + 'options' => [ + [ + 'label' => 'Main Website', + 'value' => [], + '__disableTmpl' => true, + 'website_id' => '1', + ], + [ + 'label' => 'Main Website', + 'value' => [ + [ + 'label' => '    Default Store View', + 'value' => '1', + 'website_id' => '1', + ] + ], + '__disableTmpl' => true, + 'website_id' => '1', + ] + ], + 'isWebsiteScope' => true, + 'isCustomerDataInSession' => false, + ], + [ + 'options' => [ + [ + 'label' => 'Main Website', + 'value' => [], + '__disableTmpl' => true, + 'website_id' => '1', + ], + [ + 'label' => 'Main Website', + 'value' => [ + [ + 'label' => '    Default Store View', + 'value' => '1', + 'website_id' => '1', + ] + ], + '__disableTmpl' => true, + 'website_id' => '1', + ] + ], + 'isWebsiteScope' => false, + 'isCustomerDataInSession' => false, + ], + [ + 'options' => [ + [ + 'label' => 'Main Website', + 'value' => [], + '__disableTmpl' => true, + 'website_id' => '1', + ], + [ + 'label' => 'Main Website', + 'value' => [ + [ + 'label' => '    Default Store View', + 'value' => '1', + 'website_id' => '1', + ] + ], + '__disableTmpl' => true, + 'website_id' => '1', + ] + ], + 'isWebsiteScope' => false, + 'isCustomerDataInSession' => true, + ] + ]; + } +} diff --git a/app/code/Magento/Customer/ViewModel/Customer/Store.php b/app/code/Magento/Customer/ViewModel/Customer/Store.php new file mode 100644 index 0000000000000..1e6ca69e2d77a --- /dev/null +++ b/app/code/Magento/Customer/ViewModel/Customer/Store.php @@ -0,0 +1,131 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Customer\ViewModel\Customer; + +use Magento\Customer\Model\Config\Share as ConfigShare; +use Magento\Framework\App\Request\DataPersistorInterface; +use Magento\Framework\Data\OptionSourceInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Store\Model\System\Store as SystemStore; + +/** + * Customer's store view model + */ +class Store implements OptionSourceInterface +{ + /** + * @var SystemStore + */ + private $systemStore; + + /** + * @var ConfigShare + */ + private $configShare; + + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var DataPersistorInterface + */ + private $dataPersistor; + + /** + * Store constructor. + * + * @param SystemStore $systemStore + * @param ConfigShare $configShare + * @param StoreManagerInterface $storeManager + * @param DataPersistorInterface $dataPersistor + */ + public function __construct( + SystemStore $systemStore, + ConfigShare $configShare, + StoreManagerInterface $storeManager, + DataPersistorInterface $dataPersistor + ) { + $this->systemStore = $systemStore; + $this->configShare = $configShare; + $this->storeManager = $storeManager; + $this->dataPersistor = $dataPersistor; + } + + /** + * @inheritdoc + */ + public function toOptionArray(): array + { + return (bool)$this->configShare->isWebsiteScope() ? $this->getStoreOptions() + : $this->getStoreOptionsWithCurrentWebsiteId(); + } + + /** + * Adding website ID to options list + * + * @return array + */ + private function getStoreOptions(): array + { + $options = $this->systemStore->getStoreValuesForForm(); + + $websiteKey = null; + foreach ($options as $key => $option) { + if ($websiteKey === null) { + $websiteKey = $key; + } + if (is_array($option['value']) && !empty($option['value'])) { + $websiteId = null; + foreach ($option['value'] as $storeViewKey => $storeView) { + $websiteId = $this->systemStore->getStoreData($storeView['value'])->getWebsiteId(); + $options[$key]['value'][$storeViewKey]['website_id'] = $websiteId; + } + if ($websiteId) { + $options[$key]['website_id'] = $websiteId; + if ($websiteKey !== null) { + $options[$websiteKey]['website_id'] = $websiteId; + $websiteKey = null; + } + } + } + } + + return $options; + } + + /** + * Adding current website ID to options list + * + * @return array + */ + private function getStoreOptionsWithCurrentWebsiteId(): array + { + $options = $this->systemStore->getStoreValuesForForm(); + + if (!empty($this->dataPersistor->get('customer')['account'])) { + $currentWebsiteId = (string)$this->dataPersistor->get('customer')['account']['website_id']; + } else { + $currentWebsiteId = $this->storeManager->getDefaultStoreView()->getWebsiteId(); + } + + foreach ($options as $key => $option) { + $options[$key]['website_id'] = $currentWebsiteId; + if (is_array($option['value']) && !empty($option['value'])) { + foreach ($option['value'] as $storeViewKey => $storeView) { + $storeView['website_id'] = $currentWebsiteId; + $options[$key]['value'][$storeViewKey] = $storeView; + } + } + } + + return $options; + } +} diff --git a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml index 7caaeab4f39d6..d5c7154a30f54 100644 --- a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml +++ b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml @@ -301,7 +301,7 @@ <visible>true</visible> </settings> </field> - <field name="sendemail_store_id" formElement="select"> + <field name="sendemail_store_id" component="Magento_Ui/js/form/element/select" formElement="select"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="source" xsi:type="string">customer</item> @@ -317,7 +317,11 @@ <formElements> <select> <settings> - <options class="Magento\Store\Model\System\Store"/> + <options class="Magento\Customer\ViewModel\Customer\Store"/> + <filterBy> + <field>website_id</field> + <target>${ $.provider }:${ $.parentScope }.website_id</target> + </filterBy> </settings> </select> </formElements> diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/optgroup.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/optgroup.js index 6ff7c1f673213..ab806e89385b6 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/optgroup.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/optgroup.js @@ -250,7 +250,7 @@ define([ // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document. // That's why we first added them without selection. Now it's time to set the selection. - if (previousSelectedValues.length) { + if (previousSelectedValues.length && newOptions.value) { isSelected = ko.utils.arrayIndexOf( previousSelectedValues, ko.selectExtensions.readValue(newOptions.value) From 6e4a0410ada941c681310f480c788ed4b309b11b Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Fri, 7 Feb 2020 17:14:44 +0200 Subject: [PATCH 132/176] Cover MFTF test --- ...WithCustomOptionFileToOrderActionGroup.xml | 24 +++++++++ ...minChangeCustomerOptionFileActionGroup.xml | 26 ++++++++++ .../Test/Mftf/Page/AdminOrderCreatePage.xml | 1 + .../AdminOrderFormCustomOptionsSection.xml | 16 ++++++ ...rWithSimpleProductCustomOptionFileTest.xml | 52 +++++++++++++++++++ 5 files changed, 119 insertions(+) create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddSimpleProductWithCustomOptionFileToOrderActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminChangeCustomerOptionFileActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormCustomOptionsSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductCustomOptionFileTest.xml diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddSimpleProductWithCustomOptionFileToOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddSimpleProductWithCustomOptionFileToOrderActionGroup.xml new file mode 100644 index 0000000000000..5b08ba30a8fec --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddSimpleProductWithCustomOptionFileToOrderActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminAddSimpleProductWithCustomOptionFileToOrderActionGroup" extends="AddSimpleProductToOrderActionGroup"> + <annotations> + <description>Add product to order with custom option type file. Start on create order page.</description> + </annotations> + <arguments> + <argument name="file" type="string" defaultValue="{{TestImageNew.file}}" /> + </arguments> + + <remove keyForRemoval="fillProductQty"/> + <waitForAjaxLoad stepKey="waitForAjaxLoad" after="selectProduct"/> + <fillField selector="{{AdminOrderFormCustomOptionsSection.quantity}}" userInput="{{productQty}}" stepKey="fillProductQty" after="waitForAjaxLoad"/> + <attachFile selector="{{AdminOrderFormCustomOptionsSection.file}}" userInput="{{file}}" stepKey="attachImageForOptional" after="fillProductQty"/> + <click selector="{{AdminOrderFormCustomOptionsSection.buttonOk}}" stepKey="clickButtonOK" after="attachImageForOptional"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminChangeCustomerOptionFileActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminChangeCustomerOptionFileActionGroup.xml new file mode 100644 index 0000000000000..fb9f68d861faf --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminChangeCustomerOptionFileActionGroup.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminChangeCustomerOptionFileActionGroup"> + <annotations> + <description>Change custom option file on admin order page.</description> + </annotations> + <arguments> + <argument name="file" type="string" defaultValue="{{TestImageNew.file}}" /> + </arguments> + + <click selector="{{AdminOrderFormItemsSection.configure}}" stepKey="clickConfigure"/> + <waitForAjaxLoad stepKey="waitForAjaxLoad"/> + <click selector="{{AdminOrderFormCustomOptionsSection.linkChange}}" stepKey="clickLinkChange"/> + <waitForPageLoad stepKey="waitForChangeLoad"/> + <attachFile selector="{{AdminOrderFormCustomOptionsSection.file}}" userInput="{{file}}" stepKey="changeAttachImage"/> + <click selector="{{AdminOrderFormCustomOptionsSection.buttonOk}}" stepKey="clickButtonOK"/> + <waitForPageLoad stepKey="waitForCustomOptionApplied"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml b/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml index 680d44ebb34fe..a7e2b2ec1f0d9 100644 --- a/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml +++ b/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml @@ -20,5 +20,6 @@ <section name="AdminOrderFormStoreSelectorSection"/> <section name="AdminOrderFormDiscountSection"/> <section name="AdminOrderFormMessagesSection"/> + <section name="AdminOrderFormCustomOptionsSection"/> </page> </pages> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormCustomOptionsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormCustomOptionsSection.xml new file mode 100644 index 0000000000000..066aa4181e7ef --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormCustomOptionsSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminOrderFormCustomOptionsSection"> + <element name="quantity" type="input" selector="//input[@id='product_composite_configure_input_qty']"/> + <element name="file" type="file" selector="//input[@type='file'][contains(@class, 'product-custom-option')]" /> + <element name="buttonOk" type="button" selector="//button[contains(@class, 'action-primary')][@data-role='action']"/> + <element name="linkChange" type="text" selector="//div[contains(@class, 'entry-edit')]//a[contains(text(),'Change')]"/> + </section> +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductCustomOptionFileTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductCustomOptionFileTest.xml new file mode 100644 index 0000000000000..200ac6e62ac15 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductCustomOptionFileTest.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateOrderWithSimpleProductCustomOptionFileTest"> + <annotations> + <title value="Create Order with simple product with custom option."/> + <description value="Verify, admin able to change file for custom option during order creation."/> + <features value="Sales"/> + <severity value="MAJOR"/> + <group value="Sales"/> + </annotations> + <before> + <!--Create test data.--> + <createData entity="_defaultCategory" stepKey="category"/> + <createData entity="SimpleProduct" stepKey="simpleProduct"> + <requiredEntity createDataKey="category"/> + </createData> + <createData entity="Simple_US_Customer_CA" stepKey="customer"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!--Clean up created test data.--> + <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="category" stepKey="deleteCategory"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer" /> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Add option to product.--> + <amOnPage url="{{AdminProductEditPage.url($simpleProduct.id$)}}" stepKey="navigateToProductEditPage"/> + <actionGroup ref="AddProductCustomOptionFileActionGroup" stepKey="addOption"> + <argument name="option" value="ProductOptionFile"/> + </actionGroup> + <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> + <!--Create order.--> + <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="navigateToNewOrderWithExistingCustomer"> + <argument name="customer" value="$customer$"/> + </actionGroup> + <actionGroup ref="AdminAddSimpleProductWithCustomOptionFileToOrderActionGroup" stepKey="addSimpleProductToOrder"> + <argument name="product" value="$simpleProduct$"/> + <argument name="productQty" value="$simpleProduct.quantity$"/> + </actionGroup> + <!--Verify, admin able to change file for custom option.--> + <actionGroup ref="AdminChangeCustomerOptionFileActionGroup" stepKey="changeFile"/> + </test> +</tests> From f7988a877f24ccb97473dd905d45cf4b5f3c1fcd Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 7 Feb 2020 17:58:29 +0200 Subject: [PATCH 133/176] Unit tests for Magento\Csp\Model\Mode\ConfigManager and Magento\Csp\Observer\Render --- .../Unit/Model/Mode/ConfigManagerTest.php | 127 ++++++++++++++++++ .../Csp/Test/Unit/Observer/RenderTest.php | 52 +++++++ 2 files changed, 179 insertions(+) create mode 100644 app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php create mode 100644 app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php diff --git a/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php b/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php new file mode 100644 index 0000000000000..8e47641c46b89 --- /dev/null +++ b/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php @@ -0,0 +1,127 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Csp\Test\Unit\Model\Mode; + +use Magento\Csp\Model\Mode\ConfigManager; +use Magento\Csp\Model\Mode\Data\ModeConfigured; +use Magento\Framework\App\Area; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\State; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Store\Model\Store; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit Test for \Magento\Csp\Model\Mode\ConfigManager + */ +class ConfigManagerTest extends TestCase +{ + const STUB_REPORT_ONLY = true; + const STUB_AREA_CODE_OTHER = 'other'; + + /** + * @var MockObject|ScopeConfigInterface + */ + private $configMock; + + /** + * @var MockObject|Store + */ + private $storeModelMock; + + /** + * @var MockObject|State + */ + private $stateMock; + + /** + * @var ConfigManager + */ + private $model; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->configMock = $this->createMock(ScopeConfigInterface::class); + $this->storeModelMock = $this->createMock(Store::class); + $this->stateMock = $this->createMock(State::class); + + $objectManagerHelper = new ObjectManagerHelper($this); + $this->model = $objectManagerHelper->getObject( + ConfigManager::class, + [ + 'config' => $this->configMock, + 'storeModel' => $this->storeModelMock, + 'state' => $this->stateMock + ] + ); + } + + /** + * Test case with correct Area codes. + * + * @param string $area + * @param string $pathReportOnly + * @param string $pathReportUri + * @dataProvider dataProviderGetConfiguredWithCorrectArea + */ + public function testGetConfiguredWithCorrectArea(string $area, string $pathReportOnly, string $pathReportUri) + { + $this->stateMock->expects($this->once())->method('getAreaCode')->willReturn($area); + + $this->configMock->expects($this->once())->method('getValue')->with($pathReportUri); + $this->configMock->expects($this->once()) + ->method('isSetFlag') + ->with($pathReportOnly) + ->willReturn(self::STUB_REPORT_ONLY); + + $this->assertInstanceOf(ModeConfigured::class, $this->model->getConfigured()); + } + + /** + * Data Provider with appropriate areas. + * + * @return array + */ + public function dataProviderGetConfiguredWithCorrectArea(): array + { + return [ + [ + 'area' => Area::AREA_ADMINHTML, + 'pathReportOnly' => 'csp/mode/admin/report_only', + 'pathReportUri' => 'csp/mode/admin/report_uri' + ], + [ + 'area' => Area::AREA_FRONTEND, + 'pathReportOnly' => 'csp/mode/storefront/report_only', + 'pathReportUri' => 'csp/mode/storefront/report_uri' + ] + ]; + } + + /** + * Test case with an inappropriate Area code. + */ + public function testGetConfiguredWithWrongArea() + { + $this->stateMock->expects($this->once()) + ->method('getAreaCode') + ->willReturn(self::STUB_AREA_CODE_OTHER); + + $this->configMock->expects($this->never())->method('isSetFlag'); + $this->configMock->expects($this->never())->method('getValue'); + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('CSP can only be configured for storefront or admin area'); + + $this->model->getConfigured(); + } +} diff --git a/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php b/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php new file mode 100644 index 0000000000000..48d6d6d9b4592 --- /dev/null +++ b/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Csp\Test\Unit\Observer; + +use Magento\Csp\Api\CspRendererInterface; +use Magento\Csp\Observer\Render; +use Magento\Framework\App\Response\Http as ResponseHttp; +use Magento\Framework\Event; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit Test for \Magento\Csp\Observer\Render + */ +class RenderTest extends TestCase +{ + /** + * Check if the render method is called + */ + public function testExecuteExpectsRenderCalled() + { + $eventMock = $this->createMock(Event::class); + $responseMock = $this->createMock(ResponseHttp::class); + $eventMock->expects($this->once()) + ->method('getData') + ->with('response') + ->willReturn($responseMock); + + /** @var MockObject|Observer $eventObserverMock */ + $eventObserverMock = $this->createMock(Observer::class); + $eventObserverMock->expects($this->once())->method('getEvent')->willReturn($eventMock); + + $cspRendererMock = $this->createMock(CspRendererInterface::class); + $cspRendererMock->expects($this->once())->method('render'); + + $objectManagerHelper = new ObjectManager($this); + /** @var MockObject|Render $renderObserver */ + $renderObserver = $objectManagerHelper->getObject( + Render::class, + ['cspRenderer' => $cspRendererMock] + ); + $renderObserver->execute($eventObserverMock); + } +} From 128535fb38ddeba06738333940583a11721640d7 Mon Sep 17 00:00:00 2001 From: Nikita Sarychev <sarron80@yandex.ru> Date: Fri, 7 Feb 2020 20:10:02 +0300 Subject: [PATCH 134/176] add preferences to di --- app/code/Magento/Catalog/etc/di.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index eda6dbd2d9d6f..223d690d28327 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -74,6 +74,7 @@ <preference for="Magento\Catalog\Model\Product\Configuration\Item\ItemResolverInterface" type="Magento\Catalog\Model\Product\Configuration\Item\ItemResolverComposite" /> <preference for="Magento\Catalog\Api\Data\MassActionInterface" type="\Magento\Catalog\Model\MassAction" /> <preference for="Magento\Catalog\Model\ProductLink\Data\ListCriteriaInterface" type="Magento\Catalog\Model\ProductLink\Data\ListCriteria" /> + <preference for="Magento\Catalog\Api\CategoryListDeleteBySkuInterface" type="Magento\Catalog\Model\CategoryLinkRepository"/> <type name="Magento\Customer\Model\ResourceModel\Visitor"> <plugin name="catalogLog" type="Magento\Catalog\Model\Plugin\Log" /> </type> From 0aef9add469dda3a0102b886b008757469bb8f26 Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Sat, 8 Feb 2020 01:16:03 +0530 Subject: [PATCH 135/176] feedback changes --- .../Ui/base/js/grid/data-storage.test.js | 178 ++---------------- 1 file changed, 17 insertions(+), 161 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js index ade7d09797139..33c2e97e0b85f 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js @@ -31,20 +31,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('initConfig')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.initConfig; - - expect(type).toEqual('function'); - }); - - it('Check returned value if method called without arguments', function () { - expect(model.initConfig()).toBeDefined(); - }); - it('Check returned value type if method called without arguments', function () { var type = typeof model.initConfig(); @@ -70,20 +56,6 @@ define([ dataScope: 'magento' }); - it('check for defined', function () { - expect(model.hasOwnProperty('getByIds')).toBeDefined(); - }); - - it('check method type', function () { - expect(typeof model.getByIds).toEqual('function'); - }); - - it('Check returned value if method called with argument', function () { - var ids = [1,2,3]; - - expect(model.getByIds(ids)).toBeDefined(); - }); - it('check returned type if method called with argument', function () { var ids = [1,2,3], type = typeof model.getByIds(ids); @@ -98,7 +70,13 @@ define([ }); it('Return array if "getByIds" has been called', function () { - var ids = [1]; + var ids = [1], + expectedValue = [ + { + id_field_name: 'entity_id', + entity_id: '1' + } + ]; model = new DataStorage({ dataScope: 'magento', @@ -110,7 +88,7 @@ define([ } }); - expect(typeof model.getByIds(ids)).toEqual('object'); + expect(model.getByIds(ids)).toEqual(expectedValue); }); }); @@ -121,25 +99,15 @@ define([ dataScope: 'magento' }); - it('check for defined', function () { - expect(model.hasOwnProperty('getIds')).toBeDefined(); - }); - - it('check method type', function () { - expect(typeof model.getIds).toEqual('function'); - }); - - it('check returned value if method called with argument', function () { - var ids = [1,2,3]; - - expect(model.getIds(ids)).toBeDefined(); - }); - - it('check returned type if method called with argument', function () { - var ids = [1,2,3], - type = typeof model.getIds(ids); - - expect(type).toEqual('object'); + it('check array of entity_id will return', function () { + var ids = [ + { + id_field_name: 'entity_id', + entity_id: '1' + } + ], + expectedValue = ['1']; + expect(model.getIds(ids)).toEqual(expectedValue); }); }); @@ -150,28 +118,6 @@ define([ dataScope: 'magento' }); - it('check for defined', function () { - expect(model.hasOwnProperty('getData')).toBeDefined(); - }); - - it('check method type', function () { - expect(typeof model.getData).toEqual('function'); - }); - - it('check returned value if method called with argument', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }; - - expect(model.getData(params)).toBeDefined(); - }); - it('check returned type if method called with argument', function () { var params = { namespace: 'magento', @@ -332,16 +278,6 @@ define([ } }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('updateData')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.updateData; - - expect(type).toEqual('function'); - }); - it('Check updateData has been called', function () { var data = [{ id_field_name: 'entity_id', @@ -357,16 +293,6 @@ define([ dataScope: 'magento' }); - it('Check for defined', function () { - expect(model.hasOwnProperty('requestData')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.requestData; - - expect(type).toEqual('function'); - }); - it('Check Ajax request', function () { var params = { namespace: 'magento', @@ -401,16 +327,6 @@ define([ dataScope: 'magento' }); - it('Check for defined', function () { - expect(model.hasOwnProperty('getRequest')).toBeDefined(); - }); - - it('Check method', function () { - var type = typeof model.getRequest; - - expect(type).toEqual('function'); - }); - it('check "getRequest" has been executed', function () { var params = { namespace: 'magento', @@ -434,16 +350,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('getRequestData')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.getRequestData; - - expect(type).toEqual('function'); - }); - it('check "getRequestData" has been executed', function () { var request = { ids: [1,2,3] @@ -495,16 +401,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('cacheRequest')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.cacheRequest; - - expect(type).toEqual('function'); - }); - it('check "model._requests"', function () { var params = { namespace: 'magento', @@ -559,16 +455,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('clearRequests')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.clearRequests; - - expect(type).toEqual('function'); - }); - it('check "clearRequests" will empty _requests array', function () { var params = { namespace: 'magento', @@ -600,16 +486,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('removeRequest')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.removeRequest; - - expect(type).toEqual('function'); - }); - it('check "removeRequest" is defined', function () { var params = { namespace: 'magento', @@ -634,16 +510,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('wasRequested')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.wasRequested; - - expect(type).toEqual('function'); - }); - it('Return false if getRequest method returns false', function () { var params = { namespace: 'magento', @@ -664,16 +530,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('onRequestComplete')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.onRequestComplete; - - expect(type).toEqual('function'); - }); - it('Check "updateData" method has been called', function () { var data = { items: [{ From f9697f509ae09f5c9e0f0d7b1a2de7ed9a53fc16 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Sat, 8 Feb 2020 03:02:17 +0530 Subject: [PATCH 136/176] Critical scope css fixed --- app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php index a3f054d7c8dc7..f0c343c366abc 100644 --- a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php @@ -58,9 +58,9 @@ function ($matches) use (&$cssMatches) { } $media = $media ?? 'all'; $loadCssAsync = sprintf( - '<link rel="preload" as="style" media="%s" . - onload="this.onload=null;this.rel=\'stylesheet\'"' . - 'href="%s">', + '<link rel="preload" as="style" media="%s"' . + ' onload="this.onload=null;this.rel=\'stylesheet\'"' . + ' href="%s">', $media, $href ); From aafce6541753a29f55ff87929acc0b3698ec0cf4 Mon Sep 17 00:00:00 2001 From: Pratik Mehta <pratik@seepossible.com> Date: Sat, 8 Feb 2020 13:15:26 +0530 Subject: [PATCH 137/176] Translation values add in translation file. --- app/code/Magento/Backend/i18n/en_US.csv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Backend/i18n/en_US.csv b/app/code/Magento/Backend/i18n/en_US.csv index 51fe8bfe542a2..53f7fe90cbbe5 100644 --- a/app/code/Magento/Backend/i18n/en_US.csv +++ b/app/code/Magento/Backend/i18n/en_US.csv @@ -461,3 +461,5 @@ Pagination,Pagination "Alternative text for the next pages link in the pagination menu. If empty, default arrow image is used.","Alternative text for the next pages link in the pagination menu. If empty, default arrow image is used." "Anchor Text for Next","Anchor Text for Next" "Theme Name","Theme Name" +"Use URL parameter to enable template path hints for Storefront","Use URL parameter to enable template path hints for Storefront" +"Add the following parameter to the URL to show template hints ?templatehints=[parameter_value]","Add the following parameter to the URL to show template hints ?templatehints=[parameter_value]" From 7d695bdc60658bbaec89050f0bf77da7cced81e4 Mon Sep 17 00:00:00 2001 From: Ajith <ajithkumar.maragathavel@ziffity.com> Date: Sat, 8 Feb 2020 16:40:14 +0530 Subject: [PATCH 138/176] Removed unnecessary function argument --- app/code/Magento/Sales/Model/Order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 89564f97ccf16..aee8432fb0925 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -858,7 +858,7 @@ public function canEdit() */ public function canReorder() { - return $this->_canReorder(false); + return $this->_canReorder(); } /** From 9e789ca3328035ba494f6575362c29ea955e80a9 Mon Sep 17 00:00:00 2001 From: Matthew O'Loughlin <matthew.oloughlin@aligent.com.au> Date: Sun, 9 Feb 2020 18:03:07 +1030 Subject: [PATCH 139/176] Fix return type to match function spec (empty array instead of null) --- .../Magento/BundleGraphQl/Model/Resolver/Options/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php b/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php index 7608d6e9e4d97..23bfbb5fc4e22 100644 --- a/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php +++ b/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php @@ -115,7 +115,7 @@ private function fetch() : array $this->extensionAttributesJoinProcessor->process($optionsCollection); if (empty($optionsCollection->getData())) { - return null; + return []; } /** @var \Magento\Bundle\Model\Option $option */ From 4238f7bf202e763186c2a78386ca98fdaf682de9 Mon Sep 17 00:00:00 2001 From: Matthew O'Loughlin <matthew.oloughlin@aligent.com.au> Date: Sun, 9 Feb 2020 18:09:00 +1030 Subject: [PATCH 140/176] Also switch to null-coalescing for cleanliness --- .../BundleGraphQl/Model/Resolver/Options/Collection.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php b/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php index 23bfbb5fc4e22..c8e2384fcb99c 100644 --- a/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php +++ b/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php @@ -78,11 +78,7 @@ public function addParentFilterData(int $parentId, int $parentEntityId, string $ public function getOptionsByParentId(int $parentId) : array { $options = $this->fetch(); - if (!isset($options[$parentId])) { - return []; - } - - return $options[$parentId]; + return $options[$parentId] ?? []; } /** From 9c75294d25182a1ada90ad66c621dcf9b39941fa Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Sun, 9 Feb 2020 10:14:46 +0200 Subject: [PATCH 141/176] Fix docblock for the variable --- app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php b/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php index 48d6d6d9b4592..8c42a4d051bde 100644 --- a/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php +++ b/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php @@ -42,7 +42,7 @@ public function testExecuteExpectsRenderCalled() $cspRendererMock->expects($this->once())->method('render'); $objectManagerHelper = new ObjectManager($this); - /** @var MockObject|Render $renderObserver */ + /** @var Render $renderObserver */ $renderObserver = $objectManagerHelper->getObject( Render::class, ['cspRenderer' => $cspRendererMock] From dccf5ef6b40f50c33baadcc323f52686df134753 Mon Sep 17 00:00:00 2001 From: Ajith <ajithkumar.maragathavel@ziffity.com> Date: Sun, 9 Feb 2020 14:45:04 +0530 Subject: [PATCH 142/176] Delete action added for CMS page creation MTFT test --- app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml index e6fcbab4de644..838ed025e98b6 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml @@ -29,6 +29,9 @@ <actionGroup ref="CreateNewPageWithBasicValues" stepKey="createNewPageWithBasicValues" /> <actionGroup ref="SaveCmsPageActionGroup" stepKey="clickSaveCmsPageButton" /> <actionGroup ref="VerifyCreatedCmsPage" stepKey="verifyCmsPage" /> + <actionGroup ref="DeletePageByUrlKeyActionGroup" stepKey="deletePage"> + <argument name="UrlKey" value="{{_defaultCmsPage.identifier}}"/> + </actionGroup> </test> <test name="AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest"> <annotations> From eff07be5df168b7e90bcedaf20698a9af0d7b78d Mon Sep 17 00:00:00 2001 From: Ajith <ajithkumar.maragathavel@ziffity.com> Date: Sun, 9 Feb 2020 15:39:39 +0530 Subject: [PATCH 143/176] Moved tests to seperate file --- ...PageLayoutFromConfigurationSettingTest.xml | 44 ++++++++++++ .../Test/Mftf/Test/AdminCreateCmsPageTest.xml | 71 ------------------- .../Test/AdminCreateDuplicatedCmsPageTest.xml | 49 +++++++++++++ 3 files changed, 93 insertions(+), 71 deletions(-) create mode 100644 app/code/Magento/Cms/Test/Mftf/Test/AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest.xml new file mode 100644 index 0000000000000..ee06b4ce86656 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest"> + <annotations> + <features value="Cms"/> + <stories value="Default layout configuration MAGETWO-88793"/> + <title value="Admin should be able to configure the default layout for CMS Page from System Configuration"/> + <description value="Admin should be able to configure the default layout for CMS Page from System Configuration"/> + <severity value="CRITICAL"/> + <testCaseId value="MAGETWO-89025"/> + <group value="Cms"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <actionGroup ref="RestoreLayoutSetting" stepKey="sampleActionGroup"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <amOnPage url="{{WebConfigurationPage.url}}" stepKey="navigateToWebConfigurationPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <conditionalClick stepKey="expandDefaultLayouts" selector="{{WebSection.DefaultLayoutsTab}}" dependentSelector="{{WebSection.CheckIfTabExpand}}" visible="true" /> + <waitForElementVisible selector="{{DefaultLayoutsSection.pageLayout}}" stepKey="DefaultProductLayout" /> + <seeOptionIsSelected selector="{{DefaultLayoutsSection.pageLayout}}" userInput="1 column" stepKey="seeOneColumnSelected" /> + <seeOptionIsSelected selector="{{DefaultLayoutsSection.productLayout}}" userInput="No layout updates" stepKey="seeNoLayoutUpdatesSelected1" /> + <seeOptionIsSelected selector="{{DefaultLayoutsSection.categoryLayout}}" userInput="No layout updates" stepKey="seeNoLayoutUpdatesSelected2" /> + <selectOption selector="{{DefaultLayoutsSection.pageLayout}}" userInput="2 columns with right bar" stepKey="selectColumnsWithRightBar"/> + <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig" /> + <amOnPage url="{{CmsNewPagePage.url}}" stepKey="amOnPagePagesGrid"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <waitForLoadingMaskToDisappear stepKey="wait2" /> + <click selector="{{CmsDesignSection.DesignTab}}" stepKey="clickOnDesignTab"/> + <waitForElementVisible selector="{{CmsDesignSection.LayoutDropdown}}" stepKey="waitForLayoutDropDown" /> + <seeOptionIsSelected selector="{{CmsDesignSection.LayoutDropdown}}" userInput="2 columns with right bar" stepKey="seeColumnsWithRightBar" /> + </test> +</tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml index 838ed025e98b6..7fd39ab5bb1d6 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml @@ -33,75 +33,4 @@ <argument name="UrlKey" value="{{_defaultCmsPage.identifier}}"/> </actionGroup> </test> - <test name="AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest"> - <annotations> - <features value="Cms"/> - <stories value="Default layout configuration MAGETWO-88793"/> - <title value="Admin should be able to configure the default layout for CMS Page from System Configuration"/> - <description value="Admin should be able to configure the default layout for CMS Page from System Configuration"/> - <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-89025"/> - <group value="Cms"/> - </annotations> - <before> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - </before> - <after> - <actionGroup ref="RestoreLayoutSetting" stepKey="sampleActionGroup"/> - <actionGroup ref="logout" stepKey="logout"/> - </after> - <amOnPage url="{{WebConfigurationPage.url}}" stepKey="navigateToWebConfigurationPage"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <conditionalClick stepKey="expandDefaultLayouts" selector="{{WebSection.DefaultLayoutsTab}}" dependentSelector="{{WebSection.CheckIfTabExpand}}" visible="true" /> - <waitForElementVisible selector="{{DefaultLayoutsSection.pageLayout}}" stepKey="DefaultProductLayout" /> - <seeOptionIsSelected selector="{{DefaultLayoutsSection.pageLayout}}" userInput="1 column" stepKey="seeOneColumnSelected" /> - <seeOptionIsSelected selector="{{DefaultLayoutsSection.productLayout}}" userInput="No layout updates" stepKey="seeNoLayoutUpdatesSelected1" /> - <seeOptionIsSelected selector="{{DefaultLayoutsSection.categoryLayout}}" userInput="No layout updates" stepKey="seeNoLayoutUpdatesSelected2" /> - <selectOption selector="{{DefaultLayoutsSection.pageLayout}}" userInput="2 columns with right bar" stepKey="selectColumnsWithRightBar"/> - <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig" /> - <amOnPage url="{{CmsNewPagePage.url}}" stepKey="amOnPagePagesGrid"/> - <waitForPageLoad stepKey="waitForPageLoad1"/> - <waitForLoadingMaskToDisappear stepKey="wait2" /> - <click selector="{{CmsDesignSection.DesignTab}}" stepKey="clickOnDesignTab"/> - <waitForElementVisible selector="{{CmsDesignSection.LayoutDropdown}}" stepKey="waitForLayoutDropDown" /> - <seeOptionIsSelected selector="{{CmsDesignSection.LayoutDropdown}}" userInput="2 columns with right bar" stepKey="seeColumnsWithRightBar" /> - </test> - <test name="AdminCreateDuplicatedCmsPageTest"> - <annotations> - <features value="Cms"/> - <stories value="CMS Page Duplication and Reset Removal MAGETWO-87096"/> - <title value="Admin should be able to duplicate a CMS Page"/> - <description value="Admin should be able to duplicate a CMS Page"/> - <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-89184"/> - <group value="Cms"/> - </annotations> - <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> - <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - </before> - <after> - <actionGroup ref="logout" stepKey="logout"/> - </after> - <amOnPage url="{{CmsNewPagePage.url}}" stepKey="amOnPageCreationForm"/> - <waitForPageLoad stepKey="waitForPageLoad1"/> - <!--Verify Save&Duplicate button and Save&Close button--> - <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn1" /> - <see selector="{{CmsNewPagePageActionsSection.saveAndDuplicate}}" userInput="Save & Duplicate" stepKey="seeSaveAndDuplicate"/> - <see selector="{{CmsNewPagePageActionsSection.saveAndClose}}" userInput="Save & Close" stepKey="seeSaveAndClose"/> - <!--Create new CMS Page page--> - <actionGroup ref="FillOutCMSPageContent" stepKey="FillOutBlockContent"/> - <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn2" /> - <click selector="{{CmsNewPagePageActionsSection.saveAndDuplicate}}" stepKey="clickSaveAndDuplicate" /> - <waitForPageLoad stepKey="waitForPageLoad3"/> - <see userInput="You saved the page." stepKey="seeSavedPageMsgOnForm"/> - <see userInput="You duplicated the page." stepKey="seeDuplicatedPageMsg"/> - <!--Verify duplicated CMS Page--> - <seeElement selector="{{BlockNewPageBasicFieldsSection.isActive('0')}}" stepKey="seeBlockNotEnable" /> - <actionGroup ref="AssertCMSPageContentActionGroup" stepKey="assertContent"/> - <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn3" /> - <click selector="{{CmsNewPagePageActionsSection.saveAndClose}}" stepKey="clickSaveAndClose"/> - <see userInput="You saved the page." stepKey="seeSavedCMSPageMsgOnGrid"/> - <seeElement selector="div[data-role='grid-wrapper']" stepKey="seeGridPage" /> - </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml new file mode 100644 index 0000000000000..cf333f8b559d0 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateDuplicatedCmsPageTest"> + <annotations> + <features value="Cms"/> + <stories value="CMS Page Duplication and Reset Removal MAGETWO-87096"/> + <title value="Admin should be able to duplicate a CMS Page"/> + <description value="Admin should be able to duplicate a CMS Page"/> + <severity value="CRITICAL"/> + <testCaseId value="MAGETWO-89184"/> + <group value="Cms"/> + </annotations> + <before> + <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> + </before> + <after> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <amOnPage url="{{CmsNewPagePage.url}}" stepKey="amOnPageCreationForm"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <!--Verify Save&Duplicate button and Save&Close button--> + <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn1" /> + <see selector="{{CmsNewPagePageActionsSection.saveAndDuplicate}}" userInput="Save & Duplicate" stepKey="seeSaveAndDuplicate"/> + <see selector="{{CmsNewPagePageActionsSection.saveAndClose}}" userInput="Save & Close" stepKey="seeSaveAndClose"/> + <!--Create new CMS Page page--> + <actionGroup ref="FillOutCMSPageContent" stepKey="FillOutBlockContent"/> + <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn2" /> + <click selector="{{CmsNewPagePageActionsSection.saveAndDuplicate}}" stepKey="clickSaveAndDuplicate" /> + <waitForPageLoad stepKey="waitForPageLoad3"/> + <see userInput="You saved the page." stepKey="seeSavedPageMsgOnForm"/> + <see userInput="You duplicated the page." stepKey="seeDuplicatedPageMsg"/> + <!--Verify duplicated CMS Page--> + <seeElement selector="{{BlockNewPageBasicFieldsSection.isActive('0')}}" stepKey="seeBlockNotEnable" /> + <actionGroup ref="AssertCMSPageContentActionGroup" stepKey="assertContent"/> + <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn3" /> + <click selector="{{CmsNewPagePageActionsSection.saveAndClose}}" stepKey="clickSaveAndClose"/> + <see userInput="You saved the page." stepKey="seeSavedCMSPageMsgOnGrid"/> + <seeElement selector="div[data-role='grid-wrapper']" stepKey="seeGridPage" /> + </test> +</tests> From 7ef0c88e9c0b452a5e43ad0189a052a4dab500a8 Mon Sep 17 00:00:00 2001 From: Sergii Ivashchenko <serg.ivashchenko@gmail.com> Date: Sun, 9 Feb 2020 23:31:38 +0000 Subject: [PATCH 144/176] magento/magento2#26502: Code review changes --- .../Ui/base/js/grid/data-storage.test.js | 657 ++++++++---------- 1 file changed, 287 insertions(+), 370 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js index 33c2e97e0b85f..da2e4ace72f7c 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js @@ -7,257 +7,186 @@ /*jscs:disable requireCamelCaseOrUpperCaseIdentifiers*/ define([ 'jquery', - 'mageUtils', - 'underscore', 'Magento_Ui/js/grid/data-storage' -], function ($, utils, _, DataStorage) { +], function ($, DataStorage) { 'use strict'; describe('Magento_Ui/js/grid/data-storage', function () { - describe('constructor', function () { - it('converts dataScope property to array', function () { + describe('"initConfig" method', function () { + + it('returns self', function () { var model = new DataStorage({ dataScope: 'magento' }); - expect(model.dataScope).toEqual(['magento']); + expect(model.initConfig()).toEqual(model); }); - }); - describe('"initConfig" method', function () { + it('changes string dataScope property to an array', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); - var model = new DataStorage({ - dataScope: 'magento' + expect(model.dataScope).toEqual(['magento']); }); - it('Check returned value type if method called without arguments', function () { - var type = typeof model.initConfig(); + it('changes empty string dataScope property to an empty array', function () { + var model = new DataStorage({ + dataScope: '' + }); - expect(type).toEqual('object'); + expect(model.dataScope).toEqual([]); }); - it('Check this.dataScope property (is modify in initConfig method)', function () { - model.dataScope = null; - model.initConfig(); - expect(typeof model.dataScope).toEqual('object'); + it('doesn\'t change non-string dataScope property', function () { + var testScope = { + testKey: 'test value' + }, + model = new DataStorage({ + dataScope: testScope + }); + + expect(model.dataScope).toEqual(testScope); }); - it('Check this._requests property (is modify in initConfig method)', function () { + it('initializes _requests property as an empty array', function () { + var model = new DataStorage(); model._requests = null; model.initConfig(); - expect(typeof model._requests).toEqual('object'); + expect(model._requests).toEqual([]); }); }); describe('"getByIds" method', function () { - var model = new DataStorage({ - dataScope: 'magento' + it('returns false if data for ids is missing', function () { + var model = new DataStorage(); + + expect(model.getByIds([1,2,3])).toEqual(false); }); - it('check returned type if method called with argument', function () { - var ids = [1,2,3], - type = typeof model.getByIds(ids); + it('returns array of items', function () { + var item = { + id_field_name: 'entity_id', + entity_id: '1' + }, + model = new DataStorage({ + data: { + 1: item + } + }); - expect(type).toEqual('boolean'); + expect(model.getByIds([1])).toEqual([item]); }); - it('Return false if "getByIds" has been called', function () { - var ids = [1,2,3]; + }); - expect(model.getByIds(ids)).toEqual(false); - }); + describe('"getIds" method', function () { - it('Return array if "getByIds" has been called', function () { - var ids = [1], - expectedValue = [ + it('returns an array of entity_id\'s from provided data', function () { + var model = new DataStorage(), + ids = [ { id_field_name: 'entity_id', entity_id: '1' - } - ]; - - model = new DataStorage({ - dataScope: 'magento', - data: { - 1: { + }, + { id_field_name: 'entity_id', - entity_id: '1' + entity_id: '54' } - } - }); + ]; - expect(model.getByIds(ids)).toEqual(expectedValue); + expect(model.getIds(ids)).toEqual(['1', '54']); }); - }); - - describe('"getIds" method', function () { + it('returns an array of entity_id\'s from stored data if no arguments provided', function () { + var model = new DataStorage({ + data: { + 1: { + id_field_name: 'entity_id', + entity_id: '1' + }, + 2: { + id_field_name: 'entity_id', + entity_id: '42' + }, + } + }); - var model = new DataStorage({ - dataScope: 'magento' - }); - - it('check array of entity_id will return', function () { - var ids = [ - { - id_field_name: 'entity_id', - entity_id: '1' - } - ], - expectedValue = ['1']; - expect(model.getIds(ids)).toEqual(expectedValue); + expect(model.getIds()).toEqual(['1', '42']); }); }); describe('"getData" method', function () { - var model = new DataStorage({ - dataScope: 'magento' - }); - - it('check returned type if method called with argument', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }, - type = typeof model.getData(params); - - expect(type).toEqual('object'); - }); + var model = new DataStorage(); - it('check "clearRequests" has been called', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }; + it('returns the result of requestData method if scope have been changed', function () { + var requestDataResult = 'requestDataResult'; spyOn(model, 'clearRequests'); - spyOn(model, 'hasScopeChanged').and.callFake(function () { - return true; - }); - model.getData(params); + spyOn(model, 'hasScopeChanged').and.returnValue(true); + spyOn(model, 'requestData').and.returnValue(requestDataResult); + expect(model.getData()).toEqual(requestDataResult); expect(model.clearRequests).toHaveBeenCalled(); }); - it('check "getRequest" has been called', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }; + it('returns the cached result if scope have not been changed', function () { + var cachedRequestDataResult = 'cachedRequestDataResult'; - spyOn(model, 'getRequest'); - spyOn(model, 'hasScopeChanged').and.callFake(function () { - return false; - }); - model.getData(params); - expect(model.getRequest).toHaveBeenCalled(); - }); - - it('it returns cached request data if a cached request exists and no refresh option is provided', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }, - options = { - refresh: false - }; + spyOn(model, 'clearRequests'); + spyOn(model, 'requestData'); + spyOn(model, 'hasScopeChanged').and.returnValue(false); + spyOn(model, 'getRequest').and.returnValue(true); + spyOn(model, 'getRequestData').and.returnValue(cachedRequestDataResult); - spyOn(model, 'getRequestData'); - spyOn(model, 'getRequest').and.callFake(function () { - return true; - }); - model.getData(params, options); - expect(model.getRequestData).toHaveBeenCalled(); + expect(model.getData()).toEqual(cachedRequestDataResult); + expect(model.clearRequests).not.toHaveBeenCalled(); + expect(model.requestData).not.toHaveBeenCalled(); }); - it('if refresh option is true so it will ignore cache and execute the requestData function', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }, + it('returns the result of requestData method if refresh option is provided', function () { + var requestDataResult = 'requestDataResult', options = { refresh: true }; - spyOn(model, 'requestData'); - spyOn(model, 'getRequest').and.callFake(function () { - return false; - }); - model.getData(params, options); - expect(model.requestData).toHaveBeenCalled(); + spyOn(model, 'getRequest').and.returnValue(true); + spyOn(model, 'clearRequests'); + spyOn(model, 'hasScopeChanged').and.returnValue(true); + spyOn(model, 'requestData').and.returnValue(requestDataResult); + expect(model.getData({}, options)).toEqual(requestDataResult); + expect(model.clearRequests).toHaveBeenCalled(); }); }); describe('"hasScopeChanged" method', function () { - it('is function', function () { - var model = new DataStorage({ - dataScope: '' - }); - - expect(model.hasScopeChanged).toBeDefined(); - expect(typeof model.hasScopeChanged).toEqual('function'); - }); it('returns false if no requests have been made', function () { - var model = new DataStorage({ - dataScope: '' - }); + var model = new DataStorage(); expect(model.hasScopeChanged()).toBeFalsy(); }); - it('tells whether parameters defined in the dataScope property have changed', function () { - var params, newParams, model; - - params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 + it('returns true for not cached params', function () { + var params = { + search: '1', + filters: { + store_id: 0 + } }, - sorting: {}, - paging: {} - }; - - newParams = utils.extend({}, params, { - search: 'magento', - filters: { - store_id: 1 - } - }); - - model = new DataStorage({ - dataScope: 'filters.store_id' - }); + newParams = { + search: '2', + filters: { + store_id: 1 + } + }, + model = new DataStorage({ + dataScope: 'filters.store_id' + }); model.cacheRequest({ totalRecords: 0 @@ -275,50 +204,47 @@ define([ url: 'magento.com', method: 'GET', dataType: 'json' + }, + data: { + 1: { + id_field_name: 'entity_id', + entity_id: '1', + field: 'value' + }, } }); - it('Check updateData has been called', function () { + it('updates data items', function () { var data = [{ id_field_name: 'entity_id', - entity_id: '1' + entity_id: '1', + field: 'updatedValue' }]; - expect(model.updateData(data)).toBeTruthy(); + expect(model.updateData(data)).toEqual(model); + expect(model.getByIds([1])).toEqual(data); }); }); describe('"requestData" method', function () { - var model = new DataStorage({ - dataScope: 'magento' - }); + var model = new DataStorage(); it('Check Ajax request', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }, - query = utils.copy(params); - - spyOn(model, 'onRequestComplete'); - spyOn($, 'ajax').and.callFake(function () { - return { - /** - * Success result for ajax request - */ - done: function () { - model.onRequestComplete(model, query); - } - }; + var result = 'result'; + + spyOn(model, 'onRequestComplete').and.returnValue(result); + spyOn($, 'ajax').and.returnValue({ + /** + * Success result for ajax request + * + * @param handler + * @returns {*} + */ + done: function (handler) { + return handler(); + } }); - model.requestData(params); - expect($.ajax).toHaveBeenCalled(); - expect(model.onRequestComplete).toHaveBeenCalled(); + expect(model.requestData({})).toEqual(result); }); }); @@ -327,72 +253,54 @@ define([ dataScope: 'magento' }); - it('check "getRequest" has been executed', function () { + it('returns cached request', function () { var params = { - namespace: 'magento', - search: '', - sorting: {}, - paging: {} - }; + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }, + request = { + ids: ['1'], + params: params, + totalRecords: 1, + errorMessage: '' + }; - model._requests.push({ - ids: ['1'], - params: params, - totalRecords: 1, - errorMessage: '' - }); - expect(model.getRequest(params)).toBeTruthy(); + model._requests.push(request); + expect(model.getRequest(params)).toEqual(request); }); }); describe('"getRequestData" method', function () { - var model = new DataStorage({ - dataScope: 'magento' - }); - - it('check "getRequestData" has been executed', function () { - var request = { - ids: [1,2,3] - }; - - expect(model.getRequestData(request)).toBeTruthy(); - }); - - it('check "getByIds" has been executed', function () { - var request = { - ids: [1,2,3] - }; - - spyOn(model, 'getByIds'); - model.getRequestData(request); - expect(model.getByIds).toHaveBeenCalled(); - }); - - it('check "delay" function has been executed', function () { + it('returns request data', function () { var request = { - ids: [1,2,3], - totalRecords: 3, - errorMessage: '' - }; - - spyOn(_, 'delay'); - model.getRequestData(request); - expect(_.delay).toHaveBeenCalled(); - }); - - it('check "delay" function has not been executed', function () { - var request = { - ids: [1,2,3], - totalRecords: 3, + ids: [1,2], + totalRecords: 2, errorMessage: '' - }; - model = new DataStorage({ - dataScope: 'magento', - cachedRequestDelay: 0 - }); - spyOn(_, 'delay'); - model.getRequestData(request); - expect(_.delay).not.toHaveBeenCalled(); + }, + items = [ + { + id_field_name: 'entity_id', + entity_id: '1' + }, + { + id_field_name: 'entity_id', + entity_id: '2' + } + ], + result = { + items: items, + totalRecords: 2, + errorMessage: '' + }, + model = new DataStorage({ + cachedRequestDelay: 0 + }); + spyOn(model, 'getByIds').and.returnValue(items); + model.getRequestData(request).then(function (promiseResult) { + expect(promiseResult).toEqual(result) + }) }); }); @@ -401,73 +309,83 @@ define([ dataScope: 'magento' }); - it('check "model._requests"', function () { + it('adds the request to the cache', function () { var params = { - namespace: 'magento', - search: '', - sorting: {}, - paging: {} - }, - data = { - items: ['1','2','3'], - totalRecords: 3 - }; + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }, + ids = ['1','2','3'], + data = { + items: ids, + totalRecords: 3, + errorMessage: '' + }, + request = { + ids: ids, + params: params, + totalRecords: 3, + errorMessage: '' + }; spyOn(model, 'removeRequest'); - spyOn(model, 'getIds').and.callFake(function () { - return ['1','2','3']; - }); + spyOn(model, 'getIds').and.returnValue(ids); model.cacheRequest(data, params); - expect(typeof model._requests).toEqual('object'); - expect(model.getIds).toHaveBeenCalled(); + expect(model.getRequest(params)).toEqual(request); expect(model.removeRequest).not.toHaveBeenCalled(); }); - it('check "removeRequest" is executed', function () { + it('overwrites the previously cached request for the same params', function () { var params = { namespace: 'magento', search: '', sorting: {}, paging: {} }, - data = { - items: ['1','2','3'], - totalRecords: 3 + ids = ['1','2','3'], + firstData = { + items: ids, + totalRecords: 3, + errorMessage: '' + }, + secondData = { + items: ids, + totalRecords: 3, + errorMessage: 'Error message' + }, + firstRequest = { + ids: ids, + params: params, + totalRecords: 3, + errorMessage: '' + }, + secondRequest = { + ids: ids, + params: params, + totalRecords: 3, + errorMessage: 'Error message' }; - spyOn(model, 'removeRequest'); - spyOn(model, 'getRequest').and.callFake(function () { - return true; - }); - spyOn(model, 'getIds').and.callFake(function () { - return ['1','2','3']; - }); - model.cacheRequest(data, params); - expect(typeof model._requests).toEqual('object'); - expect(model.getIds).toHaveBeenCalled(); - expect(model.removeRequest).toHaveBeenCalled(); + spyOn(model, 'getIds').and.returnValue(ids); + model.cacheRequest(firstData, params); + expect(model.getRequest(params)).toEqual(firstRequest); + model.cacheRequest(secondData, params); + expect(model.getRequest(params)).toEqual(secondRequest); }); }); describe('"clearRequests" method', function () { - var model = new DataStorage({ - dataScope: 'magento' - }); - - it('check "clearRequests" will empty _requests array', function () { - var params = { - namespace: 'magento', - search: 'magento', - filters: { - store_id: 1 - } - }; - - model = new DataStorage({ - dataScope: 'magento', - _requests: [] - }); + it('removes all cached requests', function () { + var model = new DataStorage(), + params = { + namespace: 'magento', + search: 'magento', + filters: { + store_id: 1 + } + }; model._requests.push({ ids: ['1','2','3','4'], @@ -482,26 +400,26 @@ define([ describe('"removeRequest" method', function () { - var model = new DataStorage({ - dataScope: 'magento' - }); + var model = new DataStorage(); - it('check "removeRequest" is defined', function () { + it('removes the request from the cache', function () { var params = { - namespace: 'magento', - search: 'magento', - filters: { - store_id: 1 - } - }, - request = [{ - ids: [1,2,3], - params: params, - totalRecords: 3, - errorMessage: 'errorMessage' - }]; + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }, + request = { + ids: ['1','2','3'], + params: params, + totalRecords: 3, + errorMessage: '' + }; - expect(model.removeRequest(request)).toBeDefined(); + model._requests = [request]; + expect(model.getRequest(params)).toEqual(request); + model.removeRequest(request); + expect(model.getRequest(params)).toBeFalsy(); }); }); @@ -510,7 +428,7 @@ define([ dataScope: 'magento' }); - it('Return false if getRequest method returns false', function () { + it('returns false if request is not present in cache', function () { var params = { namespace: 'magento', search: '', @@ -518,61 +436,60 @@ define([ paging: {} }; - spyOn(model, 'getRequest').and.callFake(function () { - return false; - }); expect(model.wasRequested(params)).toBeFalsy(); }); - }); - describe('"onRequestComplete" method', function () { - var model = new DataStorage({ - dataScope: 'magento' - }); - - it('Check "updateData" method has been called', function () { - var data = { - items: [{ - id_field_name: 'entity_id', - entity_id: '1' - }] - }, - params = { + it('returns true if request is present in cache', function () { + var params = { namespace: 'magento', search: '', sorting: {}, paging: {} + }, + request = { + ids: ['1','2','3'], + params: params, + totalRecords: 3, + errorMessage: '' }; - spyOn(model, 'updateData').and.callFake(function () { - return data; - }); + model._requests = [request]; + + expect(model.wasRequested(params)).toBeTruthy(); + }); + }); + + describe('"onRequestComplete" method', function () { + + it('updates data and does not cache the request if caching is disabled', function () { + var model = new DataStorage({ + cacheRequests: false + }), + data = { + items: [] + }, + params = {}; + + spyOn(model, 'updateData'); + spyOn(model, 'cacheRequest'); model.onRequestComplete(params, data); expect(model.updateData).toHaveBeenCalled(); + expect(model.cacheRequest).not.toHaveBeenCalled(); }); - it('Check "cacheRequest" method has been called', function () { - var data = { - items: [{ - id_field_name: 'entity_id', - entity_id: '1' - }] - }, - params = { - namespace: 'magento', - search: '', - sorting: {}, - paging: {} - }; + it('updates data and adds the request to cache if caching is enabled', function () { + var model = new DataStorage({ + cacheRequests: true + }), + data = { + items: [] + }, + params = {}; - model = new DataStorage({ - dataScope: 'magento', - cacheRequests: true - }); - spyOn(model, 'cacheRequest').and.callFake(function () { - return data; - }); + spyOn(model, 'updateData'); + spyOn(model, 'cacheRequest'); model.onRequestComplete(params, data); + expect(model.updateData).toHaveBeenCalled(); expect(model.cacheRequest).toHaveBeenCalled(); }); }); From 6d0fa267f2950dc6243a312d7a48d4b967be770e Mon Sep 17 00:00:00 2001 From: Slava Mankivski <mankivsk@adobe.com> Date: Sun, 9 Feb 2020 22:34:05 -0600 Subject: [PATCH 145/176] Updated composer.lock --- composer.lock | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 5b94f60fa80a9..d5f3f4917af7c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "988eebffd81167973e4a51d7efd5be46", + "content-hash": "7b6381bcafc7f064e10ee71099b7d50b", "packages": [ { "name": "braintree/braintree_php", @@ -88,16 +88,16 @@ }, { "name": "colinmollenhour/cache-backend-redis", - "version": "1.10.6", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/colinmollenhour/Cm_Cache_Backend_Redis.git", - "reference": "cc941a5f4cc017e11d3eab9061811ba9583ed6bf" + "reference": "389fb68de15660e39b055d149d31f3708b5d6cbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/colinmollenhour/Cm_Cache_Backend_Redis/zipball/cc941a5f4cc017e11d3eab9061811ba9583ed6bf", - "reference": "cc941a5f4cc017e11d3eab9061811ba9583ed6bf", + "url": "https://api.github.com/repos/colinmollenhour/Cm_Cache_Backend_Redis/zipball/389fb68de15660e39b055d149d31f3708b5d6cbc", + "reference": "389fb68de15660e39b055d149d31f3708b5d6cbc", "shasum": "" }, "require": { @@ -120,7 +120,7 @@ ], "description": "Zend_Cache backend using Redis with full support for tags.", "homepage": "https://github.com/colinmollenhour/Cm_Cache_Backend_Redis", - "time": "2018-09-24T16:02:07+00:00" + "time": "2019-03-03T04:04:49+00:00" }, { "name": "colinmollenhour/credis", @@ -830,6 +830,7 @@ } ], "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", + "abandoned": true, "time": "2018-07-31T13:22:33+00:00" }, { @@ -880,6 +881,7 @@ "Guzzle", "stream" ], + "abandoned": true, "time": "2014-10-12T19:18:40+00:00" }, { From a1d2a846d5752eb3708155ecc9468835d82f4504 Mon Sep 17 00:00:00 2001 From: Shankar Konar <konar.shankar2013@gmail.com> Date: Mon, 10 Feb 2020 11:25:47 +0530 Subject: [PATCH 146/176] Fixed static tests --- .../Magento/Ui/base/js/grid/data-storage.test.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js index da2e4ace72f7c..4fe7aff69d0e2 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js @@ -5,6 +5,8 @@ /*eslint max-nested-callbacks: 0*/ /*jscs:disable requireCamelCaseOrUpperCaseIdentifiers*/ +/*eslint newline-after-var: ["error", "always"]*/ +/*eslint-env es6*/ define([ 'jquery', 'Magento_Ui/js/grid/data-storage' @@ -52,6 +54,7 @@ define([ it('initializes _requests property as an empty array', function () { var model = new DataStorage(); + model._requests = null; model.initConfig(); expect(model._requests).toEqual([]); @@ -110,7 +113,7 @@ define([ 2: { id_field_name: 'entity_id', entity_id: '42' - }, + } } }); @@ -129,8 +132,10 @@ define([ spyOn(model, 'clearRequests'); spyOn(model, 'hasScopeChanged').and.returnValue(true); spyOn(model, 'requestData').and.returnValue(requestDataResult); + spyOn(model, 'getRequest'); expect(model.getData()).toEqual(requestDataResult); expect(model.clearRequests).toHaveBeenCalled(); + expect(model.getRequest).not.toHaveBeenCalled(); }); it('returns the cached result if scope have not been changed', function () { @@ -210,7 +215,7 @@ define([ id_field_name: 'entity_id', entity_id: '1', field: 'value' - }, + } } }); @@ -237,7 +242,7 @@ define([ /** * Success result for ajax request * - * @param handler + * @param {Function} handler * @returns {*} */ done: function (handler) { @@ -297,10 +302,11 @@ define([ model = new DataStorage({ cachedRequestDelay: 0 }); + spyOn(model, 'getByIds').and.returnValue(items); model.getRequestData(request).then(function (promiseResult) { - expect(promiseResult).toEqual(result) - }) + expect(promiseResult).toEqual(result); + }); }); }); From 1f2ed9035507c8ebf46ddacd0e9c923206ffec0d Mon Sep 17 00:00:00 2001 From: Shankar Konar <konar.shankar2013@gmail.com> Date: Mon, 10 Feb 2020 11:29:00 +0530 Subject: [PATCH 147/176] code cleanup --- .../tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js index 4fe7aff69d0e2..b53f49bd6103d 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js @@ -5,8 +5,6 @@ /*eslint max-nested-callbacks: 0*/ /*jscs:disable requireCamelCaseOrUpperCaseIdentifiers*/ -/*eslint newline-after-var: ["error", "always"]*/ -/*eslint-env es6*/ define([ 'jquery', 'Magento_Ui/js/grid/data-storage' From 435c3fe27964a15729ecbc2ebbafe04b34412faf Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Mon, 10 Feb 2020 09:42:21 +0200 Subject: [PATCH 148/176] remove fixtures after test --- .../Magento/Ui/base/js/modal/modal.test.js | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js index ccfad86c6cfb0..3625d0898e942 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js @@ -11,13 +11,24 @@ define([ describe('ui/js/modal/modal', function () { - var element = $('<div>Element</div>'), + var element, + modal; + + beforeEach(function () { + element = $('<div id="element">Element</div>'); modal = element.modal({}).data('mage-modal'); - $(element).append('<h1 class="modal-title"' + - ' data-role="title">Title</h1>' + - '<span class="modal-subtitle"' + - ' data-role="subTitle"></span>'); + $(element).append('<h1 class="modal-title"' + + ' data-role="title">Title</h1>' + + '<span class="modal-subtitle"' + + ' data-role="subTitle"></span>'); + }); + + afterEach(function () { + $('.modal-title').remove(); + $('#element').remove(); + + }); it('Check for modal definition', function () { expect(modal).toBeDefined(); @@ -32,12 +43,12 @@ define([ expect($(modal).length).toEqual(1); }); - it('Verify setTitle() method set title', function () { + it('Verify set title', function () { var newTitle = 'New modal title'; modal.setTitle(newTitle); expect($(modal.options.modalTitle).text()).toContain(newTitle); - expect($(modal.options.modalTitle).find(modal.options.modalSubTitle).length).toBe(2); + expect($(modal.options.modalTitle).find(modal.options.modalSubTitle).length).toBe(1); }); }); }); From f755b429c8022b8a2b03a5c9da0aea5100c90d41 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Mon, 10 Feb 2020 09:43:47 +0200 Subject: [PATCH 149/176] MC-30650: [Magento Cloud] Customer Creation - The store view is not in the associated website --- app/code/Magento/Customer/i18n/en_US.csv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Customer/i18n/en_US.csv b/app/code/Magento/Customer/i18n/en_US.csv index a70aa08dba735..0bcd5ce27dbb5 100644 --- a/app/code/Magento/Customer/i18n/en_US.csv +++ b/app/code/Magento/Customer/i18n/en_US.csv @@ -540,3 +540,5 @@ Addresses,Addresses "Middle Name/Initial","Middle Name/Initial" "Suffix","Suffix" "The Date of Birth should not be greater than today.","The Date of Birth should not be greater than today." +"The store view is not in the associated website.","The store view is not in the associated website." +"The Store View selected for sending Welcome email from is not related to the customer's associated website.","The Store View selected for sending Welcome email from is not related to the customer's associated website." From 959e5e260532f1fbebd37830921e8bdb52339e93 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 10 Feb 2020 10:28:59 +0200 Subject: [PATCH 150/176] MC-31262: Storefront: Reset/Forgot customer password --- .../Block/Account/ResetPasswordTest.php | 86 +++++++++++ .../Customer/Controller/AccountTest.php | 79 ---------- .../Controller/CreatePasswordTest.php | 98 +++++++++++++ .../Controller/ForgotPasswordPostTest.php | 137 ++++++++++++++++++ .../AccountManagement/ForgotPasswordTest.php | 64 ++++++++ 5 files changed, 385 insertions(+), 79 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Block/Account/ResetPasswordTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Controller/ForgotPasswordPostTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/ForgotPasswordTest.php diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Account/ResetPasswordTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Account/ResetPasswordTest.php new file mode 100644 index 0000000000000..cc087e006025d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Account/ResetPasswordTest.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Block\Account; + +use Magento\Framework\Math\Random; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Class checks password reset block output + * + * @see \Magento\Customer\Block\Account\Resetpassword + * @magentoAppArea frontend + */ +class ResetPasswordTest extends TestCase +{ + private const FORM_XPATH = "//form[contains(@action, '?token=%s')]"; + private const SET_NEW_PASSWORD_BUTTON_XPATH = "//button/span[contains(text(),'Set a New Password')]"; + private const NEW_PASSWORD_LABEL_XPATH = "//label[@for='password']/span[contains(text(), 'New Password')]"; + private const PASSWORD_CONFIRMATION_LABEL_XPATH = "//label[@for='password-confirmation']" + . "/span[contains(text(), 'Confirm New Password')]"; + + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var LayoutInterface */ + private $layout; + + /** @var Resetpassword */ + private $block; + + /** @var Random */ + private $random; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->random = $this->objectManager->get(Random::class); + $this->block = $this->layout->createBlock(Resetpassword::class); + $this->block->setTemplate('Magento_Customer::form/resetforgottenpassword.phtml'); + } + + /** + * @return void + */ + public function testResetPasswordForm(): void + { + $token = $this->random->getUniqueHash(); + $this->block->setResetPasswordLinkToken($token); + $output = $this->block->toHtml(); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf(self::FORM_XPATH, $token), $output), + 'Form action does not include correct token' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::NEW_PASSWORD_LABEL_XPATH, $output), + 'New password label was not found on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::PASSWORD_CONFIRMATION_LABEL_XPATH, $output), + 'Confirm password label was not found on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::SET_NEW_PASSWORD_BUTTON_XPATH, $output), + 'Set password button was not found on the page' + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index df4acf3acca91..18f9b2d2cb737 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -132,35 +132,6 @@ public function testLogoutAction() $this->assertRedirect($this->stringContains('customer/account/logoutSuccess')); } - /** - * Test that forgot password email message displays special characters correctly. - * - * @codingStandardsIgnoreStart - * @magentoConfigFixture current_store customer/password/limit_password_reset_requests_method 0 - * @magentoConfigFixture current_store customer/password/forgot_email_template customer_password_forgot_email_template - * @magentoConfigFixture current_store customer/password/forgot_email_identity support - * @magentoConfigFixture current_store general/store_information/name Test special' characters - * @magentoConfigFixture current_store customer/captcha/enable 0 - * @magentoDataFixture Magento/Customer/_files/customer.php - * @codingStandardsIgnoreEnd - */ - public function testForgotPasswordEmailMessageWithSpecialCharacters() - { - $email = 'customer@example.com'; - - $this->getRequest()->setPostValue(['email' => $email]); - $this->getRequest()->setMethod(HttpRequest::METHOD_POST); - - $this->dispatch('customer/account/forgotPasswordPost'); - $this->assertRedirect($this->stringContains('customer/account/')); - - $subject = $this->transportBuilderMock->getSentMessage()->getSubject(); - $this->assertContains( - 'Test special\' characters', - $subject - ); - } - /** * @magentoDataFixture Magento/Customer/_files/customer.php */ @@ -397,56 +368,6 @@ public function testActiveUserConfirmationAction() ); } - /** - * @codingStandardsIgnoreStart - * @magentoConfigFixture current_store customer/password/limit_password_reset_requests_method 0 - * @magentoConfigFixture current_store customer/password/forgot_email_template customer_password_forgot_email_template - * @magentoConfigFixture current_store customer/password/forgot_email_identity support - * @magentoConfigFixture current_store customer/captcha/enable 0 - * @magentoDataFixture Magento/Customer/_files/customer.php - * @codingStandardsIgnoreEnd - */ - public function testForgotPasswordPostAction() - { - $email = 'customer@example.com'; - - $this->getRequest()->setMethod(HttpRequest::METHOD_POST); - $this->getRequest()->setPostValue(['email' => $email]); - - $this->dispatch('customer/account/forgotPasswordPost'); - $this->assertRedirect($this->stringContains('customer/account/')); - - $message = __( - 'If there is an account associated with %1 you will receive an email with a link to reset your password.', - $email - ); - $this->assertSessionMessages( - $this->equalTo([$message]), - MessageInterface::TYPE_SUCCESS - ); - } - - /** - * @magentoConfigFixture current_store customer/captcha/enable 0 - */ - public function testForgotPasswordPostWithBadEmailAction() - { - $this->getRequest()->setMethod(HttpRequest::METHOD_POST); - $this->getRequest() - ->setPostValue( - [ - 'email' => 'bad@email', - ] - ); - - $this->dispatch('customer/account/forgotPasswordPost'); - $this->assertRedirect($this->stringContains('customer/account/forgotpassword')); - $this->assertSessionMessages( - $this->equalTo(['The email address is incorrect. Verify the email address and try again.']), - MessageInterface::TYPE_ERROR - ); - } - /** * @magentoDataFixture Magento/Customer/_files/customer.php */ diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php new file mode 100644 index 0000000000000..9ad25ae5ddd5f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Controller; + +use Magento\Customer\Model\CustomerRegistry; +use Magento\Customer\Model\ResourceModel\Customer as CustomerResource; +use Magento\Customer\Model\Session; +use Magento\Framework\Math\Random; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\AbstractController; + +/** + * Class checks password forgot scenarios + * + * @magentoDbIsolation enabled + */ +class CreatePasswordTest extends AbstractController +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Session */ + private $session; + + /** @var LayoutInterface */ + private $layout; + + /** @var Random */ + private $random; + + /** @var CustomerResource */ + private $customerResource; + + /** @var CustomerRegistry */ + private $customerRegistry; + + /** @var WebsiteRepositoryInterface */ + private $websiteRepository; + + /** @var int */ + private $customerId; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->session = $this->objectManager->get(Session::class); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->random = $this->objectManager->get(Random::class); + $this->customerResource = $this->objectManager->get(CustomerResource::class); + $this->customerRegistry = $this->objectManager->get(CustomerRegistry::class); + $this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->customerRegistry->remove($this->customerId); + + parent::tearDown(); + } + + + /** + * @magentoDataFixture Magento/Customer/_files/customer_with_website.php + * + * @return void + */ + public function testCreatePassword(): void + { + $defaultWebsite = $this->websiteRepository->get('base')->getId(); + $customer = $this->customerRegistry->retrieveByEmail('john.doe@magento.com', $defaultWebsite); + $this->customerId = $customer->getId(); + $token = $this->random->getUniqueHash(); + $customer->changeResetPasswordLinkToken($token); + $customer->setData('confirmation', 'confirmation'); + $this->customerResource->save($customer); + $this->session->setRpToken($token); + $this->session->setRpCustomerId($customer->getId()); + $this->dispatch('customer/account/createPassword'); + $block = $this->layout->getBlock('resetPassword'); + $this->assertEquals($token, $block->getResetPasswordLinkToken()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/ForgotPasswordPostTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/ForgotPasswordPostTest.php new file mode 100644 index 0000000000000..8bfe3b5524487 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/ForgotPasswordPostTest.php @@ -0,0 +1,137 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Controller; + +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\Message\MessageInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Mail\Template\TransportBuilderMock; +use Magento\TestFramework\TestCase\AbstractController; + +/** + * Class checks password forgot scenarios + * + * @see \Magento\Customer\Controller\Account\ForgotPasswordPost + * @magentoDbIsolation enabled + */ +class ForgotPasswordPostTest extends AbstractController +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var TransportBuilderMock */ + private $transportBuilderMock; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->transportBuilderMock = $this->objectManager->get(TransportBuilderMock::class); + } + + /** + * @magentoConfigFixture current_store customer/captcha/enable 0 + * + * @return void + */ + public function testWithoutEmail(): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue(['email' => '']); + $this->dispatch('customer/account/forgotPasswordPost'); + $this->assertSessionMessages( + $this->equalTo([(string)__('Please enter your email.')]), + MessageInterface::TYPE_ERROR + ); + $this->assertRedirect($this->stringContains('customer/account/forgotpassword')); + } + + /** + * Test that forgot password email message displays special characters correctly. + * + * @magentoConfigFixture current_store customer/password/limit_password_reset_requests_method 0 + * @codingStandardsIgnoreStart + * @magentoConfigFixture current_store customer/password/forgot_email_template customer_password_forgot_email_template + * @codingStandardsIgnoreEnd + * @magentoConfigFixture current_store customer/password/forgot_email_identity support + * @magentoConfigFixture current_store general/store_information/name Test special' characters + * @magentoConfigFixture current_store customer/captcha/enable 0 + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testForgotPasswordEmailMessageWithSpecialCharacters(): void + { + $email = 'customer@example.com'; + $this->getRequest()->setPostValue(['email' => $email]); + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->dispatch('customer/account/forgotPasswordPost'); + $this->assertRedirect($this->stringContains('customer/account/')); + $this->assertSuccessSessionMessage($email); + $subject = $this->transportBuilderMock->getSentMessage()->getSubject(); + $this->assertContains('Test special\' characters', $subject); + } + + /** + * @magentoConfigFixture current_store customer/password/limit_password_reset_requests_method 0 + * @codingStandardsIgnoreStart + * @magentoConfigFixture current_store customer/password/forgot_email_template customer_password_forgot_email_template + * @codingStandardsIgnoreEnd + * @magentoConfigFixture current_store customer/password/forgot_email_identity support + * @magentoConfigFixture current_store customer/captcha/enable 0 + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testForgotPasswordPostAction(): void + { + $email = 'customer@example.com'; + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue(['email' => $email]); + $this->dispatch('customer/account/forgotPasswordPost'); + $this->assertRedirect($this->stringContains('customer/account/')); + $this->assertSuccessSessionMessage($email); + } + + /** + * @magentoConfigFixture current_store customer/captcha/enable 0 + * + * @return void + */ + public function testForgotPasswordPostWithBadEmailAction(): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue(['email' => 'bad@email']); + $this->dispatch('customer/account/forgotPasswordPost'); + $this->assertRedirect($this->stringContains('customer/account/forgotpassword')); + $this->assertSessionMessages( + $this->equalTo(['The email address is incorrect. Verify the email address and try again.']), + MessageInterface::TYPE_ERROR + ); + } + + /** + * Assert success session message + * + * @param string $email + * @return void + */ + private function assertSuccessSessionMessage(string $email): void + { + $message = __( + 'If there is an account associated with %1 you will receive an email with a link to reset your password.', + $email + ); + $this->assertSessionMessages($this->equalTo([$message]), MessageInterface::TYPE_SUCCESS); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/ForgotPasswordTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/ForgotPasswordTest.php new file mode 100644 index 0000000000000..7820316d9f41f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/ForgotPasswordTest.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\AccountManagement; + +use Magento\Customer\Api\AccountManagementInterface; +use Magento\Customer\Model\AccountManagement; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use Magento\TestFramework\Mail\Template\TransportBuilderMock; +use PHPUnit\Framework\TestCase; + +/** + * Class checks password forgot scenarios + * + * @magentoDbIsolation enabled + */ +class ForgotPasswordTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var AccountManagementInterface */ + private $accountManagement; + + /** @var TransportBuilderMock */ + private $transportBuilder; + + /** @var string */ + private $newPasswordLinkPath = "//a[contains(@href, 'customer/account/createPassword') " + . "and contains(text(), 'Set a New Password')]"; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->accountManagement = $this->objectManager->get(AccountManagementInterface::class); + $this->transportBuilder = $this->objectManager->get(TransportBuilderMock::class); + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testForgotPassword(): void + { + $email = 'customer@example.com'; + $result = $this->accountManagement->initiatePasswordReset($email, AccountManagement::EMAIL_RESET); + $message = $this->transportBuilder->getSentMessage(); + $messageContent = $message->getBody()->getParts()[0]->getRawContent(); + $this->assertTrue($result); + $this->assertEquals(1, Xpath::getElementsCountForXpath($this->newPasswordLinkPath, $messageContent)); + } +} From f7827c90528f2118041a8ef139da8d30823b3161 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 10 Feb 2020 10:32:46 +0200 Subject: [PATCH 151/176] MC-31264: Storefront: View bundle product on storefront --- .../Bundle/Model/PrepareBundleLinks.php | 89 ++++++++ .../Type/AbstractBundleOptionsViewTest.php | 194 +++++++++++++++++ .../Catalog/Product/View/Type/BundleTest.php | 203 ++++++++++++++---- .../View/Type/CheckboxOptionViewTest.php | 77 +++++++ .../View/Type/DropDownOptionViewTest.php | 77 +++++++ .../View/Type/MultiselectOptionViewTest.php | 77 +++++++ .../Product/View/Type/RadioOptionViewTest.php | 73 +++++++ .../bundle_product_checkbox_options.php | 77 +++++++ ...ndle_product_checkbox_options_rollback.php | 27 +++ ...undle_product_checkbox_required_option.php | 68 ++++++ ...duct_checkbox_required_option_rollback.php | 26 +++ ...ndle_product_checkbox_required_options.php | 76 +++++++ ...uct_checkbox_required_options_rollback.php | 27 +++ .../bundle_product_dropdown_options.php | 76 +++++++ ...ndle_product_dropdown_options_rollback.php | 27 +++ ...ndle_product_dropdown_required_options.php | 76 +++++++ ...uct_dropdown_required_options_rollback.php | 27 +++ .../bundle_product_multiselect_options.php | 76 +++++++ ...e_product_multiselect_options_rollback.php | 27 +++ ...le_product_multiselect_required_option.php | 68 ++++++ ...t_multiselect_required_option_rollback.php | 26 +++ ...e_product_multiselect_required_options.php | 76 +++++++ ..._multiselect_required_options_rollback.php | 27 +++ .../_files/bundle_product_radio_options.php | 76 +++++++ .../bundle_product_radio_options_rollback.php | 27 +++ .../bundle_product_radio_required_option.php | 68 ++++++ ...product_radio_required_option_rollback.php | 26 +++ .../bundle_product_radio_required_options.php | 77 +++++++ ...roduct_radio_required_options_rollback.php | 27 +++ 29 files changed, 1860 insertions(+), 38 deletions(-) create mode 100644 dev/tests/integration/framework/Magento/TestFramework/Bundle/Model/PrepareBundleLinks.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/AbstractBundleOptionsViewTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/CheckboxOptionViewTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/DropDownOptionViewTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/MultiselectOptionViewTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/RadioOptionViewTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options_rollback.php diff --git a/dev/tests/integration/framework/Magento/TestFramework/Bundle/Model/PrepareBundleLinks.php b/dev/tests/integration/framework/Magento/TestFramework/Bundle/Model/PrepareBundleLinks.php new file mode 100644 index 0000000000000..6a7d034d5892f --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Bundle/Model/PrepareBundleLinks.php @@ -0,0 +1,89 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestFramework\Bundle\Model; + +use Magento\Bundle\Api\Data\LinkInterfaceFactory; +use Magento\Bundle\Api\Data\OptionInterfaceFactory; +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\Data\ProductExtensionFactory; +use Magento\Catalog\Api\Data\ProductInterface; + +/** + * Prepare bundle product links + */ +class PrepareBundleLinks +{ + /** @var LinkInterfaceFactory */ + private $linkFactory; + + /** @var OptionInterfaceFactory */ + private $optionLinkFactory; + + /** @var ProductExtensionFactory */ + private $extensionAttributesFactory; + + /** + * @param LinkInterfaceFactory $linkFactory + * @param OptionInterfaceFactory $optionLinkFactory + * @param ProductExtensionFactory $extensionAttributesFactory + */ + public function __construct( + LinkInterfaceFactory $linkFactory, + OptionInterfaceFactory $optionLinkFactory, + ProductExtensionFactory $extensionAttributesFactory + ) { + $this->linkFactory = $linkFactory; + $this->optionLinkFactory = $optionLinkFactory; + $this->extensionAttributesFactory = $extensionAttributesFactory; + } + + /** + * Prepare bundle product links + * + * @param ProductInterface $product + * @param array $bundleOptionsData + * @param array $bundleSelectionsData + * @return ProductInterface + */ + public function execute( + ProductInterface $product, + array $bundleOptionsData, + array $bundleSelectionsData + ): ProductInterface { + $product->setBundleOptionsData($bundleOptionsData) + ->setBundleSelectionsData($bundleSelectionsData); + $options = []; + foreach ($product->getBundleOptionsData() as $key => $optionData) { + $option = $this->optionLinkFactory->create(['data' => $optionData]); + $option->setSku($product->getSku()); + $option->setOptionId(null); + $links = []; + $bundleLinks = $product->getBundleSelectionsData(); + foreach ($bundleLinks[$key] as $linkData) { + $link = $this->linkFactory->create(['data' => $linkData]); + $link->setQty($linkData['selection_qty']); + $priceType = $price = null; + if ($product->getPriceType() === Price::PRICE_TYPE_FIXED) { + $priceType = $linkData['selection_price_type'] ?? null; + $price = $linkData['selection_price_value'] ?? null; + } + $link->setPriceType($priceType); + $link->setPrice($price); + $links[] = $link; + } + $option->setProductLinks($links); + $options[] = $option; + } + /** @var ProductExtensionFactory $extensionAttributesFactory */ + $extensionAttributes = $product->getExtensionAttributes() ?? $this->extensionAttributesFactory->create(); + $extensionAttributes->setBundleProductOptions($options); + $product->setExtensionAttributes($extensionAttributes); + + return $product; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/AbstractBundleOptionsViewTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/AbstractBundleOptionsViewTest.php new file mode 100644 index 0000000000000..287a3f07d1964 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/AbstractBundleOptionsViewTest.php @@ -0,0 +1,194 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Block\Catalog\Product\View\Type; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\ResourceModel\Product as ProductResource; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\View\Result\PageFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Class consist of basic logic for bundle options view + */ +abstract class AbstractBundleOptionsViewTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var SerializerInterface */ + private $serializer; + + /** @var Registry */ + private $registry; + + /** @var PageFactory */ + private $pageFactory; + + /** @var ProductResource */ + private $productResource; + + /** @var string */ + private $selectLabelXpath = "//fieldset[contains(@class, 'fieldset-bundle-options')]" + . "//label/span[normalize-space(text()) = '%s']"; + + /** @var string */ + private $backToProductDetailButtonXpath = "//button[contains(@class, 'back customization')]"; + + /** @var string */ + private $titleXpath = "//fieldset[contains(@class, 'bundle-options')]//span[contains(text(), 'Customize %s')]"; + + /** @var string */ + private $singleOptionXpath = "//input[contains(@class, 'bundle-option') and contains(@type, 'hidden')]"; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->serializer = $this->objectManager->get(SerializerInterface::class); + $this->registry = $this->objectManager->get(Registry::class); + $this->pageFactory = $this->objectManager->get(PageFactory::class); + $this->productResource = $this->objectManager->get(ProductResource::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister('product'); + $this->registry->unregister('current_product'); + + parent::tearDown(); + } + + /** + * Process bundle options view with few selections + * + * @param string $sku + * @param string $optionsSelectLabel + * @param array $expectedSelectionsNames + * @param bool $requiredOption + * @return void + */ + protected function processMultiSelectionsView( + string $sku, + string $optionsSelectLabel, + array $expectedSelectionsNames, + bool $requiredOption = false + ): void { + $product = $this->productRepository->get($sku); + $result = $this->renderProductOptionsBlock($product); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($this->backToProductDetailButtonXpath, $result), + "'Back to product details' button doesn't exist on the page" + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($this->selectLabelXpath, $optionsSelectLabel), $result), + 'Options select label does not exist on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($this->titleXpath, $product->getName()), $result), + sprintf('Customize %s label does not exist on the page', $product->getName()) + ); + $selectPath = $requiredOption ? $this->getRequiredSelectXpath() : $this->getNotRequiredSelectXpath(); + foreach ($expectedSelectionsNames as $selection) { + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($selectPath, $selection), $result), + sprintf('Option for product named %s does not exist on the page', $selection) + ); + } + } + + /** + * Process bundle options view with single selection + * + * @param string $sku + * @param string $optionsSelectLabel + * @return void + */ + protected function processSingleSelectionView(string $sku, string $optionsSelectLabel): void + { + $product = $this->productRepository->get($sku); + $result = $this->renderProductOptionsBlock($product); + $this->assertEquals(1, Xpath::getElementsCountForXpath($this->backToProductDetailButtonXpath, $result)); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($this->selectLabelXpath, $optionsSelectLabel), $result), + 'Options select label does not exist on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($this->singleOptionXpath, $result), + 'Bundle product options select with single option does not display correctly' + ); + } + + /** + * Register product + * + * @param ProductInterface $product + * @return void + */ + private function registerProduct(ProductInterface $product): void + { + $this->registry->unregister('product'); + $this->registry->unregister('current_product'); + $this->registry->register('product', $product); + $this->registry->register('current_product', $product); + } + + /** + * Render bundle product options block + * + * @param ProductInterface $product + * @return string + */ + private function renderProductOptionsBlock(ProductInterface $product): string + { + $this->registerProduct($product); + $page = $this->pageFactory->create(); + $page->addHandle(['default', 'catalog_product_view', 'catalog_product_view_type_bundle']); + $page->getLayout()->generateXml(); + $block = $page->getLayout()->getBlock('product.info.bundle.options'); + + return $block->toHtml(); + } + + /** + * Get required select Xpath + * + * @return string + */ + abstract protected function getRequiredSelectXpath(): string; + + /** + * Get not required select Xpath + * + * @return string + */ + abstract protected function getNotRequiredSelectXpath(): string; +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleTest.php index ce324ed774dc4..dab699064c4bb 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleTest.php @@ -7,53 +7,66 @@ namespace Magento\Bundle\Block\Catalog\Product\View\Type; +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + /** - * Test for Magento\Bundle\Block\Catalog\Product\View\Type\Bundle + * Class checks bundle product view behaviour * * @magentoDataFixture Magento/Bundle/_files/product.php - * @magentoDbIsolation disabled + * @magentoDbIsolation enabled * @magentoAppArea frontend + * @see \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle */ -class BundleTest extends \PHPUnit\Framework\TestCase +class BundleTest extends TestCase { - /** - * @var \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle - */ + /** @var Bundle */ private $block; - /** - * @var \Magento\Catalog\Api\Data\ProductInterface - */ - private $product; - - /** - * @var \Magento\TestFramework\ObjectManager - */ + /** @var ObjectManagerInterface */ private $objectManager; - /** - * @var \Magento\Catalog\Api\ProductRepositoryInterface - */ + /** @var ProductRepositoryInterface */ private $productRepository; + /** @var LayoutInterface */ + private $layout; + + /** @var SerializerInterface */ + private $json; + + /** @var Registry */ + private $registry; + /** * @inheritdoc */ protected function setUp() { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - - $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - $this->product = $this->productRepository->get('bundle-product', false, null, true); - $this->product->setPriceType(\Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC)->save(); - $this->objectManager->get(\Magento\Framework\Registry::class)->unregister('product'); - $this->objectManager->get(\Magento\Framework\Registry::class)->register('product', $this->product); - - $this->block = $this->objectManager->get( - \Magento\Framework\View\LayoutInterface::class - )->createBlock( - \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle::class - ); + $this->objectManager = Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->block = $this->layout->createBlock(Bundle::class); + $this->json = $this->objectManager->get(SerializerInterface::class); + $this->registry = $this->objectManager->get(Registry::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister('product'); + + parent::tearDown(); } /** @@ -61,12 +74,12 @@ protected function setUp() * * @return void */ - public function testGetJsonConfig() + public function testGetJsonConfig(): void { - $option = $this->productRepository->get('simple'); - $option->setSpecialPrice(5) - ->save(); - $config = json_decode($this->block->getJsonConfig(), true); + $product = $this->updateProduct('bundle-product', ['price_type' => Price::PRICE_TYPE_DYNAMIC]); + $this->registerProduct($product); + $this->updateProduct('simple', ['special_price' => 5]); + $config = $this->json->unserialize($this->block->getJsonConfig()); $options = current($config['options']); $selection = current($options['selections']); $this->assertEquals(10, $selection['prices']['oldPrice']['amount']); @@ -75,10 +88,124 @@ public function testGetJsonConfig() } /** - * Tear Down + * @dataProvider isSalableForStockStatusProvider + * + * @param bool $isSalable + * @param string $expectedValue + * @return void */ - protected function tearDown() + public function testStockStatusView(bool $isSalable, string $expectedValue): void { - $this->objectManager->get(\Magento\Framework\Registry::class)->unregister('product'); + $product = $this->productRepository->get('bundle-product'); + $product->setAllItemsSalable($isSalable); + $this->block->setTemplate('Magento_Bundle::catalog/product/view/type/bundle.phtml'); + $result = $this->renderBlockHtml($product); + $this->assertEquals($expectedValue, trim(strip_tags($result))); + } + + /** + * @return array + */ + public function isSalableForStockStatusProvider(): array + { + return [ + 'is_salable' => [ + 'is_salable' => true, + 'expected_value' => 'In stock', + ], + 'is_not_salable' => [ + 'is_salable' => false, + 'expected_value' => 'Out of stock', + ], + ]; + } + + /** + * @dataProvider isSalableForCustomizeButtonProvider + * + * @param bool $isSalable + * @param string $expectedValue + * @return void + */ + public function testCustomizeButton(bool $isSalable, string $expectedValue): void + { + $product = $this->productRepository->get('bundle-product'); + $product->setSalable($isSalable); + $this->block->setTemplate('Magento_Bundle::catalog/product/view/customize.phtml'); + $result = $this->renderBlockHtml($product); + $this->assertEquals($expectedValue, trim(strip_tags($result))); + } + + /** + * @return array + */ + public function isSalableForCustomizeButtonProvider(): array + { + return [ + 'is_salable' => [ + 'is_salable' => true, + 'expected_value' => 'Customize and Add to Cart', + ], + 'is_not_salable' => [ + 'is_salable' => false, + 'expected_value' => '', + ], + ]; + } + + /** + * @magentoDataFixture Magento/Bundle/_files/empty_bundle_product.php + * + * @param bool $isSalable + * @param string $expectedValue + * @return void + */ + public function testCustomizeButtonProductWithoutOptions(): void + { + $product = $this->productRepository->get('bundle-product'); + $product->setSalable(true); + $this->block->setTemplate('Magento_Bundle::catalog/product/view/customize.phtml'); + $result = $this->renderBlockHtml($product); + $this->assertEmpty(trim(strip_tags($result))); + } + + /** + * Update product + * + * @param ProductInterface|string $productSku + * @param array $data + * @return ProductInterface + */ + private function updateProduct(string $productSku, array $data): ProductInterface + { + $product = $this->productRepository->get($productSku); + $product->addData($data); + + return $this->productRepository->save($product); + } + + /** + * Register product + * + * @param ProductInterface $product + * @return void + */ + private function registerProduct(ProductInterface $product): void + { + $this->registry->unregister('product'); + $this->registry->register('product', $product); + } + + /** + * Render block output + * + * @param ProductInterface $product + * @return string + */ + private function renderBlockHtml(ProductInterface $product): string + { + $this->registerProduct($product); + + return $this->block->toHtml(); } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/CheckboxOptionViewTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/CheckboxOptionViewTest.php new file mode 100644 index 0000000000000..cbe150b9fb3f5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/CheckboxOptionViewTest.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Block\Catalog\Product\View\Type; + +/** + * Class checks checkbox bundle options appearance + * + * @magentoAppArea frontend + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + */ +class CheckboxOptionViewTest extends AbstractBundleOptionsViewTest +{ + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_checkbox_options.php + * + * @return void + */ + public function testNotRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-checkbox-options', + 'Checkbox Options', + $expectedSelectionsNames + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_checkbox_required_options.php + * + * @return void + */ + public function testRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-checkbox-required-options', + 'Checkbox Options', + $expectedSelectionsNames, + true + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_checkbox_required_option.php + * + * @return void + */ + public function testShowSingle(): void + { + $this->processSingleSelectionView('bundle-product-checkbox-required-option', 'Checkbox Options'); + } + + /** + * @inheritdoc + */ + protected function getRequiredSelectXpath(): string + { + return "//input[@type='checkbox' and contains(@data-validate, 'validate-one-required-by-name')" + . "and contains(@class, 'bundle-option')]/../label//span[normalize-space(text()) = '1 x %s']"; + } + + /** + * @inheritdoc + */ + protected function getNotRequiredSelectXpath(): string + { + return "//input[@type='checkbox' and not(contains(@data-validate, 'validate-one-required-by-name'))" + . "and contains(@class, 'bundle-option')]/../label//span[normalize-space(text()) = '1 x %s']"; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/DropDownOptionViewTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/DropDownOptionViewTest.php new file mode 100644 index 0000000000000..128fbe56185f3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/DropDownOptionViewTest.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Block\Catalog\Product\View\Type; + +/** + * Class checks dropdown bundle options appearance + * + * @magentoAppArea frontend + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + */ +class DropDownOptionViewTest extends AbstractBundleOptionsViewTest +{ + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_dropdown_options.php + * + * @return void + */ + public function testNotRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-dropdown-options', + 'Dropdown Options', + $expectedSelectionsNames + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_dropdown_required_options.php + * + * @return void + */ + public function testRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-dropdown-required-options', + 'Dropdown Options', + $expectedSelectionsNames, + true + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/product.php + * + * @return void + */ + public function testShowSingle(): void + { + $this->processSingleSelectionView('bundle-product', 'Bundle Product Items'); + } + + /** + * @inheritdoc + */ + protected function getRequiredSelectXpath(): string + { + return "//select[contains(@id, 'bundle-option') and contains(@data-validate, 'required:true')]" + . "/option/span[normalize-space(text()) = '%s']"; + } + + /** + * @inheritdoc + */ + protected function getNotRequiredSelectXpath(): string + { + return "//select[contains(@id, 'bundle-option') and not(contains(@data-validate, 'required:true'))]" + . "/option/span[normalize-space(text()) = '%s']"; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/MultiselectOptionViewTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/MultiselectOptionViewTest.php new file mode 100644 index 0000000000000..234981f36fa94 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/MultiselectOptionViewTest.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Block\Catalog\Product\View\Type; + +/** + * Class checks multiselect bundle options appearance + * + * @magentoAppArea frontend + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + */ +class MultiselectOptionViewTest extends AbstractBundleOptionsViewTest +{ + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_multiselect_options.php + * + * @return void + */ + public function testNotRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-multiselect-options', + 'Multiselect Options', + $expectedSelectionsNames + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_multiselect_required_options.php + * + * @return void + */ + public function testRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-multiselect-required-options', + 'Multiselect Options', + $expectedSelectionsNames, + true + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_multiselect_required_option.php + * + * @return void + */ + public function testShowSingle(): void + { + $this->processSingleSelectionView('bundle-product-multiselect-required-option', 'Multiselect Options'); + } + + /** + * @inheridoc + */ + protected function getRequiredSelectXpath(): string + { + return "//select[contains(@id, 'bundle-option') and @multiple='multiple' " + . "and contains(@data-validate, 'required:true')]/option/span[normalize-space(text()) = '1 x %s']"; + } + + /** + * @inheridoc + */ + protected function getNotRequiredSelectXpath(): string + { + return "//select[contains(@id, 'bundle-option') and @multiple='multiple'" + . "and not(contains(@data-validate, 'required:true'))]/option/span[normalize-space(text()) = '1 x %s']"; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/RadioOptionViewTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/RadioOptionViewTest.php new file mode 100644 index 0000000000000..b58f5f7d4189e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/RadioOptionViewTest.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Block\Catalog\Product\View\Type; + +/** + * Class checks radio buttons bundle options appearance + * + * @magentoAppArea frontend + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + */ +class RadioOptionViewTest extends AbstractBundleOptionsViewTest +{ + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_radio_options.php + * + * @return void + */ + public function testNotRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView('bundle-product-radio-options', 'Radio Options', $expectedSelectionsNames); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_radio_required_options.php + * + * @return void + */ + public function testRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-radio-required-options', + 'Radio Options', + $expectedSelectionsNames, + true + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_radio_required_option.php + * + * @return void + */ + public function testShowSingle(): void + { + $this->processSingleSelectionView('bundle-product-radio-required-option', 'Radio Options'); + } + + /** + * @inheritdoc + */ + protected function getRequiredSelectXpath(): string + { + return "//input[@type='radio' and contains(@data-validate, 'validate-one-required-by-name')" + . "and contains(@class, 'bundle option')]/../label//span[normalize-space(text()) = '%s']"; + } + + /** + * @inheritdoc + */ + protected function getNotRequiredSelectXpath(): string + { + return "//input[@type='radio' and not(contains(@data-validate, 'validate-one-required-by-name'))" + . "and contains(@class, 'bundle option')]/../label//span[normalize-space(text()) = '%s']"; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options.php new file mode 100644 index 0000000000000..f9636890e61f6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle-product-checkbox-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Checkbox Options', + 'default_title' => 'Checkbox Options', + 'type' => 'checkbox', + 'required' => 0, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); + +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options_rollback.php new file mode 100644 index 0000000000000..3475737790c86 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-checkbox-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option.php new file mode 100644 index 0000000000000..453b531f75b2d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle-product-checkbox-required-option') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Checkbox Options', + 'default_title' => 'Checkbox Options', + 'type' => 'checkbox', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option_rollback.php new file mode 100644 index 0000000000000..f75241fb8b680 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option_rollback.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-checkbox-required-option', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options.php new file mode 100644 index 0000000000000..9b84d1236c5c9 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle-product-checkbox-required-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Checkbox Options', + 'default_title' => 'Checkbox Options', + 'type' => 'checkbox', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options_rollback.php new file mode 100644 index 0000000000000..f601d1d6793e6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-checkbox-required-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options.php new file mode 100644 index 0000000000000..06f6473802ee2 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle-product-dropdown-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Dropdown Options', + 'default_title' => 'Dropdown Options', + 'type' => 'select', + 'required' => 0, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options_rollback.php new file mode 100644 index 0000000000000..857e44d0298cb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-dropdown-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options.php new file mode 100644 index 0000000000000..1789f472f968d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle-product-dropdown-required-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Dropdown Options', + 'default_title' => 'Dropdown Options', + 'type' => 'select', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options_rollback.php new file mode 100644 index 0000000000000..ad4464153dbf1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-dropdown-required-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options.php new file mode 100644 index 0000000000000..a5667b89f8bf4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle-product-multiselect-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Multiselect Options', + 'default_title' => 'Multiselect Options', + 'type' => 'multi', + 'required' => 0, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options_rollback.php new file mode 100644 index 0000000000000..c02f218131b20 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-multiselect-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option.php new file mode 100644 index 0000000000000..7789045f6f7ef --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle-product-multiselect-required-option') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Multiselect Options', + 'default_title' => 'Multiselect Options', + 'type' => 'multi', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option_rollback.php new file mode 100644 index 0000000000000..8e16ecb5f3890 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option_rollback.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-multiselect-required-option', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options.php new file mode 100644 index 0000000000000..65bb49f3b6122 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle-product-multiselect-required-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Multiselect Options', + 'default_title' => 'Multiselect Options', + 'type' => 'multi', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options_rollback.php new file mode 100644 index 0000000000000..bf78eece56938 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-multiselect-required-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options.php new file mode 100644 index 0000000000000..def31b48b2172 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle-product-radio-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Radio Options', + 'default_title' => 'Radio Options', + 'type' => 'radio', + 'required' => 0, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options_rollback.php new file mode 100644 index 0000000000000..5630b2f88ba4d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-radio-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option.php new file mode 100644 index 0000000000000..c659387e09dcc --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle-product-radio-required-option') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Radio Options', + 'default_title' => 'Radio Options', + 'type' => 'radio', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option_rollback.php new file mode 100644 index 0000000000000..9a44ccbca6110 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option_rollback.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-radio-required-option', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options.php new file mode 100644 index 0000000000000..ec28bf556b69c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle-product-radio-required-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Radio Options', + 'default_title' => 'Radio Options', + 'type' => 'radio', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + 'option_id' => 1, + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options_rollback.php new file mode 100644 index 0000000000000..8536a76979430 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-radio-required-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); From 997a0de132e38cc4bf4e0d94a9f65dbbc5b30bc5 Mon Sep 17 00:00:00 2001 From: Adarsh Manickam <adarsh.apple@icloud.com> Date: Mon, 10 Feb 2020 17:03:30 +0530 Subject: [PATCH 152/176] Deprecated associated integration test class --- .../Sales/Model/Order/Email/Sender/ShipmentSenderTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Email/Sender/ShipmentSenderTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Email/Sender/ShipmentSenderTest.php index 724865176188a..83bc7e10647b4 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Email/Sender/ShipmentSenderTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Email/Sender/ShipmentSenderTest.php @@ -10,6 +10,9 @@ /** * @magentoAppArea frontend + * + * @deprecated since ShipmentSender is deprecated + * @see \Magento\Sales\Model\Order\Email\Sender\ShipmentSender */ class ShipmentSenderTest extends \PHPUnit\Framework\TestCase { From c5cbcfe14a9b3019ae3f4470e857176ddbaa54f0 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Mon, 10 Feb 2020 14:57:03 +0200 Subject: [PATCH 153/176] MC-24466: Unable to use API to save quote item when backorder is set to "Allowed and Notify Customer" --- .../Model/Quote/Item/CartItemPersister.php | 16 ++-- .../Quote/Api/GuestCartItemRepositoryTest.php | 73 ++++++++++++++++++- 2 files changed, 83 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php b/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php index 9b5f5c9a126df..86dcd0e4bfc07 100644 --- a/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php +++ b/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php @@ -6,14 +6,17 @@ namespace Magento\Quote\Model\Quote\Item; -use Magento\Quote\Api\Data\CartInterface; -use Magento\Quote\Api\Data\CartItemInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\InputException; -use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Exception\LocalizedException; -use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Quote\Api\Data\CartInterface; +use Magento\Quote\Api\Data\CartItemInterface; +/** + * Cart item save handler + */ class CartItemPersister { /** @@ -39,6 +42,8 @@ public function __construct( } /** + * Save cart item into cart + * * @param CartInterface $quote * @param CartItemInterface $item * @return CartItemInterface @@ -73,12 +78,13 @@ public function save(CartInterface $quote, CartItemInterface $item) $item = $quote->updateItem($itemId, $buyRequestData); } else { if ($item->getQty() !== $currentItem->getQty()) { + $currentItem->clearMessage(); $currentItem->setQty($qty); /** * Qty validation errors are stored as items message * @see \Magento\CatalogInventory\Model\Quote\Item\QuantityValidator::validate */ - if (!empty($currentItem->getMessage())) { + if (!empty($currentItem->getMessage()) && $currentItem->getHasError()) { throw new LocalizedException(__($currentItem->getMessage())); } } diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartItemRepositoryTest.php index 00c8bb85d9be7..e03a54f9463d7 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartItemRepositoryTest.php @@ -6,6 +6,8 @@ */ namespace Magento\Quote\Api; +use Magento\CatalogInventory\Api\StockRegistryInterface; +use Magento\CatalogInventory\Model\Stock; use Magento\TestFramework\TestCase\WebapiAbstract; class GuestCartItemRepositoryTest extends WebapiAbstract @@ -167,9 +169,13 @@ public function testRemoveItem() /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php + * @param array $stockData + * @param string|null $errorMessage + * @dataProvider updateItemDataProvider */ - public function testUpdateItem() + public function testUpdateItem(array $stockData, string $errorMessage = null) { + $this->updateStockData('simple_one', $stockData); /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); $quote->load('test_order_item_with_items', 'reserved_order_id'); @@ -215,6 +221,9 @@ public function testUpdateItem() ], ]; } + if ($errorMessage) { + $this->expectExceptionMessage($errorMessage); + } $this->_webApiCall($serviceInfo, $requestData); $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); $quote->load('test_order_item_with_items', 'reserved_order_id'); @@ -223,4 +232,66 @@ public function testUpdateItem() $this->assertEquals(5, $item->getQty()); $this->assertEquals($itemId, $item->getItemId()); } + + /** + * @return array + */ + public function updateItemDataProvider(): array + { + return [ + [ + [] + ], + [ + [ + 'qty' => 0, + 'is_in_stock' => 1, + 'use_config_manage_stock' => 0, + 'manage_stock' => 1, + 'use_config_backorders' => 0, + 'backorders' => Stock::BACKORDERS_YES_NOTIFY, + ] + ], + [ + [ + 'qty' => 0, + 'is_in_stock' => 1, + 'use_config_manage_stock' => 0, + 'manage_stock' => 1, + 'use_config_backorders' => 0, + 'backorders' => Stock::BACKORDERS_NO, + ], + 'This product is out of stock.' + ], + [ + [ + 'qty' => 2, + 'is_in_stock' => 1, + 'use_config_manage_stock' => 0, + 'manage_stock' => 1, + 'use_config_backorders' => 0, + 'backorders' => Stock::BACKORDERS_NO, + ], + 'The requested qty is not available' + ] + ]; + } + + /** + * Update product stock + * + * @param string $sku + * @param array $stockData + * @return void + */ + private function updateStockData(string $sku, array $stockData): void + { + if ($stockData) { + /** @var $stockRegistry StockRegistryInterface */ + $stockRegistry = $this->objectManager->create(StockRegistryInterface::class); + $stockItem = $stockRegistry->getStockItemBySku($sku); + $stockItem->addData($stockData); + $stockRegistry->updateStockItemBySku($sku, $stockItem); + } + } } From 313e6b2c4caa8f07a72eba843925489b2b33e366 Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Mon, 10 Feb 2020 15:25:28 +0200 Subject: [PATCH 154/176] MC-31083: [FT] [MFTF] Fix test AdminCreateImageSwatchTest - delete created swatch attribute in after --- .../AdminDeleteProductAttributeByLabelActionGroup.xml | 2 +- .../Test/Mftf/Test/AdminCreateImageSwatchTest.xml | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml index 21cc90ba4b4e8..7b453735994d7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml @@ -13,7 +13,7 @@ <description>Goes to the Admin Product Attributes grid page. Filters the grid for the provided Product Attribute (Label). Deletes the Product Attribute from the grid. Validates that the Success Message is present.</description> </annotations> <arguments> - <argument name="productAttributeLabel" type="string" defaultValue="ProductAttributeFrontendLabel.label"/> + <argument name="productAttributeLabel" type="string" defaultValue="{{ProductAttributeFrontendLabel.label}}"/> </arguments> <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid"/> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml index 372df5bd3acee..d2352b9efa134 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml @@ -27,9 +27,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct"> <argument name="sku" value="{{BaseConfigurableProduct.sku}}"/> </actionGroup> - <actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteProductAttribute"> - <argument name="productAttributeLabel" value="{{ProductAttributeFrontendLabel.label}}"/> - </actionGroup> + <actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteProductAttribute"/> <actionGroup ref="NavigateToAndResetProductAttributeGridToDefaultViewActionGroup" stepKey="resetProductAttributeFilters"/> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </after> @@ -107,7 +105,7 @@ <actionGroup ref="FillMainProductFormActionGroup" stepKey="fillProductForm"> <argument name="product" value="BaseConfigurableProduct"/> </actionGroup> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory"/> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$createCategory.name$]" stepKey="fillCategory"/> <!-- Create configurations based off the Image Swatch we created earlier --> <click selector="{{AdminProductFormConfigurationsSection.createConfigurations}}" stepKey="clickCreateConfigurations"/> @@ -147,7 +145,7 @@ </assertContains> <!-- Go to the product listing page and see text swatch options --> - <amOnPage url="$$createCategory.custom_attributes[url_key]$$.html" stepKey="goToCategoryPageStorefront"/> + <amOnPage url="$createCategory.custom_attributes[url_key]$.html" stepKey="goToCategoryPageStorefront"/> <waitForPageLoad stepKey="waitForProductListingPage"/> <!-- Verify the storefront --> From 15492aa2be888f248946680f548a9a422f34db3a Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 10 Feb 2020 16:44:48 +0200 Subject: [PATCH 155/176] MC-31308: [2.4] Test AdminSaveAndCloseCmsBlockTest flaky on Jenkins --- .../Test/Mftf/ActionGroup/LoginActionGroup.xml | 3 ++- ...ndCloseCMSBlockWithSplitButtonActionGroup.xml | 3 ++- .../VerifyCmsBlockSaveSplitButtonActionGroup.xml | 1 + .../Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml | 16 ++++++++++------ 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginActionGroup.xml index 7068478bb4790..8f61a0a06dd5e 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginActionGroup.xml @@ -10,7 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="LoginActionGroup"> <annotations> - <description>Login to Backend Admin using ENV Admin credentials. PLEASE NOTE: This Action Group does NOT validate that you are Logged In.</description> + <description>DEPRECATED. Please use LoginAsAdmin instead. + Login to Backend Admin using ENV Admin credentials. PLEASE NOTE: This Action Group does NOT validate that you are Logged In.</description> </annotations> <amOnPage url="{{_ENV.MAGENTO_BACKEND_NAME}}" stepKey="navigateToAdmin"/> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndCloseCMSBlockWithSplitButtonActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndCloseCMSBlockWithSplitButtonActionGroup.xml index 95ce3c499b6b8..44e29f7e2fe55 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndCloseCMSBlockWithSplitButtonActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndCloseCMSBlockWithSplitButtonActionGroup.xml @@ -17,6 +17,7 @@ <click selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitButton"/> <click selector="{{BlockNewPagePageActionsSection.saveAndClose}}" stepKey="clickSaveBlock"/> <waitForPageLoad stepKey="waitForPageLoadAfterClickingSave"/> - <see userInput="You saved the block." stepKey="assertSaveBlockSuccessMessage"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessageAppear"/> + <see userInput="You saved the block." selector="{{AdminMessagesSection.success}}" stepKey="assertSaveBlockSuccessMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml index fee2f984c42d2..bc30098cb43c7 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml @@ -17,6 +17,7 @@ <waitForPageLoad stepKey="waitForPageLoad1"/> <!--Verify Save&Duplicate button and Save&Close button--> <click selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn1" /> + <waitForElementVisible selector="{{BlockNewPagePageActionsSection.saveAndDuplicate}}" stepKey="waitForButtonMenuOpened"/> <see selector="{{BlockNewPagePageActionsSection.saveAndDuplicate}}" userInput="Save & Duplicate" stepKey="seeSaveAndDuplicate"/> <see selector="{{BlockNewPagePageActionsSection.saveAndClose}}" userInput="Save & Close" stepKey="seeSaveAndClose"/> </actionGroup> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml index 8c89c47ab5077..23f602d7b1005 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml @@ -16,21 +16,25 @@ <description value="Admin should be able to create a CMS block using save and close"/> <severity value="CRITICAL"/> <group value="Cms"/> + <group value="WYSIWYGDisabled"/> </annotations> + <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> - <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> </before> + <after> <actionGroup ref="deleteBlock" stepKey="deleteCreatedBlock"> <argument name="Block" value="_defaultBlock"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="resetGridFilters"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </after> + <!-- Navigate to create cms block page and verify save split button --> - <actionGroup ref="VerifyCmsBlockSaveSplitButtonActionGroup" stepKey="verifyCmsBlockSaveSplitButton" /> + <actionGroup ref="VerifyCmsBlockSaveSplitButtonActionGroup" stepKey="assertCmsBlockSaveSplitButton"/> <!--Create new CMS Block page--> - <actionGroup ref="FillOutBlockContent" stepKey="FillOutBlockContent"/> + <actionGroup ref="FillOutBlockContent" stepKey="fillOutBlockContent"/> <actionGroup ref="SaveAndCloseCMSBlockWithSplitButtonActionGroup" stepKey="saveCmsBlockContent" /> </test> -</tests> \ No newline at end of file +</tests> From fda86a8c5e8472335078a77fc042a38dc46e5d2f Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 10 Feb 2020 17:33:27 +0200 Subject: [PATCH 156/176] MC-30720: [MFTF] [2.4] Fix flaky test AdminMoveAnchoredCategoryTest (MAGETWO-76273) --- .../Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml index 7261df8765dc5..f01becd2034d8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml @@ -55,7 +55,7 @@ <argument name="parentCategory" value="$simpleSubCategoryTwo.name$"/> </actionGroup> <!--Verify that navigation menu categories level is correct--> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="openHomePageFirst"/> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage1"/> <waitForPageLoad stepKey="waitForPageToLoadAfterHomePageOpened1"/> <seeElement selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryTwo.name$)}}" stepKey="verifyThatTopCategoryIsSubCategoryTwo"/> <moveMouseOver selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryTwo.name$)}}" stepKey="mouseOverSubCategoryTwo"/> @@ -97,7 +97,7 @@ <argument name="parentCategory" value="Default Category"/> </actionGroup> <!--Verify that navigation menu categories level is correct--> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="openHomePageSecond"/> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage2"/> <waitForPageLoad stepKey="waitForPageToLoadAfterHomePageOpened2"/> <seeElement selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryOne.name$)}}" stepKey="verifyThatSubCategoryOneIsTopCategory"/> <seeElement selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryTwo.name$)}}" stepKey="verifyThatSubCategoryTwoIsTopCategory"/> From bf21c4bea3cbd600ee1333186bf43b3065847681 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Tue, 11 Feb 2020 01:56:16 +0530 Subject: [PATCH 157/176] covered untit & updated loadcssasync format --- .../Controller/Result/AsyncCssPlugin.php | 4 +- .../Controller/Result/AsyncCssPluginTest.php | 143 ++++++++++++++++++ 2 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php diff --git a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php index f0c343c366abc..9dbb92d51067b 100644 --- a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php @@ -16,7 +16,7 @@ */ class AsyncCssPlugin { - private const XML_PATH_USE_CSS_CRITICAL_PATH = 'dev/css/use_css_critical_path'; + const XML_PATH_USE_CSS_CRITICAL_PATH = 'dev/css/use_css_critical_path'; /** * @var ScopeConfigInterface @@ -60,7 +60,7 @@ function ($matches) use (&$cssMatches) { $loadCssAsync = sprintf( '<link rel="preload" as="style" media="%s"' . ' onload="this.onload=null;this.rel=\'stylesheet\'"' . - ' href="%s">', + ' href="%s" />', $media, $href ); diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php new file mode 100644 index 0000000000000..98321976767e2 --- /dev/null +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php @@ -0,0 +1,143 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Theme\Test\Unit\Controller\Result; + +use Magento\Theme\Controller\Result\AsyncCssPlugin; +use Magento\Framework\App\Response\Http; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\MockObject\MockObject; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +/** + * Unit test for Magento\Theme\Test\Unit\Controller\Result\AsyncCssPlugin. + */ +class AsyncCssPluginTest extends TestCase +{ + /** + * @var AsyncCssPlugin + */ + private $plugin; + + /** + * @var ScopeConfigInterface|MockObject + */ + private $scopeConfigMock; + + /** + * @var Http|MockObject + */ + private $httpMock; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class) + ->setMethods(['isSetFlag']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->httpMock = $this->createMock(Http::class); + + $objectManager = new ObjectManagerHelper($this); + $this->plugin = $objectManager->getObject( + AsyncCssPlugin::class, + [ + 'scopeConfig' => $this->scopeConfigMock + ] + ); + } + + /** + * Data Provider for before send response + * + * @return void + */ + public function sendResponseDataProvider() + { + return [ + [ + "content" => "<body><h1>Test Title</h1>" . + "<link rel=\"stylesheet\" href=\"css/critical.css\" />" . + "<p>Test Content</p></body>", + "flag" => true, + "result" => "<body><h1>Test Title</h1>" . + "<link rel=\"preload\" as=\"style\" media=\"all\"" . + " onload=\"this.onload=null;this.rel='stylesheet'\" href=\"css/critical.css\" />" . + "<p>Test Content</p>" . + "<link rel=\"stylesheet\" href=\"css/critical.css\" />" . + "\n</body>" + ], + [ + "content" => "<body><p>Test Content</p></body>", + "flag" => false, + "result" => "<body><p>Test Content</p></body>" + ], + [ + "content" => "<body><p>Test Content</p></body>", + "flag" => true, + "result" => "<body><p>Test Content</p></body>" + ] + ]; + } + + /** + * Test beforeSendResponse + * + * @param string $content + * @param bool $isSetFlag + * @param string $result + * @return void + * @dataProvider sendResponseDataProvider + */ + public function testBeforeSendResponse($content, $isSetFlag, $result): void + { + $this->httpMock->expects($this->once()) + ->method('getContent') + ->willReturn($content); + + $this->scopeConfigMock->expects($this->once()) + ->method('isSetFlag') + ->with( + AsyncCssPlugin::XML_PATH_USE_CSS_CRITICAL_PATH, + ScopeInterface::SCOPE_STORE + ) + ->willReturn($isSetFlag); + + $this->httpMock->expects($this->any()) + ->method('setContent') + ->with($result); + + $this->plugin->beforeSendResponse($this->httpMock); + } + + /** + * Test BeforeSendResponse if content is not a string + * + * @return void + */ + public function testIfGetContentIsNotAString(): void + { + $this->httpMock->expects($this->once()) + ->method('getContent') + ->willReturn([]); + + $this->scopeConfigMock->expects($this->any()) + ->method('isSetFlag') + ->with( + AsyncCssPlugin::XML_PATH_USE_CSS_CRITICAL_PATH, + ScopeInterface::SCOPE_STORE + ) + ->willReturn(false); + + $this->plugin->beforeSendResponse($this->httpMock); + } +} From 2881e4886fee787e5ecdf73edef4a197321bea43 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Tue, 11 Feb 2020 02:02:20 +0530 Subject: [PATCH 158/176] PHPdoc updated --- .../Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php index 98321976767e2..6f9cd56c3c5c9 100644 --- a/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php @@ -59,9 +59,9 @@ protected function setUp(): void /** * Data Provider for before send response * - * @return void + * @return array */ - public function sendResponseDataProvider() + public function sendResponseDataProvider(): array { return [ [ From 1e50859a6c2f52984a9a2812fb6c93aa6b0a0f34 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Tue, 11 Feb 2020 10:02:22 +0530 Subject: [PATCH 159/176] Stub constant updated --- app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php | 2 +- .../Test/Unit/Controller/Result/AsyncCssPluginTest.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php index 9dbb92d51067b..70ea478004b9d 100644 --- a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php @@ -16,7 +16,7 @@ */ class AsyncCssPlugin { - const XML_PATH_USE_CSS_CRITICAL_PATH = 'dev/css/use_css_critical_path'; + private const XML_PATH_USE_CSS_CRITICAL_PATH = 'dev/css/use_css_critical_path'; /** * @var ScopeConfigInterface diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php index 6f9cd56c3c5c9..b1303e991a680 100644 --- a/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php @@ -20,6 +20,8 @@ */ class AsyncCssPluginTest extends TestCase { + const STUB_XML_PATH_USE_CSS_CRITICAL_PATH = 'dev/css/use_css_critical_path'; + /** * @var AsyncCssPlugin */ @@ -107,7 +109,7 @@ public function testBeforeSendResponse($content, $isSetFlag, $result): void $this->scopeConfigMock->expects($this->once()) ->method('isSetFlag') ->with( - AsyncCssPlugin::XML_PATH_USE_CSS_CRITICAL_PATH, + self::STUB_XML_PATH_USE_CSS_CRITICAL_PATH, ScopeInterface::SCOPE_STORE ) ->willReturn($isSetFlag); @@ -133,7 +135,7 @@ public function testIfGetContentIsNotAString(): void $this->scopeConfigMock->expects($this->any()) ->method('isSetFlag') ->with( - AsyncCssPlugin::XML_PATH_USE_CSS_CRITICAL_PATH, + self::STUB_XML_PATH_USE_CSS_CRITICAL_PATH, ScopeInterface::SCOPE_STORE ) ->willReturn(false); From e61a52feee7fe7401dc01ae48deda04b4024c078 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Tue, 11 Feb 2020 11:41:44 +0200 Subject: [PATCH 160/176] MC-24236: [MFTF Test] Unskip MFTF test MC-13607 "Verify that Catalog Price Rule and Customer Group Membership are persisted under long-term cookie" --- ...ertStorefrontProductPriceInCategoryPageActionGroup.xml | 1 - ...efrontProductSpecialPriceInCategoryPageActionGroup.xml | 2 +- .../Mftf/Section/StorefrontCategoryProductSection.xml | 2 +- ...GroupMembershipArePersistedUnderLongTermCookieTest.xml | 8 +++----- .../AssertDefaultWelcomeMessageActionGroup.xml | 4 ++-- 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml index e6eb475153f1f..87f6e6e705263 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml @@ -18,7 +18,6 @@ <argument name="productPrice" type="string" defaultValue="{{productWithHTMLEntityOne.price}}"/> </arguments> - <!-- Go to storefront category page, assert product visibility --> <amOnPage url="{{StorefrontCategoryPage.url(categoryUrl)}}" stepKey="navigateToCategoryPage"/> <waitForPageLoad stepKey="waitForProductPageLoad"/> <see userInput="{{productPrice}}" selector="{{StorefrontCategoryProductSection.ProductPriceByName(productName)}}" stepKey="assertProductPrice"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml index 17c9e43e15fa7..c449089dab264 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertStorefrontProductSpecialPriceInCategoryPageActionGroup" extends="AssertStorefrontProductPriceInCategoryPageActionGroup"> <annotations> - <description>Goes to Storefront Category page for the provided Category. Validates that the Product price is present and correct.</description> + <description>Goes to Storefront Category page for the provided Category. Validates that the Product price and special price is correct.</description> </annotations> <arguments> <argument name="productSpecialPrice" type="string" defaultValue="{{updateVirtualProductSpecialPrice.special_price}}"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml index 12fd350612d7d..61e6a345b9ba5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml @@ -21,7 +21,7 @@ <element name="ProductTitleByName" type="button" selector="//main//li//a[contains(text(), '{{var1}}')]" parameterized="true"/> <element name="ProductPriceByName" type="text" selector="//main//li[.//a[contains(text(), '{{var1}}')]]//span[@class='price']" parameterized="true"/> - <element name="ProductCatalogRuleSpecialPriceTitleByName" type="text" selector="//main//li[.//a[contains(text(), '{{productName}}')]]//span[@class='special-price']/span" parameterized="true"/> + <element name="ProductCatalogRuleSpecialPriceTitleByName" type="text" selector="//div[contains(@class, 'product-item-info')][.//a[contains(text(), '{{productName}}')]]//span[@class='special-price']/span" parameterized="true"/> <element name="ProductCatalogRulePriceTitleByName" type="text" selector="//div[descendant::*[contains(text(), '{{var1}}')]]//*[contains(@class, 'price-label')]" parameterized="true"/> <element name="ProductImageByName" type="text" selector="//main//li[.//a[contains(text(), '{{var1}}')]]//img[@class='product-image-photo']" parameterized="true"/> <element name="ProductImageBySrc" type="text" selector=".products-grid img[src*='{{pattern}}']" parameterized="true"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml index 65a0e30e17b37..102054c315f4c 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml @@ -25,9 +25,7 @@ <createData entity="productWithHTMLEntityOne" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <createData entity="Simple_US_Customer" stepKey="createCustomer"> - <field key="group_id">1</field> - </createData> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> <!--Delete all Catalog Price Rule if exist--> <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> @@ -46,7 +44,7 @@ <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="clickSaveAndApplyRule"/> <!-- Perform reindex --> - <magentoCLI command="indexer:reindex" arguments="catalogrule_rule" stepKey="reindex"/> + <magentoCLI command="indexer:reindex" arguments="catalogrule_rule" stepKey="reindex"/> </before> <after> <createData entity="PersistentConfigDefault" stepKey="setDefaultPersistentState"/> @@ -94,7 +92,7 @@ <!--Click the *Not you?* link and check the price for Simple Product--> <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickNotYouLink"/> - <actionGroup ref="AssertDefaultWelcomeMessageActionGroup" stepKey="seeWelcomeMessageForJohnDoeCustomerAfterLogout"/> + <actionGroup ref="AssertStorefrontDefaultWelcomeMessageActionGroup" stepKey="seeWelcomeMessageForJohnDoeCustomerAfterLogout"/> <actionGroup ref="AssertStorefrontProductPriceInCategoryPageActionGroup" stepKey="assertProductPriceInCategoryPageAfterLogout"> <argument name="categoryUrl" value="$createCategory.custom_attributes[url_key]$"/> <argument name="productName" value="$createProduct.name$"/> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml index 05414fb8ebe20..eb66cafe43dd3 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml @@ -8,12 +8,12 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertDefaultWelcomeMessageActionGroup"> + <actionGroup name="AssertStorefrontDefaultWelcomeMessageActionGroup"> <annotations> <description>Validates that the Welcome message is present and correct and not you link absent.</description> </annotations> - <waitForPageLoad stepKey="waitForPageLoad"/> + <waitForElementVisible selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="waitDefaultMessage"/> <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="verifyDefaultMessage"/> <dontSeeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkAbsenceLinkNotYou"/> </actionGroup> From a7a25ef17b0c636b7e68b3e24de2dc1533a53aac Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 11 Feb 2020 12:49:45 +0200 Subject: [PATCH 161/176] MC-31369: [2.4] Test CreateCompanyWithOptionalRegionTest fail on Jenkins (MAGETWO-94110) --- .../Data/GeneralStateOptionsConfigData.xml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 app/code/Magento/Directory/Test/Mftf/Data/GeneralStateOptionsConfigData.xml diff --git a/app/code/Magento/Directory/Test/Mftf/Data/GeneralStateOptionsConfigData.xml b/app/code/Magento/Directory/Test/Mftf/Data/GeneralStateOptionsConfigData.xml new file mode 100644 index 0000000000000..8b72e3e93efb9 --- /dev/null +++ b/app/code/Magento/Directory/Test/Mftf/Data/GeneralStateOptionsConfigData.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="AllowToChooseStateIfItIsOptionalForCountryEnabled"> + <data key="path">general/region/display_all</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="AllowToChooseStateIfItIsOptionalForCountryDisabled"> + <data key="path">general/region/display_all</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> +</entities> From 5f02e44917e639406c531cef6d8b907ac43a83fd Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Tue, 11 Feb 2020 12:53:57 +0200 Subject: [PATCH 162/176] MC-31157: Error on Place order with Braintree and 3d-secure. Address validation --- .../frontend/web/js/view/payment/3d-secure.js | 21 ++++++++++++++++++- .../view/payment/method-renderer/cc-form.js | 2 +- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js index 43aec27508ce9..b66725c063414 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js @@ -117,7 +117,7 @@ define([ options.bin = context.paymentPayload.details.bin; } - if (shippingAddress) { + if (shippingAddress && this.isValidShippingAddress(shippingAddress)) { options.additionalInformation = { shippingGivenName: shippingAddress.firstname, shippingSurname: shippingAddress.lastname, @@ -206,6 +206,25 @@ define([ } return false; + }, + + /** + * Validate shipping address + * + * @param {Object} shippingAddress + * @return {Boolean} + */ + isValidShippingAddress: function (shippingAddress) { + var isValid = false; + + // check that required fields are not empty + if (shippingAddress.firstname && shippingAddress.lastname && shippingAddress.telephone && + shippingAddress.street && shippingAddress.city && shippingAddress.regionCode && + shippingAddress.postcode && shippingAddress.countryId) { + isValid = true; + } + + return isValid; } }; }); diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js index afe22475981ec..21809f186d252 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js @@ -91,7 +91,7 @@ define( }) .then(function (hostedFieldsInstance) { self.hostedFieldsInstance = hostedFieldsInstance; - self.isPlaceOrderActionAllowed(true); + self.isPlaceOrderActionAllowed(false); self.initFormValidationEvents(hostedFieldsInstance); return self.hostedFieldsInstance; From 343ea61890663fe537d34296750fb6d9bfbd64f5 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Tue, 11 Feb 2020 14:24:52 +0200 Subject: [PATCH 163/176] MC-24236: [MFTF Test] Unskip MFTF test MC-13607 "Verify that Catalog Price Rule and Customer Group Membership are persisted under long-term cookie" --- ...rtStorefrontProductSpecialPriceInCategoryPageActionGroup.xml | 2 +- ...xml => AssertStorefrontDefaultWelcomeMessageActionGroup.xml} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename app/code/Magento/Customer/Test/Mftf/ActionGroup/{AssertDefaultWelcomeMessageActionGroup.xml => AssertStorefrontDefaultWelcomeMessageActionGroup.xml} (100%) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml index c449089dab264..b2a7d5f96ec94 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertStorefrontProductSpecialPriceInCategoryPageActionGroup" extends="AssertStorefrontProductPriceInCategoryPageActionGroup"> <annotations> - <description>Goes to Storefront Category page for the provided Category. Validates that the Product price and special price is correct.</description> + <description>Goes to Storefront Category page for the provided Category. Validates that the Product price and special price are correct.</description> </annotations> <arguments> <argument name="productSpecialPrice" type="string" defaultValue="{{updateVirtualProductSpecialPrice.special_price}}"/> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStorefrontDefaultWelcomeMessageActionGroup.xml similarity index 100% rename from app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml rename to app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStorefrontDefaultWelcomeMessageActionGroup.xml From 5d0dfb541ac9739e14de7047ad318b89ce9aea17 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Tue, 11 Feb 2020 15:26:36 +0200 Subject: [PATCH 164/176] Unit Test for \Magento\Directory\Block\Adminhtml\Frontend\Currency\Base --- .../Adminhtml/Frontend/Currency/BaseTest.php | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 app/code/Magento/Directory/Test/Unit/Block/Adminhtml/Frontend/Currency/BaseTest.php diff --git a/app/code/Magento/Directory/Test/Unit/Block/Adminhtml/Frontend/Currency/BaseTest.php b/app/code/Magento/Directory/Test/Unit/Block/Adminhtml/Frontend/Currency/BaseTest.php new file mode 100644 index 0000000000000..9d38a2c72f3ac --- /dev/null +++ b/app/code/Magento/Directory/Test/Unit/Block/Adminhtml/Frontend/Currency/BaseTest.php @@ -0,0 +1,110 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Directory\Test\Unit\Block\Adminhtml\Frontend\Currency; + +use Magento\Directory\Block\Adminhtml\Frontend\Currency\Base; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Data\Form\Element\AbstractElement; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Store\Model\Store; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for \Magento\Directory\Block\Adminhtml\Frontend\Currency\Base + */ +class BaseTest extends TestCase +{ + const STUB_WEBSITE_PARAM = 'website'; + + /** + * @var AbstractElement|MockObject + */ + private $elementMock; + + /** + * @var RequestInterface|MockObject + */ + private $requestMock; + + /** + * @var ScopeConfigInterface|MockObject + */ + private $scopeConfigMock; + + /** + * @var Base + */ + private $baseCurrency; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->elementMock = $this->createMock(AbstractElement::class); + $this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class); + $this->requestMock = $this->getMockBuilder(RequestInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getParam']) + ->getMockForAbstractClass(); + + $this->baseCurrency = (new ObjectManagerHelper($this))->getObject( + Base::class, + ['_request' => $this->requestMock, '_scopeConfig' => $this->scopeConfigMock] + ); + } + + /** + * Test case when no Website param provided + */ + public function testRenderWithoutWebsiteParam() + { + $this->requestMock->expects($this->once()) + ->method('getParam') + ->willReturn(''); + $this->scopeConfigMock->expects($this->never())->method('getValue'); + + $result = $this->baseCurrency->render(($this->elementMock)); + $this->assertFalse(empty($result), 'Result should not be empty.'); + } + + /** + * Test case when Website param is provided and Price Scope is set to Global + */ + public function testRenderWhenWebsiteParamSetAndPriceScopeGlobal() + { + $this->requestMock->expects($this->once()) + ->method('getParam') + ->willReturn(self::STUB_WEBSITE_PARAM); + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->willReturn(Store::PRICE_SCOPE_GLOBAL); + + $result = $this->baseCurrency->render(($this->elementMock)); + $this->assertEquals('', $result, 'Result should be an empty string.'); + } + + /** + * Test case when Website param is provided and Price Scope is not Global + */ + public function testRenderWhenWebsiteParamSetAndPriceScopeOther() + { + $this->requestMock->expects($this->once()) + ->method('getParam') + ->willReturn(self::STUB_WEBSITE_PARAM); + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->willReturn(Store::PRICE_SCOPE_WEBSITE); + + $result = $this->baseCurrency->render(($this->elementMock)); + $this->assertFalse(empty($result), 'Result should not be empty.'); + } +} From b4390ed4e68052b83f4551369a5ffca5e8f7be46 Mon Sep 17 00:00:00 2001 From: Arnob Saha <arnobsh@gmail.com> Date: Thu, 31 Oct 2019 13:57:20 -0500 Subject: [PATCH 165/176] MC-21501: Investigation of stock quantity calculation for Configurable Products - check $product is an instance of Product before processing --- .../Layer/Filter/_files/attribute_with_option_rollback.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/_files/attribute_with_option_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/_files/attribute_with_option_rollback.php index f3989248a8ed1..602af4d0e3c78 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/_files/attribute_with_option_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/_files/attribute_with_option_rollback.php @@ -32,7 +32,7 @@ \Magento\Catalog\Model\Product::class ); $product = $product->loadByAttribute('sku', 'simple_product_' . $option->getId()); - if ($product->getId()) { + if ($product instanceof \Magento\Catalog\Model\Product && $product->getId()) { $product->delete(); } } From 6220474bbc24e141690705134c9c66e27c94cba9 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Tue, 11 Feb 2020 22:21:31 +0530 Subject: [PATCH 166/176] [Theme] Covered Unit Test for \Magento\Theme\controller\Result\JsFooterPlugin --- .../Controller/Result/JsFooterPluginTest.php | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php new file mode 100644 index 0000000000000..a604aaf10aeb7 --- /dev/null +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php @@ -0,0 +1,145 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Theme\Test\Unit\Controller\Result; + +use Magento\Theme\Controller\Result\JsFooterPlugin; +use Magento\Framework\App\Response\Http; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\MockObject\MockObject; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +/** + * Unit test for Magento\Theme\Test\Unit\Controller\Result\JsFooterPlugin. + */ +class JsFooterPluginTest extends TestCase +{ + const STUB_XML_PATH_DEV_MOVE_JS_TO_BOTTOM = 'dev/js/move_script_to_bottom'; + + /** + * @var JsFooterPlugin + */ + private $plugin; + + /** + * @var ScopeConfigInterface|MockObject + */ + private $scopeConfigMock; + + /** + * @var Http|MockObject + */ + private $httpMock; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class) + ->setMethods(['isSetFlag']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->httpMock = $this->createMock(Http::class); + + $objectManager = new ObjectManagerHelper($this); + $this->plugin = $objectManager->getObject( + JsFooterPlugin::class, + [ + 'scopeConfig' => $this->scopeConfigMock + ] + ); + } + + /** + * Data Provider for beforeSendResponse() + * + * @return array + */ + public function sendResponseDataProvider(): array + { + return [ + [ + "content" => "<body><h1>Test Title</h1>" . + "<script text=\"text/javascript\">test</script>" . + "<script text=\"text/x-magento-template\">test</script>" . + "<p>Test Content</p></body>", + "flag" => true, + "result" => "<body><h1>Test Title</h1>" . + "<script text=\"text/x-magento-template\">test</script>" . + "<p>Test Content</p>" . + "<script text=\"text/javascript\">test</script>" . + "\n</body>" + ], + [ + "content" => "<body><p>Test Content</p></body>", + "flag" => false, + "result" => "<body><p>Test Content</p></body>" + ], + [ + "content" => "<body><p>Test Content</p></body>", + "flag" => true, + "result" => "<body><p>Test Content</p>\n</body>" + ] + ]; + } + + /** + * Test beforeSendResponse + * + * @param string $content + * @param bool $isSetFlag + * @param string $result + * @return void + * @dataProvider sendResponseDataProvider + */ + public function testBeforeSendResponse($content, $isSetFlag, $result): void + { + $this->httpMock->expects($this->once()) + ->method('getContent') + ->willReturn($content); + + $this->scopeConfigMock->expects($this->once()) + ->method('isSetFlag') + ->with( + self::STUB_XML_PATH_DEV_MOVE_JS_TO_BOTTOM, + ScopeInterface::SCOPE_STORE + ) + ->willReturn($isSetFlag); + + $this->httpMock->expects($this->any()) + ->method('setContent') + ->with($result); + + $this->plugin->beforeSendResponse($this->httpMock); + } + + /** + * Test BeforeSendResponse if content is not a string + * + * @return void + */ + public function testBeforeSendResponseIfGetContentIsNotAString(): void + { + $this->httpMock->expects($this->once()) + ->method('getContent') + ->willReturn([]); + + $this->scopeConfigMock->expects($this->never()) + ->method('isSetFlag') + ->with( + self::STUB_XML_PATH_DEV_MOVE_JS_TO_BOTTOM, + ScopeInterface::SCOPE_STORE + ) + ->willReturn(false); + + $this->plugin->beforeSendResponse($this->httpMock); + } +} From a2082260635fea744e8a9e9258e4b7f1ffcae06c Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Wed, 12 Feb 2020 01:11:03 +0530 Subject: [PATCH 167/176] Test case updated with if content NULL & fixed health check issue --- .../Controller/Result/JsFooterPluginTest.php | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php index a604aaf10aeb7..3d6bf010d4207 100644 --- a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php @@ -59,7 +59,7 @@ protected function setUp(): void } /** - * Data Provider for beforeSendResponse() + * Data Provider for testBeforeSendResponse() * * @return array */ @@ -68,14 +68,14 @@ public function sendResponseDataProvider(): array return [ [ "content" => "<body><h1>Test Title</h1>" . - "<script text=\"text/javascript\">test</script>" . - "<script text=\"text/x-magento-template\">test</script>" . + "<script type=\"text/x-magento-init\">test</script>" . + "<script type=\"text/x-magento-template\">test</script>" . "<p>Test Content</p></body>", "flag" => true, "result" => "<body><h1>Test Title</h1>" . - "<script text=\"text/x-magento-template\">test</script>" . + "<script type=\"text/x-magento-template\">test</script>" . "<p>Test Content</p>" . - "<script text=\"text/javascript\">test</script>" . + "<script type=\"text/x-magento-init\">test</script>" . "\n</body>" ], [ @@ -121,16 +121,35 @@ public function testBeforeSendResponse($content, $isSetFlag, $result): void $this->plugin->beforeSendResponse($this->httpMock); } + /** + * Data Provider for testBeforeSendResponseIfGetContentIsNotAString() + * + * @return array + */ + public function ifGetContentIsNotAStringDataProvider(): array + { + return [ + [ + 'content' => [] + ], + [ + 'content' => NULL + ] + ]; + } + /** * Test BeforeSendResponse if content is not a string * + * @param string $content * @return void + * @dataProvider ifGetContentIsNotAStringDataProvider */ - public function testBeforeSendResponseIfGetContentIsNotAString(): void + public function testBeforeSendResponseIfGetContentIsNotAString($content): void { $this->httpMock->expects($this->once()) ->method('getContent') - ->willReturn([]); + ->willReturn($content); $this->scopeConfigMock->expects($this->never()) ->method('isSetFlag') From a0ed3182c71af73fc7ad2168d7ee9631845b1611 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Tue, 11 Feb 2020 13:55:04 -0600 Subject: [PATCH 168/176] MQE-1987: Bump MFTF version and deliver Magento branches Updated with mainline + version bump to 2.6.1 --- composer.json | 2 +- composer.lock | 164 ++++++++++++++++++++++++++------------------------ 2 files changed, 87 insertions(+), 79 deletions(-) diff --git a/composer.json b/composer.json index 577987067dc76..1e38c3c13601d 100644 --- a/composer.json +++ b/composer.json @@ -88,7 +88,7 @@ "friendsofphp/php-cs-fixer": "~2.14.0", "lusitanian/oauth": "~0.8.10", "magento/magento-coding-standard": "*", - "magento/magento2-functional-testing-framework": "2.6.0", + "magento/magento2-functional-testing-framework": "2.6.1", "pdepend/pdepend": "2.5.2", "phpcompatibility/php-compatibility": "^9.3", "phpmd/phpmd": "@stable", diff --git a/composer.lock b/composer.lock index dd59126b96caa..be50d79e33eff 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "27452593216dfff37ed2a7f2aea0237c", + "content-hash": "fed60ae2b1869a71f2068e4f55a8695f", "packages": [ { "name": "braintree/braintree_php", @@ -1850,6 +1850,11 @@ "MIT" ], "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + }, { "name": "Marijn Huizendveld", "email": "marijn.huizendveld@gmail.com" @@ -1857,11 +1862,6 @@ { "name": "Thibaud Fabre", "email": "thibaud@aztech.io" - }, - { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" } ], "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", @@ -6675,67 +6675,6 @@ ], "time": "2019-10-30T14:39:59+00:00" }, - { - "name": "facebook/webdriver", - "version": "1.7.1", - "source": { - "type": "git", - "url": "https://github.com/facebook/php-webdriver.git", - "reference": "e43de70f3c7166169d0f14a374505392734160e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/e43de70f3c7166169d0f14a374505392734160e5", - "reference": "e43de70f3c7166169d0f14a374505392734160e5", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "ext-json": "*", - "ext-mbstring": "*", - "ext-zip": "*", - "php": "^5.6 || ~7.0", - "symfony/process": "^2.8 || ^3.1 || ^4.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.0", - "jakub-onderka/php-parallel-lint": "^0.9.2", - "php-coveralls/php-coveralls": "^2.0", - "php-mock/php-mock-phpunit": "^1.1", - "phpunit/phpunit": "^5.7", - "sebastian/environment": "^1.3.4 || ^2.0 || ^3.0", - "squizlabs/php_codesniffer": "^2.6", - "symfony/var-dumper": "^3.3 || ^4.0" - }, - "suggest": { - "ext-SimpleXML": "For Firefox profile creation" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-community": "1.5-dev" - } - }, - "autoload": { - "psr-4": { - "Facebook\\WebDriver\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "description": "A PHP client for Selenium WebDriver", - "homepage": "https://github.com/facebook/php-webdriver", - "keywords": [ - "facebook", - "php", - "selenium", - "webdriver" - ], - "abandoned": "php-webdriver/webdriver", - "time": "2019-06-13T08:02:18+00:00" - }, { "name": "flow/jsonpath", "version": "0.5.0", @@ -7442,16 +7381,16 @@ }, { "name": "magento/magento2-functional-testing-framework", - "version": "2.6.0", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/magento/magento2-functional-testing-framework.git", - "reference": "3609f4fa57c6e9a2ee7c3d3b7c0f02e9becd8262" + "reference": "f56c5563ae23be5abac779a97f6d75cdf505d0a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/3609f4fa57c6e9a2ee7c3d3b7c0f02e9becd8262", - "reference": "3609f4fa57c6e9a2ee7c3d3b7c0f02e9becd8262", + "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/f56c5563ae23be5abac779a97f6d75cdf505d0a2", + "reference": "f56c5563ae23be5abac779a97f6d75cdf505d0a2", "shasum": "" }, "require": { @@ -7470,9 +7409,13 @@ "monolog/monolog": "^1.0", "mustache/mustache": "~2.5", "php": "7.0.2||7.0.4||~7.0.6||~7.1.0||~7.2.0||~7.3.0", + "php-webdriver/webdriver": "^1.8.0", "symfony/process": "^2.8 || ^3.1 || ^4.0", "vlucas/phpdotenv": "^2.4" }, + "replace": { + "facebook/webdriver": "^1.7.1" + }, "require-dev": { "brainmaestro/composer-git-hooks": "^2.3.1", "codacy/coverage": "^1.4", @@ -7519,7 +7462,7 @@ "magento", "testing" ], - "time": "2020-02-05T15:53:02+00:00" + "time": "2020-02-11T19:46:39+00:00" }, { "name": "mikey179/vfsstream", @@ -7911,6 +7854,71 @@ ], "time": "2018-02-15T16:58:55+00:00" }, + { + "name": "php-webdriver/webdriver", + "version": "1.8.0", + "source": { + "type": "git", + "url": "https://github.com/php-webdriver/php-webdriver.git", + "reference": "3e33ee3b8a688d719c55acdd7c6788e3006e1d3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/3e33ee3b8a688d719c55acdd7c6788e3006e1d3e", + "reference": "3e33ee3b8a688d719c55acdd7c6788e3006e1d3e", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-zip": "*", + "php": "^5.6 || ~7.0", + "symfony/polyfill-mbstring": "^1.12", + "symfony/process": "^2.8 || ^3.1 || ^4.0 || ^5.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.0", + "jakub-onderka/php-parallel-lint": "^1.0", + "php-coveralls/php-coveralls": "^2.0", + "php-mock/php-mock-phpunit": "^1.1", + "phpunit/phpunit": "^5.7", + "sebastian/environment": "^1.3.4 || ^2.0 || ^3.0", + "sminnee/phpunit-mock-objects": "^3.4", + "squizlabs/php_codesniffer": "^3.5", + "symfony/var-dumper": "^3.3 || ^4.0 || ^5.0" + }, + "suggest": { + "ext-SimpleXML": "For Firefox profile creation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "files": [ + "lib/Exception/TimeoutException.php" + ], + "psr-4": { + "Facebook\\WebDriver\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP client for Selenium WebDriver. Previously facebook/webdriver.", + "homepage": "https://github.com/php-webdriver/php-webdriver", + "keywords": [ + "Chromedriver", + "geckodriver", + "php", + "selenium", + "webdriver" + ], + "time": "2020-02-10T15:04:25+00:00" + }, { "name": "phpcollection/phpcollection", "version": "0.5.0", @@ -8209,20 +8217,20 @@ "authors": [ { "name": "Manuel Pichler", - "role": "Project Founder", "email": "github@manuel-pichler.de", - "homepage": "https://github.com/manuelpichler" + "homepage": "https://github.com/manuelpichler", + "role": "Project Founder" }, { "name": "Marc Würth", - "role": "Project Maintainer", "email": "ravage@bluewin.ch", - "homepage": "https://github.com/ravage84" + "homepage": "https://github.com/ravage84", + "role": "Project Maintainer" }, { "name": "Other contributors", - "role": "Contributors", - "homepage": "https://github.com/phpmd/phpmd/graphs/contributors" + "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", + "role": "Contributors" } ], "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", From 6a82bf788cc9c82449cd8f40e859b7712a24a2c1 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Wed, 12 Feb 2020 01:51:31 +0530 Subject: [PATCH 169/176] Data Provider keys added with description --- .../Test/Unit/Controller/Result/JsFooterPluginTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php index 3d6bf010d4207..42e9646314ff1 100644 --- a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php @@ -66,7 +66,7 @@ protected function setUp(): void public function sendResponseDataProvider(): array { return [ - [ + 'content_with_script_tag' => [ "content" => "<body><h1>Test Title</h1>" . "<script type=\"text/x-magento-init\">test</script>" . "<script type=\"text/x-magento-template\">test</script>" . @@ -78,12 +78,12 @@ public function sendResponseDataProvider(): array "<script type=\"text/x-magento-init\">test</script>" . "\n</body>" ], - [ + 'content_with_config_disable' => [ "content" => "<body><p>Test Content</p></body>", "flag" => false, "result" => "<body><p>Test Content</p></body>" ], - [ + 'content_without_script_tag' => [ "content" => "<body><p>Test Content</p></body>", "flag" => true, "result" => "<body><p>Test Content</p>\n</body>" @@ -129,10 +129,10 @@ public function testBeforeSendResponse($content, $isSetFlag, $result): void public function ifGetContentIsNotAStringDataProvider(): array { return [ - [ + 'empty_array' => [ 'content' => [] ], - [ + 'null' => [ 'content' => NULL ] ]; From a017a64f3dc2bc44876862d72c1da8f8f83d896b Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Tue, 11 Feb 2020 16:33:28 -0600 Subject: [PATCH 170/176] MQE-1987: Bump MFTF version and deliver Magento branches Updated with mainline + version bump to 2.6.1 --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index be50d79e33eff..9620c73c90ba4 100644 --- a/composer.lock +++ b/composer.lock @@ -7385,12 +7385,12 @@ "source": { "type": "git", "url": "https://github.com/magento/magento2-functional-testing-framework.git", - "reference": "f56c5563ae23be5abac779a97f6d75cdf505d0a2" + "reference": "b00f5e195e1ed7f6335bce3052be9a0291f4d0db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/f56c5563ae23be5abac779a97f6d75cdf505d0a2", - "reference": "f56c5563ae23be5abac779a97f6d75cdf505d0a2", + "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/b00f5e195e1ed7f6335bce3052be9a0291f4d0db", + "reference": "b00f5e195e1ed7f6335bce3052be9a0291f4d0db", "shasum": "" }, "require": { @@ -7462,7 +7462,7 @@ "magento", "testing" ], - "time": "2020-02-11T19:46:39+00:00" + "time": "2020-02-11T22:23:54+00:00" }, { "name": "mikey179/vfsstream", From c9dcd277bf1a7a41e78aeae3d775b4cee258a7cb Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Wed, 12 Feb 2020 09:13:37 +0530 Subject: [PATCH 171/176] Fixed static test --- .../Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php index 42e9646314ff1..8b696251d4e73 100644 --- a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php @@ -133,7 +133,7 @@ public function ifGetContentIsNotAStringDataProvider(): array 'content' => [] ], 'null' => [ - 'content' => NULL + 'content' => null ] ]; } From 5cc2dc77f59d941b524e5879318ab0b7e509cebe Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 12 Feb 2020 16:51:31 +0200 Subject: [PATCH 172/176] add case when active element is input --- .../js/grid/columns/image-preview.test.js | 57 ++++++++++++------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js index 38c7003f08838..c762826734be2 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js @@ -13,10 +13,26 @@ define([ describe('Ui/js/grid/columns/image-preview', function () { var record = { - _rowIndex: 1, - rowNumber: 1 - }, - imagePreview; + _rowIndex: 1, + rowNumber: 1 + }, + imagePreview, + recordMock = { + _rowIndex: 2 + }, + secondRecordMock = { + _rowIndex: 1, + rowNumber: 1 + }, + elementMock = { + keyCode: 37 + }, + masonryMock = { + shows: jasmine.createSpy().and.returnValue([]), + rows: jasmine.createSpy().and.returnValue({ + 1: secondRecordMock + }) + }; beforeEach(function () { imagePreview = new Preview(); @@ -48,25 +64,9 @@ define([ }); describe('handleKeyDown method', function () { + it('veify record changed on key down', function () { - var recordMock = { - _rowIndex: 2 - }, - secondRecordMock = { - _rowIndex: 1, - rowNumber: 1 - }, - elementMock = { - keyCode: 37 - }, - masonryMock = { - shows: jasmine.createSpy().and.returnValue([]), - rows: jasmine.createSpy().and.returnValue({ - 1: secondRecordMock - }) - - }, - imageMock = document.createElement('img'), + var imageMock = document.createElement('img'), originMock = $.fn.get; spyOn($.fn, 'get').and.returnValue(imageMock); @@ -76,9 +76,22 @@ define([ imagePreview.masonry = jasmine.createSpy().and.returnValue(masonryMock); imagePreview.handleKeyDown(elementMock); expect(imagePreview.displayedRecord()._rowIndex).toBe(secondRecordMock._rowIndex); + $.fn.get = originMock; }); + it('veify record not changed on key down when active element input', function () { + var input = $('<input id=\'input-fixture\'/>'); + + $(document.body).append(input); + input.focus(); + imagePreview.visibleRecord = jasmine.createSpy().and.returnValue(1); + imagePreview.displayedRecord = ko.observable(1); + imagePreview.handleKeyDown(elementMock); + expect(imagePreview.displayedRecord()).toBe(1); + + $('#input-fixture').remove(); + }); }); }); }); From 7a88ffc63d9578865e19b9946a7bf368d6a1dda6 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 12 Feb 2020 16:53:43 +0200 Subject: [PATCH 173/176] fix typo --- .../Magento/Ui/base/js/grid/columns/image-preview.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js index c762826734be2..77ce2fb25f688 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js @@ -65,7 +65,7 @@ define([ describe('handleKeyDown method', function () { - it('veify record changed on key down', function () { + it('verify record changed on key down', function () { var imageMock = document.createElement('img'), originMock = $.fn.get; @@ -80,7 +80,7 @@ define([ $.fn.get = originMock; }); - it('veify record not changed on key down when active element input', function () { + it('verify record not changed on key down when active element input', function () { var input = $('<input id=\'input-fixture\'/>'); $(document.body).append(input); From fd42cdd722016ead58f5f830764e0f2135fd6206 Mon Sep 17 00:00:00 2001 From: Slava Mankivski <mankivsk@adobe.com> Date: Wed, 12 Feb 2020 21:40:37 -0600 Subject: [PATCH 174/176] Updated composer.lock --- composer.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/composer.lock b/composer.lock index 9620c73c90ba4..347a50bdf68e0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "fed60ae2b1869a71f2068e4f55a8695f", + "content-hash": "3b292997ff7767b89b6e08b0c550db7d", "packages": [ { "name": "braintree/braintree_php", @@ -88,16 +88,16 @@ }, { "name": "colinmollenhour/cache-backend-redis", - "version": "1.10.6", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/colinmollenhour/Cm_Cache_Backend_Redis.git", - "reference": "cc941a5f4cc017e11d3eab9061811ba9583ed6bf" + "reference": "389fb68de15660e39b055d149d31f3708b5d6cbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/colinmollenhour/Cm_Cache_Backend_Redis/zipball/cc941a5f4cc017e11d3eab9061811ba9583ed6bf", - "reference": "cc941a5f4cc017e11d3eab9061811ba9583ed6bf", + "url": "https://api.github.com/repos/colinmollenhour/Cm_Cache_Backend_Redis/zipball/389fb68de15660e39b055d149d31f3708b5d6cbc", + "reference": "389fb68de15660e39b055d149d31f3708b5d6cbc", "shasum": "" }, "require": { @@ -120,7 +120,7 @@ ], "description": "Zend_Cache backend using Redis with full support for tags.", "homepage": "https://github.com/colinmollenhour/Cm_Cache_Backend_Redis", - "time": "2018-09-24T16:02:07+00:00" + "time": "2019-03-03T04:04:49+00:00" }, { "name": "colinmollenhour/credis", @@ -1850,11 +1850,6 @@ "MIT" ], "authors": [ - { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" - }, { "name": "Marijn Huizendveld", "email": "marijn.huizendveld@gmail.com" @@ -1862,6 +1857,11 @@ { "name": "Thibaud Fabre", "email": "thibaud@aztech.io" + }, + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" } ], "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", From 464fee964c4f02e35287009f3f7a8d46eeaa26d1 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 13 Feb 2020 16:48:07 +0200 Subject: [PATCH 175/176] MC-31303: [2.4] Add To Cart enabled button element added --- .../Test/Mftf/Section/StorefrontProductInfoMainSection.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml index a5a02ad95b1f7..0b44d9bb0ea6b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml @@ -105,5 +105,7 @@ <element name="customOptionHour" type="date" selector="//div[@class='field date required']//span[text()='{{option}}']/../..//div/select[@data-calendar-role='hour']" parameterized="true"/> <element name="customOptionMinute" type="date" selector="//div[@class='field date required']//span[text()='{{option}}']/../..//div/select[@data-calendar-role='minute']" parameterized="true"/> <element name="customOptionDayPart" type="date" selector="//div[@class='field date required']//span[text()='{{option}}']/../..//div/select[@data-calendar-role='day_part']" parameterized="true"/> + + <element name="addToCartEnabled" type="button" selector="#product-addtocart-button:not([disabled])"/> </section> </sections> From 5f7e34c1e91cf0ddc45300ec800f782162e17ff9 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Thu, 13 Feb 2020 18:55:48 +0200 Subject: [PATCH 176/176] MC-31262: Storefront: Reset/Forgot customer password --- .../testsuite/Magento/Customer/Controller/CreatePasswordTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php index 9ad25ae5ddd5f..bbaf55494294e 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php @@ -74,7 +74,6 @@ protected function tearDown() parent::tearDown(); } - /** * @magentoDataFixture Magento/Customer/_files/customer_with_website.php *