Playwright TypeScript Page Object Model: Complete Beginner’s Guide with Framework Examples

Introduction

The Playwright TypeScript Page Object Model is one of the most popular design patterns for building scalable automation frameworks. Whether you are an Automation Test Engineer, Selenium tester, or a beginner learning Playwright, understanding the Playwright Page Object Model is essential.

A well-designed Playwright TypeScript Framework keeps your automation code clean, reusable, and easy to maintain. Instead of writing locators in every test file, the Page Object Model (POM) stores them in dedicated page classes.

In this guide, you’ll learn how to implement Page Object Model in Playwright TypeScript, create an enterprise-ready framework, write reusable methods, and prepare for automation testing interviews.


What is Playwright?

Playwright is Microsoft’s modern open-source automation framework used for testing web applications.

It supports:

  • Chromium
  • Firefox
  • WebKit
  • Windows
  • Linux
  • macOS

Playwright provides:

  • Auto waiting
  • Fast execution
  • Parallel testing
  • Network interception
  • Mobile emulation
  • API testing

It has become a preferred replacement for Selenium in many organizations.


Why TypeScript with Playwright?

TypeScript adds strong typing to JavaScript.

Benefits include:

  • Better IntelliSense
  • Early error detection
  • Cleaner code
  • Easier maintenance
  • Better developer productivity

Example:

let username: string = “admin”;

The compiler immediately reports incorrect data types before execution.


What is the Page Object Model (POM)?

The Playwright Page Object Model is a design pattern where every webpage is represented by a separate class.

Instead of writing:

