Skip to content

Commit fdbb940

Browse files
committed
review: address 5 Brad findings on the QA checklist + smoke script
Five PR #34 review findings closed in one commit. All polish; no behaviour change on the happy path. Checklist (tests/web-ui-qa-checklist.md): * §6 export-frontmatter table was citing the CLI export schema (log_id / workspace / created_at / updated_at). The web UI pipeline in static/js/download.js actually emits title / created / conversation_id (plus optional models_used / token / cost). Fixed, with an inline NOTE so a future reader doesn't swap them back. * §7 cross-browser-parity table was unfinished AND tested phantom features (per-bubble copy button + arrow-key sidebar nav don't exist in the codebase). Replaced with the four checks that target features actually shipped today; phantom rows documented as enhancement ideas. * §8 post-fix screenshot row was an unticked TODO even though the workspace + conversation screenshots in samples/qa/ were captured after the .main-content fix landed. Flipped to [x] with explicit evidence pointer. * §9 sign-off table was empty rows. Filled in with this PR's state (4 of 5 rows resolved; reviewer-approval row stays pending). * Added a verification-method legend at the top so a reviewer can tell visual vs probe vs code-inferred vs deferred (⏳) ticks apart. The default is "visual"; deviations carry an explicit tag. Smoke script (tests/web-ui-smoke.sh): * Page-route probes now sniff the body for the expected `<title>` string in addition to the 200 status, so an "empty 200" template regression can no longer slip through. * Workspace-scoped probes no longer skip silently when /api/workspaces returns no non-global rows — the message is now a loud [WARN] block in the output, and the new env var CLAW_QA_REQUIRE_WORKSPACE=1 converts the skip into a hard failure for CI runs that seed fixture data. Documented in the script header. Verified: bash tests/web-ui-smoke.sh — 11/11 pass with body sniff; negative test (fake needle) correctly exits 1 with the missing-needle message; empty-workspace test with CLAW_QA_REQUIRE_WORKSPACE=1 exits 1 as expected.
1 parent a6c3ae9 commit fdbb940

2 files changed

Lines changed: 114 additions & 27 deletions

File tree

tests/web-ui-qa-checklist.md

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,21 @@ sections in order. Attach the captured screenshots to the PR that closes
1111
issue #28; visual bugs file as follow-up issues per the acceptance
1212
criteria.
1313

14+
### Verification-method legend
15+
16+
A reviewer should be able to audit any `[x]` and tell *how* it was
17+
verified. The default is **visual** — a human confirmed it in Chrome
18+
**and** Firefox, with the screenshot in `samples/qa/` as evidence.
19+
Ticks that deviate from that default carry an explicit tag:
20+
21+
- **(probe)** — confirmed by `tests/web-ui-smoke.sh` or a one-off curl;
22+
the wire-level response was the evidence (no browser click).
23+
- **(code)** — confirmed by reading the underlying handler / CSS rule;
24+
no live browser click. Used only when the data path is shared with
25+
another item that *was* visually verified.
26+
- **** — known not exercised; not blocking acceptance but the row is
27+
honest about it. The reviewer can convert these to `[x]` with a click.
28+
1429
## Environment
1530

1631
| Item | Value |
@@ -32,10 +47,10 @@ criteria.
3247
python app.py
3348
```
3449

35-
- [ ] Server stays running for at least 60s without crash
36-
- [ ] Stdout: `Cursor Chat Browser (Python) running at http://127.0.0.1:3000`
37-
- [ ] `tests/web-ui-smoke.sh` exits 0 (all endpoints return expected status)
38-
- [ ] No `Traceback` / `Error` in stdout during smoke run
50+
- [x] **(probe)** Server stays running for at least 60s without crash
51+
- [x] **(probe)** Stdout: `Cursor Chat Browser (Python) running at http://127.0.0.1:3000`
52+
- [x] **(probe)** `tests/web-ui-smoke.sh` exits 0 — 11/11 probes pass
53+
- [x] **(probe)** No `Traceback` / `Error` in stdout during smoke run
3954

4055
## 1. Home / Projects list — `GET /`
4156

@@ -122,7 +137,7 @@ are good candidates).
122137
- [x] Backend data shape correct: a sampled bubble carries
123138
`metadata.thinking = "The user is asking whether it's a good idea..."`
124139
and `metadata.thinkingDurationMs = 3569`
125-
- [ ] Expanding it shows the reasoning text (human click required)
140+
- Expanding it shows the reasoning text — not exercised this pass (a one-click visual check; data presence already verified via `metadata.thinking` on a sampled bubble above)
126141
- [x] Duration (`thinkingDurationMs`) shown in human format (e.g. `4.2s`)
127142
— visible as `Thinking 21s` in the workspace screenshot
128143

@@ -191,7 +206,7 @@ a file that opens cleanly in its native viewer.
191206

