maestro/docs/tools/testworkspaceapp.md
oss-sync b857c33ef6
Some checks failed
CI / build-and-test (push) Has been cancelled
sync: update from private repo (f6d625db)
2026-06-26 03:35:45 +00:00

154 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# TestWorkspaceApp
ワークスペース・アプリをヘッドレスブラウザで実起動し、操作・期待値検証・ファイルの変化確認を行う E2E テストツール。`workspace-app` ピースの verify ステップが自動的に呼び出す。
## 入力パラメータ
| パラメータ | 型 | 必須 | 説明 |
|-----------|-----|------|------|
| `space` | string | ✓ | テスト対象スペースの ID |
| `app` | string | ✓ | `apps/` 配下のアプリフォルダ名(パスではなく名前のみ) |
| `entry` | string | — | エントリー HTML のパス(スペースファイルルートからの相対)。省略時は `apps/{app}/index.html` |
| `seed_files` | array | — | テスト前にワークスペースへ書き込むファイル群(下記参照) |
| `steps` | array | — | ブラウザアクション列(`BrowseWebAction` と同じ形式、下記参照) |
| `expect` | array | — | 検証する期待値リスト(下記参照) |
| `timeout_ms` | number | — | ブラウザ操作全体のタイムアウト(ミリ秒、デフォルト 30000 |
### seed_files
テスト開始前にワークスペースへ書き込むファイルを指定する。アプリが読み取る入力データを事前配置するために使う。
```json
"seed_files": [
{ "path": "output/notes.md", "content": "# Hello\nworld" }
]
```
- `path` はワークスペースルートからの相対パス(`resolveAndGuard` でパストラバーサルを防ぐ)
- `content` は UTF-8 文字列
- 書き込んだファイルは `file_changes` に記録されるbytes はシード時の書き込みサイズ)
### stepsBrowseWebAction 形式)
ハーネスページ上で実行するブラウザ操作を配列で渡す。型は `BrowseWebAction` と共通。
| type | 追加フィールド | 説明 |
|------|--------------|------|
| `goto` | `url` | 指定 URL へ移動(ハーネス URL は自動で最初に追加されるため通常不要) |
| `click` | `selector` または `ref` | 要素をクリック |
| `fill` | `selector` または `ref`, `value` | フォーム入力 |
| `screenshot` | `value`(ファイル名) | スクリーンショットを撮影 |
| `getText` | — | ページのテキストを取得(期待値チェックに使われる) |
| `dumpHtml` | — | ページの HTML を取得 |
| `wait` | `ms` | 指定ミリ秒待機 |
ハーネスは起動時に自動的に `goto → wait(2000ms) → getText` を実行してからユーザー指定ステップを追加する。`goto` を先頭に追加する必要はない。
### expect期待値リスト
| kind | フィールド | 説明 |
|------|-----------|------|
| `text` | `target`CSS セレクタ), `contains` | ページテキスト全体が `contains` を含む。`target` は情報的なセレクタ(精度向上には `getText` アクションを先に実行) |
| `file` | `target`(ワークスペース相対パス), `contains` | 指定ファイルが存在し、その内容が `contains` を含む |
**重要**: `kind``"text"` または `"file"` のみ有効。他の値は常に失敗として記録される(サイレントパスなし)。`contains` が空文字列の場合も評価は行われる(空文字列はどの文字列にも含まれるため通過)。
```json
"expect": [
{ "kind": "text", "target": "[data-testid=\"status\"]", "contains": "保存OK" },
{ "kind": "file", "target": "output/notes.md", "contains": "edited-by-e2e" }
]
```
## 戻り値
```json
{
"ok": true,
"failures": [],
"screenshots": ["app-test-myapp-final.png"],
"console_errors": [],
"bridge_calls": [],
"file_changes": [
{ "path": "output/notes.md", "bytes": 14 }
]
}
```
| フィールド | 説明 |
|-----------|------|
| `ok` | `failures` が空なら `true` |
| `failures` | 失敗した期待値の説明(配列) |
| `screenshots` | 撮影したスクリーンショットのファイル名一覧 |
| `console_errors` | ブラウザコンソールのエラーメッセージ |
| `bridge_calls` | **V1 では常に `[]`**(ヘッドレス環境ではブリッジ呼び出しの観測不可) |
| `file_changes` | seed_files で書き込んだファイルの一覧と byte 数 |
## テンプレートの `e2e.example.json` を使う
`docs/examples/workspace-apps/{note-editor,data-viewer,form-input,dashboard}/e2e.example.json` にひな型が入っている。TestWorkspaceApp に渡す JSON の例として使えるので、新しいアプリを作る際はここをコピーして改変する。
### note-editor の例
```json
{
"app": "note-editor",
"seed_files": [
{ "path": "output/note.md", "content": "seeded-content" }
],
"steps": [
{ "type": "click", "selector": "[data-testid=\"load\"]" },
{ "type": "getText", "selector": "[data-testid=\"status\"]" },
{ "type": "fill", "selector": "[data-testid=\"body\"]", "value": "edited-by-e2e" },
{ "type": "click", "selector": "[data-testid=\"save\"]" },
{ "type": "getText", "selector": "[data-testid=\"status\"]" }
],
"expect": [
{ "kind": "text", "target": "[data-testid=\"status\"]", "contains": "保存OK" },
{ "kind": "file", "target": "output/note.md", "contains": "edited-by-e2e" }
]
}
```
## 注意事項(ゴッチャ)
### (a) seed_files の書き込みは本物の `output/` に入る
seed_files で書き込んだファイルはワークスペースの実際のパスに書かれる。テスト用の一時領域ではなく、`output/note.md` を指定すれば本物の `output/note.md` が変更される。テスト後のクリーンアップはユーザー(またはエージェント)が行う必要がある。
### (b) 書き込み確認ダイアログはハーネス側で自動承認される
ブラウザ内の `writeFile` / `deleteFile` ブリッジ呼び出しは、`/app-harness` ルートではダイアログが自動承認される。本番の `/ui/app/...` 上では確認ダイアログが表示されるので挙動が異なる。
### (c) UI のビルドが必要
`/app-harness` ルートは Vite でビルドされた UI から配信される。`npm run build:ui` を実行していないと 404 になり、テストが失敗する。開発中は `cd ui && npm run dev` を起動してから dev モードで試すこともできる。
### (d) bridge_calls は V1 では常に空
ヘッドレスブラウザ環境ではブリッジ呼び出し(`readFile` / `writeFile` など)の観測が技術的に困難なため、`bridge_calls` フィールドは常に `[]` を返す。ブリッジの動作確認は `expect``kind: "file"` でファイルの変化を確認することで代替する。
## ワークフロー例
```
# 1. アプリを作成
Write({ path: "apps/note-editor/index.html", content: "..." })
# 2. E2E テストで動作確認
TestWorkspaceApp({
space: ctx.spaceId,
app: "note-editor",
seed_files: [{ path: "output/test-note.md", content: "# Test" }],
steps: [
{ type: "wait", ms: 1500 },
{ type: "getText" },
{ type: "screenshot", value: "after-load.png" }
],
expect: [
{ kind: "text", target: "body", contains: "Test" }
]
})
```
テストが通れば `ok: true` が返り、failures は空になる。