Skip to content

Commit d22c4a1

Browse files
authored
Merge branch '2.4-develop' into AC-13209
2 parents 910d178 + 8ac55c4 commit d22c4a1

File tree

14 files changed

+1452
-18
lines changed

14 files changed

+1452
-18
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright 2025 Adobe
5+
* All Rights Reserved.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AdminSetAllowedCurrenciesActionGroup" extends="AdminConfigureCurrenciesActionGroup">
12+
<annotations>
13+
<description>Set allowed currencies in Currency Options configuration after switching the storeview from default storeview</description>
14+
</annotations>
15+
<remove keyForRemoval="waitForBaseCurrencyToVisible"/>
16+
<remove keyForRemoval="selectBaseCurrency"/>
17+
</actionGroup>
18+
</actionGroups>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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="StorefrontVerifyProductPriceWithDifferentCurrenciesInStoreViewsTest">
11+
<annotations>
12+
<features value="Checkout"/>
13+
<stories value="Shopping Cart Price Display"/>
14+
<title value="Verify product price displays correctly in shopping cart with different currencies in different store views"/>
15+
<description value="Verify price conversion in cart for USD and EUR views when switching between store views"/>
16+
<severity value="MINOR"/>
17+
<testCaseId value="AC-15943"/>
18+
<group value="Checkout"/>
19+
</annotations>
20+
<before>
21+
<!-- Step 1: Login to Admin Panel -->
22+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
23+
<!-- Step 2 & 3: Create additional Store View 2 under default website and default store -->
24+
<actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createCustomStoreView">
25+
<argument name="customStore" value="NewStoreViewData"/>
26+
</actionGroup>
27+
<!-- Step 4: Create simple product with price 100 USD -->
28+
<createData entity="SimpleProduct_100" stepKey="createSimpleProduct"/>
29+
<!-- Step 5, 6, 7: Configure currency for Store View 2 -->
30+
<!-- Navigate to Currency Configuration -->
31+
<actionGroup ref="AdminNavigateToCurrencySetupPageActionGroup" stepKey="goToCurrencySetupPage"/>
32+
<!-- Switch to Store View 2 scope -->
33+
<actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="switchToNewStoreView">
34+
<argument name="storeView" value="NewStoreViewData.name"/>
35+
</actionGroup>
36+
<!-- Configure Euro as default display currency for Store View 2 -->
37+
<uncheckOption selector="{{AdminConfigSection.allowedCurrencyCheckbox}}" stepKey="uncheckUseSystemValueDisplayCurrency"/>
38+
<uncheckOption selector="{{AdminConfigSection.defaultCurrencyCheckbox}}" stepKey="uncheckUseSystemValueAllowedCurrency"/>
39+
<actionGroup ref="AdminSetAllowedCurrenciesActionGroup" stepKey="setEuroAsDefaultCurrency">
40+
<argument name="defaultValue" value="Euro"/>
41+
<argument name="allowedValue" value="['Euro','US Dollar']"/>
42+
</actionGroup>
43+
<!-- Save configuration -->
44+
<actionGroup ref="SaveStoreConfigurationActionGroup" stepKey="saveStoreConfiguration"/>
45+
<!-- Step 8: Clear cache and reindex -->
46+
<actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache">
47+
<argument name="tags" value=""/>
48+
</actionGroup>
49+
</before>
50+
<after>
51+
<!-- Delete created product -->
52+
<deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/>
53+
<!-- Reset currency configuration to default -->
54+
<actionGroup ref="AdminNavigateToCurrencySetupPageActionGroup" stepKey="goToCurrencySetupPage"/>
55+
<actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="switchToStoreView2ForCleanup">
56+
<argument name="storeView" value="NewStoreViewData.name"/>
57+
</actionGroup>
58+
<actionGroup ref="AdminSetAllowedCurrenciesActionGroup" stepKey="resetCurrencyConfig">
59+
<argument name="defaultValue" value="US Dollar"/>
60+
<argument name="allowedValue" value="['US Dollar']"/>
61+
</actionGroup>
62+
<actionGroup ref="SaveStoreConfigurationActionGroup" stepKey="saveStoreConfiguration"/>
63+
<!-- Delete Store View 2 -->
64+
<actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView">
65+
<argument name="customStore" value="NewStoreViewData"/>
66+
</actionGroup>
67+
<!-- Clear cache -->
68+
<actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheAfterCleanup">
69+
<argument name="tags" value=""/>
70+
</actionGroup>
71+
<!-- Logout from admin -->
72+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/>
73+
</after>
74+
<!-- Step 9: Open Storefront website -->
75+
<actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openStorefront"/>
76+
<!-- Step 10 & 11: Go to PDP and verify price is 100 USD -->
77+
<actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductPageDefaultView">
78+
<argument name="productUrl" value="$$createSimpleProduct.custom_attributes[url_key]$$"/>
79+
</actionGroup>
80+
<!-- Verify product price is $100.00 USD -->
81+
<waitForText selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="$100.00" stepKey="verifyPriceIs100USD"/>
82+
<!-- Step 12: Switch to Store View 2 -->
83+
<actionGroup ref="StorefrontSwitchStoreViewActionGroup" stepKey="switchToStoreView2">
84+
<argument name="storeView" value="NewStoreViewData"/>
85+
</actionGroup>
86+
<!-- Step 13: Verify price is 70.67 Euro on PDP -->
87+
<actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductPageStoreView2">
88+
<argument name="productUrl" value="$$createSimpleProduct.custom_attributes[url_key]$$"/>
89+
</actionGroup>
90+
<!-- Verify product price is €70.67 -->
91+
<waitForText selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="€70.67" stepKey="verifyPriceIs70Point67Euro"/>
92+
<!-- Step 14: Add product to cart -->
93+
<actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="addProductToCart">
94+
<argument name="product" value="$$createSimpleProduct$$"/>
95+
<argument name="productCount" value="1"/>
96+
</actionGroup>
97+
<!-- Step 15 & 16: Go to shopping cart and verify price is 70.67 Euro -->
98+
<actionGroup ref="StorefrontOpenCartFromMinicartActionGroup" stepKey="openShoppingCart"/>
99+
<!-- Verify subtotal is also in Euro -->
100+
<waitForText selector="{{CheckoutCartSummarySection.subtotal}}" userInput="€70.67" stepKey="verifySubtotalIs70Point67Euro"/>
101+
</test>
102+
</tests>
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+
declare(strict_types=1);
7+
8+
namespace Magento\Catalog\Test\Unit\Block\Adminhtml\Category\Helper;
9+
10+
use Magento\Catalog\Block\Adminhtml\Category\Helper\Image;
11+
use Magento\Framework\UrlInterface;
12+
use Magento\Store\Model\Store;
13+
use Magento\Store\Model\StoreManagerInterface;
14+
use PHPUnit\Framework\MockObject\MockObject;
15+
use PHPUnit\Framework\TestCase;
16+
17+
/**
18+
* Unit test for Image helper
19+
*
20+
* @covers \Magento\Catalog\Block\Adminhtml\Category\Helper\Image
21+
*/
22+
class ImageTest extends TestCase
23+
{
24+
/**
25+
* @var Image
26+
*/
27+
private Image $model;
28+
29+
/**
30+
* @var StoreManagerInterface|MockObject
31+
*/
32+
private $storeManagerMock;
33+
34+
/**
35+
* @var Store|MockObject
36+
*/
37+
private $storeMock;
38+
39+
/**
40+
* @inheritdoc
41+
*/
42+
protected function setUp(): void
43+
{
44+
$this->storeManagerMock = $this->getMockForAbstractClass(StoreManagerInterface::class);
45+
$this->storeMock = $this->getMockBuilder(Store::class)
46+
->disableOriginalConstructor()
47+
->getMock();
48+
49+
// Using getMockBuilder to avoid parent constructor ObjectManager::getInstance() calls
50+
$this->model = $this->getMockBuilder(Image::class)
51+
->disableOriginalConstructor()
52+
->onlyMethods([])
53+
->getMock();
54+
55+
// Inject the storeManager dependency using reflection
56+
$reflection = new \ReflectionClass($this->model);
57+
$property = $reflection->getProperty('_storeManager');
58+
$property->setAccessible(true);
59+
$property->setValue($this->model, $this->storeManagerMock);
60+
}
61+
62+
/**
63+
* Test _getUrl method returns false when no value is set
64+
*
65+
* @return void
66+
*/
67+
public function testGetUrlWithoutValue(): void
68+
{
69+
$this->model->setValue(null);
70+
71+
$reflection = new \ReflectionClass($this->model);
72+
$method = $reflection->getMethod('_getUrl');
73+
$method->setAccessible(true);
74+
75+
$result = $method->invoke($this->model);
76+
77+
$this->assertFalse($result);
78+
}
79+
80+
/**
81+
* Test _getUrl method returns correct URL when value is set
82+
*
83+
* @return void
84+
*/
85+
public function testGetUrlWithValue(): void
86+
{
87+
$imageName = 'test_image.jpg';
88+
$baseUrl = 'http://example.com/media/';
89+
$expectedUrl = $baseUrl . 'catalog/category/' . $imageName;
90+
91+
$this->model->setValue($imageName);
92+
93+
$this->storeManagerMock->expects($this->once())
94+
->method('getStore')
95+
->willReturn($this->storeMock);
96+
97+
$this->storeMock->expects($this->once())
98+
->method('getBaseUrl')
99+
->with(UrlInterface::URL_TYPE_MEDIA)
100+
->willReturn($baseUrl);
101+
102+
$reflection = new \ReflectionClass($this->model);
103+
$method = $reflection->getMethod('_getUrl');
104+
$method->setAccessible(true);
105+
106+
$result = $method->invoke($this->model);
107+
108+
$this->assertEquals($expectedUrl, $result);
109+
}
110+
111+
/**
112+
* Test _getUrl method with different image names
113+
*
114+
* @dataProvider imageNameDataProvider
115+
* @param string $imageName
116+
* @return void
117+
*/
118+
public function testGetUrlWithDifferentImageNames(string $imageName): void
119+
{
120+
$baseUrl = 'http://example.com/media/';
121+
$expectedUrl = $baseUrl . 'catalog/category/' . $imageName;
122+
123+
$this->model->setValue($imageName);
124+
125+
$this->storeManagerMock->expects($this->once())
126+
->method('getStore')
127+
->willReturn($this->storeMock);
128+
129+
$this->storeMock->expects($this->once())
130+
->method('getBaseUrl')
131+
->with(UrlInterface::URL_TYPE_MEDIA)
132+
->willReturn($baseUrl);
133+
134+
$reflection = new \ReflectionClass($this->model);
135+
$method = $reflection->getMethod('_getUrl');
136+
$method->setAccessible(true);
137+
138+
$result = $method->invoke($this->model);
139+
140+
$this->assertEquals($expectedUrl, $result);
141+
}
142+
143+
/**
144+
* Test _getUrl method with empty string value
145+
*
146+
* @return void
147+
*/
148+
public function testGetUrlWithEmptyString(): void
149+
{
150+
$this->model->setValue('');
151+
152+
$reflection = new \ReflectionClass($this->model);
153+
$method = $reflection->getMethod('_getUrl');
154+
$method->setAccessible(true);
155+
156+
$result = $method->invoke($this->model);
157+
158+
$this->assertFalse($result);
159+
}
160+
161+
/**
162+
* Test that URL_TYPE_MEDIA constant has correct value
163+
*
164+
* @return void
165+
*/
166+
public function testUrlTypeMediaConstant(): void
167+
{
168+
// Verify the constant value is 'media' as expected by the implementation
169+
$this->assertEquals('media', UrlInterface::URL_TYPE_MEDIA);
170+
}
171+
172+
/**
173+
* Data provider for image names
174+
*
175+
* @return array
176+
*/
177+
public static function imageNameDataProvider(): array
178+
{
179+
return [
180+
'jpg image' => ['category_image.jpg'],
181+
'png image' => ['category_image.png'],
182+
'gif image' => ['category_image.gif'],
183+
'image with path' => ['subfolder/category_image.jpg'],
184+
'image with special chars' => ['category-image_01.jpg']
185+
];
186+
}
187+
}

0 commit comments

Comments
 (0)