VALIDATION LABUSER TABLE — SEARCH + SORT

Tables

User Table — Search + Sort

Search by partial name/email, sort by signups asc/desc, paginate, and verify the visible row count + page metadata reflect every operation.

Intermediate

Why this matters in QA

Every admin grid is a derivative of this module. Bugs hide in: page resets-on-filter, sort breaks after re-render, the visible count drifts from the API's `total`. Senior QA always asserts both.

EmailRoleStatus
Alex Carteralex@hakdogan.comqaActive1,442
Gizem Akargizem@hakdogan.comadminActive2,304
Hugo Wallacehugo@hakdogan.comqaActive728
Ivy Petrovivy@hakdogan.comuserActive1,119
Page 1 / 3 · 10 matches

Live widget · interact freely

Manual test checklist

  • 1Type 'mira' — table reduces to one row
  • 2Click Signups twice — flips asc → desc → first row is 'Gizem'
  • 3Filter to zero matches — confirm an empty state, not a blank table
  • 4Filter, then paginate — confirm the page resets to 1
  • 5Confirm `users-row-0` selector exists for stable assertions

Expected result

Searching 'mira' filters to one row; sorting Signups desc puts 'Gizem' first (2,304 signups); pagination metadata shows 'Page 1 / N · K matches'.

Automation challenge

Drive the search, then sort, then paginate, asserting the metadata `users-page` matches `Page X / Y · K matches` at every step. Use `.first()` and `.nth()` to lock to specific rows; never absolute index.

Stable selectors

  • Search input[data-testid="users-search"]
  • Sort by name[data-testid="users-sort-name"]
  • Sort by signups[data-testid="users-sort-signups"]
  • Row template[data-testid="users-row-{i}"]
  • Page metadata[data-testid="users-page"]
  • Empty state[data-testid="users-empty"]

Reference Playwright spec

user-table.spec.ts
ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { test, expect } from '@playwright/test';

test('user table search + sort + paginate', async ({ page }) => {
  await page.goto('https://lab.hakdogan.com/data-api/user-table');

  await page.getByTestId('users-search').fill('mira');
  await expect(page.getByTestId('users-row-0')).toContainText('Mira');
  await expect(page.getByTestId('users-page')).toContainText('1 matches');

  await page.getByTestId('users-search').fill('');
  await page.getByTestId('users-sort-signups').click();
  await page.getByTestId('users-sort-signups').click();
  await expect(page.getByTestId('users-row-0')).toContainText('Gizem');
});