Skip to content

Commit 85b6d05

Browse files
committed
Fix #13401 - Multi-Store: "Store View" sort order values are not reflected in front-end store-switcher
1 parent 6b6f428 commit 85b6d05

File tree

2 files changed

+126
-42
lines changed

2 files changed

+126
-42
lines changed

app/code/Magento/Store/Block/Switcher.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,12 @@ public function getStores()
193193
$stores = [];
194194
} else {
195195
$stores = $rawStores[$groupId];
196+
197+
uasort($stores, static function ($itemA, $itemB) {
198+
return (int)$itemA->getSortOrder() <=> (int)$itemB->getSortOrder();
199+
});
196200
}
201+
197202
$this->setData('stores', $stores);
198203
}
199204
return $this->getData('stores');

app/code/Magento/Store/Test/Unit/Block/SwitcherTest.php

Lines changed: 121 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,84 +3,163 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Store\Test\Unit\Block;
89

10+
use Magento\Directory\Helper\Data;
11+
use Magento\Framework\App\Config\ScopeConfigInterface;
12+
use Magento\Framework\Data\Helper\PostHelper;
913
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
14+
use Magento\Framework\UrlInterface;
15+
use Magento\Framework\View\Element\Template\Context;
16+
use Magento\Store\Api\Data\StoreInterface;
17+
use Magento\Store\Block\Switcher;
18+
use Magento\Store\Model\ScopeInterface;
19+
use Magento\Store\Model\Store;
20+
use Magento\Store\Model\StoreManagerInterface;
21+
use Magento\Store\Model\Website;
22+
use PHPUnit\Framework\MockObject\MockObject;
23+
use PHPUnit\Framework\TestCase;
1024

11-
class SwitcherTest extends \PHPUnit\Framework\TestCase
25+
/**
26+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
27+
*/
28+
class SwitcherTest extends TestCase
1229
{
13-
/** @var \Magento\Store\Block\Switcher */
14-
protected $switcher;
15-
16-
/** @var \Magento\Framework\View\Element\Template\Context|\PHPUnit_Framework_MockObject_MockObject */
17-
protected $context;
30+
/**
31+
* @var Switcher
32+
*/
33+
private $switcher;
1834

19-
/** @var \Magento\Framework\Data\Helper\PostHelper|\PHPUnit_Framework_MockObject_MockObject */
20-
protected $corePostDataHelper;
35+
/**
36+
* @var PostHelper|MockObject
37+
*/
38+
private $corePostDataHelperMock;
2139

22-
/** @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */
23-
protected $storeManager;
40+
/**
41+
* @var StoreManagerInterface|MockObject
42+
*/
43+
private $storeManagerMock;
2444

25-
/** @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject */
26-
protected $urlBuilder;
45+
/**
46+
* @var UrlInterface|MockObject
47+
*/
48+
private $urlBuilderMock;
2749

28-
/** @var \Magento\Store\Api\Data\StoreInterface|\PHPUnit_Framework_MockObject_MockObject */
29-
private $store;
50+
/**
51+
* @var ScopeConfigInterface|MockObject
52+
*/
53+
private $scopeConfigMock;
3054

3155
/**
3256
* @return void
3357
*/
34-
protected function setUp()
58+
protected function setUp(): void
3559
{
36-
$this->storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)->getMock();
37-
$this->urlBuilder = $this->createMock(\Magento\Framework\UrlInterface::class);
38-
$this->context = $this->createMock(\Magento\Framework\View\Element\Template\Context::class);
39-
$this->context->expects($this->any())->method('getStoreManager')->will($this->returnValue($this->storeManager));
40-
$this->context->expects($this->any())->method('getUrlBuilder')->will($this->returnValue($this->urlBuilder));
41-
$this->corePostDataHelper = $this->createMock(\Magento\Framework\Data\Helper\PostHelper::class);
42-
$this->store = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)
43-
->disableOriginalConstructor()
44-
->getMockForAbstractClass();
60+
$this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class)->getMock();
61+
$this->urlBuilderMock = $this->createMock(UrlInterface::class);
62+
$this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class);
63+
$contextMock = $this->createMock(Context::class);
64+
$contextMock->method('getStoreManager')->willReturn($this->storeManagerMock);
65+
$contextMock->method('getUrlBuilder')->willReturn($this->urlBuilderMock);
66+
$contextMock->method('getScopeConfig')->willReturn($this->scopeConfigMock);
67+
$this->corePostDataHelperMock = $this->createMock(PostHelper::class);
4568
$this->switcher = (new ObjectManager($this))->getObject(
46-
\Magento\Store\Block\Switcher::class,
69+
Switcher::class,
4770
[
48-
'context' => $this->context,
49-
'postDataHelper' => $this->corePostDataHelper,
71+
'context' => $contextMock,
72+
'postDataHelper' => $this->corePostDataHelperMock,
5073
]
5174
);
5275
}
5376

