Skip to content

Commit 3b1ba34

Browse files
committed
Merge remote-tracking branch 'origin/MC-6420' into 2.3-develop-mftf-pr20
2 parents 2b153ee + 69761ae commit 3b1ba34

File tree

5 files changed

+383
-27
lines changed

5 files changed

+383
-27
lines changed

dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php

Lines changed: 130 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
*/
66
namespace Magento\Sales\Service\V1;
77

8+
use Magento\Catalog\Api\ProductRepositoryInterface;
9+
use Magento\Framework\ObjectManagerInterface;
10+
use Magento\Sales\Api\Data\OrderItemInterface;
11+
use Magento\Sales\Api\ShipmentRepositoryInterface;
12+
use Magento\Sales\Model\Order;
13+
814
/**
915
* API test for creation of Shipment for certain Order.
1016
*/
@@ -14,22 +20,28 @@ class ShipOrderTest extends \Magento\TestFramework\TestCase\WebapiAbstract
1420
const SERVICE_VERSION = 'V1';
1521

1622
/**
17-
* @var \Magento\Framework\ObjectManagerInterface
23+
* @var ObjectManagerInterface
1824
*/
1925
private $objectManager;
2026

2127
/**
22-
* @var \Magento\Sales\Api\ShipmentRepositoryInterface
28+
* @var ShipmentRepositoryInterface
2329
*/
2430
private $shipmentRepository;
2531

32+
/**
33+
* @var ProductRepositoryInterface
34+
*/
35+
private $productRepository;
36+
37+
/**
38+
* @inheritdoc
39+
*/
2640
protected function setUp()
2741
{
2842
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
29-
30-
$this->shipmentRepository = $this->objectManager->get(
31-
\Magento\Sales\Api\ShipmentRepositoryInterface::class
32-
);
43+
$this->shipmentRepository = $this->objectManager->get(ShipmentRepositoryInterface::class);
44+
$this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
3345
}
3446

3547
/**
@@ -40,9 +52,8 @@ public function testConfigurableShipOrder()
4052
$this->markTestIncomplete('https://github.com/magento-engcom/msi/issues/1335');
4153
$productsQuantity = 1;
4254

43-
/** @var \Magento\Sales\Model\Order $existingOrder */
44-
$existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
45-
->loadByIncrementId('100000001');
55+
/** @var Order $existingOrder */
56+
$existingOrder = $this->getOrder('100000001');
4657

