diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 94f6f8e64..46b7a27b0 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -34,7 +34,7 @@
{
"label": "Cypress Open Tool",
"type": "shell",
- "command": "yarn run cypress open",
+ "command": "yarn run cypress:open",
"problemMatcher": []
},
{
diff --git a/src/app/modules/angular-slickgrid/services/__tests__/filter.service.spec.ts b/src/app/modules/angular-slickgrid/services/__tests__/filter.service.spec.ts
index 412d02b79..86404ceaf 100644
--- a/src/app/modules/angular-slickgrid/services/__tests__/filter.service.spec.ts
+++ b/src/app/modules/angular-slickgrid/services/__tests__/filter.service.spec.ts
@@ -363,6 +363,7 @@ describe('FilterService', () => {
describe('clearFilter methods on backend grid', () => {
let mockColumn1: Column;
let mockColumn2: Column;
+ let mockColumn3: Column;
beforeEach(() => {
gridOptionMock.backendServiceApi = {
@@ -372,13 +373,16 @@ describe('FilterService', () => {
};
mockColumn1 = { id: 'firstName', field: 'firstName', filterable: true } as Column;
mockColumn2 = { id: 'lastName', field: 'lastName', filterable: true } as Column;
+ mockColumn3 = { id: 'age', field: 'age', filterable: true } as Column;
const mockArgs1 = { grid: gridStub, column: mockColumn1, node: document.getElementById(DOM_ELEMENT_ID) };
const mockArgs2 = { grid: gridStub, column: mockColumn2, node: document.getElementById(DOM_ELEMENT_ID) };
+ const mockArgs3 = { grid: gridStub, column: mockColumn3, node: document.getElementById(DOM_ELEMENT_ID) };
service.init(gridStub);
service.bindBackendOnFilter(gridStub, dataViewStub);
gridStub.onHeaderRowCellRendered.notify(mockArgs1, new Slick.EventData(), gridStub);
gridStub.onHeaderRowCellRendered.notify(mockArgs2, new Slick.EventData(), gridStub);
+ gridStub.onHeaderRowCellRendered.notify(mockArgs3, new Slick.EventData(), gridStub);
service.getFiltersMetadata()[0].callback(new Event('keyup'), { columnDef: mockColumn1, operator: 'EQ', searchTerms: ['John'], shouldTriggerQuery: true });
service.getFiltersMetadata()[1].callback(new Event('keyup'), { columnDef: mockColumn2, operator: 'NE', searchTerms: ['Doe'], shouldTriggerQuery: true });
});
@@ -402,6 +406,26 @@ describe('FilterService', () => {
expect(service.getColumnFilters()).toEqual({ lastName: filterExpectation });
expect(spyEmitter).toHaveBeenCalledWith('remote');
});
+
+ it('should not call "onBackendFilterChange" method when the filter is previously empty', () => {
+ const filterFirstExpectation = { columnDef: mockColumn1, columnId: 'firstName', operator: 'EQ', searchTerms: ['John'] };
+ const filterLastExpectation = { columnDef: mockColumn2, columnId: 'lastName', operator: 'NE', searchTerms: ['Doe'] };
+ const newEvent = new Event('mouseup');
+ const spyClear = jest.spyOn(service.getFiltersMetadata()[2], 'clear');
+ const spyFilterChange = jest.spyOn(service, 'onBackendFilterChange');
+ const spyEmitter = jest.spyOn(service, 'emitFilterChanged');
+
+ const filterCountBefore = Object.keys(service.getColumnFilters()).length;
+ service.clearFilterByColumnId(newEvent, 'age');
+ const filterCountAfter = Object.keys(service.getColumnFilters()).length;
+
+ expect(spyClear).toHaveBeenCalled();
+ expect(spyFilterChange).not.toHaveBeenCalled();
+ expect(filterCountBefore).toBe(2);
+ expect(filterCountAfter).toBe(2);
+ expect(service.getColumnFilters()).toEqual({ firstName: filterFirstExpectation, lastName: filterLastExpectation });
+ expect(spyEmitter).toHaveBeenCalledWith('remote');
+ });
});
describe('clearFilters method', () => {
diff --git a/src/app/modules/angular-slickgrid/services/filter.service.ts b/src/app/modules/angular-slickgrid/services/filter.service.ts
index e32d8677b..3f68d3120 100644
--- a/src/app/modules/angular-slickgrid/services/filter.service.ts
+++ b/src/app/modules/angular-slickgrid/services/filter.service.ts
@@ -169,6 +169,14 @@ export class FilterService {
}
clearFilterByColumnId(event: Event, columnId: number | string) {
+ // get current column filter before clearing, this allow us to know if the filter was empty prior to calling the clear filter
+ const currentColumnFilters = Object.keys(this._columnFilters) as ColumnFilter[];
+ let currentColFilter: ColumnFilter;
+ if (Array.isArray(currentColumnFilters)) {
+ currentColFilter = currentColumnFilters.find((name) => name === columnId);
+ }
+
+ // find the filter object and call its clear method with true (the argument tells the method it was called by a clear filter)
const colFilter: Filter = this._filtersMetadata.find((filter: Filter) => filter.columnDef.id === columnId);
if (colFilter && colFilter.clear) {
colFilter.clear(true);
@@ -177,10 +185,12 @@ export class FilterService {
let emitter: EmitterType = EmitterType.local;
const isBackendApi = this._gridOptions && this._gridOptions.backendServiceApi || false;
- // when using a backend service, we need to manually trigger a filter change
+ // when using a backend service, we need to manually trigger a filter change but only if the filter was previously filled
if (isBackendApi) {
emitter = EmitterType.remote;
- this.onBackendFilterChange(event as KeyboardEvent, { grid: this._grid, columnFilters: this._columnFilters });
+ if (currentColFilter) {
+ this.onBackendFilterChange(event as KeyboardEvent, { grid: this._grid, columnFilters: this._columnFilters });
+ }
}
// emit an event when filter is cleared
diff --git a/src/tsconfig.spec.json b/src/tsconfig.spec.json
index 18bad40ed..17b3c7fca 100644
--- a/src/tsconfig.spec.json
+++ b/src/tsconfig.spec.json
@@ -6,6 +6,7 @@
"module": "commonjs",
"target": "es5",
"types": [
+ "cypress",
"jasmine",
"node"
]
diff --git a/test/cypress/integration/example1.spec.js b/test/cypress/integration/example1.spec.js
index 3c7d64970..3f70068de 100644
--- a/test/cypress/integration/example1.spec.js
+++ b/test/cypress/integration/example1.spec.js
@@ -1,5 +1,3 @@
-///
-
describe('Example 1 - Basic Grids', () => {
const titles = ['Title', 'Duration (days)', '% Complete', 'Start', 'Finish', 'Effort Driven'];
diff --git a/test/cypress/integration/example6.spec.js b/test/cypress/integration/example6.spec.js
index 7a8bd31db..834ff4142 100644
--- a/test/cypress/integration/example6.spec.js
+++ b/test/cypress/integration/example6.spec.js
@@ -1,5 +1,3 @@
-///
-
describe('Example 6 - GraphQL Grid', () => {
it('should display Example 6 title', () => {
cy.visit(`${Cypress.config('baseExampleUrl')}/gridgraphql`);
@@ -69,6 +67,57 @@ describe('Example 6 - GraphQL Grid', () => {
});
});
+ it('should clear a single filter, that is not empty, by the header menu and expect query change', () => {
+ cy.get('#grid6')
+ .find('.slick-header-column:nth(1)')
+ .trigger('mouseover')
+ .children('.slick-header-menubutton')
+ .should('be.hidden')
+ .invoke('show')
+ .click();
+
+ cy.get('.slick-header-menu')
+ .should('be.visible')
+ .children('.slick-header-menuitem:nth-child(4)')
+ .children('.slick-header-menucontent')
+ .should('contain', 'Remove Filter')
+ .click();
+
+ // wait for the query to finish
+ cy.get('[data-test=status]').should('contain', 'done');
+
+ cy.get('[data-test=graphql-query-result]')
+ .should(($span) => {
+ const text = $span.text().replace(/\s/g, ''); // remove all white spaces
+ expect(text).to.eq('query{users(first:30,offset:0,orderBy:[{field:"name",direction:ASC},{field:"company",direction:DESC}],filterBy:[{field:"gender",operator:EQ,value:"male"},{field:"company",operator:IN,value:"xyz"}],locale:"en",userId:123){totalCount,nodes{id,name,gender,company,billing{address{street,zip}}}}}');
+ });
+ });
+
+ it('should try clearing same filter, which is now empty, by the header menu and expect same query without loading spinner', () => {
+ cy.get('#grid6')
+ .find('.slick-header-column:nth(1)')
+ .trigger('mouseover')
+ .children('.slick-header-menubutton')
+ .invoke('show')
+ .click();
+
+ cy.get('.slick-header-menu')
+ .should('be.visible')
+ .children('.slick-header-menuitem:nth-child(4)')
+ .children('.slick-header-menucontent')
+ .should('contain', 'Remove Filter')
+ .click();
+
+ // wait for the query to finish
+ cy.get('[data-test=status]').should('contain', 'done');
+
+ cy.get('[data-test=graphql-query-result]')
+ .should(($span) => {
+ const text = $span.text().replace(/\s/g, ''); // remove all white spaces
+ expect(text).to.eq('query{users(first:30,offset:0,orderBy:[{field:"name",direction:ASC},{field:"company",direction:DESC}],filterBy:[{field:"gender",operator:EQ,value:"male"},{field:"company",operator:IN,value:"xyz"}],locale:"en",userId:123){totalCount,nodes{id,name,gender,company,billing{address{street,zip}}}}}');
+ });
+ });
+
it('should clear all Filters & Sorts', () => {
cy.contains('Clear all Filter & Sorts').click();
diff --git a/test/cypress/integration/home.spec.js b/test/cypress/integration/home.spec.js
index 82092a04a..1992a42dc 100644
--- a/test/cypress/integration/home.spec.js
+++ b/test/cypress/integration/home.spec.js
@@ -1,5 +1,3 @@
-///
-
describe('Home Page', () => {
it('should display Home Page', () => {
cy.visit('http://localhost:4300/home');