一键导入
report-viewer-spec
Add, run, or fix bugs exposed by end-to-end tests for the report viewer itself (it has grown into a complicated app in its own right)
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Add, run, or fix bugs exposed by end-to-end tests for the report viewer itself (it has grown into a complicated app in its own right)
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
List and run agent tasks defined in _module/agent_tasks/ directories across the repo
Build the Meadow Electron app and launch it in test mode to verify it starts cleanly
Safely clean up the current worktree after verifying no unmerged work would be lost
Run the end-to-end test suite, automatically diagnose and fix failures
Finish a worktree development session - commit, merge to main, and clean up
Understand and extend the regenerable canonical scenario artifact in the e2e report viewer — used for iterating on the viewer's UI against stable, self-documenting data without running real tests
| name | report-viewer-spec |
| description | Add, run, or fix bugs exposed by end-to-end tests for the report viewer itself (it has grown into a complicated app in its own right) |
The e2e report viewer (app/e2e-tests/report-viewer/) has grown into a
complicated application in its own right, so it needs its own end-to-end
test suite — separate from the main Meadow e2e tests in
app/e2e-tests/test-runner/tests/.
When invoked, the user wants to either add a new spec, run the existing suite, or fix a bug a spec exposed. Use this skill to establish shared context, then follow the user's specific ask.
app/e2e-tests/report-viewer/
├── e2e/
│ ├── playwright.config.ts # two-entry webServer (express + vite)
│ ├── fixtures/
│ │ └── publish-flow-fixture.ts # ensurePublishFlowArtifact()
│ ├── pages/
│ │ ├── TickNavComponent.ts # navigate to a specific tick
│ │ └── MeadowHomeFilesComponent.ts # Files-tab assertions
│ └── tests/
│ └── *.spec.ts # one spec per file
├── tsconfig.e2e.json # separate tsconfig for e2e/
└── package.json # has "e2e" and "e2e:install" scripts
Specs should be thin. DOM selectors and interaction sequences belong in
page-object components under e2e/pages/, mirroring the convention used
by the main e2e suite (see
app/e2e-tests/test-runner/src/run/pages/SiteEditorPage/components/FilterPanelComponent.ts
for the reference).
(page: Page, expect: Expect).async methods for
actions and assertions.data-* attribute selectors over structural CSS. The
ScenarioViewer already exposes data-idx, data-tick-index,
data-file-path, and data-file-status; add more when a new spec
needs a stable hook rather than relying on class names or text content.Existing components:
TickNavComponent.goToTick(n) — 1-indexed tick navigation via the
header dropdown. Throws if the tick isn't in the dropdown.MeadowHomeFilesComponent.activate() / fileEntry(path) /
expectFileNotModified(path) / expectFileCommitted(path) /
getFileStatus(path). Prefer expectFileCommitted when the intent
is "this file should have been committed by the app" — it covers
both uncommitted-new and uncommitted-modified. Use
expectFileNotModified when the tighter "shouldn't have local edits"
assertion is what you want.cd app/e2e-tests/report-viewer
# First time only (or after package-lock changes):
npm install
npm run e2e:install # installs chromium
# Run the suite:
npm run e2e
# Run a single spec:
npm run e2e -- tests/sanity.spec.ts
# Run with UI / headed mode for debugging:
npm run e2e -- --headed
First-run cost. The very first run builds the cached publish-flow
fixture, which shells out to the main test-runner CLI and actually runs
publish-flow.spec.ts (Docker containers, MinIO, any extension backing
services, the works). Expect it to take a couple of minutes. Subsequent
runs reuse the cache and are fast.
Port isolation. The e2e suite runs on dedicated ports 3556 (server)
and 5275 (client) — NOT the /dev defaults of 3456/5175. This is
deliberate so the suite works regardless of what dev servers other
worktrees are running. The server and vite configs accept
REPORT_VIEWER_PORT and REPORT_VIEWER_CLIENT_PORT env vars (defaults
preserved for /dev); e2e/playwright.config.ts sets them for its
webServer subprocesses and uses reuseExistingServer: false.
All specs share a single fixture: the artifact directory produced by running
app/e2e-tests/test-runner/tests/publish-flow.spec.ts.
app/e2e-tests/report-viewer/e2e/fixtures/publish-flow-fixture.ts
— exports ensurePublishFlowArtifact() which returns
{ runId, testSlug, artifactDir }.publish-flow.spec.ts contents (first 12 chars).rv-fixture-<key>.~/meadow-e2e-artifacts/current/rv-fixture-<key>/publish-flow-uploads-files-to-minio/
(lives under the standard artifacts root so the report viewer server
can read it with no extra plumbing).status.txt in the
test slug dir says passed.npx tsx src/cli.ts --run-id <stableId> --grep "Publish flow" inside
app/e2e-tests/test-runner/. Assumes test-runner deps are already installed
(quickcheck does this). It bypasses slowcheck.sh to avoid the
npm install --force on every invocation.rv-fixture-* directory:
rm -rf ~/meadow-e2e-artifacts/current/rv-fixture-*
import { test, expect } from "@playwright/test";
import {
ensurePublishFlowArtifact,
type PublishFlowFixture,
} from "../fixtures/publish-flow-fixture.js";
let fixture: PublishFlowFixture;
test.beforeAll(() => {
fixture = ensurePublishFlowArtifact();
});
test("...", async ({ page, request }) => {
const { runId, testSlug } = fixture;
// API-level assertions: await request.get(`/api/${runId}/${testSlug}/...`)
// UI-level assertions: await page.goto(`/${runId}/${testSlug}`)
});
One test per file. Reuse the cached fixture. Prefer a cheap API-level sanity check before the UI assertions — it produces a clearer failure message if the fixture is malformed.
Tick X/Y: counter is hidden until a tick is selected. On initial
scenario load, ScenarioViewer renders Tick: -- (dash) until the
user scrubs the video or picks a tick from the dropdown. Don't assert
on the X/Y text unless your test first selects a tick.hasTicks via the dropdown button. The tick dropdown button
is present whenever hasTicks=true, so page.getByRole("button", { name: /^Tick/ }) is a reliable way to prove the client saw ticks
in the manifest.page.getByText(testSlug) being
visible is a simple proof that the SPA router mounted
ScenarioViewer for the target artifact.(Served by app/e2e-tests/report-viewer/src/server/index.ts on port 3456,
proxied through Vite at 5175.)
GET /api/:runId/:testSlug/manifest — full manifest, includes
ticks: ProcessedTick[]GET /api/:runId/:testSlug/snapshots — MeadowHome commit snapshotsGET /api/:runId/:testSlug/minio-snapshots — S3/MinIO snapshotsGET /api/:runId/:testSlug/state-repos — extension-contributed state
repos with their rendering meta (display name, key map, etc.)GET /api/:runId/:testSlug/state-snapshots/:repoName — snapshots for
a named state repoGET /api/:runId/:testSlug/state-snapshot/:repoName/:hash — table
contents at a state-repo commitThe client route for a scenario is /:runId/:testSlug, rendered by
ScenarioViewer.tsx.
For the current publish-flow.spec.ts, the test slug is
publish-flow-uploads-files-to-minio (derived as
title.replace(/[^a-zA-Z0-9]+/g, "-").toLowerCase()). If the test title
ever changes, update PUBLISH_FLOW_TEST_SLUG in
publish-flow-fixture.ts.
npm run e2e in app/e2e-tests/report-viewer/ and confirm it passes../quickcheck from the repo root (per project AGENTS.md). If
changes are limited to app/e2e-tests/, the scoped check is faster:
cd app/e2e-tests && _module/scripts/quickcheck
Quickcheck type-checks the e2e/ directory via tsconfig.e2e.json but
does NOT run the Playwright tests — those are opt-in via npm run e2e.Many specs in this suite are intentionally written to fail first —
they are tripwires pointing at real bugs in the Meadow app (e.g.
"app/app_config.yaml should not be marked modified at tick 2"). When
the user asks to fix the underlying bug, use this tight loop:
manifest.json and ticks.jsonl tell it. If a file is reported as
modified/new/etc., check:
git status against the saved state repo at
~/meadow-e2e-artifacts/current/<runId>/<testSlug>/meadowHome-state-repo
(use --git-dir=.git --work-tree=.). If git itself agrees with the
tick data, the bug is NOT in fast_git_ops or the report viewer —
it's upstream in the Meadow app (some code path writes to the file
without committing).fast_git_ops (see
app/native_utils/fast_git_ops/fast_git_ops_code/src/main.rs) or in
how test-fixtures.ts consumes its output.app/backend/src/index.ts startServer()
where init helpers like ensureAppConfigInitialized run. Have the
init helper report whether it patched the file, and commit when it
did — not only on first creation. See the existing
ensureAppConfigInitialized / ensureResourcesConfigInitialized
pattern for reference.rm -rf ~/meadow-e2e-artifacts/current/rv-fixture-*
npm run e2e in
app/e2e-tests/report-viewer/. The fixture builder will rerun
publish-flow.spec.ts (slow, ~20s) to produce a fresh artifact, then
Playwright runs every spec against it. Confirm the target spec flips
from red to green — and that no other spec regresses../quickcheck from the repo root to catch any type or lint
fallout from the app-side fix.Cache key caveat. The fixture cache key is a hash of
publish-flow.spec.ts alone — it does NOT invalidate when the Meadow
app code changes. That's why step 3 is mandatory for app-side fixes.
Adjacent-bug heuristic. When you fix one "written but not committed" bug, look at the same startup sequence for sibling bugs in the same family, then have the user decide whether to add sibling specs before or after the fix. Writing the failing spec first is valuable because it proves the tripwire works.
Per project AGENTS.md: flaky tests are never acceptable. If a spec fails sometimes and passes sometimes, fix the root cause — don't retry it away. An intentionally failing regression spec (tripwire for an unfixed bug) is NOT flakiness — it's a controlled, deterministic failure that should stay red until the underlying bug is fixed. Don't silence or skip such specs; the failure is the signal.