await page.locator(“#username”).fill(“admin”);

inside every test, you create reusable methods.

Example:

Login Page

      │

      ▼

LoginPage.ts

      │

      ▼

login(username,password)

      │

      ▼

Used by all tests

This reduces duplicate code and improves maintainability.


Why Use the Playwright TypeScript Page Object Model?

Advantages include:

  • Cleaner tests
  • Reusable methods
  • Centralized locators
  • Easy maintenance
  • Faster framework updates
  • Enterprise-ready architecture
  • Improved readability
  • Better collaboration among QA teams

Enterprise Playwright Framework Folder Structure

PlaywrightFramework

├── tests

│     login.spec.ts

├── pages

│     LoginPage.ts

│     DashboardPage.ts

├── fixtures

│     baseFixture.ts

├── utils

│     ReadData.ts

├── test-data

│     users.json

├── playwright.config.ts

└── package.json

This structure separates responsibilities and keeps the framework organized.


Creating the First Page Object (LoginPage.ts)

import { Page } from ‘@playwright/test’;

export class LoginPage {

    constructor(private page: Page){}

    username = this.page.locator(“#username”);

    password = this.page.locator(“#password”);

    loginButton = this.page.locator(“#login”);

    async login(user:string,pass:string){

        await this.username.fill(user);

        await this.password.fill(pass);

        await this.loginButton.click();

    }

}

Step-by-Step Explanation

Import Page

import { Page } from ‘@playwright/test’;

Imports the Playwright Page class.


Constructor

constructor(private page: Page){}

Stores the current browser page for later use.


Username Locator

username = this.page.locator(“#username”);

Stores the username textbox locator.


Password Locator

password = this.page.locator(“#password”);

Stores the password textbox.


Login Button

loginButton = this.page.locator(“#login”);

Stores the login button locator.


Login Method

async login(user:string,pass:string){

Reusable login method.

Inside it:

await this.username.fill(user);

Enters username.

await this.password.fill(pass);

Enters password.

await this.loginButton.click();

Clicks Login.

Now every test can simply call:

await loginPage.login(“admin”,”admin123″);


Writing Test Scripts Using POM

import { test } from ‘@playwright/test’;

import { LoginPage } from ‘../pages/LoginPage’;

test(‘Login Test’, async ({ page }) => {

    const loginPage = new LoginPage(page);

    await page.goto(“https://example.com”);

    await loginPage.login(“admin”,”admin123″);

});

Explanation

  • Creates LoginPage object
  • Opens application
  • Calls reusable login method
  • Keeps test readable

Reusable Methods

Instead of writing locators repeatedly:

async enterUsername(username:string){

    await this.username.fill(username);

}

Similarly:

async enterPassword(password:string){

    await this.password.fill(password);

}

Now methods can be reused across hundreds of tests.


Working with Playwright Locators

Examples:

page.locator(“#email”)

ID locator

page.locator(“.login”)

Class locator

page.getByRole(‘button’,{name:’Login’})

Role locator

page.getByText(“Logout”)

Text locator

Best practice is to use semantic locators like getByRole() or stable test IDs when available.


Using Fixtures

Fixtures help reduce duplicate setup code.

Example:

import { test as base } from ‘@playwright/test’;

export const test = base.extend({

});

Fixtures can initialize:

  • Login
  • Browser
  • Test data
  • Database
  • API authentication

This makes the Playwright Automation Framework more scalable.


Playwright Configuration (playwright.config.ts)

import { defineConfig } from ‘@playwright/test’;

export default defineConfig({

    use:{

        headless:true,

        viewport:{

            width:1280,

            height:720

        },

        screenshot:’only-on-failure’,

        video:’retain-on-failure’

    }

});

Explanation

  • headless:true runs tests without opening the browser UI.
  • viewport defines the browser window size.
  • screenshot:’only-on-failure’ captures screenshots when a test fails.
  • video:’retain-on-failure’ stores videos only for failed tests, helping with debugging.

Best Practices for Playwright Page Object Model

  1. Keep locators inside Page Objects.
  2. Avoid duplicate code.
  3. Use reusable methods.
  4. Follow naming conventions.
  5. Use TypeScript interfaces.
  6. Use fixtures.
  7. Keep tests short.
  8. Store test data separately.
  9. Use explicit assertions.
  10. Follow the Single Responsibility Principle.
  11. Create one class per page.
  12. Use stable locators like data-testid.
  13. Group related actions into business methods.
  14. Keep configuration separate.
  15. Generate HTML reports after execution.
  16. Use Git for version control.
  17. Integrate with CI/CD pipelines.
  18. Review and refactor page classes regularly.

Common Mistakes

Avoid these common issues:

  • Writing locators inside test files.
  • Hardcoding usernames and passwords.
  • Creating overly large page classes.
  • Ignoring reusable methods.
  • Using unstable XPath locators.
  • Copy-pasting the same code.
  • Not organizing the project structure.
  • Mixing assertions with page object methods.

Real-Time Enterprise Framework Example

Imagine an e-commerce application.

Pages

HomePage

LoginPage

ProductPage

CartPage

CheckoutPage

OrderPage

Workflow:

Home

 ↓

Login

 ↓

Products

 ↓

Cart

 ↓

Checkout

 ↓

Payment

 ↓

Order Success

Each page has:

  • Locators
  • Business methods
  • Assertions (preferably kept in tests or dedicated helper classes)
  • Reusable actions

This modular approach makes the Enterprise Playwright framework easier to scale as the application grows.


Selenium vs Playwright Page Object Model

FeatureSeleniumPlaywright
Auto WaitNoYes
SpeedMediumFast
Parallel TestingLimitedBuilt-in
Multiple BrowsersYesYes
Mobile TestingLimitedBuilt-in
Network MockingExternal toolsBuilt-in
SetupMore configurationSimple
Modern APIsModerateExcellent

Playwright TypeScript Page Object Model Interview Questions

1. What is Page Object Model?

A design pattern that separates UI locators and actions from test scripts.

2. Why use POM?

To improve code reuse, readability, and maintenance.

3. Why TypeScript?

Type safety, better IDE support, and fewer runtime errors.

4. What is a Locator?

An object used to identify and interact with page elements.

5. Why avoid duplicate locators?

Centralizing locators makes updates easier when the UI changes.

6. What is a Fixture?

Reusable setup code shared across tests.

7. What is auto waiting?

Playwright automatically waits for elements to become actionable before interacting with them.

8. What is getByRole()?

A locator based on accessibility roles, making tests more stable and user-focused.

9. Why separate page classes?

To follow the Single Responsibility Principle and improve maintainability.

10. What is playwright.config.ts?

The central configuration file for browser, reporter, retries, timeouts, and other settings.

11. Can one page object call another?

Yes, when implementing complete business workflows, though dependencies should remain clear.

12. What are fixtures used for?

Browser setup, authentication, shared test data, and environment preparation.

13. How do you make a framework scalable?

Use modular page objects, reusable utilities, fixtures, configuration management, and CI/CD integration.

14. Why avoid hardcoded test data?

It reduces flexibility and makes maintenance harder.

15. How do you organize test data?

Store it in JSON, CSV, or dedicated data providers.

16. What is a business method?

A method that performs a complete user action, such as login() or checkout().

17. What is the advantage of Playwright over Selenium?

Built-in auto waiting, faster execution, and modern automation features.

18. What is headless mode?

Running browser tests without displaying the browser window.

19. How do you debug failed tests?

Use traces, screenshots, videos, logs, and Playwright Inspector.

20. What are the characteristics of a good Page Object?

Reusable, readable, maintainable, and focused on a single page.


FAQs

1. What is the Playwright TypeScript Page Object Model?

A design pattern that organizes locators and page actions into reusable classes.

2. Is Playwright better than Selenium?

For many modern web applications, Playwright offers faster execution and built-in features such as auto waiting and tracing.

3. Is TypeScript mandatory?

No, but it is highly recommended for larger automation projects.

4. Can beginners learn Playwright?

Yes. Its API is simple and well documented.

5. What is the main benefit of POM?

Better maintainability and code reuse.

6. Should every page have its own class?

Yes, in most enterprise frameworks.

7. Can I use POM with API tests?

Yes. You can combine UI page objects with API helper classes.

8. What is the best locator strategy?

Use getByRole(), getByLabel(), or data-testid whenever possible.

9. Is Playwright free?

Yes. Playwright is open source.

10. Is Playwright suitable for enterprise automation?

Yes. It supports parallel execution, CI/CD, multiple browsers, reporting, and advanced debugging.

Leave a Comment

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