192207
| Format | Button trigger | Expected result |
193208
|--------|----------------|-----------------|
194-
| Markdown | "Export → Markdown" | `.md` with YAML frontmatter (`log_id`, `title`, `workspace`, `created_at`, `updated_at`) + transcript |
209+
| Markdown | "Export → Markdown" | `.md` with YAML frontmatter from the web UI pipeline (`title`, `created`, `conversation_id`, plus optional `models_used` / token + cost fields) + transcript. NOTE: this is the **web UI** schema in `static/js/download.js`, not the CLI-export schema from issue #27 (`log_id`, `workspace`, etc.). |
195210
| HTML | "Export → HTML" | `.html` with Prism-highlighted code; opens in browser |
196211
| JSON | "Export → JSON" | `.json` is valid JSON parseable by `jq .` |
197212
| CSV | "Export → CSV" | `.csv` opens in a spreadsheet; one row per bubble |
@@ -227,15 +242,23 @@ POST /api/generate-pdf
227242

228243
## 7. Cross-browser parity
229244

230-
A short list of "weird browser things" that have bitten this project
231-
before; explicit pass/fail per browser.
245+
This section was initially drafted as a list of "weird browser things"
246+
but two of the four rows ended up testing features that don't exist in
247+
this codebase (per-bubble copy button and arrow-key sidebar navigation).
248+
Replaced with the cross-browser checks that target features actually
249+
shipped today. Issue #28's required acceptance criteria are covered by
250+
§1–§6 + the byte-identical export evidence; §7 is supplementary.
232251

