Skip to content

Commit 90380be

Browse files
Merge branch '2.4-develop' of github.com:magento-gl/magento2ce into ACQE-functional-deployment-version14
2 parents 3717600 + 835e075 commit 90380be

File tree

60 files changed

+4581
-385
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+4581
-385
lines changed

app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckSpecialPriceWithCustomOptionAndTaxTest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@
5757
<magentoCLI command="config:set shipping/origin/country_id US" stepKey="setOriginCountryToUS"/>
5858

5959
<!-- Display product price excluding tax in shopping cart -->
60-
<magentoCLI command="config:set tax/cart_display/price 0" stepKey="disableShowIncludingTaxInCart"/>
60+
<magentoCLI command="config:set tax/cart_display/price 1" stepKey="disableShowIncludingTaxInCart"/>
6161

6262
<!-- Display product price excluding tax in catalog -->
63-
<magentoCLI command="config:set tax/display/type 0" stepKey="disableShowIncludingTax"/>
63+
<magentoCLI command="config:set tax/display/type 1" stepKey="disableShowIncludingTax"/>
6464

6565
<!-- Set up catalog to store product price excluding tax -->
6666
<magentoCLI command="config:set tax/calculation/price_includes_tax 0" stepKey="disableCatalogIncludingTax"/>

app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Listing/Collector/UrlTest.php

Lines changed: 187 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,21 @@ protected function setUp(): void
7878
);
7979
}
8080

81-
public function testGet()
81+
public function testCollectWithNullButtons()
8282
{
8383
$product = $this->getMockBuilder(Product::class)
8484
->disableOriginalConstructor()
8585
->getMock();
8686
$productRenderInfoDto = $this->getMockForAbstractClass(ProductRenderInterface::class);
87+
88+
// Mock both getAddToCartButton and getAddToCompareButton returning null (line 81-82)
89+
$productRenderInfoDto->expects($this->once())
90+
->method('getAddToCartButton')
91+
->willReturn(null);
92+
$productRenderInfoDto->expects($this->once())
93+
->method('getAddToCompareButton')
94+
->willReturn(null);
95+
8796
$this->catalogProductHelperMock
8897
->expects($this->once())
8998
->method('getPostDataParams')
@@ -92,6 +101,15 @@ public function testGet()
92101
$product->expects($this->once())
93102
->method('getId')
94103
->willReturn(1);
104+
$product->expects($this->once())
105+
->method('getData')
106+
->with('has_options')
107+
->willReturn(true);
108+
$product->expects($this->once())
109+
->method('getProductUrl')
110+
->willReturn('http://example.com/product/1');
111+
112+
// Expect buttonFactory to be called twice (once for cart, once for compare) since both are null
95113
$this->buttonFactoryMock->expects($this->exactly(2))
96114
->method('create')
97115
->willReturn($this->buttonMock);
@@ -113,6 +131,174 @@ public function testGet()
113131
)
114132
->willReturn(['some cart url post data']);
115133

