Skip to content

Commit aa260d0

Browse files
Merge branch 'ACQE-8206' into ACQE-functional-deployment-version11
2 parents 90b054d + 7d51a2e commit aa260d0

File tree

1 file changed

+187
-0
lines changed
  • dev/tests/integration/testsuite/Magento/Checkout/Helper

1 file changed

+187
-0
lines changed
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Checkout\Helper;
10+
11+
use Magento\Checkout\Helper\Data;
12+
use Magento\Framework\ObjectManagerInterface;
13+
use Magento\Quote\Model\Quote;
14+
use Magento\Quote\Model\QuoteManagement;
15+
use Magento\Sales\Api\OrderRepositoryInterface;
16+
use Magento\Sales\Model\Order;
17+
use Magento\TestFramework\Helper\Bootstrap;
18+
use Magento\TestFramework\Mail\Template\TransportBuilderMock;
19+
use PHPUnit\Framework\TestCase;
20+
21+
/**
22+
* Integration test for sending the "payment failed" email on virtual product order failure.
23+
*
24+
* Ensures that when a virtual product order fails during payment, the appropriate failure email is
25+
* sent and does not include any shipping address or method information.
26+
*
27+
* @magentoDbIsolation enabled
28+
* @magentoAppIsolation enabled
29+
* @magentoDataFixture Magento/Checkout/_files/quote_with_virtual_product_and_address.php
30+
*
31+
* @AllureSuite("Checkout")
32+
* @AllureFeature("Payment Failed Email")
33+
*/
34+
class DataTest extends TestCase
35+
{
36+
/**
37+
* @var ObjectManagerInterface
38+
*/
39+
private ObjectManagerInterface $objectManager;
40+
41+
/**
42+
* @var QuoteManagement
43+
*/
44+
private QuoteManagement $quoteManagement;
45+
46+
/**
47+
* @var Data
48+
*/
49+
private Data $checkoutHelper;
50+
51+
/**
52+
* @var OrderRepositoryInterface
53+
*/
54+
private OrderRepositoryInterface $orderRepository;
55+
56+
/**
57+
* @var TransportBuilderMock
58+
*/
59+
private TransportBuilderMock $transportBuilder;
60+
61+
/**
62+
* Reserved order ID used in fixture.
63+
*/
64+
private const FIXTURE_RESERVED_ORDER_ID = 'test_order_with_virtual_product';
65+
66+
/**
67+
* Payment method code to use in test.
68+
*/
69+
private const PAYMENT_METHOD = 'checkmo';
70+
71+
/**
72+
* Set up required Magento services for the test.
73+
*
74+
* @return void
75+
*/
76+
protected function setUp(): void
77+
{
78+
parent::setUp();
79+
80+
$this->objectManager = Bootstrap::getObjectManager();
81+
$this->quoteManagement = $this->objectManager->get(QuoteManagement::class);
82+
$this->checkoutHelper = $this->objectManager->get(Data::class);
83+
$this->orderRepository = $this->objectManager->get(OrderRepositoryInterface::class);
84+
$this->transportBuilder = $this->objectManager->get(TransportBuilderMock::class);
85+
}
86+
87+
/**
88+
* Test sending the "payment failed" email for an order with a virtual product.
89+
*
90+
* This test verifies that:
91+
* - The payment failure email is sent successfully.
92+
* - The email content does not include shipping address or shipping method
93+
* since the product is virtual.
94+
*
95+
* @return void
96+
*/
97+
public function testSendPaymentFailedEmail(): void
98+
{
99+
[$order, $quote] = $this->createOrderFromFixture();
100+
$this->simulatePaymentFailure($order);
101+
102+
$this->checkoutHelper->sendPaymentFailedEmail(
103+
$quote,
104+
'Simulated payment failure',
105+
'onepage'
106+
);
107+
108+
$message = $this->transportBuilder->getSentMessage();
109+
$this->assertNotNull($message, 'Expected a payment failed email to be sent.');
110+
111+
$emailBody = $message->getBody();
112+
if (method_exists($emailBody, 'bodyToString')) {
113+
$emailContent = quoted_printable_decode($emailBody->bodyToString());
114+
} elseif (method_exists($emailBody, 'getParts') && isset($emailBody->getParts()[0])) {
115+
$emailContent = $emailBody->getParts()[0]->getRawContent();
116+
} else {
117+
$this->fail('Unable to extract email content for assertion.');
118+
}
119+
120+
$this->assertStringNotContainsString(
121+
'Shipping Address',
122+
$emailContent,
123+
'Shipping address should not appear in the payment failed email for virtual product.'
124+
);
125+
$this->assertStringNotContainsString(
126+
'Shipping Method',
127+
$emailContent,
128+
'Shipping method should not appear in the payment failed email for virtual product.'
129+
);
130+
$this->assertStringContainsString(
131+
'Simulated payment failure',
132+
$emailContent,
133+
'Expected payment failure message to be present in the email.'
134+
);
135+
}
136+
137+
/**
138+
* Prepare an order from a fixture quote containing a virtual product.
139+
*
140+
* Loads the quote with reserved_order_id from fixture,
141+
* sets payment method, submits the quote to create the order.
142+
*
143+
* @return array{0: Order, 1: Quote} Returns the created order and the original quote.
144+
*/
145+
private function createOrderFromFixture(): array
146+
{
147+
/** @var Quote $quote */
148+
$quote = $this->objectManager->create(Quote::class)
149+
->load(self::FIXTURE_RESERVED_ORDER_ID, 'reserved_order_id');
150+
151+
$this->assertNotNull($quote->getId(), 'Failed to load quote from fixture.');
152+
$this->assertNotEmpty($quote->getAllItems(), 'Quote from fixture is empty.');
153+
154+
$quote->getPayment()->setMethod(self::PAYMENT_METHOD);
155+
156+
$order = $this->quoteManagement->submit($quote);
157+
158+
$this->assertNotNull($order->getId(), 'Order was not created from quote.');
159+
$this->assertNotEmpty($order->getIncrementId(), 'Order increment ID is missing.');
160+
161+
return [$order, $quote];
162+
}
163+
164+
/**
165+
* Simulate a payment failure by cancelling the order and adding a history comment.
166+
*
167+
* This method updates the order state and status to 'canceled',
168+
* adds a comment explaining the payment failure, and saves the order.
169+
*
170+
* @param Order $order
171+
* @return void
172+
*/
173+
private function simulatePaymentFailure(Order $order): void
174+
{
175+
$order->setState(Order::STATE_CANCELED)
176+
->setStatus(Order::STATE_CANCELED)
177+
->addCommentToStatusHistory((string)__('Simulated: Payment failure due to gateway timeout.'));
178+
179+
$this->orderRepository->save($order);
180+
181+
$this->assertSame(
182+
Order::STATE_CANCELED,
183+
$order->getState(),
184+
'Order state should be canceled after simulating payment failure.'
185+
);
186+
}
187+
}

0 commit comments

Comments
 (0)