Skip to content
This repository was archived by the owner on Apr 29, 2019. It is now read-only.

Commit 2933325

Browse files
committed
MAGETWO-71520: Product Grid filtered to Store View is broken if corresponding Store is deleted
- fixing grid to render and reset filters if filters will throw an exception - covering with functional tests
1 parent 29bc9ad commit 2933325

File tree

10 files changed

+510
-8
lines changed

10 files changed

+510
-8
lines changed

app/code/Magento/Ui/Controller/Adminhtml/Index/Render.php

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,49 @@
77

88
use Magento\Ui\Controller\Adminhtml\AbstractAction;
99
use Magento\Framework\View\Element\UiComponentInterface;
10+
use Magento\Backend\App\Action\Context;
11+
use Magento\Framework\View\Element\UiComponentFactory;
1012

1113
class Render extends AbstractAction
1214
{
15+
/**
16+
* @var \Magento\Framework\Controller\Result\JsonFactory
17+
*/
18+
private $resultJsonFactory;
19+
20+
/**
21+
* @var \Magento\Framework\Escaper
22+
*/
23+
private $escaper;
24+
25+
/**
26+
* @var \Psr\Log\LoggerInterface
27+
*/
28+
private $logger;
29+
30+
/**
31+
* @param Context $context
32+
* @param UiComponentFactory $factory
33+
* @param \Magento\Framework\Controller\Result\JsonFactory|null $resultJsonFactory
34+
* @param \Magento\Framework\Escaper|null $escaper
35+
* @param \Psr\Log\LoggerInterface|null $logger
36+
*/
37+
public function __construct(
38+
Context $context,
39+
UiComponentFactory $factory,
40+
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory = null,
41+
\Magento\Framework\Escaper $escaper = null,
42+
\Psr\Log\LoggerInterface $logger = null
43+
) {
44+
parent::__construct($context, $factory);
45+
$this->resultJsonFactory = $resultJsonFactory ?: $this->_objectManager
46+
->get(\Magento\Framework\Controller\Result\JsonFactory::class);
47+
$this->escaper = $escaper ?: $this->_objectManager
48+
->get(\Magento\Framework\Escaper::class);
49+
$this->logger = $logger ?: $this->_objectManager
50+
->get(\Psr\Log\LoggerInterface::class);
51+
}
52+
1353
/**
1454
* Action for AJAX request
1555
*
@@ -22,10 +62,40 @@ public function execute()
2262
return;
2363
}
2464

25-
$component = $this->factory->create($this->_request->getParam('namespace'));
26-
if ($this->validateAclResource($component->getContext()->getDataProvider()->getConfigData())) {
27-
$this->prepareComponent($component);
28-
$this->_response->appendBody((string) $component->render());
65+
try {
66+
$component = $this->factory->create($this->_request->getParam('namespace'));
67+
if ($this->validateAclResource($component->getContext()->getDataProvider()->getConfigData())) {
68+
$this->prepareComponent($component);
69+
$this->_response->appendBody((string) $component->render());
70+
}
71+
} catch (\Magento\Framework\Exception\LocalizedException $e) {
72+
$this->logger->critical($e);
73+
$result = [
74+
'error' => $this->escaper->escapeHtml($e->getMessage()),
75+
'errorcode' => $this->escaper->escapeHtml($e->getCode())
76+
];
77+
/** @var \Magento\Framework\Controller\Result\Json $resultJson */
78+
$resultJson = $this->resultJsonFactory->create();
79+
$resultJson->setStatusHeader(
80+
\Zend\Http\Response::STATUS_CODE_400,
81+
\Zend\Http\AbstractMessage::VERSION_11,
82+
'Bad Request'
83+
);
84+
return $resultJson->setData($result);
85+
} catch (\Exception $e) {
86+
$this->logger->critical($e);
87+
$result = [
88+
'error' => _('UI component could not be rendered because of system exception'),
89+
'errorcode' => $this->escaper->escapeHtml($e->getCode())
90+
];
91+
/** @var \Magento\Framework\Controller\Result\Json $resultJson */
92+
$resultJson = $this->resultJsonFactory->create();
93+
$resultJson->setStatusHeader(
94+
\Zend\Http\Response::STATUS_CODE_400,
95+
\Zend\Http\AbstractMessage::VERSION_11,
96+
'Bad Request'
97+
);
98+
return $resultJson->setData($result);
2999
}
30100
}
31101

