Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->

<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
<test name="AdminProductGridUrlFilterApplierTest">
<annotations>
<features value="Catalog"/>
<stories value="Filter product using GET URL parameter"/>
<title value="Verify that filter is applied on product grid when filters parameter is set on url"/>
<description value="Accessing product grid url with filters parameter"/>
<severity value="MAJOR"/>
<testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1320712/scenarios/4931106"/>
<group value="product"/>
</annotations>
<before>
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
<createData entity="simpleProductWithShortNameAndSku" stepKey="createSimpleProduct"/>
</before>
<after>
<actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilter"/>
<deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/>
<actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/>
</after>
<amOnPage url="{{AdminProductIndexPage.url}}?filters[name]=$$createSimpleProduct.name$$" stepKey="navigateToProductGridWithFilters"/>
<waitForPageLoad stepKey="waitForProductGrid"/>
<see selector="{{AdminProductGridSection.productGridNameProduct($$createSimpleProduct.name$$)}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProduct"/>
<seeElement selector="{{AdminProductGridFilterSection.enabledFilters}}" stepKey="seeEnabledFilters"/>
<see selector="{{AdminProductGridFilterSection.enabledFilters}}" userInput="Name: $$createSimpleProduct.name$$" stepKey="seeProductNameFilter"/>
</test>
</tests>
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<referenceContainer name="content">
<uiComponent name="product_listing"/>
<block class="Magento\Catalog\Block\Adminhtml\Product" name="products_list"/>
<block class="Magento\Backend\Block\Template" template="Magento_Catalog::product/grid/url_filter_applier.phtml" name="product_list_url_filter_applier" />
</referenceContainer>
</body>
</page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

