Skip to content

Commit 136bbde

Browse files
Merge branch 'ACQE-8868' into ACQE-functional-deployment-v4-3
2 parents f858a11 + 4a8042f commit 136bbde

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Sales\Model\Order\Email\Sender;
9+
10+
use Magento\Catalog\Test\Fixture\Product as ProductFixture;
11+
use Magento\Checkout\Test\Fixture\PlaceOrder as PlaceOrderFixture;
12+
use Magento\Checkout\Test\Fixture\SetBillingAddress as SetBillingAddressFixture;
13+
use Magento\Checkout\Test\Fixture\SetDeliveryMethod as SetDeliveryMethodFixture;
14+
use Magento\Checkout\Test\Fixture\SetGuestEmail as SetGuestEmailFixture;
15+
use Magento\Checkout\Test\Fixture\SetPaymentMethod as SetPaymentMethodFixture;
16+
use Magento\Checkout\Test\Fixture\SetShippingAddress as SetShippingAddressFixture;
17+
use Magento\Framework\Exception\LocalizedException;
18+
use Magento\Framework\Mail\EmailMessageInterface;
19+
use Magento\Quote\Test\Fixture\AddProductToCart as AddProductToCartFixture;
20+
use Magento\Quote\Test\Fixture\GuestCart as GuestCartFixture;
21+
use Magento\Sales\Api\CreditmemoManagementInterface;
22+
use Magento\Sales\Api\CreditmemoRepositoryInterface;
23+
use Magento\Sales\Model\Order\CreditmemoFactory;
24+
use Magento\Sales\Test\Fixture\Invoice as InvoiceFixture;
25+
use Magento\TestFramework\Fixture\Config;
26+
use Magento\TestFramework\Fixture\DataFixture;
27+
use Magento\TestFramework\Fixture\DataFixtureStorageManager;
28+
use Magento\TestFramework\Helper\Bootstrap;
29+
use Magento\TestFramework\Mail\Template\TransportBuilderMock;
30+
use PHPUnit\Framework\TestCase;
31+
32+
/**
33+
* Test credit memo creation for offline payment with async email notification.
34+
*
35+
*/
36+
class CreditmemoAsyncEmailTest extends TestCase
37+
{
38+
/**
39+
* @var CreditmemoFactory
40+
*/
41+
private $creditmemoFactory;
42+
43+
/**
44+
* @var CreditmemoManagementInterface
45+
*/
46+
private $creditmemoManagement;
47+
48+
/**
49+
* @var CreditmemoSender
50+
*/
51+
private $creditmemoSender;
52+
53+
/**
54+
* @var TransportBuilderMock
55+
*/
56+
private $transportBuilder;
57+
58+
/**
59+
* @var array
60+
*/
61+
private $sentEmails = [];
62+
63+
/**
64+
* @inheritdoc
65+
*/
66+
protected function setUp(): void
67+
{
68+
$objectManager = Bootstrap::getObjectManager();
69+
$this->creditmemoFactory = $objectManager->get(CreditmemoFactory::class);
70+
$this->creditmemoManagement = $objectManager->get(CreditmemoManagementInterface::class);
71+
$this->creditmemoSender = $objectManager->get(CreditmemoSender::class);
72+
$this->transportBuilder = $objectManager->get(TransportBuilderMock::class);
73+
$this->sentEmails = [];
74+
// Capture sent emails
75+
$this->transportBuilder->setOnMessageSentCallback(
76+
function (EmailMessageInterface $message) {
77+
$this->sentEmails[] = $message;
78+
}
79+
);
80+
}
81+
82+
/**
83+
* Test: Create Credit Memo for Offline Payment Methods with Async Email Notification
84+
*
85+
* @return void
86+
* @throws LocalizedException
87+
*/
88+
#[
89+
Config('payment/checkmo/active', '1'),
90+
Config('carriers/flatrate/active', '1'),
91+
Config('sales_email/general/async_sending', '1'),
92+
Config('sales_email/creditmemo/enabled', '1'),
93+
DataFixture(ProductFixture::class, as: 'product'),
94+
DataFixture(GuestCartFixture::class, as: 'cart'),
95+
DataFixture(AddProductToCartFixture::class, ['cart_id' => '$cart.id$', 'product_id' => '$product.id$']),
96+
DataFixture(SetBillingAddressFixture::class, ['cart_id' => '$cart.id$']),
97+
DataFixture(SetShippingAddressFixture::class, ['cart_id' => '$cart.id$']),
98+
DataFixture(SetGuestEmailFixture::class, ['cart_id' => '$cart.id$']),
99+
DataFixture(SetDeliveryMethodFixture::class, ['cart_id' => '$cart.id$']),
100+
DataFixture(SetPaymentMethodFixture::class, ['cart_id' => '$cart.id$', 'method' => 'checkmo']),
101+
DataFixture(PlaceOrderFixture::class, ['cart_id' => '$cart.id$'], 'order'),
102+
DataFixture(InvoiceFixture::class, ['order_id' => '$order.id$'], 'invoice'),
103+
]
104+
public function testCreateCreditmemoWithAsyncEmailNotification(): void
105+
{
106+
$fixtures = DataFixtureStorageManager::getStorage();
107+
$order = $fixtures->get('order');
108+
$this->assertNotNull($order->getId(), 'Order should exist');
109+
$this->assertTrue($order->hasInvoices(), 'Order should have invoice');
110+
$this->assertEquals('checkmo', $order->getPayment()->getMethod());
111+
$creditmemo = $this->creditmemoFactory->createByOrder($order);
112+
$creditmemoRepository = Bootstrap::getObjectManager()->get(CreditmemoRepositoryInterface::class);
113+
$creditmemoRepository->save($creditmemo);
114+
$creditmemo->setSendEmail(true);
115+
$creditmemoRepository->save($creditmemo);
116+
$this->assertCount(
117+
0,
118+
$this->sentEmails,
119+
'Email should NOT be sent immediately in async mode'
120+
);
121+
$this->assertEmpty(
122+
$creditmemo->getEmailSent(),
123+
'EmailSent should be empty until async process sends it'
124+
);
125+
$creditmemoEmailCron = Bootstrap::getObjectManager()->get('SalesCreditmemoSendEmailsCron');
126+
$creditmemoEmailCron->execute();
127+
$this->assertCount(1, $this->sentEmails, 'One refund email should be sent');
128+
$email = $this->sentEmails[0];
129+
$this->assertInstanceOf(EmailMessageInterface::class, $email);
130+
$this->assertStringContainsString(
131+
'Credit memo',
132+
$email->getSubject(),
133+
'Email subject should contain "Credit memo"'
134+
);
135+
}
136+
137+
/**
138+
* @inheritdoc
139+
*/
140+
protected function tearDown(): void
141+
{
142+
$this->sentEmails = [];
143+
}
144+
}

0 commit comments

Comments
 (0)