134+
// Verify buttons are set back to productRender
135+
$productRenderInfoDto->expects($this->once())
136+
->method('setAddToCartButton')
137+
->with($this->buttonMock);
138+
$productRenderInfoDto->expects($this->once())
139+
->method('setAddToCompareButton')
140+
->with($this->buttonMock);
141+
$productRenderInfoDto->expects($this->once())
142+
->method('setUrl')
143+
->with('http://example.com/product/1');
144+
145+
$this->model->collect($product, $productRenderInfoDto);
146+
}
147+
148+
public function testCollectWithExistingAddToCompareButton()
149+
{
150+
$product = $this->getMockBuilder(Product::class)
151+
->disableOriginalConstructor()
152+
->getMock();
153+
$productRenderInfoDto = $this->getMockForAbstractClass(ProductRenderInterface::class);
154+
155+
$existingCompareButton = $this->getMockForAbstractClass(ButtonInterface::class);
156+
157+
// Test line 82: getAddToCompareButton returns existing button
158+
$productRenderInfoDto->expects($this->once())
159+
->method('getAddToCartButton')
160+
->willReturn(null);
161+
$productRenderInfoDto->expects($this->once())
162+
->method('getAddToCompareButton')
163+
->willReturn($existingCompareButton);
164+
165+
$this->catalogProductHelperMock
166+
->expects($this->once())
167+
->method('getPostDataParams')
168+
->with($product)
169+
->willReturn(['Some compare Data']);
170+
$product->expects($this->once())
171+
->method('getId')
172+
->willReturn(1);
173+
$product->expects($this->once())
174+
->method('getData')
175+
->with('has_options')
176+
->willReturn(false);
177+
$product->expects($this->once())
178+
->method('getProductUrl')
179+
->willReturn('http://example.com/product/1');
180+
181+
// Expect buttonFactory to be called only once (for cart button) since compare button exists
182+
$this->buttonFactoryMock->expects($this->once())
183+
->method('create')
184+
->willReturn($this->buttonMock);
185+
$this->abstractProductMock->expects($this->exactly(2))
186+
->method('getAddToCartUrl')
187+
->with(
188+
$product,
189+
['useUencPlaceholder' => true]
190+
)
191+
->willReturn('some:url');
192+
$this->postHelperMock->expects($this->once())
193+
->method('getPostData')
194+
->with(
195+
'some:url',
196+
[
197+
'product' => 1,
198+
ActionInterface::PARAM_NAME_URL_ENCODED => "%uenc%"
199+
]
200+
)
201+
->willReturn(['some cart url post data']);
202+
203+
// Verify the existing compare button is used and configured
204+
$existingCompareButton->expects($this->once())
205+
->method('setUrl')
206+
->with(['Some compare Data']);
207+
208+
// Verify buttons are set back to productRender
209+
$productRenderInfoDto->expects($this->once())
210+
->method('setAddToCartButton')
211+
->with($this->buttonMock);
212+
$productRenderInfoDto->expects($this->once())
213+
->method('setAddToCompareButton')
214+
->with($existingCompareButton);
215+
$productRenderInfoDto->expects($this->once())
216+
->method('setUrl')
217+
->with('http://example.com/product/1');
218+
219+
$this->model->collect($product, $productRenderInfoDto);
220+
}
221+
222+
public function testCollectWithExistingButtons()
223+
{
224+
$product = $this->getMockBuilder(Product::class)
225+
->disableOriginalConstructor()
226+
->getMock();
227+
$productRenderInfoDto = $this->getMockForAbstractClass(ProductRenderInterface::class);
228+
229+
$existingCartButton = $this->getMockForAbstractClass(ButtonInterface::class);
230+
$existingCompareButton = $this->getMockForAbstractClass(ButtonInterface::class);
231+
232+
// Test both buttons already exist
233+
$productRenderInfoDto->expects($this->once())
234+
->method('getAddToCartButton')
235+
->willReturn($existingCartButton);
236+
$productRenderInfoDto->expects($this->once())
237+
->method('getAddToCompareButton')
238+
->willReturn($existingCompareButton);
239+
240+
$this->catalogProductHelperMock
241+
->expects($this->once())
242+
->method('getPostDataParams')
243+
->with($product)
244+
->willReturn(['Some compare Data']);
245+
$product->expects($this->once())
246+
->method('getId')
247+
->willReturn(1);
248+
$product->expects($this->once())
249+
->method('getData')
250+
->with('has_options')
251+
->willReturn(true);
252+
$product->expects($this->once())
253+
->method('getProductUrl')
254+
->willReturn('http://example.com/product/1');
255+
256+
// Expect buttonFactory to NOT be called since both buttons exist
257+
$this->buttonFactoryMock->expects($this->never())
258+
->method('create');
259+
$this->abstractProductMock->expects($this->exactly(2))
260+
->method('getAddToCartUrl')
261+
->with(
262+
$product,
263+
['useUencPlaceholder' => true]
264+
)
265+
->willReturn('some:url');
266+
$this->postHelperMock->expects($this->once())
267+
->method('getPostData')
268+
->with(
269+
'some:url',
270+
[
271+
'product' => 1,
272+
ActionInterface::PARAM_NAME_URL_ENCODED => "%uenc%"
273+
]
274+
)
275+
->willReturn(['some cart url post data']);
276+
277+
// Verify both existing buttons are used and configured
278+
$existingCartButton->expects($this->once())
279+
->method('setPostData')
280+
->with(['some cart url post data']);
281+
$existingCartButton->expects($this->once())
282+
->method('setRequiredOptions')
283+
->with(true);
284+
$existingCartButton->expects($this->once())
285+
->method('setUrl')
286+
->with('some:url');
287+
$existingCompareButton->expects($this->once())
288+
->method('setUrl')
289+
->with(['Some compare Data']);
290+
291+
// Verify buttons are set back to productRender
292+
$productRenderInfoDto->expects($this->once())
293+
->method('setAddToCartButton')
294+
->with($existingCartButton);
295+
$productRenderInfoDto->expects($this->once())
296+
->method('setAddToCompareButton')
297+
->with($existingCompareButton);
298+
$productRenderInfoDto->expects($this->once())
299+
->method('setUrl')
300+
->with('http://example.com/product/1');
301+
116302
$this->model->collect($product, $productRenderInfoDto);
117303
}
118304
}

