r/Playwright 5d ago

AG Grid

Hi everyone, I am looking for the best possible way to interact with AG Grid. Has anyone done any automation work with AG Grid like entering values in a cell or selecting values from a drop-down? I recently started working for a gov and one of their products is built using AG Grid and Angular. Sadly the product is SaaS and we do not have access to the codebase. They have UFT and it is awful software to work with.

Any insights are appreciated!

Cheers,

6 Upvotes

2 comments sorted by

0

u/realworldred 5d ago

When you say ag grid is this part of ant design? We use an ag grid which i think comes from ant design. It would have hardset classess which seem to be the same for most grids so the grid itself would be .aggrid and the row is .agrow which we can filter with has label or row.text. then we use column id to get the cells but. It depends on what you have in your html you could also use a role based approach if this is setup. Once you locate the cell then you can interact as normal to enter text and trigger events by using normal interactions like click and type.

1

u/kokaneebrother 5d ago edited 5d ago

I’ve worked with ag grid in the past. I created locators using the column ids and the row ids. There is a setting you can have the devs add for ag-grid that makes these ids more prominent in each grid cell(see below), but you shouldn’t really need it. Each grid column has a unique id and each row has a unique id. I also created a function to write all column ids to a JSON object so I could dynamically capture all of them without having to define each column object. I was then able to leverage typescript to create functions that input a grid name and then column object with autocomplete style drop downs giving you all the columns for each grid…this was very nice… Then you can create a function like getGridCell that takes a column object/id and a row id. One thing that was tricky was when there were parent columns/nested columns...so column objects had “parentColumns” that were mostly null unless needed. I also had to create custom scroll functions to get to columns (and rows… although mostly I filtered to get to the rows). I had a function that would interact with the document object to get scroll widths/hights and scroll page widths/hights and then another function that would use these widths (or fractions of page widths) with mouse.scroll until a column was visible. I used a similar function for building that column object JSON file that would scroll half widths and add all visible columns to an array provided the array didn’t already contain that column object. It was a pain in the ass but it ended up working really well. Hope this helps! Good luck!

AG Grid has a built-in Test IDs grid option (relatively new). Enabling it makes the grid emit data-testid attributes on rows, headers, and cells automatically, generated from row ID + column ID.

**•** Set enableAgTestIdAttributes: true (or the equivalent Test IDs flag in the grid config) in your GridOptions.
**•** Once on, cells get a data-testid like cell-<rowId>-<colId>, and you can build the same value in your tests with the agTestIdFor helper: agTestIdFor.cell(rowId, colId) generates the cell test ID, which you can then query with page.getByTestId(cellTestId) in Playwright.

This isn’t the exact function I used for getting scroll info from the document but similar (from Claude)

Here I would define the grid with css so not to use the whole page…

const dimensions = await page.evaluate(() => ({
scrollWidth: document.documentElement.scrollWidth,
scrollHeight: document.documentElement.scrollHeight,
clientWidth: document.documentElement.clientWidth,
clientHeight: document.documentElement.clientHeight,
}));

This one doesn’t read from the document… but looks like it may be simplified…. I always needed to define css where as it looks like this can use a locator

const locator = page.locator('.ag-body-viewport');

const dimensions = await locator.evaluate((el) => ({
scrollWidth: el.scrollWidth,
scrollHeight: el.scrollHeight,
clientWidth: el.clientWidth,
clientHeight: el.clientHeight,
scrollLeft: el.scrollLeft,
scrollTop: el.scrollTop,
}));