cypress-ag-grid 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,507 +1,538 @@
1
- /// <reference types="cypress" />
2
- import { sort } from "./sort.enum";
3
- import { filterTab } from "./menuTab.enum";
4
-
5
- /**
6
- * Uses the attribute value's index and sorts the data accordingly.
7
- * For our purposes, we are getting the attribute with the items' indices and sorting accordingly.
8
- *
9
- * @param {*} index
10
- * @returns
11
- */
12
- function sortElementsByAttributeValue(attribute) {
13
- return (a, b) => {
14
- const contentA = parseInt(a.attributes[attribute].nodeValue, 10).valueOf();
15
- const contentB = parseInt(b.attributes[attribute].nodeValue, 10).valueOf();
16
- return contentA < contentB ? -1 : contentA > contentB ? 1 : 0;
17
- };
18
- }
19
-
20
- /**
21
- * Retrieves the values from the *displayed* page in ag grid and assigns each value to its respective column name.
22
- * @param agGridElement The get() selector for which ag grid table you wish to retrieve.
23
- * @param options Provide an array of columns you wish to exclude from the table retrieval.
24
- */
25
- export const getAgGridData = (agGridElement, options = {}) => {
26
- return _getAgGrid(agGridElement, options, false);
27
- };
28
-
29
- /**
30
- * Retrieves the values from the *displayed* page in ag grid and assigns each value to its respective column name.
31
- * @param agGridElement The get() selector for which ag grid table you wish to retrieve.
32
- * @param options Provide an array of columns you wish to exclude from the table retrieval.
33
- */
34
- export const getAgGridElements = (agGridElement, options = {}) => {
35
- return _getAgGrid(agGridElement, options, true);
36
- };
37
-
38
- function _getAgGrid(agGridElement, options = {}, returnElements) {
39
- const agGridColumnSelectors =
40
- ".ag-pinned-left-cols-container^.ag-center-cols-clipper^.ag-pinned-right-cols-container";
41
- if (agGridElement.get().length > 1)
42
- throw new Error(
43
- `Selector "${agGridElement.selector}" returned more than 1 element.`
44
- );
45
-
46
- const tableElement = agGridElement.get()[0].querySelectorAll(".ag-root")[0];
47
- const agGridSelectors = agGridColumnSelectors.split("^");
48
- const headers = [
49
- ...tableElement.querySelectorAll(".ag-header-row-column [aria-colindex]"),
50
- ]
51
- .sort(sortElementsByAttributeValue("aria-colindex"))
52
- .map((headerElement) => {
53
- // Check if the elements returned are already .ag-header-cell-text elements
54
- // If not, query for that element and return the text content
55
- let headerCells = [
56
- ...headerElement.querySelectorAll(".ag-header-cell-text"),
57
- ];
58
- if (headerCells.length === 0) {
59
- return [headerElement].map((e) => e.textContent.trim());
60
- } else {
61
- return [...headerElement.querySelectorAll(".ag-header-cell-text")].map(
62
- (e) => e.textContent.trim()
63
- );
64
- }
65
- })
66
- .flat();
67
-
68
- let allRows = [];
69
- let rows = [];
70
-
71
- agGridSelectors.forEach((selector) => {
72
- const _rows = [
73
- ...tableElement.querySelectorAll(`${selector}:not(.ag-hidden) .ag-row`),
74
- ]
75
- // Sort rows by their row-index attribute value
76
- .sort(sortElementsByAttributeValue("row-index"))
77
- .map((row) => {
78
- // Sort row cells by their aria-colindex attribute value
79
- // First check if elements returned already contain the aria-colindex
80
- // If not, just query for the .ag-cell
81
- let rowCells = [...row.querySelectorAll(".ag-cell [aria-colindex]")];
82
- if (rowCells.length === 0) {
83
- rowCells = [...row.querySelectorAll(".ag-cell")];
84
- }
85
- return rowCells
86
- .sort(sortElementsByAttributeValue("aria-colindex"))
87
- .map((e) => {
88
- if (returnElements) {
89
- return e;
90
- } else {
91
- return e.textContent.trim();
92
- }
93
- });
94
- });
95
- allRows.push(_rows);
96
- });
97
-
98
- // Remove any empty arrays before merging
99
- allRows = allRows.filter(function (ele) {
100
- return ele.length;
101
- });
102
-
103
- if (!allRows.length) rows = [];
104
- else {
105
- // Combine results from all specified tables (either single table, or all pinned columns) by index
106
- rows = allRows.reduce(function (a, b) {
107
- return a.map(function (v, i) {
108
- return v.concat(b[i]);
109
- });
110
- });
111
- }
112
-
113
- // if options.rawValues = true, return headers & rows values as arrays instead of mapping as objects
114
- if (options.valuesArray) {
115
- return { headers, rows };
116
- }
117
-
118
- // return structured object from headers and rows variables
119
- return rows.map((row) =>
120
- row.reduce((acc, curr, idx) => {
121
- if (
122
- //@ts-ignore
123
- (options.onlyColumns && !options.onlyColumns.includes(headers[idx])) ||
124
- headers[idx] === undefined
125
- ) {
126
- // dont include columns that are not present in onlyColumns, or if the header is undefined
127
- return { ...acc };
128
- }
129
- return { ...acc, [headers[idx]]: curr };
130
- }, {})
131
- );
132
- }
133
-
134
- /**
135
- * Retrieve the ag grid column header element based on its column name value
136
- * @param columnName The name of the column's header to retrieve.
137
- */
138
- function getColumnHeaderElement(agGridElement, columnName) {
139
- return cy
140
- .get(agGridElement)
141
- .find(".ag-header-cell-text")
142
- .contains(new RegExp("^" + columnName + "$", "g"));
143
- }
144
-
145
- /**
146
- * * Performs sorting operation on the specified column
147
- * @param {*} agGridElement The get() selector for which ag grid table you wish to retrieve.
148
- * @param columnName The name of the column you wish to sort
149
- * @param sortDirection sort enum value
150
- * @returns
151
- */
152
- export function sortColumnBy(agGridElement, columnName, sortDirection) {
153
- if (sortDirection === sort.ascending || sortDirection === sort.descending) {
154
- return getColumnHeaderElement(agGridElement, columnName)
155
- .parents(".ag-header-cell")
156
- .invoke("attr", "aria-sort")
157
- .then((value) => {
158
- cy.log(`sort: ${sortDirection}`);
159
- if (value !== sortDirection) {
160
- getColumnHeaderElement(agGridElement, columnName).click().wait(250);
161
- sortColumnBy(agGridElement, columnName, sortDirection);
162
- }
163
- });
164
- } else {
165
- throw new Error(
166
- "sortDirection must be either 'ascending' or 'descending'."
167
- );
168
- }
169
- }
170
-
171
- function getMenuTabElement(agGridElement, tab) {
172
- return cy
173
- .get(agGridElement)
174
- .find(".ag-tab")
175
- .find(`.ag-icon-${tab}`)
176
- .filter(":visible");
177
- }
178
-
179
- /**
180
- * Will select the specified filter tab if it is not already selected
181
- * @param tab
182
- */
183
- function selectMenuTab(agGridElement, tab) {
184
- getMenuTabElement(agGridElement, tab).then(($ele) => {
185
- cy.wrap($ele)
186
- .parent("span")
187
- .invoke("attr", "class")
188
- .then(($attr) => {
189
- if (!$attr.includes("selected")) {
190
- cy.wrap($ele).click();
191
- }
192
- });
193
- });
194
- }
195
-
196
- /**
197
- * Returns the filter button element for a specified column
198
- * @param columnName
199
- */
200
- function getFilterColumnButtonElement(
201
- agGridElement,
202
- columnName,
203
- isFloatingFilter = false
204
- ) {
205
- let columnIndex;
206
- if (isFloatingFilter)
207
- return getColumnHeaderElement(agGridElement, columnName)
208
- .parents(".ag-header-cell")
209
- .then(($ele) => {
210
- cy.wrap($ele)
211
- .invoke("attr", "aria-colindex")
212
- .then((colIndex) => {
213
- columnIndex = colIndex;
214
- })
215
- .then(() => {
216
- cy.wrap($ele)
217
- .parents(".ag-header-row-column")
218
- .siblings(".ag-header-row-column-filter")
219
- .find(`.ag-header-cell[aria-colindex=${columnIndex}]`)
220
- .find(".ag-floating-filter-button");
221
- });
222
- });
223
- else
224
- return getColumnHeaderElement(agGridElement, columnName)
225
- .parent()
226
- .siblings(".ag-header-cell-menu-button");
227
- }
228
-
229
- /**
230
- *
231
- * @param filterValue value to input into the filter textbox
232
- * @param operator (optional) use if using a search operator (i.e. Less Than, Equals, etc...use filterOperator.enum values)
233
- * @param noMenuTabs (optional) boolean indicating if the menu has tabs.
234
- */
235
- function filterBySearchTerm(agGridElement, options) {
236
- const filterValue = options.searchCriteria.filterValue;
237
- const operator = options.searchCriteria.operator;
238
- const searchInputIndex = options.searchCriteria.searchInputIndex || 0;
239
- const noMenuTabs = options.noMenuTabs;
240
-
241
- // Navigate to the filter tab
242
- if (!noMenuTabs) {
243
- selectMenuTab(agGridElement, filterTab.filter);
244
- }
245
- if (operator) {
246
- cy.get(agGridElement)
247
- .find(".ag-picker-field-wrapper")
248
- .filter(":visible")
249
- .click();
250
- cy.get(agGridElement)
251
- .find(".ag-popup")
252
- .find("span")
253
- .contains(operator)
254
- .then(($ele) => {
255
- //Have to use the unwrapped element, since Cypress .click() event does not appropriately select the operator
256
- $ele.trigger("click");
257
- });
258
- }
259
- // Input filter term and allow grid a moment to render the results
260
- cy.get(agGridElement)
261
- .find(".ag-popup-child")
262
- .find("input")
263
- .filter(":visible")
264
- .eq(searchInputIndex)
265
- .clear()
266
- .type(filterValue)
267
- .wait(500);
268
- }
269
-
270
- function applyColumnFilter(agGridElement, hasApplyButton, noMenuTabs) {
271
- if (hasApplyButton) {
272
- cy.get(agGridElement)
273
- .find(".ag-filter-apply-panel-button")
274
- .contains("Apply")
275
- .click();
276
- }
277
- if (!noMenuTabs) {
278
- getMenuTabElement(agGridElement, filterTab.filter).click();
279
- }
280
- }
281
-
282
- /**
283
- * Either toggle
284
- * @param filterValue
285
- * @param doSelect
286
- * @param hasTabs
287
- */
288
- function toggleColumnCheckboxFilter(
289
- agGridElement,
290
- filterValue,
291
- doSelect,
292
- noMenuTabs = false
293
- ) {
294
- if (!noMenuTabs) {
295
- selectMenuTab(agGridElement, filterTab.filter);
296
- }
297
- cy.get(agGridElement)
298
- .find(".ag-input-field-label")
299
- .contains(filterValue)
300
- .siblings("div")
301
- .find("input")
302
- .then(($ele) => {
303
- if (doSelect) cy.wrap($ele).check();
304
- else cy.wrap($ele).uncheck();
305
- });
306
- }
307
-
308
- function populateSearchCriteria(
309
- searchCriteria,
310
- hasApplyButton = false,
311
- noMenuTabs = false
312
- ) {
313
- const options = {};
314
- //@ts-ignore
315
- options.searchCriteria = {};
316
- //@ts-ignore
317
- options.searchCriteria.columnName = searchCriteria.columnName;
318
- //@ts-ignore
319
- options.searchCriteria.filterValue = searchCriteria.filterValue;
320
- //@ts-ignore
321
- options.hasApplyButton = hasApplyButton;
322
- //@ts-ignore
323
- options.noMenuTabs = noMenuTabs;
324
- return options;
325
- }
326
-
327
- /**
328
- * * Performs a filter operation on the specified column via the context menu using plain text search
329
- * @param agGridElement The get() selector for which ag grid table you wish to retrieve.
330
- * @param {{searchCriteria:[{columnName:string,filterValue:string,operator?:string}], hasApplyButton?:boolean}} options JSON with search properties
331
- * @param options.searchCriteria JSON with search properties
332
- * @param options.searchCriteria.columnName [REQUIRED] name of the column to filter
333
- * @param options.searchCriteria.filterValue [REQUIRED] value to input into the filter textbox
334
- * @param options.searchCriteria.operator [Optional] Use if using a search operator (i.e. Less Than, Equals, etc...use filterOperator.enum values).
335
- * @param options.hasApplyButton [Optional] True if "Apply" button is used, false if filters by text input automatically.
336
- * @param options.noMenuTabs [Optional] True if you use for example the community edition of ag-grid, which has no menu tabs
337
- */
338
- export function filterBySearchTextColumnMenu(agGridElement, options) {
339
- // Check if there are multiple search criteria provided by attempting to access the columnName
340
- if (!options.searchCriteria.columnName) {
341
- options.searchCriteria.forEach((_searchCriteria) => {
342
- const _options = populateSearchCriteria(
343
- _searchCriteria,
344
- options.hasApplyButton,
345
- options.noMenuTabs
346
- );
347
- _filterBySearchTextColumnMenu(agGridElement, _options);
348
- });
349
- } else {
350
- _filterBySearchTextColumnMenu(agGridElement, options);
351
- }
352
- }
353
-
354
- function _filterBySearchTextColumnMenu(agGridElement, options) {
355
- // Get the header's menu element
356
- getFilterColumnButtonElement(
357
- agGridElement,
358
- options.searchCriteria.columnName
359
- ).click();
360
- filterBySearchTerm(
361
- agGridElement,
362
- options
363
- );
364
- applyColumnFilter(agGridElement, options.hasApplyButton, options.noMenuTabs);
365
- }
366
-
367
- /**
368
- * * Performs a filter operation on the specified column via the column's floating filter field using plain text search
369
- * @param agGridElement The get() selector for which ag grid table you wish to retrieve.
370
- * @param {{searchCriteria:[{columnName:string,filterValue:string,operator?:string}], hasApplyButton?:boolean}} options JSON with search properties
371
- * @param options.searchCriteria JSON with search properties and options
372
- * @param options.searchCriteria.columnName name of the column to filter
373
- * @param options.searchCriteria.filterValue value to input into the filter textbox
374
- * @param options.searchCriteria.searchInputIndex [Optional] Uses 0 by default. Index of which filter box to use in event of having multiple search conditionals
375
- * @param options.searchCriteria.operator [Optional] Use if using a search operator (i.e. Less Than, Equals, etc...use filterOperator.enum values).
376
- * @param options.hasApplyButton [Optional] True if "Apply" button is used, false if filters by text input automatically.
377
- * @param options.noMenuTabs [Optional] True if you use for example the community edition of ag-grid, which has no menu tabs
378
- */
379
- export function filterBySearchTextColumnFloatingFilter(agGridElement, options) {
380
- // Check if there are multiple search criteria provided by attempting to access the columnName
381
- if (!options.searchCriteria.columnName) {
382
- options.searchCriteria.forEach((_searchCriteria) => {
383
- const _options = populateSearchCriteria(
384
- _searchCriteria,
385
- options.hasApplyButton,
386
- options.noMenuTabs
387
- );
388
- _filterBySearchTextColumnFloatingFilter(agGridElement, _options);
389
- });
390
- } else {
391
- _filterBySearchTextColumnFloatingFilter(agGridElement, options);
392
- }
393
- }
394
-
395
- function _filterBySearchTextColumnFloatingFilter(agGridElement, options) {
396
- cy.get(agGridElement).then((agGridElement) => {
397
- getFilterColumnButtonElement(
398
- agGridElement,
399
- options.searchCriteria.columnName,
400
- true
401
- ).click();
402
- filterBySearchTerm(
403
- agGridElement,
404
- options
405
- );
406
- applyColumnFilter(
407
- agGridElement,
408
- options.hasApplyButton,
409
- options.noMenuTabs
410
- );
411
- });
412
- }
413
-
414
- /**
415
- * * Performs a filter operation on the specified column and selects only the provided filterValue
416
- * @param agGridElement The get() selector for which ag grid table you wish to retrieve.
417
- * @param {{searchCriteria:[{columnName:string,filterValue:string], hasApplyButton?:boolean}} options JSON with search values and options
418
- * @param options.searchCriteria [REQUIRED] JSON with search properties
419
- * @param options.searchCriteria.columnName [REQUIRED] name of the column to filter
420
- * @param options.searchCriteria.filterValue [REQUIRED] value to input into the filter textbox
421
- * @param options.hasApplyButton [Optional] True if "Apply" button is used, false if filters by text input automatically.
422
- * @param options.noMenuTabs [Optional] True if you use for example the community edition of ag-grid, which has no menu tabs
423
- */
424
- export function filterByCheckboxColumnMenu(agGridElement, options) {
425
- // Check if there are multiple search criteria provided by attempting to access the columnName
426
- if (!options.searchCriteria.columnName) {
427
- options.searchCriteria.forEach((_searchCriteria) => {
428
- const _options = populateSearchCriteria(
429
- _searchCriteria,
430
- options.hasApplyButton,
431
- options.noMenuTabs
432
- );
433
- _filterByCheckboxColumnMenu(agGridElement, _options);
434
- });
435
- } else {
436
- _filterByCheckboxColumnMenu(agGridElement, options);
437
- }
438
- }
439
-
440
- function _filterByCheckboxColumnMenu(agGridElement, options) {
441
- cy.get(agGridElement).then((agGridElement) => {
442
- getFilterColumnButtonElement(
443
- agGridElement,
444
- options.searchCriteria.columnName
445
- ).click();
446
- const selectAllText = options.selectAllLocaleText || "Select All";
447
- toggleColumnCheckboxFilter(
448
- agGridElement,
449
- selectAllText,
450
- false,
451
- options.noMenuTabs
452
- );
453
- toggleColumnCheckboxFilter(
454
- agGridElement,
455
- options.searchCriteria.filterValue,
456
- true,
457
- options.noMenuTabs
458
- );
459
- applyColumnFilter(
460
- agGridElement,
461
- options.hasApplyButton,
462
- options.noMenuTabs
463
- );
464
- });
465
- }
466
-
467
- /**
468
- * Will perform a filter for all search criteria provided, then selects all found entries in the grid
469
- * @param searchCriteria a "\^" delimited string of all columns and searchCriteria to search for in the grid (i.e. "Name=John Smith^Rate Plan=Standard"
470
- */
471
- export function filterGridEntriesBySearchText(
472
- agGridElement,
473
- searchCriteria,
474
- isFloatingFilter = false
475
- ) {
476
- if (isFloatingFilter) {
477
- filterBySearchTextColumnFloatingFilter(agGridElement, searchCriteria);
478
- } else {
479
- filterBySearchTextColumnMenu(agGridElement, searchCriteria);
480
- }
481
- }
482
-
483
- /**
484
- * Will add or remove a column from ag grid.
485
- * @param columnName The column name to add/remove
486
- * @param doRemove true will remove the column. false will add the column.
487
- */
488
-
489
- export function toggleColumnFromSideBar(agGridElement, columnName, doRemove) {
490
- cy.get(agGridElement)
491
- .find(".ag-column-select-header-filter-wrapper")
492
- .find("input")
493
- .then(($columnFilterInputField) => {
494
- if (!$columnFilterInputField.is(":visible")) {
495
- cy.get(".ag-side-buttons").find("span").contains("Columns").click();
496
- }
497
- cy.wrap($columnFilterInputField).clear().wait(250).type(columnName);
498
- cy.get(".ag-column-select-column-label")
499
- .contains(columnName)
500
- .parent()
501
- .find("input")
502
- .then(($columnCheckbox) => {
503
- if (doRemove) cy.wrap($columnCheckbox).uncheck();
504
- else cy.wrap($columnCheckbox).check();
505
- });
506
- });
507
- }
1
+ /// <reference types="cypress" />
2
+ import { sort } from "./sort.enum";
3
+ import { filterTab } from "./menuTab.enum";
4
+
5
+ /**
6
+ * Uses the attribute value's index and sorts the data accordingly.
7
+ * For our purposes, we are getting the attribute with the items' indices and sorting accordingly.
8
+ *
9
+ * @param {*} index
10
+ * @returns
11
+ */
12
+ function sortElementsByAttributeValue(attribute) {
13
+ return (a, b) => {
14
+ const contentA = parseInt(a.attributes[attribute].nodeValue, 10).valueOf();
15
+ const contentB = parseInt(b.attributes[attribute].nodeValue, 10).valueOf();
16
+ return contentA < contentB ? -1 : contentA > contentB ? 1 : 0;
17
+ };
18
+ }
19
+
20
+ /**
21
+ * Retrieves the values from the *displayed* page in ag grid and assigns each value to its respective column name.
22
+ * @param agGridElement The get() selector for which ag grid table you wish to retrieve.
23
+ * @param options Provide an array of columns you wish to exclude from the table retrieval.
24
+ */
25
+ export const getAgGridData = (agGridElement, options = {}) => {
26
+ return _getAgGrid(agGridElement, options, false);
27
+ };
28
+
29
+ /**
30
+ * Retrieves the values from the *displayed* page in ag grid and assigns each value to its respective column name.
31
+ * @param agGridElement The get() selector for which ag grid table you wish to retrieve.
32
+ * @param options Provide an array of columns you wish to exclude from the table retrieval.
33
+ */
34
+ export const getAgGridElements = (agGridElement, options = {}) => {
35
+ return _getAgGrid(agGridElement, options, true);
36
+ };
37
+
38
+ function _getAgGrid(agGridElement, options = {}, returnElements) {
39
+ const agGridColumnSelectors =
40
+ ".ag-pinned-left-cols-container^.ag-center-cols-clipper^.ag-pinned-right-cols-container";
41
+ if (agGridElement.get().length > 1)
42
+ throw new Error(
43
+ `Selector "${agGridElement.selector}" returned more than 1 element.`
44
+ );
45
+
46
+ const tableElement = agGridElement.get()[0].querySelectorAll(".ag-root")[0];
47
+ const agGridSelectors = agGridColumnSelectors.split("^");
48
+ const headers = [
49
+ ...tableElement.querySelectorAll(".ag-header-row-column [aria-colindex]"),
50
+ ]
51
+ .sort(sortElementsByAttributeValue("aria-colindex"))
52
+ .map((headerElement) => {
53
+ // Check if the elements returned are already .ag-header-cell-text elements
54
+ // If not, query for that element and return the text content
55
+ let headerCells = [
56
+ ...headerElement.querySelectorAll(".ag-header-cell-text"),
57
+ ];
58
+ if (headerCells.length === 0) {
59
+ return [headerElement].map((e) => e.textContent.trim());
60
+ } else {
61
+ return [...headerElement.querySelectorAll(".ag-header-cell-text")].map(
62
+ (e) => e.textContent.trim()
63
+ );
64
+ }
65
+ })
66
+ .flat();
67
+
68
+ let allRows = [];
69
+ let rows = [];
70
+
71
+ agGridSelectors.forEach((selector) => {
72
+ const _rows = [
73
+ ...tableElement.querySelectorAll(`${selector}:not(.ag-hidden) .ag-row`),
74
+ ]
75
+ // Sort rows by their row-index attribute value
76
+ .sort(sortElementsByAttributeValue("row-index"))
77
+ .map((row) => {
78
+ // Sort row cells by their aria-colindex attribute value
79
+ // First check if elements returned already contain the aria-colindex
80
+ // If not, just query for the .ag-cell
81
+ let rowCells = [...row.querySelectorAll(".ag-cell [aria-colindex]")];
82
+ if (rowCells.length === 0) {
83
+ rowCells = [...row.querySelectorAll(".ag-cell")];
84
+ }
85
+ return rowCells
86
+ .sort(sortElementsByAttributeValue("aria-colindex"))
87
+ .map((e) => {
88
+ if (returnElements) {
89
+ return e;
90
+ } else {
91
+ return e.textContent.trim();
92
+ }
93
+ });
94
+ });
95
+ allRows.push(_rows);
96
+ });
97
+
98
+ // Remove any empty arrays before merging
99
+ allRows = allRows.filter(function (ele) {
100
+ return ele.length;
101
+ });
102
+
103
+ if (!allRows.length) rows = [];
104
+ else {
105
+ // Combine results from all specified tables (either single table, or all pinned columns) by index
106
+ rows = allRows.reduce(function (a, b) {
107
+ return a.map(function (v, i) {
108
+ return v.concat(b[i]);
109
+ });
110
+ });
111
+ }
112
+
113
+ // if options.rawValues = true, return headers & rows values as arrays instead of mapping as objects
114
+ if (options.valuesArray) {
115
+ return { headers, rows };
116
+ }
117
+
118
+ // return structured object from headers and rows variables
119
+ return rows.map((row) =>
120
+ row.reduce((acc, curr, idx) => {
121
+ if (
122
+ //@ts-ignore
123
+ (options.onlyColumns && !options.onlyColumns.includes(headers[idx])) ||
124
+ headers[idx] === undefined
125
+ ) {
126
+ // dont include columns that are not present in onlyColumns, or if the header is undefined
127
+ return { ...acc };
128
+ }
129
+ return { ...acc, [headers[idx]]: curr };
130
+ }, {})
131
+ );
132
+ }
133
+
134
+ /**
135
+ * Retrieve the ag grid column header element based on its column name value
136
+ * @param columnName The name of the column's header to retrieve.
137
+ */
138
+ function getColumnHeaderElement(agGridElement, columnName) {
139
+ return cy
140
+ .get(agGridElement)
141
+ .find(".ag-header-cell-text")
142
+ .contains(new RegExp("^" + columnName + "$", "g"));
143
+ }
144
+
145
+ /**
146
+ * * Performs sorting operation on the specified column
147
+ * @param {*} agGridElement The get() selector for which ag grid table you wish to retrieve.
148
+ * @param columnName The name of the column you wish to sort
149
+ * @param sortDirection sort enum value
150
+ * @returns
151
+ */
152
+ export function sortColumnBy(agGridElement, columnName, sortDirection) {
153
+ if (sortDirection === sort.ascending || sortDirection === sort.descending) {
154
+ return getColumnHeaderElement(agGridElement, columnName)
155
+ .parents(".ag-header-cell")
156
+ .invoke("attr", "aria-sort")
157
+ .then((value) => {
158
+ cy.log(`sort: ${sortDirection}`);
159
+ if (value !== sortDirection) {
160
+ getColumnHeaderElement(agGridElement, columnName).click().wait(250);
161
+ sortColumnBy(agGridElement, columnName, sortDirection);
162
+ }
163
+ });
164
+ } else {
165
+ throw new Error(
166
+ "sortDirection must be either 'ascending' or 'descending'."
167
+ );
168
+ }
169
+ }
170
+
171
+ function getMenuTabElement(agGridElement, tab) {
172
+ return cy
173
+ .get(agGridElement)
174
+ .find(".ag-tab")
175
+ .find(`.ag-icon-${tab}`)
176
+ .filter(":visible");
177
+ }
178
+
179
+ /**
180
+ * Will select the specified filter tab if it is not already selected
181
+ * @param tab
182
+ */
183
+ function selectMenuTab(agGridElement, tab) {
184
+ getMenuTabElement(agGridElement, tab).then(($ele) => {
185
+ cy.wrap($ele)
186
+ .parent("span")
187
+ .invoke("attr", "class")
188
+ .then(($attr) => {
189
+ if (!$attr.includes("selected")) {
190
+ cy.wrap($ele).click();
191
+ }
192
+ });
193
+ });
194
+ }
195
+
196
+ /**
197
+ * Returns the filter button element for a specified column
198
+ * @param columnName
199
+ */
200
+ function getFilterColumnButtonElement(
201
+ agGridElement,
202
+ columnName,
203
+ isFloatingFilter = false
204
+ ) {
205
+ let columnIndex;
206
+ if (isFloatingFilter)
207
+ return getColumnHeaderElement(agGridElement, columnName)
208
+ .parents(".ag-header-cell")
209
+ .then(($ele) => {
210
+ cy.wrap($ele)
211
+ .invoke("attr", "aria-colindex")
212
+ .then((colIndex) => {
213
+ columnIndex = colIndex;
214
+ })
215
+ .then(() => {
216
+ cy.wrap($ele)
217
+ .parents(".ag-header-row-column")
218
+ .siblings(".ag-header-row-column-filter")
219
+ .find(`.ag-header-cell[aria-colindex=${columnIndex}]`)
220
+ .find(".ag-floating-filter-button");
221
+ });
222
+ });
223
+ else
224
+ return getColumnHeaderElement(agGridElement, columnName)
225
+ .parent()
226
+ .siblings(".ag-header-cell-menu-button");
227
+ }
228
+
229
+ /**
230
+ *
231
+ * @param filterValue value to input into the filter textbox
232
+ * @param operator (optional) use if using a search operator (i.e. Less Than, Equals, etc...use filterOperator.enum values)
233
+ * @param noMenuTabs (optional) boolean indicating if the menu has tabs.
234
+ */
235
+ function filterBySearchTerm(agGridElement, options) {
236
+ const filterValue = options.searchCriteria.filterValue;
237
+ const operator = options.searchCriteria.operator;
238
+ const searchInputIndex = options.searchCriteria.searchInputIndex || 0;
239
+ const isMultiFilter = options.searchCriteria.isMultiFilter;
240
+ const noMenuTabs = options.noMenuTabs;
241
+
242
+ // Navigate to the filter tab
243
+ if (!noMenuTabs) {
244
+ selectMenuTab(agGridElement, filterTab.filter);
245
+ }
246
+ if (operator) {
247
+ cy.get(agGridElement)
248
+ .find(".ag-picker-field-wrapper")
249
+ .filter(":visible")
250
+ .click();
251
+ cy.get(agGridElement)
252
+ .find(".ag-popup")
253
+ .find("span")
254
+ .contains(operator)
255
+ .then(($ele) => {
256
+ //Have to use the unwrapped element, since Cypress .click() event does not appropriately select the operator
257
+ $ele.trigger("click");
258
+ });
259
+ }
260
+ // Input filter term and allow grid a moment to render the results
261
+ cy.get(agGridElement)
262
+ .find(".ag-popup-child")
263
+ .find("input")
264
+ .filter(":visible")
265
+ .as("filterInput")
266
+
267
+ // If it's a multi filter, de-select the 'select-all' checkbox
268
+ if(isMultiFilter){
269
+ const selectAllText = options.selectAllLocaleText || "Select All";
270
+ toggleColumnCheckboxFilter(
271
+ agGridElement,
272
+ selectAllText,
273
+ false,
274
+ true
275
+ );
276
+ }
277
+
278
+ // Get the saved filter input and enter the search term
279
+ cy.get("@filterInput").then(($ele)=>{
280
+ cy.wrap($ele)
281
+ .eq(searchInputIndex)
282
+ .clear()
283
+ .type(filterValue)
284
+ .wait(500);
285
+ })
286
+
287
+ // Finally, if a multi-filter, select the filter value's checkbox
288
+ if(isMultiFilter){
289
+ toggleColumnCheckboxFilter(agGridElement, filterValue, true, true)
290
+ }
291
+ }
292
+
293
+ function applyColumnFilter(agGridElement, hasApplyButton, noMenuTabs) {
294
+ if (hasApplyButton) {
295
+ cy.get(agGridElement)
296
+ .find(".ag-filter-apply-panel-button")
297
+ .contains("Apply")
298
+ .click();
299
+ }
300
+ if (!noMenuTabs) {
301
+ getMenuTabElement(agGridElement, filterTab.filter).click();
302
+ }
303
+ }
304
+
305
+ /**
306
+ * Either toggle
307
+ * @param filterValue
308
+ * @param doSelect
309
+ * @param hasTabs
310
+ */
311
+ function toggleColumnCheckboxFilter(
312
+ agGridElement,
313
+ filterValue,
314
+ doSelect,
315
+ noMenuTabs = false
316
+ ) {
317
+ if (!noMenuTabs) {
318
+ selectMenuTab(agGridElement, filterTab.filter);
319
+ }
320
+ cy.get(agGridElement)
321
+ .find(".ag-input-field-label")
322
+ .contains(filterValue)
323
+ .siblings("div")
324
+ .find("input")
325
+ .then(($ele) => {
326
+ if (doSelect) cy.wrap($ele).check();
327
+ else cy.wrap($ele).uncheck();
328
+ });
329
+ }
330
+
331
+ function populateSearchCriteria(
332
+ searchCriteria,
333
+ hasApplyButton = false,
334
+ noMenuTabs = false,
335
+ selectAllLocaleText = 'Select All'
336
+ ) {
337
+ const options = {};
338
+ //@ts-ignore
339
+ options.searchCriteria = {};
340
+ //@ts-ignore
341
+ options.searchCriteria.columnName = searchCriteria.columnName;
342
+ //@ts-ignore
343
+ options.searchCriteria.filterValue = searchCriteria.filterValue;
344
+ //@ts-ignore
345
+ options.searchCriteria.isMultiFilter = searchCriteria.isMultiFilter;
346
+ //@ts-ignore
347
+ options.selectAllLocaleText = selectAllLocaleText;
348
+ //@ts-ignore
349
+ options.hasApplyButton = hasApplyButton;
350
+ //@ts-ignore
351
+ options.noMenuTabs = noMenuTabs;
352
+ return options;
353
+ }
354
+
355
+ /**
356
+ * * Performs a filter operation on the specified column via the context menu using plain text search
357
+ * @param agGridElement The get() selector for which ag grid table you wish to retrieve.
358
+ * @param {{searchCriteria:[{columnName:string,filterValue:string,operator?:string}], hasApplyButton?:boolean}} options JSON with search properties
359
+ * @param options.searchCriteria JSON with search properties
360
+ * @param options.searchCriteria.columnName [REQUIRED] name of the column to filter
361
+ * @param options.searchCriteria.filterValue [REQUIRED] value to input into the filter textbox
362
+ * @param options.searchCriteria.operator [Optional] Use if using a search operator (i.e. Less Than, Equals, etc...use filterOperator.enum values).
363
+ * @param options.hasApplyButton [Optional] True if "Apply" button is used, false if filters by text input automatically.
364
+ * @param options.noMenuTabs [Optional] True if you use for example the community edition of ag-grid, which has no menu tabs
365
+ */
366
+ export function filterBySearchTextColumnMenu(agGridElement, options) {
367
+ // Check if there are multiple search criteria provided by attempting to access the columnName
368
+ if (!options.searchCriteria.columnName) {
369
+ options.searchCriteria.forEach((_searchCriteria) => {
370
+ const _options = populateSearchCriteria(
371
+ _searchCriteria,
372
+ options.hasApplyButton,
373
+ options.noMenuTabs,
374
+ options.isMultiFilter
375
+ );
376
+ _filterBySearchTextColumnMenu(agGridElement, _options);
377
+ });
378
+ } else {
379
+ _filterBySearchTextColumnMenu(agGridElement, options);
380
+ }
381
+ }
382
+
383
+ function _filterBySearchTextColumnMenu(agGridElement, options) {
384
+ // Get the header's menu element
385
+ getFilterColumnButtonElement(
386
+ agGridElement,
387
+ options.searchCriteria.columnName
388
+ ).click();
389
+ filterBySearchTerm(
390
+ agGridElement,
391
+ options
392
+ );
393
+ applyColumnFilter(agGridElement, options.hasApplyButton, options.noMenuTabs);
394
+ }
395
+
396
+ /**
397
+ * * Performs a filter operation on the specified column via the column's floating filter field using plain text search
398
+ * @param agGridElement The get() selector for which ag grid table you wish to retrieve.
399
+ * @param {{searchCriteria:[{columnName:string,filterValue:string,operator?:string}], hasApplyButton?:boolean, noMenuTab?:boolean, selectAllLocaleText:string}} options JSON with search properties
400
+ * @param options.searchCriteria JSON with search properties and options
401
+ * @param options.searchCriteria.columnName name of the column to filter
402
+ * @param options.searchCriteria.filterValue value to input into the filter textbox
403
+ * @param options.searchCriteria.searchInputIndex [Optional] Uses 0 by default. Index of which filter box to use in event of having multiple search conditionals
404
+ * @param options.searchCriteria.operator [Optional] Use if using a search operator (i.e. Less Than, Equals, etc...use filterOperator.enum values).
405
+ * @param options.hasApplyButton [Optional] True if "Apply" button is used, false if filters by text input automatically.
406
+ * @param options.noMenuTabs [Optional] True if you use, for example, the community edition of ag-grid, which has no menu tabs
407
+ * @param options.selectAllLocaleText [Optional] Pass in the locale text value of "Select All" for when you are filtering by checkbox - this wil first deselect the "Select All" option before selecting your filter value
408
+ */
409
+ export function filterBySearchTextColumnFloatingFilter(agGridElement, options) {
410
+ // Check if there are multiple search criteria provided by attempting to access the columnName
411
+ if (!options.searchCriteria.columnName) {
412
+ options.searchCriteria.forEach((_searchCriteria) => {
413
+ const _options = populateSearchCriteria(
414
+ _searchCriteria,
415
+ options.hasApplyButton,
416
+ options.noMenuTabs
417
+ );
418
+ _filterBySearchTextColumnFloatingFilter(agGridElement, _options);
419
+ });
420
+ } else {
421
+ _filterBySearchTextColumnFloatingFilter(agGridElement, options);
422
+ }
423
+ }
424
+
425
+ function _filterBySearchTextColumnFloatingFilter(agGridElement, options) {
426
+ cy.get(agGridElement).then((agGridElement) => {
427
+ getFilterColumnButtonElement(
428
+ agGridElement,
429
+ options.searchCriteria.columnName,
430
+ true
431
+ ).click();
432
+ filterBySearchTerm(
433
+ agGridElement,
434
+ options
435
+ );
436
+ applyColumnFilter(
437
+ agGridElement,
438
+ options.hasApplyButton,
439
+ options.noMenuTabs
440
+ );
441
+ });
442
+ }
443
+
444
+ /**
445
+ * * Performs a filter operation on the specified column and selects only the provided filterValue
446
+ * @param agGridElement The get() selector for which ag grid table you wish to retrieve.
447
+ * @param {{searchCriteria:[{columnName:string,filterValue:string], hasApplyButton?:boolean}} options JSON with search values and options
448
+ * @param options.searchCriteria [REQUIRED] JSON with search properties
449
+ * @param options.searchCriteria.columnName [REQUIRED] name of the column to filter
450
+ * @param options.searchCriteria.filterValue [REQUIRED] value to input into the filter textbox
451
+ * @param options.hasApplyButton [Optional] True if "Apply" button is used, false if filters by text input automatically.
452
+ * @param options.noMenuTabs [Optional] True if you use for example the community edition of ag-grid, which has no menu tabs
453
+ */
454
+ export function filterByCheckboxColumnMenu(agGridElement, options) {
455
+ // Check if there are multiple search criteria provided by attempting to access the columnName
456
+ if (!options.searchCriteria.columnName) {
457
+ options.searchCriteria.forEach((_searchCriteria) => {
458
+ const _options = populateSearchCriteria(
459
+ _searchCriteria,
460
+ options.hasApplyButton,
461
+ options.noMenuTabs,
462
+ options.selectAllLocaleText
463
+ );
464
+ _filterByCheckboxColumnMenu(agGridElement, _options);
465
+ });
466
+ } else {
467
+ _filterByCheckboxColumnMenu(agGridElement, options);
468
+ }
469
+ }
470
+
471
+ function _filterByCheckboxColumnMenu(agGridElement, options) {
472
+ cy.get(agGridElement).then((agGridElement) => {
473
+ getFilterColumnButtonElement(
474
+ agGridElement,
475
+ options.searchCriteria.columnName
476
+ ).click();
477
+ const selectAllText = options.selectAllLocaleText || "Select All";
478
+ toggleColumnCheckboxFilter(
479
+ agGridElement,
480
+ selectAllText,
481
+ false,
482
+ options.noMenuTabs
483
+ );
484
+ toggleColumnCheckboxFilter(
485
+ agGridElement,
486
+ options.searchCriteria.filterValue,
487
+ true,
488
+ options.noMenuTabs
489
+ );
490
+ applyColumnFilter(
491
+ agGridElement,
492
+ options.hasApplyButton,
493
+ options.noMenuTabs
494
+ );
495
+ });
496
+ }
497
+
498
+ /**
499
+ * Will perform a filter for all search criteria provided, then selects all found entries in the grid
500
+ * @param searchCriteria a "\^" delimited string of all columns and searchCriteria to search for in the grid (i.e. "Name=John Smith^Rate Plan=Standard"
501
+ */
502
+ export function filterGridEntriesBySearchText(
503
+ agGridElement,
504
+ searchCriteria,
505
+ isFloatingFilter = false
506
+ ) {
507
+ if (isFloatingFilter) {
508
+ filterBySearchTextColumnFloatingFilter(agGridElement, searchCriteria);
509
+ } else {
510
+ filterBySearchTextColumnMenu(agGridElement, searchCriteria);
511
+ }
512
+ }
513
+
514
+ /**
515
+ * Will add or remove a column from ag grid.
516
+ * @param columnName The column name to add/remove
517
+ * @param doRemove true will remove the column. false will add the column.
518
+ */
519
+
520
+ export function toggleColumnFromSideBar(agGridElement, columnName, doRemove) {
521
+ cy.get(agGridElement)
522
+ .find(".ag-column-select-header-filter-wrapper")
523
+ .find("input")
524
+ .then(($columnFilterInputField) => {
525
+ if (!$columnFilterInputField.is(":visible")) {
526
+ cy.get(".ag-side-buttons").find("span").contains("Columns").click();
527
+ }
528
+ cy.wrap($columnFilterInputField).clear().wait(250).type(columnName);
529
+ cy.get(".ag-column-select-column-label")
530
+ .contains(columnName)
531
+ .parent()
532
+ .find("input")
533
+ .then(($columnCheckbox) => {
534
+ if (doRemove) cy.wrap($columnCheckbox).uncheck();
535
+ else cy.wrap($columnCheckbox).check();
536
+ });
537
+ });
538
+ }