Skip to content
This repository was archived by the owner on Jun 1, 2025. It is now read-only.

Commit f74246c

Browse files
Ghislain BeaulacGhislain Beaulac
Ghislain Beaulac
authored and
Ghislain Beaulac
committed
feat(tests): add OdataQueryBuilder full test suite
- renamed OdataService to OdataQueryBuilderService - add couple more tests in the GridOdataService to cover more scenarios
1 parent 6dc2d21 commit f74246c

File tree

7 files changed

+446
-211
lines changed

7 files changed

+446
-211
lines changed

src/app/modules/angular-slickgrid/models/odataOption.interface.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,30 @@ import { BackendServiceOption } from './backendServiceOption.interface';
22
import { CaseType } from './caseType';
33

44
export interface OdataOption extends BackendServiceOption {
5-
caseType?: CaseType;
6-
top?: number;
7-
skip?: number;
8-
filter?: string;
9-
filterBy?: any;
10-
filterBySeparator?: string;
11-
filterQueue?: any[];
12-
orderBy?: string;
13-
[key: string]: any;
5+
/** What is the casing type to use? Typically that would be 1 of the following 2: camelCase or PascalCase */
6+
caseType?: CaseType;
7+
8+
/** How many rows to pull? */
9+
top?: number;
10+
11+
/** How many rows to skip on the pagination? */
12+
skip?: number;
13+
14+
/** (alias to "filter") Filter string (or array of string) that must be a valid OData string */
15+
filter?: string | string[];
16+
17+
/** Filter string (or array of string) that must be a valid OData string */
18+
filterBy?: any;
19+
20+
/** What is separator between each filters? Typically "and", "or" */
21+
filterBySeparator?: 'and' | 'or';
22+
23+
/** Filter queue */
24+
filterQueue?: any[];
25+
26+
/** Sorting string (or array of string) that must be a valid OData string */
27+
orderBy?: string | string[];
28+
29+
/** When accessed as an object */
30+
[key: string]: any;
1431
}