4758
$requestData = [
4859
'orderId' => $existingOrder->getId(),
@@ -83,9 +94,8 @@ public function testConfigurableShipOrder()
8394
*/
8495
public function testShipOrder()
8596
{
86-
/** @var \Magento\Sales\Model\Order $existingOrder */
87-
$existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
88-
->loadByIncrementId('100000001');
97+
/** @var Order $existingOrder */
98+
$existingOrder = $this->getOrder('100000001');
8999

90100
$requestData = [
91101
'orderId' => $existingOrder->getId(),
@@ -103,7 +113,7 @@ public function testShipOrder()
103113
]
104114
];
105115

106-
/** @var \Magento\Sales\Api\Data\OrderItemInterface $item */
116+
/** @var OrderItemInterface $item */
107117
foreach ($existingOrder->getAllItems() as $item) {
108118
$requestData['items'][] = [
109119
'order_item_id' => $item->getItemId(),
@@ -121,9 +131,8 @@ public function testShipOrder()
121131
$this->fail('Failed asserting that Shipment was created');
122132
}
123133

124-
/** @var \Magento\Sales\Model\Order $updatedOrder */
125-
$updatedOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
126-
->loadByIncrementId('100000001');
134+
/** @var Order $updatedOrder */
135+
$updatedOrder = $this->getOrder('100000001');
127136

128137
$this->assertNotEquals(
129138
$existingOrder->getStatus(),
@@ -144,9 +153,8 @@ public function testShipOrderWithoutTrackingNumberReturnsError()
144153
{
145154
$this->_markTestAsRestOnly('SOAP requires an tracking number to be provided so this case is not possible.');
146155

147-
/** @var \Magento\Sales\Model\Order $existingOrder */
148-
$existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
149-
->loadByIncrementId('100000001');
156+
/** @var Order $existingOrder */
157+
$existingOrder = $this->getOrder('100000001');
150158

151159
$requestData = [
152160
'orderId' => $existingOrder->getId(),
@@ -170,9 +178,7 @@ public function testShipOrderWithoutTrackingNumberReturnsError()
170178
*/
171179
public function testPartialShipOrderWithBundleShippedSeparately()
172180
{
173-
/** @var \Magento\Sales\Model\Order $existingOrder */
174-
$existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
175-
->loadByIncrementId('100000001');
181+
$existingOrder = $this->getOrder('100000001');
176182

177183
$requestData = [
178184
'orderId' => $existingOrder->getId(),
@@ -213,9 +219,8 @@ public function testPartialShipOrderWithBundleShippedSeparately()
213219

214220
$this->assertEquals(1, $shipment->getTotalQty());
215221

216-
/** @var \Magento\Sales\Model\Order $existingOrder */
217-
$existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
218-
->loadByIncrementId('100000001');
222+
/** @var Order $existingOrder */
223+
$existingOrder = $this->getOrder('100000001');
219224

220225
foreach ($existingOrder->getAllItems() as $item) {
221226
if ($item->getItemId() == $shippedItemId) {
@@ -227,10 +232,73 @@ public function testPartialShipOrderWithBundleShippedSeparately()
227232
}
228233

229234
/**
230-
* @param \Magento\Sales\Model\Order $order
235+
* @magentoApiDataFixture Magento/Bundle/_files/order_with_2_bundles_shipping_separately.php
236+
*/
237+
public function testPartialShipOrderWithTwoBundleShippedSeparatelyContainsSameSimple()
238+
{
239+
$order = $this->getOrder('order_bundle_separately_shipped');
240+
241+
$requestData = [
242+
'orderId' => $order->getId(),
243+
'items' => [],
244+
'comment' => [
245+
'comment' => 'Test Comment',
246+
'is_visible_on_front' => 1,
247+
],
248+
'tracks' => [],
249+
];
250+
251+
$shippedItemId = null;
252+
$parentItemId = null;
253+
foreach ($order->getAllItems() as $item) {
254+
if ($item->getSku() === 'simple1') {
255+
$requestData['items'][] = [
256+
'order_item_id' => $item->getItemId(),
257+
'qty' => $item->getQtyOrdered(),
258+
];
259+
$shippedItemId = $item->getItemId();
260+
$parentItemId = $item->getParentItemId();
261+
break;
262+
}
263+
}
264+
265+
$shipmentId = $this->_webApiCall($this->getServiceInfo($order), $requestData);
266+
$this->assertNotEmpty($shipmentId);
267+
268+
try {
269+
$shipment = $this->shipmentRepository->get($shipmentId);
270+
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
271+
$this->fail('Failed asserting that Shipment was created');
272+
}
273+
274+
$this->assertEquals(1, $shipment->getTotalQty());
275+
276+
$order = $this->getOrder('order_bundle_separately_shipped');
277+
278+
foreach ($order->getAllItems() as $item) {
279+
if (in_array($item->getItemId(), [$shippedItemId, $parentItemId])) {
280+
$this->assertEquals(1, $item->getQtyShipped());
281+
continue;
282+
}
283+
$this->assertEquals(0, $item->getQtyShipped());
284+
}
285+
286+
try {
287+
$this->_webApiCall($this->getServiceInfo($order), $requestData);
288+
$this->fail('Expected exception was not raised');
289+
} catch (\Exception $exception) {
290+
$this->assertExceptionMessage(
291+
$exception,
292+
'Shipment Document Validation Error(s): You can\'t create a shipment without products.'
293+
);
294+
}
295+
}
296+
297+
/**
298+
* @param Order $order
231299
* @return array
232300
*/
233-
private function getServiceInfo(\Magento\Sales\Model\Order $order)
301+
private function getServiceInfo(Order $order): array
234302
{
235303
$serviceInfo = [
236304
'rest' => [
@@ -243,6 +311,41 @@ private function getServiceInfo(\Magento\Sales\Model\Order $order)
243311
'operation' => self::SERVICE_READ_NAME . 'execute',
244312
],
245313
];
314+
246315
return $serviceInfo;
247316
}
317+
318+
/**
319+
* Returns order by increment id.
320+
*
321+
* @param string $incrementId
322+
* @return Order
323+
*/
324+
private function getOrder(string $incrementId): Order
325+
{
326+
return $this->objectManager->create(Order::class)->loadByIncrementId($incrementId);
327+
}
328+
329+
/**
330+
* Assert correct exception message.
331+
*
332+
* @param \Exception $exception
333+
* @param string $expectedMessage
334+
* @return void
335+
*/
336+
private function assertExceptionMessage(\Exception $exception, string $expectedMessage): void
337+
{
338+
$actualMessage = '';
339+
switch (TESTS_WEB_API_ADAPTER) {
340+
case self::ADAPTER_SOAP:
341+
$actualMessage = trim(preg_replace('/\s+/', ' ', $exception->getMessage()));
342+
break;
343+
case self::ADAPTER_REST:
344+
$error = $this->processRestExceptionResult($exception);
345+
$actualMessage = $error['message'];
346+
break;
347+
}
348+
349+
$this->assertEquals($expectedMessage, $actualMessage);
350+
}
248351
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
use Magento\Bundle\Model\Option;
9+
use Magento\Bundle\Model\Product\Type as BundleProductType;
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Checkout\Model\Cart;
12+
use Magento\Checkout\Model\Session;
13+
use Magento\Quote\Api\CartManagementInterface;
14+
use Magento\Quote\Model\Quote\Address;
15+
use Magento\Quote\Model\Quote\Payment;
16+
use Magento\Quote\Model\QuoteManagement;
17+
use Magento\TestFramework\Helper\Bootstrap;
18+
19+
require __DIR__ . '/two_bundle_products_with_separate_shipping.php';
20+
$addressData = include __DIR__ . '/../../../Magento/Sales/_files/address_data.php';
21+
22+
$objectManager = Bootstrap::getObjectManager();
23+
$billingAddress = $objectManager->create(Address::class, ['data' => $addressData]);
24+
$billingAddress->setAddressType('billing');
25+
26+
$shippingAddress = clone $billingAddress;
27+
$shippingAddress->setId(null)
28+
->setAddressType('shipping')
29+
->setShippingMethod('flatrate_flatrate');
30+
31+
/** @var Payment $payment */
32+
$payment = $objectManager->create(Payment::class);
33+
$payment->setMethod('checkmo');
34+
35+
/** @var ProductRepositoryInterface $productRepository */
36+
$productRepository = $objectManager->create(ProductRepositoryInterface::class);
37+
38+
$bundleProduct = $productRepository->get('bundle-product-separate-shipping-1');
39+
$bundleProduct2 = $productRepository->get('bundle-product-separate-shipping-2');
40+
$selectionProducts = [
41+
$bundleProduct->getId() => [10, 12],
42+
$bundleProduct2->getId() => [11, 13],
43+
];
44+
45+
/** @var Cart $cart */
46+
$cart = $objectManager->create(Cart::class);
47+
48+
foreach ([$bundleProduct, $bundleProduct2] as $product) {
49+
50+
/** @var BundleProductType $typeInstance */
51+
$typeInstance = $product->getTypeInstance();
52+
$typeInstance->setStoreFilter($product->getStoreId(), $product);
53+
$optionCollection = $typeInstance->getOptionsCollection($product);
54+
55+
$bundleOptions = [];
56+
$bundleOptionsQty = [];
57+
$optionsData = [];
58+
59+
/** @var Option $option */
60+
foreach ($optionCollection as $option) {
61+
$selectionsCollection = $typeInstance->getSelectionsCollection([$option->getId()], $product);
62+
$selectionIds = $selectionProducts[$product->getId()];
63+
$selectionsCollection->addIdFilter($selectionIds);
64+
65+
foreach ($selectionIds as $productId) {
66+
$selection = $selectionsCollection->getItemByColumnValue('product_id', $productId);
67+
if ($selection !== null) {
68+
$bundleOptions[$option->getId()] = $selection->getSelectionId();
69+
$optionsData[$option->getId()] = $selection->getProductId();
70+
$bundleOptionsQty[$option->getId()] = 1;
71+
}
72+
}
73+
}
74+
75+
$requestInfo = [
76+
'product' => $product->getId(),
77+
'bundle_option' => $bundleOptions,
78+
'bundle_option_qty' => $bundleOptionsQty,
79+
'qty' => 1,
80+
];
81+
82+
$cart->addProduct($product, $requestInfo);
83+
}
84+
85+
$cart->getQuote()
86+
->setReservedOrderId('order_bundle_separately_shipped')
87+
->setBillingAddress($billingAddress)
88+
->setShippingAddress($shippingAddress)
89+
->setCheckoutMethod(CartManagementInterface::METHOD_GUEST)
90+
->setPayment($payment);
91+
$cart->save();
92+
93+
/** @var QuoteManagement $quoteManager */
94+
$quoteManager = $objectManager->get(QuoteManagement::class);
95+
$orderId = $quoteManager->placeOrder($cart->getQuote()->getId());
96+
97+
$objectManager->removeSharedInstance(Session::class);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
require __DIR__ . '/../../../Magento/Sales/_files/default_rollback.php';

0 commit comments

Comments
 (0)