Skip to content

Commit cc06bc9

Browse files
ACQE-8964: Create Shipment for Offline Payment Methods with Async Notification
- Removed cron execution twice and split the function to sub functions
1 parent dc451ff commit cc06bc9

File tree

1 file changed

+88
-45
lines changed

1 file changed

+88
-45
lines changed

dev/tests/integration/testsuite/Magento/Sales/Model/Order/Email/Sender/AdminShipmentAsyncEmailTest.php

Lines changed: 88 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ function (EmailMessageInterface $message): void {
7070
}
7171

7272
/**
73-
* Ensures shipment emails created in async mode are dispatched only after the cron runs.
73+
* Tests shipment email async behavior: not sent immediately, then sent by cron.
7474
*
7575
* @return void
7676
* @throws LocalizedException
@@ -92,33 +92,87 @@ function (EmailMessageInterface $message): void {
9292
DataFixture(SetPaymentMethodFixture::class, ['cart_id' => '$cart.id$', 'method' => 'checkmo']),
9393
DataFixture(PlaceOrderFixture::class, ['cart_id' => '$cart.id$'], 'order'),
9494
]
95-
public function testShipmentEmailDispatchedByCron(): void
95+
public function testShipmentAsyncEmailBehavior(): void
9696
{
9797
Bootstrap::getInstance()->loadArea(Area::AREA_ADMINHTML);
98+
$shipment = $this->createShipmentForOrder();
99+
$objectManager = Bootstrap::getObjectManager();
100+
$shipmentNotifier = $objectManager->get(ShipmentNotifier::class);
101+
$notifyResult = $shipmentNotifier->notify($shipment);
102+
$this->assertFalse(
103+
$notifyResult,
104+
'ShipmentNotifier::notify should defer sending when async mode is active.'
105+
);
106+
$this->assertCount(
107+
0,
108+
$this->sentEmails,
109+
'Email must not be sent immediately in async mode.'
110+
);
111+
$cron = $objectManager->get('SalesShipmentSendEmailsCron');
112+
$cron->execute();
113+
$this->assertCount(
114+
1,
115+
$this->sentEmails,
116+
'One shipment email should be dispatched after cron execution.'
117+
);
118+
$this->assertShipmentEmailContent($this->sentEmails[0]);
119+
}
98120

99-
$fixtures = DataFixtureStorageManager::getStorage();
100-
/** @var Order $fixtureOrder */
101-
$fixtureOrder = $fixtures->get('order');
102-
121+
/**
122+
* Creates an invoice for the given order.
123+
*
124+
* @param Order $order
125+
* @return void
126+
* @throws LocalizedException
127+
*/
128+
private function createInvoiceForOrder(Order $order): void
129+
{
103130
$objectManager = Bootstrap::getObjectManager();
104-
$orderRepository = $objectManager->get(OrderRepositoryInterface::class);
105131
$invoiceService = $objectManager->get(InvoiceService::class);
106132
$invoiceRepository = $objectManager->get(InvoiceRepositoryInterface::class);
107-
$shipmentRepository = $objectManager->get(ShipmentRepositoryInterface::class);
108-
$shipmentNotifier = $objectManager->get(ShipmentNotifier::class);
109-
$shipmentFactory = $objectManager->get(ShipmentFactory::class);
110-
111-
$order = $orderRepository->get((int)$fixtureOrder->getEntityId());
112-
$this->assertTrue($order->canInvoice(), 'Order must be invoiceable before creating a shipment.');
113-
133+
$orderRepository = $objectManager->get(OrderRepositoryInterface::class);
114134
$invoice = $invoiceService->prepareInvoice($order);
115135
$invoice->register();
116136
$invoice->setSendEmail(false);
117137
$invoiceRepository->save($invoice);
118138
$orderRepository->save($order);
139+
}
140+
141+
/**
142+
* Creates a shipment for the order from fixtures.
143+
*
144+
* @return \Magento\Sales\Api\Data\ShipmentInterface
145+
* @throws LocalizedException
146+
*/
147+
private function createShipmentForOrder()
148+
{
149+
$fixtures = DataFixtureStorageManager::getStorage();
150+
/** @var Order $fixtureOrder */
151+
$fixtureOrder = $fixtures->get('order');
152+
$objectManager = Bootstrap::getObjectManager();
153+
$orderRepository = $objectManager->get(OrderRepositoryInterface::class);
154+
$shipmentRepository = $objectManager->get(ShipmentRepositoryInterface::class);
155+
$shipmentFactory = $objectManager->get(ShipmentFactory::class);
156+
$order = $orderRepository->get((int)$fixtureOrder->getEntityId());
157+
$this->createInvoiceForOrder($order);
158+
$quantities = $this->calculateShippableQuantities($order);
159+
$shipment = $shipmentFactory->create($order, $quantities);
160+
$shipment->register();
161+
$shipment->setSendEmail(true);
162+
$shipmentRepository->save($shipment);
163+
$orderRepository->save($shipment->getOrder());
119164

120-
$this->assertTrue($order->canShip(), 'Order must be shippable after invoicing.');
165+
return $shipment;
166+
}
121167

