Skip to content

Commit 17c905d

Browse files
committed
fix(filter): default operator of input filter should be empty
1 parent 5f2ec3f commit 17c905d

16 files changed

+205
-42
lines changed

src/app/examples/grid-graphql.component.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ export class GridGraphqlComponent implements OnInit, OnDestroy {
5757
gridStateSub: Subscription;
5858

5959
constructor(private translate: TranslateService) {
60-
this.selectedLanguage = this.translate.getDefaultLang();
60+
// always start with English for Cypress E2E tests to be consistent
61+
const defaultLang = 'en';
62+
this.translate.use(defaultLang);
63+
this.selectedLanguage = defaultLang;
6164
}
6265

6366
ngOnDestroy() {

src/app/examples/grid-localization.component.html

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ <h2>{{title}}</h2>
55
<hr />
66

77
<div class="row col-sm-12">
8-
<button class="btn btn-default btn-sm" (click)="switchLanguage()">
8+
<button class="btn btn-default btn-sm" (click)="switchLanguage()" data-test="language-button">
99
<i class="fa fa-language"></i>
1010
Switch Language
1111
</button>
12-
<b>Locale:</b> <span style="font-style: italic">{{selectedLanguage + '.json'}}</span>
12+
<b>Locale:</b>
13+
<span style="font-style: italic" data-test="selected-locale">
14+
{{selectedLanguage + '.json'}}
15+
</span>
1316

1417
<span style="margin-left: 20px">
1518
<button class="btn btn-default btn-sm" (click)="exportToFile('csv')">
@@ -34,11 +37,8 @@ <h2>{{title}}</h2>
3437
</div>
3538

3639
<div class="col-sm-12">
37-
<angular-slickgrid gridId="grid12"
38-
(onAngularGridCreated)="angularGridReady($event)"
39-
[columnDefinitions]="columnDefinitions"
40-
[gridOptions]="gridOptions"
41-
[dataset]="dataset">
40+
<angular-slickgrid gridId="grid12" (onAngularGridCreated)="angularGridReady($event)"
41+
[columnDefinitions]="columnDefinitions" [gridOptions]="gridOptions" [dataset]="dataset">
4242
</angular-slickgrid>
4343
</div>
4444
</div>

src/app/examples/grid-localization.component.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
GridOption
1313
} from './../modules/angular-slickgrid';
1414

15+
const NB_ITEMS = 1500;
16+
1517
// create a custom translate Formatter (typically you would move that a separate file, for separation of concerns)
1618
const taskTranslateFormatter: Formatter = (row: number, cell: number, value: any, columnDef: any, dataContext: any, grid: any) => {
1719
const gridOptions = (grid && typeof grid.getOptions === 'function') ? grid.getOptions() : {};
@@ -60,7 +62,10 @@ export class GridLocalizationComponent implements OnInit {
6062
duplicateTitleHeaderCount = 1;
6163

6264
constructor(private translate: TranslateService) {
63-
this.selectedLanguage = this.translate.getDefaultLang();
65+
// always start with English for Cypress E2E tests to be consistent
66+
const defaultLang = 'en';
67+
this.translate.use(defaultLang);
68+
this.selectedLanguage = defaultLang;
6469
}
6570

6671
ngOnInit(): void {
@@ -169,7 +174,7 @@ export class GridLocalizationComponent implements OnInit {
169174
}
170175
};
171176

172-
this.loadData(1000);
177+
this.loadData(NB_ITEMS);
173178
}
174179

175180
// mock a dataset
+10-17
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,22 @@
11
<div class="container-fluid">
22
<h2>{{title}}</h2>
3-
<div class="subtitle"
4-
[innerHTML]="subTitle"></div>
3+
<div class="subtitle" [innerHTML]="subTitle"></div>
54

6-
<button class="btn btn-default btn-sm"
7-
(click)="clearGridStateFromLocalStorage()"
8-
data-test="reset-button">
5+
<button class="btn btn-default btn-sm" (click)="clearGridStateFromLocalStorage()" data-test="reset-button">
96
<i class="fa fa-times"></i>
107
Clear Grid State from Local Storage &amp; Reset Grid
118
</button>
12-
<button class="btn btn-default btn-sm"
13-
(click)="switchLanguage()"
14-
data-test="language-button">
9+
<button class="btn btn-default btn-sm" (click)="switchLanguage()" data-test="language-button">
1510
<i class="fa fa-language"></i>
1611
Switch Language
1712
</button>
18-
<b>Locale:</b> <span style="font-style: italic"
19-
data-test="selected-locale">{{selectedLanguage + '.json'}}</span>
13+
<b>Locale:</b>
14+
<span style="font-style: italic" data-test="selected-locale">
15+
{{selectedLanguage + '.json'}}
16+
</span>
2017

21-
<angular-slickgrid gridId="grid16"
22-
[columnDefinitions]="columnDefinitions"
23-
[gridOptions]="gridOptions"
24-
[dataset]="dataset"
25-
(onAngularGridCreated)="angularGridReady($event)"
26-
(onGridStateChanged)="gridStateChanged($event)"
27-
(onBeforeGridDestroy)="saveCurrentGridState($event)">
18+
<angular-slickgrid gridId="grid16" [columnDefinitions]="columnDefinitions" [gridOptions]="gridOptions"
19+
[dataset]="dataset" (onAngularGridCreated)="angularGridReady($event)"
20+
(onGridStateChanged)="gridStateChanged($event)" (onBeforeGridDestroy)="saveCurrentGridState($event)">
2821
</angular-slickgrid>
2922
</div>

src/app/modules/angular-slickgrid/filters/__tests__/inputFilter.spec.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,15 @@ describe('InputFilter', () => {
8181
const filterFilledElms = divContainer.querySelectorAll<HTMLInputElement>('input.filter-duration.filled');
8282

8383
expect(filterFilledElms.length).toBe(1);
84-
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['abc'], shouldTriggerQuery: true });
84+
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '', searchTerms: ['abc'], shouldTriggerQuery: true });
8585
});
8686