app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ define([
1010
'underscore',
1111
'mageUtils',
1212
'uiLayout',
13-
'uiCollection'
14-
], function (_, utils, layout, Collection) {
13+
'uiCollection',
14+
'mage/translate',
15+
'jquery'
16+
], function (_, utils, layout, Collection, $t, $) {
1517
'use strict';
1618

1719
/**
@@ -48,6 +50,7 @@ define([
4850
stickyTmpl: 'ui/grid/sticky/filters',
4951
_processed: [],
5052
columnsProvider: 'ns = ${ $.ns }, componentType = columns',
53+
bookmarksProvider: 'ns = ${ $.ns }, componentType = bookmark',
5154
applied: {
5255
placeholder: true
5356
},
@@ -102,7 +105,9 @@ define([
102105
applied: '${ $.provider }:params.filters'
103106
},
104107
imports: {
105-
'onColumnsUpdate': '${ $.columnsProvider }:elems'
108+
onColumnsUpdate: '${ $.columnsProvider }:elems',
109+
onBackendError: '${ $.provider }:lastError',
110+
bookmarksActiveIndex: '${ $.bookmarksProvider }:activeIndex'
106111
},
107112
modules: {
108113
columns: '${ $.columnsProvider }',
@@ -350,6 +355,15 @@ define([
350355
return this.active.length;
351356
},
352357

358+
/**
359+
* Assigns filters index change.
360+
*
361+
* @param {integer} index - Selected index of the filter.
362+
*/
363+
onActiveIndexChange: function (index) {
364+
this.activeIndex = index;
365+
},
366+
353367
/**
354368
* Extract previews of a specified filters.
355369
*
@@ -371,6 +385,37 @@ define([
371385
*/
372386
onColumnsUpdate: function (columns) {
373387
columns.forEach(this.addFilter, this);
388+
},
389+
390+
/**
391+
* Provider ajax error listener.
392+
*
393+
* @param {bool} isError - Selected index of the filter.
394+
*/
395+
onBackendError: function (isError) {
396+
var defaultMessage = 'Something went wrong with processing the default view and we have restored the' +
397+
' filter to its original state.',
398+
customMessage = 'Something went wrong with processing current custom view and filters have been' +
399+
' reset to its original state. Please edit filters then click apply.';
400+
401+
if (isError) {
402+
this.clear();
403+
404+
$('body').notification('clear')
405+
.notification('add', {
406+
error: true,
407+
message: $.mage.__(this.bookmarksActiveIndex !== 'default' ? customMessage : defaultMessage),
408+
409+
/**
410+
* @param {String} message
411+
*/
412+
insertMethod: function (message) {
413+
var $wrapper = $('<div/>').html(message);
414+
415+
$('.page-main-actions').after($wrapper);
416+
}
417+
});
418+
}
374419
}
375420
});
376421
});

