Skip to content

fix(ui): surface failure evidence first on the execution page - #430

Open
PhenX wants to merge 7 commits into
mainfrom
claude/audit-quick-wins-ui
Open

fix(ui): surface failure evidence first on the execution page#430
PhenX wants to merge 7 commits into
mainfrom
claude/audit-quick-wins-ui

Conversation

@PhenX

@PhenX PhenX commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

What & why

The UI slice of the failing-run data audit's quick wins (§7 items 1, 5, 6, 7, 11 and 14), plus the optional tree-view item. Each item is one commit.

1. Failure evidence expanded by defaultfix(ui): surface failure evidence first on the execution page

  • app/pages/test-run-cases/[id].vue — the test-source and failure-evidence cards get :default-folded="false"; console and network get storage keys and reveal through the jump chips.
  • app/components/test-case/TestCaseEvidenceCard.vue, TestSourceCard.vue — a defaultFolded passthrough.
  • app/components/test-case/TestCaseConsoleCard.vue, TestCaseNetworkRequests.vue — an optional storageKey turns them into CollapsibleSectionCards that start folded with a peek (entry count + first entry, ANSI-stripped); the Artifacts tab keeps them as plain cards. Cookie persistence is unchanged.
  • apps/docs/evidence.md — figure caption and evidence-funnel paragraph.
  • The cluster page's Test evidence section is a plain CollapsibleSectionCard, not this component, and cluster-page-layout.spec.ts asserts it starts folded, so it was left alone.

5. Rail order and dead jump chipsfix(ui): align the diagnosis rail breakpoint and gate jump chips on rendered sections

  • app/pages/test-run-cases/[id].vuelg:order-*xl:order-* to match xl:grid-cols-[3fr_2fr]; the environment-diff, visual-diff and DOM-snapshot chips are gated on an available boolean.
  • app/components/shared/EnvironmentDiffCard.vue, app/components/test-case/VisualDiffCard.vue, DomSnapshotCard.vue — emit available with exactly the condition the card renders on.

6. Locator rendering and diff arrowfix(ui): render the failing locator as code and label the environment diff sides

  • shared/locator-healing.ts — new locatorExpression(method, args), the inverse of the server's expression parser (getByRole('row'), getByLabel('Email address'), options object, regex kept verbatim). Unit-tested in tests/unit/locator-healing.test.ts.
  • app/components/shared/LocatorHealingPanel.vue — the failing locator renders through LocatorCode; copy and fix-prompt use the same text.
  • app/components/shared/EnvironmentDiffCard.vue — a caption row labels the sides This runLast pass, run #N; colors unchanged.

7. Attempt chips become linksfeat(ui): link attempt chips to their sibling executions

  • shared/handlers/test-cases.tsgetTestRunCase looks up the sibling rows (same run, test case and browser) and stamps executionId on each attempt. The demo router already calls this shared handler, so there was nothing to mirror; app:check:demo passes. The demo seed stores one row per test, so in the demo only the current attempt has a row and the others render as non-link chips.
  • types/api.ts — a shared AttemptOutcome type with executionId.
  • app/components/test-case/TestCaseSummary.vue — sibling attempts are links; the current attempt is the ringed non-link chip with aria-current.
  • app/components/test-case/TestCaseVerdictCard.vue — the strip is a labelled group and each square has a visible keyboard focus.
  • apps/docs/ui-overview.md — one sentence.

11. Three small fixesfix(ui): fix the AI card copy, the missing-cluster state and the demo Share button

  • app/components/test-case/TestCaseAiCard.vue — points at the card's own Copy prompt button.
  • app/pages/failure-clusters/[id].vueErrorState for a missing cluster; Share hidden in demo mode.
  • app/pages/test-run-cases/[id].vue — Share hidden in demo mode (mirroring the share-link routes would need the share_links table and the settings route in the in-browser DB, so hiding was the trivial option).
  • apps/docs/share-links.md — notes that the demo has no share links.

14. One retry-command builder per runrefactor(ui): build the run retry command from one shared composable

  • app/composables/useRunRetryCommand.ts — derives the failing set once from the run's execution rows (final attempt per test and Playwright project, so a passed-on-retry test is excluded, matching the clusters tab), builds the command with file:line and project, and shares the mode via useState.
  • app/components/run/RunSummary.vue, FailureGroups.vue, app/pages/test-runs/[id].vue — both buttons use it; FailureGroups receives the run's test cases as a prop.
  • ARCHITECTURE.md — composable listed.

Optional: tree viewfeat(ui): show the error line and cluster badge on failing tree-view rows

  • app/components/run/TestCasesTree.vue, TestCasesList.vue — failing tree rows carry the same one-line error and cluster badge as the flat list. Failures-first sorting in the tree was not added.

