Skip to content

Commit 4c93579

Browse files
ENGCOM-7997: fix Same store name overriding in the store view grid filter #29474
- Merge Pull Request #29474 from engcom-Charlie/magento2:fix_store_name_rewrite - Merged commits: 1. 1b39196 2. 9a98048 3. 5fbb3cf 4. 5565349
2 parents 8b7d949 + 5565349 commit 4c93579

File tree

7 files changed

+232
-16
lines changed

7 files changed

+232
-16
lines changed

app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridFilterSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,6 @@
3838
<element name="storeViewDropdown" type="text" selector="//select[@name='store_id']/option[contains(.,'{{storeView}}')]" parameterized="true"/>
3939
<element name="inputByCodeRangeFrom" type="input" selector="input.admin__control-text[name='{{code}}[from]']" parameterized="true"/>
4040
<element name="inputByCodeRangeTo" type="input" selector="input.admin__control-text[name='{{code}}[to]']" parameterized="true"/>
41+
<element name="storeViewOptions" type="text" selector=".admin__data-grid-outer-wrap select[name='store_id'] > option[value='{{value}}']" parameterized="true"/>
4142
</section>
4243
</sections>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
10+
<actionGroup name="AdminCheckStoreViewOptionsActionGroup">
11+
<annotations>
12+
<description>Goes to the Catalog->Product filters and check store view options at the Store View dropdown</description>
13+
</annotations>
14+
<arguments>
15+
<argument name="storeViewId" type="string"/>
16+
</arguments>
17+
<amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage"/>
18+
<waitForPageLoad stepKey="waitForProductCatalogPage"/>
19+
<click selector="{{AdminProductGridFilterSection.filters}}" stepKey="clickFiltersButton"/>
20+
<click selector="{{AdminProductFiltersSection.storeViewDropDown}}" stepKey="clickStoreViewSwitchDropdown"/>
21+
<waitForElementVisible selector="{{AdminProductFiltersSection.storeViewDropDown}}" stepKey="waitForWebsiteAreVisible"/>
22+
<seeElement selector="{{AdminProductGridFilterSection.storeViewOptions(storeViewId)}}" stepKey="seeStoreViewOption"/>
23+
</actionGroup>
24+
</actionGroups>

app/code/Magento/Store/Test/Mftf/Data/StoreData.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,4 +206,23 @@
206206
<data key="store_type">store</data>
207207
<data key="store_action">add</data>
208208
</entity>
209+
<!--Stores views with same name-->
210+
<entity name="customStoreViewSameNameFirst" type="store">
211+
<data key="name">sameNameStoreView</data>
212+
<data key="code" unique="suffix">storeViewCode</data>
213+
<data key="is_active">1</data>
214+
<data key="store_id">null</data>
215+
<data key="store_action">add</data>
216+
<data key="store_type">store</data>
217+
<requiredEntity type="storeGroup">customStoreGroup</requiredEntity>
218+
</entity>
219+
<entity name="customStoreViewSameNameSecond" type="store">
220+
<data key="name">sameNameStoreView</data>
221+
<data key="code" unique="suffix">storeViewCode</data>
222+
<data key="is_active">1</data>
223+
<data key="store_id">null</data>
224+
<data key="store_action">add</data>
225+
<data key="store_type">store</data>
226+
<requiredEntity type="storeGroup">customStoreGroup</requiredEntity>
227+
</entity>
209228
</entities>

