How do I get elements in a table with Playwright?

I'm trying to get hold of two users in a hideous structure with tables within tables and I'm just not getting it to work... The structure is something like this (inner most table):

<table>
  <tbody>
    <tr>
    <tr>
    <tr>
    <tr>
      <td>
      <td>
      <td>
        <input lotsofuselesstext value="Steve">
        <img>
      </td>
      <td>
    </tr>
    <tr>
    <tr>
    <tr>
      <td>
      <td>
      <td>
        <input lotsofuselesstext value="Mark">
        <img>
      </td>
      <td>
    </tr>
  </tbody>
</table>

I'm trying to get hold of Steve and Mark. I can get an xpath that will give me the two input tags, but no matter what I can't get the value fields. I'm using Playwright with C#...

I've tried so many variants that I can't keep track of them, but some that I still have in my code are:

var Planners = await Page.QuerySelectorAllAsync("//*[@summary=\"Planners\"]/tbody/tr/td[3]/input");
var values = await Task.WhenAll(Planners.Select(async element => await element.GetAttributeAsync("value")));

var Planners= await Page.Locator("//*[@summary=\"Planners\"]/tbody/tr/td[3]/input").ElementHandlesAsync();

var Planners = await Page.Locator("//*[@summary=\"Planners\"]/tbody/tr/td[3]/input").AllTextContentsAsync();

And, I'm new to this, as if you couldn't already tell...

Upvotes: 6

Views: 33160

Answers (4)

Vishal Aggarwal
Vishal Aggarwal

Reputation: 4225

The below code solutions are in JavaScript

How to verify a certain text from a specific column from a Table?

await expect(page.locator('.my-table-row').nth(2)).toContainText('Steve');

To get all values from an specific column in an array:(JS)

 const textsFromNthColumn = [];
 const rows = await page.locator('.table-tbody tr').all();

 for (const row of rows) {
  const cellText = await row.locator('td').nth(n).innerText();
  textsFromNthColumn.push(cellText);
 }

console.log(textsFromNthColumn);

Reference: How to get text from a specific column from a table in Playwright

https://github.com/microsoft/playwright/issues/9747

Upvotes: 6

Stefan Cronert
Stefan Cronert

Reputation: 31

I would do something like this

IElementHandle? table = await Page.WaitForSelectorAsync("//*[@summary=\"Planners\"]");
IElementHandle? tableBody = await table.WaitForSelectorAsync("tbody");
var rows = await table?.QuerySelectorAllAsync("tr");
foreach(var row in rows)
{
    var cells = await row.QuerySelectorAllAsync("td");
    var input = await cells[2].WaitForSelectorAsync("input");
    var value = await input.GetAttributeAsync("value");
    if(value == "Steve" || value == "Mark")
        //Do something
}

Upvotes: 1

ReigniteMars
ReigniteMars

Reputation: 11

TLDR:

await Page.GetByRole(AriaRole.Cell, new PageGetByRoleOptions { Name = "Steve" }).GetByRole(AriaRole.Textbox).InputValueAsync();
await Page.GetByRole(AriaRole.Cell, new PageGetByRoleOptions { Name = "Mark" }).GetByRole(AriaRole.Textbox).InputValueAsync();

Here's a breakdown of the code.

  • Page.GetByRole: This method is used to locate elements based on their ARIA role. In this case, you're looking for cells (AriaRole.Cell) in a table.

  • new PageGetByRoleOptions { Name = "Steve" }: This part is creating a new instance of a search criterion, specifically looking for a cell that has the accessible name "Steve".

  • GetByRole(AriaRole.Textbox): Once the specific cell is found, this method is called again to find the textbox within that cell.

  • InputValueAsync(): This method is called to input a value into the found textbox asynchronously.

Besides write these element locators yourself, codegen command is also a recommended way to auto generate testing scripts with a relatively high accuracy.

Upvotes: 1

I rewrote the xpath and managed to eventually get the names. This is what I ended up with (but I still don't understand why the use of the input tag didn't work):

        List<string> textsFromNthColumn = new List<string>();
        var rowCount = await Page.Locator("//*[@summary=\"Planners\"]/tbody/tr//td/*[contains(@id,'tdrow_[C:1]_txt-tb')]").CountAsync();

        for (int i = 0; i < rowCount; i++)
        {
            textsFromNthColumn.Add(await Page.Locator("//*[@summary=\"Planners\"]/tbody/tr//td/*[contains(@id,'tdrow_[C:1]_txt-tb')]").Nth(i).GetAttributeAsync("value"));
        }

Upvotes: 0

Related Questions