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

7.2 KiB
Raw Permalink Blame History

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

テスト開始前にワークスペースへ書き込むファイルを指定する。アプリが読み取る入力データを事前配置するために使う。

"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 targetCSS セレクタ), contains ページテキスト全体が contains を含む。target は情報的なセレクタ(精度向上には getText アクションを先に実行)
file target(ワークスペース相対パス), contains 指定ファイルが存在し、その内容が contains を含む

重要: kind"text" または "file" のみ有効。他の値は常に失敗として記録される(サイレントパスなし)。contains が空文字列の場合も評価は行われる(空文字列はどの文字列にも含まれるため通過)。

"expect": [
  { "kind": "text", "target": "[data-testid=\"status\"]", "contains": "保存OK" },
  { "kind": "file", "target": "output/notes.md", "contains": "edited-by-e2e" }
]

戻り値

{
  "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 の例

{
  "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 フィールドは常に [] を返す。ブリッジの動作確認は expectkind: "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 は空になる。