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 +71 -6
- package/app/{grid.js → grid-basic.js} +3 -3
- package/app/grid-grouped.js +71 -0
- package/app/index.html +4 -2
- package/cypress/e2e/{ag-grid.cy.js → ag-grid-data.cy.js} +37 -17
- package/cypress/e2e/ag-grid-elements.cy.js +59 -0
- package/package.json +1 -1
- package/src/agGrid/agGridInteractions.js +105 -33
- package/src/agGrid/agGridValidations.js +1 -1
- package/src/index.d.ts +3 -1
- package/src/index.js +6 -5
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.
|
|
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.
|
|
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.
|
|
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 & 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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
@@ -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(
|
|
37
|
-
|
|
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 = [
|
|
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
|
-
|
|
61
|
+
return [...headerElement.querySelectorAll(".ag-header-cell-text")].map(
|
|
62
|
+
(e) => e.textContent.trim()
|
|
63
|
+
);
|
|
47
64
|
}
|
|
48
|
-
})
|
|
65
|
+
})
|
|
66
|
+
.flat();
|
|
49
67
|
|
|
50
68
|
let allRows = [];
|
|
51
69
|
let rows = [];
|
|
52
70
|
|
|
53
71
|
agGridSelectors.forEach((selector) => {
|
|
54
|
-
const _rows = [
|
|
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
|
|
66
|
-
|
|
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(
|
|
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
|
-
.
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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(
|
|
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(
|
|
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 ||
|
|
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(
|
|
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(
|
|
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
|
|
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:
|
|
14
|
-
Cypress.Commands.add('agGridValidateRowsExactOrder', {prevSubject:
|
|
15
|
-
Cypress.Commands.add('agGridValidateRowsSubset', {prevSubject:
|
|
16
|
-
Cypress.Commands.add('agGridValidateEmptyTable', {prevSubject:
|
|
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)
|