mcpField
P
playwright-skill

playwright-skill

github.com/sickn33テスト・品質48.7k3.9k 回インストール1 日前に更新
リポジトリ

playwright-skill について

playwright-skill は、カスタム Playwright スクリプトを作成して実行するブラウザー自動化スキルです。ローカルサーバーの検出、一時スクリプトの扱い、可視ブラウザーでの実行手順を案内します。

主な機能

  1. 01ローカルサーバーの自動検出
  2. 02/tmp でのカスタム Playwright スクリプト作成
  3. 03可視ブラウザーでのデフォルト実行
  4. 04対象 URL とヘッダーの設定
  5. 05ブラウザー操作用ヘルパー

活用シーン

  1. 01ローカルページを複数のビューポートでテスト
  2. 02ログインリダイレクトやフォーム送信を確認
  3. 03リンクを調べてスクリーンショットを撮影
  4. 04許可されたサイトでブラウザー作業を自動化

インストール

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

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill playwright-skill

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

API_REFERENCE.md
package.json
run.js
lib/
helpers.js

詳細

重要 - パスの解決: このスキルは、プラグインシステム、手動インストール、グローバル、プロジェクト固有など、さまざまな場所にインストールできます。コマンドを実行する前に、この SKILL.md ファイルを読み込んだ場所を基にスキルディレクトリを特定し、以下のすべてのコマンドでそのパスを使用してください。$SKILL_DIR を実際に特定したパスに置き換えてください。

一般的なインストールパス:

  • プラグインシステム:<plugin-root>/skills/playwright-skill
  • 手動でのグローバルインストール:<agent-home>/skills/playwright-skill
  • プロジェクト固有:<project>/.agent/skills/playwright-skill

Playwright ブラウザー自動化

汎用ブラウザー自動化スキルです。ご依頼いただいた自動化タスクに合わせてカスタムの Playwright コードを作成し、ユニバーサルエグゼキューターで実行します。

重要なワークフロー - 次の手順を順番どおりに実行してください:

  1. 開発サーバーを自動検出する - localhost のテストでは、必ず最初にサーバー検出を実行してください:

    cd "$SKILL_DIR" && node -e "require('./lib/helpers').detectDevServers().then(servers => console.log(JSON.stringify(servers)))"
    
    • サーバーが1つ見つかった場合:自動的に使用し、ユーザーに伝えます
    • 複数のサーバーが見つかった場合:どれをテストするかユーザーに尋ねます
    • サーバーが見つからなかった場合:URL を尋ねるか、開発サーバーの起動を支援することを提案します
  2. スクリプトを /tmp に書き込む - スキルディレクトリにテストファイルを書き込まないでください。必ず /tmp/playwright-test-*.js を使用してください

  3. デフォルトで表示ブラウザーを使用する - ユーザーからヘッドレスモードを明示的に求められない限り、常に headless: false を使用してください

  4. URL をパラメーター化する - スクリプトの先頭にある環境変数または定数で、常に URL を設定できるようにしてください

範囲とデータの境界

エグゼキューターは、現在のアカウントのファイルシステム、環境、ネットワーク権限を使って任意の Node コードを実行します。サンドボックスではありません。生成されたコードを確認し、ページのコンテンツは実行されない状態にしてください。テストアカウントとフィクスチャを使用してください。localhost のポートが見つかっても、その背後にあるアプリケーションや所有者が特定されるわけではありません。ナビゲーション、アップロード、メッセージ送信、購入、その他の変更は、ユーザーが許可した範囲に限定してください。汎用の「Accept」/「OK」ボタンではなく、明示的な Cookie の設定を使用してください。スクリーンショット、トレース、セッション状態には、認証情報や個人データが含まれる場合があります。コンテキスト全体に適用されるヘッダーは、そのコンテキスト内のすべての宛先に送信されます。信頼できないリソースを含むページで、この機能を使って秘密情報を送信しないでください。認証は、信頼できるオリジンに限定してください。

動作の仕組み

  1. テスト/自動化したい内容を説明します
  2. 実行中の開発サーバーを自動検出します(外部サイトをテストする場合は URL を尋ねます)
  3. カスタムの Playwright コードを /tmp/playwright-test-*.js に書き込みます(プロジェクトが散らかることはありません)
  4. 次のコマンドで実行します:cd "$SKILL_DIR" && node run.js /tmp/playwright-test-*.js
  5. 結果はリアルタイムで表示され、デバッグ用にブラウザーウィンドウも表示されます
  6. 確認後、スクリプト、スクリーンショット、保存したセッションを削除してください。OS による一時ファイルのクリーンアップは、保持されないことを保証するものではありません。

セットアップ(初回)

cd "$SKILL_DIR"
npm run setup