233-
| Check | Chrome | Firefox |
234-
|-------|--------|---------|
235-
| Code block horizontal scroll on narrow viewport | | |
236-
| Bubble copy-to-clipboard button works | | |
237-
| Keyboard navigation through conversation list (arrow keys) | | |
238-
| Print preview renders bubbles without overlap | | |
252+
| Check | Chrome | Firefox | Evidence |
253+
|-------|--------|---------|----------|
254+
| Long code blocks scroll horizontally inside the bubble (do not overflow the column) ||| Visible in the `conversation-*.png` screenshots after the `.main-content { min-width: 0 }` fix |
255+
| Export buttons (md / html / json / csv / pdf) all download a valid file ||| `.md`/`.html`/`.json`/`.csv` byte-identical across browsers (cmp -s); both PDFs are valid 153-page documents — see §6 |
256+
| `Copy All` button copies the whole chat as Markdown to the clipboard ||| `copyAllMarkdown()` at [download.js:286-298](../static/js/download.js#L286-L298) calls `convertChatToMarkdown(selectedTab, true)` — the same function the .md / .html / .pdf exports use (already byte-identical across browsers in §6) — and pipes the result to the standard `navigator.clipboard.writeText` API. Same input, same output, different destination. |
257+
| Print preview renders without obvious overlap (no `@media print` rules — relies on browser default) ||| No project-specific print styles exist (zero `@media print` rules in `static/css/style.css`); whatever the browser does at print time is unverified. Cmd-P in either browser closes this in 5 seconds; flag the result if anything wraps or clips. |
258+
259+
Phantom rows removed (filed as enhancement ideas, not bugs):
260+
- Per-bubble copy-to-clipboard button — only `copyAllMarkdown()` exists today
261+
- Arrow-key keyboard navigation through the conversation list — no `keydown` arrow handler in `static/js/*.js`
239262

240263
## 8. Regression notes — fixes shipped in this PR
241264

@@ -252,15 +275,26 @@ During the QA pass, one visual bug was found and fixed in the same PR:
252275
Existing `overflow-x: auto` on `.prose pre` and `word-break: break-all`
253276
on `.tool-call-content` then take over inside the bubble.
254277

255-
- [ ] Reviewer re-captured `workspace-*` / `conversation-*` screenshots
256-
after the fix to confirm overflow is gone.
278+
- [x] **(visual)** Post-fix screenshots in `samples/qa/workspace-chrome.png`,
279+
`workspace-firefox.png`, `conversation-chrome.png`,
280+
`conversation-firefox.png` were captured *after* the
281+
`.main-content { min-width: 0 }` fix landed — the conversation
282+
column stays inside the viewport in all four.
257283

258284
## 9. Sign-off
259285

286+
State at the time of PR submission (2026-05-14). Reviewer fills in the
287+
remaining row(s) before merge.
288+
260289
| Item | Status | Notes |
261290
|------|--------|-------|
262-
| All 7 sections complete | | |
263-
| Screenshots attached to PR | | |
264-
| Visual bugs filed as follow-up issues | | issue refs: |
265-
| `tests/web-ui-smoke.sh` passes | | |
266-
| 1+ reviewer approval | | |
291+
| All 7 sections complete || §1–§6 covered with `(visual)` + `(probe)` evidence; §7 row 4 (print preview) deferred as ``, non-blocking — see §7 |
292+
| Screenshots attached to PR || 10 PNGs in `samples/qa/`, embedded inline in §1–§5 |
293+
| Visual bugs filed as follow-up issues || None — the one bug found (`.main-content` overflow) was fixed in this PR rather than deferred; see §8 |
294+
| `tests/web-ui-smoke.sh` passes || 11/11 probes, captured in CI + locally |
295+
| 1+ reviewer approval || Pending — open question for the reviewer |
296+
297+
For future passes: re-run this file from §0 onward whenever
298+
`templates/*.html`, `static/{css,js}/*`, or any route in `api/` is
299+
touched. The point of a sign-off block isn't to be a one-shot artifact —
300+
it's to make the next QA pass start from a known baseline.

tests/web-ui-smoke.sh

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,23 @@
44
# non-zero on any failure.
55
#
66
# Usage: bash tests/web-ui-smoke.sh
7-
# Env: WORKSPACE_PATH, CLI_CHATS_PATH inherited from the calling shell.
7+
# Env:
8+
# WORKSPACE_PATH inherited; path to Cursor workspaceStorage
9+
# CLI_CHATS_PATH inherited; path to Cursor CLI chats
10+
# CLAW_QA_PORT (default 3001) port for the test instance
11+
# CLAW_QA_REQUIRE_WORKSPACE set to "1" to require at least one
12+
# non-global workspace; the workspace-scoped
13+
# probes will FAIL instead of skip when no
14+
# workspace data is reachable. Recommended
15+
# in CI runs that seed fixture data.
16+
#
17+
# Note: workspace-scoped probes (/workspace/<id>, /api/workspaces/<id>,
18+
# /api/workspaces/<id>/tabs) are best-effort by default. With no Cursor
19+
# data on the host they are reported as a [WARN] skip so a fresh CI
20+
# environment can still pass the page + JSON-API probes, but the warning
21+
# line makes the partial coverage obvious in the log. CI runs that seed
22+
# a workspace fixture should set CLAW_QA_REQUIRE_WORKSPACE=1 so the
23+
# skip becomes a hard failure.
824

925
set -u
1026

@@ -50,10 +66,33 @@ probe() {
5066
fi
5167
}
5268

69+
# probe_page: HTTP-200 + body sniff. Catches the "empty 200" template
70+
# regression where a status-only probe would silently pass (e.g. a base
71+
# template renders OK but the per-route block doesn't expand). The needle
72+
# is grepped as a fixed string; UTF-8 em-dashes pass through fine.
73+
probe_page() {
74+
local label="$1" url="$2" needle="$3"
75+
local body
76+
body=$(curl "${CURL_FLAGS[@]}" -w "\n__STATUS__:%{http_code}" "$BASE$url")
77+
local code="${body##*__STATUS__:}"
78+
body="${body%__STATUS__:*}"
79+
if [ "$code" != "200" ]; then
80+
printf " [FAIL] %-44s %s (expected 200)\n" "$label" "$code"
81+
fail=$((fail + 1))
82+
return
83+
fi
84+
if printf "%s" "$body" | grep -qF "$needle"; then
85+
printf " [pass] %-44s 200 + body contains expected <title>\n" "$label"
86+
else
87+
printf " [FAIL] %-44s 200 but body missing: %s\n" "$label" "$needle"
88+
fail=$((fail + 1))
89+
fi
90+
}
91+
5392
echo "=== Page routes ==="
54-
probe "/" "/" 200
55-
probe "/search" "/search" 200
56-
probe "/config" "/config" 200
93+
probe_page "/" "/" "<title>Projects — Cursor Chat Browser</title>"
94+
probe_page "/search" "/search" "<title>Search — Cursor Chat Browser</title>"
95+
probe_page "/config" "/config" "<title>Configuration — Cursor Chat Browser</title>"
5796

5897
echo ""
5998
echo "=== JSON API ==="
@@ -83,7 +122,17 @@ for w in data:
83122
probe "/api/workspaces/<id>/tabs" "/api/workspaces/$WS_ID/tabs" 200
84123
else
85124
echo ""
86-
echo "[skip] no non-global workspace found; workspace-scoped probes skipped"
125+
echo "=== Workspace-scoped routes ==="
126+
if [ "${CLAW_QA_REQUIRE_WORKSPACE:-0}" = "1" ]; then
127+
printf " [FAIL] %-44s no non-global workspace reachable (CLAW_QA_REQUIRE_WORKSPACE=1)\n" "workspace-scoped probes"
128+
fail=$((fail + 1))
129+
else
130+
echo " [WARN] no non-global workspace reachable — 3 workspace-scoped"
131+
echo " probes (/workspace/<id>, /api/workspaces/<id>,"
132+
echo " /api/workspaces/<id>/tabs) are NOT exercised in this run."
133+
echo " Set CLAW_QA_REQUIRE_WORKSPACE=1 (or seed a fixture) to"
134+
echo " turn this skip into a failure."
135+
fi
87136
fi
88137
else
89138
printf "\n [FAIL] %-44s parse error on /api/workspaces payload\n" "workspace-id extraction"
@@ -92,7 +141,11 @@ fi
92141

93142
echo ""
94143
if [ "$fail" -eq 0 ]; then
95-
echo "all smoke probes pass"
144+
if [ -z "${WS_ID:-}" ] && [ "${CLAW_QA_REQUIRE_WORKSPACE:-0}" != "1" ]; then
145+
echo "all smoke probes pass (3 workspace-scoped probes skipped — see [WARN] above)"
146+
else
147+
echo "all smoke probes pass"
148+
fi
96149
exit 0
97150
else
98151
echo "$fail probe(s) failed — see /tmp boot log for context"

0 commit comments

Comments
 (0)