/** @var $block \Magento\Backend\Block\Template */
?>
<script type="text/x-magento-init">
{
"*": {
"Magento_Ui/js/grid/url-filter-applier": {
"listingNamespace": "product_listing"
}
}
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
<element name="idColumn" type="button" selector="//div[contains(@data-role, 'grid-wrapper')]/table/thead/tr/th/span[contains(text(), 'ID')]"/>
<element name="clearAll" type="button" selector="//div[@class='admin__data-grid-header']//button[contains(text(), 'Clear all')]"/>
<element name="activeFilters" type="button" selector="//div[@class='admin__data-grid-header']//span[contains(text(), 'Active filters:')]" />
<element name="activeFilterDiv" type="button" selector="(//div[contains(@class, 'admin__data-grid-filters-current') and contains(@class, '_show')])[1]"/>
<element name="FilterBtn" type="input" selector="//button[text()='Filters']"/>
<element name="URLKey" type="input" selector="//div[@class='admin__form-field-control']/input[@name='identifier']"/>
<element name="ApplyFiltersBtn" type="button" selector="//span[text()='Apply Filters']"/>
<element name="blockGridRowByTitle" type="input" selector="//tbody//tr//td//div[contains(., '{{var1}}')]" parameterized="true" timeout="30"/>
</section>
</sections>
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<element name="edit" type="button" selector="//div[text()='{{var1}}']/parent::td//following-sibling::td[@class='data-grid-actions-cell']//a[text()='Edit']" parameterized="true"/>
<element name="preview" type="button" selector="//div[text()='{{var1}}']/parent::td//following-sibling::td[@class='data-grid-actions-cell']//a[text()='View']" parameterized="true"/>
<element name="clearAllButton" type="button" selector="//div[@class='admin__data-grid-header']//button[contains(text(), 'Clear all')]"/>
<element name="clearFilters" type="button" selector=".admin__data-grid-header button[data-action='grid-filter-reset']" timeout="30"/>
<element name="activeFilters" type="button" selector="//div[@class='admin__data-grid-header']//span[contains(text(), 'Active filters:')]" />
<element name="spinner" type="input" selector='//div[@data-component="cms_page_listing.cms_page_listing.cms_page_columns"]'/>
<element name="firstItemSelectButton" type="button" selector=".data-grid .action-select-wrap button.action-select"/>
Expand All @@ -31,5 +32,6 @@
<element name="massActionsButton" type="button" selector="//div[@class='admin__data-grid-header'][(not(ancestor::*[@class='sticky-header']) and not(contains(@style,'visibility: hidden'))) or (ancestor::*[@class='sticky-header' and not(contains(@style,'display: none'))])]//button[contains(@class, 'action-select')]" />
<element name="massActionsOption" type="button" selector="//div[@class='admin__data-grid-header'][(not(ancestor::*[@class='sticky-header']) and not(contains(@style,'visibility: hidden'))) or (ancestor::*[@class='sticky-header' and not(contains(@style,'display: none'))])]//span[contains(@class, 'action-menu-item') and .= '{{action}}']" parameterized="true"/>
<element name="gridDataRow" type="input" selector=".data-row .data-grid-cell-content"/>
<element name="pagesGridRowByTitle" type="input" selector="//tbody//tr//td//div[contains(., '{{var1}}')]" parameterized="true" timeout="30"/>
</section>
</sections>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->

<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
<test name="AdminCmsBlockGridUrlFilterApplierTest">
<annotations>
<features value="Cms"/>
<stories value="Filter CMS block using GET URL parameter"/>
<title value="Verify that filter is applied on block grid when filters parameter is set on url"/>
<description value="Accessing block grid url with filters parameter"/>
<severity value="MAJOR"/>
<testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1320712/scenarios/4931106"/>
<group value="Cms"/>
</annotations>
<before>
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
<createData entity="Sales25offBlock" stepKey="createBlock"/>
</before>
<after>
<actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilter"/>
<deleteData createDataKey="createBlock" stepKey="deletePage"/>
<actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/>
</after>
<amOnPage url="{{CmsBlocksPage.url}}?filters[title]=$$createBlock.title$$" stepKey="navigateToBlockGridWithFilters"/>
<waitForPageLoad stepKey="waitForBlockGrid"/>
<see selector="{{BlockPageActionsSection.blockGridRowByTitle($$createBlock.title$$)}}" userInput="$$createBlock.title$$" stepKey="seeBlock"/>
<seeElement selector="{{BlockPageActionsSection.activeFilterDiv}}" stepKey="seeEnabledFilters"/>
<see selector="{{BlockPageActionsSection.activeFilterDiv}}" userInput="Title: $$createBlock.title$$" stepKey="seeBlockTitleFilter"/>
</test>
</tests>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->

<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
<test name="AdminCmsPageGridUrlFilterApplierTest">
<annotations>
<features value="CmsPage"/>
<stories value="Filter CMS page using GET URL parameter"/>
<title value="Verify that filter is applied on page grid when filters parameter is set on url"/>
<description value="Accessing page grid url with filters parameter"/>
<severity value="MAJOR"/>
<testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1320712/scenarios/4931106"/>
<group value="Cms"/>
</annotations>
<before>
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
<createData entity="_defaultCmsPage" stepKey="createPage"/>
</before>
<after>
<actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilter"/>
<deleteData createDataKey="createPage" stepKey="deletePage"/>
<actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/>
</after>
<amOnPage url="{{CmsPagesPage.url}}?filters[title]=$$createPage.title$$" stepKey="navigateToPageGridWithFilters"/>
<waitForPageLoad stepKey="waitForPageGrid"/>
<see selector="{{CmsPagesPageActionsSection.pagesGridRowByTitle($$createPage.title$$)}}" userInput="$$createPage.title$$" stepKey="seePage"/>
<seeElement selector="{{CmsPagesPageActionsSection.activeFilter}}" stepKey="seeEnabledFilters"/>
<see selector="{{CmsPagesPageActionsSection.activeFilter}}" userInput="Title: $$createPage.title$$" stepKey="seePageTitleFilter"/>
</test>
</tests>
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
<body>
<referenceContainer name="content">
<uiComponent name="cms_block_listing"/>
<block class="Magento\Backend\Block\Template" template="Magento_Cms::url_filter_applier.phtml" name="block_list_url_filter_applier">
<arguments>
<argument name="listing_namespace" xsi:type="string">cms_block_listing</argument>
</arguments>
</block>
</referenceContainer>
<referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" /> <!-- ToDo UI: remove this wrapper with old styles removal. The class name "admin__old" is for tests only, we shouldn't use it in any way -->
</body>
Expand Down
5 changes: 5 additions & 0 deletions app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
<body>
<referenceContainer name="content">
<uiComponent name="cms_page_listing"/>
<block class="Magento\Backend\Block\Template" template="Magento_Cms::url_filter_applier.phtml" name="page_list_url_filter_applier">
<arguments>
<argument name="listing_namespace" xsi:type="string">cms_page_listing</argument>
</arguments>
</block>
</referenceContainer>
</body>
</page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

/** @var $block \Magento\Backend\Block\Template */
/** @var \Magento\Framework\Escaper $escaper */
?>
<script type="text/x-magento-init">
{
"*": {
"Magento_Ui/js/grid/url-filter-applier": {
"listingNamespace": "<?= $escaper->escapeJs($block->getListingNamespace()) ?>"
}
}
}
</script>
80 changes: 80 additions & 0 deletions app/code/Magento/Ui/view/base/web/js/grid/url-filter-applier.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

define([
'uiComponent',
'underscore'
], function (Component, _) {
'use strict';

return Component.extend({
defaults: {
listingNamespace: null,
filterProvider: 'componentType = filters, ns = ${ $.listingNamespace }',
filterKey: 'filters',
searchString: location.search,
modules: {
filterComponent: '${ $.filterProvider }'
}
},

/**
* Init component
*
* @return {exports}
*/
initialize: function () {
this._super();
this.apply();

return this;
},

/**
* Apply filter
*/
apply: function () {
var urlFilter = this.getFilterParam(this.searchString);

if (_.isUndefined(this.filterComponent())) {
setTimeout(function () {
this.apply();
}.bind(this), 100);

return;
}

if (Object.keys(urlFilter).length) {
this.filterComponent().setData(urlFilter, false);
this.filterComponent().apply();
}
},

/**
* Get filter param from url
*
* @returns {Object}
*/
getFilterParam: function (url) {
var searchString = decodeURI(url),
itemArray;

return _.chain(searchString.slice(1).split('&'))
.map(function (item) {
if (item && item.search(this.filterKey) !== -1) {
itemArray = item.split('=');

itemArray[0] = itemArray[0].replace(this.filterKey, '')
.replace(/[\[\]]/g, '');

return itemArray;
}
}.bind(this))
.compact()
.object()
.value();
}
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

/*eslint max-nested-callbacks: 0*/
define([
'Magento_Ui/js/grid/url-filter-applier'
], function (UrlFilterApplier) {
'use strict';

describe('Magento_Ui/js/grid/url-filter-applier', function () {
var urlFilterApplierObj,
filterComponentMock = {
setData: jasmine.createSpy(),
apply: jasmine.createSpy()
};

beforeEach(function () {
urlFilterApplierObj = new UrlFilterApplier({});
urlFilterApplierObj.filterComponent = jasmine.createSpy().and.returnValue(filterComponentMock);
});

describe('"getFilterParam" method', function () {
it('return object from url with a simple filters parameter', function () {
var urlSearch = '?filters[name]=test';

expect(urlFilterApplierObj.getFilterParam(urlSearch)).toEqual({
'name': 'test'
});
});
it('return object from url with multiple filters parameter', function () {
var urlSearch = '?filters[name]=test&filters[qty]=1';

expect(urlFilterApplierObj.getFilterParam(urlSearch)).toEqual({
'name': 'test',
'qty': '1'
});
});
it('return object from url with multiple filters parameter and another parameter', function () {
var urlSearch = '?filters[name]=test&filters[qty]=1&anotherparam=1';

expect(urlFilterApplierObj.getFilterParam(urlSearch)).toEqual({
'name': 'test',
'qty': '1'
});
});
it('return object from url with another parameter', function () {
var urlSearch = '?anotherparam=1';

expect(urlFilterApplierObj.getFilterParam(urlSearch)).toEqual({});
});
});

describe('"apply" method', function () {
it('applies url filter on filter component', function () {
urlFilterApplierObj.searchString = '?filters[name]=test&filters[qty]=1';
urlFilterApplierObj.apply();
expect(urlFilterApplierObj.filterComponent().setData).toHaveBeenCalledWith({
'name': 'test',
'qty': '1'
}, false);
expect(urlFilterApplierObj.filterComponent().apply).toHaveBeenCalled();
});
});
});
});