src/app/modules/angular-slickgrid/services/__tests__/grid-odata.service.spec.ts

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { CaseType } from './../../models/caseType';
2-
import { TranslateService } from '@ngx-translate/core';
32
import { GridOdataService } from '../grid-odata.service';
43
import {
54
Column,
@@ -127,7 +126,7 @@ describe('GridOdataService', () => {
127126
expect(query).toBe(expectation);
128127
});
129128

130-
it('should be able to provide "orderBy" and see the query string include the sorting', () => {
129+
it('should be able to provide "orderBy" through the "init" and see the query string include the sorting', () => {
131130
const expectation = `$top=20&$skip=40&$orderby=Name desc`;
132131
const columns = [{ id: 'field1', field: 'field1', width: 100 }, { id: 'field2', field: 'field2', width: 100 }];
133132

@@ -138,16 +137,40 @@ describe('GridOdataService', () => {
138137
expect(query).toBe(expectation);
139138
});
140139

141-
it('should be able to provide "filter" and see the query string include the sorting', () => {
140+
it('should be able to provide "orderBy" through the "updateOptions" and see the query string include the sorting', () => {
141+
const expectation = `$top=20&$skip=40&$orderby=Name desc`;
142+
const columns = [{ id: 'field1', field: 'field1', width: 100 }, { id: 'field2', field: 'field2', width: 100 }];
143+
144+
service.init({ columnDefinitions: columns }, paginationOptions, gridStub);
145+
service.updatePagination(3, 20);
146+
service.updateOptions({ orderBy: 'Name desc' });
147+
const query = service.buildQuery();
148+
149+
expect(query).toBe(expectation);
150+
});
151+
152+
it('should be able to provide "filter" through the "init" and see the query string include the filter', () => {
142153
const expectation = `$top=20&$skip=40&$filter=(IsActive eq true)`;
143154
const columns = [{ id: 'field1', field: 'field1', width: 100 }, { id: 'field2', field: 'field2', width: 100 }];
144155

145-
service.init({ columnDefinitions: columns, filter: `IsActive eq true` }, paginationOptions, gridStub);
156+
service.init({ columnDefinitions: columns, filterBy: `IsActive eq true` }, paginationOptions, gridStub);
146157
service.updatePagination(3, 20);
147158
const query = service.buildQuery();
148159

149160
expect(query).toBe(expectation);
150161
});
162+
163+
it('should be able to provide "filter" through the "updateOptions" and see the query string include the filter', () => {
164+
const expectation = `$top=20&$skip=40&$filter=(IsActive eq true)`;
165+
const columns = [{ id: 'field1', field: 'field1', width: 100 }, { id: 'field2', field: 'field2', width: 100 }];
166+
167+
service.init({ columnDefinitions: columns }, paginationOptions, gridStub);
168+
service.updatePagination(3, 20);
169+
service.updateOptions({ filterBy: `IsActive eq true` });
170+
const query = service.buildQuery();
171+
172+
expect(query).toBe(expectation);
173+
});
151174
});
152175

153176
describe('clearFilters method', () => {
@@ -571,8 +594,8 @@ describe('GridOdataService', () => {
571594
expect(query).toBe(expectation);
572595
});
573596

574-
it('should return a query with the new filter search value of empty string when searchTerms has an undefined value', () => {
575-
const expectation = `$top=10&$filter=(Gender eq '')`;
597+
it('should return a query without any filters when the "searchTerms" has an undefined value', () => {
598+
const expectation = `$top=10`;
576599
const mockColumn = { id: 'gender', field: 'gender' } as Column;
577600
const mockColumnFilters = {
578601
gender: { columnId: 'gender', columnDef: mockColumn, searchTerms: [undefined], operator: 'EQ' },
@@ -585,6 +608,20 @@ describe('GridOdataService', () => {
585608
expect(query).toBe(expectation);
586609
});
587610

611+
it('should return a query without any filters when the "searchTerms" has an empty string', () => {
612+
const expectation = `$top=10`;
613+
const mockColumn = { id: 'gender', field: 'gender' } as Column;
614+
const mockColumnFilters = {
615+
gender: { columnId: 'gender', columnDef: mockColumn, searchTerms: [''], operator: 'EQ' },
616+
} as ColumnFilters;
617+
618+
service.init(serviceOptions, paginationOptions, gridStub);
619+
service.updateFilters(mockColumnFilters, false);
620+
const query = service.buildQuery();
621+
622+
expect(query).toBe(expectation);
623+
});
624+
588625
it('should return a query using a different field to query when the column has a "queryField" defined in its definition', () => {
589626
const expectation = `$top=10&$filter=(IsMale eq true)`;
590627
const mockColumn = { id: 'gender', field: 'gender', type: FieldType.boolean, queryField: 'isMale' } as Column;
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
import { CaseType } from '../../models/caseType';
2+
import { OdataQueryBuilderService } from '../odataQueryBuilder.service';
3+
import {
4+
Column,
5+
ColumnFilter,
6+
ColumnSort,
7+
CurrentFilter,
8+
FilterChangedArgs,
9+
GridOption,
10+
MultiColumnSort,
11+
Pagination,
12+
ColumnFilters,
13+
OperatorType,
14+
FieldType,
15+
CurrentSorter,
16+
OdataOption,
17+
} from '../../models';
18+
19+
const DEFAULT_ITEMS_PER_PAGE = 25;
20+
const DEFAULT_PAGE_SIZE = 20;
21+
22+
const gridOptionMock = {
23+
enablePagination: true,
24+
backendServiceApi: {
25+
service: undefined,
26+
preProcess: jest.fn(),
27+
process: jest.fn(),
28+
postProcess: jest.fn(),
29+
}
30+
} as GridOption;
31+
32+
const gridStub = {
33+
autosizeColumns: jest.fn(),
34+
getColumnIndex: jest.fn(),
35+
getScrollbarDimensions: jest.fn(),
36+
getOptions: () => gridOptionMock,
37+
getColumns: jest.fn(),
38+
setColumns: jest.fn(),
39+
registerPlugin: jest.fn(),
40+
setSelectedRows: jest.fn(),
41+
setSortColumns: jest.fn(),
42+
};
43+
44+
describe('OdataService', () => {
45+
let mockColumns: Column[];
46+
let service: OdataQueryBuilderService;
47+
48+
beforeEach(() => {
49+
mockColumns = [{ id: 'field1', field: 'field1', width: 100 }, { id: 'field2', field: 'field2', width: 100 }];
50+
service = new OdataQueryBuilderService();
51+
});
52+
53+
afterEach(() => {
54+
jest.clearAllMocks();
55+
});
56+
57+
it('should create the service', () => {
58+
expect(service).toBeTruthy();
59+
});
60+
61+
describe('buildQuery method', () => {
62+
beforeEach(() => {
63+
service.options = { filterQueue: [], orderBy: '' };
64+
});
65+
66+
it('should throw an error when odata options are null', () => {
67+
service.options = undefined;
68+
expect(() => service.buildQuery()).toThrow();
69+
});
70+
71+
it('should return a query with $top pagination', () => {
72+
const expectation = '$top=25';
73+
74+
service.options = { top: 25 };
75+
const query = service.buildQuery();
76+
77+
expect(query).toBe(expectation);
78+
});
79+
80+
it('should return a query with $top and $skip pagination', () => {
81+
const expectation = '$top=25&$skip=10';
82+
83+
service.options = { top: 25, skip: 10 };
84+
const query = service.buildQuery();
85+
86+
expect(query).toBe(expectation);
87+
});
88+
89+
it('should return a query with sorting when "orderBy" is provided as a string', () => {
90+
const expectation = '$top=10&$orderby=Gender asc';
91+
92+
service.options = { top: 10, orderBy: 'Gender asc' };
93+
const query = service.buildQuery();
94+
95+
expect(query).toBe(expectation);
96+
});
97+
98+
it('should return a query with sorting when "orderBy" is provided as an array', () => {
99+
const expectation = '$top=10&$orderby=Gender asc,Company desc';
100+
101+
service.options = { top: 10, orderBy: ['Gender asc', 'Company desc'] };
102+
const query = service.buildQuery();
103+
104+
expect(query).toBe(expectation);
105+
});
106+
107+
it('should return a query with sorting when "filter" is provided as a string', () => {
108+
const expectation = `$top=10&$filter=(FirstName eq 'John')`;
109+
110+
service.options = { top: 10, filter: `FirstName eq 'John'` };
111+
const query = service.buildQuery();
112+
113+
expect(query).toBe(expectation);
114+
});
115+
116+
it('should return a query with sorting when "filterBy" is provided as a string', () => {
117+
const expectation = `$top=10&$filter=(FirstName eq 'John')`;
118+
119+
service.options = { top: 10, filterBy: `FirstName eq 'John'` };
120+
const query = service.buildQuery();
121+
122+
expect(query).toBe(expectation);
123+
});
124+
125+
it('should return a query with sorting when "filterBy" is provided as an array', () => {
126+
const expectation = `$top=10&$filter=(FirstName eq 'John' and FirstName eq 'Jane')`;
127+
128+
service.options = { top: 10, filter: [`FirstName eq 'John'`, `FirstName eq 'Jane'`] };
129+
const query = service.buildQuery();
130+
131+
expect(query).toBe(expectation);
132+
});
133+
134+
it('should return a query with sorting when "filterBy" is provided as an array', () => {
135+
const expectation = `$top=10&$filter=(FirstName eq 'John' or FirstName eq 'Jane')`;
136+
137+
service.options = { top: 10, filterBy: [`FirstName eq 'John'`, `FirstName eq 'Jane'`], filterBySeparator: 'or' };
138+
const query = service.buildQuery();
139+
const filterCount = service.getFilterCount();
140+
141+
expect(query).toBe(expectation);
142+
expect(filterCount).toBe(2);
143+
});
144+
});
145+
146+
describe('saveColumnFilter method', () => {
147+
it('should return "columnFilters" object with multiple properties as the filter names', () => {
148+
service.saveColumnFilter('FirstName', 'John', ['John']);
149+
150+
const columnFilters = service.columnFilters;
151+
152+
expect(columnFilters).toEqual({ FirstName: { search: ['John'], value: 'John' } });
153+
});
154+
155+
it('should return "columnFilters" object with multiple properties as the filter names', () => {
156+
service.saveColumnFilter('FirstName', 'John', ['John']);
157+
service.saveColumnFilter('LastName', 'Doe', ['Doe']);
158+
159+
const columnFilters = service.columnFilters;
160+
161+
expect(columnFilters).toEqual({
162+
FirstName: { search: ['John'], value: 'John' },
163+
LastName: { search: ['Doe'], value: 'Doe' }
164+
});
165+
});
166+
});
167+
168+
describe('removeColumnFilter method', () => {
169+
it('should return "columnFilters" object without the one deleted', () => {
170+
service.saveColumnFilter('FirstName', 'John', ['John']);
171+
service.saveColumnFilter('LastName', 'Doe', ['Doe']);
172+
173+
service.removeColumnFilter('LastName');
174+
const columnFilters = service.columnFilters;
175+
176+
expect(columnFilters).toEqual({
177+
FirstName: { search: ['John'], value: 'John' }
178+
});
179+
});
180+
});
181+
182+
describe('updateOptions method', () => {
183+
beforeEach(() => {
184+
service.updateOptions({ caseType: CaseType.pascalCase });
185+
});
186+
187+
it('should be able to provide "filterBy" array and expect see the query string include the filter', () => {
188+
const expectation = `$filter=(FirstName eq 'John')`;
189+
190+
service.updateOptions({ filterBy: `FirstName eq 'John'` });
191+
const query = service.buildQuery();
192+
193+
expect(query).toBe(expectation);
194+
});
195+
196+
it('should be able to provide "filterBy" array and expect see the query string include the filter', () => {
197+
const expectation = `$filter=(FirstName eq 'John' and substring(Gender 'male')`;
198+
199+
service.updateOptions({ filterBy: [`FirstName eq 'John'`, `substring(Gender 'male'`] });
200+
const query = service.buildQuery();
201+
202+
expect(query).toBe(expectation);
203+
});
204+
205+
it('should be able to provide "orderBy" array and expect see the query string include the filter', () => {
206+
const expectation = `$orderby=FirstName desc`;
207+
208+
service.updateOptions({ orderBy: 'FirstName desc' });
209+
const query = service.buildQuery();
210+
211+
expect(query).toBe(expectation);
212+
});
213+
214+
it('should be able to provide "orderBy" array and expect see the query string include the filter', () => {
215+
const expectation = `$orderby=FirstName desc,LastName asc`;
216+
217+
service.updateOptions({ orderBy: ['FirstName desc', 'LastName asc'] });
218+
const query = service.buildQuery();
219+
220+
expect(query).toBe(expectation);
221+
});
222+
});
223+
});

0 commit comments

Comments
 (0)