sync: update from private repo (f6d625db)
CI / build-and-test (push) Has been cancelled

This commit is contained in:
oss-sync
2026-06-26 03:35:45 +00:00
parent 29ccaf1e92
commit b857c33ef6
371 changed files with 31312 additions and 8172 deletions
+153
View File
@@ -0,0 +1,153 @@
# 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 は空になる。