mcpField
P
prowler-test-ui

prowler-test-ui

github.com/prowler-cloudテスト・品質15.1k64 回インストール今日更新
リポジトリ

prowler-test-ui について

prowler-test-uiは、ProwlerのUIエンドツーエンドテスト向けスキルです。プロジェクト固有のPlaywright規約を示し、テストとMarkdown文書の同期や、作成前のMCPツールによる実画面の確認を重視します。

主な機能

  1. 01UIテストのディレクトリー構成
  2. 02テストと文書の同期要件
  3. 03作成前のページ探索
  4. 04待機とナビゲーション検証の規約
  5. 05テストタグとコマンドの指定

活用シーン

  1. 01Prowler画面のエンドツーエンドテスト追加
  2. 02テスト変更に伴うケース文書の更新
  3. 03実際の画面構造に基づくテスト作成

MCP 対応

テスト作成前にPlaywright MCPツールで対象ページへ移動し、スナップショットの確認と要素の操作を行って、実際の構造やセレクターを確かめる手順を示します。

インストール

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

$npx skills add https://github.com/prowler-cloud/prowler --skill prowler-test-ui

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

同梱ファイルreferences/e2e-docs.md

詳細

一般的なパターン:Page Object Model、セレクター、ヘルパーなどの基本的な Playwright パターンについては、playwright スキルを参照してください。 このスキルでは Prowler 固有の規約のみを扱います。

Prowler UI テストの構成

ui/tests/
├── base-page.ts              # Prowler-specific base page
├── helpers.ts                # Prowler test utilities
└── {page-name}/
    ├── {page-name}-page.ts   # Page Object Model
    ├── {page-name}.spec.ts   # ALL tests (single file per feature)
    └── {page-name}.md        # Test documentation (MANDATORY - sync with spec.ts)

必須チェックリスト(テストの作成または変更)

⚠️ E2E タスクを完了する前に、必ず確認してください:

新しいテストを作成する場合
  • {page-name}-page.ts - Page Object を作成または更新する
  • {page-name}.spec.ts - 正しいタグ(@TEST-ID)を付けてテストを追加する
  • {page-name}.md - すべてのテストケースを含むドキュメントを作成する
  • .md のテスト ID が .spec.ts のタグと一致している
既存のテストを変更する場合
  • 次の場合、{page-name}.md を必ず更新する:
    • テストケースを追加または削除した
    • テストフロー(手順)を変更した
    • 前提条件または期待される結果を変更した
    • タグまたは優先度を変更した
  • .md と .spec.ts のテスト ID が同期している
簡易検証
# Verify .md exists for each test folder
ls ui/tests/{feature}/{feature}.md

# Verify test IDs match
grep -o "@[A-Z]*-E2E-[0-9]*" ui/tests/{feature}/{feature}.spec.ts | sort -u
grep -o "\`[A-Z]*-E2E-[0-9]*\`" ui/tests/{feature}/{feature}.md | sort -u

重要

❌ 対応する .md ファイルを更新しない限り、E2E の変更は完了したとは見なされません。


MCP ワークフロー - 重要

⚠️ 必須:Playwright MCP ツールが利用可能な場合は、テストを作成する前に必ず使用してください。

  1. 対象ページに移動する
  2. 実際の DOM 構造を確認するためにスナップショットを取得する
  3. 実際のフローを確認するためにフォームや要素を操作する
  4. スナップショットから実際のセレクターを記録する
  5. その後でテストコードを書く

理由:推測に基づくテストを防ぎます。実際に調査することで、安定したテストを作成できます。


待機戦略(重要)

⚠️ networkidle は絶対に使用しないでください。テストが不安定になります!

戦略用途
❌ networkidle絶対に使用しない - ポーリングや WebSocket で不安定になります
⚠️ loadどうしても必要な場合のみ
✅ expect(element).toBeVisible()推奨 - 特定の UI 状態を待機します
✅ page.waitForURL()ページ遷移を待機します
✅ pageObject.verifyPageLoaded()最適 - 検証をカプセル化します

良い例:

await homePage.verifyPageLoaded();
await expect(page).toHaveURL("/dashboard");
await expect(page.getByRole("heading", { name: "Overview" })).toBeVisible();

悪い例:

await page.waitForLoadState("networkidle"); // ❌ FLAKY
await page.waitForTimeout(2000);            // ❌ ARBITRARY WAIT

Prowler 基本ページ

import { Page, Locator, expect } from "@playwright/test";