app/code/Magento/Store/Test/Mftf/Section/AdminStoresGridSection/AdminStoresGridSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@
2222
<element name="emptyText" type="text" selector="//tr[@class='data-grid-tr-no-data even']/td[@class='empty-text']"/>
2323
<element name="websiteName" type="text" selector="//td[@class='a-left col-website_title ']/a[contains(.,'{{websiteName}}')]" parameterized="true"/>
2424
<element name="gridCell" type="text" selector="//table[@class='data-grid']//tr[{{row}}]//td[count(//table[@class='data-grid']//tr//th[contains(., '{{column}}')]/preceding-sibling::th) +1 ]" parameterized="true"/>
25+
<element name="storeViewLinkInNthRow" type="text" selector="tr:nth-of-type({{row}}) &gt; .col-store_title &gt; a" parameterized="true"/>
2526
</section>
2627
</sections>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
9+
<test name="AdminCreateDuplicateNameStoreViewTest">
10+
<annotations>
11+
<features value="Store"/>
12+
<stories value="Create a store view in admin"/>
13+
<title value="Admin should be able to create a Store View with the same name"/>
14+
<description value="Admin should be able to create a Store View with the same name"/>
15+
<group value="storeView"/>
16+
<severity value="AVERAGE"/>
17+
<testCaseId value="MC-36863"/>
18+
</annotations>
19+
<before>
20+
<!--Create two store views with same name, but different codes-->
21+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
22+
<actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createFirstStoreView">
23+
<argument name="StoreGroup" value="_defaultStoreGroup"/>
24+
<argument name="customStore" value="customStoreViewSameNameFirst"/>
25+
</actionGroup>
26+
<actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createSecondStoreView">
27+
<argument name="StoreGroup" value="_defaultStoreGroup"/>
28+
<argument name="customStore" value="customStoreViewSameNameSecond"/>
29+
</actionGroup>
30+
</before>
31+
<after>
32+
<!--Delete both store views-->
33+
<actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteFirstStoreView">
34+
<argument name="customStore" value="customStoreViewSameNameFirst"/>
35+
</actionGroup>
36+
<actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteSecondStoreView">
37+
<argument name="customStore" value="customStoreViewSameNameSecond"/>
38+
</actionGroup>
39+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>
40+
</after>
41+
<!--Get Id of store views-->
42+
<amOnPage url="{{AdminSystemStorePage.url}}" stepKey="navigateToStoreViews"/>
43+
<click selector="{{AdminStoresGridSection.storeViewLinkInNthRow('2')}}" stepKey="openFirstViewPAge" />
44+
<grabFromCurrentUrl stepKey="getStoreViewIdFirst" regex="~/store_id/(\d+)/~"/>
45+
<amOnPage url="{{AdminSystemStorePage.url}}" stepKey="navigateToStoreViewsAgain"/>
46+
<click selector="{{AdminStoresGridSection.storeViewLinkInNthRow('3')}}" stepKey="openSecondViewPAge" />
47+
<grabFromCurrentUrl stepKey="getStoreViewIdSecond" regex="~/store_id/(\d+)/~"/>
48+
<!--Go to catalog -> product grid, open the filter and check the listed store view-->
49+
<actionGroup ref="AdminCheckStoreViewOptionsActionGroup" stepKey="checkFirstStoreView">
50+
<argument name="storeViewId" value="{$getStoreViewIdFirst}"/>
51+
</actionGroup>
52+
<actionGroup ref="AdminCheckStoreViewOptionsActionGroup" stepKey="checkSecondStoreView">
53+
<argument name="storeViewId" value="{$getStoreViewIdSecond}"/>
54+
</actionGroup>
55+
</test>
56+
</tests>

app/code/Magento/Store/Ui/Component/Listing/Column/Store/Options.php

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use Magento\Store\Model\System\Store as SystemStore;
1111

