What You Will Learn
Playwright is a modern browser automation framework used to automate web applications and create reliable end-to-end tests. In this lesson, we start from the fundamentals and gradually build practical automation scenarios that resemble real software projects.
Open browsers, navigate to websites, click elements, enter data and verify results.
Validate complete business workflows such as login → search → checkout → confirmation.
Run the same tests against Chromium, Firefox and WebKit.
Use locators, auto-waiting, assertions, traces and test isolation to reduce flaky tests.
1. What Is Playwright?
Playwright is a browser automation and testing framework for modern web applications. It can control browsers programmatically and is commonly used for functional, regression, smoke and end-to-end testing.
2. Why Teams Use Playwright
| Need | Playwright Approach | Real-Time Example |
|---|---|---|
| Browser testing | Automate Chromium, Firefox and WebKit | Verify a checkout flow in multiple browsers |
| Reliable waits | Built-in auto-waiting | Wait for a button to become actionable |
| UI validation | Assertions | Verify that “Order placed” is displayed |
| API testing | API request context | Create test data through an API before a UI test |
| Debugging | Trace, screenshots and videos | Investigate why a CI test failed |
3. Installing Playwright
A common Playwright setup uses Node.js and the Playwright Test runner.
npm init playwright@latest
During setup, you can choose JavaScript or TypeScript, the test directory and browser installation.
npx playwright test
4. Your First Playwright Test
A basic test can open a web page and verify its title. The following example uses the Playwright Test runner.
const { test, expect } = require('@playwright/test');
test('homepage has the expected title', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveTitle(/Example Domain/);
});
- Playwright starts a browser for the test.
- A page is created.
- The page navigates to the URL.
- The title is checked.
- The test passes when the expectation is satisfied.
5. Real-Time Example — Login Automation
Login automation is one of the most common real-world Playwright use cases. Imagine an application with email, password and login controls.
const { test, expect } = require('@playwright/test');
test('user can log in', async ({ page }) => {
await page.goto('https://your-app.example/login');
await page.getByLabel('Email').fill('employee@example.com');
await page.getByLabel('Password').fill('Password123!');
await page.getByRole('button', { name: 'Login' }).click();
await expect(page.getByText('Dashboard')).toBeVisible();
});
6. Real-Time Example — E-Commerce Search
A typical e-commerce regression test might search for a product and verify that matching results appear.
test('customer can search for a laptop', async ({ page }) => {
await page.goto('https://your-shop.example');
await page.getByPlaceholder('Search products').fill('laptop');
await page.keyboard.press('Enter');
await expect(
page.getByRole('heading', { name: /laptop/i }).first()
).toBeVisible();
});
This is closer to a real business requirement than a simple “click this button” demonstration.
7. Understanding Browser, Context and Page
These three concepts are fundamental to Playwright.
Browser
The browser process, such as Chromium, Firefox or WebKit.
Browser Context
An isolated browser session. It can have its own cookies, storage and permissions.
Page
A browser tab or page where your automation actions happen.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'homepage.png' });
await browser.close();
})();
8. Locators — Finding Real Web Elements
Locators tell Playwright which element should receive an action or assertion. Prefer user-facing and stable locators where possible.
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByLabel('Email').fill('user@example.com');
await page.getByPlaceholder('Search').fill('Playwright');
await page.getByText('Order confirmed').click();
9. Assertions — Proving the Application Works
Automation is valuable when it verifies expected behavior. Assertions turn browser actions into actual tests.
await expect(page).toHaveTitle(/Dashboard/);
await expect(page.getByRole('button', { name: 'Save' }))
.toBeVisible();
await expect(page.getByTestId('cart-count'))
.toHaveText('2');
await expect(page.getByLabel('Email'))
.toHaveValue('user@example.com');
10. Real-Time Example — Form Validation
A registration form can be tested for both successful and unsuccessful scenarios.
test('registration shows validation for missing email', async ({ page }) => {
await page.goto('https://your-app.example/register');
await page.getByLabel('Password').fill('Password123!');
await page.getByRole('button', { name: 'Create account' }).click();
await expect(
page.getByText('Email is required')
).toBeVisible();
});
A professional test suite should normally contain positive, negative and boundary-value scenarios rather than testing only the happy path.
11. Real-Time Example — Checkout Workflow
A realistic e-commerce flow can combine several actions and assertions.
test('customer can complete checkout', async ({ page }) => {
await page.goto('https://your-shop.example');
await page.getByPlaceholder('Search products').fill('headphones');
await page.keyboard.press('Enter');
await page.getByRole('button', { name: 'Add to cart' }).first().click();
await page.getByRole('link', { name: 'Cart' }).click();
await expect(page.getByText('Your cart')).toBeVisible();
await page.getByRole('button', { name: 'Checkout' }).click();
await page.getByLabel('Address').fill('10 Main Street');
await page.getByRole('button', { name: 'Place order' }).click();
await expect(page.getByText('Order confirmed')).toBeVisible();
});
12. Auto-Waiting
Modern web applications often load elements asynchronously. Playwright performs built-in waiting around many actions and assertions, which helps avoid unnecessary fixed delays.
// Prefer:
await expect(page.getByText('Payment successful')).toBeVisible();
// Avoid unnecessary fixed delays:
await page.waitForTimeout(5000);
13. Screenshots and Debugging
When an automation test fails, screenshots and traces can provide evidence of what happened.
await page.screenshot({
path: 'artifacts/checkout-page.png',
fullPage: true
});
npx playwright test --ui
14. Cross-Browser Testing
A web application can behave differently across browser engines. Playwright projects can be configured to execute the same suite against multiple browsers.
Chromium
Common desktop coverageUseful for Chromium-based browser testing.
Firefox
Browser coverageHelps detect browser-specific behavior.
WebKit
Safari engine coverageUseful for validating WebKit behavior.
15. Real-Time Example — API + UI Testing
Modern applications often depend on APIs. A test can prepare data through an API and then validate the result through the browser.
test('new customer appears in the dashboard', async ({ request, page }) => {
const response = await request.post('/api/customers', {
data: {
name: 'Test Customer',
email: 'customer@example.com'
}
});
expect(response.ok()).toBeTruthy();
await page.goto('/dashboard');
await expect(
page.getByText('Test Customer')
).toBeVisible();
});
In a real project, the API URL, authentication and test data would normally be configured for the test environment rather than hard-coded.
16. Recommended Learning Workflow
- Understand browsers, contexts and pages.
- Practice reliable locators.
- Learn actions such as click, fill, select and keyboard interaction.
- Learn assertions and test isolation.
- Build Page Object Model classes.
- Add API testing and reusable fixtures.
- Run tests across browsers and in CI/CD.
17. Mini Project — Employee Portal
Build a small automation suite for an employee portal. This project combines the concepts from this lesson into a realistic workflow.
| Test | Scenario | Expected Result |
|---|---|---|
| Login | Valid employee credentials | Dashboard is displayed |
| Invalid Login | Wrong password | Error message is displayed |
| Employee Search | Search by employee name | Matching employee is shown |
| Profile Update | Change phone number | Updated value is displayed |
| Logout | Click logout | Login page is displayed |
18. Common Beginner Mistakes
- Using brittle XPath or CSS selectors everywhere.
- Adding unnecessary fixed waits.
- Writing tests that depend on another test's state.
- Hard-coding real credentials or production data.
- Testing only the happy path.
- Creating very large tests that cover unrelated business flows.
- Ignoring screenshots, traces and failure diagnostics.
- Running only one browser when cross-browser behavior matters.
19. Professional Playwright Checklist
- Use meaningful test names.
- Prefer stable, user-facing locators.
- Use assertions to verify business outcomes.
- Keep tests independent and repeatable.
- Use fixtures and Page Objects when they improve maintainability.
- Store secrets outside source code.
- Capture useful artifacts for failed tests.
- Run important suites in CI/CD.
- Track flaky tests and fix their underlying causes.
20. Final Perspective
Playwright becomes most valuable when it is used to automate meaningful business workflows, not simply individual clicks. Start with small tests, learn reliable locators and assertions, then progress toward reusable frameworks, API integration, cross-browser execution and CI/CD.