| Find by role / label / text |
page.getByRole("button", { name: "Send" }), getByLabel("Email"), getByText(/invalid/i) |
| Scope a locator |
card.getByRole("button", { name: "Decline" }), locator.filter({ hasText: "A-1001" }) |
| Assert (retrying) |
await expect(loc).toBeVisible() / toHaveText() / toHaveCount() / toHaveAttribute() |
| Assert structure |
await expect(loc).toMatchAriaSnapshot("- article \"Order A-1002\"") |
| Sign in once |
setup project + storageState: "playwright/.auth/user.json" |
| Start signed out |
test.use({ storageState: { cookies: [], origins: [] } }) |
| Mock a response |
await page.route("**/api/x", (r) => r.fulfill({ status: 500, json: {...} })) |
| Call an API |
const res = await request.post("/api/x", { data, headers }) |
| Two users |
const ctx = await browser.newContext() per user |
| Fake time |
await page.clock.install(); await page.clock.fastForward("15:00") |
| Accessibility |
await new AxeBuilder({ page }).analyze() (@axe-core/playwright) |
| Screenshot diff |
await expect(page).toHaveScreenshot("name.png") |
| Custom fixture |
base.extend({ thing: async ({ page }, use) => { /* setup */ await use(x); /* teardown */ } }) |
| Find flakes |
npx playwright test --repeat-each=10 --workers=8 |
| Debug |
--ui, --debug, npx playwright show-trace trace.zip, npx playwright codegen URL |
| CI split |
--shard=1/4 --reporter=blob then npx playwright merge-reports |