CTCaliberTek
Course: Playwright with TypeScript: End to End · Lesson 3 of 9Log in to track your progress and earn a certificate when you finish the course.
Software Testing

Page Object Model in Playwright with TypeScript

Published August 13, 2026·Updated October 29, 2026·8 min read
Like SaveLog in to like, save, and track progress.

Introduction

As a suite grows, repeating locators in every test makes maintenance painful. The Page Object Model (POM) puts a page's locators and actions into one class, so a change to the page means one fix instead of dozens. This lesson builds a page object for the TodoMVC demo app.

Prerequisites

  • Locators and assertions in Playwright
  • TypeScript classes

Step-by-Step Guide

Step 1: Create a page class

Store locators as readonly properties and wrap user actions in methods. Keep assertions in the tests, not the page object, so the class describes the page rather than the expectations.

// tests/pages/todo-page.ts
import { type Page, type Locator } from '@playwright/test';

export class TodoPage {
  readonly page: Page;
  readonly newTodo: Locator;
  readonly titles: Locator;

  constructor(page: Page) {
    this.page = page;
    this.newTodo = page.getByPlaceholder('What needs to be done?');
    this.titles = page.getByTestId('todo-title');
  }

  async goto() {
    await this.page.goto('/todomvc');
  }

  async addTodo(text: string) {
    await this.newTodo.fill(text);
    await this.newTodo.press('Enter');
  }
}

Step 2: Set a base URL

Configure baseURL so the page object can use relative paths and the same tests can target different environments.

// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    baseURL: 'https://demo.playwright.dev',
  },
});

Step 3: Use the page object in a test

The test now reads like a description of the behavior, with no selectors in sight.

import { test, expect } from '@playwright/test';
import { TodoPage } from './pages/todo-page';

test('adds a todo item', async ({ page }) => {
  const todoPage = new TodoPage(page);
  await todoPage.goto();
  await todoPage.addTodo('Buy milk');

  await expect(todoPage.titles).toHaveText(['Buy milk']);
});

Step 4: Keep page objects focused

Create one class per page or significant component. Return another page object from a method when an action navigates to a new page, and avoid putting test logic or hard-coded test data inside them.

FAQs

Should page objects contain assertions?
Most teams keep assertions in tests and only expose locators and actions in page objects. This keeps page objects reusable across tests that expect different outcomes.
Is the Page Object Model required with Playwright?
No. For small suites, plain tests and helper functions are fine. POM pays off as the suite and number of contributors grow.

Summary

A page object centralizes locators and actions for one page, which makes tests short and changes cheap. In the next lesson, fixtures remove the setup boilerplate from every test.

Related tutorials

Comments

Log in or create a free account to join the discussion.

  • No comments yet. Be the first to comment.