Node 22 以降が必要です。最初にパッケージのインストール内容を確認してください。セットアップでは依存関係とブラウザーがダウンロードされ、パッケージのライフサイクルコードが実行される場合があります。インストール済みの Playwright バージョンで必要になった場合は、ブラウザーを再インストールしてください。エグゼキューターは不足しているパッケージを黙ってインストールすることはありません。

実行パターン

ステップ1:開発サーバーを検出する(localhost のテスト用)

cd "$SKILL_DIR" && node -e "require('./lib/helpers').detectDevServers().then(s => console.log(JSON.stringify(s)))"

ステップ2:URL パラメーターを含むテストスクリプトを /tmp に書き込む

// /tmp/playwright-test-page.js
const { chromium } = require('playwright');

// Parameterized URL (detected or user-provided)
const TARGET_URL = 'http://localhost:3001'; // <-- Auto-detected or from user

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(TARGET_URL);
  console.log('Page loaded:', await page.title());

  await page.screenshot({ path: '/tmp/screenshot.png', fullPage: true });
  console.log('📸 Screenshot saved to /tmp/screenshot.png');

  await browser.close();
})();

ステップ3:スキルディレクトリから実行する

cd "$SKILL_DIR" && node run.js /tmp/playwright-test-page.js

よく使うパターン

ページをテストする(複数のビューポート)
// /tmp/playwright-test-responsive.js
const { chromium } = require('playwright');

const TARGET_URL = 'http://localhost:3001'; // Auto-detected

(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 100 });
  const page = await browser.newPage();

  // Desktop test
  await page.setViewportSize({ width: 1920, height: 1080 });
  await page.goto(TARGET_URL);
  console.log('Desktop - Title:', await page.title());
  await page.screenshot({ path: '/tmp/desktop.png', fullPage: true });

  // Mobile test
  await page.setViewportSize({ width: 375, height: 667 });
  await page.screenshot({ path: '/tmp/mobile.png', fullPage: true });

  await browser.close();
})();
ログインフローをテストする
// /tmp/playwright-test-login.js
const { chromium } = require('playwright');

const TARGET_URL = 'http://localhost:3001'; // Auto-detected

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(`${TARGET_URL}/login`);

  await page.fill('input[name="email"]', '[email protected]');
  await page.fill('input[name="password"]', 'password123');
  await page.click('button[type="submit"]');

  // Wait for redirect
  await page.waitForURL('**/dashboard');
  console.log('✅ Login successful, redirected to dashboard');

  await browser.close();
})();
フォームに入力して送信する
// /tmp/playwright-test-form.js
const { chromium } = require('playwright');

const TARGET_URL = 'http://localhost:3001'; // Auto-detected

(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 50 });
  const page = await browser.newPage();

  await page.goto(`${TARGET_URL}/contact`);

  await page.fill('input[name="name"]', 'John Doe');
  await page.fill('input[name="email"]', '[email protected]');
  await page.fill('textarea[name="message"]', 'Test message');
  await page.click('button[type="submit"]');

  // Verify submission
  await page.waitForSelector('.success-message');
  console.log('✅ Form submitted successfully');

  await browser.close();
})();
リンク切れを確認する
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto('http://localhost:3000');

  const links = await page.locator('a[href^="http"]').all();
  const results = { working: 0, broken: [] };

  for (const link of links) {
    const href = await link.getAttribute('href');
    try {
      const response = await page.request.head(href);
      if (response.ok()) {
        results.working++;
      } else {
        results.broken.push({ url: href, status: response.status() });
      }
    } catch (e) {
      results.broken.push({ url: href, error: e.message });
    }
  }

  console.log(`✅ Working links: ${results.working}`);
  console.log(`❌ Broken links:`, results.broken);

  await browser.close();
})();
エラー処理付きでスクリーンショットを撮る
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  try {
    await page.goto('http://localhost:3000', {
      waitUntil: 'domcontentloaded',
      timeout: 10000,
    });

    await page.screenshot({
      path: '/tmp/screenshot.png',
      fullPage: true,
    });

    console.log('📸 Screenshot saved to /tmp/screenshot.png');
  } catch (error) {
    console.error('❌ Error:', error.message);
  } finally {
    await browser.close();
  }
})();
レスポンシブデザインをテストする
// /tmp/playwright-test-responsive-full.js
const { chromium } = require('playwright');

