Introduction: What Does a Simple Playwright Example Look Like?
If you are new to browser automation, the easiest way to learn Playwright is to start with a Playwright simple example.
A simple test does not need a complicated framework. You only need to:
- Open a web page.
- Find an element.
- Perform an action.
- Verify the expected result.
For example:
import { test, expect } from ‘@playwright/test’;
test(‘verify Playwright homepage’, async ({ page }) => {
await page.goto(‘https://playwright.dev/’);
await expect(page).toHaveTitle(/Playwright/);
});
This is a complete, runnable Playwright test.
The example opens the Playwright website and checks its page title.
That simple workflow is the foundation of Playwright automation testing.
This Playwright simple example tutorial starts from project setup and gradually introduces locators, actions, assertions, auto-waiting, forms, screenshots, reports, debugging, Page Object Model, browsers, and CI/CD.
What Is Playwright?
Playwright is an open-source browser automation and end-to-end testing framework originally developed by Microsoft.
It can automate modern web applications using:
- Chromium
- Firefox
- WebKit
It supports several programming languages, including:
- TypeScript
- JavaScript
- Python
- Java
- .NET
For this tutorial, we use Playwright TypeScript because it is a popular choice for modern automation projects.
A simple Playwright workflow looks like:
Test
↓
Browser
↓
Page
↓
Locator
↓
Action
↓
Assertion
↓
Pass / Fail
Let’s understand the important terms.
Browser
The browser engine that executes the application.
Page
A browser tab.
Example:
await page.goto(‘https://example.com’);
Locator
A way to identify an element.
page.getByRole(‘button’, { name: ‘Login’ })
Action
An interaction such as:
await page.getByRole(‘button’, { name: ‘Login’ }).click();
Assertion
A verification:
await expect(page).toHaveTitle(/Dashboard/);
Test
A scenario containing actions and validations.
Reporter
A component that presents test execution results, such as the HTML report.
These concepts are the foundation of the Playwright testing framework.
Why Start With a Simple Playwright Example?
Beginners often make automation harder than necessary.
They start with:
- Page Object Model
- Custom fixtures
- Multiple environments
- CI/CD
- Advanced reporting
- API authentication
- Parallel execution
before understanding basic test execution.
A better learning approach is:
Simple test
↓
Locators
↓
Assertions
↓
Forms
↓
Dynamic elements
↓
POM
↓
Fixtures
↓
Reporting
↓
CI/CD
A simple Playwright test helps you understand how browser automation works before introducing framework architecture.
For Selenium users, this is also a useful way to understand the differences between Selenium-style WebDriver automation and Playwright’s modern approach.
Playwright Prerequisites and Installation
Before creating a simple Playwright test example, install Node.js.
Check Node.js:
node –version
Check npm:
npm –version
Create a Playwright project:
npm init playwright@latest
Select:
TypeScript
Choose a test directory such as:
tests
If browsers are not installed automatically:
Verify Playwright:
npx playwright –version
Creating a Basic Playwright Project
A beginner project may look like:
playwright-project/
│
├── tests/
│ └── example.spec.ts
│
├── playwright.config.ts
├── package.json
├── package-lock.json
└── node_modules/
Important files
| File | Purpose |
| tests/ | Stores test files |
| .spec.ts | TypeScript test file |
| playwright.config.ts | Test configuration |
| package.json | Dependencies and project scripts |
| package-lock.json | Dependency lock file |
For beginners, do not worry about creating a complicated folder structure.
Start with one test file.
Writing the Simplest Playwright Test
This is the most important Playwright simple example for beginners.
What It Does
The test opens the Playwright website and verifies the title.
Code
import { test, expect } from ‘@playwright/test’;
test(‘Playwright homepage title’, async ({ page }) => {
await page.goto(‘https://playwright.dev/’);
await expect(page).toHaveTitle(/Playwright/);
});
Line-by-Line Explanation
Import Playwright
import { test, expect } from ‘@playwright/test’;
test creates a test case.
expect performs assertions.
Define the test
test(‘Playwright homepage title’, async ({ page }) => {
This creates a test named Playwright homepage title.
The page fixture represents a browser tab.
Open the webpage
await page.goto(‘https://playwright.dev/’);
goto() navigates to the specified URL.
Verify the title
await expect(page).toHaveTitle(/Playwright/);
This checks whether the page title contains Playwright.
Expected Result
Run:
npx playwright test
The test should pass.
Best Practice
Start with one clear behavior per test.
Playwright Locators: Simple Examples
Locators are essential in every Playwright simple example.
They tell Playwright which element to use.
getByRole()
What It Does
Finds an element using its accessible role.
Code
await page.getByRole(‘button’, { name: ‘Login’ }).click();
Explanation
Playwright searches for a button with the accessible name Login.
Expected Result
The Login button is clicked.
Best Practice
Prefer role-based locators when appropriate.
Using getByText()
What It Does
Finds visible text.
Code
await page.getByText(‘Welcome’).click();
Explanation
Playwright locates the element containing the specified text.
Expected Result
The matching element is clicked.
Best Practice
Make the locator specific enough if the same text appears multiple times.
Using getByLabel()
This is particularly useful for forms.
Code
await page.getByLabel(‘Username’).fill(‘admin’);
Explanation
Playwright finds the field associated with the Username label and fills it.
Expected Result
The username field contains admin.
Best Practice
Use accessible labels whenever your application provides them.
Adding Assertions With expect()
A test should not only perform actions. It should verify results.
Title
await expect(page).toHaveTitle(/Playwright/);
URL
await expect(page).toHaveURL(/dashboard/);
Visibility
await expect(page.getByText(‘Welcome’)).toBeVisible();
Text
await expect(page.getByRole(‘heading’)).toHaveText(‘Dashboard’);
Button State
await expect(
page.getByRole(‘button’, { name: ‘Submit’ })
).toBeEnabled();
Why Assertions Matter
Without assertions, a test may click a button without confirming that the application actually behaved correctly.
A good test follows:
Action
↓
Expected Behavior
↓
Assertion
Understanding Playwright Auto-Waiting
Auto-waiting is one of the most useful Playwright features for beginners.
Suppose a button appears after an API request.
You should generally not write:
await page.waitForTimeout(5000);
await page.getByRole(‘button’, { name: ‘Submit’ }).click();
Instead:
await page.getByRole(‘button’, { name: ‘Submit’ }).click();
Playwright automatically waits for supported actionability conditions.
For dynamic results:
await expect(page.getByText(‘Order completed’)).toBeVisible();
The assertion waits for the expected condition.
Best Practice
Avoid hard-coded waits unless you have a specific reason to use one.
Prefer meaningful conditions over arbitrary delays.
Simple Login Automation Example
A login flow is a common Playwright automation example for beginners.
What It Does
It:
- Opens the login page.
- Enters username.
- Enters password.
- Clicks Login.
- Verifies the Dashboard.
Code
import { test, expect } from ‘@playwright/test’;
test(‘valid user login’, 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();
});
Line-by-Line Explanation
goto() opens the login page.
getByLabel() identifies the username and password fields.
fill() enters test data.
getByRole() finds the Login button.
click() submits the form.
expect() verifies the Dashboard.
Expected Result
The test passes when the Dashboard is visible.
Best Practice
Never commit real passwords to Git.
Use environment variables or CI/CD secrets.
Simple Form-Filling Example
Suppose an application has:
- First Name
- Last Name
- Submit button
A simple test is:
import { test, expect } from ‘@playwright/test’;
test(‘submit registration form’, async ({ page }) => {
await page.goto(‘https://example.com/register’);
await page.getByLabel(‘First Name’).fill(‘John’);
await page.getByLabel(‘Last Name’).fill(‘Smith’);
await page.getByLabel(‘Email’).fill(‘john@example.com’);
await page.getByRole(‘button’, { name: ‘Register’ }).click();
await expect(
page.getByText(‘Registration successful’)
).toBeVisible();
});
This is a useful Playwright basic example because it demonstrates several fundamental actions in one workflow.
Simple Dropdown, Checkbox, and Button Examples
Dropdown
For a standard HTML <select>:
await page.getByLabel(‘Country’).selectOption(‘IN’);
Expected Result
India is selected.
Checkbox
await page.getByLabel(‘Accept Terms’).check();
Verify it:
await expect(
page.getByLabel(‘Accept Terms’)
).toBeChecked();
Button
await page.getByRole(‘button’, { name: ‘Submit’ }).click();
Best Practice
Prefer semantic locators over fragile DOM structures.
Taking Screenshots and Generating Reports
Screenshot
What It Does
Captures the current page.
Code
await page.screenshot({
path: ‘screenshots/result.png’,
fullPage: true
});
Expected Result
A PNG file is created.
For larger suites, configure:
use: {
screenshot: ‘only-on-failure’
}
Viewing the HTML Report
Run:
npx playwright test
Then:
npx playwright show-report
The HTML report can display:
- Passed tests
- Failed tests
- Test duration
- Errors
- Screenshots
- Trace information
Reporting becomes especially important when tests run in CI/CD.
Debugging a Simple Playwright Test
Even a simple test can fail.
Start debugging with:
npx playwright test –debug
You can also run:
npx playwright test –headed
This lets you watch the browser.
For deeper debugging, configure tracing:
use: {
trace: ‘on-first-retry’
}
A trace can help you inspect what happened during the test.
Beginner Debugging Checklist
When a test fails, check:
- Is the URL correct?
- Is the locator correct?
- Is the element inside an iframe?
- Did the page navigate?
- Is the element dynamically rendered?
- Are test credentials valid?
- Does the problem occur only in CI?
Do not immediately add a five-second wait.
First understand the failure.
Running the Simple Example in Chromium, Firefox, and WebKit
Playwright supports multiple browser engines.
Configure:
import { defineConfig, devices } from ‘@playwright/test’;
export default defineConfig({
projects: [
{
name: ‘chromium’,
use: { …devices[‘Desktop Chrome’] },
},
{
name: ‘firefox’,
use: { …devices[‘Desktop Firefox’] },
},
{
name: ‘webkit’,
use: { …devices[‘Desktop Safari’] },
},
],
});
Run Chromium:
npx playwright test –project=chromium
Run Firefox:
npx playwright test –project=firefox
Run WebKit:
npx playwright test –project=webkit
Run all browsers:
npx playwright test
Career Tip
Cross-browser testing is an important topic for SDET interviews.
Converting the Simple Example Into Page Object Model
Once your tests become larger, repeated locators can make the test code difficult to maintain.
Page Object Model solves this problem.
What It Does
Create a class representing the login page.
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 POM’, async ({ page }) => {
const loginPage = new LoginPage(page);
await page.goto(‘https://example.com/login’);
await loginPage.login(‘testuser’, ‘Password123’);
await expect(page.getByText(‘Dashboard’)).toBeVisible();
});
Expected Result
The test performs the same login workflow, but the locators and login behavior are reusable.
Best Practice
Do not create complex abstractions for every single line of a beginner test.
Introduce POM when reuse and maintainability justify it.
Basic CI/CD Execution
After learning a simple Playwright test, the next step is running it automatically.
A basic GitHub Actions workflow is:
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/
The workflow is:
Checkout code
↓
Install dependencies
↓
↓
Run tests
↓
Upload report
This is the foundation of professional Playwright automation testing.
Common Beginner Mistakes and Solutions
Mistake 1: Using long XPath selectors
Fragile:
html/body/div[2]/div[3]/button
Prefer:
page.getByRole(‘button’, { name: ‘Submit’ })
Mistake 2: Using hard waits
Avoid:
await page.waitForTimeout(5000);
Prefer auto-waiting and assertions.
Mistake 3: No assertion
Bad:
await page.getByRole(‘button’, { name: ‘Login’ }).click();
Better:
await page.getByRole(‘button’, { name: ‘Login’ }).click();
await expect(page.getByText(‘Dashboard’)).toBeVisible();
Mistake 4: Tests depend on one another
Each test should be independently executable.
Mistake 5: Hard-coding credentials
Use environment variables and secrets.
Mistake 6: Building a huge framework immediately
First understand:
Test
Locators
Actions
Assertions
Auto-waiting
Then add POM, fixtures, and CI/CD.
Playwright Best Practices
Use these rules as your framework grows.
1. Prefer stable locators
Use:
getByRole()
getByLabel()
getByText()
getByTestId()
where appropriate.
2. Keep tests focused
One test should validate one meaningful behavior.
3. Use web-first assertions
Assertions should verify the state you actually care about.
4. Avoid unnecessary waits
Let Playwright handle synchronization where possible.
5. Keep test data separate
Do not mix large datasets directly into test logic.
6. Use POM for reusable workflows
Centralize frequently used page interactions.
7. Use screenshots and traces strategically
Capture failure artifacts rather than generating unnecessary files.
8. Run tests in CI
A test that only runs on a developer’s machine provides less value than one integrated into the delivery pipeline.
9. Learn TypeScript
For Playwright TypeScript projects, understand:
- Functions
- Classes
- Interfaces
- Types
- Async/await
- Imports
- Exports
Playwright Interview Questions With Answers
1. What is a simple Playwright test?
A simple Playwright test opens a page, interacts with an element, and verifies the expected result.
2. How do I write a simple Playwright test?
Example:
import { test, expect } from ‘@playwright/test’;
test(‘simple test’, async ({ page }) => {
await page.goto(‘https://playwright.dev/’);
await expect(page).toHaveTitle(/Playwright/);
});
3. What is page.goto()?
It navigates a browser page to a specified URL.
4. What is a locator?
A locator identifies a page element for interaction or validation.
5. What is auto-waiting?
Playwright automatically waits for supported conditions before performing actions.
6. What is expect()?
expect() is used to verify expected application behavior.
7. How do you run Playwright tests?
npx playwright test
8. How do you debug a Playwright test?
npx playwright test –debug
You can also use headed mode, screenshots, traces, and reports.
9. Can Playwright test multiple browsers?
Yes. Playwright supports Chromium, Firefox, and WebKit.
10. Why use Page Object Model?
POM improves reuse and separates page interaction logic from test scenarios.
Learning Roadmap After the Simple Example
Once your first Playwright simple example works, follow this learning path.
Level 1: Fundamentals
Learn:
- Installation
- Project structure
- Configuration
- Browser
- Page
- Locator
- Actions
- Assertions
Level 2: Web Automation
Practice:
- Login
- Forms
- Dropdowns
- Checkboxes
- Tables
- Dynamic elements
- Alerts
- Popups
- Frames
Level 3: Framework Design
Learn:
- Page Object Model
- Fixtures
- Hooks
- Test data
- Utilities
- Environment management
Level 4: Advanced Automation
Learn:
- API testing
- Authentication
- Network interception
- Parallel execution
- Visual testing
- Advanced reporting
Level 5: DevOps
Learn:
- Git
- GitHub Actions
- CI/CD
- Docker
- Test artifacts
- Pipeline troubleshooting
For QA Automation and SDET careers, combine Playwright with TypeScript, API testing, SQL, Git, CI/CD, and testing fundamentals.
Related Playwright Tutorials
After completing this Playwright simple example tutorial, continue with:
- Playwright Basics
- Playwright for Beginners
- Playwright Installation Guide
- Playwright First Test Script
- Playwright Getting Started Guide
- 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 Troubleshooting
- Playwright Interview Questions
These topics provide a progression from a simple Playwright test example to a complete automation framework.
FAQs About Playwright Simple Example
How do I write a simple Playwright test?
Create a .spec.ts file:
import { test, expect } from ‘@playwright/test’;
test(‘simple Playwright test‘, async ({ page }) => {
await page.goto(‘https://playwright.dev/’);
await expect(page).toHaveTitle(/Playwright/);
});
Run it using:
npx playwright test
What is the simplest Playwright example?
A simple example is opening a page and checking its title:
await page.goto(‘https://playwright.dev/’);
await expect(page).toHaveTitle(/Playwright/);
Is Playwright easy for beginners?
Yes. Beginners can start with navigation, locators, actions, and assertions before progressing to framework design and CI/CD.
What language should beginners use for Playwright?
TypeScript is a strong choice for modern automation projects. JavaScript, Python, Java, and .NET are also supported.
What is the difference between a locator and an assertion?
A locator identifies an element. An assertion verifies an expected condition.
Example:
const button = page.getByRole(‘button’, { name: ‘Login’ });
await button.click();
await expect(page.getByText(‘Dashboard’)).toBeVisible();
Does Playwright automatically wait?
Yes. Playwright automatically waits for supported actionability conditions, and its web-first assertions retry until the expected condition is met or the timeout is reached.
Can Playwright handle forms?
Yes. You can fill inputs, select dropdowns, check checkboxes, click buttons, upload files, and validate results.
Can a simple Playwright test run in Firefox?
Yes. Playwright supports Chromium, Firefox, and WebKit.
How do I view the Playwright test report?
Run:
npx playwright show-report
What should I learn after a simple Playwright test?
Learn Playwright locators, auto-waiting, Page Object Model, fixtures, API testing, authentication, reporting, parallel execution, CI/CD, and Docker.
