From c03084cc77e96bc48c615d29ab2ac343f2762637 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Tue, 2 Jul 2019 15:09:07 +0300 Subject: [PATCH 01/12] MC-6425: [API] Order with state STATE_HOLDED should not be canceled --- .../Sales/Service/V1/OrderCancelTest.php | 24 +++++++++++++++++++ .../Magento/Sales/_files/order_state_hold.php | 14 +++++++++++ 2 files changed, 38 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/order_state_hold.php diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php index 62a44f851e405..f0d10208d885c 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php @@ -36,4 +36,28 @@ public function testOrderCancel() $result = $this->_webApiCall($serviceInfo, $requestData); $this->assertTrue($result); } + + /** + * @magentoApiDataFixture Magento/Sales/_files/order_state_hold.php + */ + public function testOrderWithStateHoldedShouldNotBeCanceled() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $order = $objectManager->get(\Magento\Sales\Model\Order::class)->loadByIncrementId('100000001'); + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/orders/' . $order->getId() . '/cancel', + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'cancel', + ], + ]; + + $requestData = ['id' => $order->getId()]; + $result = $this->_webApiCall($serviceInfo, $requestData); + $this->assertFalse($result); + } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_state_hold.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_state_hold.php new file mode 100644 index 0000000000000..a2814c0641c41 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_state_hold.php @@ -0,0 +1,14 @@ +setState(Order::STATE_HOLDED); +$order->setStatus(Order::STATE_HOLDED); +$order->save(); From c1e9db2a45b310542eed5b34485f7965efa9566f Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Tue, 2 Jul 2019 16:42:47 +0300 Subject: [PATCH 02/12] MC-6425: [API] Order with state STATE_HOLDED should not be canceled --- .../testsuite/Magento/Sales/Service/V1/OrderCancelTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php index f0d10208d885c..4fa0442720558 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php @@ -8,6 +8,10 @@ use Magento\TestFramework\TestCase\WebapiAbstract; +/** + * Class OrderCancelTest + * @package Magento\Sales\Service\V1 + */ class OrderCancelTest extends WebapiAbstract { const SERVICE_VERSION = 'V1'; From a3adb31fa73d0a62b83e9c1e4479ed61152ca6fc Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Wed, 3 Jul 2019 11:14:04 +0300 Subject: [PATCH 03/12] MC-6425: [API] Order with state STATE_HOLDED should not be canceled --- .../testsuite/Magento/Sales/Service/V1/OrderCancelTest.php | 3 +-- .../testsuite/Magento/Sales/_files/order_state_hold.php | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php index 4fa0442720558..cf295229df558 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php @@ -9,8 +9,7 @@ use Magento\TestFramework\TestCase\WebapiAbstract; /** - * Class OrderCancelTest - * @package Magento\Sales\Service\V1 + * Canceling of the order, in different states */ class OrderCancelTest extends WebapiAbstract { diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_state_hold.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_state_hold.php index a2814c0641c41..5578a55b57e8b 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/order_state_hold.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_state_hold.php @@ -3,10 +3,11 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); use Magento\Sales\Model\Order; -require 'order.php'; +require __DIR__ . '/order.php'; /** @var Order $order */ $order->setState(Order::STATE_HOLDED); From 1537251bc266b9386dcc2694957d71d5203d61f0 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Wed, 3 Jul 2019 12:38:51 +0300 Subject: [PATCH 04/12] MC-6425: [API] Order with state STATE_HOLDED should not be canceled --- .../testsuite/Magento/Sales/Service/V1/OrderCancelTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php index cf295229df558..42541099a236f 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php @@ -9,7 +9,7 @@ use Magento\TestFramework\TestCase\WebapiAbstract; /** - * Canceling of the order, in different states + * Canceling of the order */ class OrderCancelTest extends WebapiAbstract { From e8fe05400a8f5e080a860817a2ffd6a3b36c2a72 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Wed, 3 Jul 2019 15:17:14 +0300 Subject: [PATCH 05/12] MC-6425: [API] Order with state STATE_HOLDED should not be canceled --- .../Sales/Service/V1/OrderCancelTest.php | 65 ++++++++++++------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php index 42541099a236f..d030b07ba528a 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php @@ -6,6 +6,8 @@ namespace Magento\Sales\Service\V1; +use Magento\Framework\ObjectManagerInterface; +use Magento\Sales\Model\Order\Interceptor; use Magento\TestFramework\TestCase\WebapiAbstract; /** @@ -14,16 +16,40 @@ class OrderCancelTest extends WebapiAbstract { const SERVICE_VERSION = 'V1'; - const SERVICE_NAME = 'salesOrderManagementV1'; /** - * @magentoApiDataFixture Magento/Sales/_files/order.php + * @var ObjectManagerInterface */ - public function testOrderCancel() + private $objectManager; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + } + + /** + * Gets order by increment ID. + * + * @param string $incrementId + * @return Interceptor + */ + private function getOrder(string $incrementId): Interceptor + { + return $this->objectManager->get(\Magento\Sales\Model\Order::class)->loadByIncrementId($incrementId); + } + + /** + * Send API request for canceling the order + * + * @param object $order + * @return array|bool|float|int|string + */ + private function sendCancelRequest($order) { - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $order = $objectManager->get(\Magento\Sales\Model\Order::class)->loadByIncrementId('100000001'); $serviceInfo = [ 'rest' => [ 'resourcePath' => '/V1/orders/' . $order->getId() . '/cancel', @@ -36,7 +62,16 @@ public function testOrderCancel() ], ]; $requestData = ['id' => $order->getId()]; - $result = $this->_webApiCall($serviceInfo, $requestData); + return $this->_webApiCall($serviceInfo, $requestData); + } + + /** + * @magentoApiDataFixture Magento/Sales/_files/order.php + */ + public function testOrderCancel() + { + $order = $this->getOrder('100000001'); + $result = $this->sendCancelRequest($order); $this->assertTrue($result); } @@ -45,22 +80,8 @@ public function testOrderCancel() */ public function testOrderWithStateHoldedShouldNotBeCanceled() { - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $order = $objectManager->get(\Magento\Sales\Model\Order::class)->loadByIncrementId('100000001'); - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => '/V1/orders/' . $order->getId() . '/cancel', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'cancel', - ], - ]; - - $requestData = ['id' => $order->getId()]; - $result = $this->_webApiCall($serviceInfo, $requestData); + $order = $this->getOrder('100000001'); + $result = $this->sendCancelRequest($order); $this->assertFalse($result); } } From 554f2e2c3a693d6108bd20bc7e721bb6fca06fe0 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Wed, 3 Jul 2019 15:48:17 +0300 Subject: [PATCH 06/12] MC-6425: [API] Order with state STATE_HOLDED should not be canceled --- .../Magento/Sales/Service/V1/OrderCancelTest.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php index d030b07ba528a..80a6535f26330 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php @@ -7,7 +7,8 @@ namespace Magento\Sales\Service\V1; use Magento\Framework\ObjectManagerInterface; -use Magento\Sales\Model\Order\Interceptor; +use Magento\Sales\Model\Order; +use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\WebapiAbstract; /** @@ -28,27 +29,27 @@ class OrderCancelTest extends WebapiAbstract */ protected function setUp() { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->objectManager = Bootstrap::getObjectManager(); } /** * Gets order by increment ID. * * @param string $incrementId - * @return Interceptor + * @return Order */ - private function getOrder(string $incrementId): Interceptor + private function getOrder(string $incrementId): Order { - return $this->objectManager->get(\Magento\Sales\Model\Order::class)->loadByIncrementId($incrementId); + return $this->objectManager->create(Order::class)->loadByIncrementId($incrementId); } /** * Send API request for canceling the order * - * @param object $order + * @param Order $order * @return array|bool|float|int|string */ - private function sendCancelRequest($order) + private function sendCancelRequest(Order $order) { $serviceInfo = [ 'rest' => [ From 39938098b45d79edbb5b75b2f8eba60758118c25 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Thu, 4 Jul 2019 11:48:22 +0300 Subject: [PATCH 07/12] MC-6459: [API] Order with state STATE_COMPLETE should not be canceled --- .../Sales/Service/V1/OrderCancelTest.php | 61 +++++++++++++++++-- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php index 62a44f851e405..4e847ac62cf5d 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php @@ -6,21 +6,51 @@ namespace Magento\Sales\Service\V1; +use Magento\Framework\ObjectManagerInterface; +use Magento\Sales\Model\Order; +use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\WebapiAbstract; +/** + * Canceling of the order + */ class OrderCancelTest extends WebapiAbstract { const SERVICE_VERSION = 'V1'; - const SERVICE_NAME = 'salesOrderManagementV1'; /** - * @magentoApiDataFixture Magento/Sales/_files/order.php + * @var ObjectManagerInterface */ - public function testOrderCancel() + private $objectManager; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + } + + /** + * Gets order by increment ID. + * + * @param string $incrementId + * @return Order + */ + private function getOrder(string $incrementId): Order + { + return $this->objectManager->create(Order::class)->loadByIncrementId($incrementId); + } + + /** + * Send API request for canceling the order + * + * @param Order $order + * @return array|bool|float|int|string + */ + private function sendCancelRequest(Order $order) { - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $order = $objectManager->get(\Magento\Sales\Model\Order::class)->loadByIncrementId('100000001'); $serviceInfo = [ 'rest' => [ 'resourcePath' => '/V1/orders/' . $order->getId() . '/cancel', @@ -33,7 +63,26 @@ public function testOrderCancel() ], ]; $requestData = ['id' => $order->getId()]; - $result = $this->_webApiCall($serviceInfo, $requestData); + return $this->_webApiCall($serviceInfo, $requestData); + } + + /** + * @magentoApiDataFixture Magento/Sales/_files/order.php + */ + public function testOrderCancel() + { + $order = $this->getOrder('100000001'); + $result = $this->sendCancelRequest($order); $this->assertTrue($result); } + + /** + * @magentoApiDataFixture Magento/Sales/_files/order_with_shipping_and_invoice.php + */ + public function testOrderWithStateCompleteShouldNotBeCanceled() + { + $order = $this->getOrder('100000001'); + $result = $this->sendCancelRequest($order); + $this->assertFalse($result); + } } From 5cc44b729e152ebba52e07fbc4cf77d4cbdccf2c Mon Sep 17 00:00:00 2001 From: Andrii Meysar Date: Tue, 9 Jul 2019 16:05:46 +0300 Subject: [PATCH 08/12] MC-6420: Ship Order API. Two bundle products with ship bundle items set to separately in order --- .../Sales/Service/V1/ShipOrderTest.php | 159 +++++++++++++++--- ...der_with_2_bundles_shipping_separately.php | 84 +++++++++ ...2_bundles_shipping_separately_rollback.php | 8 + ...bundle_products_with_separate_shipping.php | 102 +++++++++++ ...oducts_with_separate_shipping_rollback.php | 28 +++ 5 files changed, 354 insertions(+), 27 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping_rollback.php diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php index e2a156cc6fbfc..ccbeadecdb62a 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php @@ -5,6 +5,12 @@ */ namespace Magento\Sales\Service\V1; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Sales\Api\Data\OrderItemInterface; +use Magento\Sales\Api\ShipmentRepositoryInterface; +use Magento\Sales\Model\Order; + /** * API test for creation of Shipment for certain Order. */ @@ -14,22 +20,28 @@ class ShipOrderTest extends \Magento\TestFramework\TestCase\WebapiAbstract const SERVICE_VERSION = 'V1'; /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ private $objectManager; /** - * @var \Magento\Sales\Api\ShipmentRepositoryInterface + * @var ShipmentRepositoryInterface */ private $shipmentRepository; + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @inheritdoc + */ protected function setUp() { $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - - $this->shipmentRepository = $this->objectManager->get( - \Magento\Sales\Api\ShipmentRepositoryInterface::class - ); + $this->shipmentRepository = $this->objectManager->get(ShipmentRepositoryInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); } /** @@ -40,9 +52,8 @@ public function testConfigurableShipOrder() $this->markTestIncomplete('https://github.com/magento-engcom/msi/issues/1335'); $productsQuantity = 1; - /** @var \Magento\Sales\Model\Order $existingOrder */ - $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) - ->loadByIncrementId('100000001'); + /** @var Order $existingOrder */ + $existingOrder = $this->getOrder('100000001'); $requestData = [ 'orderId' => $existingOrder->getId(), @@ -83,9 +94,8 @@ public function testConfigurableShipOrder() */ public function testShipOrder() { - /** @var \Magento\Sales\Model\Order $existingOrder */ - $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) - ->loadByIncrementId('100000001'); + /** @var Order $existingOrder */ + $existingOrder = $this->getOrder('100000001'); $requestData = [ 'orderId' => $existingOrder->getId(), @@ -103,7 +113,7 @@ public function testShipOrder() ] ]; - /** @var \Magento\Sales\Api\Data\OrderItemInterface $item */ + /** @var OrderItemInterface $item */ foreach ($existingOrder->getAllItems() as $item) { $requestData['items'][] = [ 'order_item_id' => $item->getItemId(), @@ -121,9 +131,8 @@ public function testShipOrder() $this->fail('Failed asserting that Shipment was created'); } - /** @var \Magento\Sales\Model\Order $updatedOrder */ - $updatedOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) - ->loadByIncrementId('100000001'); + /** @var Order $updatedOrder */ + $updatedOrder = $this->getOrder('100000001'); $this->assertNotEquals( $existingOrder->getStatus(), @@ -144,9 +153,8 @@ public function testShipOrderWithoutTrackingNumberReturnsError() { $this->_markTestAsRestOnly('SOAP requires an tracking number to be provided so this case is not possible.'); - /** @var \Magento\Sales\Model\Order $existingOrder */ - $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) - ->loadByIncrementId('100000001'); + /** @var Order $existingOrder */ + $existingOrder = $this->getOrder('100000001'); $requestData = [ 'orderId' => $existingOrder->getId(), @@ -170,9 +178,7 @@ public function testShipOrderWithoutTrackingNumberReturnsError() */ public function testPartialShipOrderWithBundleShippedSeparately() { - /** @var \Magento\Sales\Model\Order $existingOrder */ - $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) - ->loadByIncrementId('100000001'); + $existingOrder = $this->getOrder('100000001'); $requestData = [ 'orderId' => $existingOrder->getId(), @@ -213,9 +219,8 @@ public function testPartialShipOrderWithBundleShippedSeparately() $this->assertEquals(1, $shipment->getTotalQty()); - /** @var \Magento\Sales\Model\Order $existingOrder */ - $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) - ->loadByIncrementId('100000001'); + /** @var Order $existingOrder */ + $existingOrder = $this->getOrder('100000001'); foreach ($existingOrder->getAllItems() as $item) { if ($item->getItemId() == $shippedItemId) { @@ -227,10 +232,75 @@ public function testPartialShipOrderWithBundleShippedSeparately() } /** - * @param \Magento\Sales\Model\Order $order + * @magentoApiDataFixture Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php + */ + public function testPartialShipOrderWithTwoBundleShippedSeparatelyContainsSameSimple() + { + /** @var Order $order */ + $order = $this->getOrder('order_bundle_separately_shipped'); + + $requestData = [ + 'orderId' => $order->getId(), + 'items' => [], + 'comment' => [ + 'comment' => 'Test Comment', + 'is_visible_on_front' => 1, + ], + 'tracks' => [] + ]; + + $shippedItemId = null; + $parentItemId = null; + foreach ($order->getAllItems() as $item) { + if ($item->getSku() === 'simple1') { + $requestData['items'][] = [ + 'order_item_id' => $item->getItemId(), + 'qty' => $item->getQtyOrdered(), + ]; + $shippedItemId = $item->getItemId(); + $parentItemId = $item->getParentItemId(); + break; + } + } + + $shipmentId = $this->_webApiCall($this->getServiceInfo($order), $requestData); + $this->assertNotEmpty($shipmentId); + + try { + $shipment = $this->shipmentRepository->get($shipmentId); + } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + $this->fail('Failed asserting that Shipment was created'); + } + + $this->assertEquals(1, $shipment->getTotalQty()); + + /** @var Order $existingOrder */ + $order = $this->getOrder('order_bundle_separately_shipped'); + + foreach ($order->getAllItems() as $item) { + if (in_array($item->getItemId(), [$shippedItemId, $parentItemId])) { + $this->assertEquals(1, $item->getQtyShipped()); + continue; + } + $this->assertEquals(0, $item->getQtyShipped()); + } + + try { + $this->_webApiCall($this->getServiceInfo($order), $requestData); + $this->fail('Expected exception was not raised'); + } catch (\Exception $exception) { + $this->assertExceptionMessage( + $exception, + 'Shipment Document Validation Error(s): You can\'t create a shipment without products.' + ); + } + } + + /** + * @param Order $order * @return array */ - private function getServiceInfo(\Magento\Sales\Model\Order $order) + private function getServiceInfo(Order $order): array { $serviceInfo = [ 'rest' => [ @@ -243,6 +313,41 @@ private function getServiceInfo(\Magento\Sales\Model\Order $order) 'operation' => self::SERVICE_READ_NAME . 'execute', ], ]; + return $serviceInfo; } + + /** + * Returns order by increment id. + * + * @param string $incrementId + * @return Order + */ + private function getOrder(string $incrementId): Order + { + return $this->objectManager->create(Order::class)->loadByIncrementId($incrementId); + } + + /** + * Assert correct exception message. + * + * @param \Exception $exception + * @param string $expectedMessage + * @return void + */ + private function assertExceptionMessage(\Exception $exception, string $expectedMessage): void + { + $actualMessage = ''; + switch (TESTS_WEB_API_ADAPTER) { + case self::ADAPTER_SOAP: + $actualMessage = trim(preg_replace('/\s+/', ' ', $exception->getMessage())); + break; + case self::ADAPTER_REST: + $error = $this->processRestExceptionResult($exception); + $actualMessage = $error['message']; + break; + } + + $this->assertEquals($expectedMessage, $actualMessage); + } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php new file mode 100644 index 0000000000000..f2f0a99e31507 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php @@ -0,0 +1,84 @@ +create(\Magento\Quote\Model\Quote\Address::class, ['data' => $addressData]); +$billingAddress->setAddressType('billing'); + +$shippingAddress = clone $billingAddress; +$shippingAddress->setId(null)->setAddressType('shipping')->setShippingMethod('flatrate_flatrate'); + +/** @var \Magento\Quote\Model\Quote\Payment $payment */ +$payment = $objectManager->create(\Magento\Quote\Model\Quote\Payment::class); +$payment->setMethod('checkmo'); + +/** @var \Magento\Catalog\Model\ProductRepository $productRepository */ +$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + +$bundleProduct = $productRepository->get('bundle-product-separate-shipping-1'); +$bundleProduct2 = $productRepository->get('bundle-product-separate-shipping-2'); +$selectionProducts = [ + $bundleProduct->getId() => [10, 12], + $bundleProduct2->getId() => [11, 13], +]; + +/** @var $cart \Magento\Checkout\Model\Cart */ +$cart = $objectManager->create(\Magento\Checkout\Model\Cart::class); + +foreach ([$bundleProduct, $bundleProduct2] as $product) { + + /** @var $typeInstance \Magento\Bundle\Model\Product\Type */ + $typeInstance = $product->getTypeInstance(); + $typeInstance->setStoreFilter($product->getStoreId(), $product); + $optionCollection = $typeInstance->getOptionsCollection($product); + + $bundleOptions = []; + $bundleOptionsQty = []; + $optionsData = []; + foreach ($optionCollection as $option) { + /** @var $option \Magento\Bundle\Model\Option */ + $selectionsCollection = $typeInstance->getSelectionsCollection([$option->getId()], $product); + $selectionIds = $selectionProducts[$product->getId()]; + $selectionsCollection->addIdFilter($selectionIds); + + foreach ($selectionIds as $productId) { + $selection = $selectionsCollection->getItemByColumnValue('product_id', $productId); + if ($selection !== null) { + $bundleOptions[$option->getId()] = $selection->getSelectionId(); + $optionsData[$option->getId()] = $selection->getProductId(); + $bundleOptionsQty[$option->getId()] = 1; + } + } + } + + $requestInfo = [ + 'product' => $product->getId(), + 'bundle_option' => $bundleOptions, + 'bundle_option_qty' => $bundleOptionsQty, + 'qty' => 1, + ]; + + $cart->addProduct($product, $requestInfo); +} + +$cart->getQuote() + ->setReservedOrderId('order_bundle_separately_shipped') + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setCheckoutMethod(\Magento\Quote\Api\CartManagementInterface::METHOD_GUEST) + ->setPayment($payment); +$cart->save(); + +/** @var \Magento\Quote\Model\QuoteManagement $quoteManager */ +$quoteManager = $objectManager->get(\Magento\Quote\Model\QuoteManagement::class); +$orderId = $quoteManager->placeOrder($cart->getQuote()->getId()); + +$objectManager->removeSharedInstance(\Magento\Checkout\Model\Session::class); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately_rollback.php new file mode 100644 index 0000000000000..96e3adb65a7d6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately_rollback.php @@ -0,0 +1,8 @@ +create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +/** @var \Magento\Catalog\Model\ProductFactory $productFactory */ +$productFactory = $objectManager->create(\Magento\Catalog\Model\ProductFactory::class); +/** @var \Magento\Bundle\Api\Data\OptionInterfaceFactory $bundleOptionFactory */ +$bundleOptionFactory = $objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class); +/** @var \Magento\Bundle\Api\Data\LinkInterfaceFactory $bundleLinkFactory */ +$bundleLinkFactory = $objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class); + +/** @var $bundleProduct \Magento\Catalog\Model\Product */ +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) + ->setAttributeSetId(4) + ->setWebsiteIds([1]) + ->setName('Bundle Product With Separate Items Shipping') + ->setSku('bundle-product-separate-shipping-1') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(1) + ->setPriceType(1) + ->setPrice(10.0) + ->setShipmentType(1) + ->setBundleOptionsData( + [ + [ + 'title' => 'Option 1', + 'default_title' => 'Option 1', + 'type' => 'radio', + 'required' => 1, + 'delete' => '', + ], + [ + 'title' => 'Option 2', + 'default_title' => 'Option 2', + 'type' => 'radio', + 'required' => 1, + 'delete' => '', + ], + ] + )->setBundleSelectionsData( + [ + [ + ['product_id' => 10, 'selection_qty' => 1, 'selection_can_change_qty' => 1, 'delete' => ''], + ['product_id' => 11, 'selection_qty' => 1, 'selection_can_change_qty' => 1, 'delete' => ''], + ], + [ + ['product_id' => 12, 'selection_qty' => 1, 'selection_can_change_qty' => 1, 'delete' => ''], + ['product_id' => 13, 'selection_qty' => 1, 'selection_can_change_qty' => 1, 'delete' => ''], + ], + ] + ); + +$bundleProduct2 = $productFactory->create(['data' => $bundleProduct->getData()]); +$bundleProduct2 + ->setName('Bundle Product With Separate Items Shipping Two') + ->setSku('bundle-product-separate-shipping-2'); + +foreach ([$bundleProduct, $bundleProduct2] as $product) { + if ($product->getBundleOptionsData()) { + $options = []; + foreach ($product->getBundleOptionsData() as $key => $optionData) { + if (!(bool)$optionData['delete']) { + $option = $bundleOptionFactory->create(['data' => $optionData]); + $option->setSku($product->getSku()); + $option->setOptionId(null); + + $links = []; + $bundleLinks = $product->getBundleSelectionsData(); + if (!empty($bundleLinks[$key])) { + foreach ($bundleLinks[$key] as $linkData) { + if (!(bool)$linkData['delete']) { + $link = $bundleLinkFactory->create(['data' => $linkData]); + $linkProduct = $productRepository->getById($linkData['product_id']); + $link->setSku($linkProduct->getSku()); + $link->setQty($linkData['selection_qty']); + $links[] = $link; + } + } + $option->setProductLinks($links); + $options[] = $option; + } + } + } + $extension = $product->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $product->setExtensionAttributes($extension); + } + + $productRepository->save($product, true); +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping_rollback.php new file mode 100644 index 0000000000000..19f73060c5ca6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping_rollback.php @@ -0,0 +1,28 @@ +get(\Magento\Framework\Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); + +try { + $productRepository->deleteById('bundle-product-separate-shipping-1'); + $productRepository->deleteById('bundle-product-separate-shipping-2'); +} catch (\Magento\Framework\Exception\NoSuchEntityException $exception) { + // When DbIsolation is used products can be already removed by rollback main transaction +} + +$registry->register('isSecureArea', false); + +require __DIR__ . '/multiple_products_rollback.php'; From 69761aea095f60c1585bdfbf5d030090d0a09b06 Mon Sep 17 00:00:00 2001 From: Andrii Meysar Date: Wed, 10 Jul 2019 10:02:17 +0300 Subject: [PATCH 09/12] MC-6420: Ship Order API. Two bundle products with ship bundle items set to separately in order --- .../Sales/Service/V1/ShipOrderTest.php | 4 +- ...der_with_2_bundles_shipping_separately.php | 43 ++++++++++++------- ...bundle_products_with_separate_shipping.php | 43 ++++++++++++------- ...oducts_with_separate_shipping_rollback.php | 17 +++++--- 4 files changed, 68 insertions(+), 39 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php index ccbeadecdb62a..049f49c93c7cd 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php @@ -236,7 +236,6 @@ public function testPartialShipOrderWithBundleShippedSeparately() */ public function testPartialShipOrderWithTwoBundleShippedSeparatelyContainsSameSimple() { - /** @var Order $order */ $order = $this->getOrder('order_bundle_separately_shipped'); $requestData = [ @@ -246,7 +245,7 @@ public function testPartialShipOrderWithTwoBundleShippedSeparatelyContainsSameSi 'comment' => 'Test Comment', 'is_visible_on_front' => 1, ], - 'tracks' => [] + 'tracks' => [], ]; $shippedItemId = null; @@ -274,7 +273,6 @@ public function testPartialShipOrderWithTwoBundleShippedSeparatelyContainsSameSi $this->assertEquals(1, $shipment->getTotalQty()); - /** @var Order $existingOrder */ $order = $this->getOrder('order_bundle_separately_shipped'); foreach ($order->getAllItems() as $item) { diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php index f2f0a99e31507..11d99ef59f911 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php @@ -5,23 +5,35 @@ */ declare(strict_types=1); -$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +use Magento\Bundle\Model\Option; +use Magento\Bundle\Model\Product\Type as BundleProductType; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Checkout\Model\Cart; +use Magento\Checkout\Model\Session; +use Magento\Quote\Api\CartManagementInterface; +use Magento\Quote\Model\Quote\Address; +use Magento\Quote\Model\Quote\Payment; +use Magento\Quote\Model\QuoteManagement; +use Magento\TestFramework\Helper\Bootstrap; require __DIR__ . '/two_bundle_products_with_separate_shipping.php'; $addressData = include __DIR__ . '/../../../Magento/Sales/_files/address_data.php'; -$billingAddress = $objectManager->create(\Magento\Quote\Model\Quote\Address::class, ['data' => $addressData]); +$objectManager = Bootstrap::getObjectManager(); +$billingAddress = $objectManager->create(Address::class, ['data' => $addressData]); $billingAddress->setAddressType('billing'); $shippingAddress = clone $billingAddress; -$shippingAddress->setId(null)->setAddressType('shipping')->setShippingMethod('flatrate_flatrate'); +$shippingAddress->setId(null) + ->setAddressType('shipping') + ->setShippingMethod('flatrate_flatrate'); -/** @var \Magento\Quote\Model\Quote\Payment $payment */ -$payment = $objectManager->create(\Magento\Quote\Model\Quote\Payment::class); +/** @var Payment $payment */ +$payment = $objectManager->create(Payment::class); $payment->setMethod('checkmo'); -/** @var \Magento\Catalog\Model\ProductRepository $productRepository */ -$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(ProductRepositoryInterface::class); $bundleProduct = $productRepository->get('bundle-product-separate-shipping-1'); $bundleProduct2 = $productRepository->get('bundle-product-separate-shipping-2'); @@ -30,12 +42,12 @@ $bundleProduct2->getId() => [11, 13], ]; -/** @var $cart \Magento\Checkout\Model\Cart */ -$cart = $objectManager->create(\Magento\Checkout\Model\Cart::class); +/** @var Cart $cart */ +$cart = $objectManager->create(Cart::class); foreach ([$bundleProduct, $bundleProduct2] as $product) { - /** @var $typeInstance \Magento\Bundle\Model\Product\Type */ + /** @var BundleProductType $typeInstance */ $typeInstance = $product->getTypeInstance(); $typeInstance->setStoreFilter($product->getStoreId(), $product); $optionCollection = $typeInstance->getOptionsCollection($product); @@ -43,8 +55,9 @@ $bundleOptions = []; $bundleOptionsQty = []; $optionsData = []; + + /** @var Option $option */ foreach ($optionCollection as $option) { - /** @var $option \Magento\Bundle\Model\Option */ $selectionsCollection = $typeInstance->getSelectionsCollection([$option->getId()], $product); $selectionIds = $selectionProducts[$product->getId()]; $selectionsCollection->addIdFilter($selectionIds); @@ -73,12 +86,12 @@ ->setReservedOrderId('order_bundle_separately_shipped') ->setBillingAddress($billingAddress) ->setShippingAddress($shippingAddress) - ->setCheckoutMethod(\Magento\Quote\Api\CartManagementInterface::METHOD_GUEST) + ->setCheckoutMethod(CartManagementInterface::METHOD_GUEST) ->setPayment($payment); $cart->save(); -/** @var \Magento\Quote\Model\QuoteManagement $quoteManager */ -$quoteManager = $objectManager->get(\Magento\Quote\Model\QuoteManagement::class); +/** @var QuoteManagement $quoteManager */ +$quoteManager = $objectManager->get(QuoteManagement::class); $orderId = $quoteManager->placeOrder($cart->getQuote()->getId()); -$objectManager->removeSharedInstance(\Magento\Checkout\Model\Session::class); +$objectManager->removeSharedInstance(Session::class); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping.php index e1dd3b23666bb..5521b16354085 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping.php @@ -5,31 +5,44 @@ */ declare(strict_types=1); +use Magento\Bundle\Api\Data\LinkInterfaceFactory; +use Magento\Bundle\Api\Data\OptionInterfaceFactory; +use Magento\Bundle\Model\Product\Price as BundlePrice; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type as BundleProductType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\TestFramework\Helper\Bootstrap; + require __DIR__ . '/multiple_products.php'; -$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +$objectManager = Bootstrap::getObjectManager(); + +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(ProductRepositoryInterface::class); + +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->create(ProductFactory::class); + +/** @var OptionInterfaceFactory $bundleOptionFactory */ +$bundleOptionFactory = $objectManager->create(OptionInterfaceFactory::class); -/** @var \Magento\Catalog\Model\ProductRepository $productRepository */ -$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); -/** @var \Magento\Catalog\Model\ProductFactory $productFactory */ -$productFactory = $objectManager->create(\Magento\Catalog\Model\ProductFactory::class); -/** @var \Magento\Bundle\Api\Data\OptionInterfaceFactory $bundleOptionFactory */ -$bundleOptionFactory = $objectManager->create(\Magento\Bundle\Api\Data\OptionInterfaceFactory::class); -/** @var \Magento\Bundle\Api\Data\LinkInterfaceFactory $bundleLinkFactory */ -$bundleLinkFactory = $objectManager->create(\Magento\Bundle\Api\Data\LinkInterfaceFactory::class); +/** @var LinkInterfaceFactory $bundleLinkFactory */ +$bundleLinkFactory = $objectManager->create(LinkInterfaceFactory::class); -/** @var $bundleProduct \Magento\Catalog\Model\Product */ $bundleProduct = $productFactory->create(); -$bundleProduct->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) - ->setAttributeSetId(4) +$attributeSetId = $bundleProduct->getDefaultAttributeSetId(); +$bundleProduct->setTypeId(BundleProductType::TYPE_BUNDLE) + ->setAttributeSetId($attributeSetId) ->setWebsiteIds([1]) ->setName('Bundle Product With Separate Items Shipping') ->setSku('bundle-product-separate-shipping-1') - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->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(1) - ->setPriceType(1) + ->setPriceType(BundlePrice::PRICE_TYPE_FIXED) ->setPrice(10.0) ->setShipmentType(1) ->setBundleOptionsData( diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping_rollback.php index 19f73060c5ca6..c2c4d992d763e 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/two_bundle_products_with_separate_shipping_rollback.php @@ -5,21 +5,26 @@ */ declare(strict_types=1); -$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\TestFramework\Helper\Bootstrap; -/** @var \Magento\Framework\Registry $registry */ -$registry = $objectManager->get(\Magento\Framework\Registry::class); +$objectManager = Bootstrap::getObjectManager(); + +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); $registry->unregister('isSecureArea'); $registry->register('isSecureArea', true); -/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ -$productRepository = $objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); try { $productRepository->deleteById('bundle-product-separate-shipping-1'); $productRepository->deleteById('bundle-product-separate-shipping-2'); -} catch (\Magento\Framework\Exception\NoSuchEntityException $exception) { +} catch (NoSuchEntityException $exception) { // When DbIsolation is used products can be already removed by rollback main transaction } From ec0e89f9024e743faa29167cf61b71ad49ebf304 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra Date: Thu, 11 Jul 2019 15:48:23 +0300 Subject: [PATCH 10/12] MAGETWO-97216: Random fail of test "Add products to wishlist from different stores" --- .../DeleteCustomStoreActionGroup.xml | 4 +- ...AddMultipleStoreProductsToWishlistTest.xml | 44 ++++++++++++------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Store/Test/Mftf/ActionGroup/DeleteCustomStoreActionGroup.xml b/app/code/Magento/Store/Test/Mftf/ActionGroup/DeleteCustomStoreActionGroup.xml index 8a1d830661aad..70fc08528f85e 100644 --- a/app/code/Magento/Store/Test/Mftf/ActionGroup/DeleteCustomStoreActionGroup.xml +++ b/app/code/Magento/Store/Test/Mftf/ActionGroup/DeleteCustomStoreActionGroup.xml @@ -22,6 +22,8 @@ + + @@ -52,4 +54,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontAddMultipleStoreProductsToWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontAddMultipleStoreProductsToWishlistTest.xml index ede63322235f2..e8b645990390e 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontAddMultipleStoreProductsToWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontAddMultipleStoreProductsToWishlistTest.xml @@ -10,16 +10,14 @@ - + <description value="All products added to wishlist should be visible on any store. Even if product visibility was set to 'Not Visible Individually' for this store"/> <group value="wishlist"/> <severity value="AVERAGE"/> - <testCaseId value="MAGETWO-95678"/> - <skip> - <issueId value="MC-13867"/> - </skip> + <testCaseId value="MC-6243"/> </annotations> + <before> <createData entity="customStoreGroup" stepKey="storeGroup"/> <createData entity="SimpleSubCategory" stepKey="categoryHandle"/> @@ -36,6 +34,7 @@ <argument name="storeGroupName" value="$$storeGroup.group[name]$$"/> </actionGroup> </before> + <after> <deleteData createDataKey="product" stepKey="deleteFirstProduct"/> <deleteData createDataKey="secondProduct" stepKey="deleteSecondProduct"/> @@ -43,8 +42,16 @@ <actionGroup ref="DeleteCustomStoreActionGroup" stepKey="deleteCustomStoreGroup"> <argument name="storeGroupName" value="$$storeGroup.group[name]$$"/> </actionGroup> - <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + <actionGroup ref="clearFiltersAdminDataGrid" stepKey="clearWebsitesGridFilter"/> + + <!--Clear products filter--> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> + <actionGroup ref="clearFiltersAdminDataGrid" stepKey="clearProductsFilters"/> + <!--Logout everywhere--> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> </after> + <!-- Change products visibility on store-view level --> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForProduct1"> <argument name="product" value="$$product$$"/> @@ -52,7 +59,9 @@ <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openEditProduct1"> <argument name="product" value="$$product$$"/> </actionGroup> + <scrollToTopOfPage stepKey="scrollToTopToChangeStore"/> <click selector="{{AdminProductFormActionSection.changeStoreButton}}" stepKey="clickSwitchStoreMenuForProduct1"/> + <waitForElementVisible selector="{{AdminProductFormChangeStoreSection.storeSelector(customStore.name)}}" stepKey="waitCustomStoreItemAppers"/> <click selector="{{AdminProductFormChangeStoreSection.storeSelector(customStore.name)}}" stepKey="clickOnStoreNameItemForProduct1"/> <waitForElementVisible selector="{{AdminProductFormChangeStoreSection.acceptButton}}" stepKey="waitAcceptStoreSwitchingForProduct1n"/> <click selector="{{AdminProductFormChangeStoreSection.acceptButton}}" stepKey="acceptStoreSwitchingForProduct1"/> @@ -65,36 +74,37 @@ <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openEditProduct2"> <argument name="product" value="$$secondProduct$$"/> </actionGroup> + <scrollToTopOfPage stepKey="scrollToTopToChangeStoreAgain"/> <click selector="{{AdminProductFormActionSection.changeStoreButton}}" stepKey="clickSwitchStoreMenuForProduct2"/> + <waitForElementVisible selector="{{AdminProductFormChangeStoreSection.storeSelector(customStore.name)}}" stepKey="waitDefaultStoreItemAppers"/> <click selector="{{AdminProductFormChangeStoreSection.storeSelector('Default Store View')}}" stepKey="clickOnStoreNameItemForProduct2"/> <waitForElementVisible selector="{{AdminProductFormChangeStoreSection.acceptButton}}" stepKey="waitAcceptStoreSwitchingForProduct2"/> <click selector="{{AdminProductFormChangeStoreSection.acceptButton}}" stepKey="acceptStoreSwitchingForProduct2"/> <click selector="{{AdminProductFormSection.visibilityUseDefault}}" stepKey="uncheckVisibilityUseDefaultValueForProduct2"/> <selectOption userInput="Not Visible Individually" selector="{{AdminProductFormSection.visibility}}" stepKey="makeProductNotVisibleOnDefaultStoreView"/> <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveEditedProductForProduct2"/> + <!-- Sign in as customer --> - <amOnPage url="{{StorefrontCustomerSignInPage.url}}" stepKey="amOnSignInPage"/> - <fillField userInput="$$customer.email$$" selector="{{StorefrontCustomerSignInFormSection.emailField}}" stepKey="fillEmail"/> - <fillField userInput="$$customer.password$$" selector="{{StorefrontCustomerSignInFormSection.passwordField}}" stepKey="fillPassword"/> - <waitForElementVisible selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}" stepKey="waitForButton"/> - <click selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}" stepKey="clickSignInAccountButton"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> + <argument name="Customer" value="$$customer$$" /> + </actionGroup> <see userInput="$$customer.firstname$$" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}" stepKey="seeFirstName"/> <see userInput="$$customer.lastname$$" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}" stepKey="seeLastName"/> <see userInput="$$customer.email$$" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}" stepKey="seeEmail"/> <!-- Add product visible on default store to wishlist --> - <amOnPage url="$$product.name$$.html" stepKey="navigateToProductPageOnDefaultStore"/> + <amOnPage url="{{StorefrontProductPage.url($$product.custom_attributes[url_key]$$)}}" stepKey="navigateToProductPageOnDefaultStore"/> <see userInput="$$product.name$$" selector="{{StorefrontProductInfoMainSection.productName}}" stepKey="assertFirstProductNameTitle"/> <click selector="{{StorefrontProductPageSection.addToWishlist}}" stepKey="addFirstProductToWishlist"/> <!-- Switch to second store and add second product (visible on second store) to wishlist --> - <click selector="{{StorefrontFooterSection.switchStoreButton}}" stepKey="ClickSwitchStoreButtonOnDefaultStore"/> - <click selector="{{StorefrontFooterSection.storeLink($$storeGroup.group[name]$$)}}" stepKey="SelectSecondStoreToSwitchOn"/> + <click selector="{{StorefrontFooterSection.switchStoreButton}}" stepKey="clickSwitchStoreButtonOnDefaultStore"/> + <click selector="{{StorefrontFooterSection.storeLink($$storeGroup.group[name]$$)}}" stepKey="selectSecondStoreToSwitchOn"/> <!-- Verify that both products are visible in wishlist on both stores --> - <amOnPage url="$$secondProduct.name$$.html" stepKey="navigateToProductPageOnSecondStore"/> + <amOnPage url="{{StorefrontProductPage.url($$secondProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToProductPageOnSecondStore"/> <see userInput="$$secondProduct.name$$" selector="{{StorefrontProductInfoMainSection.productName}}" stepKey="assertSecondProductNameTitle"/> <click selector="{{StorefrontProductPageSection.addToWishlist}}" stepKey="addSecondProductToWishlist"/> <see userInput="$$secondProduct.name$$" selector="{{StorefrontCustomerWishlistSection.productItemNameText}}" stepKey="seeProduct2InWishlistOnSecondStore"/> - <click selector="{{StorefrontFooterSection.switchStoreButton}}" stepKey="ClickSwitchStoreButtonOnSecondStore"/> - <click selector="{{StorefrontFooterSection.storeLink('Main Website Store')}}" stepKey="SelectDefaultStoreToSwitchOn"/> + <click selector="{{StorefrontFooterSection.switchStoreButton}}" stepKey="clickSwitchStoreButtonOnSecondStore"/> + <click selector="{{StorefrontFooterSection.storeLink('Main Website Store')}}" stepKey="selectDefaultStoreToSwitchOn"/> <see userInput="$$product.name$$" selector="{{StorefrontCustomerWishlistSection.productItemNameText}}" stepKey="seeProduct1InWishlistOnDefaultStore"/> </test> </tests> From 3708732c8f64fa9d87b9230e56faaa19de05199a Mon Sep 17 00:00:00 2001 From: Nikita Fomin <nikita.fomin@transoftgroup.com> Date: Mon, 29 Jul 2019 11:06:47 +0300 Subject: [PATCH 11/12] MC-227: Customer should be able to see search results when searching for bundle products by keyword --- .../Bundle/Test/Mftf/Data/ProductData.xml | 31 ++++ ...omerSearchBundleProductsByKeywordsTest.xml | 137 ++++++++++++++++++ .../Test/Mftf/Data/CustomAttributeData.xml | 16 ++ .../StorefrontCatalogSearchActionGroup.xml | 7 + 4 files changed, 191 insertions(+) create mode 100644 app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSearchBundleProductsByKeywordsTest.xml diff --git a/app/code/Magento/Bundle/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Bundle/Test/Mftf/Data/ProductData.xml index 5034c72b9ee3f..6e7e4a7a16573 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Data/ProductData.xml @@ -107,4 +107,35 @@ <requiredEntity type="custom_attribute">CustomAttributeDynamicPrice</requiredEntity> <requiredEntity type="custom_attribute">CustomAttributePriceViewRange</requiredEntity> </entity> + <entity name="DynamicBundleProductCustomDescription" type="product2"> + <data key="name" unique="suffix">Test 123 Dynamic </data> + <data key="sku" unique="suffix">test-dynamic-bundle-product</data> + <data key="type_id">bundle</data> + <data key="attribute_set_id">4</data> + <data key="visibility">4</data> + <data key="status">1</data> + <data key="urlKey" unique="suffix">test-dynamic-bundle-product</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute">CustomDynamicProductDescription</requiredEntity> + <requiredEntity type="custom_attribute">CustomDynamicProductShortDescription</requiredEntity> + <requiredEntity type="custom_attribute">CustomAttributeDynamicPrice</requiredEntity> + <requiredEntity type="custom_attribute">CustomAttributePriceViewRange</requiredEntity> + </entity> + <entity name="FixedBundleProductCustomDescription" type="product2"> + <data key="name" unique="suffix">Test 123 Fixed </data> + <data key="sku" unique="suffix">test-fixed-bundle-product</data> + <data key="type_id">bundle</data> + <data key="attribute_set_id">4</data> + <data key="price">10</data> + <data key="visibility">4</data> + <data key="status">1</data> + <data key="urlKey" unique="suffix">api-fixed-bundle-product</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute">CustomFixedProductDescription</requiredEntity> + <requiredEntity type="custom_attribute">CustomFixedProductShortDescription</requiredEntity> + <requiredEntity type="custom_attribute">CustomAttributePriceView</requiredEntity> + <requiredEntity type="custom_attribute">CustomAttributeFixPrice</requiredEntity> + <requiredEntity type="custom_attribute">CustomAttributeFixWeight</requiredEntity> + <requiredEntity type="custom_attribute">CustomAttributeFixSku</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSearchBundleProductsByKeywordsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSearchBundleProductsByKeywordsTest.xml new file mode 100644 index 0000000000000..d27cd0df88239 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSearchBundleProductsByKeywordsTest.xml @@ -0,0 +1,137 @@ +<?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="StorefrontCustomerSearchBundleProductsByKeywordsTest"> + <annotations> + <features value="Bundle"/> + <stories value="Bundle products list on Storefront"/> + <title value="Customer should be able to see search results when searching for bundle products by keyword"/> + <description value="Customer should be able to see search results when searching for bundle products by keyword"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-227"/> + <group value="bundle"/> + </annotations> + <before> + <createData entity="SimpleProductNotVisibleIndividually" stepKey="createSimpleProduct"/> + <createData entity="DynamicBundleProductCustomDescription" stepKey="createDynamicBundle"/> + <createData entity="DropDownBundleOption" stepKey="dynamicBundleOption"> + <requiredEntity createDataKey="createDynamicBundle"/> + </createData> + <createData entity="ApiBundleLink" stepKey="createDynamicBundleLink"> + <requiredEntity createDataKey="createDynamicBundle"/> + <requiredEntity createDataKey="dynamicBundleOption"/> + <requiredEntity createDataKey="createSimpleProduct"/> + </createData> + <createData entity="SimpleProductNotVisibleIndividually" stepKey="createSimpleProductTwo"/> + <createData entity="FixedBundleProductCustomDescription" stepKey="createFixedBundle"/> + <createData entity="DropDownBundleOption" stepKey="fixedBundleOption"> + <requiredEntity createDataKey="createFixedBundle"/> + </createData> + <createData entity="ApiBundleLink" stepKey="createFixedBundleLink"> + <requiredEntity createDataKey="createFixedBundle"/> + <requiredEntity createDataKey="fixedBundleOption"/> + <requiredEntity createDataKey="createSimpleProductTwo"/> + </createData> + <magentoCLI command="indexer:reindex" arguments="cataloginventory_stock catalogsearch_fulltext" stepKey="reindex"/> + </before> + <after> + <deleteData createDataKey="createDynamicBundle" stepKey="deleteDynamicBundleProduct"/> + <deleteData createDataKey="createFixedBundle" stepKey="deleteFixedBundleProduct"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createSimpleProductTwo" stepKey="createSimpleProductTwo"/> + </after> + <!-- 1. Go to storefront home page --> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> + <!-- 2. Fill quick search bar with test values unique for dynamic bundle product and click search --> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchDynamic"> + <argument name="phrase" value="Dynamic"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="assertDynamicBundleInSearchResultByDynamic"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGrid" stepKey="assertFixedBundleInSearchResultByDynamic"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByDescription"> + <argument name="phrase" value="Dynamicscription"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="assertDynamicBundleInSearchResultByDescription"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGrid" stepKey="dontSeeFixedBundleInSearchResultByDescription"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchShortDescription"> + <argument name="phrase" value="Dynamictest"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="assertDynamicBundleInSearchResultByShortDescription"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGrid" stepKey="dontSeeFixedBundleInSearchResultByShortDescription"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <!-- 3. Fill quick search bar with test values mutual for both products and click search --> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchTest123"> + <argument name="phrase" value="Test 123"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeDynamicBundleByTest123"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeFixedBundleByTest123"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchTesting321"> + <argument name="phrase" value="Testing 321"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeDynamicBundleByTesting321"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeFixedBundleByTesting321"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchShort555"> + <argument name="phrase" value="Short 555"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeDynamicBundleByShort555"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeFixedBundleByShort555"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <!-- 4. Fill quick search bar with test values unique for fixed bundle product and click search --> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByFixed"> + <argument name="phrase" value="Fixed"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeFixedBundleByFixed"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGrid" stepKey="dontSeeDynamicBundleByFixed"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByDescriptionForFixed"> + <argument name="phrase" value="Fixedscription"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeFixedBundleByDescriptionForFixed"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGrid" stepKey="dontSeeDynamicProductByDescriptionForFixed"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByShortDescriptionForFixed"> + <argument name="phrase" value="Fixedtest"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByName" stepKey="seeFixedBundleByShortDescriptionForFixed"> + <argument name="productName" value="$createFixedBundle.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGrid" stepKey="dontSeeDynamicBundleByShortDescriptionForFixed"> + <argument name="productName" value="$createDynamicBundle.name$"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/CustomAttributeData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/CustomAttributeData.xml index 389c41abf0bd1..1684bd0c8a2c3 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/CustomAttributeData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/CustomAttributeData.xml @@ -35,4 +35,20 @@ <data key="attribute_code">news_from_date</data> <data key="value">2018-05-17 00:00:00</data> </entity> + <entity name="CustomDynamicProductDescription" type="custom_attribute"> + <data key="attribute_code">description</data> + <data key="value">Dynamicscription testing 321</data> + </entity> + <entity name="CustomDynamicProductShortDescription" type="custom_attribute"> + <data key="attribute_code">short_description</data> + <data key="value">Short dynamictest 555</data> + </entity> + <entity name="CustomFixedProductDescription" type="custom_attribute"> + <data key="attribute_code">description</data> + <data key="value">Fixedscription testing 321</data> + </entity> + <entity name="CustomFixedProductShortDescription" type="custom_attribute"> + <data key="attribute_code">short_description</data> + <data key="value">Short Fixedtest 555</data> + </entity> </entities> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/StorefrontCatalogSearchActionGroup.xml b/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/StorefrontCatalogSearchActionGroup.xml index 067d76821d687..34e86566d73ba 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/StorefrontCatalogSearchActionGroup.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/StorefrontCatalogSearchActionGroup.xml @@ -64,6 +64,13 @@ <see selector="{{StorefrontQuickSearchResultsSection.productByIndex(index)}}" userInput="{{productName}}" stepKey="seeProductName"/> </actionGroup> + <actionGroup name="StorefrontQuickSearchSeeProductByName"> + <arguments> + <argument name="productName" type="string"/> + </arguments> + <see selector="{{StorefrontQuickSearchResultsSection.productByName(productName)}}" userInput="{{productName}}" stepKey="seeProductName"/> + </actionGroup> + <actionGroup name="StorefrontQuickSearchCheckProductNameNotInGrid"> <arguments> <argument name="productName" type="string"/> From 55feda69c097dead6760d52a28d7d09f7c51cc91 Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Mon, 29 Jul 2019 13:45:16 +0300 Subject: [PATCH 12/12] MC-219: Admin should be able to mass update attributes for bundle products --- ...sUpdateAttributesForBundleProductsTest.xml | 76 +++++++++++++++++++ .../ActionGroup/AdminProductActionGroup.xml | 17 +++++ ...nProductAttributeMassUpdateActionGroup.xml | 29 +++++++ .../Data/ProductAttributeMassUpdateData.xml | 15 ++++ .../Section/AdminUpdateAttributesSection.xml | 1 + 5 files changed, 138 insertions(+) create mode 100644 app/code/Magento/Bundle/Test/Mftf/Test/AdminShouldBeAbleToMassUpdateAttributesForBundleProductsTest.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeMassUpdateActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeMassUpdateData.xml diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminShouldBeAbleToMassUpdateAttributesForBundleProductsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminShouldBeAbleToMassUpdateAttributesForBundleProductsTest.xml new file mode 100644 index 0000000000000..fe55fda4d0e05 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminShouldBeAbleToMassUpdateAttributesForBundleProductsTest.xml @@ -0,0 +1,76 @@ +<?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="AdminShouldBeAbleToMassUpdateAttributesForBundleProductsTest"> + <annotations> + <features value="Bundle"/> + <stories value="Admin list bundle products"/> + <title value="Admin should be able to mass update attributes for bundle products"/> + <description value="Admin should be able to mass update attributes for bundle products"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-219"/> + <group value="bundle"/> + <group value="WYSIWYGDisabled"/> + </annotations> + <before> + <!-- Create Simple Product --> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"/> + <!-- Create Fixed Bundle Product --> + <createData entity="ApiFixedBundleProduct" stepKey="createFixedBundleProduct"/> + <!-- Create DropDown Bundle Option --> + <createData entity="DropDownBundleOption" stepKey="createBundleOption"> + <requiredEntity createDataKey="createFixedBundleProduct"/> + </createData> + <!-- Link Simple Product --> + <createData entity="ApiBundleLink" stepKey="createNewBundleLink"> + <requiredEntity createDataKey="createFixedBundleProduct"/> + <requiredEntity createDataKey="createBundleOption"/> + <requiredEntity createDataKey="createSimpleProduct"/> + </createData> + </before> + <after> + <!-- Delete Simple Product --> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <!-- Delete Fixed Bundle Product --> + <deleteData createDataKey="createFixedBundleProduct" stepKey="deleteBundleProduct"/> + <!-- Clear Filter --> + <actionGroup ref="ClearProductsFilterActionGroup" stepKey="clearProductFilter"/> + <!--Log Out Admin--> + <actionGroup ref="logout" stepKey="logoutAsAdmin"/> + </after> + <!-- Login as Admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!-- Go to Catalog -> Catalog -> Products and Search created product in precondition and choose it --> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchProduct"> + <argument name="product" value="$$createFixedBundleProduct$$"/> + </actionGroup> + <!-- Choose "Update attributes" and Change any product data --> + <actionGroup ref="AdminUpdateProductNameAndDescriptionAttributes" stepKey="updateProductAttribute"> + <argument name="product" value="UpdateAttributeNameAndDescription"/> + </actionGroup> + <!--Run cron twice--> + <magentoCLI command="cron:run" stepKey="cronRun"/> + <magentoCLI command="cron:run" stepKey="cronRunTwice"/> + <!-- Search for a product with a new name and Open Product --> + <actionGroup ref="filterProductGridByName" stepKey="searchWithNewProductName"> + <argument name="product" value="UpdateAttributeNameAndDescription"/> + </actionGroup> + <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openProductPage"> + <argument name="product" value="$$createFixedBundleProduct$$"/> + </actionGroup> + <!-- Assert product name and description --> + <actionGroup ref="AssertProductNameInProductEditForm" stepKey="assertProductName"> + <argument name="productName" value="{{UpdateAttributeNameAndDescription.name}}"/> + </actionGroup> + <actionGroup ref="AssertProductDescriptionInProductEditForm" stepKey="assertProductDescription"> + <argument name="productDescription" value="{{UpdateAttributeNameAndDescription.description}}"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml index 5f3614e1ae659..22668e1c78527 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml @@ -542,4 +542,21 @@ <remove keyForRemoval="seeCheckboxForWebsite"/> <seeCheckboxIsChecked selector="{{ProductInWebsitesSection.website(website)}}" after="expandProductWebsitesSection" stepKey="seeCustomWebsiteIsChecked"/> </actionGroup> + <!-- You are on product Edit Page --> + <!-- Assert Product Name in admin Product page --> + <actionGroup name="AssertProductNameInProductEditForm"> + <arguments> + <argument name="productName" type="string"/> + </arguments> + <seeInField selector="{{AdminProductFormSection.productName}}" userInput="{{productName}}" stepKey="seeProductNameOnEditProductPage"/> + </actionGroup> + <!-- You are on product Edit Page --> + <!-- Assert Product Description in admin Product page --> + <actionGroup name="AssertProductDescriptionInProductEditForm"> + <arguments> + <argument name="productDescription" type="string"/> + </arguments> + <conditionalClick selector="{{AdminProductContentSection.sectionHeader}}" dependentSelector="{{AdminProductContentSection.sectionHeaderShow}}" visible="false" stepKey="expandContentSection"/> + <seeInField selector="{{AdminProductContentSection.descriptionTextArea}}" userInput="{{productDescription}}" stepKey="seeProductDescription"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeMassUpdateActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeMassUpdateActionGroup.xml new file mode 100644 index 0000000000000..57b180ada1536 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeMassUpdateActionGroup.xml @@ -0,0 +1,29 @@ +<?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"> + <!-- Update Product Name and Description attribute --> + <actionGroup name="AdminUpdateProductNameAndDescriptionAttributes"> + <arguments> + <argument name="product"/> + </arguments> + <click selector="{{AdminProductGridSection.productGridCheckboxOnRow('1')}}" stepKey="clickCheckbox"/> + <click selector="{{AdminProductGridSection.bulkActionDropdown}}" stepKey="clickDropdown"/> + <click selector="{{AdminProductGridSection.bulkActionOption('Update attributes')}}" stepKey="clickOption"/> + <waitForPageLoad stepKey="waitForUploadPage"/> + <seeInCurrentUrl url="{{ProductAttributesEditPage.url}}" stepKey="seeAttributePageEditUrl"/> + <click selector="{{AdminUpdateAttributesSection.toggleName}}" stepKey="clickToChangeName"/> + <fillField selector="{{AdminUpdateAttributesSection.name}}" userInput="{{product.name}}" stepKey="fillFieldName"/> + <click selector="{{AdminUpdateAttributesSection.toggleDescription}}" stepKey="clickToChangeDescription"/> + <fillField selector="{{AdminUpdateAttributesSection.description}}" userInput="{{product.description}}" stepKey="fillFieldDescription"/> + <click selector="{{AdminUpdateAttributesSection.saveButton}}" stepKey="save"/> + <waitForElementVisible selector="{{AdminMessagesSection.successMessage}}" stepKey="waitVisibleSuccessMessage"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="Message is added to queue" stepKey="seeSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeMassUpdateData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeMassUpdateData.xml new file mode 100644 index 0000000000000..99908f1c9df5f --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeMassUpdateData.xml @@ -0,0 +1,15 @@ +<?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="UpdateAttributeNameAndDescription" type="productAttributeMassUpdate"> + <data key="name" unique="suffix">New Bundle Product Name</data> + <data key="description" unique="suffix">This is the description</data> + </entity> +</entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminUpdateAttributesSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminUpdateAttributesSection.xml index 53af1d5bd6eb1..69d7297628d56 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminUpdateAttributesSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminUpdateAttributesSection.xml @@ -36,6 +36,7 @@ <element name="toggleWeight" type="checkbox" selector="#toggle_weight"/> <element name="toggleColor" type="checkbox" selector="#toggle_color"/> + <element name="name" type="input" selector="#name"/> <element name="description" type="input" selector="#description"/> </section> <section name="AdminUpdateAttributesWebsiteSection">