77+
public function testGetStoresSortOrder()
78+
{
79+
$groupId = 1;
80+
$storesSortOrder = [
81+
1 => 2,
82+
2 => 4,
83+
3 => 1,
84+
4 => 3
85+
];
86+
87+
$currentStoreMock = $this->getMockBuilder(Store::class)
88+
->disableOriginalConstructor()
89+
->getMock();
90+
$currentStoreMock->method('getGroupId')->willReturn($groupId);
91+
$currentStoreMock->method('isUseStoreInUrl')->willReturn(false);
92+
$this->storeManagerMock->method('getStore')
93+
->willReturn($currentStoreMock);
94+
95+
$currentWebsiteMock = $this->getMockBuilder(Website::class)
96+
->disableOriginalConstructor()
97+
->getMock();
98+
$this->storeManagerMock->method('getWebsite')
99+
->willReturn($currentWebsiteMock);
100+
101+
$stores = [];
102+
foreach ($storesSortOrder as $storeId => $sortOrder) {
103+
$storeMock = $this->getMockBuilder(Store::class)
104+
->disableOriginalConstructor()
105+
->setMethods(['getId', 'getGroupId', 'getSortOrder', 'isActive', 'getUrl'])
106+
->getMock();
107+
$storeMock->method('getId')->willReturn($storeId);
108+
$storeMock->method('getGroupId')->willReturn($groupId);
109+
$storeMock->method('getSortOrder')->willReturn($sortOrder);
110+
$storeMock->method('isActive')->willReturn(true);
111+
$storeMock->method('getUrl')->willReturn('https://example.org');
112+
$stores[] = $storeMock;
113+
}
114+
115+
$scopeConfigMap = array_map(static function ($item) {
116+
return [
117+
Data::XML_PATH_DEFAULT_LOCALE,
118+
ScopeInterface::SCOPE_STORE,
119+
$item,
120+
'en_US'
121+
];
122+
}, $stores);
123+
$this->scopeConfigMock->method('getValue')
124+
->willReturnMap($scopeConfigMap);
125+
126+
$currentWebsiteMock->method('getStores')
127+
->willReturn($stores);
128+
129+
$this->assertEquals([3, 1, 4, 2], array_keys($this->switcher->getStores()));
130+
}
131+
54132
/**
55133
* @return void
56134
*/
57135
public function testGetTargetStorePostData()
58136
{
59-
$store = $this->getMockBuilder(\Magento\Store\Model\Store::class)
137+
$storeMock = $this->getMockBuilder(Store::class)
60138
->disableOriginalConstructor()
61139
->getMock();
62-
$store->expects($this->any())
63-
->method('getCode')
140+
$oldStoreMock = $this->getMockBuilder(StoreInterface::class)
141+
->disableOriginalConstructor()
142+
->getMockForAbstractClass();
143+
$storeMock->method('getCode')
64144
->willReturn('new-store');
65145
$storeSwitchUrl = 'http://domain.com/stores/store/redirect';
66-
$store->expects($this->atLeastOnce())
146+
$storeMock->expects($this->atLeastOnce())
67147
->method('getCurrentUrl')
68148
->with(false)
69149
->willReturn($storeSwitchUrl);
70-
$this->storeManager->expects($this->once())
150+
$this->storeManagerMock->expects($this->once())
71151
->method('getStore')
72-
->willReturn($this->store);
73-
$this->store->expects($this->once())
152+
->willReturn($oldStoreMock);
153+
$oldStoreMock->expects($this->once())
74154
->method('getCode')
75155
->willReturn('old-store');
76-
$this->urlBuilder->expects($this->once())
156+
$this->urlBuilderMock->expects($this->once())
77157
->method('getUrl')
78158
->willReturn($storeSwitchUrl);
79-
$this->corePostDataHelper->expects($this->any())
80-
->method('getPostData')
159+
$this->corePostDataHelperMock->method('getPostData')
81160
->with($storeSwitchUrl, ['___store' => 'new-store', 'uenc' => null, '___from_store' => 'old-store']);
82161

83-
$this->switcher->getTargetStorePostData($store);
162+
$this->switcher->getTargetStorePostData($storeMock);
84163
}
85164

86165
/**
@@ -89,11 +168,11 @@ public function testGetTargetStorePostData()
89168
*/
90169
public function testIsStoreInUrl($isUseStoreInUrl)
91170
{
92-
$storeMock = $this->createMock(\Magento\Store\Model\Store::class);
171+
$storeMock = $this->createMock(Store::class);
93172

94-
$storeMock->expects($this->once())->method('isUseStoreInUrl')->will($this->returnValue($isUseStoreInUrl));
173+
$storeMock->expects($this->once())->method('isUseStoreInUrl')->willReturn($isUseStoreInUrl);
95174

96-
$this->storeManager->expects($this->any())->method('getStore')->will($this->returnValue($storeMock));
175+
$this->storeManagerMock->method('getStore')->willReturn($storeMock);
97176
$this->assertEquals($this->switcher->isStoreInUrl(), $isUseStoreInUrl);
98177
// check value is cached
99178
$this->assertEquals($this->switcher->isStoreInUrl(), $isUseStoreInUrl);
@@ -103,7 +182,7 @@ public function testIsStoreInUrl($isUseStoreInUrl)
103182
* @see self::testIsStoreInUrlDataProvider()
104183
* @return array
105184
*/
106-
public function isStoreInUrlDataProvider()
185+
public function isStoreInUrlDataProvider(): array
107186
{
108187
return [[true], [false]];
109188
}

0 commit comments

Comments
 (0)