TESTEROPS

A pragmatic approach to QA and OPS

Playwright – Table Handling – 1

HTML tables are one of the most basic and most used HTML format of displaying multiple values of data.

HTML tables are created using the <table> tag along with several other tags including:

  • <tr>: Stands for “table row”. This tag is used to define a row in the table. Each row is filled with data using <td> or <th> tags.
  • <td>: Stands for “table data”. This tag is used to define a cell in the table that contains data.
  • <th>: Stands for “table header”. This tag is used to define a cell in the table that contains header information. Text within <th> is generally bold and centered.
  • <thead>: Used to group the header content in an HTML table.
  • <tbody>: Used to group the body content in an HTML table, and is used in conjunction with <thead> and <tfoot> elements.
  • <tfoot>: Used to group the footer content in an HTML table.

Here is a simple example of how a table is created

<table>
  <thead>
    <tr>
      <th>Firstname</th>
      <th>Lastname</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>John</td>
      <td>Doe</td>
    </tr>
    <tr>
      <td>Jane</td>
      <td>Doe</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="2">This is the table footer</td>
    </tr>
  </tfoot>
</table>

Handling Tables In Automation

Most of us, in one time or other, would have faced this challenge, where we have to automate data in a table. May be finding some value or asserting that some value is present in the tables. We have done that in Selenium using the xpaths or the cssSelector – the former in most cases.

While doing so, some common scenarios that may arise are

  • Read the data from the table.
  • Validate the number of rows or columns in the table.
  • Interact with some elements in the table.
  • Filter the data from the table and assert something.

and so on. The scenarios are endless and may depend a lot on what you want to achieve in your suite, or as per your requirement.

Handling Table In Playwright

Now that we’ve understood what tables are and what scenarios we may encounter. Let’s try to see and automate some of these scenarios using Playwright.

Now I’m not going into this discussion of what Playwright is and what are the capabilities of Playwright are, I’m assuming that you’ve had certain bit of understanding of the working of Playwright and how it can be set up.

If you’re looking for an awesome series of videos about Playwright, I’d suggest you to go over to Youtube and find tutorials by LetCode – by Koushik . This channel has videos for both Java and TS flavors of Playwright.

Scenarios For Automation

For the sake of this tutorial, we’ll try to automate certain scenarios

  • Get the total number of rows from a table.
  • Get the total number of columns for all rows.
  • Get all data from a row from table.
  • Get the last data row from the table.
  • Increase the count of rows and get all names
  • Search data from table and get some data from that filtered table.
  • Sort the table and then get the data.
  • Get multiple selected data from the table

And couple of more complicated scenarios we’ll try to automate. We’ll use multiple tables for this and I’ll share the code for each of them.

Total Number of Rows in a Table

So one of the use cases when coming to automation is that we’ve to validate that the count of rows in the table matches an expected count or you simply want to get all the rows in the table for further operations. So how can we do that.

So table rows have tags <tr>, which we can use.

Let’s go to this URL – https://datatables.net/extensions/select/examples/initialisation/checkbox.html

This contains a table, which consists of data related to some employees – let’s find out how many rows are there ( there is a drop down for selecting the rows count – lets ignore it for now).

The table has an id example, which we can use to get the table and the body of the table <tbody> contains the row <tr> elements.

To get the count of all rows we can have this

This will print 10 , which is the count of the table rows. You can increase the count from the drop down and then run this script and it will then print count of rows.

Total number of columns for each row

Now that we’ve printed how many rows are there, let’s see how many columns are there for each row. For this we’ll use the same id for the table and also the <tbody> tag.

Now there is a nice method in Playwright which is locator.all(), which we can use – this method returns promises, so you have to be careful when using in a loop

First we get all the <tr> elements in the variable allRows. Then use the forEach() method to get the count of the table columns, using the <td> tag elements.

All Data From A Single Row

Now that we have the count of all rows and columns. How about getting data from a single row. Let’s say we want to get all the table values from the second row. So how can we do that.

Now we want to hard code the index of the table row in the locator.

Now there is something which is very important here which is the :scope in the second line. Let’s explain.

Role of :scope

The :scope pseudo-class selector in CSS and JavaScript is used to select elements that are at the root of a given scope. In the context of web scraping or automation frameworks like Playwright, the :scope selector can be useful for constraining the scope of a selector to a certain root element, instead of the whole document. It essentially allows you to search for elements within a specific subtree of your DOM.

For instance, imagine you have an element and you want to find a child of this element with a certain property. If you use the :scope selector, your search will only consider children of this specific element, rather than searching the entire document.

The reason why this is important is because it allows for more efficient and targeted searching. If you’re dealing with a large and complex DOM, being able to limit your search to a specific section can save a significant amount of time and resources. Moreover, it reduces the chance of selecting the wrong element if there are multiple elements with similar properties in different parts of the document.

So, we get the output as

which is what we wanted to get.

Get the last row from Table

Let’s do one thing – we also have a search functionality for this table. We want to search how many people have Tokyo office and then select the last person checkbox beside them.

First search for the people with office as Tokyo – you can directly search this from the search bar.

Now we use the same locator for the table body and then use the :scope pseudo selector for selecting the last() child of the <tr> tag, from the table search

I’ve added a 5s delay so that the user can see the changes if any – but this is optional and can be gotten rid of.

Increase count of rows and get all names

Now, in the current tests, we have been searching with only 10 records – now lets change this to 25 and let’s collect all the names of the people appearing.

Here again we’ve used the concept of :scope and have used the allInnerTexts() method to get the names of the people.

Search data from table and get some data from that filtered table.

Now from the table above, let’s apply a search criteria and then select some row values from them. So now let’s say that we want to search for all the people whose office is Tokyo and then we want to select their names from the searched table. So how to do that.

First we enter the search term i.e. Tokyo in the search box

And then we use the print all texts from the all rows

which gives us the desired output

In my next part, I’ll try to come up with another table and then we’ll try couple of more scenarios. All the tests for these series will be posted in this github repo