87-
it('should call "setValues" with extra spaces at the beginning of the searchTerms and trim value when "enableFilterTrimWhiteSpace" is enabled in grid options', () => {
87+
it('should call "setValues" an operator and with with extra spaces at the beginning of the searchTerms and trim value when "enableFilterTrimWhiteSpace" is enabled in grid options', () => {
8888
gridOptionMock.enableFilterTrimWhiteSpace = true;
8989
const spyCallback = jest.spyOn(filterArguments, 'callback');
9090

9191
filter.init(filterArguments);
92-
filter.setValues(' abc ');
92+
filter.setValues(' abc ', 'EQ');
9393
const filterElm = divContainer.querySelector<HTMLInputElement>('input.filter-duration');
9494

9595
filterElm.focus();
@@ -114,7 +114,7 @@ describe('InputFilter', () => {
114114
const filterFilledElms = divContainer.querySelectorAll<HTMLInputElement>('input.filter-duration.filled');
115115

116116
expect(filterFilledElms.length).toBe(1);
117-
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['abc'], shouldTriggerQuery: true });
117+
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '', searchTerms: ['abc'], shouldTriggerQuery: true });
118118
});
119119

120120
it('should trigger the callback method when user types something in the input', () => {

src/app/modules/angular-slickgrid/filters/__tests__/inputMaskFilter.spec.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,15 @@ describe('InputMaskFilter', () => {
8585
filterElm.focus();
8686
filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true }));
8787

88-
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['1234567890'], shouldTriggerQuery: true });
88+
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '', searchTerms: ['1234567890'], shouldTriggerQuery: true });
8989
});
9090

91-
it('should call "setValues" with 10 digits and expect input value to be formatted as a phone as the mask format specifies', () => {
91+
it('should call "setValues" an operator and with with 10 digits and expect input value to be formatted as a phone as the mask format specifies', () => {
9292
mockColumn.filter.params = { mask: '(000) 000-0000' };
9393
const spyCallback = jest.spyOn(filterArguments, 'callback');
9494

9595
filter.init(filterArguments);
96-
filter.setValues('1234567890');
96+
filter.setValues('1234567890', 'EQ');
9797
const filterElm = divContainer.querySelector<HTMLInputElement>('input.filter-mask');
9898
filterElm.focus();
9999
filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true }));
@@ -113,7 +113,7 @@ describe('InputMaskFilter', () => {
113113
filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true }));
114114

115115
expect(filterElm.value).toBe('(123) 456-7890');
116-
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['1234567890'], shouldTriggerQuery: true });
116+
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '', searchTerms: ['1234567890'], shouldTriggerQuery: true });
117117
});
118118

119119
it('should call "setValues" with 10 digits and expect it to work with using 9 instead of 0 in the mask', () => {
@@ -127,7 +127,7 @@ describe('InputMaskFilter', () => {
127127
filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true }));
128128

129129
expect(filterElm.value).toBe('(123) 456-7890');
130-
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['1234567890'], shouldTriggerQuery: true });
130+
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '', searchTerms: ['1234567890'], shouldTriggerQuery: true });
131131
});
132132

