Skip to content

Commit bffbb68

Browse files
committed
PB-314: Error on PageBuilder if sortInstances[$sortOption] is not exists
1 parent aed6d94 commit bffbb68

File tree

2 files changed

+182
-6
lines changed

2 files changed

+182
-6
lines changed

app/code/Magento/PageBuilder/Model/Catalog/Sorting.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,15 @@ public function getSortingOptions(): array
6262
* Get the instance of the first option which is None
6363
*
6464
* @param string $sortOption
65-
* @return Sorting\OptionInterface
65+
* @return Sorting\OptionInterface|null
6666
*/
67-
public function getSortingInstance($sortOption): Sorting\OptionInterface
67+
public function getSortingInstance($sortOption): ?Sorting\OptionInterface
6868
{
6969
if (isset($this->sortInstances[$sortOption])) {
7070
return $this->sortInstances[$sortOption];
7171
}
72+
73+
return null;
7274
}
7375

7476
/**
@@ -83,12 +85,14 @@ public function applySorting(
8385
\Magento\Catalog\Model\ResourceModel\Product\Collection $collection
8486
): \Magento\Catalog\Model\ResourceModel\Product\Collection {
8587
$sortBuilder = $this->getSortingInstance($option);
86-
$_collection = $sortBuilder->sort($collection);
88+
if ($sortBuilder) {
89+
$collection = $sortBuilder->sort($collection);
90+
}
8791

88-
if ($_collection->isLoaded()) {
89-
$_collection->clear();
92+
if ($collection->isLoaded()) {
93+
$collection->clear();
9094
}
9195

92-
return $_collection;
96+
return $collection;
9397
}
9498
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
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\PageBuilder\Test\Unit\Model\Catalog;
9+
10+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
11+
use PHPUnit\Framework\MockObject\MockObject;
12+
use PHPUnit\Framework\MockObject\Stub\ReturnValueMap;
13+
use Magento\PageBuilder\Model\Catalog\Sorting\OptionInterface;
14+
use Magento\PageBuilder\Model\Catalog\Sorting\Factory;
15+
use Magento\PageBuilder\Model\Catalog\Sorting;
16+
use PHPUnit\Framework\TestCase;
17+
18+
/**
19+
* Test for Sorting.
20+
*/
21+
class SortingTest extends TestCase
22+
{
23+
/**
24+
* @var ObjectManager
25+
*/
26+
private $objectManager;
27+
28+
/**
29+
* @var Factory|MockObject
30+
*/
31+
private $sortingFactoryMock;
32+
33+
/**
34+
* @inheritdoc
35+
*/
36+
protected function setUp()
37+
{
38+
$this->objectManager = new ObjectManager($this);
39+
$this->sortingFactoryMock = $this->createMock(Factory::class);
40+
}
41+
42+
/**
43+
* Tests getSortingInstance method.
44+
*
45+
* @return void
46+
*/
47+
public function testGetSortingInstance(): void
48+
{
49+
$sortClassesMap = [
50+
'position' => [
51+
'className' => 'Magento\PageBuilder\Model\Catalog\Sorting\Position',
52+
'label' => 'Position',
53+
],
54+
'position_by_sku' => [
55+
'className' => 'Magento\PageBuilder\Model\Catalog\Sorting\PositionBySku',
56+
'label' => 'Position',
57+
],
58+
];
59+
$optionMocks = $this->createOptionMocks($sortClassesMap);
60+
$model = $this->createTestingModel($optionMocks, $sortClassesMap);
61+
62+
$this->assertEquals(
63+
$optionMocks['position'],
64+
$model->getSortingInstance('position'),
65+
"Appropriate sort class should be returned."
66+
);
67+
68+
$this->assertEquals(
69+
$optionMocks['position_by_sku'],
70+
$model->getSortingInstance('position_by_sku'),
71+
"Appropriate sort class should be returned."
72+
);
73+
74+
$this->assertNull(
75+
$model->getSortingInstance('non-existent-class'),
76+
"Null should be returned for an unassigned sort class."
77+
);
78+
}
79+
80+
/**
81+
* Creates testing model.
82+
* Creates testing model with mocked Sorting Factory and populated with Option mocks.
83+
*
84+
* @param OptionInterface[]|MockObject[] $optionMocks
85+
* @param array $sortClassesMap
86+
* @return Sorting
87+
*/
88+
private function createTestingModel(array $optionMocks = [], array $sortClassesMap = []): Sorting
89+
{
90+
$factoryValueMap = $this->createFactoryValueMap($optionMocks, $sortClassesMap);
91+
92+
$this->sortingFactoryMock->method('create')
93+
->will($factoryValueMap);
94+
95+
$sortClasses = [];
96+
97+
foreach ($sortClassesMap as $key => $value) {
98+
$sortClasses[$key] = $value['className'];
99+
}
100+
101+
return $this->objectManager->getObject(
102+
Sorting::class,
103+
[
104+
'factory' => $this->sortingFactoryMock,
105+
'sortClasses' => $sortClasses,
106+
]
107+
);
108+
}
109+
110+
/**
111+
* Creates value map for the create method of Sorting Factory Mock.
112+
*
113+
* @param array $optionMocks
114+
* @param array $sortClassesMap
115+
* @return ReturnValueMap
116+
*/
117+
private function createFactoryValueMap(array $optionMocks, array $sortClassesMap): ReturnValueMap
118+
{
119+
$map = [];
120+
121+
foreach ($optionMocks as $key => $mock) {
122+
$map[] = [$sortClassesMap[$key]['className'], [], $mock];
123+
}
124+
125+
return $this->returnValueMap($map);
126+
}
127+
128+
/**
129+
* Creates OptionInterface mocks by the given configurations.
130+
*
131+
* The optionMocksConfiguration parameter should be like:
132+
* [
133+
* 'position' => [
134+
* 'className' => 'Magento\PageBuilder\Model\Catalog\Sorting\Position',
135+
* 'label' => 'Position',
136+
* ],
137+
* 'position_by_sku' => [
138+
* 'className' => 'Magento\PageBuilder\Model\Catalog\Sorting\PositionBySku',
139+
* 'label' => 'Position by sku',
140+
* ],
141+
* ...
142+
* ]
143+
*
144+
* @param array $optionMocksConfiguration
145+
* @return OptionInterface[]|MockObject[] OptionInterface mocks indexed by configuration keys
146+
*/
147+
private function createOptionMocks(array $optionMocksConfiguration): array
148+
{
149+
$mocks = [];
150+
151+
foreach ($optionMocksConfiguration as $key => $optionMockConfiguration) {
152+
$mocks[$key] = $this->createOptionMock($optionMockConfiguration['label']);
153+
}
154+
155+
return $mocks;
156+
}
157+
158+
/**
159+
* Creates OptionInterface mock object.
160+
*
161+
* @param string $label
162+
* @return OptionInterface|MockObject
163+
*/
164+
private function createOptionMock(string $label): MockObject
165+
{
166+
$mock = $this->createMock(OptionInterface::class);
167+
$mock->method('getLabel')
168+
->willReturn(__($label));
169+
170+
return $mock;
171+
}
172+
}

0 commit comments

Comments
 (0)