Introduction: What Are Playwright Basics and Why Do They Matter?
If you are new to test automation, learning Playwright basics gives you a practical foundation for automating modern web applications.
Playwright is a browser automation and end-to-end testing framework that supports Chromium, Firefox, and WebKit. It can automate actions such as opening pages, clicking buttons, entering text, submitting forms, handling popups, working with frames, and validating application behavior.
For QA Automation Engineers and SDETs, the basics are especially important because advanced Playwright frameworks are built on these fundamentals.
Before learning Page Object Model, fixtures, API testing, parallel execution, or CI/CD, you should understand:
- Browser
- Browser context
- Page
- Locator
- Assertion
- Test
- Fixture
- Reporter
- Auto-waiting
- Test configuration
This Playwright Basics Tutorial for Beginners explains each concept with practical Playwright TypeScript examples.
What Is Playwright?
Playwright is an open-source automation and testing framework originally developed by Microsoft.
It can automate modern web applications across multiple browser engines.
A basic test looks like this:
import { test, expect } from ‘@playwright/test’;
test(‘verify Playwright homepage’, async ({ page }) => {
await page.goto(‘https://playwright.dev/’);
await expect(page).toHaveTitle(/Playwright/);
});
This small example already demonstrates several important Playwright concepts:
- test() defines a test.
- page represents a browser page.
- goto() navigates to a URL.
- expect() verifies application behavior.
- toHaveTitle() is an assertion.
Understanding these building blocks is the foundation of Playwright automation testing.
Playwright Architecture and Core Concepts
One of the most important parts of learning Playwright basics for beginners is understanding how the framework is organized.
A simplified architecture looks like this:
|
+—- Browser
|
+—- Browser Context
|
+—- Page
|
+—- Locator
|
+—- Assertions
Let’s understand each term.
Browser
The browser represents a browser engine such as Chromium, Firefox, or WebKit.
Browser Context
A browser context is an isolated browser session.
It is similar to creating a fresh browser profile without launching an entirely separate browser process.
Contexts help keep tests isolated.
Page
A page represents a browser tab.
For example:
await page.goto(‘https://example.com’);
Locator
A locator identifies an element on the page.
page.getByRole(‘button’, { name: ‘Login’ });
Assertion
An assertion verifies expected behavior.
await expect(page).toHaveTitle(/Dashboard/);
Test
A test contains the actions and validations for a particular scenario.
Fixture
A fixture provides reusable test resources.
The built-in page fixture is one of the most commonly used Playwright fixtures.
Reporter
A reporter controls how test results are displayed or stored.
Playwright supports reporters such as the HTML reporter.
Playwright Browsers and Supported Environments
Playwright supports three major browser engines:
| Browser | Playwright project |
| Chromium | Chrome/Chromium-based testing |
| Firefox | Firefox testing |
| WebKit | Safari engine testing |
This is useful because QA teams can test the same application across different browser engines.
Playwright can also run in:
- Windows
- Linux
- macOS
- CI/CD environments
- Containers such as Docker
For beginners, start with Chromium and then add Firefox and WebKit when you understand the fundamentals.
Installing Playwright and Creating a Project
Step 1: Install Node.js
Playwright Test works with Node.js.
Verify your installation:
node –version
npm –version
Step 2: Create a Playwright project
Run:
npm init playwright@latest
The setup wizard will ask several questions.
For this tutorial, choose:
TypeScript
You can choose a test directory such as:
tests
Step 3: Install browsers
If required, run:
Step 4: Verify Playwright
npx playwright –version
Your project is now ready.
Understanding playwright.config.ts
The playwright.config.ts file controls important test settings.
A simple configuration looks like this:
import { defineConfig, devices } from ‘@playwright/test’;
export default defineConfig({
testDir: ‘./tests’,
use: {
baseURL: ‘https://example.com’,
headless: true,
screenshot: ‘only-on-failure’,
trace: ‘on-first-retry’,
},
projects: [
{
name: ‘chromium’,
use: { …devices[‘Desktop Chrome’] },
},
],
});
Important settings include:
testDir
Specifies where tests are stored.
testDir: ‘./tests’
baseURL
Allows shorter navigation commands.
baseURL: ‘https://example.com’
Then:
await page.goto(‘/login’);
instead of:
await page.goto(‘https://example.com/login’);
headless
Controls whether the browser is visible.
headless: true
screenshot
Controls screenshot behavior.
screenshot: ‘only-on-failure’
trace
Controls trace collection.
trace: ‘on-first-retry’
For beginners, avoid changing too many configuration options until you understand what each one does.
Writing Your First Playwright Test
Concept
A Playwright test generally contains:
- Test definition
- Browser interaction
- Assertion
Code
Create:
tests/homepage.spec.ts
Add:
import { test, expect } from ‘@playwright/test’;
test(‘verify Playwright homepage’, async ({ page }) => {
await page.goto(‘https://playwright.dev/’);
await expect(page).toHaveTitle(/Playwright/);
await expect(
page.getByRole(‘heading’, { name: /Playwright enables reliable/ })
).toBeVisible();
});
Explanation
The test:
- Opens Playwright’s website.
- Checks the title.
- Finds a heading using its accessible role.
- Verifies that the heading is visible.
Expected Result
The test passes if the title and heading meet the expectations.
Run:
npx playwright test
To see the browser:
npx playwright test –headed
Best Practice
Use meaningful test names:
test(‘valid user can log in successfully’, async ({ page }) => {
});
instead of:
test(‘test1’, async ({ page }) => {
});
Playwright Locators and Element Interactions
Locators are a fundamental part of Playwright testing framework basics.
A locator tells Playwright which element you want to interact with.
getByRole()
Use accessible roles where possible.
await page.getByRole(‘button’, { name: ‘Login’ }).click();
getByLabel()
Excellent for form fields.
await page.getByLabel(‘Username’).fill(‘admin’);
getByText()
Useful for visible text.
await page.getByText(‘Welcome’).click();
getByPlaceholder()
await page.getByPlaceholder(‘Enter email’).fill(‘user@example.com’);
getByTestId()
await page.getByTestId(‘submit-button’).click();
CSS Locator
await page.locator(‘#username’).fill(‘admin’);
Locator Best Practice
Prefer:
page.getByRole(‘button’, { name: ‘Submit’ })
over fragile selectors such as:
page.locator(‘div.container > div:nth-child(2) > button’)
Stable, user-facing locators generally make tests easier to maintain.
Assertions and Auto-Waiting
Assertions are another essential part of Playwright basics.
They answer questions such as:
- Is the element visible?
- Is the button enabled?
- Does the page have the correct title?
- Is the URL correct?
- Does the text match?
- Is a checkbox selected?
Examples:
await expect(page).toHaveTitle(/Playwright/);
await expect(page).toHaveURL(/playwright/);
await expect(page.getByRole(‘button’)).toBeVisible();
await expect(page.getByText(‘Success’)).toHaveText(‘Success’);
What Is Auto-Waiting?
Playwright automatically waits for many actionability conditions before performing actions.
For example:
await page.getByRole(‘button’, { name: ‘Submit’ }).click();
Playwright can wait for the button to become actionable instead of requiring you to manually pause the test.
Avoid unnecessary code such as:
await page.waitForTimeout(5000);
Instead, use an assertion:
await expect(page.getByText(‘Order completed’)).toBeVisible();
This is more reliable because the test waits for the actual application condition.
Navigation, Forms, Buttons, Dropdowns, and Checkboxes
These are the most common browser automation operations.
Navigation
await page.goto(‘https://example.com’);
await page.goBack();
await page.goForward();
await page.reload();
Clicking
await page.getByRole(‘button’, { name: ‘Submit’ }).click();
Typing
await page.getByLabel(‘Email’).fill(‘user@example.com’);
Form Submission
await page.getByLabel(‘Username’).fill(‘admin’);
await page.getByLabel(‘Password’).fill(‘Password123’);
await page.getByRole(‘button’, { name: ‘Login’ }).click();
Dropdown
For a standard HTML <select>:
await page.getByLabel(‘Country’).selectOption(‘IN’);
Checkbox
await page.getByLabel(‘Accept Terms’).check();
Verify it:
await expect(page.getByLabel(‘Accept Terms’)).toBeChecked();
Real-World Login Automation Example
A login scenario is one of the best Playwright basics examples for QA engineers.
Concept
Automate a typical username/password login flow.
Code
import { test, expect } from ‘@playwright/test’;
test(‘user can log in’, async ({ page }) => {
await page.goto(‘https://example.com/login’);
await page.getByLabel(‘Username’).fill(‘testuser’);
await page.getByLabel(‘Password’).fill(‘Password123’);
await page.getByRole(‘button’, { name: ‘Login’ }).click();
await expect(
page.getByRole(‘heading’, { name: ‘Dashboard’ })
).toBeVisible();
});
Explanation
The test:
- Opens the login page.
- Enters the username.
- Enters the password.
- Clicks Login.
- Verifies the Dashboard.
Expected Result
The test passes when the Dashboard appears.
Best Practice
Never commit real credentials into your Git repository. Use environment variables or CI/CD secrets.
Handling Alerts, Popups, Frames, and Multiple Pages
Handling Alerts
Browser dialogs can be handled with a dialog event:
page.on(‘dialog’, async dialog => {
console.log(dialog.message());
await dialog.accept();
});
await page.getByRole(‘button’, { name: ‘Delete’ }).click();
Handling Popups
Suppose a button opens another page:
const popupPromise = page.waitForEvent(‘popup’);
await page.getByRole(‘link’, { name: ‘Open Report’ }).click();
const popup = await popupPromise;
await popup.waitForLoadState();
await expect(popup).toHaveTitle(/Report/);
Handling Frames
Use frameLocator():
const frame = page.frameLocator(‘#payment-frame’);
await frame.getByLabel(‘Card Number’).fill(‘4111111111111111’);
Multiple Pages
You can access pages through the browser context:
const pages = page.context().pages();
console.log(pages.length);
These features become particularly useful in real-world applications containing payment widgets, authentication flows, external links, and embedded content.
Screenshots, Videos, Trace Viewer, and Reports
Debugging is a critical automation skill.
Taking a Screenshot
await page.screenshot({
path: ‘screenshots/home.png’,
fullPage: true
});
Screenshot on Failure
Configure:
use: {
screenshot: ‘only-on-failure’
}
This prevents unnecessary screenshots for successful tests.
Trace
A trace can provide detailed information about a test execution.
For example:
use: {
trace: ‘on-first-retry’
}
After a failure and retry, you can inspect the generated trace using Playwright’s trace tooling.
HTML Report
Run:
npx playwright show-report
The report helps you inspect:
- Test status
- Duration
- Errors
- Screenshots
- Traces
- Test steps
Best Practice
Do not simply rerun a failed test repeatedly. Investigate the error, locator, application state, screenshot, and trace.
Test Hooks, Fixtures, and Basic Test Organization
Hooks help organize setup and cleanup.
import { test, expect } from ‘@playwright/test’;
test.describe(‘Login Tests’, () => {
test.beforeEach(async ({ page }) => {
await page.goto(‘https://example.com/login’);
});
test(‘valid login’, async ({ page }) => {
await page.getByLabel(‘Username’).fill(‘admin’);
await page.getByLabel(‘Password’).fill(‘Password123’);
await page.getByRole(‘button’, { name: ‘Login’ }).click();
await expect(page.getByText(‘Dashboard’)).toBeVisible();
});
});
Common hooks include:
- beforeEach
- afterEach
- beforeAll
- afterAll
Fixtures
The page object is a built-in fixture:
test(‘example’, async ({ page }) => {
await page.goto(‘https://example.com’);
});
You can later create custom fixtures for:
- Login sessions
- Test data
- API clients
- Page objects
- Database utilities
Introduction to Page Object Model
Page Object Model, or POM, is a design pattern for organizing automation code.
Instead of placing every locator inside the test, create a class.
LoginPage.ts
import { Page } from ‘@playwright/test’;
export class LoginPage {
constructor(private page: Page) {}
username = this.page.getByLabel(‘Username’);
password = this.page.getByLabel(‘Password’);
loginButton = this.page.getByRole(‘button’, { name: ‘Login’ });
async login(username: string, password: string) {
await this.username.fill(username);
await this.password.fill(password);
await this.loginButton.click();
}
}
Test
import { test, expect } from ‘@playwright/test’;
import { LoginPage } from ‘../pages/LoginPage’;
test(‘login using Page Object Model‘, async ({ page }) => {
const loginPage = new LoginPage(page);
await page.goto(‘https://example.com/login’);
await loginPage.login(‘admin’, ‘Password123’);
await expect(page.getByText(‘Dashboard’)).toBeVisible();
});
Why Use POM?
POM provides:
- Reusable page actions
- Centralized locators
- Cleaner tests
- Easier maintenance
- Better scalability
For beginners, start with simple POM classes. Do not create an overly complicated framework before understanding the fundamentals.
Cross-Browser Testing and Parallel Execution Basics
One benefit of Playwright is cross-browser testing.
A configuration can define multiple projects:
import { defineConfig, devices } from ‘@playwright/test’;
export default defineConfig({
testDir: ‘./tests’,
projects: [
{
name: ‘chromium’,
use: { …devices[‘Desktop Chrome’] },
},
{
name: ‘firefox’,
use: { …devices[‘Desktop Firefox’] },
},
{
name: ‘webkit’,
use: { …devices[‘Desktop Safari’] },
},
],
});
Run only Chromium:
npx playwright test –project=chromium
Run Firefox:
npx playwright test –project=firefox
Playwright Test also supports parallel execution.
Parallel testing is useful for large suites, but tests should not depend on one another.
Bad design:
↓
Test B uses Test A’s data
Better design:
Independent tests are easier to run in parallel.
Basic CI/CD Integration
A basic CI/CD workflow looks like this:
Code Push
↓
Install Node dependencies
↓
↓
↓
↓
Publish artifacts
A simple GitHub Actions workflow:
name: Playwright Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v6
– uses: actions/setup-node@v6
with:
node-version: lts/*
– run: npm ci
– run: npx playwright install –with-deps
– run: npx playwright test
– uses: actions/upload-artifact@v5
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
For a beginner, understanding this pipeline is enough initially. Later, learn:
- Environment variables
- Secrets
- Test sharding
- Docker
- Retry strategies
- Artifact management
Common Playwright Beginner Errors and Solutions
Error 1: Browser executable missing
Try:
npx playwright install
Error 2: Locator not found
Check:
- Is the locator correct?
- Is the element inside an iframe?
- Has the page loaded?
- Is the element dynamically rendered?
- Is the accessible name correct?
Use:
npx playwright test –debug
Error 3: Test passes locally but fails in CI
Check:
- Browser installation
- Environment variables
- Base URL
- Timing
- Test isolation
- CI-specific dependencies
Avoid solving every CI failure by adding long waits.
Error 4: Strict mode violation
This often means your locator matches multiple elements.
Instead of using a broad locator:
page.getByText(‘Submit’)
make it more specific:
page.getByRole(‘button’, { name: ‘Submit’ })
Error 5: Flaky tests
Look for:
- Fragile locators
- Shared test data
- Race conditions
- Hard-coded waits
- External dependencies
- Incorrect synchronization
Playwright Best Practices
A strong beginner framework follows a few simple principles.
1. Prefer resilient locators
Use:
getByRole()
getByLabel()
getByTestId()
before fragile selectors.
2. Avoid hard waits
Prefer:
await expect(locator).toBeVisible();
over:
await page.waitForTimeout(3000);
3. Keep tests independent
Each test should be able to run by itself.
4. Use Page Object Model when appropriate
Do not duplicate the same page interactions throughout dozens of tests.
5. Keep credentials secure
Use environment variables and CI/CD secrets.
6. Use meaningful test names
Good:
valid user can submit payment
Poor:
7. Use debugging artifacts intelligently
Screenshots, traces, and reports are especially valuable when tests execute in CI.
8. Learn TypeScript
Playwright TypeScript becomes much easier when you understand:
- Variables
- Functions
- Classes
- Interfaces
- Types
- Async/await
- Imports and exports
Playwright Interview Questions With Answers
1. What are Playwright basics?
Playwright basics are the core concepts needed to automate web applications, including browsers, contexts, pages, locators, actions, assertions, fixtures, configuration, and test execution.
2. What is Playwright?
Playwright is an open-source browser automation and end-to-end testing framework.
3. What browsers does Playwright support?
Playwright supports Chromium, Firefox, and WebKit.
4. What is a browser context?
A browser context is an isolated browser session that helps keep tests independent.
5. What is a page in Playwright?
A page represents a browser tab.
6. What is a locator?
A locator identifies an element that Playwright should interact with or validate.
Example:
page.getByRole(‘button’, { name: ‘Login’ })
7. What is auto-waiting?
Auto-waiting allows Playwright to wait for required actionability conditions before performing actions.
8. What is a fixture?
A fixture provides reusable test resources such as the built-in page fixture.
9. How do you execute Playwright tests?
npx playwright test
10. How do you execute a test in headed mode?
npx playwright test –headed
11. How do you debug Playwright tests?
You can use headed execution, the Playwright Inspector, screenshots, traces, and HTML reports.
12. Why is Page Object Model used?
POM separates page interaction logic from test logic and improves maintainability and reuse.
Playwright Learning Roadmap for Beginners
A practical learning roadmap is:
Stage 1: Programming Fundamentals
Learn:
- JavaScript basics
- TypeScript basics
- Async/await
- Functions
- Classes
- Arrays and objects
Stage 2: Playwright Fundamentals
Learn:
- Installation
- Configuration
- Browser
- Context
- Page
- Locators
- Actions
- Assertions
Stage 3: Web Automation
Practice:
- Login
- Forms
- Dropdowns
- Checkboxes
- Tables
- Dynamic elements
- Alerts
- Frames
- Popups
- Multiple pages
Stage 4: Framework Development
Learn:
- Page Object Model
- Fixtures
- Hooks
- Test data
- Utilities
- Configuration
- Environment management
Stage 5: Advanced Automation
Move into:
- API testing
- Authentication
- Network mocking
- Parallel execution
- Advanced reporting
- Visual testing
Stage 6: DevOps
Learn:
- Git
- GitHub Actions
- CI/CD
- Docker
- Test artifacts
- Failure analysis
Stage 7: Interview Preparation
Practice explaining:
- Why Playwright?
- Playwright vs Selenium
- Locators
- Auto-waiting
- Fixtures
- POM
- Parallel execution
- Browser contexts
- CI/CD
- Debugging flaky tests
For QA Automation and SDET roles, combine Playwright with API testing, SQL, Git, CI/CD, JavaScript/TypeScript, and strong software testing fundamentals.
Related Playwright Tutorials to Learn Next
Once you understand Playwright basics, continue with:
- Playwright for Beginners
- Playwright Tutorial
- Playwright Tutorial Step by Step
- Playwright TypeScript Tutorial
- Playwright Python Tutorial
- Playwright Java Tutorial
- Playwright Locators
- Playwright Auto Waiting
- Playwright Page Object Model
- Playwright Fixtures Tutorial
- Playwright API Testing
- Playwright Authentication Tutorial
- Playwright Reporting Tutorial
- Playwright Parallel Execution Tutorial
- Playwright CI/CD Tutorial
- Playwright GitHub Actions Tutorial
- Playwright Docker Tutorial
- Playwright Interview Questions
These topics can take you from basic browser automation to designing a complete automation framework.
FAQs About Playwright Basics
What are Playwright basics?
Playwright basics include installation, project setup, browser and page concepts, locators, browser actions, assertions, auto-waiting, test configuration, debugging, and reporting.
How do I get started with Playwright basics?
Install Node.js, create a Playwright TypeScript project using npm init playwright@latest, install the browsers, create a test, and execute it using npx playwright test.
Is Playwright easy for beginners?
Yes. The framework provides a readable API and built-in capabilities such as auto-waiting, assertions, browser contexts, tracing, and reporting.
What language should beginners use with Playwright?
TypeScript is an excellent option for beginners who want to build modern automation frameworks. JavaScript, Python, Java, and .NET are also supported.
What is the difference between Playwright and Selenium?
Both automate browsers. Playwright provides a modern testing experience with features such as built-in auto-waiting, browser contexts, tracing, and integrated test execution. Selenium has a mature ecosystem and extensive enterprise adoption.
Does Playwright require coding knowledge?
Yes. Basic programming knowledge is useful. For Playwright TypeScript, beginners should understand variables, functions, classes, async/await, and basic TypeScript syntax.
Can Playwright be used for CI/CD?
Yes. Playwright tests can run in CI/CD platforms such as GitHub Actions and other continuous integration systems.
What should I learn after Playwright basics?
Learn Page Object Model, fixtures, authentication, API testing, reporting, parallel execution, CI/CD, Docker, and advanced debugging.
