Skip to content

Commit c3aab07

Browse files
committed
MAGETWO-54361: Configurable variation is displayed on category/product page when is out of stock
- Update logic in plugin; - Add unit test; - Functional test updated;
1 parent 3610727 commit c3aab07

File tree

7 files changed

+166
-20
lines changed

7 files changed

+166
-20
lines changed

app/code/Magento/CatalogInventoryConfigurableProduct/Plugin/GetInStockAttributeOptionsPlugin.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
use Magento\CatalogInventory\Api\StockStatusRepositoryInterface;
1010
use Magento\ConfigurableProduct\Model\AttributeOptionProviderInterface;
1111

12+
/**
13+
* Check what option is out of stock and remove it from result
14+
*/
1215
class GetInStockAttributeOptionsPlugin
1316
{
1417
/**
@@ -52,15 +55,16 @@ public function afterGetAttributeOptions(AttributeOptionProviderInterface $subje
5255
$criteria->addFilter('sku', 'sku', ['in' => $sku], 'public');
5356
$collection = $this->stockStatusRepository->getList($criteria);
5457

58+
if (!$collection->getTotalCount()) {
59+
return [];
60+
}
5561
$inStockSku = [];
5662
foreach ($collection->getItems() as $inStockOption) {
5763
$inStockSku[] = $inStockOption->getData('sku');
5864
}
59-
if (!empty($inStockSku)) {
60-
foreach ($options as $key => $option) {
61-
if (!in_array($options[$key]['sku'], $inStockSku)) {
62-
unset($options[$key]);
63-
}
65+
foreach ($options as $key => $option) {
66+
if (!in_array($options[$key]['sku'], $inStockSku)) {
67+
unset($options[$key]);
6468
}
6569
}
6670
$options = array_values($options);

app/code/Magento/CatalogInventoryConfigurableProduct/Test/Unit/Plugin/GetInStockAttributeOptionsPluginTest.php

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ protected function setUp()
6868
->getMockForAbstractClass();
6969
$this->stockStatusCollection = $this->getMockBuilder(StockStatusCollectionInterface::class)
7070
->disableOriginalConstructor()
71+
->setMethods(['getItems'])
7172
->getMockForAbstractClass();
7273

7374
$this->objectManagerHelper = new ObjectManagerHelper($this);
@@ -120,7 +121,10 @@ public function testGetInStockAttributeOptions(array $options)
120121
$this->stockStatusRepository->expects($this->once())
121122
->method('getList')
122123
->willReturn($this->stockStatusCollection);
123-
$this->stockStatusCollection->expects($this->at(0))
124+
$this->stockStatusCollection->expects($this->once())
125+
->method('getTotalCount')
126+
->willReturn(2);
127+
$this->stockStatusCollection->expects($this->any())
124128
->method('getItems')
125129
->willReturn($statuses);
126130
$status1->expects($this->atLeastOnce())
@@ -136,6 +140,105 @@ public function testGetInStockAttributeOptions(array $options)
136140
);
137141
}
138142

143+
/**
144+
* @param array $options
145+
* @dataProvider testOptionsDataProvider
146+
*/
147+
public function testGetInStockAttributeOptionsWithAllOutOfStock(array $options)
148+
{
149+
$expectedOptions = [];
150+
$this->stockStatusCriteriaFactory->expects($this->once())
151+
->method('create')
152+
->willReturn($this->stockStatusCriteria);
153+
$this->stockStatusCriteria->expects($this->atLeastOnce())
154+
->method('addFilter')
155+
->willReturnSelf();
156+
$this->stockStatusRepository->expects($this->once())
157+
->method('getList')
158+
->willReturn($this->stockStatusCollection);
159+
$this->stockStatusCollection->expects($this->once())
160+
->method('getTotalCount')
161+
->willReturn(0);
162+
163+
$this->assertEquals(
164+
$expectedOptions,
165+
$this->plugin->afterGetAttributeOptions($this->attributeOptionProvider, $options)
166+
);
167+
}
168+
169+
/**
170+
* @param array $options
171+
* @dataProvider testOptionsDataProvider
172+
*/
173+
public function testGetInStockAttributeOptionsWithAllInStock(array $options)
174+
{
175+
$expectedOptions = [
176+
[
177+
'sku' => 'Configurable1-Black',
178+
'product_id' => 4,
179+
'attribute_code' => 'color',
180+
'value_index' => '13',
181+
'option_title' => 'Black'
182+
],
183+
[
184+
'sku' => 'Configurable1-White',
185+
'product_id' => 4,
186+
'attribute_code' => 'color',
187+
'value_index' => '14',
188+
'option_title' => 'White'
189+
],
190+
[
191+
'sku' => 'Configurable1-Red',
192+
'product_id' => 4,
193+
'attribute_code' => 'color',
194+
'value_index' => '15',
195+
'option_title' => 'Red'
196+
]
197+
];
198+
$status1 = $this->getMockBuilder(StockStatusInterface::class)
199+
->setMethods(['getData'])
200+
->disableOriginalConstructor()
201+
->getMockForAbstractClass();
202+
$status2 = $this->getMockBuilder(StockStatusInterface::class)
203+
->setMethods(['getData'])
204+
->disableOriginalConstructor()
205+
->getMockForAbstractClass();
206+
$status3 = $this->getMockBuilder(StockStatusInterface::class)
207+
->setMethods(['getData'])
208+
->disableOriginalConstructor()
209+
->getMockForAbstractClass();
210+
$statuses = [$status1, $status2, $status3];
211+
$this->stockStatusCriteriaFactory->expects($this->once())
212+
->method('create')
213+
->willReturn($this->stockStatusCriteria);
214+
$this->stockStatusCriteria->expects($this->atLeastOnce())
215+
->method('addFilter')
216+
->willReturnSelf();
217+
$this->stockStatusRepository->expects($this->once())
218+
->method('getList')
219+
->willReturn($this->stockStatusCollection);
220+
$this->stockStatusCollection->expects($this->once())
221+
->method('getTotalCount')
222+
->willReturn(3);
223+
$this->stockStatusCollection->expects($this->any())
224+
->method('getItems')
225+
->willReturn($statuses);
226+
$status1->expects($this->atLeastOnce())
227+
->method('getData')
228+
->willReturn('Configurable1-Black');
229+
$status2->expects($this->atLeastOnce())
230+
->method('getData')
231+
->willReturn('Configurable1-White');
232+
$status3->expects($this->atLeastOnce())
233+
->method('getData')
234+
->willReturn('Configurable1-Red');
235+
236+
$this->assertEquals(
237+
$expectedOptions,
238+
$this->plugin->afterGetAttributeOptions($this->attributeOptionProvider, $options)
239+
);
240+
}
241+
139242
/**
140243
* @return array
141244
*/

dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public function getOptions(FixtureInterface $product)
153153
*
154154
* @return array
155155
*/
156-
public function getListOptions()
156+
protected function getListOptions()
157157
{
158158
$customOptions = [];
159159

@@ -226,7 +226,7 @@ protected function getFileData(SimpleElement $option)
226226
* @param SimpleElement $option
227227
* @return array
228228
*/
229-
public function getDropdownData(SimpleElement $option)
229+
protected function getDropdownData(SimpleElement $option)
230230
{
231231
$select = $option->find($this->selectOption, Locator::SELECTOR_XPATH, 'select');
232232
// Skip "Choose option ..."(option #1)
@@ -328,7 +328,7 @@ protected function getTimeData(SimpleElement $option)
328328
* @param int $firstOption
329329
* @return array
330330
*/
331-
protected function getSelectOptionsData(SimpleElement $element, $firstOption = 1)
331+
public function getSelectOptionsData(SimpleElement $element, $firstOption = 1)
332332
{
333333
$listOptions = [];
334334

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
/**
1515
* Assert that out of stock configurable option is not displayed on product page.
1616
*/
17-
class AssertProductOptionsOnProductPage extends AbstractConstraint
17+
class AssertOutOfStockOptionIsAbsentOnOnProductPage extends AbstractConstraint
1818
{
1919
/**
2020
* Assert that out of stock configurable option is not displayed on product page on frontend.
@@ -32,31 +32,31 @@ public function processAssert(
3232
$outOfStockOption
3333
) {
3434
$browser->open($_ENV['app_frontend_url'] . $product->getUrlKey() . '.html');
35-
$listOptions = $catalogProductView->getConfigurableAttributesBlock()->getListOptions();
35+
$listOptions = $catalogProductView->getConfigurableAttributesBlock()->getPresentOptions();
3636
$productOptions = [];
3737
foreach ($listOptions as $option) {
38-
$productOptions = $catalogProductView->getConfigurableAttributesBlock()->getDropdownData($option);
38+
$productOptions = $catalogProductView->getConfigurableAttributesBlock()->getSelectOptionsData($option);
3939
}
40-
$option = $this->searchForOption($outOfStockOption, $productOptions);
41-
\PHPUnit_Framework_Assert::assertNull($option, 'Out of stock option is present on product page.');
40+
$option = $this->isOptionPresent($outOfStockOption, $productOptions);
41+
\PHPUnit_Framework_Assert::assertTrue($option, 'Out of stock option is present on product page.');
4242
}
4343

4444
/**
45-
* Search for option.
45+
* Check if option is present on product page.
4646
*
4747
* @param string $needle
4848
* @param array $haystack
49-
* @return int|null|string
49+
* @return bool
5050
*/
51-
private function searchForOption($needle, $haystack) {
51+
private function isOptionPresent($needle, array $haystack) {
5252
foreach ($haystack as $options) {
5353
foreach ($options as $key => $option) {
5454
if ($option['title'] === $needle) {
55-
return $key;
55+
return false;
5656
}
5757
}
5858
}
59-
return null;
59+
return true;
6060
}
6161

6262
/**

dev/tests/functional/tests/app/Magento/CatalogInventoryConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<data name="product/data/description" xsi:type="string">Configurable Product description %isolation%</data>
2020
<data name="outOfStockOption" xsi:type="string">SIZE_S</data>
2121
<constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" />
22-
<constraint name="Magento\CatalogInventoryConfigurableProduct\Test\Constraint\AssertProductOptionsOnProductPage" />
22+
<constraint name="Magento\CatalogInventoryConfigurableProduct\Test\Constraint\AssertOutOfStockOptionIsAbsentOnOnProductPage" />
2323
</variation>
2424
</testCase>
2525
</config>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
/**
4+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
9+
<type name="Magento\CatalogInventoryConfigurableProduct\Test\Constraint\AssertOutOfStockOptionIsAbsentOnOnProductPage">
10+
<arguments>
11+
<argument name="severity" xsi:type="string">middle</argument>
12+
</arguments>
13+
</type>
14+
</config>

dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Product/View/ConfigurableOptions.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ class ConfigurableOptions extends CustomOptions
4141
*/
4242
private $tierPricesSelector = '.prices-tier li';
4343

44+
/**
45+
* Locator for configurable option element.
46+
*
47+
* @var string
48+
*/
49+
protected $configurableOptionElement = '#product-options-wrapper > * > .configurable';
50+
4451
/**
4552
* Get configurable product options
4653
*
@@ -188,4 +195,22 @@ protected function chooseOptions($variationOptions, $attributesData)
188195
$this->selectOption($attributeTitle, $optionTitle);
189196
}
190197
}
198+
199+
/**
200+
* Get present options
201+
*
202+
* @return array
203+
*/
204+
public function getPresentOptions()
205+
{
206+
$options = [];
207+
208+
$optionElements = $this->_rootElement->getElements($this->configurableOptionElement);
209+
foreach ($optionElements as $optionElement) {
210+
$title = $optionElement->find($this->title)->getText();
211+
$options[$title] = $optionElement;
212+
}
213+
214+
return $options;
215+
}
191216
}

0 commit comments

Comments
 (0)