playwright-ag-grid 1.0.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # playwright-ag-grid
2
+
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 2a7e5d7: Move to monorepo structure to support more node-based testing tools for ag grid interactions and validations
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [2a7e5d7]
12
+ - @kpmck/ag-grid-core@1.0.0
package/README.md ADDED
@@ -0,0 +1,387 @@
1
+ # playwright-ag-grid
2
+
3
+ Playwright helpers for interacting with and validating AG Grid.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Installation](#installation)
8
+ - [Usage](#usage)
9
+ - [Create the Grid Helper](#create-the-grid-helper)
10
+ - [Getting Data From the Grid](#getting-data-from-the-grid)
11
+ - [Getting Select Row Data](#getting-select-row-data)
12
+ - [Editing Grid Cells](#editing-grid-cells)
13
+ - [Sorting Columns](#sorting-columns)
14
+ - [Pinning Columns](#pinning-columns)
15
+ - [Filter Options](#filter-options)
16
+ - [Filter by Text - Column Menu](#filter-by-text---column-menu)
17
+ - [Filter by Text - Floating Filter](#filter-by-text---floating-filter)
18
+ - [Filter by Checkbox - Column Menu](#filter-by-checkbox---column-menu)
19
+ - [Filtering - Localization and Internationalization](#filtering---localization-and-internationalization)
20
+ - [Add or Remove Columns](#add-or-remove-columns)
21
+ - [Validation Examples](#validation-examples)
22
+ - [Validate Paginated Table](#validate-paginated-table)
23
+ - [Validate Table in the Exact Order](#validate-table-in-the-exact-order)
24
+ - [Validate Subset of Table Data](#validate-subset-of-table-data)
25
+ - [Validate Empty Grid](#validate-empty-grid)
26
+ - [Limitations](#limitations)
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ npm install playwright-ag-grid --save-dev
32
+ ```
33
+
34
+ Then import the helper in your Playwright tests:
35
+
36
+ ```javascript
37
+ import { createAgGrid, filterOperator, sort } from "playwright-ag-grid";
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ ### Create the Grid Helper
43
+
44
+ Create a helper instance from the top-level AG Grid locator, including headers and controls.
45
+
46
+ ```javascript
47
+ import { createAgGrid } from "playwright-ag-grid";
48
+
49
+ const grid = createAgGrid(page.locator("#myGrid"));
50
+ ```
51
+
52
+ ### Getting Data From the Grid
53
+
54
+ Use `getData()` to read the displayed AG Grid rows as structured objects.
55
+
56
+ ```javascript
57
+ const grid = createAgGrid(page.locator("#myGrid"));
58
+ const tableData = await grid.getData();
59
+ ```
60
+
61
+ The returned value looks like:
62
+
63
+ ```json
64
+ [
65
+ { "Year": "2020", "Make": "Toyota", "Model": "Celica" },
66
+ { "Year": "2020", "Make": "Ford", "Model": "Mondeo" },
67
+ { "Year": "2020", "Make": "Porsche", "Model": "Boxter" },
68
+ { "Year": "2020", "Make": "BMW", "Model": "3-series" },
69
+ { "Year": "2020", "Make": "Mercedes", "Model": "GLC300" }
70
+ ]
71
+ ```
72
+
73
+ ### Getting Select Row Data
74
+
75
+ To only return certain columns, pass `onlyColumns`:
76
+
77
+ ```javascript
78
+ const grid = createAgGrid(page.locator("#myGrid"));
79
+ const tableData = await grid.getData({ onlyColumns: ["Year", "Make"] });
80
+ ```
81
+
82
+ You can also request the raw header/row arrays instead of mapped objects:
83
+
84
+ ```javascript
85
+ const grid = createAgGrid(page.locator("#myGrid"));
86
+ const tableData = await grid.getData({ valuesArray: true });
87
+ ```
88
+
89
+ ### Editing Grid Cells
90
+
91
+ Playwright does not expose AG Grid cells as Cypress-style command subjects, so the package provides `getCellLocator()` for targeted cell interaction.
92
+
93
+ ```javascript
94
+ const grid = createAgGrid(page.locator("#myGrid2"));
95
+
96
+ await grid.filterTextFloating({
97
+ searchCriteria: {
98
+ columnName: "Make",
99
+ filterValue: "Porsche",
100
+ operator: filterOperator.equals,
101
+ },
102
+ hasApplyButton: true,
103
+ });
104
+
105
+ const priceCell = await grid.getCellLocator(
106
+ { Make: "Porsche", Price: "72000" },
107
+ "Price"
108
+ );
109
+
110
+ await priceCell.dblclick();
111
+ await priceCell.locator("input").fill("66000");
112
+ await priceCell.locator("input").press("Enter");
113
+ ```
114
+
115
+ ### Sorting Columns
116
+
117
+ Use `sortColumn(columnName, sortDirection)`:
118
+
119
+ ```javascript
120
+ const grid = createAgGrid(page.locator("#myGrid"));
121
+ await grid.sortColumn("Model", "descending");
122
+ ```
123
+
124
+ You can also use the exported enum values:
125
+
126
+ ```javascript
127
+ await grid.sortColumn("Model", sort.ascending);
128
+ ```
129
+
130
+ ### Pinning Columns
131
+
132
+ Use `pinColumn(columnName, pin)` where `pin` is `"left"`, `"right"`, or `null`.
133
+
134
+ ```javascript
135
+ const grid = createAgGrid(page.locator("#myGrid"));
136
+
137
+ await grid.pinColumn("Model", "left");
138
+ await grid.pinColumn("Model", "right");
139
+ await grid.pinColumn("Model", null);
140
+ ```
141
+
142
+ ### Filter Options
143
+
144
+ The filtering commands accept an options object shaped like:
145
+
146
+ ```javascript
147
+ {
148
+ searchCriteria: {
149
+ columnName: string;
150
+ filterValue: string;
151
+ operator?: string;
152
+ searchInputIndex?: number;
153
+ operatorIndex?: number;
154
+ isMultiFilter?: boolean;
155
+ } | Array<{
156
+ columnName: string;
157
+ filterValue: string;
158
+ operator?: string;
159
+ searchInputIndex?: number;
160
+ operatorIndex?: number;
161
+ isMultiFilter?: boolean;
162
+ }>;
163
+ hasApplyButton?: boolean;
164
+ noMenuTabs?: boolean;
165
+ selectAllLocaleText?: string;
166
+ }
167
+ ```
168
+
169
+ Option notes:
170
+
171
+ - `searchCriteria.columnName`: column to filter.
172
+ - `searchCriteria.filterValue`: value to type or select.
173
+ - `searchCriteria.operator`: optional AG Grid operator text such as `Equals`, `Contains`, or `Between`.
174
+ - `searchCriteria.searchInputIndex`: optional input index when multiple visible inputs exist.
175
+ - `searchCriteria.operatorIndex`: optional operator picker index when multiple visible operators exist.
176
+ - `searchCriteria.isMultiFilter`: optional flag for floating filters using checkbox values rather than free-form text.
177
+ - `hasApplyButton`: use `true` when the filter UI has an explicit Apply button.
178
+ - `noMenuTabs`: use `true` for grids that render a menu list instead of filter tabs.
179
+ - `selectAllLocaleText`: localized text for the checkbox filter's Select All entry.
180
+
181
+ ### Filter by Text - Column Menu
182
+
183
+ Use `filterTextMenu(options)` to filter via the column menu:
184
+
185
+ ```javascript
186
+ const grid = createAgGrid(page.locator("#myGrid"));
187
+
188
+ await grid.filterTextMenu({
189
+ searchCriteria: [
190
+ {
191
+ columnName: "Model",
192
+ filterValue: "GLC300",
193
+ operator: filterOperator.equals,
194
+ },
195
+ {
196
+ columnName: "Make",
197
+ filterValue: "Mercedes",
198
+ operator: filterOperator.equals,
199
+ },
200
+ ],
201
+ hasApplyButton: true,
202
+ });
203
+ ```
204
+
205
+ ### Filter by Text - Floating Filter
206
+
207
+ Use `filterTextFloating(options)` to filter via a column's floating filter:
208
+
209
+ ```javascript
210
+ const grid = createAgGrid(page.locator("#myGrid"));
211
+
212
+ await grid.filterTextFloating({
213
+ searchCriteria: {
214
+ columnName: "Make",
215
+ filterValue: "Ford",
216
+ },
217
+ hasApplyButton: true,
218
+ });
219
+ ```
220
+
221
+ For multiple conditions in the same floating filter:
222
+
223
+ ```javascript
224
+ await grid.filterTextFloating({
225
+ searchCriteria: {
226
+ columnName: "Make",
227
+ filterValue: "B",
228
+ searchInputIndex: 0,
229
+ },
230
+ hasApplyButton: true,
231
+ });
232
+
233
+ await grid.filterTextFloating({
234
+ searchCriteria: {
235
+ columnName: "Make",
236
+ filterValue: "MW",
237
+ searchInputIndex: 1,
238
+ },
239
+ hasApplyButton: true,
240
+ });
241
+ ```
242
+
243
+ For `Between`, pass two entries for the same column:
244
+
245
+ ```javascript
246
+ await grid.filterTextFloating({
247
+ searchCriteria: [
248
+ {
249
+ columnName: "Year",
250
+ filterValue: "1990",
251
+ operator: filterOperator.inRange,
252
+ },
253
+ {
254
+ columnName: "Year",
255
+ filterValue: "2011",
256
+ operator: filterOperator.inRange,
257
+ },
258
+ ],
259
+ hasApplyButton: true,
260
+ });
261
+ ```
262
+
263
+ ### Filter by Checkbox - Column Menu
264
+
265
+ Use `filterCheckboxMenu(options)` to filter by checkbox values from the column menu:
266
+
267
+ ```javascript
268
+ const grid = createAgGrid(page.locator("#myGrid"));
269
+
270
+ await grid.filterCheckboxMenu({
271
+ searchCriteria: {
272
+ columnName: "Model",
273
+ filterValue: "2002",
274
+ },
275
+ hasApplyButton: true,
276
+ });
277
+ ```
278
+
279
+ Multiple checkbox values:
280
+
281
+ ```javascript
282
+ await grid.filterCheckboxMenu({
283
+ searchCriteria: [
284
+ { columnName: "Model", filterValue: "2002" },
285
+ { columnName: "Model", filterValue: "3-series" },
286
+ ],
287
+ hasApplyButton: true,
288
+ });
289
+ ```
290
+
291
+ ### Filtering - Localization and Internationalization
292
+
293
+ When filtering by checkbox, the helper first deselects the Select All entry so only the requested values remain selected. For localized grids, pass the localized Select All text:
294
+
295
+ ```javascript
296
+ await grid.filterCheckboxMenu({
297
+ searchCriteria: {
298
+ columnName: "Model",
299
+ filterValue: "2002",
300
+ },
301
+ selectAllLocaleText: "Tout Sélectionner",
302
+ hasApplyButton: true,
303
+ });
304
+ ```
305
+
306
+ ### Add or Remove Columns
307
+
308
+ Use `toggleColumnFromSideBar(columnName, doRemove)` to toggle columns from the sidebar:
309
+
310
+ ```javascript
311
+ const grid = createAgGrid(page.locator("#myGrid"));
312
+
313
+ await grid.toggleColumnFromSideBar("Year", true);
314
+ await grid.toggleColumnFromSideBar("Year", false);
315
+ ```
316
+
317
+ ## Validation Examples
318
+
319
+ Unlike the Cypress package, the Playwright package does not currently register assertion helpers. The intended pattern is to use `await grid.getData()` together with Playwright's `expect`.
320
+
321
+ ### Validate Paginated Table
322
+
323
+ ```javascript
324
+ import { expect } from "@playwright/test";
325
+ import { createAgGrid } from "playwright-ag-grid";
326
+
327
+ const expectedPaginatedTableData = [
328
+ [
329
+ { Year: "2020", Make: "Toyota", Model: "Celica" },
330
+ { Year: "2020", Make: "Ford", Model: "Mondeo" },
331
+ ],
332
+ [
333
+ { Year: "2020", Make: "Honda", Model: "Civic" },
334
+ { Year: "2020", Make: "Honda", Model: "Accord" },
335
+ ],
336
+ ];
337
+
338
+ const grid = createAgGrid(page.locator("#myGrid"));
339
+
340
+ for (const expectedPage of expectedPaginatedTableData) {
341
+ await expect(await grid.getData({ onlyColumns: ["Year", "Make", "Model"] }))
342
+ .toEqual(expectedPage);
343
+ await page.locator("#myGrid .ag-icon-next").click();
344
+ }
345
+ ```
346
+
347
+ ### Validate Table in the Exact Order
348
+
349
+ ```javascript
350
+ import { expect } from "@playwright/test";
351
+
352
+ const grid = createAgGrid(page.locator("#myGrid"));
353
+ const actualTableData = await grid.getData();
354
+
355
+ await expect(actualTableData).toEqual(expectedTableData);
356
+ ```
357
+
358
+ ### Validate Subset of Table Data
359
+
360
+ ```javascript
361
+ import { expect } from "@playwright/test";
362
+
363
+ const grid = createAgGrid(page.locator("#myGrid"));
364
+ const actualTableData = await grid.getData({ onlyColumns: ["Year", "Make", "Model"] });
365
+
366
+ for (const expectedRow of expectedTableData) {
367
+ expect(actualTableData).toContainEqual(expectedRow);
368
+ }
369
+ ```
370
+
371
+ ### Validate Empty Grid
372
+
373
+ ```javascript
374
+ import { expect } from "@playwright/test";
375
+
376
+ const grid = createAgGrid(page.locator("#myGrid"));
377
+ const actualTableData = await grid.getData();
378
+
379
+ await expect(actualTableData).toEqual([]);
380
+ ```
381
+
382
+ ## Limitations
383
+
384
+ - Validation helpers are not yet packaged as Playwright-specific assertion methods; use Playwright `expect` with `getData()`.
385
+ - `getCellLocator()` is the supported element-interaction path; there is not currently a `getAgGridElements()`-style API returning live DOM element maps.
386
+ - Unlimited scrolling grids are not fully supported when data is outside the rendered DOM.
387
+ - Data outside the current rendered viewport is not available until AG Grid renders it into the DOM.
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "playwright-ag-grid",
3
+ "version": "1.0.0",
4
+ "description": "Playwright helpers for interacting with AG Grid",
5
+ "type": "module",
6
+ "main": "src/index.js",
7
+ "types": "src/index.d.ts",
8
+ "exports": {
9
+ ".": "./src/index.js"
10
+ },
11
+ "scripts": {
12
+ "test": "npm run test:all",
13
+ "test:all": "playwright test",
14
+ "test:v33": "playwright test tests/ag-grid-data.v33.spec.js tests/ag-grid-elements.v33.spec.js",
15
+ "test:v34": "playwright test tests/ag-grid-data.v34.spec.js tests/ag-grid-elements.v34.spec.js",
16
+ "test:v35": "playwright test tests/ag-grid-data.v35.spec.js tests/ag-grid-elements.v35.spec.js tests/ag-grid-animation-wait.v35.spec.js",
17
+ "test:watch": "playwright test --ui"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/kpmck/cypress-ag-grid.git"
25
+ },
26
+ "keywords": [
27
+ "ag-grid",
28
+ "aggrid",
29
+ "playwright",
30
+ "testing",
31
+ "e2e"
32
+ ],
33
+ "author": "Kerry McKeever <kerry@kerrymckeever.com>",
34
+ "license": "MIT",
35
+ "dependencies": {
36
+ "@kpmck/ag-grid-core": "1.0.0"
37
+ },
38
+ "devDependencies": {
39
+ "@playwright/test": "^1.52.0"
40
+ }
41
+ }
@@ -0,0 +1,21 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { defineConfig } from "@playwright/test";
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+
8
+ export default defineConfig({
9
+ testDir: path.join(__dirname, "tests"),
10
+ timeout: 30000,
11
+ use: {
12
+ baseURL: "http://127.0.0.1:4173",
13
+ headless: true,
14
+ },
15
+ webServer: {
16
+ command: "node ./tests/server.mjs",
17
+ cwd: __dirname,
18
+ port: 4173,
19
+ reuseExistingServer: true,
20
+ },
21
+ });
package/src/index.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ export declare const filterOperator: Record<string, string>;
2
+ export declare const sort: Record<string, string>;
3
+
4
+ export interface SearchCriteria {
5
+ columnName: string;
6
+ filterValue: string;
7
+ operator?: string;
8
+ searchInputIndex?: number;
9
+ operatorIndex?: number;
10
+ isMultiFilter?: boolean;
11
+ }
12
+
13
+ export interface FilterOptions {
14
+ searchCriteria: SearchCriteria | SearchCriteria[];
15
+ hasApplyButton?: boolean;
16
+ noMenuTabs?: boolean;
17
+ selectAllLocaleText?: string;
18
+ }
19
+
20
+ export declare class PlaywrightAgGrid {
21
+ constructor(rootLocator: any);
22
+ waitForAnimation(options?: object): Promise<void>;
23
+ getData(options?: object): Promise<any>;
24
+ sortColumn(columnName: string, sortDirection: string): Promise<void>;
25
+ pinColumn(columnName: string, pin?: "left" | "right" | null): Promise<void>;
26
+ filterTextMenu(options: FilterOptions): Promise<void>;
27
+ filterTextFloating(options: FilterOptions): Promise<void>;
28
+ filterCheckboxMenu(options: FilterOptions): Promise<void>;
29
+ toggleColumnFromSideBar(columnName: string, doRemove: boolean): Promise<void>;
30
+ getCellLocator(rowMatcher: Record<string, string>, columnName: string): Promise<any>;
31
+ }
32
+
33
+ export declare function createAgGrid(rootLocator: any): PlaywrightAgGrid;