const TARGET_URL = 'http://localhost:3001'; // Auto-detected

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  const viewports = [
    { name: 'Desktop', width: 1920, height: 1080 },
    { name: 'Tablet', width: 768, height: 1024 },
    { name: 'Mobile', width: 375, height: 667 },
  ];

  for (const viewport of viewports) {
    console.log(
      `Testing ${viewport.name} (${viewport.width}x${viewport.height})`,
    );

    await page.setViewportSize({
      width: viewport.width,
      height: viewport.height,
    });

    await page.goto(TARGET_URL);
    await page.waitForTimeout(1000);

    await page.screenshot({
      path: `/tmp/${viewport.name.toLowerCase()}.png`,
      fullPage: true,
    });
  }

  console.log('✅ All viewports tested');
  await browser.close();
})();

インライン実行(簡単なタスク)

簡単な単発タスクでは、ファイルを作成せずにコードをインラインで実行できます:

# Take a quick screenshot
cd "$SKILL_DIR" && node run.js "
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('http://localhost:3001');
await page.screenshot({ path: '/tmp/quick-screenshot.png', fullPage: true });
console.log('Screenshot saved');
await browser.close();
"

インライン実行とファイルの使い分け:

  • インライン:簡単な単発タスク(スクリーンショット、要素の有無の確認、ページタイトルの取得)
  • ファイル:複雑なテスト、レスポンシブデザインのチェック、ユーザーが再実行する可能性のあるタスク

利用可能なヘルパー

lib/helpers.js にオプションのユーティリティ関数があります:

const helpers = require('./lib/helpers');

// Detect running dev servers (CRITICAL - use this first!)
const servers = await helpers.detectDevServers();
console.log('Found servers:', servers);

// Safe click with retry
await helpers.safeClick(page, 'button.submit'); // one action; do not blindly retry submissions

// Safe type with clear
await helpers.safeType(page, '#username', 'testuser');

// Take timestamped screenshot
await helpers.takeScreenshot(page, 'test-result');

// Handle cookie banners
await helpers.handleCookieBanner(page, '[data-testid="cookie-reject"]'); // only if rejection was requested

// Extract table data
const data = await helpers.extractTableData(page, 'table.results');

一覧については lib/helpers.js を参照してください。

カスタム HTTP ヘッダー

環境変数を使用して、すべての HTTP リクエストにカスタムヘッダーを設定できます。次のような用途に便利です。

  • バックエンドへの自動化されたトラフィックを識別する
  • LLM に最適化されたレスポンスを取得する(例:スタイル付き HTML ではなくプレーンテキストのエラー)
  • 認証トークンをグローバルに追加する
設定

単一のヘッダー(一般的なケース):

cd "$SKILL_DIR" && PW_HEADER_NAME=X-Automated-By PW_HEADER_VALUE=playwright-skill \
  node run.js /tmp/my-script.js

複数のヘッダー(JSON 形式):

cd "$SKILL_DIR" && PW_EXTRA_HEADERS='{"X-Automated-By":"playwright-skill","X-Debug":"true"}' \
  node run.js /tmp/my-script.js
適用範囲とデータの境界

executor は、現在のアカウントのファイルシステム、環境、ネットワーク権限で任意の Node コードを実行します。サンドボックスではありません。生成されたコードを確認し、ページのコンテンツは不活性な状態に保ってください。テスト用アカウントとフィクスチャを使用してください。localhost のポートが見つかっても、その背後にあるアプリケーションや所有者が特定されるわけではありません。ナビゲーション、アップロード、メッセージの送信、購入、その他の変更は、ユーザーが許可した範囲に制限してください。一般的な Accept/OK ボタンではなく、明示的な Cookie の設定を選択してください。スクリーンショット、トレース、セッション状態には、認証情報や個人データが含まれる場合があります。コンテキスト全体に適用されるヘッダーは、そのコンテキスト内のすべての宛先に送信されます。この機能を、信頼できないリソースを含むページ上で秘密情報に使用しないでください。認証は、信頼できるオリジンに限定してください。

仕組み

helpers.createContext() を使用すると、ヘッダーが自動的に適用されます。

const context = await helpers.createContext(browser);
const page = await context.newPage();
// All requests from this page include your custom headers

Playwright の生の API を使用するスクリプトでは、注入された getContextOptionsWithHeaders() を使用してください。

const context = await browser.newContext(
  getContextOptionsWithHeaders({ viewport: { width: 1920, height: 1080 } }),
);

高度な使い方

Playwright API の包括的なドキュメントについては、API_REFERENCE.md を参照してください。

  • セレクターとロケーターのベストプラクティス
  • ネットワークのインターセプトと API モック
  • 認証とセッション管理
  • ビジュアルリグレッションテスト
  • モバイルデバイスのエミュレーション
  • パフォーマンステスト
  • デバッグ手法
  • CI/CD との統合