168+
/**
169+
* Calculates shippable quantities for order items.
170+
*
171+
* @param Order $order
172+
* @return array
173+
*/
174+
private function calculateShippableQuantities(Order $order): array
175+
{
122176
$quantities = [];
123177
foreach ($order->getAllItems() as $orderItem) {
124178
if ($orderItem->getIsVirtual()) {
@@ -129,39 +183,28 @@ public function testShipmentEmailDispatchedByCron(): void
129183
$quantities[$orderItem->getItemId()] = $qtyToShip;
130184
}
131185
}
132-
$this->assertNotEmpty($quantities, 'At least one shippable item is required.');
133-
134-
$shipment = $shipmentFactory->create($order, $quantities);
135-
$shipment->register();
136-
$shipment->setSendEmail(true);
137-
138-
$shipmentRepository->save($shipment);
139-
$orderRepository->save($shipment->getOrder());
186+
return $quantities;
187+
}
140188

141-
$notifyResult = $shipmentNotifier->notify($shipment);
142-
$this->assertFalse(
143-
$notifyResult,
144-
'ShipmentNotifier::notify should return false while the email is queued for async sending.'
145-
);
146-
$this->assertCount(
147-
0,
148-
$this->sentEmails,
149-
'No shipment email should be dispatched immediately.'
189+
/**
190+
* Asserts shipment email has correct content.
191+
*
192+
* @param EmailMessageInterface $email
193+
* @return void
194+
*/
195+
private function assertShipmentEmailContent(EmailMessageInterface $email): void
196+
{
197+
$this->assertInstanceOf(EmailMessageInterface::class, $email);
198+
$this->assertStringContainsString(
199+
'order has shipped',
200+
$email->getSubject(),
201+
'Email subject should contain shipment confirmation text.'
150202
);
151-
152-
$cron = $objectManager->get('SalesShipmentSendEmailsCron');
153-
$cron->execute();
154-
$cron->execute();
155-
156-
$this->assertCount(
157-
1,
158-
$this->sentEmails,
159-
'One shipment email should be dispatched after cron execution.'
203+
$this->assertEquals(
204+
'async-shipment@example.com',
205+
$email->getTo()[0]->getEmail(),
206+
'Email should be sent to the customer email address.'
160207
);
161-
$email = $this->sentEmails[0];
162-
$this->assertInstanceOf(EmailMessageInterface::class, $email);
163-
$this->assertStringContainsString('order has shipped', $email->getSubject());
164-
$this->assertEquals('async-shipment@example.com', $email->getTo()[0]->getEmail());
165208
}
166209

167210
/**

0 commit comments

Comments
 (0)