import { test, expect } from "@playwright/test";
test("user can log in", async ({ page }) => {
await page.goto("/login");
await page.getByLabel("Email").fill("ana@example.com");
await page.getByLabel("Password").fill("secret");
await page.getByRole("button", { name: "Log in" }).click();
await expect(page.getByRole("heading", { name: "Dashboard" })).toBeVisible();
});
Playwright is an E2E (end-to-end) testing framework. It drives real Chromium, Firefox and WebKit browsers.
Its test runner gives each test a fresh browser context. A context is like a new incognito profile, so cookies and storage don't leak between tests.
Auto-waiting: actions wait until the element is ready before they act. For example, await page.getByRole('button', { name: 'Save' }).click() waits until the button is:
- attached to the page
- visible
- stable, so not moving
- enabled
- able to receive events
Web-first assertions retry until the condition is true or the timeout passes. Examples: await expect(locator).toBeVisible() and toHaveText.
Together they remove most manual waiting. Manual waiting is the main cause of flaky E2E tests, meaning tests that pass and fail at random.
Locators follow the same idea as Testing Library: prefer getByRole, getByLabel and getByText. The trace viewer records each step, which helps you debug failures.
- Playwright drives real browsers: Chromium, Firefox and WebKit.
- Each test gets a fresh browser context, so tests stay isolated.
- Actions auto-wait until the element is ready to act on.
- Web-first assertions retry until they pass or time out.
- Prefer user-facing locators, and use the trace viewer for debugging.
- Playwright intro (https://playwright.dev/docs/intro)playwright.dev
- Locators (https://playwright.dev/docs/locators)playwright.dev