Not in this PR: the audit document itself (it stays on its own branch), and the gather-evidence.png docs illustration, which this environment cannot regenerate faithfully (brand icons resolve from a CDN and render blank offline). The alt text and caption were updated to describe the new default.

How was it tested?

From apps/application/: app:typecheck, app:lint, app:format:check, app:test:unit (120 files, 1616 tests) and app:check:demo all pass.

Playwright, against a dev server: test-run-case-page, cluster-page-layout, run-page-filters, failure-clusters, mobile-responsiveness, share-links, dashboard-ui, test-case-history, trace-insights, keyboard-nav, export, performance-ui, inline-help — all pass. (One first pass had two timeouts caused by the dev server compiling under load and by a hand-started server missing the PIWI_SHARE_LINKS_ENABLED flag the config injects; both specs pass on a fresh server.)

Checklist

  • PR title follows Conventional Commits (type(scope): subject)
  • Tests added/updated for behavior changes
  • Docs updated if user-facing (apps/docs/, README, or reporter README)

🤖 Generated with Claude Code

https://claude.ai/code/session_0122WucKkRwT2weCog4xDZ3w


Generated by Claude Code

The Diagnosis tab opened with the screenshot folded away while console and
network were always expanded. The test source and failure evidence cards
now start expanded, and console/network become foldable cards with a peek
line (entry count plus the first entry). Fold choices still persist per
user through the existing cookie.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122WucKkRwT2weCog4xDZ3w
…endered sections

The Diagnosis grid splits into two columns at xl while the column order
flipped at lg, which pushed the verdict/cluster/AI rail under the whole
evidence funnel between 1024 and 1279 px. Both now switch at xl. The
environment-diff, visual-diff and DOM-snapshot cards report whether they
rendered anything, so their jump chips only appear when there is a section
to scroll to.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122WucKkRwT2weCog4xDZ3w
… diff sides

The alternative-locators panel printed the failing locator as a serialized
object (getByRole({"role":"row"})) while every alternative rendered as
Playwright source. A shared locatorExpression() formatter turns the parsed
{ method, args } back into the expression a developer writes, highlighted
through LocatorCode and used for the copy and fix-prompt text too. The
environment diff now captions its two sides as this run and the last pass.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122WucKkRwT2weCog4xDZ3w
Every attempt is its own execution row, but the Attempts tile only showed
badges with a title. The execution detail now carries the sibling execution
id per attempt (server and demo share the handler), so each chip links to
that attempt while the viewed one stays a ringed, non-link chip. The
recent-executions strip on the verdict card gets a group label and a
visible keyboard focus on each square.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122WucKkRwT2weCog4xDZ3w
… Share button

The AI card's not-configured copy named an Export menu item that does not
exist; it now points at the card's own Copy prompt button. A missing
cluster renders through the shared ErrorState like every other detail
page. The Share button is hidden in demo mode, where the share-link routes
are not mirrored.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122WucKkRwT2weCog4xDZ3w
The run summary and the failure-clusters tab each built their own retry
command, one with file:line and Playwright project and one without, so the
two buttons on the same run copied different commands. useRunRetryCommand
derives the failing set once from the run's execution rows (final attempt
per test and project) and shares the mode, so both buttons agree.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122WucKkRwT2weCog4xDZ3w
…rows

The run page's tree view dropped the one-line error and the cluster badge
the flat list shows on failing rows, so switching views lost the very
information a failing run is opened for. Both now render on failing tree
rows with the same markup as the list.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122WucKkRwT2weCog4xDZ3w
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Reporter (./packages/reporter)

Status Category Percentage Covered / Total
🔵 Lines 74.9% 2262 / 3020
🔵 Statements 73.24% 2573 / 3513
🔵 Functions 77.97% 393 / 504
🔵 Branches 67.36% 1810 / 2687
File CoverageNo changed files found.
Generated in workflow #1484 for commit e59297e by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Application (./apps/application)

Status Category Percentage Covered / Total
🔵 Lines 43.18% 5723 / 13253
🔵 Statements 42.41% 6662 / 15705
🔵 Functions 42.26% 1114 / 2636
🔵 Branches 38.74% 4998 / 12899
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
apps/application/app/composables/useRunRetryCommand.ts 0% 0% 0% 0% 16-45
apps/application/shared/locator-healing.ts 91.66% 86.74% 100% 91.66% 115, 153-155, 232-233
apps/application/shared/handlers/test-cases.ts 0% 0% 0% 0% 20-498
Generated in workflow #1484 for commit e59297e by the Vitest Coverage Report Action

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants