Skip to main content

Performing Hand Seals...

SCROLLS (GUIDES) ▸ ACADEMY - LOCATOR DISCIPLINE
01

Setup & Tooling

Academy Student - Academy Enrollment

Before you write a single test, you need Playwright installed, configured, and running. This rank covers: npm init playwright@latest, the config file, codegen, trace viewer, and your first raw test against the Training Ground.

THE SETUP

Run npm init playwright@latest. Choose TypeScript. Accept the defaults. Open the Training Ground at /dojo/app and run npx playwright codegen against it. Record one action. That's your first test.

02

Locator Discipline

Academy Graduate - Graduation Exam

Your first real tests. The goal isn't just green — it's tests that survive a redesign and actually catch bugs. The locator you reach for first decides both.

THE RULE

Locator priority: role / label / texttestid → CSS last. And never waitForTimeout — web-first assertions auto-wait.

✓ GOOD - role-based, web-first search.spec.ts
import { test, expect } from '@playwright/test';

test('search narrows the menu', async ({ page }) => {
  await page.goto('/dojo/app');

  // role + label work because the
  // markup is built for it
  await page.getByRole('searchbox',
    { name: 'Search menu' }).fill('miso');

  await expect(page.getByRole('listitem'))
    .toHaveCount(1);
  await expect(page.getByText('Miso Ramen'))
    .toBeVisible();
});
✗ BAD - the common AI mistake search.spec.ts
test('search', async ({ page }) => {
  await page.goto('/dojo/app');

  // brittle CSS, coupled to layout
  await page.locator('div > input.search')
    .fill('miso');

  await page.waitForTimeout(2000);

  // asserts existence, not the result
  const n = await page.locator('.item').count();
  expect(n).toBeGreaterThan(0);
});

Pitfalls

  • Hardcoded waits hide races and make the suite slow. Use web-first assertions that retry until the condition is true.
  • Asserting existence (count() > 0) passes even when the value is wrong. Assert the real, user-visible state.
  • nth-child CSS chains break the moment a wrapper div moves. Reach for testid before CSS.
Next: Genin - Page Object Models →