133133
it('should call "setValues" with a characters & numbers mask (e.g. postal code) and expect it to returned a formatted string', () => {
@@ -141,7 +141,7 @@ describe('InputMaskFilter', () => {
141141
filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true }));
142142

143143
expect(filterElm.value).toBe('H1H 1H1');
144-
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['H1H1H1'], shouldTriggerQuery: true });
144+
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '', searchTerms: ['H1H1H1'], shouldTriggerQuery: true });
145145
});
146146

147147
it('should call "setValues" with 10 digits and expect it to work even if input as extra spaces at the beginning when "enableFilterTrimWhiteSpace" is enabled in grid options', () => {
@@ -156,7 +156,7 @@ describe('InputMaskFilter', () => {
156156
filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true }));
157157

158158
expect(filterElm.value).toBe('(123) 456-7890');
159-
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['1234567890'], shouldTriggerQuery: true });
159+
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '', searchTerms: ['1234567890'], shouldTriggerQuery: true });
160160
});
161161

162162
it('should call "setValues" with 10 digits and expect it to work even if input as extra spaces at the beginning when "enableTrimWhiteSpace" is enabled in the column filter', () => {
@@ -172,7 +172,7 @@ describe('InputMaskFilter', () => {
172172
filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true }));
173173

174174
expect(filterElm.value).toBe('(123) 456-7890');
175-
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['1234567890'], shouldTriggerQuery: true });
175+
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '', searchTerms: ['1234567890'], shouldTriggerQuery: true });
176176
});
177177

178178
it('should call "setValues" all invalid characters and expect an empty shell as it does not match the mask', () => {
@@ -186,7 +186,7 @@ describe('InputMaskFilter', () => {
186186
filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true }));
187187

188188
expect(filterElm.value).toBe('() -');
189-
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: [''], shouldTriggerQuery: true });
189+
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '', searchTerms: [''], shouldTriggerQuery: true });
190190
});
191191

192192
it('should trigger the callback method when user types something in the input', () => {

src/app/modules/angular-slickgrid/filters/__tests__/selectFilter.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ describe('SelectFilter', () => {
511511
expect(filterListElm[1].checked).toBe(true);
512512
expect(spyCallback).toHaveBeenCalledWith(undefined, { columnDef: mockColumn, operator: 'IN', searchTerms: ['female'], shouldTriggerQuery: true });
513513
done();
514-
});
514+
}, 2);
515515
});
516516