app/code/Magento/Catalog/Ui/DataProvider/Product/Listing/Collector/Url.php

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,6 @@
2020
*/
2121
class Url implements ProductRenderCollectorInterface
2222
{
23-
/** Compare Data key */
24-
const KEY_COMPARE_URL_POST_DATA = "compare_url_post_data";
25-
26-
/** Add to cart url key post data */
27-
const KEY_ADD_TO_CART_URL_POST_DATA = "add_to_cart_url_post_data";
28-
29-
/** Add to cart url key */
30-
const KEY_ADD_TO_CART_URL = "add_to_cart_url";
31-
32-
/** Product Url */
33-
const KEY_URL = "url";
34-
35-
/** Has Required options key */
36-
const KEY_HAS_REQUIRED_OPTIONS = "has_required_options";
37-
3823
/**
3924
* @var AbstractProduct
4025
*/
@@ -79,7 +64,7 @@ public function __construct(
7964
public function collect(ProductInterface $product, ProductRenderInterface $productRender)
8065
{
8166
$addToCart = $productRender->getAddToCartButton();
82-
$addToCompare = $productRender->getAddToCartButton();
67+
$addToCompare = $productRender->getAddToCompareButton();
8368

8469
if (!$addToCart) {
8570
$addToCart = $this->buttonFactory->create();

app/code/Magento/Checkout/Test/Mftf/Data/CheckoutConfigData.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,7 @@
4444
<data key="label">No</data>
4545
<data key="value">0</data>
4646
</entity>
47+
<entity name="ErrorMessageAfterAddingCoupon">
48+
<data key="text">The shipping method is missing. Select the shipping method and try again.</data>
49+
</entity>
4750
</entities>

app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,6 @@
5757
<element name="customerAddressAttribute" type="input" selector="[id*='{{attribute}}']" parameterized="true"/>
5858
<element name="savedAddress" type="text" selector="div[class='shipping-address-item selected-item']"/>
5959
<element name="shippingAddressBox" type="text" selector="//div[@class='shipping-address-item selected-item']" timeout="30"/>
60+
<element name="cancelCouponText" type="text" selector="//div[@data-ui-id='message-success']//div[text()='{{cancelCodeText}}']" parameterized="true"/>
6061
</section>
6162
</sections>
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright 2025 Adobe
5+
* All Rights Reserved.
6+
*/
7+
-->
8+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
10+
<test name="StoreFrontCheckoutFreeShippingRecalculationAfterCouponCodeAppliedTest">
11+
<annotations>
12+
<features value="Checkout"/>
13+
<stories value="Checkout with Free Shipping"/>
14+
<title value="Checkout Free Shipping Recalculation after Coupon Code Applied"/>
15+
<description value="Verify customer should be able to do checkout free shipping recalculation after adding coupon code"/>
16+
<severity value="MAJOR"/>
17+
<testCaseId value="AC-6178"/>
18+
<group value="Checkout"/>
19+
</annotations>
20+
<before>
21+
<!--Precondition 1: Create US Customer-->
22+
<createData entity="Simple_US_Customer" stepKey="createCustomer"/>
23+
<!--Precondition 2: Create Simple product-->
24+
<createData entity="_defaultCategory" stepKey="defaultCategory"/>
25+
<createData entity="_defaultProduct" stepKey="simpleProduct">
26+
<field key="price">90</field>
27+
<requiredEntity createDataKey="defaultCategory"/>
28+
</createData>
29+
<!--Precondition 4: Enable Free Shipping-->
30+
<createData entity="FreeShippingMethodsSettingConfig" stepKey="freeShippingMethodsSettingConfig"/>
31+
<createData entity="MinimumOrderAmount90" stepKey="minimumOrderAmount90"/>
32+
<!--Precondition 5: Create cart price rule-->
33+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
34+
<actionGroup ref="AdminCartPriceRuleDeleteAllActionGroup" stepKey="deleteAllCartPriceRules"/>
35+
<actionGroup ref="AdminCreateCartPriceRuleWithCouponCodeActionGroup" stepKey="createCartPriceRule">
36+
<argument name="ruleName" value="CatPriceRule"/>
37+
<argument name="couponCode" value="CatPriceRule.coupon_code"/>
38+
</actionGroup>
39+
<!--Login to Storefront-->
40+
<actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStoreFront">
41+
<argument name="Customer" value="$createCustomer$"/>
42+
</actionGroup>
43+
<!--Navigate to product page-->
44+
<actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductPage">
45+
<argument name="productUrl" value="$simpleProduct.custom_attributes[url_key]$"/>
46+
</actionGroup>
47+
</before>
48+
<after>
49+
<deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/>
50+
<deleteData createDataKey="defaultCategory" stepKey="deleteCategory"/>
51+
<createData entity="DefaultShippingMethodsConfig" stepKey="defaultShippingMethodsConfig"/>
52+
<createData entity="DefaultMinimumOrderAmount" stepKey="defaultMinimumOrderAmount"/>
53+
<actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer" />
54+
<deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/>
55+
<actionGroup ref="AdminCartPriceRuleDeleteAllActionGroup" stepKey="deleteAllCartPriceRules"/>
56+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>
57+
</after>
58+
<!--Step 1:Add product to cart and apply cart price discount-->
59+
<actionGroup ref="ApplyCartRuleOnStorefrontActionGroup" stepKey="applyCartRule">
60+
<argument name="product" value="$simpleProduct$"/>
61+
<argument name="couponCode" value="{{CatPriceRule.coupon_code}}"/>
62+
</actionGroup>
63+
<!--Step 2:Navigate to checkout page and verify free shipping is not available-->
64+
<actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicartAfterCouponApplied"/>
65+
<waitForElementNotVisible selector="{{CheckoutShippingMethodsSection.shippingMethodRowByName('Free')}}" stepKey="verifyFreeShippingIsNotAvailable"/>
66+
<!--Step 3:Navigate back to shopping cart and cancel the discount-->
67+
<actionGroup ref="StorefrontCartPageOpenActionGroup" stepKey="goToShoppingCartPage"/>
68+
<conditionalClick selector="{{DiscountSection.DiscountTab}}" dependentSelector="{{DiscountSection.CouponInput}}" visible="false" stepKey="openDiscountTabIfClosed"/>
69+
<waitForElementClickable selector="{{DiscountSection.CancelCoupon}}" stepKey="waitForCancelCouponButton"/>
70+
<click selector="{{DiscountSection.CancelCoupon}}" stepKey="clickCancelCouponButton"/>
71+
<waitForElementVisible selector="{{CheckoutShippingSection.cancelCouponText('You canceled the coupon code.')}}" stepKey="seeCancellationMessage"/>
72+
<!--Step 4:Proceed to checkout-->
73+
<actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicartAfterCouponCancelled"/>
74+
<waitForPageLoad stepKey="waitForShippingMethods"/>
75+
<!--Step 5:Select free shipping method-->
76+
<actionGroup ref="StorefrontSetShippingMethodActionGroup" stepKey="selectFreeShipping">
77+
<argument name="shippingMethodName" value="Free Shipping"/>
78+
</actionGroup>
79+
<actionGroup ref="StorefrontCheckoutClickNextOnShippingStepActionGroup" stepKey="clickNext"/>
80+
<!--Step 6:Apply Discount Code -->
81+
<actionGroup ref="StorefrontApplyDiscountCodeActionGroup" stepKey="applyCouponCode">
82+
<argument name="discountCode" value="{{CatPriceRule.coupon_code}}"/>
83+
</actionGroup>
84+
<!--Step 7:Click on place order and verify assert order cannot be placed and error message will show.-->
85+
<actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectDefaultPaymentMethod"/>
86+
<actionGroup ref="AssertStorefrontOrderIsNotPlacedActionGroup" stepKey="seeShippingMethodError">
87+
<argument name="error" value="{{ErrorMessageAfterAddingCoupon.text}}"/>
88+
</actionGroup>
89+
<!--Step 8:Navigate back to shipping page and select flatrate-->
90+
<amOnPage stepKey="navigateToShippingPage" url="{{CheckoutShippingPage.url}}"/>
91+
<waitForPageLoad stepKey="waitForShippingPageLoad"/>
92+
<actionGroup ref="CheckoutSelectFlatRateShippingMethodActionGroup" stepKey="checkFlatRateShippingMethod"/>
93+
<actionGroup ref="StorefrontCheckoutClickNextOnShippingStepActionGroup" stepKey="clickNextAfterFlatRateShippingMethodSelection"/>
94+
<actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectPaymentMethod"/>
95+
<!--Step 9: Place Order -->
96+
<actionGroup ref="CheckoutPlaceOrderActionGroup" stepKey="placeOrder">
97+
<argument name="orderNumberMessage" value="CONST.successCheckoutOrderNumberMessage"/>
98+
<argument name="emailYouMessage" value="CONST.successCheckoutEmailYouMessage"/>
99+
</actionGroup>
100+
</test>
101+
</tests>

0 commit comments

Comments
 (0)