Playwright Simple Example: Complete Beginner Tutorial

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:

  1. Open a web page.
  2. Find an element.
  3. Perform an action.
  4. 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:

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:

npx playwright install

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

FilePurpose
tests/Stores test files
.spec.tsTypeScript test file
playwright.config.tsTest configuration
package.jsonDependencies and project scripts
package-lock.jsonDependency 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:

  1. Opens the login page.
  2. Enters username.
  3. Enters password.
  4. Clicks Login.
  5. 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
  • Email
  • 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

    ↓

Install browsers

    ↓

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:

Level 4: Advanced Automation

Learn:

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:

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.

Leave a Comment

Your email address will not be published. Required fields are marked *