ヒント

  • 重要:最初にサーバーを検出する - localhost のテストコードを書く前に、必ず detectDevServers() を実行してください
  • カスタムヘッダー - PW_HEADER_NAME/PW_HEADER_VALUE 環境変数を使用して、バックエンドへの自動化されたトラフィックを識別してください
  • テストファイルには /tmp を使用する - /tmp/playwright-test-*.js に書き込み、スキルディレクトリやユーザーのプロジェクトには絶対に書き込まないでください
  • URL をパラメーター化する - 検出または指定した URL を、すべてのスクリプトの先頭にある TARGET_URL 定数に設定してください
  • デフォルト:ブラウザーを表示する - ユーザーがヘッドレスモードを明示的に求めない限り、常に headless: false を使用してください
  • ヘッドレスモード - ユーザーが「headless」または「background」での実行を明示的に要求した場合にのみ、headless: true を使用してください
  • 速度を落とす: slowMo: 100 を使用して、操作を見やすく、追いやすくしてください
  • 待機方法: 固定タイムアウトではなく、waitForURL、waitForSelector、waitForLoadState を使用してください
  • エラー処理: 堅牢な自動化のため、必ず try-catch を使用してください
  • コンソール出力: console.log() を使用して進行状況を記録し、実行内容を表示してください

トラブルシューティング

Playwright がインストールされていない場合:

cd "$SKILL_DIR" && npm run setup

モジュールが見つからない場合: run.js ラッパーを使用し、スキルディレクトリから実行してください

ブラウザーが開かない場合: headless: false を確認し、ディスプレイが利用可能であることを確認してください

要素が見つからない場合: 待機を追加してください:await page.waitForSelector('.element', { timeout: 10000 })

使用例

User: "Test if the marketing page looks good"

Claude: I'll test the marketing page across multiple viewports. Let me first detect running servers...
[Runs: detectDevServers()]
[Output: Found server on port 3001]
I found your dev server running on http://localhost:3001

[Writes custom automation script to /tmp/playwright-test-marketing.js with URL parameterized]
[Runs: cd "$SKILL_DIR" && node run.js /tmp/playwright-test-marketing.js]
[Shows results with screenshots from /tmp/]
User: "Check if login redirects correctly"

Claude: I'll test the login flow. First, let me check for running servers...
[Runs: detectDevServers()]
[Output: Found servers on ports 3000 and 3001]
I found 2 dev servers. Which one should I test?
- http://localhost:3000
- http://localhost:3001

User: "Use 3001"

[Writes login automation to /tmp/playwright-test-login.js]
[Runs: cd "$SKILL_DIR" && node run.js /tmp/playwright-test-login.js]
[Reports: ✅ Login successful, redirected to /dashboard]

注記

  • 各自動化は、具体的なリクエストに合わせて個別に作成されます
  • 自動化は、許可範囲、利用可能なブラウザーサポート、サイトの動作、インストール済みの依存関係によって制限されます
  • 実行中の開発サーバーを自動検出し、URL のハードコードを不要にします
  • プライベートで一意な一時ディレクトリを使用し、機密性の高い成果物は明示的に削除してください
  • executor は、依存関係を解決するため、CommonJS コードをスキルディレクトリ内のプライベートモードの一意なファイルにコピーします。相対インポートは入力スクリプトの隣ではなく、その場所を基準に解決されます。正常終了時にはその呼び出しで作成したファイルのみを削除します。クラッシュするとファイルが残ることがあります。
  • 段階的な情報開示 - 高度な機能が必要な場合にのみ API_REFERENCE.md が読み込まれます

使用するタイミング

このスキルは、概要で説明されているワークフローまたはアクションを実行する場合に適用できます。

制限事項

  • API リファレンスでは、単独の playwright スクリプトと、別個の @playwright/test および axe-playwright プロジェクトが混在しています。セットアップでインストールされるのは単独のライブラリのみです。ランナーの例を使用する前に、対象のテストプロジェクトにテストランナーの依存関係をインストールしてください。
  • リンクチェックの結果は HTTP 上の観測結果であり、リンク切れの証明ではありません。HEAD がサポートされていない場合や、認証に依存する場合があります。チェック対象は承認済みのオリジンに限定し、件数と時間に上限を設け、認証情報を使ったクロスオリジンリクエストは避けてください。
  • require() を含むスクリプトでは、ラッパーは getContextOptionsWithHeaders を注入しません。ヘルパーを明示的にインポートしてください。ブラウザーとコンテキストは必ず finally で閉じ、エラーを伝播させてください。
  • このスキルは、タスクが上記の範囲に明確に合致する場合にのみ使用してください。
  • 出力を、環境固有の検証、テスト、または専門家によるレビューの代わりとして扱わないでください。
  • 必要な入力、権限、安全上の境界、または成功基準が不足している場合は、作業を中断して確認を求めてください。

コメント