app/code/Magento/Ui/view/base/web/js/grid/provider.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ define([
120120

121121
request
122122
.done(this.onReload)
123-
.fail(this.onError);
123+
.fail(this.onError.bind(this));
124124

125125
return request;
126126
},
@@ -144,6 +144,10 @@ define([
144144
return;
145145
}
146146

147+
this.set('lastError', true);
148+
149+
this.firstLoad = false;
150+
147151
alert({
148152
content: $t('Something went wrong.')
149153
});
@@ -157,6 +161,8 @@ define([
157161
onReload: function (data) {
158162
this.firstLoad = false;
159163

164+
this.set('lastError', false);
165+
160166
this.setData(data)
161167
.trigger('reloaded');
162168
},

dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/StoreGrid.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,18 @@ public function searchAndOpenWebsite(Website $website)
9999
$this->_rootElement->find(sprintf($this->storeName, $websiteName), Locator::SELECTOR_XPATH)->click();
100100
}
101101

102+
/**
103+
* Search and open appropriate Website by name.
104+
*
105+
* @param string $websiteName
106+
* @return void
107+
*/
108+
public function searchAndOpenWebsiteByName($websiteName)
109+
{
110+
$this->search(['website_title' => $websiteName]);
111+
$this->_rootElement->find(sprintf($this->storeName, $websiteName), Locator::SELECTOR_XPATH)->click();
112+
}
113+
102114
/**
103115
* Search and open appropriate Store View.
104116
*

dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Grid.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ class Grid extends DataGrid
6060
'selector' => '[name="attribute_set_id"]',
6161
'input' => 'select',
6262
],
63+
'store_id' => [
64+
'selector' => '[name="store_id"]',
65+
'input' => 'select',
66+
],
6367
];
6468

6569
/**
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Catalog\Test\Constraint;
8+
9+
/**
10+
* Assert that product grid is rendered correctly.
11+
*/
12+
class AssertProductGridIsRendered extends \Magento\Mtf\Constraint\AbstractConstraint
13+
{
14+
/**
15+
* Assert that product grid is rendered correctly.
16+
*
17+
* @param \Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex $catalogProductIndex
18+
* @return void
19+
*/
20+
public function processAssert(
21+
\Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex $catalogProductIndex
22+
) {
23+
$productId = $catalogProductIndex->open()->getProductGrid()->getFirstItemId();
24+
\PHPUnit_Framework_Assert::assertNotNull(
25+
$productId,
26+
'Product grid is not rendered correctly.'
27+
);
28+
}
29+
30+
/**
31+
* Returns a string representation of the object.
32+
*
33+
* @return string
34+
*/
35+
public function toString()
36+
{
37+
return 'Product grid is rendered correctly.';
38+
}
39+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Catalog\Test\Constraint;
8+
9+
/**
10+
* Assert that filters have been reset successfully.
11+
*/
12+
class AssertResetFilterMessage extends \Magento\Mtf\Constraint\AbstractConstraint
13+
{
14+
/**
15+
* Assert message that filters have been reset.
16+
*
17+
* @param \Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex $catalogProductIndex
18+
* @return void
19+
*/
20+
public function processAssert(
21+
\Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex $catalogProductIndex
22+
) {
23+
\PHPUnit_Framework_Assert::assertContains(
24+
'restored the filter to its original state',
25+
$catalogProductIndex->getMessagesBlock()->getErrorMessage()
26+
);
27+
}
28+
29+
/**
30+
* Returns a string representation of the object.
31+
*
32+
* @return string
33+
*/
34+
public function toString()
35+
{
36+
return 'Filters have been reset successfully.';
37+
}
38+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd">
9+
<testCase name="Magento\Ui\Test\TestCase\GridFilteringDeletedEntityTest" summary="Grid filtering by deleted entity" ticketId="MAGETWO-71940">
10+
<variation name="GridFilteringDeletedEntityTestVariation1">
11+
<data name="tag" xsi:type="string">severity:S2</data>
12+
<data name="steps" xsi:type="array">
13+
<item name="0" xsi:type="array">
14+
<item name="0" xsi:type="string">Magento\Store\Test\TestStep\DeleteWebsitesEntityStep</item>
15+
</item>
16+
</data>
17+
<data name="fixtureName" xsi:type="string">catalogProductSimple</data>
18+
<data name="fixtureDataSet" xsi:type="string">product_with_additional_website</data>
19+
<data name="filters" xsi:type="array">
20+
<item name="0" xsi:type="array">
21+
<item name="name" xsi:type="string">:name</item>
22+
</item>
23+
</data>
24+
<data name="pageClass" xsi:type="string">Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex</data>
25+
<data name="gridRetriever" xsi:type="string">getProductGrid</data>
26+
<constraint name="\Magento\Catalog\Test\Constraint\AssertProductGridIsRendered"/>
27+
<constraint name="Magento\Catalog\Test\Constraint\AssertResetFilterMessage"/>
28+
</variation>
29+
</testCase>
30+
</config>

0 commit comments

Comments
 (0)