517517
it('should create the multi-select filter with a "collectionAsync" as an Observable and be able to call next on it', (done) => {

src/app/modules/angular-slickgrid/filters/inputFilter.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class InputFilter implements Filter {
3232

3333
/** Getter to know what would be the default operator when none is specified */
3434
get defaultOperator(): OperatorType | OperatorString {
35-
return OperatorType.equal;
35+
return OperatorType.empty;
3636
}
3737

3838
/** Getter of input type (text, number, password) */

test/cypress/integration/example1.spec.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/// <reference types="cypress" />
2+
13
describe('Example 1 - Basic Grids', () => {
24
const titles = ['Title', 'Duration (days)', '% Complete', 'Start', 'Finish', 'Effort Driven'];
35

test/cypress/integration/example10.spec.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/// <reference types="cypress" />
2+
13
describe('Example 10 - Multiple Grids with Row Selection', () => {
24
const titles = ['', 'Title', 'Duration (days)', '% Complete', 'Start', 'Finish', 'Effort Driven'];
35

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/// <reference types="cypress" />
2+
3+
describe('Example 12: Localization (i18n)', () => {
4+
const fullEnglishTitles = ['Title', 'Description', 'Duration', 'Start', 'Finish', 'Completed', 'Completed'];
5+
const fullFrenchTitles = ['Titre', 'Description', 'Durée', 'Début', 'Fin', 'Terminé', 'Terminé'];
6+
7+
beforeEach(() => {
8+
cy.restoreLocalStorage();
9+
});
10+
11+
afterEach(() => {
12+
cy.saveLocalStorage();
13+
});
14+
15+
it('should display Example title', () => {
16+
cy.visit(`${Cypress.config('baseExampleUrl')}/localization`);
17+
cy.get('h2').should('contain', 'Example 12: Localization (i18n)');
18+
});
19+
20+
describe('English Locale', () => {
21+
it('should have exact English Column Titles in the grid', () => {
22+
cy.get('#grid12')
23+
.find('.slick-header-columns')
24+
.children()
25+
.each(($child, index) => expect($child.text()).to.eq(fullEnglishTitles[index]));
26+
});
27+
28+
it('should filter certain tasks with the word "ask 1" and expect filter to use contain/include text', () => {
29+
const tasks = ['Task 1', 'Task 10', 'Task 11', 'Task 12'];
30+
31+
cy.get('.grid-canvas')
32+
.find('.slick-row')
33+
.should('be.visible');
34+
35+
cy.get('input.filter-title')
36+
.type('ask 1');
37+
38+
cy.get('#grid12')
39+
.find('.slick-row')
40+
.each(($row, index) => {
41+
if (index > tasks.length - 1) {
42+
return;
43+
}
44+
cy.wrap($row).children('.slick-cell')
45+
.first()
46+
.should('contain', tasks[index]);
47+
});
48+
});
49+
});
50+
51+
describe('French locale', () => {
52+
it('should reset filters and switch locale to French', () => {
53+
cy.get('#grid12')
54+
.find('button.slick-gridmenu-button')
55+
.trigger('click')
56+
.click();
57+
58+
cy.get(`.slick-gridmenu:visible`)
59+
.find('.slick-gridmenu-item')
60+
.first()
61+
.find('span')
62+
.contains('Clear All Filters')
63+
.click();
64+
65+
cy.get('[data-test=language-button]')
66+
.click();
67+
68+
cy.get('[data-test=selected-locale]')
69+
.should('contain', 'fr.json');
70+
});
71+
72+
it('should have French Column Titles in the grid after switching locale', () => {
73+
cy.get('#grid12')
74+
.find('.slick-header-columns')
75+
.children()
76+
.each(($child, index) => expect($child.text()).to.eq(fullFrenchTitles[index]));
77+
});
78+
79+
it('should filter certain tasks', () => {
80+
const tasks = ['Tâche 1', 'Tâche 10', 'Tâche 11', 'Tâche 12'];
81+
82+
cy.get('.grid-canvas')
83+
.find('.slick-row')
84+
.should('be.visible');
85+
86+
cy.get('input.filter-title')
87+
.type('âche 1');
88+
89+
cy.get('#grid12')
90+
.find('.slick-row')
91+
.each(($row, index) => {
92+
if (index > tasks.length - 1) {
93+
return;
94+
}
95+
cy.wrap($row).children('.slick-cell')
96+
.first()
97+
.should('contain', tasks[index]);
98+
});
99+
});
100+
101+
it('should reset filters before filtering duration', () => {
102+
cy.get('#grid12')
103+
.find('button.slick-gridmenu-button')
104+
.trigger('click')
105+
.click();
106+
107+
cy.get(`.slick-gridmenu:visible`)
108+
.find('.slick-gridmenu-item')
109+
.first()
110+
.find('span')
111+
.contains('Supprimer tous les filtres')
112+
.click();
113+
});
114+
115+
it('should filter duration with slider filter', () => {
116+
cy.get('.filter-duration input[type=range]').as('range')
117+
.invoke('val', 25)
118+
.trigger('change');
119+
120+
cy.get('#grid12')
121+
.find('.slick-row')
122+
.each(($row, index) => {
123+
let fullCellWidth;
124+
125+
// only checks first 5 rows
126+
if (index > 5) {
127+
return;
128+
}
129+
130+
// get full cell width of the first cell, then return
131+
cy.wrap($row).children('.slick-cell:nth(2)')
132+
.first()
133+
.then(($cell) => fullCellWidth = $cell.width());
134+
135+
136+
cy.wrap($row)
137+
.children('.slick-cell:nth(2)')
138+
.children()
139+
.should('have.css', 'background-color', 'rgb(255, 0, 0)')
140+
.should(($el) => {
141+
// calculate 25% and expect the element width to be about the calculated size with a (+/-)1px precision
142+
const expectedWidth = (fullCellWidth * .25);
143+
expect($el.width()).greaterThan(expectedWidth - 1);
144+
expect($el.width()).lessThan(expectedWidth + 1);
145+
});
146+
});
147+
});
148+
});
149+
});

test/cypress/integration/example16.spec.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/// <reference types="cypress" />
2+
13
describe('Example 16: Grid State & Presets using Local Storage', () => {
24
const fullEnglishTitles = ['', 'Title', 'Description', 'Duration', '% Complete', 'Start', 'Completed'];
35
const fullFrenchTitles = ['', 'Titre', 'Description', 'Durée', '% Achevée', 'Début', 'Terminé'];

0 commit comments

Comments
 (0)