From 8d9fd5153c15fcf11eeef566f0ead3a80078096d Mon Sep 17 00:00:00 2001 From: Serhii Balko Date: Fri, 4 Sep 2020 14:47:14 +0300 Subject: [PATCH 01/23] MC-37109: Session Cache Local Storage | Checkout Issue --- .../Magento/Persistent/Model/QuoteManager.php | 40 ++++++++++++++++--- .../Test/Unit/Model/QuoteManagerTest.php | 22 ++++++++-- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Persistent/Model/QuoteManager.php b/app/code/Magento/Persistent/Model/QuoteManager.php index b6504d528fbe4..35b07ebdb7c44 100644 --- a/app/code/Magento/Persistent/Model/QuoteManager.php +++ b/app/code/Magento/Persistent/Model/QuoteManager.php @@ -5,6 +5,7 @@ */ namespace Magento\Persistent\Model; +use Magento\Customer\Api\Data\CustomerInterfaceFactory; use Magento\Customer\Api\Data\GroupInterface; use Magento\Framework\App\ObjectManager; use Magento\Persistent\Helper\Data; @@ -64,6 +65,11 @@ class QuoteManager */ private $cartExtensionFactory; + /** + * @var CustomerInterfaceFactory + */ + private $customerDataFactory; + /** * @param \Magento\Persistent\Helper\Session $persistentSession * @param Data $persistentData @@ -71,6 +77,7 @@ class QuoteManager * @param CartRepositoryInterface $quoteRepository * @param CartExtensionFactory|null $cartExtensionFactory * @param ShippingAssignmentProcessor|null $shippingAssignmentProcessor + * @param CustomerInterfaceFactory|null $customerDataFactory */ public function __construct( \Magento\Persistent\Helper\Session $persistentSession, @@ -78,7 +85,8 @@ public function __construct( \Magento\Checkout\Model\Session $checkoutSession, CartRepositoryInterface $quoteRepository, ?CartExtensionFactory $cartExtensionFactory = null, - ?ShippingAssignmentProcessor $shippingAssignmentProcessor = null + ?ShippingAssignmentProcessor $shippingAssignmentProcessor = null, + ?CustomerInterfaceFactory $customerDataFactory = null ) { $this->persistentSession = $persistentSession; $this->persistentData = $persistentData; @@ -88,6 +96,8 @@ public function __construct( ?? ObjectManager::getInstance()->get(CartExtensionFactory::class); $this->shippingAssignmentProcessor = $shippingAssignmentProcessor ?? ObjectManager::getInstance()->get(ShippingAssignmentProcessor::class); + $this->customerDataFactory = $customerDataFactory + ?? ObjectManager::getInstance()->get(CustomerInterfaceFactory::class); } /** @@ -109,14 +119,11 @@ public function setGuest($checkQuote = false) $quote->getPaymentsCollection()->walk('delete'); $quote->getAddressesCollection()->walk('delete'); $this->_setQuotePersistent = false; + $this->cleanCustomerData($quote); $quote->setIsActive(true) - ->setCustomerId(null) - ->setCustomerEmail(null) - ->setCustomerFirstname(null) - ->setCustomerLastname(null) - ->setCustomerGroupId(GroupInterface::NOT_LOGGED_IN_ID) ->setIsPersistent(false) ->removeAllAddresses(); + //Create guest addresses $quote->getShippingAddress(); $quote->getBillingAddress(); @@ -129,6 +136,27 @@ public function setGuest($checkQuote = false) $this->persistentSession->setSession(null); } + /** + * Clear customer data in quote + * + * @param Quote $quote + */ + private function cleanCustomerData($quote) + { + /** + * Set empty customer object in quote to avoid restore customer id + * @see Quote::beforeSave() + */ + if ($quote->getCustomerId()) { + $quote->setCustomer($this->customerDataFactory->create()); + } + $quote->setCustomerId(null) + ->setCustomerEmail(null) + ->setCustomerFirstname(null) + ->setCustomerLastname(null) + ->setCustomerGroupId(GroupInterface::NOT_LOGGED_IN_ID); + } + /** * Emulate guest cart with persistent cart * diff --git a/app/code/Magento/Persistent/Test/Unit/Model/QuoteManagerTest.php b/app/code/Magento/Persistent/Test/Unit/Model/QuoteManagerTest.php index 0c183084edca2..03d6ab02beb3c 100644 --- a/app/code/Magento/Persistent/Test/Unit/Model/QuoteManagerTest.php +++ b/app/code/Magento/Persistent/Test/Unit/Model/QuoteManagerTest.php @@ -9,6 +9,8 @@ namespace Magento\Persistent\Test\Unit\Model; use Magento\Checkout\Model\Session; +use Magento\Customer\Api\Data\CustomerInterface; +use Magento\Customer\Api\Data\CustomerInterfaceFactory; use Magento\Customer\Model\GroupManagement; use Magento\Eav\Model\Entity\Collection\AbstractCollection; use Magento\Persistent\Helper\Data; @@ -78,6 +80,11 @@ class QuoteManagerTest extends TestCase */ private $shippingAssignmentProcessor; + /** + * @var CustomerInterfaceFactory|MockObject + */ + private $customerDataFactory; + protected function setUp(): void { $this->persistentSessionMock = $this->createMock(\Magento\Persistent\Helper\Session::class); @@ -124,13 +131,15 @@ protected function setUp(): void 'getItemsQty', 'getExtensionAttributes', 'setExtensionAttributes', - '__wakeup' + '__wakeup', + 'setCustomer' ]) ->disableOriginalConstructor() ->getMock(); $this->cartExtensionFactory = $this->createPartialMock(CartExtensionFactory::class, ['create']); $this->shippingAssignmentProcessor = $this->createPartialMock(ShippingAssignmentProcessor::class, ['create']); + $this->customerDataFactory = $this->createMock(CustomerInterfaceFactory::class); $this->model = new QuoteManager( $this->persistentSessionMock, @@ -138,7 +147,8 @@ protected function setUp(): void $this->checkoutSessionMock, $this->quoteRepositoryMock, $this->cartExtensionFactory, - $this->shippingAssignmentProcessor + $this->shippingAssignmentProcessor, + $this->customerDataFactory ); } @@ -189,6 +199,7 @@ public function testSetGuestWhenShoppingCartAndQuoteAreNotPersistent() public function testSetGuest() { + $customerId = 22; $this->checkoutSessionMock->expects($this->once()) ->method('getQuote')->willReturn($this->quoteMock); $this->quoteMock->expects($this->once())->method('getId')->willReturn(11); @@ -220,6 +231,7 @@ public function testSetGuest() ->method('getShippingAddress')->willReturn($quoteAddressMock); $this->quoteMock->expects($this->once()) ->method('getBillingAddress')->willReturn($quoteAddressMock); + $this->quoteMock->method('getCustomerId')->willReturn($customerId); $this->quoteMock->expects($this->once())->method('collectTotals')->willReturn($this->quoteMock); $this->quoteRepositoryMock->expects($this->once())->method('save')->with($this->quoteMock); $this->persistentSessionMock->expects($this->once()) @@ -229,7 +241,6 @@ public function testSetGuest() $this->quoteMock->expects($this->once())->method('isVirtual')->willReturn(false); $this->quoteMock->expects($this->once())->method('getItemsQty')->willReturn(1); $extensionAttributes = $this->getMockBuilder(CartExtensionInterface::class) - ->addMethods(['getShippingAssignments', 'setShippingAssignments']) ->getMockForAbstractClass(); $shippingAssignment = $this->createMock(ShippingAssignmentInterface::class); $extensionAttributes->expects($this->once()) @@ -248,6 +259,11 @@ public function testSetGuest() $this->quoteMock->expects($this->once()) ->method('setExtensionAttributes') ->with($extensionAttributes); + $customerMock = $this->createMock(CustomerInterface::class); + $this->customerDataFactory->method('create')->willReturn($customerMock); + $this->quoteMock->expects($this->once()) + ->method('setCustomer') + ->with($customerMock); $this->model->setGuest(false); } From d26a2606c089343dd49d0a0c1e8919bdc3e46cfb Mon Sep 17 00:00:00 2001 From: Serhii Balko Date: Wed, 9 Sep 2020 15:41:58 +0300 Subject: [PATCH 02/23] MC-37109: Session Cache Local Storage | Checkout Issue --- .../MakePersistentQuoteGuestObserver.php | 16 ++++++------- .../MakePersistentQuoteGuestObserverTest.php | 23 +++++++++++-------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Persistent/Observer/MakePersistentQuoteGuestObserver.php b/app/code/Magento/Persistent/Observer/MakePersistentQuoteGuestObserver.php index f2f9b96fa82e4..98c9c3df27852 100644 --- a/app/code/Magento/Persistent/Observer/MakePersistentQuoteGuestObserver.php +++ b/app/code/Magento/Persistent/Observer/MakePersistentQuoteGuestObserver.php @@ -1,16 +1,14 @@ _persistentSession = $persistentSession; $this->_persistentData = $persistentData; $this->_customerSession = $customerSession; - $this->quoteManager = $quoteManager; + $this->checkoutSession = $checkoutSession; } /** @@ -74,7 +72,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) if (($this->_persistentSession->isPersistent() && !$this->_customerSession->isLoggedIn()) || $this->_persistentData->isShoppingCartPersist() ) { - $this->quoteManager->setGuest(true); + $this->checkoutSession->clearQuote()->clearStorage(); } } } diff --git a/app/code/Magento/Persistent/Test/Unit/Observer/MakePersistentQuoteGuestObserverTest.php b/app/code/Magento/Persistent/Test/Unit/Observer/MakePersistentQuoteGuestObserverTest.php index 3622fe66099a4..bb78447cf852f 100644 --- a/app/code/Magento/Persistent/Test/Unit/Observer/MakePersistentQuoteGuestObserverTest.php +++ b/app/code/Magento/Persistent/Test/Unit/Observer/MakePersistentQuoteGuestObserverTest.php @@ -1,6 +1,5 @@ actionMock = $this->createMock(Index::class); @@ -67,7 +69,7 @@ protected function setUp(): void $this->sessionHelperMock = $this->createMock(Session::class); $this->helperMock = $this->createMock(Data::class); $this->customerSessionMock = $this->createMock(\Magento\Customer\Model\Session::class); - $this->quoteManagerMock = $this->createMock(QuoteManager::class); + $this->checkoutSession = $this->createMock(CheckoutSession::class); $this->eventManagerMock = $this->getMockBuilder(Event::class) ->addMethods(['getControllerAction']) @@ -81,7 +83,7 @@ protected function setUp(): void $this->sessionHelperMock, $this->helperMock, $this->customerSessionMock, - $this->quoteManagerMock + $this->checkoutSession ); } @@ -94,7 +96,8 @@ public function testExecute() $this->sessionHelperMock->expects($this->once())->method('isPersistent')->willReturn(true); $this->customerSessionMock->expects($this->once())->method('isLoggedIn')->willReturn(false); $this->helperMock->expects($this->never())->method('isShoppingCartPersist'); - $this->quoteManagerMock->expects($this->once())->method('setGuest')->with(true); + $this->checkoutSession->expects($this->once())->method('clearQuote')->willReturnSelf(); + $this->checkoutSession->expects($this->once())->method('clearStorage')->willReturnSelf(); $this->model->execute($this->observerMock); } @@ -107,7 +110,8 @@ public function testExecuteWhenShoppingCartIsPersist() $this->sessionHelperMock->expects($this->once())->method('isPersistent')->willReturn(true); $this->customerSessionMock->expects($this->once())->method('isLoggedIn')->willReturn(true); $this->helperMock->expects($this->once())->method('isShoppingCartPersist')->willReturn(true); - $this->quoteManagerMock->expects($this->once())->method('setGuest')->with(true); + $this->checkoutSession->expects($this->once())->method('clearQuote')->willReturnSelf(); + $this->checkoutSession->expects($this->once())->method('clearStorage')->willReturnSelf(); $this->model->execute($this->observerMock); } @@ -120,7 +124,8 @@ public function testExecuteWhenShoppingCartIsNotPersist() $this->sessionHelperMock->expects($this->once())->method('isPersistent')->willReturn(true); $this->customerSessionMock->expects($this->once())->method('isLoggedIn')->willReturn(true); $this->helperMock->expects($this->once())->method('isShoppingCartPersist')->willReturn(false); - $this->quoteManagerMock->expects($this->never())->method('setGuest'); + $this->checkoutSession->expects($this->never())->method('clearQuote')->willReturnSelf(); + $this->checkoutSession->expects($this->never())->method('clearStorage')->willReturnSelf(); $this->model->execute($this->observerMock); } } From 68c504d53c7f1ce03095e19fdeabd2e28adfab9f Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" Date: Mon, 14 Sep 2020 14:40:31 +0300 Subject: [PATCH 03/23] MC-37249: Grouped product remains In Stock on product edit page --- .../Model/Inventory/ParentItemProcessor.php | 125 ++++++++++++++++++ app/code/Magento/GroupedProduct/etc/di.xml | 7 + .../Inventory/ParentItemProcessorTest.php | 59 +++++++++ 3 files changed, 191 insertions(+) create mode 100644 app/code/Magento/GroupedProduct/Model/Inventory/ParentItemProcessor.php create mode 100644 dev/tests/integration/testsuite/Magento/GroupedProduct/Model/Inventory/ParentItemProcessorTest.php diff --git a/app/code/Magento/GroupedProduct/Model/Inventory/ParentItemProcessor.php b/app/code/Magento/GroupedProduct/Model/Inventory/ParentItemProcessor.php new file mode 100644 index 0000000000000..61b30bc905cc8 --- /dev/null +++ b/app/code/Magento/GroupedProduct/Model/Inventory/ParentItemProcessor.php @@ -0,0 +1,125 @@ +groupedType = $groupedType; + $this->criteriaInterfaceFactory = $criteriaInterfaceFactory; + $this->stockConfiguration = $stockConfiguration; + $this->stockItemRepository = $stockItemRepository; + } + + /** + * Process parent products + * + * @param Product $product + * @return void + */ + public function process(Product $product) + { + $parentIds = $this->groupedType->getParentIdsByChild($product->getId()); + foreach ($parentIds as $productId) { + $this->processStockForParent((int)$productId); + } + } + + /** + * Change stock item for parent product depending on children stock items + * + * @param int $productId + * @return void + */ + private function processStockForParent(int $productId) + { + $criteria = $this->criteriaInterfaceFactory->create(); + $criteria->setScopeFilter($this->stockConfiguration->getDefaultScopeId()); + $criteria->setProductsFilter($productId); + $stockItemCollection = $this->stockItemRepository->getList($criteria); + $allItems = $stockItemCollection->getItems(); + if (empty($allItems)) { + return; + } + $parentStockItem = array_shift($allItems); + $groupedChildrenIds = $this->groupedType->getChildrenIds($productId); + $criteria->setProductsFilter($groupedChildrenIds); + $stockItemCollection = $this->stockItemRepository->getList($criteria); + $allItems = $stockItemCollection->getItems(); + + $groupedChildrenIsInStock = false; + + foreach ($allItems as $childItem) { + if ($childItem->getIsInStock() === true) { + $groupedChildrenIsInStock = true; + break; + } + } + + if ($this->isNeedToUpdateParent($parentStockItem, $groupedChildrenIsInStock)) { + $parentStockItem->setIsInStock($groupedChildrenIsInStock); + $parentStockItem->setStockStatusChangedAuto(1); + $this->stockItemRepository->save($parentStockItem); + } + } + + /** + * Check is parent item should be updated + * + * @param StockItemInterface $parentStockItem + * @param bool $childrenIsInStock + * @return bool + */ + private function isNeedToUpdateParent(StockItemInterface $parentStockItem, bool $childrenIsInStock): bool + { + return $parentStockItem->getIsInStock() !== $childrenIsInStock && + ($childrenIsInStock === false || $parentStockItem->getStockStatusChangedAuto()); + } +} diff --git a/app/code/Magento/GroupedProduct/etc/di.xml b/app/code/Magento/GroupedProduct/etc/di.xml index 43678d0ad7a82..d9534c6d3fe7d 100644 --- a/app/code/Magento/GroupedProduct/etc/di.xml +++ b/app/code/Magento/GroupedProduct/etc/di.xml @@ -105,4 +105,11 @@ + + + + Magento\GroupedProduct\Model\Inventory\ParentItemProcessor + + + diff --git a/dev/tests/integration/testsuite/Magento/GroupedProduct/Model/Inventory/ParentItemProcessorTest.php b/dev/tests/integration/testsuite/Magento/GroupedProduct/Model/Inventory/ParentItemProcessorTest.php new file mode 100644 index 0000000000000..4b430e7a71886 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GroupedProduct/Model/Inventory/ParentItemProcessorTest.php @@ -0,0 +1,59 @@ +objectManager = Bootstrap::getObjectManager(); + } + + /** + * Test stock status parent product if children are out of stock + * + * @magentoDataFixture Magento/GroupedProduct/_files/product_grouped_with_simple_out_of_stock.php + * + * @return void + */ + public function testOutOfStockParentProduct(): void + { + $productRepository = $this->objectManager->create(ProductRepositoryInterface::class); + /** @var Product $product */ + $product = $productRepository->get('simple_100000001'); + $product->setStockData(['qty' => 0, 'is_in_stock' => 0]); + $productRepository->save($product); + /** @var StockItemRepository $stockItemRepository */ + $stockItemRepository = $this->objectManager->create(StockItemRepository::class); + /** @var StockRegistryInterface $stockRegistry */ + $stockRegistry = $this->objectManager->create(StockRegistryInterface::class); + $stockItem = $stockRegistry->getStockItemBySku('grouped'); + $stockItem = $stockItemRepository->get($stockItem->getItemId()); + + $this->assertEquals(false, $stockItem->getIsInStock()); + } +} From 91a7251bc50a597581b2533d763360bdfdc33d28 Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" Date: Tue, 15 Sep 2020 11:41:16 +0300 Subject: [PATCH 04/23] MC-37249: Grouped product remains In Stock on product edit page --- .../Model/Inventory/ParentItemProcessor.php | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/GroupedProduct/Model/Inventory/ParentItemProcessor.php b/app/code/Magento/GroupedProduct/Model/Inventory/ParentItemProcessor.php index 61b30bc905cc8..0bb102f34dd2d 100644 --- a/app/code/Magento/GroupedProduct/Model/Inventory/ParentItemProcessor.php +++ b/app/code/Magento/GroupedProduct/Model/Inventory/ParentItemProcessor.php @@ -7,6 +7,8 @@ namespace Magento\GroupedProduct\Model\Inventory; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Framework\EntityManager\MetadataPool; use Magento\GroupedProduct\Model\Product\Type\Grouped; use Magento\Catalog\Api\Data\ProductInterface as Product; use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory; @@ -14,6 +16,8 @@ use Magento\CatalogInventory\Api\StockConfigurationInterface; use Magento\CatalogInventory\Observer\ParentItemProcessorInterface; use Magento\CatalogInventory\Api\Data\StockItemInterface; +use Magento\GroupedProduct\Model\ResourceModel\Product\Link; +use Magento\Framework\App\ResourceConnection; /** * Process parent stock item for grouped product @@ -40,22 +44,40 @@ class ParentItemProcessor implements ParentItemProcessorInterface */ private $criteriaInterfaceFactory; + /** + * Product metadata pool + * + * @var MetadataPool + */ + private $metadataPool; + + /** + * @var ResourceConnection + */ + private $resource; + /** * @param Grouped $groupedType * @param StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory * @param StockItemRepositoryInterface $stockItemRepository * @param StockConfigurationInterface $stockConfiguration + * @param ResourceConnection $resource + * @param MetadataPool $metadataPool */ public function __construct( Grouped $groupedType, StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory, StockItemRepositoryInterface $stockItemRepository, - StockConfigurationInterface $stockConfiguration + StockConfigurationInterface $stockConfiguration, + ResourceConnection $resource, + MetadataPool $metadataPool ) { $this->groupedType = $groupedType; $this->criteriaInterfaceFactory = $criteriaInterfaceFactory; $this->stockConfiguration = $stockConfiguration; $this->stockItemRepository = $stockItemRepository; + $this->resource = $resource; + $this->metadataPool = $metadataPool; } /** @@ -66,7 +88,7 @@ public function __construct( */ public function process(Product $product) { - $parentIds = $this->groupedType->getParentIdsByChild($product->getId()); + $parentIds = $this->getParentEntityIdsByChild($product->getId()); foreach ($parentIds as $productId) { $this->processStockForParent((int)$productId); } @@ -122,4 +144,30 @@ private function isNeedToUpdateParent(StockItemInterface $parentStockItem, bool return $parentStockItem->getIsInStock() !== $childrenIsInStock && ($childrenIsInStock === false || $parentStockItem->getStockStatusChangedAuto()); } + + /** + * Retrieve parent ids array by child id + * + * @param int $childId + * @return string[] + */ + private function getParentEntityIdsByChild($childId) + { + $select = $this->resource->getConnection() + ->select() + ->from(['l' => $this->resource->getTableName('catalog_product_link')], []) + ->join( + ['e' => $this->resource->getTableName('catalog_product_entity')], + 'e.' . + $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField() . ' = l.product_id', + ['e.entity_id'] + ) + ->where('l.linked_product_id = ?', $childId) + ->where( + 'link_type_id = ?', + Link::LINK_TYPE_GROUPED + ); + + return $this->resource->getConnection()->fetchCol($select); + } } From eed21b7d4873216d290d663e21f0b894ab58e8d3 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh Date: Tue, 15 Sep 2020 15:56:39 +0300 Subject: [PATCH 05/23] MC-36884: Incorrect default country displayed on shipping page when store view is changed in cart --- .../frontend/web/js/view/cart/shipping-estimation.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js index a857d89a72b14..fd01ca7806584 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js @@ -78,9 +78,13 @@ define( } if (!quote.isVirtual()) { - checkoutProvider.on('shippingAddress', function (shippingAddressData) { - checkoutData.setShippingAddressFromData(shippingAddressData); - }); + checkoutProvider.on('shippingAddress', function (shippingAddressData) { + if (quote.shippingAddress().countryId !== shippingAddressData.country_id || + (shippingAddressData.postcode || shippingAddressData.region_id) + ) { + checkoutData.setShippingAddressFromData(shippingAddressData); + } + }); } else { checkoutProvider.on('shippingAddress', function (shippingAddressData) { checkoutData.setBillingAddressFromData(shippingAddressData); From 9c5119af03734e796970e60e98ef2ce056094e91 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh Date: Tue, 15 Sep 2020 18:25:39 +0300 Subject: [PATCH 06/23] MC-36884: Incorrect default country displayed on shipping page when store view is changed in cart --- .../web/js/view/cart/shipping-estimation.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js index fd01ca7806584..4656dd6f09669 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js @@ -78,13 +78,13 @@ define( } if (!quote.isVirtual()) { - checkoutProvider.on('shippingAddress', function (shippingAddressData) { - if (quote.shippingAddress().countryId !== shippingAddressData.country_id || - (shippingAddressData.postcode || shippingAddressData.region_id) - ) { - checkoutData.setShippingAddressFromData(shippingAddressData); - } - }); + checkoutProvider.on('shippingAddress', function (shippingAddressData) { + if (quote.shippingAddress().countryId !== shippingAddressData.country_id || + (shippingAddressData.postcode || shippingAddressData.region_id) + ) { + checkoutData.setShippingAddressFromData(shippingAddressData); + } + }); } else { checkoutProvider.on('shippingAddress', function (shippingAddressData) { checkoutData.setBillingAddressFromData(shippingAddressData); From b87300a0cf05d866c074700e9a0310a0f25b4eb8 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh Date: Tue, 15 Sep 2020 20:09:26 +0300 Subject: [PATCH 07/23] MC-36884: Incorrect default country displayed on shipping page when store view is changed in cart --- .../view/frontend/web/js/view/cart/shipping-estimation.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js index 4656dd6f09669..d1adb27353e1c 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js @@ -79,11 +79,13 @@ define( if (!quote.isVirtual()) { checkoutProvider.on('shippingAddress', function (shippingAddressData) { + //jscs:disable requireCamelCaseOrUpperCaseIdentifiers if (quote.shippingAddress().countryId !== shippingAddressData.country_id || (shippingAddressData.postcode || shippingAddressData.region_id) ) { checkoutData.setShippingAddressFromData(shippingAddressData); } + //jscs:enable requireCamelCaseOrUpperCaseIdentifiers }); } else { checkoutProvider.on('shippingAddress', function (shippingAddressData) { From 5af1420d6ad91b23b5eef5ffba71f4c936f8b4d8 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi Date: Wed, 16 Sep 2020 10:47:19 +0300 Subject: [PATCH 08/23] MC-37584: Fix Failing Quote Integration tests when DB table prefixes are enabled --- .../Quote/Model/Product/Plugin/UpdateQuoteItemsTest.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/Product/Plugin/UpdateQuoteItemsTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/Product/Plugin/UpdateQuoteItemsTest.php index 3aadad7e9ebec..de6501ee78986 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/Product/Plugin/UpdateQuoteItemsTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/Product/Plugin/UpdateQuoteItemsTest.php @@ -9,6 +9,7 @@ use Magento\Catalog\Model\ProductRepository; use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\Quote\Model\GetQuoteByReservedOrderId; use PHPUnit\Framework\TestCase; @@ -60,11 +61,13 @@ public function testMarkQuoteRecollectAfterChangeProductPrice(): void $product->setPrice((float)$product->getPrice() + 10); $this->productRepository->save($product); + /** @var QuoteResource $quoteResource */ + $quoteResource = $quote->getResource(); /** @var AdapterInterface $connection */ - $connection = $quote->getResource()->getConnection(); + $connection = $quoteResource->getConnection(); $select = $connection->select() ->from( - $connection->getTableName('quote'), + $quoteResource->getTable('quote'), ['updated_at', 'trigger_recollect'] )->where( "reserved_order_id = 'test_order_with_simple_product_without_address'" From 7d6fb95f33edceb8e2e43222f05600a30f43eb18 Mon Sep 17 00:00:00 2001 From: Serhii Balko Date: Wed, 16 Sep 2020 12:13:24 +0300 Subject: [PATCH 09/23] MC-37109: Session Cache Local Storage | Checkout Issue --- app/code/Magento/Persistent/Model/QuoteManager.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Persistent/Model/QuoteManager.php b/app/code/Magento/Persistent/Model/QuoteManager.php index 35b07ebdb7c44..f8456b94c0a81 100644 --- a/app/code/Magento/Persistent/Model/QuoteManager.php +++ b/app/code/Magento/Persistent/Model/QuoteManager.php @@ -108,6 +108,9 @@ public function __construct( */ public function setGuest($checkQuote = false) { + $this->persistentSession->getSession()->removePersistentCookie(); + $this->persistentSession->setSession(null); + /** @var $quote Quote */ $quote = $this->checkoutSession->getQuote(); if ($quote && $quote->getId()) { @@ -131,9 +134,6 @@ public function setGuest($checkQuote = false) $quote->collectTotals(); $this->quoteRepository->save($quote); } - - $this->persistentSession->getSession()->removePersistentCookie(); - $this->persistentSession->setSession(null); } /** From 2204ad6683abff948b02a59b03dd045b6aee0464 Mon Sep 17 00:00:00 2001 From: Serhii Balko Date: Wed, 16 Sep 2020 12:39:47 +0300 Subject: [PATCH 10/23] MC-37109: Session Cache Local Storage | Checkout Issue --- app/code/Magento/Persistent/Model/QuoteManager.php | 6 +++--- .../RemoveGuestPersistenceOnEmptyCartObserver.php | 2 ++ ...moveGuestPersistenceOnEmptyCartObserverTest.php | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Persistent/Model/QuoteManager.php b/app/code/Magento/Persistent/Model/QuoteManager.php index f8456b94c0a81..35b07ebdb7c44 100644 --- a/app/code/Magento/Persistent/Model/QuoteManager.php +++ b/app/code/Magento/Persistent/Model/QuoteManager.php @@ -108,9 +108,6 @@ public function __construct( */ public function setGuest($checkQuote = false) { - $this->persistentSession->getSession()->removePersistentCookie(); - $this->persistentSession->setSession(null); - /** @var $quote Quote */ $quote = $this->checkoutSession->getQuote(); if ($quote && $quote->getId()) { @@ -134,6 +131,9 @@ public function setGuest($checkQuote = false) $quote->collectTotals(); $this->quoteRepository->save($quote); } + + $this->persistentSession->getSession()->removePersistentCookie(); + $this->persistentSession->setSession(null); } /** diff --git a/app/code/Magento/Persistent/Observer/RemoveGuestPersistenceOnEmptyCartObserver.php b/app/code/Magento/Persistent/Observer/RemoveGuestPersistenceOnEmptyCartObserver.php index fe754711c910b..baeb023341f65 100644 --- a/app/code/Magento/Persistent/Observer/RemoveGuestPersistenceOnEmptyCartObserver.php +++ b/app/code/Magento/Persistent/Observer/RemoveGuestPersistenceOnEmptyCartObserver.php @@ -96,6 +96,8 @@ public function execute(\Magento\Framework\Event\Observer $observer) } if (!$cart || $cart->getItemsCount() == 0) { + $this->customerSession->setCustomerId(null) + ->setCustomerGroupId(null); $this->quoteManager->setGuest(); } } diff --git a/app/code/Magento/Persistent/Test/Unit/Observer/RemoveGuestPersistenceOnEmptyCartObserverTest.php b/app/code/Magento/Persistent/Test/Unit/Observer/RemoveGuestPersistenceOnEmptyCartObserverTest.php index 4adc806fed415..7bef8feaaacc5 100644 --- a/app/code/Magento/Persistent/Test/Unit/Observer/RemoveGuestPersistenceOnEmptyCartObserverTest.php +++ b/app/code/Magento/Persistent/Test/Unit/Observer/RemoveGuestPersistenceOnEmptyCartObserverTest.php @@ -137,6 +137,13 @@ public function testExecuteWithEmptyCart() ->with($customerId) ->willReturn($quoteMock); $quoteMock->expects($this->once())->method('getItemsCount')->willReturn($emptyCount); + $this->customerSessionMock->expects($this->once()) + ->method('setCustomerId') + ->with(null) + ->willReturnSelf(); + $this->customerSessionMock->expects($this->once()) + ->method('setCustomerGroupId') + ->with(null); $this->quoteManagerMock->expects($this->once())->method('setGuest'); $this->model->execute($this->observerMock); @@ -160,6 +167,13 @@ public function testExecuteWithNonexistentCart() ->method('getActiveForCustomer') ->with($customerId) ->willThrowException($exception); + $this->customerSessionMock->expects($this->once()) + ->method('setCustomerId') + ->with(null) + ->willReturnSelf(); + $this->customerSessionMock->expects($this->once()) + ->method('setCustomerGroupId') + ->with(null); $this->quoteManagerMock->expects($this->once())->method('setGuest'); $this->model->execute($this->observerMock); From 9c764e2c66cf9d3730edb04fb5f7ed50e76e1b5e Mon Sep 17 00:00:00 2001 From: Serhii Balko Date: Wed, 16 Sep 2020 14:38:48 +0300 Subject: [PATCH 11/23] MC-37109: Session Cache Local Storage | Checkout Issue --- .../Observer/RemoveGuestPersistenceOnEmptyCartObserver.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Persistent/Observer/RemoveGuestPersistenceOnEmptyCartObserver.php b/app/code/Magento/Persistent/Observer/RemoveGuestPersistenceOnEmptyCartObserver.php index baeb023341f65..efc9ecd4c1a59 100644 --- a/app/code/Magento/Persistent/Observer/RemoveGuestPersistenceOnEmptyCartObserver.php +++ b/app/code/Magento/Persistent/Observer/RemoveGuestPersistenceOnEmptyCartObserver.php @@ -10,6 +10,8 @@ /** * Observer to remove persistent session if guest empties persistent cart previously created and added to by customer. + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class RemoveGuestPersistenceOnEmptyCartObserver implements ObserverInterface { From c066be546fbd9fcb2e955ff44c1ea84ef61a0597 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh Date: Thu, 17 Sep 2020 11:57:43 +0300 Subject: [PATCH 12/23] MC-36884: Incorrect default country displayed on shipping page when store view is changed in cart --- ...outDifferentDefaultCountryPerStoreTest.xml | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 app/code/Magento/Checkout/Test/Mftf/Test/CheckoutDifferentDefaultCountryPerStoreTest.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/CheckoutDifferentDefaultCountryPerStoreTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/CheckoutDifferentDefaultCountryPerStoreTest.xml new file mode 100644 index 0000000000000..c4c70cef81b0b --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/Test/CheckoutDifferentDefaultCountryPerStoreTest.xml @@ -0,0 +1,63 @@ + + + + + + + + + + <description value="Checkout display default country per store view"/> + <severity value="MAJOR"/> + <testCaseId value="MC-37707"/> + <useCaseId value="MC-36884"/> + <group value="checkout"/> + </annotations> + <before> + <!-- Create simple product --> + <createData entity="SimpleProduct2" stepKey="createProduct"/> + <!-- Create store view --> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginToAdminArea"/> + <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreView"> + <argument name="customStore" value="customStore"/> + </actionGroup> + <!-- Set Germany as default country for created store view --> + <magentoCLI command="config:set --scope=stores --scope-code={{customStore.code}} general/country/default {{DE_Address_Berlin_Not_Default_Address.country_id}}" stepKey="changeDefaultCountry"/> + </before> + <after> + <!--Delete product and store view--> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> + <argument name="customStore" value="customStore"/> + </actionGroup> + </after> + <!-- Open product and add product to cart--> + <actionGroup ref="OpenStoreFrontProductPageActionGroup" stepKey="openProductPage"> + <argument name="productUrlKey" value="$$createProduct.custom_attributes[url_key]$$"/> + </actionGroup> + <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="addProductToCart"> + <argument name="product" value="$$createProduct$$"/> + <argument name="productCount" value="1"/> + </actionGroup> + <!-- Go to cart --> + <actionGroup ref="StorefrontOpenCartFromMinicartActionGroup" stepKey="openCart"/> + <!-- Switch store view --> + <actionGroup ref="StorefrontSwitchStoreViewActionGroup" stepKey="switchStoreViewActionGroup"> + <argument name="storeView" value="customStore"/> + </actionGroup> + <!-- Go to checkout page --> + <actionGroup ref="OpenStoreFrontCheckoutShippingPageActionGroup" stepKey="openCheckoutShippingPage"/> + <!-- Grab country code from checkout page and assert value with default country for created store view --> + <grabValueFrom selector="{{CheckoutShippingSection.country}}" stepKey="grabCountry"/> + <assertEquals stepKey="assertCountryValue"> + <actualResult type="const">$grabCountry</actualResult> + <expectedResult type="string">{{DE_Address_Berlin_Not_Default_Address.country_id}}</expectedResult> + </assertEquals> + </test> +</tests> From aa38466d5222ea0923a339922a185098a661b490 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Mon, 21 Sep 2020 11:38:53 +0300 Subject: [PATCH 13/23] MC-37369: Datepicker issue with arabic locale on orders grid --- .../Model/Product/Filter/DateTimeTest.php | 3 +- .../Test/Unit/Block/Widget/DobTest.php | 8 +- .../Component/Form/Element/DataType/Date.php | 2 +- .../DateTime/Intl/DateFormatterFactory.php | 106 ++++++++++++ .../Framework/Stdlib/DateTime/Timezone.php | 161 +++++++----------- .../Test/Unit/DateTime/TimezoneTest.php | 62 +++++-- 6 files changed, 228 insertions(+), 114 deletions(-) create mode 100644 lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Filter/DateTimeTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Filter/DateTimeTest.php index 629500ca91cdc..053d7d6e97826 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Filter/DateTimeTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Filter/DateTimeTest.php @@ -10,6 +10,7 @@ use Magento\Catalog\Model\Product\Filter\DateTime; use Magento\Framework\Locale\Resolver; use Magento\Framework\Locale\ResolverInterface; +use Magento\Framework\Stdlib\DateTime\Intl\DateFormatterFactory; use Magento\Framework\Stdlib\DateTime\Timezone; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use PHPUnit\Framework\TestCase; @@ -43,7 +44,7 @@ function () { ); $timezone = $objectManager->getObject( Timezone::class, - ['localeResolver' => $localeResolver] + ['localeResolver' => $localeResolver, 'dateFormatterFactory' => new DateFormatterFactory()] ); $stdlibDateTimeFilter = $objectManager->getObject( \Magento\Framework\Stdlib\DateTime\Filter\DateTime::class, diff --git a/app/code/Magento/Customer/Test/Unit/Block/Widget/DobTest.php b/app/code/Magento/Customer/Test/Unit/Block/Widget/DobTest.php index 39071f25ea18c..70232e955a86d 100644 --- a/app/code/Magento/Customer/Test/Unit/Block/Widget/DobTest.php +++ b/app/code/Magento/Customer/Test/Unit/Block/Widget/DobTest.php @@ -19,6 +19,7 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Locale\Resolver; use Magento\Framework\Locale\ResolverInterface; +use Magento\Framework\Stdlib\DateTime\Intl\DateFormatterFactory; use Magento\Framework\Stdlib\DateTime\Timezone; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\View\Element\Html\Date; @@ -50,7 +51,7 @@ class DobTest extends TestCase const YEAR = '2014'; // Value of date('Y', strtotime(self::DATE)) - const DATE_FORMAT = 'M/d/Y'; + const DATE_FORMAT = 'M/d/y'; /** Constants used by Dob::setDateInput($code, $html) */ const DAY_HTML = @@ -119,7 +120,7 @@ function () { ); $timezone = $objectManager->getObject( Timezone::class, - ['localeResolver' => $localeResolver] + ['localeResolver' => $localeResolver, 'dateFormatterFactory' => new DateFormatterFactory()] ); $this->_locale = Resolver::DEFAULT_LOCALE; @@ -357,7 +358,8 @@ public function getDateFormatDataProvider(): array preg_replace( '/[^MmDdYy\/\.\-]/', '', - (new \IntlDateFormatter('ar_SA', \IntlDateFormatter::SHORT, \IntlDateFormatter::NONE)) + (new DateFormatterFactory()) + ->create('ar_SA', \IntlDateFormatter::SHORT, \IntlDateFormatter::NONE) ->getPattern() ) ], diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php index ef2df77e7daff..3600992011ed6 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php @@ -111,7 +111,7 @@ public function getComponentName() public function convertDate($date, $hour = 0, $minute = 0, $second = 0, $setUtcTimeZone = true) { try { - $dateObj = $this->localeDate->date($date, $this->getLocale(), false); + $dateObj = $this->localeDate->date($date, $this->getLocale(), false, false); $dateObj->setTime($hour, $minute, $second); //convert store date to default date in UTC timezone without DST if ($setUtcTimeZone) { diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php new file mode 100644 index 0000000000000..cb9621aa2634f --- /dev/null +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php @@ -0,0 +1,106 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Framework\Stdlib\DateTime\Intl; + +/** + * Class to get Intl date formatter by locale + */ +class DateFormatterFactory +{ + /** + * Custom date formats by locale + */ + private const CUSTOM_DATE_FORMATS = [ + 'ar_SA' => [ + \IntlDateFormatter::SHORT => 'd/MM/y', + \IntlDateFormatter::MEDIUM => 'MMM d, y', + ] + ]; + + /** + * Create Intl Date formatter + * + * The Intl Date formatter gives date formats by ICU standard. + * http://userguide.icu-project.org/formatparse/datetime + * + * @param string $locale + * @param int $dateStyle + * @param int $timeStyle + * @param string|null $timeZone + * @return \IntlDateFormatter + */ + public function create( + string $locale, + int $dateStyle, + int $timeStyle, + ?string $timeZone = null + ): \IntlDateFormatter { + $formatter = new \IntlDateFormatter( + $locale, + $dateStyle, + $timeStyle, + $timeZone ? new \DateTimeZone($timeZone): null + ); + /** + * Process custom date formats + */ + $customDateFormat = $this->getCustomDateFormat($locale, $dateStyle, $timeStyle); + if ($customDateFormat !== null) { + $formatter->setPattern($customDateFormat); + } elseif ($dateStyle === \IntlDateFormatter::SHORT) { + /** + * Gives 4 places for year value in short style + */ + $pattern = $formatter->getPattern(); + $dateFormat = $this->setFourYearPlaces($formatter->getPattern()); + if ($dateFormat !== $pattern) { + $formatter->setPattern($dateFormat); + } + } + + return $formatter; + } + + /** + * Get custom date format if it exists + * + * @param string $locale + * @param int $dateStyle + * @param int $timeStyle + * @return string + */ + private function getCustomDateFormat(string $locale, int $dateStyle, int $timeStyle): ?string + { + $customDateFormat = null; + if ($dateStyle !== \IntlDateFormatter::NONE && isset(self::CUSTOM_DATE_FORMATS[$locale][$dateStyle])) { + $customDateFormat = self::CUSTOM_DATE_FORMATS[$locale][$dateStyle]; + if ($timeStyle !== \IntlDateFormatter::NONE) { + $timeFormat = (new \IntlDateFormatter($locale, \IntlDateFormatter::NONE, $timeStyle)) + ->getPattern(); + $customDateFormat .= ' ' . $timeFormat; + } + } + + return $customDateFormat; + } + + /** + * Set 4 places for year value in format string + * + * @param string $format + * @return string + */ + private function setFourYearPlaces(string $format): string + { + return preg_replace( + '/(?<!y)yy(?!y)/', + 'y', + $format + ); + } +} diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php index cdf175767d6aa..7510b1b197ea2 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php @@ -12,6 +12,7 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Locale\ResolverInterface; use Magento\Framework\Phrase; +use Magento\Framework\Stdlib\DateTime\Intl\DateFormatterFactory; /** * Timezone library @@ -30,11 +31,6 @@ class Timezone implements TimezoneInterface \IntlDateFormatter::SHORT, ]; - /** - * @var array - */ - private $dateFormatterCache = []; - /** * @var string */ @@ -65,6 +61,11 @@ class Timezone implements TimezoneInterface */ protected $_localeResolver; + /** + * @var DateFormatterFactory + */ + private $dateFormatterFactory; + /** * @param ScopeResolverInterface $scopeResolver * @param ResolverInterface $localeResolver @@ -72,6 +73,7 @@ class Timezone implements TimezoneInterface * @param ScopeConfigInterface $scopeConfig * @param string $scopeType * @param string $defaultTimezonePath + * @param DateFormatterFactory $dateFormatterFactory */ public function __construct( ScopeResolverInterface $scopeResolver, @@ -79,7 +81,8 @@ public function __construct( \Magento\Framework\Stdlib\DateTime $dateTime, ScopeConfigInterface $scopeConfig, $scopeType, - $defaultTimezonePath + $defaultTimezonePath, + DateFormatterFactory $dateFormatterFactory ) { $this->_scopeResolver = $scopeResolver; $this->_localeResolver = $localeResolver; @@ -87,6 +90,7 @@ public function __construct( $this->_defaultTimezonePath = $defaultTimezonePath; $this->_scopeConfig = $scopeConfig; $this->_scopeType = $scopeType; + $this->dateFormatterFactory = $dateFormatterFactory; } /** @@ -122,11 +126,13 @@ public function getConfigTimezone($scopeType = null, $scopeCode = null) */ public function getDateFormat($type = \IntlDateFormatter::SHORT) { - return (new \IntlDateFormatter( - $this->_localeResolver->getLocale(), - $type, + $formatter = $this->dateFormatterFactory->create( + (string)$this->_localeResolver->getLocale(), + (int)$type, \IntlDateFormatter::NONE - ))->getPattern(); + ); + + return $formatter->getPattern(); } /** @@ -134,11 +140,7 @@ public function getDateFormat($type = \IntlDateFormatter::SHORT) */ public function getDateFormatWithLongYear() { - return preg_replace( - '/(?<!y)yy(?!y)/', - 'Y', - $this->getDateFormat() - ); + return $this->getDateFormat(); } /** @@ -146,11 +148,13 @@ public function getDateFormatWithLongYear() */ public function getTimeFormat($type = \IntlDateFormatter::SHORT) { - return (new \IntlDateFormatter( - $this->_localeResolver->getLocale(), + $formatter = $this->dateFormatterFactory->create( + (string)$this->_localeResolver->getLocale(), \IntlDateFormatter::NONE, - $type - ))->getPattern(); + (int)$type + ); + + return $formatter->getPattern(); } /** @@ -166,10 +170,8 @@ public function getDateTimeFormat($type) */ public function date($date = null, $locale = null, $useTimezone = true, $includeTime = true) { - $locale = $locale ?: $this->_localeResolver->getLocale(); - $timezone = $useTimezone - ? $this->getConfigTimezone() - : date_default_timezone_get(); + $locale = (string)($locale ?: $this->_localeResolver->getLocale()); + $timezone = (string)($useTimezone ? $this->getConfigTimezone() : date_default_timezone_get()); switch (true) { case (empty($date)): @@ -179,9 +181,14 @@ public function date($date = null, $locale = null, $useTimezone = true, $include case ($date instanceof \DateTimeImmutable): return new \DateTime($date->format('Y-m-d H:i:s'), $date->getTimezone()); case (!is_numeric($date)): - $date = $this->appendTimeIfNeeded($date, $includeTime, $timezone, $locale); - $date = $this->parseLocaleDate($date, $locale, $timezone, $includeTime) - ?: (new \DateTime($date))->getTimestamp(); + $date = $this->appendTimeIfNeeded((string)$date, (bool)$includeTime, $timezone, $locale); + $formatter = $this->dateFormatterFactory->create( + $locale, + \IntlDateFormatter::SHORT, + $includeTime ? \IntlDateFormatter::SHORT : \IntlDateFormatter::NONE, + $timezone + ); + $date = $formatter->parse($date) ?: (new \DateTime($date))->getTimestamp(); break; } @@ -279,25 +286,32 @@ public function formatDateTime( if (!($date instanceof \DateTimeInterface)) { $date = new \DateTime($date); } - + if ($dateType === null) { + $dateType = \IntlDateFormatter::SHORT; + } + if ($timeType === null) { + $timeType = \IntlDateFormatter::SHORT; + } if ($timezone === null) { if ($date->getTimezone() == null || $date->getTimezone()->getName() == 'UTC' || $date->getTimezone()->getName() == '+00:00' ) { $timezone = $this->getConfigTimezone(); } else { - $timezone = $date->getTimezone(); + $timezone = $date->getTimezone()->getName(); } } - $formatter = new \IntlDateFormatter( - $locale ?: $this->_localeResolver->getLocale(), - $dateType, - $timeType, - $timezone, - null, - $pattern + $formatter = $this->dateFormatterFactory->create( + (string)($locale ?: $this->_localeResolver->getLocale()), + (int)$dateType, + (int)$timeType, + (string)$timezone ); + if ($pattern) { + $formatter->setPattern($pattern); + } + return $formatter->format($date); } @@ -338,11 +352,17 @@ public function convertConfigTimeToUtc($date, $format = 'Y-m-d H:i:s') * @return string * @throws LocalizedException */ - private function appendTimeIfNeeded($date, $includeTime, $timezone, $locale) + private function appendTimeIfNeeded(string $date, bool $includeTime, string $timezone, string $locale) { if ($includeTime && !preg_match('/\d{1}:\d{2}/', $date)) { - $convertedDate = $this->parseLocaleDate($date, $locale, $timezone, false); - if (!$convertedDate) { + $formatter = $this->dateFormatterFactory->create( + $locale, + \IntlDateFormatter::SHORT, + \IntlDateFormatter::NONE, + $timezone + ); + $timestamp = $formatter->parse($date); + if (!$timestamp) { throw new LocalizedException( new Phrase( 'Could not append time to DateTime' @@ -350,68 +370,15 @@ private function appendTimeIfNeeded($date, $includeTime, $timezone, $locale) ); } - $formatterWithHour = $this->getDateFormatter( + $formatterWithHour = $this->dateFormatterFactory->create( $locale, - $timezone, - \IntlDateFormatter::MEDIUM, - \IntlDateFormatter::SHORT + \IntlDateFormatter::SHORT, + \IntlDateFormatter::SHORT, + $timezone ); - $date = $formatterWithHour->format($convertedDate); + $date = $formatterWithHour->format($timestamp); } - return $date; - } - /** - * Parse date by locale format through IntlDateFormatter - * - * @param string $date - * @param string $locale - * @param string $timeZone - * @param bool $includeTime - * @return int|null Timestamp of date - */ - private function parseLocaleDate(string $date, string $locale, string $timeZone, bool $includeTime): ?int - { - $allowedStyles = [\IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT]; - $timeStyle = $includeTime ? \IntlDateFormatter::SHORT : \IntlDateFormatter::NONE; - - /** - * Try to parse date with different styles - */ - foreach ($allowedStyles as $style) { - $formatter = $this->getDateFormatter($locale, $timeZone, $style, $timeStyle); - $timeStamp = $formatter->parse($date); - if ($timeStamp) { - return $timeStamp; - } - } - - return null; - } - - /** - * Get date formatter for locale - * - * @param string $locale - * @param string $timeZone - * @param int $style - * @param int $timeStyle - * @return \IntlDateFormatter - */ - private function getDateFormatter(string $locale, string $timeZone, int $style, int $timeStyle): \IntlDateFormatter - { - $cacheKey = "{$locale}_{$timeZone}_{$style}_{$timeStyle}"; - if (isset($this->dateFormatterCache[$cacheKey])) { - return $this->dateFormatterCache[$cacheKey]; - } - - $this->dateFormatterCache[$cacheKey] = new \IntlDateFormatter( - $locale, - $style, - $timeStyle, - new \DateTimeZone($timeZone) - ); - - return $this->dateFormatterCache[$cacheKey]; + return $date; } } diff --git a/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php b/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php index 2e8110316ec29..ad2f24566be4e 100644 --- a/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php +++ b/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php @@ -12,6 +12,7 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Locale\ResolverInterface; use Magento\Framework\Stdlib\DateTime; +use Magento\Framework\Stdlib\DateTime\Intl\DateFormatterFactory; use Magento\Framework\Stdlib\DateTime\Timezone; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use PHPUnit\Framework\MockObject\MockObject; @@ -90,22 +91,23 @@ protected function tearDown(): void * @param string $date * @param string $locale * @param bool $includeTime - * @param int $expectedTimestamp + * @param int|string $expectedTime + * @param string|null $timeZone * @dataProvider dateIncludeTimeDataProvider */ - public function testDateIncludeTime($date, $locale, $includeTime, $expectedTimestamp) + public function testDateIncludeTime($date, $locale, $includeTime, $expectedTime, $timeZone = 'America/Chicago') { - $this->scopeConfig->method('getValue')->willReturn('America/Chicago'); - /** @var Timezone $timezone */ - $timezone = $this->objectManager->getObject(Timezone::class, ['scopeConfig' => $this->scopeConfig]); + if ($timeZone !== null) { + $this->scopeConfig->method('getValue')->willReturn($timeZone); + } /** @var \DateTime $dateTime */ - $dateTime = $timezone->date($date, $locale, true, $includeTime); - if (is_numeric($expectedTimestamp)) { - $this->assertEquals($expectedTimestamp, $dateTime->getTimestamp()); + $dateTime = $this->getTimezone()->date($date, $locale, $timeZone !== null, $includeTime); + if (is_numeric($expectedTime)) { + $this->assertEquals($expectedTime, $dateTime->getTimestamp()); } else { $format = $includeTime ? DateTime::DATETIME_PHP_FORMAT : DateTime::DATE_PHP_FORMAT; - $this->assertEquals($expectedTimestamp, date($format, $dateTime->getTimestamp())); + $this->assertEquals($expectedTime, date($format, $dateTime->getTimestamp())); } } @@ -158,10 +160,24 @@ public function dateIncludeTimeDataProvider(): array 1635570000 // expected timestamp ], 'Parse Saudi Arabia date without time' => [ - '31‏/8‏/2020 02020', + '4/09/2020', 'ar_SA', false, - '2020-08-31' + '2020-09-04' + ], + 'Parse Saudi Arabia date with time' => [ + '4/09/2020 10:10 مساء', + 'ar_SA', + true, + '2020-09-04 22:10:00', + null + ], + 'Parse Saudi Arabia date with zero time' => [ + '4/09/2020', + 'ar_SA', + true, + '2020-09-04 00:00:00', + null ], 'Parse date in short style with long year 1999' => [ '9/11/1999', @@ -178,6 +194,27 @@ public function dateIncludeTimeDataProvider(): array ]; } + /** + * @param string $locale + * @param int $style + * @param string $expectedFormat + * @dataProvider getDatetimeFormatDataProvider + */ + public function testGetDatetimeFormat(string $locale, int $style, string $expectedFormat): void + { + /** @var Timezone $timezone */ + $this->localeResolver->method('getLocale')->willReturn($locale); + $this->assertEquals($expectedFormat, $this->getTimezone()->getDateTimeFormat($style)); + } + + public function getDatetimeFormatDataProvider(): array + { + return [ + ['en_US', \IntlDateFormatter::SHORT, 'M/d/y h:mm a'], + ['ar_SA', \IntlDateFormatter::SHORT, 'd/MM/y h:mm a'] + ]; + } + /** * @param string $date * @param string $configuredTimezone @@ -320,7 +357,8 @@ private function getTimezone() $this->createMock(DateTime::class), $this->scopeConfig, $this->scopeType, - $this->defaultTimezonePath + $this->defaultTimezonePath, + new DateFormatterFactory() ); } From 60b82b3ddee209bc32a3aa1908301850d4a1ccac Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Mon, 21 Sep 2020 15:56:12 +0300 Subject: [PATCH 14/23] MC-37369: Datepicker issue with arabic locale on orders grid --- .../Framework/Stdlib/DateTime/Timezone.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php index 7510b1b197ea2..2c9fe36fbca29 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php @@ -286,28 +286,24 @@ public function formatDateTime( if (!($date instanceof \DateTimeInterface)) { $date = new \DateTime($date); } - if ($dateType === null) { - $dateType = \IntlDateFormatter::SHORT; - } - if ($timeType === null) { - $timeType = \IntlDateFormatter::SHORT; - } if ($timezone === null) { if ($date->getTimezone() == null || $date->getTimezone()->getName() == 'UTC' || $date->getTimezone()->getName() == '+00:00' ) { $timezone = $this->getConfigTimezone(); } else { - $timezone = $date->getTimezone()->getName(); + $timezone = $date->getTimezone(); } } $formatter = $this->dateFormatterFactory->create( (string)($locale ?: $this->_localeResolver->getLocale()), - (int)$dateType, - (int)$timeType, - (string)$timezone + (int)($dateType ?? \IntlDateFormatter::SHORT), + (int)($timeType ?? \IntlDateFormatter::SHORT) ); + if ($timezone) { + $formatter->setTimeZone($timezone); + } if ($pattern) { $formatter->setPattern($pattern); } From af7b84a4e1770a69810386d3ad600cf12d668f73 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Mon, 21 Sep 2020 18:11:24 +0300 Subject: [PATCH 15/23] MC-37369: Datepicker issue with arabic locale on orders grid --- .../Test/AdminCreateDatetimeProductAttributeTest.xml | 2 +- .../StorefrontPurchaseProductWithCustomOptionsTest.xml | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDatetimeProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDatetimeProductAttributeTest.xml index 4c57504b60ad7..cc321834c6424 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDatetimeProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDatetimeProductAttributeTest.xml @@ -27,7 +27,7 @@ <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Generate the datetime default value --> - <generateDate date="now" format="n/j/y g:i A" stepKey="generateDefaultValue"/> + <generateDate date="now" format="n/j/Y g:i A" stepKey="generateDefaultValue"/> <!-- Create new datetime product attribute --> <actionGroup ref="AdminOpenProductAttributePageActionGroup" stepKey="goToProductAttributes"/> <actionGroup ref="CreateProductAttributeWithDatetimeFieldActionGroup" stepKey="createAttribute"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml index 631d1d50077e9..fc25fccde035a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml @@ -61,7 +61,6 @@ <!--Generate year--> <generateDate date="Now" format="Y" stepKey="year"/> - <generateDate date="Now" format="y" stepKey="shortYear"/> <!-- Adding items to the checkout --> @@ -111,7 +110,7 @@ <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="{{ProductOptionValueCheckbox.title}}" stepKey="seeProductOptionValueCheckboxInput1" /> <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="{{ProductOptionValueMultiSelect1.title}}" stepKey="seeproductAttributeOptionsMultiselect1Input1" /> <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="Jan 1, $year" stepKey="seeProductOptionDateAndTimeInput" /> - <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="1/1/$shortYear, 1:00 AM" stepKey="seeProductOptionDataInput" /> + <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="1/1/$year, 1:00 AM" stepKey="seeProductOptionDataInput" /> <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="1:00 AM" stepKey="seeProductOptionTimeInput" /> <!--Select shipping method--> <actionGroup ref="CheckoutSelectFlatRateShippingMethodActionGroup" stepKey="selectFlatRateShippingMethod"/> @@ -145,7 +144,7 @@ <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueCheckbox.title}}" stepKey="seeAdminOrderProductOptionValueCheckbox" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueMultiSelect1.title}}" stepKey="seeAdminOrderproductAttributeOptionsMultiselect1" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="Jan 1, $year" stepKey="seeAdminOrderProductOptionDateAndTime" /> - <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1/1/$shortYear, 1:00 AM" stepKey="seeAdminOrderProductOptionData" /> + <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1/1/$year, 1:00 AM" stepKey="seeAdminOrderProductOptionData" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1:00 AM" stepKey="seeAdminOrderProductOptionTime" /> <!-- Reorder and Checking the correctness of displayed custom options for user parameters on Order and correctness of displayed price Subtotal--> @@ -163,7 +162,7 @@ <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueCheckbox.title}}" stepKey="seeAdminOrderProductOptionValueCheckbox1" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueMultiSelect1.title}}" stepKey="seeAdminOrderproductAttributeOptionsMultiselect11" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="Jan 1, $year" stepKey="seeAdminOrderProductOptionDateAndTime1" /> - <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1/1/$shortYear, 1:00 AM" stepKey="seeAdminOrderProductOptionData1" /> + <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1/1/$year, 1:00 AM" stepKey="seeAdminOrderProductOptionData1" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1:00 AM" stepKey="seeAdminOrderProductOptionTime1" /> <see selector="{{AdminOrderTotalSection.subTotal}}" userInput="{$finalProductPrice}" stepKey="seeOrderSubTotal"/> @@ -181,7 +180,7 @@ <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($$createProduct.name$$, ProductOptionCheckbox.title, ProductOptionValueCheckbox.title)}}" userInput="{{ProductOptionValueCheckbox.title}}" stepKey="seeStorefontOrderProductOptionValueCheckbox1" /> <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($$createProduct.name$$, ProductOptionMultiSelect.title, ProductOptionValueMultiSelect1.title)}}" userInput="{{ProductOptionValueMultiSelect1.title}}" stepKey="seeStorefontOrderproductAttributeOptionsMultiselect11" /> <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($$createProduct.name$$, ProductOptionDate.title, 'Jan 1, $year')}}" userInput="Jan 1, $year" stepKey="seeStorefontOrderProductOptionDateAndTime1" /> - <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($$createProduct.name$$, ProductOptionDateTime.title, '1/1/$shortYear, 1:00 AM')}}" userInput="1/1/$shortYear, 1:00 AM" stepKey="seeStorefontOrderProductOptionData1" /> + <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($$createProduct.name$$, ProductOptionDateTime.title, '1/1/$year, 1:00 AM')}}" userInput="1/1/$year, 1:00 AM" stepKey="seeStorefontOrderProductOptionData1" /> <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($$createProduct.name$$, ProductOptionTime.title, '1:00 AM')}}" userInput="1:00 AM" stepKey="seeStorefontOrderProductOptionTime1" /> </test> </tests> From 720d02262980aea936c421d48d6db49c6a08847c Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Tue, 22 Sep 2020 15:56:48 +0300 Subject: [PATCH 16/23] MC-36410: [Chrome] Loader stacks during import when the same file is checked after update --- .../Block/Adminhtml/Import/Edit/Form.php | 3 +- app/code/Magento/ImportExport/i18n/en_US.csv | 1 + .../templates/import/form/before.phtml | 35 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php index 55992c92226af..87cd4cf346288 100644 --- a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php +++ b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php @@ -226,6 +226,7 @@ protected function _prepareForm() 'title' => __('Select File to Import'), 'required' => true, 'class' => 'input-file', + 'onchange' => 'varienImport.refreshLoadedFileLastModified(this);', 'note' => __( 'File must be saved in UTF-8 encoding for proper import' ), @@ -282,7 +283,7 @@ protected function getDownloadSampleFileHtml() private function getImportBehaviorTooltip() { $html = '<div class="admin__field-tooltip tooltip"> - <a class="admin__field-tooltip-action action-help" target="_blank" title="What is this?" + <a class="admin__field-tooltip-action action-help" target="_blank" title="What is this?" href="https://docs.magento.com/m2/ce/user_guide/system/data-import.html"><span>' . __('What is this?') . '</span></a></div>'; diff --git a/app/code/Magento/ImportExport/i18n/en_US.csv b/app/code/Magento/ImportExport/i18n/en_US.csv index a4943fe72826f..9334d8c5dd348 100644 --- a/app/code/Magento/ImportExport/i18n/en_US.csv +++ b/app/code/Magento/ImportExport/i18n/en_US.csv @@ -127,3 +127,4 @@ Summary,Summary "File %1 deleted","File %1 deleted" "Please provide valid export file name","Please provide valid export file name" "%1 is not a valid file","%1 is not a valid file" +"Something went wrong while getting data from a file, please re-upload file","Something went wrong while getting data from a file, please re-upload file" diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml index 69779baba381d..06064c9d93af1 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml +++ b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml @@ -7,6 +7,10 @@ <?php /** @var $block \Magento\ImportExport\Block\Adminhtml\Import\Edit\Before */ /** @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer */ +$fieldNameSourceFile = \Magento\ImportExport\Model\Import::FIELD_NAME_SOURCE_FILE; +$uploaderErrorMessage = $block->escapeHtml( + __('Something went wrong while getting data from a file, please re-upload file') +); ?> <?php $scriptString = <<<script @@ -49,6 +53,12 @@ require([ */ sampleFilesBaseUrl: '{$block->escapeJs($block->getUrl('*/*/download/', ['filename' => 'entity-name']))}', + /** + * Loaded file last modified + * @type {int|null} + */ + loadedFileLastModified: null, + /** * Reset selected index * @param {string} elementId @@ -162,11 +172,36 @@ require([ } }, + /** + * Refresh loaded file last modified + */ + refreshLoadedFileLastModified: function(e) { + if (jQuery(e)[0].files.length > 0) { + this.loadedFileLastModified = jQuery(e)[0].files[0].lastModified; + } else { + this.loadedFileLastModified = null; + } + }, + /** * Post form data to dynamic iframe. * @param {string} newActionUrl OPTIONAL Change form action to this if specified */ postToFrame: function(newActionUrl) { + var fileUploader = document.getElementById('{$fieldNameSourceFile}'); + + for (var i = 0; i < fileUploader.files.length; i++) { + const file = fileUploader.files[i]; + + if (this.loadedFileLastModified !== file.lastModified) { + alert({ + content: '{$uploaderErrorMessage}' + }); + fileUploader.value = null; + return; + } + } + if (!jQuery('[name="' + this.ifrElemName + '"]').length) { jQuery('body').append('<iframe name="' + this.ifrElemName + '" id="' + this.ifrElemName + '"/>'); jQuery('iframe#' + this.ifrElemName).attr('display', 'none'); From ce6753009fd476be09c785006a50636394524ab4 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Tue, 22 Sep 2020 16:28:13 +0300 Subject: [PATCH 17/23] MC-37369: Datepicker issue with arabic locale on orders grid --- ...dminCreateDatetimeProductAttributeTest.xml | 2 +- .../DateTime/Intl/DateFormatterFactory.php | 8 ++-- .../Framework/Stdlib/DateTime/Timezone.php | 12 +++++- .../Test/Unit/DateTime/TimezoneTest.php | 38 +++++++++++++++++-- 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDatetimeProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDatetimeProductAttributeTest.xml index cc321834c6424..4c57504b60ad7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDatetimeProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDatetimeProductAttributeTest.xml @@ -27,7 +27,7 @@ <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Generate the datetime default value --> - <generateDate date="now" format="n/j/Y g:i A" stepKey="generateDefaultValue"/> + <generateDate date="now" format="n/j/y g:i A" stepKey="generateDefaultValue"/> <!-- Create new datetime product attribute --> <actionGroup ref="AdminOpenProductAttributePageActionGroup" stepKey="goToProductAttributes"/> <actionGroup ref="CreateProductAttributeWithDatetimeFieldActionGroup" stepKey="createAttribute"> diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php index cb9621aa2634f..3516754ca0710 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php @@ -32,19 +32,21 @@ class DateFormatterFactory * @param int $dateStyle * @param int $timeStyle * @param string|null $timeZone + * @param bool $useFourDigitsForYear * @return \IntlDateFormatter */ public function create( string $locale, int $dateStyle, int $timeStyle, - ?string $timeZone = null + ?string $timeZone = null, + bool $useFourDigitsForYear = true ): \IntlDateFormatter { $formatter = new \IntlDateFormatter( $locale, $dateStyle, $timeStyle, - $timeZone ? new \DateTimeZone($timeZone): null + $timeZone ); /** * Process custom date formats @@ -52,7 +54,7 @@ public function create( $customDateFormat = $this->getCustomDateFormat($locale, $dateStyle, $timeStyle); if ($customDateFormat !== null) { $formatter->setPattern($customDateFormat); - } elseif ($dateStyle === \IntlDateFormatter::SHORT) { + } elseif ($dateStyle === \IntlDateFormatter::SHORT && $useFourDigitsForYear) { /** * Gives 4 places for year value in short style */ diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php index 2c9fe36fbca29..b10e05aae8030 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php @@ -129,7 +129,9 @@ public function getDateFormat($type = \IntlDateFormatter::SHORT) $formatter = $this->dateFormatterFactory->create( (string)$this->_localeResolver->getLocale(), (int)$type, - \IntlDateFormatter::NONE + \IntlDateFormatter::NONE, + null, + false ); return $formatter->getPattern(); @@ -140,7 +142,13 @@ public function getDateFormat($type = \IntlDateFormatter::SHORT) */ public function getDateFormatWithLongYear() { - return $this->getDateFormat(); + $formatter = $this->dateFormatterFactory->create( + (string)$this->_localeResolver->getLocale(), + \IntlDateFormatter::SHORT, + \IntlDateFormatter::NONE + ); + + return $formatter->getPattern(); } /** diff --git a/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php b/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php index ad2f24566be4e..38a62f006adbc 100644 --- a/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php +++ b/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php @@ -180,10 +180,10 @@ public function dateIncludeTimeDataProvider(): array null ], 'Parse date in short style with long year 1999' => [ - '9/11/1999', + '8/11/1999', 'en_US', false, - '1999-09-11' + '1999-08-11' ], 'Parse date in short style with long year 2099' => [ '9/2/2099', @@ -191,6 +191,12 @@ public function dateIncludeTimeDataProvider(): array false, '2099-09-02' ], + 'Parse date in short style with short year 1999' => [ + '8/11/99', + 'en_US', + false, + '1999-08-11' + ], ]; } @@ -207,14 +213,40 @@ public function testGetDatetimeFormat(string $locale, int $style, string $expect $this->assertEquals($expectedFormat, $this->getTimezone()->getDateTimeFormat($style)); } + /** + * @return array + */ public function getDatetimeFormatDataProvider(): array { return [ - ['en_US', \IntlDateFormatter::SHORT, 'M/d/y h:mm a'], + ['en_US', \IntlDateFormatter::SHORT, 'M/d/yy h:mm a'], ['ar_SA', \IntlDateFormatter::SHORT, 'd/MM/y h:mm a'] ]; } + /** + * @param string $locale + * @param int $style + * @param string $expectedFormat + * @dataProvider getDateFormatWithLongYearDataProvider + */ + public function testGetDateFormatWithLongYear(string $locale, string $expectedFormat): void + { + /** @var Timezone $timezone */ + $this->localeResolver->method('getLocale')->willReturn($locale); + $this->assertEquals($expectedFormat, $this->getTimezone()->getDateFormatWithLongYear()); + } + + /** + * @return array + */ + public function getDateFormatWithLongYearDataProvider(): array + { + return [ + ['en_US', 'M/d/y'], + ]; + } + /** * @param string $date * @param string $configuredTimezone From 44c9eddec39035f9603b3ebb63f4dafbbbb0f2cb Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Tue, 22 Sep 2020 17:05:31 +0300 Subject: [PATCH 18/23] MC-36410: [Chrome] Loader stacks during import when the same file is checked after update --- .../adminhtml/templates/import/form/before.phtml | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml index 06064c9d93af1..91ce6145cb80a 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml +++ b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml @@ -190,16 +190,12 @@ require([ postToFrame: function(newActionUrl) { var fileUploader = document.getElementById('{$fieldNameSourceFile}'); - for (var i = 0; i < fileUploader.files.length; i++) { - const file = fileUploader.files[i]; - - if (this.loadedFileLastModified !== file.lastModified) { - alert({ - content: '{$uploaderErrorMessage}' - }); - fileUploader.value = null; - return; - } + if (fileUploader.files.length > 0 && fileUploader.files[0].lastModified !== this.loadedFileLastModified) { + alert({ + content: '{$uploaderErrorMessage}' + }); + fileUploader.value = null; + return; } if (!jQuery('[name="' + this.ifrElemName + '"]').length) { From a7c15b8fa42de6212eb6cde8c4929c5e874ed8e5 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Tue, 22 Sep 2020 17:31:06 +0300 Subject: [PATCH 19/23] MC-37369: Datepicker issue with arabic locale on orders grid --- .../StorefrontPurchaseProductWithCustomOptionsTest.xml | 9 +++++---- .../Stdlib/DateTime/Intl/DateFormatterFactory.php | 7 ++----- .../Magento/Framework/Stdlib/DateTime/Timezone.php | 4 +++- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml index fc25fccde035a..631d1d50077e9 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml @@ -61,6 +61,7 @@ <!--Generate year--> <generateDate date="Now" format="Y" stepKey="year"/> + <generateDate date="Now" format="y" stepKey="shortYear"/> <!-- Adding items to the checkout --> @@ -110,7 +111,7 @@ <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="{{ProductOptionValueCheckbox.title}}" stepKey="seeProductOptionValueCheckboxInput1" /> <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="{{ProductOptionValueMultiSelect1.title}}" stepKey="seeproductAttributeOptionsMultiselect1Input1" /> <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="Jan 1, $year" stepKey="seeProductOptionDateAndTimeInput" /> - <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="1/1/$year, 1:00 AM" stepKey="seeProductOptionDataInput" /> + <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="1/1/$shortYear, 1:00 AM" stepKey="seeProductOptionDataInput" /> <see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="1:00 AM" stepKey="seeProductOptionTimeInput" /> <!--Select shipping method--> <actionGroup ref="CheckoutSelectFlatRateShippingMethodActionGroup" stepKey="selectFlatRateShippingMethod"/> @@ -144,7 +145,7 @@ <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueCheckbox.title}}" stepKey="seeAdminOrderProductOptionValueCheckbox" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueMultiSelect1.title}}" stepKey="seeAdminOrderproductAttributeOptionsMultiselect1" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="Jan 1, $year" stepKey="seeAdminOrderProductOptionDateAndTime" /> - <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1/1/$year, 1:00 AM" stepKey="seeAdminOrderProductOptionData" /> + <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1/1/$shortYear, 1:00 AM" stepKey="seeAdminOrderProductOptionData" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1:00 AM" stepKey="seeAdminOrderProductOptionTime" /> <!-- Reorder and Checking the correctness of displayed custom options for user parameters on Order and correctness of displayed price Subtotal--> @@ -162,7 +163,7 @@ <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueCheckbox.title}}" stepKey="seeAdminOrderProductOptionValueCheckbox1" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueMultiSelect1.title}}" stepKey="seeAdminOrderproductAttributeOptionsMultiselect11" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="Jan 1, $year" stepKey="seeAdminOrderProductOptionDateAndTime1" /> - <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1/1/$year, 1:00 AM" stepKey="seeAdminOrderProductOptionData1" /> + <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1/1/$shortYear, 1:00 AM" stepKey="seeAdminOrderProductOptionData1" /> <see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="1:00 AM" stepKey="seeAdminOrderProductOptionTime1" /> <see selector="{{AdminOrderTotalSection.subTotal}}" userInput="{$finalProductPrice}" stepKey="seeOrderSubTotal"/> @@ -180,7 +181,7 @@ <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($$createProduct.name$$, ProductOptionCheckbox.title, ProductOptionValueCheckbox.title)}}" userInput="{{ProductOptionValueCheckbox.title}}" stepKey="seeStorefontOrderProductOptionValueCheckbox1" /> <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($$createProduct.name$$, ProductOptionMultiSelect.title, ProductOptionValueMultiSelect1.title)}}" userInput="{{ProductOptionValueMultiSelect1.title}}" stepKey="seeStorefontOrderproductAttributeOptionsMultiselect11" /> <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($$createProduct.name$$, ProductOptionDate.title, 'Jan 1, $year')}}" userInput="Jan 1, $year" stepKey="seeStorefontOrderProductOptionDateAndTime1" /> - <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($$createProduct.name$$, ProductOptionDateTime.title, '1/1/$year, 1:00 AM')}}" userInput="1/1/$year, 1:00 AM" stepKey="seeStorefontOrderProductOptionData1" /> + <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($$createProduct.name$$, ProductOptionDateTime.title, '1/1/$shortYear, 1:00 AM')}}" userInput="1/1/$shortYear, 1:00 AM" stepKey="seeStorefontOrderProductOptionData1" /> <see selector="{{StorefrontCustomerOrderSection.productCustomOptions($$createProduct.name$$, ProductOptionTime.title, '1:00 AM')}}" userInput="1:00 AM" stepKey="seeStorefontOrderProductOptionTime1" /> </test> </tests> diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php index 3516754ca0710..34ce7763cbfa1 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php @@ -58,11 +58,8 @@ public function create( /** * Gives 4 places for year value in short style */ - $pattern = $formatter->getPattern(); - $dateFormat = $this->setFourYearPlaces($formatter->getPattern()); - if ($dateFormat !== $pattern) { - $formatter->setPattern($dateFormat); - } + $longYearPattern = $this->setFourYearPlaces((string)$formatter->getPattern()); + $formatter->setPattern($longYearPattern); } return $formatter; diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php index b10e05aae8030..1dfc621b1e1ea 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php @@ -307,7 +307,9 @@ public function formatDateTime( $formatter = $this->dateFormatterFactory->create( (string)($locale ?: $this->_localeResolver->getLocale()), (int)($dateType ?? \IntlDateFormatter::SHORT), - (int)($timeType ?? \IntlDateFormatter::SHORT) + (int)($timeType ?? \IntlDateFormatter::SHORT), + null, + false ); if ($timezone) { $formatter->setTimeZone($timezone); From 041c56479c3adb784f0fb21394d95deaf39482ed Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Tue, 22 Sep 2020 17:57:49 +0300 Subject: [PATCH 20/23] MC-36410: [Chrome] Loader stacks during import when the same file is checked after update --- app/code/Magento/ImportExport/i18n/en_US.csv | 2 +- .../view/adminhtml/templates/import/form/before.phtml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/ImportExport/i18n/en_US.csv b/app/code/Magento/ImportExport/i18n/en_US.csv index 9334d8c5dd348..a91a76612fd9f 100644 --- a/app/code/Magento/ImportExport/i18n/en_US.csv +++ b/app/code/Magento/ImportExport/i18n/en_US.csv @@ -127,4 +127,4 @@ Summary,Summary "File %1 deleted","File %1 deleted" "Please provide valid export file name","Please provide valid export file name" "%1 is not a valid file","%1 is not a valid file" -"Something went wrong while getting data from a file, please re-upload file","Something went wrong while getting data from a file, please re-upload file" +"Content of uploaded file was changed, please re-upload the file","Content of uploaded file was changed, please re-upload the file" diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml index 91ce6145cb80a..f18cd57c3f720 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml +++ b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml @@ -9,7 +9,7 @@ /** @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer */ $fieldNameSourceFile = \Magento\ImportExport\Model\Import::FIELD_NAME_SOURCE_FILE; $uploaderErrorMessage = $block->escapeHtml( - __('Something went wrong while getting data from a file, please re-upload file') + __('Content of uploaded file was changed, please re-upload the file') ); ?> From 050b46f1e878c04086ba44c6bb64ad204d84515e Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Wed, 23 Sep 2020 10:28:45 +0300 Subject: [PATCH 21/23] MC-37369: Datepicker issue with arabic locale on orders grid --- .../Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php index 34ce7763cbfa1..42a381535b8b9 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php @@ -18,7 +18,6 @@ class DateFormatterFactory private const CUSTOM_DATE_FORMATS = [ 'ar_SA' => [ \IntlDateFormatter::SHORT => 'd/MM/y', - \IntlDateFormatter::MEDIUM => 'MMM d, y', ] ]; From 9f166b9361fe6eff55a77a55c3dca993aed95f4a Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Wed, 23 Sep 2020 13:21:51 +0300 Subject: [PATCH 22/23] MC-36410: [Chrome] Loader stacks during import when the same file is checked after update --- .../templates/import/form/before.phtml | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml index f18cd57c3f720..d512ce8182ede 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml +++ b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml @@ -190,12 +190,30 @@ require([ postToFrame: function(newActionUrl) { var fileUploader = document.getElementById('{$fieldNameSourceFile}'); - if (fileUploader.files.length > 0 && fileUploader.files[0].lastModified !== this.loadedFileLastModified) { - alert({ - content: '{$uploaderErrorMessage}' - }); - fileUploader.value = null; - return; + if (fileUploader.files.length > 0) { + var file = fileUploader.files[0], + ifrElName = this.ifrElemName, + reader = new FileReader(); + + reader.readAsText(file, "UTF-8"); + + reader.onerror = function () { + jQuery('body').loader('hide'); + alert({ + content: '{$uploaderErrorMessage}' + }); + fileUploader.value = null; + jQuery('iframe#' + ifrElName).remove(); + return; + } + + if (file.lastModified !== this.loadedFileLastModified) { + alert({ + content: '{$uploaderErrorMessage}' + }); + fileUploader.value = null; + return; + } } if (!jQuery('[name="' + this.ifrElemName + '"]').length) { From aebb9a59d792d5df2a065f97aaead0b60452953e Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Tue, 29 Sep 2020 13:30:52 +0300 Subject: [PATCH 23/23] MC-37109: Stabilize MFTF --- .../Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml | 2 +- .../Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml index 264c55ba43390..bebf6ce5302d6 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml @@ -35,7 +35,7 @@ <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="saveAndApplyFirstPriceRule"/> <!-- Perform reindex --> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value="catalogrule_rule"/> + <argument name="indices" value=""/> </actionGroup> </before> diff --git a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml index eaebc7fdaf74a..fc17bc7f0f10a 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml @@ -21,6 +21,9 @@ </annotations> <before> <magentoCLI command="config:set {{StorefrontEnableAddStoreCodeToUrls.path}} {{StorefrontEnableAddStoreCodeToUrls.value}}" stepKey="addStoreCodeToUrlEnable"/> + <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushPageCache"> + <argument name="tags" value="full_page"/> + </actionGroup> </before> <after> <magentoCLI command="config:set {{StorefrontDisableAddStoreCodeToUrls.path}} {{StorefrontDisableAddStoreCodeToUrls.value}}" stepKey="addStoreCodeToUrlDisable"/>