Skip to content
QA Knowledge Hub

Tables, sorting and pagination

Beginner

A table with sorting, a filter box, pagination and row actions. Rows change after each action.

Practice area

#City
1AshaQA Engineer720000Pune
2RaviDeveloper1100000Bengaluru
3MeenaQA Engineer650000Chennai
4KabirSDET1500000Hyderabad
5DivyaProduct Manager1800000Mumbai
Page 1 of 3Total rows: 12

Tasks to automate

  1. Read Meena's salary from the table without using a row index.
  2. Sort by salary (high to low) and assert that the first row is the highest paid.
  3. Type QA in the filter and assert that every visible row has the role QA Engineer.
  4. Go to page 2 and assert the page indicator and the first name on that page.
  5. Delete one row and assert that the total count shown drops by one.
  6. Collect all names across all pages into a list, using the next button until it is disabled.

Model solutions

Try the tasks first. These show one good way, not the only way.

Selenium (Java)
// Salary of Meena, found by text and not by position
String salary = driver.findElement(
    By.xpath("//table[@id='pg-table']//tr[td[normalize-space()='Meena']]/td[4]")).getText();

// Sort, then read the first row
driver.findElement(By.id("pg-sort-salary")).click();
driver.findElement(By.id("pg-sort-salary")).click();   // second click = descending
String top = driver.findElement(By.cssSelector("#pg-table tbody tr:first-child td:nth-child(2)")).getText();

// Walk all pages
List<String> names = new ArrayList<>();
do {
    driver.findElements(By.cssSelector("#pg-table tbody tr td:nth-child(2)"))
          .forEach(td -> names.add(td.getText()));
    WebElement next = driver.findElement(By.id("pg-next"));
    if (!next.isEnabled()) break;
    next.click();
} while (true);
Playwright (TypeScript)
const salary = await page.locator('#pg-table tr', { hasText: 'Meena' }).locator('td').nth(3).innerText();

await page.locator('#pg-sort-salary').click();
await page.locator('#pg-sort-salary').click();
await expect(page.locator('#pg-table tbody tr').first().locator('td').nth(1)).toHaveText('Kabir');

const names: string[] = [];
while (true) {
  names.push(...(await page.locator('#pg-table tbody tr td:nth-child(2)').allInnerTexts()));
  if (await page.locator('#pg-next').isDisabled()) break;
  await page.locator('#pg-next').click();
}

Element IDs on this page are stable and will not change. Nothing you do here is sent to a server.