Back to Skills

playwright-page-object-model

verified

Use when creating page objects or refactoring Playwright tests for better maintainability with Page Object Model patterns.

View on GitHub

Marketplace

han

TheBushidoCollective/han

Plugin

jutsu-playwright

Technique

Repository

TheBushidoCollective/han
60stars

jutsu/jutsu-playwright/skills/playwright-page-object-model/SKILL.md

Last Verified

January 24, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/TheBushidoCollective/han/blob/main/jutsu/jutsu-playwright/skills/playwright-page-object-model/SKILL.md -a claude-code --skill playwright-page-object-model

Installation paths:

Claude
.claude/skills/playwright-page-object-model/
Powered by add-skill CLI

Instructions

# Playwright Page Object Model

Master the Page Object Model (POM) pattern to create maintainable, reusable,
and scalable test automation code. This skill covers modern Playwright
patterns including component-based architecture, locator strategies, and
app actions.

## Core POM Principles

### Single Responsibility

Each page object should represent one page or component with a single,
well-defined responsibility.

### Encapsulation

Hide implementation details and expose only meaningful actions and
assertions.

### Reusability

Create reusable components that can be composed into larger page objects.

### Maintainability

When UI changes, update page objects in one place rather than across
multiple tests.

## Basic Page Object Pattern

### Simple Page Object

```typescript
// pages/login-page.ts
import { Page, Locator } from '@playwright/test';

export class LoginPage {
  readonly page: Page;
  readonly emailInput: Locator;
  readonly passwordInput: Locator;
  readonly loginButton: Locator;
  readonly errorMessage: Locator;

  constructor(page: Page) {
    this.page = page;
    this.emailInput = page.getByLabel('Email');
    this.passwordInput = page.getByLabel('Password');
    this.loginButton = page.getByRole('button', { name: 'Login' });
    this.errorMessage = page.getByRole('alert');
  }

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

  async login(email: string, password: string) {
    await this.emailInput.fill(email);
    await this.passwordInput.fill(password);
    await this.loginButton.click();
  }

  async getErrorMessage() {
    return await this.errorMessage.textContent();
  }
}
```

### Using Page Object in Tests

```typescript
// tests/login.spec.ts
import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/login-page';

test.describe('Login', () => {
  test('should login successfully', async ({ page }) => {
    const loginPage = new LoginPage(page);
    await loginPage.goto();
    await loginPage.login('user@exa

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
18700 chars