mcpField
C
create-pom

create-pom

github.com/agentmantisテスト・品質12121 回インストール29 週間前に更新
リポジトリ

create-pom について

Playwright の E2E テスト用に TypeScript の Page Object Model クラスを生成するスキルです。既存 POM の確認、ベースページの継承、生成結果の検証を支援します。

主な機能

  1. 01既存ページオブジェクトの確認
  2. 02共有ベースページの継承
  3. 03セレクター優先順位の適用
  4. 04JSDoc による公開メソッドの記述
  5. 05TypeScript コンパイルの確認

活用シーン

  1. 01新しいアプリページ用の POM 作成
  2. 02既存 POM への動作追加
  3. 03テスト規約に沿ったページオブジェクトの維持

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/agentmantis/test-skills --skill create-pom

インストール後、Claude Code で/create-pomを入力して読み込まれたか確認します。

同梱ファイルreferences/pom-template.md

詳細

ページオブジェクトモデルの作成

すべての E2E テストの規約に従って、指定されたページ用の POM クラスを生成します。


ワークフロー

  1. ユーザーのリクエストからページ名を判断します(例:「Settings」→ settings.page.ts)
  2. e2e/poms/ にこのページの POM がすでにあるか確認します。ある場合は、既存の POM にメソッドを追加し、同じページ用の POM を新たに作成しないでください
  3. e2e/poms/base.page.ts にあるベースページクラスを特定し、それを継承します
  4. アプリケーションで対象のページを読み込み、要素と操作を把握します
  5. 以下のテンプレートに従って POM ファイルを生成します
  6. ファイルを検証し、TypeScript エラーがないことを確認します

ルール

  • 1 ページにつき POM は 1 つ — 個別のページ/ビューごとに、POM ファイルを必ず 1 つだけ作成します
  • すべての POM はベースページクラスを継承します — 抽象クラスについては e2e/poms/base.page.ts を確認してください
  • setUp() と tearDown() を実装します — これらはベースクラスから継承します
  • 再利用可能なヘルパーは BasePage に記述します — 複数の POM で役立つヘルパーメソッド(例:waitForToast、dismissModal)は、派生 POM ではなく BasePage に置く必要があります。派生 POM には、そのページ固有の動作だけを記述してください。同じヘルパーを 2 つ目の POM に書く必要が出てきた場合は、直ちに BasePage に移してください
  • POM 内から別の POM を絶対に参照しないでください — テストで複数のページが必要な場合は、spec ファイルで各 POM の処理を調整します
  • すべてのパブリックメソッドに詳細な JSDoc を記述します — 実行手順を段階ごとに説明し、@param タグを付けてください
  • セレクターの優先順位を使用します:getByRole() > getByLabel() > getByText() > getByPlaceholder() > locator()

POM の構成

コメントバナーを使用して、各 POM を以下の明確に分けられたセクションで構成します。

import { Page, Locator, expect } from '@playwright/test';
// TODO: Import your project's base page class
import { BasePage } from './base.page';

export class FeaturePage extends BasePage {
    constructor(page: Page) {
        super(page);
    }

    // ==========================================
    // LIFECYCLE (from BasePage)
    // ==========================================

    /**
     * Navigates to the feature page and cleans up any stale data
     * left by previous failed test runs.
     *
     * Steps:
     * 1. Navigates to /feature via direct URL.
     * 2. Waits for the page heading to be visible.
     * 3. Deletes any items matching the test data pattern.
     */
    async setUp(): Promise<void> {
        // TODO: Implement navigation and cleanup
    }

    /**
     * Cleans up any data created during the test suite.
     *
     * Steps:
     * 1. Navigates to /feature.
     * 2. Deletes all items created by this test run.
     */
    async tearDown(): Promise<void> {
        // TODO: Implement cleanup
    }

    // ==========================================
    // LOCATORS
    // ==========================================

    /** The main heading of the feature page. */
    get heading(): Locator {
        return this.page.getByRole('heading', { name: 'Feature Name' });
    }

    /** The "Create" button that opens the creation modal. */
    get createButton(): Locator {
        return this.page.getByRole('button', { name: /create/i });
    }

    // TODO: Add locators for all interactive elements on this page

    // ==========================================
    // NAVIGATION
    // ==========================================

    /**
     * Navigates directly to the feature page via URL.
     *
     * Steps:
     * 1. Calls page.goto('/feature').
     * 2. Asserts the page heading is visible.
     * 3. Asserts the URL contains '/feature'.
     */
    async navigateToPage(): Promise<void> {
        await this.page.goto('/feature');
        await expect(this.heading).toBeVisible();
        await expect(this.page).toHaveURL(/\/feature/);
    }

    // ==========================================
    // VERIFICATION
    // ==========================================

    /**
     * Verifies an item appears in the list with the expected name.
     *
     * Steps:
     * 1. Locates the item row by name text.
     * 2. Asserts the row is visible.
     *
     * @param name - The expected item name
     */
    async verifyItemExists(name: string): Promise<void> {
        await expect(
            this.page.getByRole('row', { name: new RegExp(name, 'i') })
        ).toBeVisible();
    }

    // ==========================================
    // CREATE
    // ==========================================

    /**
     * Creates a new item via the creation modal.
     *
     * Steps:
     * 1. Clicks the "Create" button to open the modal.
     * 2. Fills in the name field.
     * 3. Clicks "Submit" and waits for the modal to close.
     *
     * @param name - Display name for the new item
     */
    async createItem(name: string): Promise<void> {
        await this.createButton.click();
        const modal = this.page.getByRole('dialog');
        await modal.getByLabel('Name').fill(name);
        await modal.getByRole('button', { name: 'Submit' }).click();
        await expect(modal).toBeHidden();
    }

    // ==========================================
    // EDIT
    // ==========================================

    // TODO: Add edit methods

    // ==========================================
    // DELETE
    // ==========================================

    // TODO: Add delete methods
}

JSDoc の要件

すべてのパブリックメソッドに、以下を含む JSDoc コメントを必ず付けてください。

  1. 概要行 — メソッドの動作
  2. 手順ブロック — 呼び出し時に実行される処理を番号付きリストで記載
  3. @param タグ — すべてのパラメーターに記載
  4. @returns タグ — 値を返す場合に記載

LLM はこれらのコメントを読んで利用可能な操作を把握し、そこからテスト spec を生成するため、これは非常に重要です。

/**
 * Updates an existing item's name and value.
 *
 * Steps:
 * 1. Locates the item row by its current name.
 * 2. Clicks the "Edit" button within that row.
 * 3. Clears and fills the name field with the new name.
 * 4. Clears and fills the value field with the new value.
 * 5. Clicks "Save" and waits for the edit modal to close.
 * 6. Waits for the success toast notification to appear.
 *
 * @param currentName - The item's current display name (used to locate the row)
 * @param newName     - The new display name
 * @param newValue    - The new value
 */
async editItem(currentName: string, newName: string, newValue: string): Promise<void> {

命名規則

  • ファイル:e2e/poms/{feature}.page.ts(小文字、ケバブケースの feature 名)
  • クラス:{Feature}Page(パスカルケース)
  • feature 名は、対応する spec ファイルおよび test-data ファイルと一致させます

完全なボイラープレートについては、references/pom-template.md を参照してください。

コメント