diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 4ebcfc4..10db5a5 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -8,7 +8,7 @@ { "name": "ndf", "source": "./plugins/ndf", - "description": "All-in-one plugin (v4.0.0): 8 specialized agents, 33 skills (PR/review workflows, principles, data analysis, Codex CLI integration, skill usage stats), SessionStart hook (transcript retention >= 90 days), Stop hook (AI-summarized Slack notifications). Codex CLI is invoked via /ndf:codex skill or corder agent (MCP server removed in v4.0.0)." + "description": "All-in-one plugin (v4.10.0): 8 specialized agents (model-tiered), 46 skills including pytest-playwright E2E testing (7 focused skills: test-planning, script-creation, execution, report, kit-ops, browser-connect, evidence-drive), CDP remote browser support, Google Drive evidence archival, PR/review workflows, principles, data analysis, Codex/Gemini CLI integration, skill usage stats. SessionStart hook (transcript retention >= 90 days), Stop hook (AI-summarized Slack notifications)." }, { "name": "affaan-m", diff --git a/plugins/ndf/.claude-plugin/plugin.json b/plugins/ndf/.claude-plugin/plugin.json index 4a249f5..084911d 100644 --- a/plugins/ndf/.claude-plugin/plugin.json +++ b/plugins/ndf/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "ndf", - "version": "4.9.0", - "description": "Integrated plugin with 8 specialized agents (model-tiered: opus/sonnet/haiku), 44 skills including official mcp-builder, on-demand loader for Anthropic official skills, generic workflow/principle skills, skill usage statistics, pytest-playwright E2E testing split into 5 focused skills (test-planning, script-creation, execution, report, kit-ops) + orchestrator with video-by-default evidence, Google Drive/Chat integration, and Codex CLI integration via /ndf:codex skill. Transcript retention is automatically kept at >= 90 days. Serena MCP is a separate plugin (mcp-serena).", + "version": "4.10.0", + "description": "Integrated plugin with 8 specialized agents (model-tiered: opus/sonnet/haiku), 46 skills including official mcp-builder, on-demand loader for Anthropic official skills, generic workflow/principle skills, skill usage statistics, pytest-playwright E2E testing split into 7 focused skills (test-planning, script-creation, execution, report, kit-ops, browser-connect, evidence-drive) + orchestrator with video-by-default evidence, CDP remote browser support, and Google Drive evidence archival, Google Drive/Chat integration, and Codex CLI integration via /ndf:codex skill. Transcript retention is automatically kept at >= 90 days. Serena MCP is a separate plugin (mcp-serena).", "author": { "name": "takemi-ohama", "url": "https://github.com/takemi-ohama" @@ -66,6 +66,8 @@ "./skills/playwright-execution", "./skills/playwright-report", "./skills/playwright-kit-ops", + "./skills/playwright-browser-connect", + "./skills/playwright-evidence-drive", "./skills/playwright-scenario-test", "./skills/google-drive", "./skills/google-chat", diff --git a/plugins/ndf/CHANGELOG.md b/plugins/ndf/CHANGELOG.md index 200ba47..ac70103 100644 --- a/plugins/ndf/CHANGELOG.md +++ b/plugins/ndf/CHANGELOG.md @@ -1,5 +1,31 @@ # NDF Plugin CHANGELOG +### v4.10.0 (playwright-browser-connect / playwright-evidence-drive Skill 追加) + +`/ndf:playwright-browser-connect` と `/ndf:playwright-evidence-drive` を新規 Skill +として追加。CDP リモートブラウザ接続と Google Drive エビデンスアーカイブを +playwright-scenario-test エコシステムから独立した専門 Skill に分離。 + +- **新規 Skill `playwright-browser-connect`**: + - `scenario.config.yaml` の `browser.mode: cdp-remote` で既存 Chrome に + CDP (Chrome DevTools Protocol) 接続するワークフローを提供 + - `conftest.py.template` に browser fixture を追加 (mode 切り替え) + - `config.py` に `BrowserConfig` dataclass を追加 +- **新規 Skill `playwright-evidence-drive`**: + - テスト実行後のエビデンス (video/trace/screenshot/HAR) を Google Drive に + 自動アーカイブする手順を提供 + - 認証は `ndf:google-auth` に委譲 +- **conftest.py.template の改善** (PR #19 クロスレビュー対応): + - `browser_type_launch_args` を browser fixture の依存に追加し、 + `--headed` / `slow_mo` / `channel` 等が local モードで反映されるよう修正 + - CDP 接続時に Chromium 以外のブラウザが選択された場合の fail-fast チェックを追加 + - 変数名 `b` → `browser` に改名 (可読性向上) +- **config.py の修正** (PR #19 クロスレビュー対応): + - `BrowserConfig.cdp_endpoint` の既定値を `ws://localhost:9222` → + `http://localhost:9222` に変更 (Playwright の `connect_over_cdp()` は + HTTP endpoint から `/json/version` 経由で WebSocket URL を自動解決する) +- Skills: 44個 → **46個** + ### v4.7.6 (fix/review-pr-comments: PRコメント取得を3ソース対応に拡張) PRレビューコメント取得が review body / PR レベルコメントを含む3ソースに対応。 diff --git a/plugins/ndf/skills/playwright-browser-connect/SKILL.md b/plugins/ndf/skills/playwright-browser-connect/SKILL.md new file mode 100644 index 0000000..e3d8685 --- /dev/null +++ b/plugins/ndf/skills/playwright-browser-connect/SKILL.md @@ -0,0 +1,377 @@ +--- +name: playwright-browser-connect +description: "Playwright E2E テストのブラウザ接続先を構成する。ローカル Chromium / Windows リモート Chrome (CDP) / macOS リモート Chrome (CDP) の 3 パターンをサポートし、scenario.config.yaml の browser: セクションで宣言的に切り替える。" +when_to_use: "E2E テストのブラウザ接続先を設定・変更するとき / remote Chrome に CDP で接続したいとき / WSL2 Docker から Windows Chrome を操作したいとき / macOS ホストの Chrome を使いたいとき。Triggers: 'ブラウザ接続', 'remote chrome', 'CDP接続', 'connectOverCDP', 'リモートブラウザ', 'Windows Chrome', 'macOS Chrome', 'browser connect', 'cdp endpoint', 'remote debugging'" +allowed-tools: + - Read + - Bash +--- + +# Playwright Browser Connect (ブラウザ接続構成) + +E2E テスト実行時のブラウザ接続先を構成する。 + +## 接続モード一覧 + +| モード | scenario.config.yaml | 接続先 | 用途 | +|---|---|---|---| +| `local` | `browser.mode: local` | コンテナ内 Chromium | CI / ヘッドレス実行 (デフォルト) | +| `cdp-remote` | `browser.mode: cdp-remote` | リモート Chrome (CDP) | GUI 操作・ログイン済み Session 再利用 | + +## 設定 (scenario.config.yaml) + +```yaml +# --- ブラウザ接続設定 -------------------------------------------------- +browser: + # local: playwright install chromium でインストールしたローカルブラウザ (デフォルト) + # cdp-remote: Chrome DevTools Protocol 経由でリモートブラウザに接続 + mode: local + + # cdp-remote 時のみ有効 + cdp_endpoint: ${CDP_ENDPOINT:-http://localhost:9222} +``` + +## パターン別セットアップ + +### パターン 1: ローカルコンテナ Chromium (デフォルト) + +設定不要。`run.sh` 初回実行時に `playwright install chromium` が自動実行される。 + +```yaml +browser: + mode: local +``` + +### パターン 2: Windows ホスト Chrome (WSL2 + Docker → CDP) + +WSL2 上の Docker コンテナから Windows 側の Chrome GUI を CDP 経由で操作する。 + +#### 構成図 + +``` +Docker container (playwright) + ↓ http://host.docker.internal:9222 +Docker Desktop (WSL2 backend) + ↓ host.docker.internal → Windows host IP +Windows host + ↓ localhost:9222 +Chrome (--remote-debugging-port=9222 --remote-allow-origins=*) +``` + +#### セットアップ手順 + +**Step 1: Windows Chrome をリモートデバッグモードで起動** + +```powershell +# Windows PowerShell +& "C:\Program Files\Google\Chrome\Application\chrome.exe" ` + --remote-debugging-port=9222 ` + --remote-allow-origins=* ` + --user-data-dir="C:\tmp\chrome-debug" +``` + +既存プロファイルのログイン済み Session を使う場合: + +```powershell +# 全 Chrome プロセスを閉じてから +& "C:\Program Files\Google\Chrome\Application\chrome.exe" ` + --remote-debugging-port=9222 ` + --remote-allow-origins=* +``` + +**Step 2: `--remote-allow-origins=*` で Host ヘッダ検証を無効化** + +Chrome CDP の WebSocket は Host ヘッダ検証があるため、リモートからの接続がデフォルトで拒否される。 +Chrome 起動時に `--remote-allow-origins=*` フラグを付けることで、任意の Origin からの接続を許可できる。 + +Step 1 のコマンドにフラグを追加: + +```powershell +# Windows PowerShell +& "C:\Program Files\Google\Chrome\Application\chrome.exe" ` + --remote-debugging-port=9222 ` + --remote-allow-origins=* ` + --user-data-dir="C:\tmp\chrome-debug" +``` + +これにより proxy を設置する必要がなくなり、Docker コンテナから直接 CDP エンドポイントに接続できる。 + +> **Note**: `--remote-allow-origins=*` は Chrome 106+ で利用可能。セキュリティ上、信頼できるネットワーク内での利用に限定すること。 + +> **Important**: Chrome はデフォルトで `127.0.0.1` にバインドするため、`--remote-allow-origins=*` だけでは WSL2/Docker から接続できない場合がある。対処方法は「ネットワーク別接続ガイド」セクションを参照。 + +**Step 3: WSL2 .wslconfig (NAT mode 確認)** + +```ini +# %USERPROFILE%\.wslconfig +[wsl2] +networkingMode=NAT +``` + +**Step 4: scenario.config.yaml** + +Docker Desktop (WSL2 backend) は `host.docker.internal` を標準サポートしている。 + +```yaml +browser: + mode: cdp-remote + cdp_endpoint: ${CDP_ENDPOINT:-http://host.docker.internal:9222} +``` + +環境変数で指定する場合: + +```bash +export CDP_ENDPOINT="http://host.docker.internal:9222" +``` + +> **Note (Docker Desktop を使わず WSL2 から直接実行する場合)**: `host.docker.internal` は Docker Desktop 固有の DNS 名のため利用できない。代わりに Windows ホストの IP アドレスを直接指定する: +> ```bash +> # WSL2 から Windows ホスト IP を取得 +> export CDP_ENDPOINT="http://$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):9222" +> ``` + +### パターン 3: macOS ホスト Chrome (Docker → CDP) + +macOS 上の Docker コンテナから macOS 側の Chrome GUI を CDP 経由で操作する。 + +#### 構成図 + +``` +Docker container (playwright) + ↓ http://host.docker.internal:9222 +macOS host + ↓ localhost:9222 +Chrome (--remote-debugging-port=9222 --remote-allow-origins=*) +``` + +#### セットアップ手順 + +**Step 1: macOS Chrome をリモートデバッグモードで起動** + +```bash +/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \ + --remote-debugging-port=9222 \ + --remote-allow-origins=* \ + --user-data-dir="$HOME/tmp/chrome-debug" +``` + +既存プロファイルのログイン済み Session を使う場合: + +```bash +# 全 Chrome プロセスを終了してから +/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \ + --remote-debugging-port=9222 \ + --remote-allow-origins=* +``` + +**Step 2: scenario.config.yaml** + +macOS Docker Desktop は `host.docker.internal` を標準サポートしており、 +`--remote-allow-origins=*` で Host ヘッダ検証を無効化しているため proxy 不要。 + +```yaml +browser: + mode: cdp-remote + cdp_endpoint: ${CDP_ENDPOINT:-http://host.docker.internal:9222} +``` + +## conftest.py への統合 + +`browser.mode: cdp-remote` の場合、pytest-playwright の通常のブラウザ起動をバイパスし、 +`connectOverCDP()` で既存 Chrome に接続する fixture を有効化する必要がある。 + +`scenario-test/conftest.py` に以下を追加: + +```python +import pytest +from playwright.sync_api import Browser, BrowserType + +@pytest.fixture(scope="session") +def browser( + browser_type: BrowserType, + browser_type_launch_args: dict, + pwk_config, +) -> Browser: + """browser.mode に応じてブラウザ接続を切り替える。 + + - local: pytest-playwright デフォルト (chromium.launch()) + - cdp-remote: chromium.connect_over_cdp(endpoint) + """ + browser_cfg = pwk_config.browser + # slow_mo: browser_type_launch_args が優先、なければ config の slow_mo_ms + _slow_mo = browser_type_launch_args.get( + "slow_mo", pwk_config.playwright.slow_mo_ms or None + ) + if browser_cfg.mode == "cdp-remote": + if browser_type.name != "chromium": + pytest.fail( + f"cdp-remote モードは Chromium 専用です (現在: {browser_type.name})。" + "--browser chromium を指定するか、browser.mode を local に変更してください。" + ) + browser = browser_type.connect_over_cdp( + browser_cfg.cdp_endpoint, + slow_mo=_slow_mo, + ) + yield browser + # CDP 接続の場合、close() は接続を切断 (disconnect) するだけで、 + # リモートブラウザ自体は終了しない。 + browser.close() + else: + launch_args = {**browser_type_launch_args} + launch_args.setdefault("headless", pwk_config.playwright.headless) + if _slow_mo is not None: + launch_args.setdefault("slow_mo", _slow_mo) + browser = browser_type.launch(**launch_args) + yield browser + browser.close() +``` + +### CDP モードでの既存セッション再利用 + +`cdp-remote` モードでは、テンプレートの `conftest.py` が `context` / `page` fixture を +自動的にオーバーライドし、CDP 接続先の既存コンテキスト (ログイン済み Session) を返す。 +標準のテストコードは何も変更せずに既存セッションを利用できる。 + +```python +@pytest.fixture(scope="session") +def context(browser, pwk_config, _cdp_default_context): + """cdp-remote: 既存コンテキスト / local: 新規コンテキスト""" + if pwk_config.browser.mode == "cdp-remote" and _cdp_default_context is not None: + yield _cdp_default_context + else: + ctx = browser.new_context() + yield ctx + ctx.close() + +@pytest.fixture(scope="session") +def page(context, pwk_config): + """cdp-remote: 既存ページ / local: 新規ページ""" + if pwk_config.browser.mode == "cdp-remote" and context.pages: + yield context.pages[0] + else: + pg = context.new_page() + yield pg + pg.close() +``` + +`browser.new_context()` は新規コンテキストを作成するため、既存のログイン Session は引き継がれない。 +`cdp-remote` モードでは `context` fixture が自動的に `browser.contexts[0]` を返すため、 +テスト側で特別な対応は不要。 + +## run.sh での利用 + +`cdp-remote` モード時は `playwright install chromium` が不要。 +`run.sh` は初回セットアップで `playwright install` を実行するが、 +接続先がリモートの場合はスキップして問題ない (ローカルブラウザは使わないため)。 + +CDP 接続テストを手動確認する場合: + +```bash +# エンドポイントの疎通確認 +curl -s http://host.docker.internal:9222/json/version | python3 -m json.tool +``` + +## ネットワーク別接続ガイド + +Chrome はデフォルトで `127.0.0.1` (ループバック) にバインドするため、同一ホストからしか CDP エンドポイントにアクセスできない。Docker コンテナや WSL2 からリモート接続する場合は、以下のいずれかの方法でネットワーク到達性を確保する必要がある。 + +### 方法 1: `--remote-debugging-address=0.0.0.0` (推奨) + +Chrome 起動時に全インターフェースでリッスンさせる。最もシンプルな方法。 + +```bash +# Linux / macOS +google-chrome \ + --remote-debugging-port=9222 \ + --remote-debugging-address=0.0.0.0 \ + --remote-allow-origins=* +``` + +```powershell +# Windows PowerShell +& "C:\Program Files\Google\Chrome\Application\chrome.exe" ` + --remote-debugging-port=9222 ` + --remote-debugging-address=0.0.0.0 ` + --remote-allow-origins=* +``` + +> **Security**: `0.0.0.0` はすべてのネットワークインターフェースに公開するため、信頼できるネットワーク内でのみ使用すること。ファイアウォールでポート 9222 へのアクセスを制限することを推奨。 + +### 方法 2: socat によるポートフォワード (Linux) + +Chrome を `127.0.0.1` バインドのまま維持し、socat でリモートからのアクセスを中継する。 + +```bash +# Chrome は通常どおり起動 (127.0.0.1 バインド) +google-chrome --remote-debugging-port=9222 --remote-allow-origins=* + +# 別ターミナルで socat を起動 +socat TCP-LISTEN:9222,bind=0.0.0.0,reuseaddr,fork TCP:127.0.0.1:9222 +``` + +### 方法 3: netsh portproxy (Windows → WSL2) + +Windows ホストの Chrome を WSL2 からアクセスする場合、Windows 側でポートフォワードを設定する。 + +```powershell +# 管理者権限の PowerShell で実行 +netsh interface portproxy add v4tov4 ` + listenaddress=0.0.0.0 listenport=9222 ` + connectaddress=127.0.0.1 connectport=9222 + +# 確認 +netsh interface portproxy show all + +# 削除する場合 +netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=9222 +``` + +### 接続先の早見表 + +| 実行環境 | Chrome の場所 | 推奨方法 | CDP エンドポイント | +|---|---|---|---| +| ローカル (同一ホスト) | 同一ホスト | 設定不要 | `http://localhost:9222` | +| Docker → ホスト (macOS) | macOS ホスト | 方法 1 | `http://host.docker.internal:9222` | +| Docker → ホスト (Linux) | Linux ホスト | 方法 1 or 2 | `http://host.docker.internal:9222` or `http://172.17.0.1:9222` | +| Docker (WSL2) → Windows | Windows ホスト | 方法 1 or 3 | `http://host.docker.internal:9222` | +| WSL2 → Windows | Windows ホスト | 方法 1 or 3 | `http://$(cat /etc/resolv.conf \| grep nameserver \| awk '{print $2}'):9222` | + +## トラブルシュート + +### 共通 + +| 症状 | 原因 | 対策 | +|---|---|---| +| `connect_over_cdp` で接続拒否 | Chrome が起動していない / ポートが違う | `curl http:///json/version` で確認 | +| WebSocket handshake 失敗 | Host ヘッダ不一致 | Chrome 起動時に `--remote-allow-origins=*` を付与 | +| ページ操作が異常に遅い | VPN / DNS 解決の遅延 | `extra_hosts` で IP 直指定 | + +### Windows (WSL2) 固有 + +| 症状 | 原因 | 対策 | +|---|---|---| +| `host.docker.internal` 解決不能 | Docker Desktop 未使用 or 古いバージョン | Docker Desktop を使用するか、WSL2 直接の場合は Windows ホスト IP を直接指定 | +| IPv6 でバインドされる | WSL2 が IPv6 優先 | proxy.js で `0.0.0.0` を明示 | +| `netsh portproxy` で接続ループ | portproxy の自己参照 | `--remote-allow-origins=*` を使い proxy を廃止 | +| mirrored mode で動かない | mirrored は localhost 共有だが CDP の WS 接続でポート競合 | NAT mode に戻す | + +### macOS 固有 + +| 症状 | 原因 | 対策 | +|---|---|---| +| `host.docker.internal` 解決不能 | Docker Desktop が古い / Linux Docker | `--add-host=host.docker.internal:host-gateway` を指定 | +| ファイアウォールでブロック | macOS のアプリファイアウォール | システム設定 > ネットワーク > ファイアウォール で Chrome を許可 | + +## CDP 接続のメリット + +- **GUI Chrome をそのまま操作可能** — OBS 録画可、人間と AI の協調操作が可能 +- **ログイン済み Session の再利用** — Google / AWS / Slack 等の MFA 済み Session をそのまま使える +- **ブラウザ拡張機能が有効** — テスト時にも拡張機能の影響を確認可能 +- **AI Agent との相性** — Claude Code / Browser Use / OpenHands がリアルブラウザを操作 + +## 関連 Skill + +- `/ndf:playwright-execution` — テスト実行 + エビデンス収集 +- `/ndf:playwright-kit-ops` — プロジェクト初期化 / ツール群 +- `/ndf:playwright-scenario-test` — 全機能統括 +- `/ndf:docker-container-access` — Docker コンテナアクセス一般 diff --git a/plugins/ndf/skills/playwright-evidence-drive/SKILL.md b/plugins/ndf/skills/playwright-evidence-drive/SKILL.md new file mode 100644 index 0000000..667fd14 --- /dev/null +++ b/plugins/ndf/skills/playwright-evidence-drive/SKILL.md @@ -0,0 +1,190 @@ +--- +name: playwright-evidence-drive +description: "Playwright E2E テスト後のエビデンス一式 (動画/trace/HAR/report.md) を Google Drive に保管し、共有リンクを生成する。自動アップロード (--pwk-drive-folder) と手動アップロード (scripts) の両方をサポート。report.md → Google Docs 変換 + Drive リンク埋め込みも対応。" +when_to_use: "テストエビデンスを Google Drive に保管・共有したいとき / テスト結果を Google Docs としてチームに配布したいとき / Drive 上のエビデンスリンクを report に埋め込みたいとき。Triggers: 'Drive にアップロード', 'Drive 共有', 'エビデンス保管', 'evidence drive', 'pwk-drive-folder', 'テスト結果共有', 'Google Drive エビデンス', 'trace アップロード', '動画アップロード', 'report を Docs に', 'エビデンス配布'" +allowed-tools: + - Read + - Bash(python *) + - Bash(uv *) +--- + +# Playwright Evidence → Google Drive 保管 + +テスト実行後のエビデンス一式を Google Drive に保管し、共有可能にする。 + +## 前提条件 + +- `/ndf:google-auth` で OAuth2 認証が完了していること (drive.file スコープ) +- テスト実行済みで `reports//` にエビデンスが存在すること + +## アップロード対象 + +| ファイル | 種別 | セキュリティ考慮 | +|---|---|---| +| `video.mp4` | テスト動画 | 画面に表示された情報が含まれる | +| `trace.zip` | Playwright Trace | DOM snapshot + 操作ログ + Cookie/localStorage | +| `request.har` | ネットワーク通信ログ | HTTP request/response body を含む場合あり | +| `report.md` | テスト結果サマリ | URL + テスト名程度 | +| `body_check.jsonl` | PHP/SSR エラー詳細 | ソースコード片を含む場合あり | +| `screenshot-*.png` | 失敗時スクリーンショット | 画面に表示された情報 | + +**セキュリティ注意**: trace.zip / HAR には認証情報 (Cookie, localStorage, Basic Auth) や +入力内容が含まれる可能性がある。アップロード先は **private folder** + **信頼できる共有相手** に限定すること。 + +## 方法 1: テスト実行時の自動アップロード + +`--pwk-drive-folder` を指定すると `pytest_sessionfinish` hook で自動アップロードされる。 + +```bash +./scenario-test/run.sh --pwk-drive-folder= +``` + +動作: +1. テスト終了後に `pytest_sessionfinish` が発火 +2. `report.md` をアップロード +3. 各テストの `trace.zip` / `*.har` / `*.mp4` / `body_check.jsonl` をアップロード +4. 全ファイルは非公開 (private) でアップロードされる + +## 方法 2: 手動アップロード (scripts) + +テスト実行後に個別にアップロードする場合。スクリプトは `playwright-kit-ops/scripts/` に配置。 + +### 単一ファイルアップロード + +```bash +cd scenario-test +uv run python scripts/upload_evidence.py reports//test_login/trace.zip \ + --kind trace \ + --parent-folder-id +``` + +オプション: +- `--kind {trace|har|video|any}` — ファイル種別 (拡張子から自動判定も可) +- `--parent-folder-id ` — Drive 上のアップロード先フォルダ ID +- `--public` — anyone/read 権限を付与 (trace viewer URL 生成に必要) + +### ディレクトリ一括アップロード + +```bash +uv run python scripts/gdrive_upload_dir.py \ + --local reports// \ + --parent +``` + +ディレクトリ構造を保ったまま Drive にミラーする。 +サブフォルダも再帰的に作成される。 + +### report.md → Google Docs 変換 + +```bash +uv run python scripts/upload_md_as_gdoc.py \ + --md reports//report.md \ + --parent \ + --name "E2E テスト報告書 2026-05-26" +``` + +Markdown を Google Docs 形式に変換してアップロード。 +テーブル・リスト・見出しが Docs のネイティブ形式に変換される。 + +### Google Docs にエビデンス Drive リンクを埋め込み + +```bash +uv run python scripts/build_gdoc_with_drive_links.py \ + --md reports//report.md \ + --folder \ + --run-id \ + --name "E2E テスト報告書 2026-05-26" +``` + +1. Drive 上の `` 配下の `` フォルダからファイル一覧を取得 +2. `report.md` 内の相対パスリンク (`./TC-XX/trace.zip`) を Drive URL に書き換え +3. 書き換え済み Markdown を Google Docs としてアップロード + +→ チームメンバーが Docs 上で report を読みながら、エビデンスへの Drive リンクをクリックして確認できる。 + +## 推奨ワークフロー + +``` +[テスト実行] + ./scenario-test/run.sh --pwk-overlay + ↓ +[ローカル確認] + reports//report.md で結果確認 + ↓ +[Drive 一括アップロード] + uv run python scripts/gdrive_upload_dir.py --local reports// --parent + ↓ +[Docs 変換 + リンク埋め込み] + uv run python scripts/build_gdoc_with_drive_links.py --md reports//report.md --folder --run-id --name "報告書" + ↓ +[共有] + Docs URL をチーム (Slack / Google Chat) に共有 +``` + +ワンコマンドで全てを行う場合: + +```bash +./scenario-test/run.sh --pwk-drive-folder= --pwk-overlay +``` + +## Drive フォルダ構成の推奨 + +``` +E2E テスト証跡/ ← 共有ドライブ or チームフォルダ +├── <プロジェクト名>/ +│ ├── 20260526-134500/ ← run-id (自動生成) +│ │ ├── report.md +│ │ ├── test_login/ +│ │ │ ├── video.mp4 +│ │ │ ├── trace.zip +│ │ │ └── request.har +│ │ └── test_admin_dashboard/ +│ │ ├── video.mp4 +│ │ └── trace.zip +│ └── report (Google Docs) ← build_gdoc_with_drive_links で生成 +``` + +## Trace Viewer 連携 + +`--public` でアップロードした trace.zip は Playwright Trace Viewer で直接開ける: + +```bash +uv run python scripts/upload_evidence.py reports/.../trace.zip \ + --kind trace --public --parent-folder-id +``` + +出力例: +``` +playwright_trace_viewer: https://trace.playwright.dev/?trace=https%3A%2F%2Fdrive.google.com%2Fuc%3Fexport%3Ddownload%26id%3D... +``` + +この URL を共有すると、インストール不要でブラウザ上から trace を再生できる。 + +**注意**: `--public` は anyone/read を付与するため、trace 内の機密情報 (Cookie, 入力値) が +公開される。社内限定の場合は private のまま `playwright show-trace` をローカルで使うこと。 + +## トラブルシュート + +| 症状 | 原因 | 対策 | +|---|---|---| +| `google_auth スキルが見つかりません` | google-auth スキル未インストール | `GOOGLE_AUTH_SCRIPTS` env を設定、または `/ndf:google-auth` で認証セットアップ | +| `HttpError 403: insufficient permissions` | drive.file スコープ不足 | `/ndf:google-auth` で再認証 (`drive.file` スコープ指定) | +| `HttpError 404: File not found` | FOLDER_ID が間違っている / アクセス権なし | Drive で共有フォルダ ID を確認 | +| `resumable upload failed` | ファイルサイズが大きい / ネットワーク不安定 | 再試行。動画は mp4 (H.264) で容量を抑える | +| pytest 後に自動アップロードされない | `--pwk-drive-folder` 未指定 | CLI 引数を確認 | + +## 環境変数 + +| 変数 | 用途 | 例 | +|---|---|---| +| `GOOGLE_AUTH_SCRIPTS` | google-auth スキルの scripts/ パス | `~/.claude/skills/google-auth/scripts` | +| `PWK_DRIVE_FOLDER` | デフォルトの Drive アップロード先 (将来対応予定) | `1ABCxyz...` | + +## 関連 Skill + +- `/ndf:playwright-execution` — テスト実行 + エビデンス収集 (Drive アップロードの前段) +- `/ndf:playwright-report` — Markdown レポート生成 +- `/ndf:playwright-kit-ops` — スクリプト実行 (upload_evidence 等のスクリプトはここに配置) +- `/ndf:google-auth` — Google API OAuth2 認証 +- `/ndf:google-drive` — Google Drive 汎用操作 +- `/ndf:playwright-scenario-test` — 全機能統括 diff --git a/plugins/ndf/skills/playwright-execution/SKILL.md b/plugins/ndf/skills/playwright-execution/SKILL.md index 0247137..0011abf 100644 --- a/plugins/ndf/skills/playwright-execution/SKILL.md +++ b/plugins/ndf/skills/playwright-execution/SKILL.md @@ -96,4 +96,6 @@ reports// - `/ndf:playwright-script-creation` — テストスクリプト作成 (実行の前段) - `/ndf:playwright-report` — Markdown レポート生成 - `/ndf:playwright-kit-ops` — スクリプト実行 (init_project / スキャン) +- `/ndf:playwright-browser-connect` — ブラウザ接続構成 (local / CDP remote) +- `/ndf:playwright-evidence-drive` — エビデンス Google Drive 保管 - `/ndf:playwright-scenario-test` — 全機能統括 diff --git a/plugins/ndf/skills/playwright-kit-ops/SKILL.md b/plugins/ndf/skills/playwright-kit-ops/SKILL.md index 76ed24c..b3ff459 100644 --- a/plugins/ndf/skills/playwright-kit-ops/SKILL.md +++ b/plugins/ndf/skills/playwright-kit-ops/SKILL.md @@ -104,5 +104,6 @@ playwright_kit Python パッケージ本体・templates・tests はこの skill - `/ndf:playwright-test-planning` — テスト計画 (方法論 + チェックリスト) - `/ndf:playwright-script-creation` — テストスクリプト作成 - `/ndf:playwright-execution` — テスト実行 + エビデンス収集 (video/trace/overlay/quality) +- `/ndf:playwright-browser-connect` — ブラウザ接続構成 (local / CDP remote) - `/ndf:playwright-report` — レポート生成 - `/ndf:playwright-scenario-test` — 全機能統括 diff --git a/plugins/ndf/skills/playwright-kit-ops/playwright_kit/config.py b/plugins/ndf/skills/playwright-kit-ops/playwright_kit/config.py index 95a21ca..18436b4 100644 --- a/plugins/ndf/skills/playwright-kit-ops/playwright_kit/config.py +++ b/plugins/ndf/skills/playwright-kit-ops/playwright_kit/config.py @@ -49,6 +49,44 @@ def _expand_env(value: Any) -> Any: return value +# --- ブラウザ接続 --------------------------------------------------- + +BrowserMode = Literal["local", "cdp-remote"] +BROWSER_MODES: tuple[BrowserMode, ...] = ("local", "cdp-remote") + + +@dataclass +class BrowserConfig: + """ブラウザ接続設定。 + + cdp_endpoint が空文字列や空白のみの場合はデフォルト値 + ``http://localhost:9222`` にフォールバックする。 + """ + + mode: BrowserMode = "local" + cdp_endpoint: str = "http://localhost:9222" + + @classmethod + def from_raw(cls, raw: dict[str, Any]) -> "BrowserConfig": + base = cls() + mode_raw = str(raw.get("mode") or base.mode).lower() + if mode_raw not in BROWSER_MODES: + raise ValueError( + f"browser.mode は {BROWSER_MODES} のいずれかを指定してください " + f"(指定値: {mode_raw!r})" + ) + mode: BrowserMode = mode_raw # type: ignore[assignment] + # cdp_endpoint: 空文字列・空白のみの場合はデフォルト値にフォールバック + cdp_raw = raw.get("cdp_endpoint") + cdp_endpoint = str(cdp_raw).strip() if cdp_raw else "" + if not cdp_endpoint: + cdp_endpoint = base.cdp_endpoint + return cls( + mode=mode, + cdp_endpoint=cdp_endpoint, + ) + + # --- 接続/認証 ------------------------------------------------------- @dataclass @@ -260,6 +298,7 @@ class Config: runner: RunnerConfig report: ReportConfig config_path: Path # 設定ファイルの絶対パス(testcases_dir の解決基点) + browser: BrowserConfig = field(default_factory=BrowserConfig) # docs/checklists/checklist-common.md C8/C9 の境界曖昧さに対応する「除外」設定。 # console.error / pageerror の本文がいずれかの正規表現にマッチした場合は # 集計から除外し FAIL を抑制する。3rd party の既知 warning などを許容するための @@ -323,6 +362,7 @@ def _from_dict(cls, raw: dict[str, Any], *, config_path: Path) -> "Config": runner=RunnerConfig.from_raw(raw.get("runner") or {}), report=_report_from_raw(raw.get("report") or {}), config_path=config_path, + browser=BrowserConfig.from_raw(raw.get("browser") or {}), tolerated_console_errors=list(raw.get("tolerated_console_errors") or []), tolerated_page_errors=list(raw.get("tolerated_page_errors") or []), accessibility=_accessibility_from_raw(raw.get("accessibility") or {}), diff --git a/plugins/ndf/skills/playwright-kit-ops/templates/conftest.py.template b/plugins/ndf/skills/playwright-kit-ops/templates/conftest.py.template index f9de18e..9ad04d4 100644 --- a/plugins/ndf/skills/playwright-kit-ops/templates/conftest.py.template +++ b/plugins/ndf/skills/playwright-kit-ops/templates/conftest.py.template @@ -11,6 +11,7 @@ fixture を追加する。 from __future__ import annotations import pytest +from playwright.sync_api import Browser, BrowserType # pytest-playwright の標準 fixture (browser_context_args / page) は plugin 経由で # 読み込まれる。playwright_kit 側 fixture (pwk_config / pwk_role_ / @@ -24,6 +25,90 @@ import pytest # return {**browser_type_launch_args, "headless": False, "slow_mo": 200} +# --- ブラウザ接続 fixture ------------------------------------------------ +# scenario.config.yaml の browser.mode に応じてブラウザ接続を切り替える。 +# - local: pytest-playwright デフォルト (chromium.launch()) +# - cdp-remote: connect_over_cdp() で既存 Chrome に CDP 接続 +# → /ndf:playwright-browser-connect 参照 + + +@pytest.fixture(scope="session") +def browser( + browser_type: BrowserType, + browser_type_launch_args: dict, + pwk_config, +) -> Browser: + browser_cfg = pwk_config.browser + # slow_mo: browser_type_launch_args が優先、なければ config の slow_mo_ms + _slow_mo = browser_type_launch_args.get( + "slow_mo", pwk_config.playwright.slow_mo_ms or None + ) + if browser_cfg.mode == "cdp-remote": + if browser_type.name != "chromium": + pytest.fail( + f"cdp-remote モードは Chromium 専用です (現在: {browser_type.name})。" + "--browser chromium を指定するか、browser.mode を local に変更してください。" + ) + browser = browser_type.connect_over_cdp( + browser_cfg.cdp_endpoint, + slow_mo=_slow_mo, + ) + yield browser + # CDP 接続の場合、close() は接続を切断 (disconnect) するだけで、 + # リモートブラウザ自体は終了しない。次回のテスト実行でも同じ Chrome を再利用できる。 + browser.close() + else: + launch_args = {**browser_type_launch_args} + launch_args.setdefault("headless", pwk_config.playwright.headless) + if _slow_mo is not None: + launch_args.setdefault("slow_mo", _slow_mo) + browser = browser_type.launch(**launch_args) + yield browser + browser.close() + + +@pytest.fixture(scope="session") +def _cdp_default_context(browser, pwk_config): + """CDP モードで既存ブラウザの最初のコンテキスト (ログイン済み Session) を返す。 + + CDP 接続先の Chrome が持つ既存 context (browser.contexts[0]) を再利用する。 + local モードでは None を返す。 + """ + if pwk_config.browser.mode == "cdp-remote" and browser.contexts: + return browser.contexts[0] + return None + + +@pytest.fixture(scope="session") +def context(browser, pwk_config, _cdp_default_context): + """pytest-playwright の context fixture をオーバーライド。 + + cdp-remote モードでは既存コンテキスト (ログイン済み Session) を返し、 + local モードでは新規コンテキストを作成する (pytest-playwright 既定動作)。 + """ + if pwk_config.browser.mode == "cdp-remote" and _cdp_default_context is not None: + yield _cdp_default_context + else: + ctx = browser.new_context() + yield ctx + ctx.close() + + +@pytest.fixture(scope="session") +def page(context, pwk_config): + """pytest-playwright の page fixture をオーバーライド。 + + cdp-remote モードでは既存コンテキストの最初のページを返し (なければ新規作成)、 + local モードでは新規ページを作成する (pytest-playwright 既定動作)。 + """ + if pwk_config.browser.mode == "cdp-remote" and context.pages: + yield context.pages[0] + else: + pg = context.new_page() + yield pg + pg.close() + + # プロジェクト固有の fixture をここに追加する。例: # # @pytest.fixture diff --git a/plugins/ndf/skills/playwright-kit-ops/templates/scenario.config.yaml b/plugins/ndf/skills/playwright-kit-ops/templates/scenario.config.yaml index 0f749ab..6bd08b4 100644 --- a/plugins/ndf/skills/playwright-kit-ops/templates/scenario.config.yaml +++ b/plugins/ndf/skills/playwright-kit-ops/templates/scenario.config.yaml @@ -12,6 +12,19 @@ # .env ファイルや shell export で環境変数を設定して使用します。 # 例: export ADMIN_PASSWORD=secret または direnv / .env ファイルを活用 +# --- ブラウザ接続設定 -------------------------------------------------- +# local: playwright install chromium でインストールしたローカルブラウザ (デフォルト) +# cdp-remote: Chrome DevTools Protocol 経由でリモートブラウザに接続 +# → Windows / macOS のホスト Chrome を GUI 付きで操作可能 +# → ログイン済み Session (Google, AWS, Slack 等) をそのまま再利用 +# → 詳細は /ndf:playwright-browser-connect を参照 +browser: + mode: local + # cdp-remote 時のみ有効。環境変数で切り替え推奨: + # Windows (WSL2 Docker): export CDP_ENDPOINT=http://host-gateway:9222 + # macOS (Docker Desktop): export CDP_ENDPOINT=http://host.docker.internal:9222 + # cdp_endpoint: ${CDP_ENDPOINT:-http://localhost:9222} + # --- 接続先 ---------------------------------------------------------- target: base_url: https://example.com diff --git a/plugins/ndf/skills/playwright-report/SKILL.md b/plugins/ndf/skills/playwright-report/SKILL.md index aca64e8..8da2568 100644 --- a/plugins/ndf/skills/playwright-report/SKILL.md +++ b/plugins/ndf/skills/playwright-report/SKILL.md @@ -42,8 +42,14 @@ report: phase_labels: {} ``` +## Google Drive での共有 + +レポート + エビデンスを Drive にアップロードしてチーム共有する場合は +`/ndf:playwright-evidence-drive` を参照。 + ## 関連 Skill - `/ndf:playwright-execution` — テスト実行 + エビデンス収集 -- `/ndf:playwright-kit-ops` — エビデンスアップロードツール (Drive 連携が必要な場合) +- `/ndf:playwright-evidence-drive` — エビデンス Google Drive 保管・共有 +- `/ndf:playwright-kit-ops` — エビデンスアップロードツール (スクリプト群) - `/ndf:playwright-scenario-test` — 全機能を統括したフルワークフロー diff --git a/plugins/ndf/skills/playwright-scenario-test/SKILL.md b/plugins/ndf/skills/playwright-scenario-test/SKILL.md index 3fefbe1..b38f595 100644 --- a/plugins/ndf/skills/playwright-scenario-test/SKILL.md +++ b/plugins/ndf/skills/playwright-scenario-test/SKILL.md @@ -29,6 +29,8 @@ Web アプリの E2E シナリオを **理論ベース** で計画し、**再現 | 3 | `/ndf:playwright-execution` | テスト実行 + エビデンス収集 (video/trace/overlay/quality) | | 4 | `/ndf:playwright-report` | レポート生成 (Markdown) | | -- | `/ndf:playwright-kit-ops` | ツール群 (init_project / スキャン / アップロード) | +| -- | `/ndf:playwright-browser-connect` | ブラウザ接続 (local / CDP remote) | +| -- | `/ndf:playwright-evidence-drive` | エビデンス Google Drive 保管・共有 | ## 標準ワークフロー