Skip to content

Commit 6917a2d

Browse files
committed
ACQE-8206: [Issue] [Checkout] Depend directives updated in failed payment email template
- Modified test code with email content assertion
1 parent 01218ab commit 6917a2d

File tree

1 file changed

+168
-43
lines changed
  • dev/tests/integration/testsuite/Magento/Checkout/Helper

1 file changed

+168
-43
lines changed

dev/tests/integration/testsuite/Magento/Checkout/Helper/DataTest.php

Lines changed: 168 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
* Copyright 2025 Adobe
44
* All Rights Reserved.
55
*/
6-
76
declare(strict_types=1);
87

98
namespace Magento\Checkout\Helper;
@@ -28,6 +27,8 @@
2827
* @magentoAppIsolation enabled
2928
* @magentoDbIsolation enabled
3029
* @magentoDataFixture Magento/Checkout/_files/quote_with_virtual_product_and_address.php
30+
* @magentoConfigFixture default_store checkout/payment_failed/template payment_failed_template
31+
* @magentoConfigFixture default_store checkout/payment_failed/identity support
3132
*
3233
* @AllureSuite("Checkout")
3334
* @AllureFeature("Payment Failed Email")
@@ -40,52 +41,48 @@ class DataTest extends TestCase
4041
* @var ObjectManagerInterface
4142
*/
4243
private ObjectManagerInterface $objectManager;
43-
4444
/**
4545
* Quote management service
4646
*
4747
* @var QuoteManagement
4848
*/
4949
private QuoteManagement $quoteManagement;
50-
5150
/**
5251
* Quote factory
5352
*
5453
* @var QuoteFactory
5554
*/
5655
private QuoteFactory $quoteFactory;
57-
5856
/**
5957
* Checkout data helper
6058
*
6159
* @var Data
6260
*/
6361
private Data $checkoutHelper;
64-
6562
/**
6663
* Order repository
6764
*
6865
* @var OrderRepositoryInterface
6966
*/
7067
private OrderRepositoryInterface $orderRepository;
71-
7268
/**
7369
* Transport builder mock
7470
*
7571
* @var TransportBuilderMock
7672
*/
7773
private TransportBuilderMock $transportBuilder;
78-
7974
/**
8075
* Reserved order ID used in fixture.
8176
*/
8277
private const FIXTURE_RESERVED_ORDER_ID = 'test_order_with_virtual_product';
83-
8478
/**
8579
* Payment method code to use in test.
8680
*/
8781
private const PAYMENT_METHOD = 'checkmo';
88-
82+
/**
83+
* Payment failure message used in test.
84+
*/
85+
private const PAYMENT_FAILURE_MESSAGE = 'Simulated payment failure';
8986
/**
9087
* Set up required Magento services for the test.
9188
*
@@ -94,7 +91,6 @@ class DataTest extends TestCase
9491
protected function setUp(): void
9592
{
9693
parent::setUp();
97-
9894
$this->objectManager = Bootstrap::getObjectManager();
9995
$this->quoteManagement = $this->objectManager->get(QuoteManagement::class);
10096
$this->quoteFactory = $this->objectManager->get(QuoteFactory::class);
@@ -107,48 +103,49 @@ protected function setUp(): void
107103
* Test sending the "payment failed" email for an order with a virtual product.
108104
*
109105
* This test verifies that:
110-
* - The payment failure email is sent successfully.
106+
* - The payment failure email is sent successfully
111107
* - The email content does not include shipping address or shipping method
112-
* since the product is virtual.
108+
* - The email contains appropriate payment failure information
109+
* - The email is properly formatted for virtual products
113110
*
114111
* @return void
115112
*/
116113
public function testSendPaymentFailedEmail(): void
117114
{
118115
[$order, $quote] = $this->prepareOrderFromFixtureQuote();
119116
$this->simulatePaymentFailure($order);
120-
121117
$this->checkoutHelper->sendPaymentFailedEmail(
122118
$quote,
123-
(string)__('Simulated payment failure'),
119+
(string)__(self::PAYMENT_FAILURE_MESSAGE),
124120
$quote->getPayment()->getMethod(),
125121
$quote->getCheckoutMethod()
126122
);
127-
128123
$message = $this->transportBuilder->getSentMessage();
129124
$this->assertNotNull($message, 'Expected a payment failed email to be sent.');
130-
131-
$emailBody = $message->getBody();
132-
if (method_exists($emailBody, 'bodyToString')) {
133-
$emailContent = quoted_printable_decode($emailBody->bodyToString());
134-
} elseif (method_exists($emailBody, 'getParts') && isset($emailBody->getParts()[0])) {
135-
$emailContent = $emailBody->getParts()[0]->getRawContent();
136-
} else {
137-
$this->fail('Unable to extract email content for assertion.');
138-
}
139-
140-
$this->assertStringNotContainsString(
141-
'Shipping Address',
142-
$emailContent,
143-
'Shipping address should not appear in the payment failed email for virtual product.'
144-
);
145-
$this->assertStringNotContainsString(
146-
'Shipping Method',
147-
$emailContent,
148-
'Shipping method should not appear in the payment failed email for virtual product.'
125+
$emailContent = $this->extractEmailContent($message->getBody());
126+
$this->assertVirtualProductEmailContent($emailContent);
127+
}
128+
/**
129+
* Test payment failed email with custom checkout method.
130+
*
131+
* @return void
132+
*/
133+
public function testSendPaymentFailedEmailWithCustomCheckoutMethod(): void
134+
{
135+
[$order, $quote] = $this->prepareOrderFromFixtureQuote();
136+
$quote->setCheckoutMethod('custom_method');
137+
$this->simulatePaymentFailure($order);
138+
$this->checkoutHelper->sendPaymentFailedEmail(
139+
$quote,
140+
(string)__(self::PAYMENT_FAILURE_MESSAGE),
141+
$quote->getPayment()->getMethod(),
142+
$quote->getCheckoutMethod()
149143
);
144+
$message = $this->transportBuilder->getSentMessage();
145+
$this->assertNotNull($message, 'Expected a payment failed email to be sent with custom checkout method.');
146+
$emailContent = $this->extractEmailContent($message->getBody());
147+
$this->assertVirtualProductEmailContent($emailContent);
150148
}
151-
152149
/**
153150
* Prepare an order from a fixture quote containing a virtual product.
154151
*
@@ -162,20 +159,16 @@ private function prepareOrderFromFixtureQuote(): array
162159
/** @var Quote $quote */
163160
$quote = $this->objectManager->create(Quote::class)
164161
->load(self::FIXTURE_RESERVED_ORDER_ID, 'reserved_order_id');
165-
166162
$this->assertNotNull($quote->getId(), 'Failed to load quote from fixture.');
167163
$this->assertNotEmpty($quote->getAllItems(), 'Quote from fixture is empty.');
168-
164+
$this->assertTrue($quote->hasVirtualItems(), 'Quote should contain virtual items.');
169165
$quote->getPayment()->setMethod(self::PAYMENT_METHOD);
170-
166+
$quote->collectTotals();
171167
$order = $this->quoteManagement->submit($quote);
172-
173168
$this->assertNotNull($order->getId(), 'Order was not created from quote.');
174169
$this->assertNotEmpty($order->getIncrementId(), 'Order increment ID is missing.');
175-
176170
return [$order, $quote];
177171
}
178-
179172
/**
180173
* Simulate a payment failure by cancelling the order and adding a history comment.
181174
*
@@ -190,13 +183,145 @@ private function simulatePaymentFailure(Order $order): void
190183
$order->setState(Order::STATE_CANCELED)
191184
->setStatus(Order::STATE_CANCELED)
192185
->addCommentToStatusHistory((string)__('Simulated: Payment failure due to gateway timeout.'));
193-
194186
$this->orderRepository->save($order);
195-
196187
$this->assertSame(
197188
Order::STATE_CANCELED,
198189
$order->getState(),
199190
'Order state should be canceled after simulating payment failure.'
200191
);
201192
}
193+
/**
194+
* Extract email content for testing from various email body formats.
195+
*
196+
* @param mixed $emailBody
197+
* @return string
198+
*/
199+
private function extractEmailContent($emailBody): string
200+
{
201+
// Try different methods to extract email content
202+
if (method_exists($emailBody, 'bodyToString')) {
203+
return quoted_printable_decode($emailBody->bodyToString());
204+
}
205+
if (method_exists($emailBody, 'getParts')) {
206+
$parts = $emailBody->getParts();
207+
if (!empty($parts) && method_exists($parts[0], 'getRawContent')) {
208+
return $parts[0]->getRawContent();
209+
}
210+
}
211+
if (method_exists($emailBody, 'getContent')) {
212+
return $emailBody->getContent();
213+
}
214+
if (method_exists($emailBody, '__toString')) {
215+
return (string)$emailBody;
216+
}
217+
$this->fail(
218+
'Unable to extract email content. Email body type: ' . get_class($emailBody) .
219+
'. Available methods: ' . implode(', ', get_class_methods($emailBody))
220+
);
221+
}
222+
/**
223+
* Assert virtual product email content meets requirements.
224+
*
225+
* @param string $emailContent
226+
* @return void
227+
*/
228+
private function assertVirtualProductEmailContent(string $emailContent): void
229+
{
230+
// Negative assertions - what should NOT be included for virtual products
231+
$this->assertStringNotContainsString(
232+
'Shipping Address',
233+
$emailContent,
234+
'Shipping address should not appear in payment failed email for virtual product.'
235+
);
236+
$this->assertStringNotContainsString(
237+
'Shipping Method',
238+
$emailContent,
239+
'Shipping method should not appear in payment failed email for virtual product.'
240+
);
241+
$this->assertStringNotContainsString(
242+
'Delivery',
243+
$emailContent,
244+
'Delivery information should not appear in payment failed email for virtual product.'
245+
);
246+
$this->assertStringNotContainsString(
247+
'Ship to',
248+
$emailContent,
249+
'Ship to information should not appear in payment failed email for virtual product.'
250+
);
251+
// Positive assertions - what should be included
252+
$this->assertStringContainsString(
253+
self::PAYMENT_FAILURE_MESSAGE,
254+
$emailContent,
255+
'Payment failure message should be present in email.'
256+
);
257+
$this->assertStringContainsString(
258+
self::PAYMENT_METHOD,
259+
$emailContent,
260+
'Payment method should be mentioned in email.'
261+
);
262+
// Verify email is not empty
263+
$this->assertNotEmpty(
264+
trim($emailContent),
265+
'Email content should not be empty.'
266+
);
267+
// Verify email contains order information
268+
$this->assertThat(
269+
$emailContent,
270+
$this->logicalOr(
271+
$this->stringContains('Order'),
272+
$this->stringContains('Payment'),
273+
$this->stringContains('Failed')
274+
),
275+
'Email should contain order or payment related information.'
276+
);
277+
}
278+
/**
279+
* Assert that email contains billing information but not shipping information.
280+
*
281+
* @param string $emailContent
282+
* @return void
283+
*/
284+
private function assertBillingButNoShippingInformation(string $emailContent): void
285+
{
286+
// Billing information should be present
287+
$this->assertStringContainsString(
288+
'Billing Address',
289+
$emailContent,
290+
'Billing address should be present in payment failed email.'
291+
);
292+
// Shipping information should not be present
293+
$this->assertStringNotContainsString(
294+
'Shipping Address',
295+
$emailContent,
296+
'Shipping address should not be present for virtual products.'
297+
);
298+
}
299+
/**
300+
* Test that email template variables are properly set.
301+
*
302+
* @return void
303+
*/
304+
public function testEmailTemplateVariables(): void
305+
{
306+
[$order, $quote] = $this->prepareOrderFromFixtureQuote();
307+
$this->simulatePaymentFailure($order);
308+
$this->checkoutHelper->sendPaymentFailedEmail(
309+
$quote,
310+
(string)__(self::PAYMENT_FAILURE_MESSAGE),
311+
$quote->getPayment()->getMethod(),
312+
$quote->getCheckoutMethod()
313+
);
314+
$message = $this->transportBuilder->getSentMessage();
315+
$this->assertNotNull($message, 'Expected a payment failed email to be sent.');
316+
// Verify email headers
317+
$headers = $message->getHeaders();
318+
$this->assertNotNull($headers, 'Email headers should be present.');
319+
// Verify email subject
320+
$subject = $message->getSubject();
321+
$this->assertNotEmpty($subject, 'Email subject should not be empty.');
322+
// Verify email recipient
323+
$to = $message->getTo();
324+
$this->assertNotEmpty($to, 'Email recipient should be present.');
325+
}
202326
}
327+

0 commit comments

Comments
 (0)