1212
/**
13-
* Class Options
13+
* Ui stores options
1414
*/
1515
class Options implements OptionSourceInterface
1616
{
@@ -93,37 +93,38 @@ protected function sanitizeName($name)
9393
*
9494
* @return void
9595
*/
96-
protected function generateCurrentOptions()
96+
protected function generateCurrentOptions(): void
9797
{
9898
$websiteCollection = $this->systemStore->getWebsiteCollection();
9999
$groupCollection = $this->systemStore->getGroupCollection();
100100
$storeCollection = $this->systemStore->getStoreCollection();
101-
/** @var \Magento\Store\Model\Website $website */
101+
102102
foreach ($websiteCollection as $website) {
103103
$groups = [];
104-
/** @var \Magento\Store\Model\Group $group */
105104
foreach ($groupCollection as $group) {
106-
if ($group->getWebsiteId() == $website->getId()) {
105+
if ($group->getWebsiteId() === $website->getId()) {
107106
$stores = [];
108-
/** @var \Magento\Store\Model\Store $store */
109107
foreach ($storeCollection as $store) {
110-
if ($store->getGroupId() == $group->getId()) {
111-
$name = $this->sanitizeName($store->getName());
112-
$stores[$name]['label'] = str_repeat(' ', 8) . $name;
113-
$stores[$name]['value'] = $store->getId();
108+
if ($store->getGroupId() === $group->getId()) {
109+
$stores[] = [
110+
'label' => str_repeat(' ', 8) . $this->sanitizeName($store->getName()),
111+
'value' => $store->getId(),
112+
];
114113
}
115114
}
116115
if (!empty($stores)) {
117-
$name = $this->sanitizeName($group->getName());
118-
$groups[$name]['label'] = str_repeat(' ', 4) . $name;
119-
$groups[$name]['value'] = array_values($stores);
116+
$groups[] = [
117+
'label' => str_repeat(' ', 4) . $this->sanitizeName($group->getName()),
118+
'value' => array_values($stores),
119+
];
120120
}
121121
}
122122
}
123123
if (!empty($groups)) {
124-
$name = $this->sanitizeName($website->getName());
125-
$this->currentOptions[$name]['label'] = $name;
126-
$this->currentOptions[$name]['value'] = array_values($groups);
124+
$this->currentOptions[] = [
125+
'label' => $this->sanitizeName($website->getName()),
126+
'value' => array_values($groups),
127+
];
127128
}
128129
}
129130
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Store\Ui\Component\Listing\Column\Store;
9+
10+
use Magento\Store\Model\ResourceModel\Group as GroupResource;
11+
use Magento\Store\Model\ResourceModel\Store as StoreResource;
12+
use Magento\Store\Model\ResourceModel\Website as WebsiteResource;
13+
use Magento\Store\Model\StoreManagerInterface;
14+
use Magento\TestFramework\Helper\Bootstrap;
15+
use PHPUnit\Framework\TestCase;
16+
17+
/**
18+
* Test for \Magento\Store\Ui\Component\Listing\Column\Store\Options.
19+
*/
20+
class OptionsTest extends TestCase
21+
{
22+
private const DEFAULT_WEBSITE_NAME = 'Main Website';
23+
private const DEFAULT_STORE_GROUP_NAME = 'Main Website Store';
24+
private const DEFAULT_STORE_NAME = 'Default Store View';
25+
26+
/**
27+
* @var OptionsFactory
28+
*/
29+
private $modelFactory;
30+
31+
/**
32+
* @var StoreManagerInterface
33+
*/
34+
private $storeManager;
35+
36+
/**
37+
* @var WebsiteResource
38+
*/
39+
private $websiteResource;
40+
41+
/**
42+
* @var StoreResource
43+
*/
44+
private $storeResource;
45+
46+
/**
47+
* @var GroupResource
48+
*/
49+
private $groupResource;
50+
51+
/**
52+
* @return void
53+
*/
54+
protected function setUp(): void
55+
{
56+
$objectManager = Bootstrap::getObjectManager();
57+
58+
$this->modelFactory = $objectManager->get(OptionsFactory::class);
59+
$this->storeManager = $objectManager->get(StoreManagerInterface::class);
60+
61+
$this->websiteResource = $objectManager->get(WebsiteResource::class);
62+
$this->groupResource = $objectManager->get(GroupResource::class);
63+
$this->storeResource = $objectManager->get(StoreResource::class);
64+
}
65+
66+
/**
67+
* To option array test with duplicate website, store group, store view names
68+
*
69+
* @magentoDataFixture Magento/Store/_files/second_website_with_store_group_and_store.php
70+
*
71+
* @return void
72+
*/
73+
public function testToOptionArray(): void
74+
{
75+
$website = $this->storeManager->getWebsite('test');
76+
$this->websiteResource->save($website->setName(self::DEFAULT_WEBSITE_NAME));
77+
78+
$storeGroup = current($website->getGroups());
79+
$this->groupResource->save($storeGroup->setName(self::DEFAULT_STORE_GROUP_NAME));
80+
81+
$store = current($website->getStores());
82+
$this->storeResource->save($store->setName(self::DEFAULT_STORE_NAME));
83+
84+
$model = $this->modelFactory->create();
85+
$storeIds = [$this->storeManager->getStore('default')->getId(), $store->getId()];
86+
87+
$this->assertEquals($this->getExpectedOptions($storeIds), $model->toOptionArray());
88+
}
89+
90+
/**
91+
* Returns expected options
92+
*
93+
* @param array $storeIds
94+
* @return array
95+
*/
96+
private function getExpectedOptions(array $storeIds): array
97+
{
98+
$expectedOptions = [];
99+
foreach ($storeIds as $storeId) {
100+
$expectedOptions[] = [
101+
'label' => self::DEFAULT_WEBSITE_NAME,
102+
'value' => [[
103+
'label' => str_repeat(' ', 4) . self::DEFAULT_STORE_GROUP_NAME,
104+
'value' => [[
105+
'label' => str_repeat(' ', 8) . self::DEFAULT_STORE_NAME,
106+
'value' => $storeId,
107+
]],
108+
]],
109+
];
110+
}
111+
112+
return $expectedOptions;
113+
}
114+
}

0 commit comments

Comments
 (0)