E2E Tests
Act as a top-tier software engineer with serious testing skills.
Write e2e tests for: $ARGUMENTS
Each test must answer these 5 questions:
- •What is the user flow under test? (test should be in a named describe block)
- •What is the expected behavior? ($given and $should arguments are adequate)
- •What actions does the user perform? (navigations, clicks, form fills, etc.)
- •What is the expected outcome? (visible elements, URLs, toasts, database state)
- •How can we find the bug? (implicitly answered if the above questions are answered correctly)
Rules
- •Use Playwright with test, expect, and test.describe.
- •Tests must use the "given: ..., should: ..." prose format.
- •Test files live in
playwright/directory, organized by feature subdirectories. - •Test files use the
.e2e.tsextension. - •Prefer accessible locators:
getByRole,getByLabel,getByTextover CSS selectors. - •Use
getByRolewith name option as the primary locator strategy. - •When accessible locators are insufficient, use
data-testidattributes viagetByTestId. - •Never use CSS class selectors for test locators — classes are for styling, not testing.
- •Define
data-testidvalues as named exports in a shared constants file (e.g.app/test/test-ids.ts) and import them in both the component and the test. - •Use regex with case-insensitive flag for text matching:
{ name: /submit/i }. - •Await all Playwright actions and assertions.
- •Use
toBeVisible()andtoBeHidden()for element presence checks. - •Use
toHaveURL()or agetPath(page)helper for URL assertions. - •Handle auth setup in helper functions, not inline in every test.
- •Clean up test data in teardown — don't leave state for the next test.
- •Each test should be independent and not depend on other tests' state.
- •Use
test.step("description", async () => { ... })to organize logical phases within a test — never use inline comments like// Open notifications panelas step separators. - •Block images in performance-sensitive tests via
page.route. - •Use
test.describeblocks to group related scenarios. - •Assert toast notifications via
getByRole("region", { name: /notifications/i }). - •For forms, use
getByRole("textbox", { name: /label/i })and.fill(). - •For dropdowns, use
getByRole("combobox")thengetByRole("option"). - •For accessibility checks, use
@axe-core/playwrightwithexpect(results.violations).toEqual([]). - •Create reusable setup/teardown helpers for common flows (login, org creation, etc.).
- •Use factories from the codebase to create test data — never hardcode full objects.
- •Verify database state after mutations using model functions from infrastructure layer.