export class BasePage {
  constructor(protected page: Page) {}

  async goto(path: string): Promise<void> {
    await this.page.goto(path);
    // Child classes should override verifyPageLoaded() to wait for specific elements
  }

  // Override in child classes to wait for page-specific elements
  async verifyPageLoaded(): Promise<void> {
    await expect(this.page.locator("main")).toBeVisible();
  }

  // Prowler-specific: notification handling
  async waitForNotification(): Promise<Locator> {
    const notification = this.page.locator('[role="status"]');
    await notification.waitFor({ state: "visible" });
    return notification;
  }

  async verifyNotificationMessage(message: string): Promise<void> {
    const notification = await this.waitForNotification();
    await expect(notification).toContainText(message);
  }
}

ページ遷移の検証パターン

⚠️ URL のアサーションは Page Object に記述し、テストには記述しないでください!

リダイレクトやページ遷移を検証する場合は、遷移先の Page Object に専用のメソッドを作成します。

// ✅ GOOD - In SignInPage
async verifyOnSignInPage(): Promise<void> {
  await expect(this.page).toHaveURL(/\/sign-in/);
  await expect(this.pageTitle).toBeVisible();
}

// ✅ GOOD - In test
await homePage.goto();  // Try to access protected route
await signInPage.verifyOnSignInPage();  // Verify redirect

// ❌ BAD - Direct assertions in test
await homePage.goto();
await expect(page).toHaveURL(/\/sign-in/);  // Should be in Page Object
await expect(page.getByText("Sign in")).toBeVisible();

命名規則: リダイレクト検証メソッドには verifyOn{PageName}Page() を使用します。


Prowler 固有のページ

プロバイダーページ
import { BasePage } from "../base-page";

export class ProvidersPage extends BasePage {
  readonly addButton = this.page.getByRole("button", { name: "Add Provider" });
  readonly providerTable = this.page.getByRole("table");

  async goto(): Promise<void> {
    await super.goto("/providers");
  }

  async addProvider(type: string, alias: string): Promise<void> {
    await this.addButton.click();
    await this.page.getByLabel("Provider Type").selectOption(type);
    await this.page.getByLabel("Alias").fill(alias);
    await this.page.getByRole("button", { name: "Create" }).click();
  }
}
スキャンページ
export class ScansPage extends BasePage {
  readonly newScanButton = this.page.getByRole("button", { name: "New Scan" });
  readonly scanTable = this.page.getByRole("table");

  async goto(): Promise<void> {
    await super.goto("/scans");
  }

  async startScan(providerAlias: string): Promise<void> {
    await this.newScanButton.click();
    await this.page.getByRole("combobox", { name: "Provider" }).click();
    await this.page.getByRole("option", { name: providerAlias }).click();
    await this.page.getByRole("button", { name: "Start Scan" }).click();
  }
}

Prowler のテストタグ

test("Provider CRUD operations",
  { tag: ["@critical", "@e2e", "@providers", "@PROV-E2E-001"] },
  async ({ page }) => {
    // ...
  }
);
カテゴリータグ
優先度@critical、@high、@medium、@low
種類@e2e、@smoke、@regression
機能@providers、@scans、@findings、@compliance、@signin、@signup
テスト ID@PROV-E2E-001、@SCAN-E2E-002

Prowler テストドキュメントのテンプレート

60 行以内に収めてください。フロー、前提条件、期待される結果のみに重点を置いてください。

### E2E Tests: {Feature Name}

**Suite ID:** `{SUITE-ID}`
**Feature:** {Feature description}

---

## Test Case: `{TEST-ID}` - {Test case title}

**Priority:** `{critical|high|medium|low}`
**Tags:** @e2e, @{feature-name}

**Preconditions:**
- {Prerequisites}

### Flow Steps:
1. {Step}
2. {Step}

### Expected Result:
- {Outcome}

### Key Verification Points:
- {Assertion}

コマンド

cd ui && pnpm run test:e2e                              # All tests
cd ui && pnpm run test:e2e tests/providers/             # Specific folder
cd ui && pnpm run test:e2e --grep "provider"            # By pattern
cd ui && pnpm run test:e2e:ui                           # With UI
cd ui && pnpm run test:e2e:debug                        # Debug mode
cd ui && pnpm run test:e2e:headed                       # See browser
cd ui && pnpm run test:e2e:report                       # Generate report

リソース

  • ドキュメント:ローカルの開発者ガイドへのリンクについては、references/ を参照してください。

コメント