cypress-ag-grid 1.5.0 → 2.0.1

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.
package/README.md CHANGED
@@ -7,10 +7,14 @@ Cypress plugin for interacting with and validating against ag grid.
7
7
  + [Grid Interaction](#)
8
8
  - [Getting Data From the Grid](#getting-data-from-the-grid)
9
9
  - [Getting Select Row Data](#getting-select-row-data)
10
+ - [Getting Elements From the Grid](#getting-elements-from-the-grid)
10
11
  - [Sorting Columns](#sorting-columns)
12
+ + [Grid Filtering](#)
13
+ - [Filter Options](#filter-options)
11
14
  - [Filter by Text - Column Menu](#filter-by-text---column-menu)
12
15
  - [Filterby Text - Floating Filter](#filterby-text---floating-filter)
13
16
  - [Filter by Checkbox - Column Menu](#filter-by-checkbox---column-menu)
17
+ - [Filtering - Localization and Internationalization](#filtering---localization-and-internationalization)
14
18
  - [Add or Remove Columns](#add-or-remove-columns)
15
19
  + [Grid Validation](#)
16
20
  - [Validate Paginated Table](#validate-paginated-table)
@@ -86,6 +90,25 @@ The above command will return the follwoing:
86
90
  </br>
87
91
  </br>
88
92
 
93
+ ### Getting Elements From the Grid
94
+ To get the Ag Grid data as elements (if you want to interact with the cells themselves), you must chain `.getAgGridElements()` after the `cy.get()` command for the topmost level of the grid, including controls and headers (see selected DOM element in above image).
95
+ ```javascript
96
+ cy.get(agGridSelector)
97
+ .getAgGridElements()
98
+ .then((tableElements) => {
99
+ const porscheRow = tableElements.find(
100
+ (row) => row.Price.innerText === "72000"
101
+ );
102
+ const priceCell = porscheRow.Price;
103
+ cy.wrap(priceCell).dblclick().type("66000{enter}");
104
+ });
105
+
106
+ ```
107
+
108
+ The above example will grab the table as elements, finds the row whose `Price` equals `72000`. It then gets the `Price` cell for that row, double clicks on it to enable an editable input, and changes the value of the cell.
109
+ </br>
110
+ </br>
111
+
89
112
  ### Sorting Columns
90
113
  This command will sort the specified column by the sort direction specified.
91
114
 
@@ -100,6 +123,34 @@ cy.get("#myGrid").agGridSortColumn("Model", "descending");
100
123
  </br>
101
124
  </br>
102
125
 
126
+ ### Filter Options
127
+
128
+ The below filtering commands takes an `options` parameter comprised of the following properties:
129
+
130
+ ```javascript
131
+ options: {
132
+ searchCriteria: [{
133
+ columnName: string;
134
+ filterValue: string;
135
+ operator?: string;
136
+ }];
137
+ hasApplyButton?: boolean;
138
+ noMenuTab?: boolean;
139
+ selectAllLocaleText: string;
140
+ }
141
+
142
+ /**
143
+ - options.searchCriteria JSON with search properties and options
144
+ - options.searchCriteria.columnName name of the column to filter
145
+ - options.searchCriteria.filterValue value to input into the filter textbox
146
+ - options.searchCriteria.searchInputIndex [Optional] Uses 0 by default. Index of which filter box to use in event of having multiple search conditionals
147
+ - options.searchCriteria.operator [Optional] Use if using a search operator (i.e. Less Than, Equals, etc...use filterOperator.enum values).
148
+ - options.hasApplyButton [Optional] True if "Apply" button is used, false if filters by text input automatically.
149
+ - options.noMenuTabs [Optional] True if you use, for example, the community edition of ag-grid, which has no menu tabs
150
+ - 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
151
+ */
152
+ ```
153
+
103
154
  ### Filter by Text - Column Menu
104
155
  This command will filter a column by a text value from its menu. In the options, you must specify a `searchCriteria` objects containing one or more objects with `columnName`, `filterValue`, and optionally `operator` (i.e. Contains, Not contains, Equals, etc.).
105
156
 
@@ -194,6 +245,20 @@ Example:
194
245
 
195
246
  ```
196
247
  </br>
248
+
249
+ ### Filtering - Localization and Internationalization
250
+ When we filter by checkbox, we first deselect the Select All checkbox to ensure we ONLY select the specified checkbox. Since AG grid allows for localization, we need a way to be able to pass in the localeText for Select All. This is the only area of this plugin that has a hard-coded value, so no other localization accommodations are needed.
251
+
252
+ ```
253
+ cy.get("#myGrid").agGridColumnFilterCheckboxMenu({
254
+ searchCriteria: {
255
+ columnName: "Model",
256
+ filterValue: "2002",
257
+ },
258
+ selectAllLocaleText: "Tout Sélectionner"
259
+ hasApplyButton: true,
260
+ });
261
+ ```
197
262
  </br>
198
263
 
199
264
  ### Add or Remove Columns
@@ -251,7 +316,7 @@ Example:
251
316
  cy.get("#myGrid")
252
317
  .getAgGridData()
253
318
  .then((actualTableData) => {
254
- cy.get(agGridSelector).agGridValidateRowsExactOrder(actualTableData, expectedTableData);
319
+ cy.agGridValidateRowsExactOrder(actualTableData, expectedTableData);
255
320
  });
256
321
  ```
257
322
  <br/>
@@ -274,7 +339,7 @@ Example:
274
339
  cy.get(agGridSelector)
275
340
  .getAgGridData({ onlyColumns: ["Year", "Make", "Model"] })
276
341
  .then((actualTableData) => {
277
- cy.get(agGridSelector).agGridValidateRowsSubset(actualTableData, expectedTableData);
342
+ cy.agGridValidateRowsSubset(actualTableData, expectedTableData);
278
343
  });
279
344
  });
280
345
  ```
@@ -291,13 +356,13 @@ Example:
291
356
  cy.get(agGridSelector)
292
357
  .getAgGridData()
293
358
  .then((actualTableData) => {
294
- cy.get(agGridSelector).agGridValidateEmptyTable(actualTableData);
359
+ cy.agGridValidateEmptyTable(actualTableData);
295
360
  });
296
361
  ```
297
362
 
298
363
  ## Limitations
299
- * Unable to validate deeply nested row groups
300
- * Unable to validate deeply nested column groups
364
+ * ~~Unable to validate deeply nested row groups~~ As of v2.x, using `.getAgGridElements()` you should be able to accomplish this.
365
+ * ~~Unable to validate deeply nested column groups~~ As of v2.x, using `.getAgGridElements()` you should be able to accomplish this.
301
366
  * Unable to validate the entirety of an unlimited scrolling grid.
302
367
  * Unable to validate data that is out of view. The DOM will register the ag grid data as it's scrolled into view.
303
368
  * To combat this, in your code where the ag grid is called, check if the Cypress window is controlling the app and set the ag grid object to `.sizeColumnsToFit()`. You can see an example of this in the `app/grid.js` file of this repository. Read more [here](https://www.ag-grid.com/javascript-grid/column-sizing/#size-columns-to-fit)
@@ -308,4 +373,4 @@ Example:
308
373
  }
309
374
  ```
310
375
  ## Credit
311
- A portion of the logic to retrieve table data was expanded upon from the project [Cypress-Get-Table](https://github.com/roggerfe/cypress-get-table) by [Rogger Fernandez](https://github.com/roggerfe).
376
+ A portion of the logic to retrieve table data was expanded upon from the project [Cypress-Get-Table](https://github.com/roggerfe/cypress-get-table) by [Rogger Fernandez](https://github.com/roggerfe).
@@ -1,9 +1,9 @@
1
1
  // specify the columns
2
2
  const columnDefs = [
3
- { field: "year", pinned: "left" },
3
+ { field: "year", pinned: "left"},
4
4
  { field: "make", rowGroup: false, pinned: "left" },
5
5
  { field: "model", filter: true },
6
- { field: "price", pinned: "right", floatingFilter: false, sortable: false },
6
+ { field: "price", pinned: "right", floatingFilter: false, sortable: false, editable: true, cellEditor: 'agTextCellEditor' },
7
7
  ];
8
8
 
9
9
  const autoGroupColumnDef = {
@@ -47,7 +47,7 @@ new agGrid.Grid(eGridDiv, gridOptions);
47
47
  // Grab the grid data from the supplied API endpoint
48
48
  agGrid
49
49
  .simpleHttpRequest({
50
- url: "https://api.jsonbin.io/v3/b/608304f69a9aa933335613a6/2"
50
+ url: "https://api.jsonbin.io/v3/b/608304f69a9aa933335613a6/2",
51
51
  })
52
52
  .then((data) => {
53
53
  gridOptions.api.setRowData(data.record);
@@ -0,0 +1,71 @@
1
+ // specify the columns
2
+ const columnDefsGrouped = [
3
+ { field: "year", pivot: true, },
4
+ { field: "make", rowGroup: true, enableRowGroup: true },
5
+ { field: "model", filter: true },
6
+ { field: "price", editable: true, cellEditor: 'agTextCellEditor' },
7
+ ];
8
+
9
+ const autoGroupColumnDefGrouped = {
10
+ headerName: "Model",
11
+ field: "model",
12
+ cellRenderer: "agGroupCellRenderer",
13
+ cellRendererParams: {
14
+ checkbox: true,
15
+ },
16
+ };
17
+
18
+ // let the grid know which columns to use
19
+ const gridOptionsGrouped = {
20
+ defaultColDef: {
21
+ sortable: true,
22
+ filter: "agTextColumnFilter",
23
+ floatingFilter: true,
24
+ filterParams: {
25
+ buttons: ["reset", "apply"],
26
+ debounceMs: 200,
27
+ },
28
+ animateRows: true,
29
+ resizable: true,
30
+ },
31
+ groupDefaultExpanded: 2,
32
+ autoGroupColumnDef: autoGroupColumnDefGrouped,
33
+ groupSelectsChildren: true,
34
+ columnDefs: columnDefsGrouped,
35
+ rowSelection: "multiple",
36
+ domLayout: "normal",
37
+ pagination: true,
38
+ paginationPageSize: 5,
39
+ sideBar: false,
40
+ };
41
+
42
+ // lookup the container we want the Grid to use
43
+ const eGridDivGrouped = document.querySelector("#myGrid2");
44
+
45
+ // create the grid passing in the div to use together with the columns &amp; data we want to use
46
+ new agGrid.Grid(eGridDivGrouped, gridOptionsGrouped);
47
+
48
+ // Grab the grid data from the supplied API endpoint
49
+ agGrid
50
+ .simpleHttpRequest({
51
+ url: "https://api.jsonbin.io/v3/b/608304f69a9aa933335613a6/2",
52
+ })
53
+ .then((data) => {
54
+ gridOptionsGrouped.api.setRowData(data.record);
55
+ });
56
+
57
+ function autoSizeAllColumns() {
58
+ var allColumnIds = [];
59
+ gridOptionsGrouped.columnApi.getAllColumns().forEach(function (column) {
60
+ allColumnIds.push(column.colId);
61
+ });
62
+ gridOptionsGrouped.columnApi.autoSizeColumns(allColumnIds);
63
+ }
64
+
65
+ // If the Cypress test is running, ensure all columns fit within the window
66
+ if (window.Cypress) {
67
+ gridOptionsGrouped.api.sizeColumnsToFit();
68
+ } else {
69
+ // Otherwise auto-size columns the way we wish to view the grid in production.
70
+ autoSizeAllColumns();
71
+ }
package/app/index.html CHANGED
@@ -7,7 +7,9 @@
7
7
  </head>
8
8
  <body>
9
9
  <div id="myGrid" style="height: 600px;width:900px;" class="ag-theme-alpine" sideBar="true"></div>
10
- <script src="grid.js" type="text/javascript" charset="utf-8">
11
- </script>
10
+ <script src="grid-basic.js" type="text/javascript" charset="utf-8"></script>
11
+
12
+ <div id="myGrid2" style="height: 600px;width:900px;" class="ag-theme-alpine" sideBar="true"></div>
13
+ <script src="grid-grouped.js" type="text/javascript" charset="utf-8"></script>
12
14
  </body>
13
15
  </html>
@@ -104,7 +104,7 @@ describe("ag-grid get data scenarios", () => {
104
104
  cy.get(agGridSelector)
105
105
  .getAgGridData()
106
106
  .then((actualTableData) => {
107
- cy.get(agGridSelector).agGridValidateRowsExactOrder(actualTableData, expectedTableData)
107
+ cy.agGridValidateRowsExactOrder(actualTableData, expectedTableData);
108
108
  });
109
109
  });
110
110
 
@@ -130,11 +130,7 @@ describe("ag-grid get data scenarios", () => {
130
130
  cy.get(agGridSelector)
131
131
  .getAgGridData()
132
132
  .then((actualTableData) => {
133
- cy.get(agGridSelector).agGridValidateRowsExactOrder(
134
- actualTableData,
135
- expectedTableData,
136
- true
137
- );
133
+ cy.agGridValidateRowsExactOrder(actualTableData, expectedTableData, true);
138
134
  });
139
135
  });
140
136
 
@@ -156,7 +152,7 @@ describe("ag-grid get data scenarios", () => {
156
152
  cy.get(agGridSelector)
157
153
  .getAgGridData()
158
154
  .then((actualTableData) => {
159
- cy.get(agGridSelector).agGridValidateRowsExactOrder(actualTableData, expectedTableData);
155
+ cy.agGridValidateRowsExactOrder(actualTableData, expectedTableData);
160
156
  });
161
157
  });
162
158
 
@@ -183,7 +179,7 @@ describe("ag-grid get data scenarios", () => {
183
179
  cy.get(agGridSelector)
184
180
  .getAgGridData()
185
181
  .then((actualTableData) => {
186
- cy.get(agGridSelector).agGridValidateRowsExactOrder(actualTableData, expectedTableData);
182
+ cy.agGridValidateRowsExactOrder(actualTableData, expectedTableData);
187
183
  });
188
184
  });
189
185
 
@@ -205,7 +201,7 @@ describe("ag-grid get data scenarios", () => {
205
201
  cy.get(agGridSelector)
206
202
  .getAgGridData()
207
203
  .then((actualTableData) => {
208
- cy.get(agGridSelector).agGridValidateRowsExactOrder(actualTableData, expectedTableData);
204
+ cy.agGridValidateRowsExactOrder(actualTableData, expectedTableData);
209
205
  });
210
206
  });
211
207
 
@@ -235,7 +231,7 @@ describe("ag-grid get data scenarios", () => {
235
231
  cy.get(agGridSelector)
236
232
  .getAgGridData()
237
233
  .then((actualTableData) => {
238
- cy.get(agGridSelector).agGridValidateRowsExactOrder(actualTableData, expectedTableData);
234
+ cy.agGridValidateRowsExactOrder(actualTableData, expectedTableData);
239
235
  });
240
236
  });
241
237
 
@@ -264,6 +260,30 @@ describe("ag-grid get data scenarios", () => {
264
260
  });
265
261
  });
266
262
 
263
+ it("able to filter by text - floating filter - multi filter", () => {
264
+ const expectedTableData = [
265
+ { Year: "2020", Make: "Ford", Model: "Taurus", Price: "19000" },
266
+ { Year: "1990", Make: "Ford", Model: "Taurus", Price: "900" },
267
+ ];
268
+ cy.get(agGridSelector).agGridSortColumn("Model", sort.ascending);
269
+ cy.get(agGridSelector).agGridColumnFilterTextFloating({
270
+ searchCriteria: [
271
+ {
272
+ columnName: "Model",
273
+ filterValue: "Taurus",
274
+ isMultiFilter: true
275
+ },
276
+ ],
277
+ hasApplyButton: true,
278
+ });
279
+ cy.get(agGridSelector)
280
+ .getAgGridData()
281
+ .then((actualTableData) => {
282
+ cy.get(agGridSelector).agGridValidateRowsExactOrder(actualTableData, expectedTableData);
283
+ });
284
+ });
285
+
286
+
267
287
  it("able to validate empty table", () => {
268
288
  //Search for an entry that does not exist
269
289
  cy.get(agGridSelector).agGridColumnFilterTextMenu({
@@ -277,7 +297,7 @@ describe("ag-grid get data scenarios", () => {
277
297
  cy.get(agGridSelector)
278
298
  .getAgGridData()
279
299
  .then((actualTableData) => {
280
- cy.get(agGridSelector).agGridValidateEmptyTable(actualTableData);
300
+ cy.agGridValidateEmptyTable(actualTableData);
281
301
  });
282
302
  });
283
303
 
@@ -296,7 +316,7 @@ describe("ag-grid get data scenarios", () => {
296
316
  cy.get(agGridSelector)
297
317
  .getAgGridData()
298
318
  .then((actualTableData) => {
299
- cy.get(agGridSelector).agGridValidateRowsExactOrder(
319
+ cy.agGridValidateRowsExactOrder(
300
320
  actualTableData,
301
321
  expectedData_sortedByAscending
302
322
  );
@@ -319,7 +339,7 @@ describe("ag-grid get data scenarios", () => {
319
339
  cy.get(agGridSelector)
320
340
  .getAgGridData()
321
341
  .then((actualTableData) => {
322
- cy.get(agGridSelector).agGridValidateRowsExactOrder(
342
+ cy.agGridValidateRowsExactOrder(
323
343
  actualTableData,
324
344
  expectedData_sortedByDescending
325
345
  );
@@ -337,7 +357,7 @@ describe("ag-grid get data scenarios", () => {
337
357
  cy.get(agGridSelector)
338
358
  .getAgGridData()
339
359
  .then((actualTableData) => {
340
- cy.get(agGridSelector).agGridValidateRowsExactOrder(
360
+ cy.agGridValidateRowsExactOrder(
341
361
  actualTableData,
342
362
  expectedData_yearColumnRemoved.slice(0, _pageSize)
343
363
  );
@@ -356,7 +376,7 @@ describe("ag-grid get data scenarios", () => {
356
376
  cy.get(agGridSelector)
357
377
  .getAgGridData()
358
378
  .then((actualTableData) => {
359
- cy.get(agGridSelector).agGridValidateRowsExactOrder(
379
+ cy.agGridValidateRowsExactOrder(
360
380
  actualTableData,
361
381
  expectedData_priceColumnRemoved.slice(0, _pageSize)
362
382
  );
@@ -375,7 +395,7 @@ describe("ag-grid get data scenarios", () => {
375
395
  cy.get(agGridSelector)
376
396
  .getAgGridData()
377
397
  .then((actualTableData) => {
378
- cy.get(agGridSelector).agGridValidateRowsExactOrder(
398
+ cy.agGridValidateRowsExactOrder(
379
399
  actualTableData,
380
400
  expectedData_multipleColumnsRemoved.slice(0, _pageSize)
381
401
  );
@@ -394,7 +414,7 @@ describe("ag-grid get data scenarios", () => {
394
414
  cy.get(agGridSelector)
395
415
  .getAgGridData({ onlyColumns: ["Year", "Make", "Model"] })
396
416
  .then((actualTableData) => {
397
- cy.get(agGridSelector).agGridValidateRowsSubset(actualTableData, expectedTableData);
417
+ cy.agGridValidateRowsSubset(actualTableData, expectedTableData);
398
418
  });
399
419
  });
400
420
  });
@@ -0,0 +1,59 @@
1
+ import { filterOperator } from "../../src/agGrid/filterOperator.enum";
2
+
3
+ const agGridSelector = "#myGrid2";
4
+
5
+ describe("ag-grid get elements scenario", () => {
6
+ beforeEach(() => {
7
+ cy.visit("../app/index.html");
8
+ cy.get(".ag-cell", { timeout: 10000 }).should("be.visible");
9
+ });
10
+
11
+ it("able to update grid cell value", () => {
12
+ // filter to only show the porsche
13
+ cy.get(agGridSelector).agGridColumnFilterTextFloating({
14
+ searchCriteria: {
15
+ columnName: "Make",
16
+ filterValue: "Porsche",
17
+ operator: filterOperator.equals,
18
+ },
19
+ hasApplyButton: true,
20
+ });
21
+
22
+ // expected values before changing the price
23
+ const expectedTableBeforeEditing = [
24
+ { Year: "2020", Make: "Porsche", Model: "Boxter", Price: "72000" },
25
+ { Year: "2020", Make: "Porsche", Model: "Boxter", Price: "99000" },
26
+ ];
27
+
28
+ // verify values before editing
29
+ cy.get(agGridSelector)
30
+ .getAgGridData()
31
+ .then((tableData) => {
32
+ cy.agGridValidateRowsSubset(tableData, expectedTableBeforeEditing);
33
+ });
34
+
35
+ // edit the porsche boxter from 72000 to 66000
36
+ cy.get(agGridSelector)
37
+ .getAgGridElements()
38
+ .then((tableElements) => {
39
+ const porscheRow = tableElements.find(
40
+ (row) => row.Price.innerText === "72000"
41
+ );
42
+ const priceCell = porscheRow.Price;
43
+ cy.wrap(priceCell).dblclick().type("66000{enter}");
44
+ });
45
+
46
+ // expected values after changing the price
47
+ const expectedTableAfterEditing = [
48
+ { Year: "2020", Make: "Porsche", Model: "Boxter", Price: "66000" },
49
+ { Year: "2020", Make: "Porsche", Model: "Boxter", Price: "99000" },
50
+ ];
51
+
52
+ // verify values before editing
53
+ cy.get(agGridSelector)
54
+ .getAgGridData()
55
+ .then((tableData) => {
56
+ cy.agGridValidateRowsSubset(tableData, expectedTableAfterEditing);
57
+ });
58
+ });
59
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cypress-ag-grid",
3
- "version": "1.5.0",
3
+ "version": "2.0.1",
4
4
  "description": "Cypress plugin to interact with ag grid",
5
5
  "main": "src/index.js",
6
6
  "repository": {
@@ -5,9 +5,9 @@ import { filterTab } from "./menuTab.enum";
5
5
  /**
6
6
  * Uses the attribute value's index and sorts the data accordingly.
7
7
  * For our purposes, we are getting the attribute with the items' indices and sorting accordingly.
8
- *
9
- * @param {*} index
10
- * @returns
8
+ *
9
+ * @param {*} index
10
+ * @returns
11
11
  */
12
12
  function sortElementsByAttributeValue(attribute) {
13
13
  return (a, b) => {
@@ -23,6 +23,19 @@ function sortElementsByAttributeValue(attribute) {
23
23
  * @param options Provide an array of columns you wish to exclude from the table retrieval.
24
24
  */
25
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) {
26
39
  const agGridColumnSelectors =
27
40
  ".ag-pinned-left-cols-container^.ag-center-cols-clipper^.ag-pinned-right-cols-container";
28
41
  if (agGridElement.get().length > 1)
@@ -33,45 +46,59 @@ export const getAgGridData = (agGridElement, options = {}) => {
33
46
  const tableElement = agGridElement.get()[0].querySelectorAll(".ag-root")[0];
34
47
  const agGridSelectors = agGridColumnSelectors.split("^");
35
48
  const headers = [
36
- ...tableElement.querySelectorAll('.ag-header-row-column [aria-colindex]')]
37
- .sort(sortElementsByAttributeValue('aria-colindex'))
49
+ ...tableElement.querySelectorAll(".ag-header-row-column [aria-colindex]"),
50
+ ]
51
+ .sort(sortElementsByAttributeValue("aria-colindex"))
38
52
  .map((headerElement) => {
39
53
  // Check if the elements returned are already .ag-header-cell-text elements
40
54
  // If not, query for that element and return the text content
41
- let headerCells = [...headerElement.querySelectorAll(".ag-header-cell-text")]
55
+ let headerCells = [
56
+ ...headerElement.querySelectorAll(".ag-header-cell-text"),
57
+ ];
42
58
  if (headerCells.length === 0) {
43
- return [headerElement].map((e) => e.textContent.trim())
59
+ return [headerElement].map((e) => e.textContent.trim());
44
60
  } else {
45
- return [...headerElement.querySelectorAll(".ag-header-cell-text")]
46
- .map((e) => e.textContent.trim())
61
+ return [...headerElement.querySelectorAll(".ag-header-cell-text")].map(
62
+ (e) => e.textContent.trim()
63
+ );
47
64
  }
48
- }).flat()
65
+ })
66
+ .flat();
49
67
 
50
68
  let allRows = [];
51
69
  let rows = [];
52
70
 
53
71
  agGridSelectors.forEach((selector) => {
54
- const _rows = [...tableElement.querySelectorAll(`${selector}:not(.ag-hidden) .ag-row`)]
72
+ const _rows = [
73
+ ...tableElement.querySelectorAll(`${selector}:not(.ag-hidden) .ag-row`),
74
+ ]
55
75
  // Sort rows by their row-index attribute value
56
76
  .sort(sortElementsByAttributeValue("row-index"))
57
77
  .map((row) => {
58
78
  // Sort row cells by their aria-colindex attribute value
59
79
  // First check if elements returned already contain the aria-colindex
60
80
  // If not, just query for the .ag-cell
61
- let rowCells = [...row.querySelectorAll(".ag-cell [aria-colindex]")]
81
+ let rowCells = [...row.querySelectorAll(".ag-cell [aria-colindex]")];
62
82
  if (rowCells.length === 0) {
63
- rowCells = [...row.querySelectorAll(".ag-cell")]
83
+ rowCells = [...row.querySelectorAll(".ag-cell")];
64
84
  }
65
- return rowCells.sort(sortElementsByAttributeValue("aria-colindex"))
66
- .map((e)=> e.textContent.trim())
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
+ });
67
94
  });
68
95
  allRows.push(_rows);
69
96
  });
70
97
 
71
98
  // Remove any empty arrays before merging
72
99
  allRows = allRows.filter(function (ele) {
73
- return ele.length
74
- })
100
+ return ele.length;
101
+ });
75
102
 
76
103
  if (!allRows.length) rows = [];
77
104
  else {
@@ -102,7 +129,7 @@ export const getAgGridData = (agGridElement, options = {}) => {
102
129
  return { ...acc, [headers[idx]]: curr };
103
130
  }, {})
104
131
  );
105
- };
132
+ }
106
133
 
107
134
  /**
108
135
  * Retrieve the ag grid column header element based on its column name value
@@ -209,6 +236,7 @@ function getFilterColumnButtonElement(
209
236
  const filterValue = options.searchCriteria.filterValue;
210
237
  const operator = options.searchCriteria.operator;
211
238
  const searchInputIndex = options.searchCriteria.searchInputIndex || 0;
239
+ const isMultiFilter = options.searchCriteria.isMultiFilter;
212
240
  const noMenuTabs = options.noMenuTabs;
213
241
 
214
242
  // Navigate to the filter tab
@@ -226,7 +254,7 @@ function getFilterColumnButtonElement(
226
254
  .contains(operator)
227
255
  .then(($ele) => {
228
256
  //Have to use the unwrapped element, since Cypress .click() event does not appropriately select the operator
229
- $ele.trigger('click');
257
+ $ele.trigger("click");
230
258
  });
231
259
  }
232
260
  // Input filter term and allow grid a moment to render the results
@@ -234,10 +262,32 @@ function getFilterColumnButtonElement(
234
262
  .find(".ag-popup-child")
235
263
  .find("input")
236
264
  .filter(":visible")
237
- .eq(searchInputIndex)
238
- .clear()
239
- .type(filterValue)
240
- .wait(500);
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
+ }
241
291
  }
242
292
 
243
293
  function applyColumnFilter(agGridElement, hasApplyButton, noMenuTabs) {
@@ -246,7 +296,6 @@ function applyColumnFilter(agGridElement, hasApplyButton, noMenuTabs) {
246
296
  .find(".ag-filter-apply-panel-button")
247
297
  .contains("Apply")
248
298
  .click();
249
-
250
299
  }
251
300
  if (!noMenuTabs) {
252
301
  getMenuTabElement(agGridElement, filterTab.filter).click();
@@ -279,7 +328,12 @@ function toggleColumnCheckboxFilter(
279
328
  });
280
329
  }
281
330
 
282
- function populateSearchCriteria(searchCriteria, hasApplyButton = false, noMenuTabs = false) {
331
+ function populateSearchCriteria(
332
+ searchCriteria,
333
+ hasApplyButton = false,
334
+ noMenuTabs = false,
335
+ selectAllLocaleText = 'Select All'
336
+ ) {
283
337
  const options = {};
284
338
  //@ts-ignore
285
339
  options.searchCriteria = {};
@@ -288,6 +342,10 @@ function populateSearchCriteria(searchCriteria, hasApplyButton = false, noMenuTa
288
342
  //@ts-ignore
289
343
  options.searchCriteria.filterValue = searchCriteria.filterValue;
290
344
  //@ts-ignore
345
+ options.searchCriteria.isMultiFilter = searchCriteria.isMultiFilter;
346
+ //@ts-ignore
347
+ options.selectAllLocaleText = selectAllLocaleText;
348
+ //@ts-ignore
291
349
  options.hasApplyButton = hasApplyButton;
292
350
  //@ts-ignore
293
351
  options.noMenuTabs = noMenuTabs;
@@ -312,7 +370,8 @@ export function filterBySearchTextColumnMenu(agGridElement, options) {
312
370
  const _options = populateSearchCriteria(
313
371
  _searchCriteria,
314
372
  options.hasApplyButton,
315
- options.noMenuTabs
373
+ options.noMenuTabs,
374
+ options.isMultiFilter
316
375
  );
317
376
  _filterBySearchTextColumnMenu(agGridElement, _options);
318
377
  });
@@ -337,15 +396,16 @@ function _filterBySearchTextColumnMenu(agGridElement, options) {
337
396
  /**
338
397
  * * Performs a filter operation on the specified column via the column's floating filter field using plain text search
339
398
  * @param agGridElement The get() selector for which ag grid table you wish to retrieve.
340
- * @param {{searchCriteria:[{columnName:string,filterValue:string,operator?:string}], hasApplyButton?:boolean}} options JSON with search properties
399
+ * @param {{searchCriteria:[{columnName:string,filterValue:string,operator?:string}], hasApplyButton?:boolean, noMenuTab?:boolean, selectAllLocaleText:string}} options JSON with search properties
341
400
  * @param options.searchCriteria JSON with search properties and options
342
401
  * @param options.searchCriteria.columnName name of the column to filter
343
402
  * @param options.searchCriteria.filterValue value to input into the filter textbox
344
403
  * @param options.searchCriteria.searchInputIndex [Optional] Uses 0 by default. Index of which filter box to use in event of having multiple search conditionals
345
404
  * @param options.searchCriteria.operator [Optional] Use if using a search operator (i.e. Less Than, Equals, etc...use filterOperator.enum values).
346
405
  * @param options.hasApplyButton [Optional] True if "Apply" button is used, false if filters by text input automatically.
347
- * @param options.noMenuTabs [Optional] True if you use for example the community edition of ag-grid, which has no menu tabs
348
- */
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
+ */
349
409
  export function filterBySearchTextColumnFloatingFilter(agGridElement, options) {
350
410
  // Check if there are multiple search criteria provided by attempting to access the columnName
351
411
  if (!options.searchCriteria.columnName) {
@@ -373,7 +433,11 @@ function _filterBySearchTextColumnFloatingFilter(agGridElement, options) {
373
433
  agGridElement,
374
434
  options
375
435
  );
376
- applyColumnFilter(agGridElement, options.hasApplyButton, options.noMenuTabs);
436
+ applyColumnFilter(
437
+ agGridElement,
438
+ options.hasApplyButton,
439
+ options.noMenuTabs
440
+ );
377
441
  });
378
442
  }
379
443
 
@@ -409,7 +473,7 @@ function _filterByCheckboxColumnMenu(agGridElement, options) {
409
473
  agGridElement,
410
474
  options.searchCriteria.columnName
411
475
  ).click();
412
- const selectAllText = options.selectAllLocaleText || 'Select All'
476
+ const selectAllText = options.selectAllLocaleText || "Select All";
413
477
  toggleColumnCheckboxFilter(
414
478
  agGridElement,
415
479
  selectAllText,
@@ -422,7 +486,11 @@ function _filterByCheckboxColumnMenu(agGridElement, options) {
422
486
  true,
423
487
  options.noMenuTabs
424
488
  );
425
- applyColumnFilter(agGridElement, options.hasApplyButton, options.noMenuTabs);
489
+ applyColumnFilter(
490
+ agGridElement,
491
+ options.hasApplyButton,
492
+ options.noMenuTabs
493
+ );
426
494
  });
427
495
  }
428
496
 
@@ -430,7 +498,11 @@ function _filterByCheckboxColumnMenu(agGridElement, options) {
430
498
  * Will perform a filter for all search criteria provided, then selects all found entries in the grid
431
499
  * @param searchCriteria a "\^" delimited string of all columns and searchCriteria to search for in the grid (i.e. "Name=John Smith^Rate Plan=Standard"
432
500
  */
433
- export function filterGridEntriesBySearchText(agGridElement, searchCriteria, isFloatingFilter = false) {
501
+ export function filterGridEntriesBySearchText(
502
+ agGridElement,
503
+ searchCriteria,
504
+ isFloatingFilter = false
505
+ ) {
434
506
  if (isFloatingFilter) {
435
507
  filterBySearchTextColumnFloatingFilter(agGridElement, searchCriteria);
436
508
  } else {
@@ -30,7 +30,7 @@ export function validateTablePages(agGridElement,expectedPaginatedTableData, onl
30
30
  .then((table) => {
31
31
  const actualPage = JSON.parse(JSON.stringify(table));
32
32
  validateTableExactOrder(agGridElement, actualPage, expectedPage, true);
33
- cy.get(".ag-icon-next").click();
33
+ cy.get(agGridElement).find(".ag-icon-next").click();
34
34
  iterator++;
35
35
  });
36
36
  });
package/src/index.d.ts CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  declare namespace Cypress {
4
4
  interface Chainable<Subject> {
5
- getAgGridData<E extends Node = HTMLElement>(options?: {}): Chainable<JQuery<E>>;
5
+ getAgGridData(options?: {}): Chainable<Array<Record<string, string>>>;
6
+ getAgGridElements<E extends Node = HTMLElement>(options?: {}): Chainable<JQuery<E>>;
6
7
  /**
7
8
  * * Performs sorting operation on the specified column
8
9
  * @param {*} subject The get() selector for which ag grid table you wish to retrieve.
@@ -43,6 +44,7 @@ declare namespace Cypress {
43
44
  * @param options.searchCriteria.columnName name of the column to filter
44
45
  * @param options.searchCriteria.filterValue value to input into the filter textbox
45
46
  * @param options.searchCriteria.operator [Optional] Use if using a search operator (i.e. Less Than, Equals, etc...use filterOperator.enum values).
47
+ * @param options.searchCriteria.isMultiFilter [Optional] Use if floating filter is multiselect checkboxes vs free form input.
46
48
  * @param options.hasApplyButton [Optional] True if "Apply" button is used, false if filters by text input automatically.
47
49
  */
48
50
  agGridColumnFilterTextFloating<E extends Node = HTMLElement>(options: {}): Chainable<JQuery<E>>;
package/src/index.js CHANGED
@@ -1,18 +1,19 @@
1
1
  /// <reference types="cypress" />
2
2
 
3
- import {getAgGridData, sortColumnBy} from "./agGrid/agGridInteractions"
3
+ import {getAgGridData, getAgGridElements, sortColumnBy} from "./agGrid/agGridInteractions"
4
4
  import {validateTablePages, validateTableExactOrder, validateEmptyTable, validateTableRowSubset} from "./agGrid/agGridValidations"
5
5
  import {filterByCheckboxColumnMenu, filterBySearchTextColumnFloatingFilter, filterBySearchTextColumnMenu, toggleColumnFromSideBar} from "./agGrid/agGridInteractions";
6
6
 
7
7
  Cypress.Commands.add('getAgGridData', { prevSubject: true }, getAgGridData);
8
+ Cypress.Commands.add('getAgGridElements', {prevSubject: true}, getAgGridElements);
8
9
  Cypress.Commands.add('agGridSortColumn', {prevSubject: true}, sortColumnBy);
9
10
  Cypress.Commands.add('agGridColumnFilterCheckboxMenu', {prevSubject: true}, filterByCheckboxColumnMenu)
10
11
  Cypress.Commands.add('agGridColumnFilterTextMenu', {prevSubject: true}, filterBySearchTextColumnMenu)
11
12
  Cypress.Commands.add('agGridColumnFilterTextFloating', {prevSubject: true}, filterBySearchTextColumnFloatingFilter)
12
13
 
13
- Cypress.Commands.add('agGridValidatePaginatedTable', {prevSubject: true}, validateTablePages)
14
- Cypress.Commands.add('agGridValidateRowsExactOrder', {prevSubject: true}, validateTableExactOrder)
15
- Cypress.Commands.add('agGridValidateRowsSubset', {prevSubject: true}, validateTableRowSubset)
16
- Cypress.Commands.add('agGridValidateEmptyTable', {prevSubject: true}, validateEmptyTable)
14
+ Cypress.Commands.add('agGridValidatePaginatedTable', {prevSubject: 'optional'}, validateTablePages)
15
+ Cypress.Commands.add('agGridValidateRowsExactOrder', {prevSubject: 'optional'}, validateTableExactOrder)
16
+ Cypress.Commands.add('agGridValidateRowsSubset', {prevSubject: 'optional'}, validateTableRowSubset)
17
+ Cypress.Commands.add('agGridValidateEmptyTable', {prevSubject: 'optional'}, validateEmptyTable)
17
18
 
18
19
  Cypress.Commands.add('agGridToggleColumnsSideBar', {prevSubject: true}, toggleColumnFromSideBar)