Skip to content

Latest commit

 

History

History
315 lines (241 loc) · 15.5 KB

File metadata and controls

315 lines (241 loc) · 15.5 KB

Web UI — manual QA checklist

Companion document for issue #28. Run this whenever the web UI (templates, static/js/*, or any route in api/) is touched. Each section below has a backend smoke result captured automatically by tests/web-ui-smoke.sh and a visual checklist that a human reviewer fills in with Chrome + Firefox screenshots.

Boot the app with python app.py (default port 3000) and follow the sections in order. Attach the captured screenshots to the PR that closes issue #28; visual bugs file as follow-up issues per the acceptance criteria.

Verification-method legend

A reviewer should be able to audit any [x] and tell how it was verified. The default is visual — a human confirmed it in Chrome and Firefox, with the screenshot in samples/qa/ as evidence. Ticks that deviate from that default carry an explicit tag:

  • (probe) — confirmed by tests/web-ui-smoke.sh or a one-off curl; the wire-level response was the evidence (no browser click).
  • (code) — confirmed by reading the underlying handler / CSS rule; no live browser click. Used only when the data path is shared with another item that was visually verified.
  • — known not exercised; not blocking acceptance but the row is honest about it. The reviewer can convert these to [x] with a click.

Environment

Item Value
OS / version
Python version python3 --version
Browser A Chrome
Browser A version
Browser B Firefox
Browser B version
Repo SHA git rev-parse HEAD
Cursor data default ~/.config/Cursor/User/workspaceStorage (or override via WORKSPACE_PATH)
Reviewer
Date

0. Server launch

python app.py
  • (probe) Server stays running for at least 60s without crash
  • (probe) Stdout: Cursor Chat Browser (Python) running at http://127.0.0.1:3000
  • (probe) tests/web-ui-smoke.sh exits 0 — 11/11 probes pass
  • (probe) No Traceback / Error in stdout during smoke run

1. Home / Projects list — GET /

Backend smoke: expect HTTP 200 and the page sniff must include <title>Projects — Cursor Chat Browser</title> and the text Cursor Chat Browser.

Chrome:

home / Chrome

  • Page loads, no JS console errors
  • Workspace cards render with workspace name + conversation count
  • "Other chats" card present for global storage
  • Clicking a workspace card navigates to /workspace/<id>
  • Dark / light mode toggle works (if present)

Firefox:

home / Firefox

  • Same checks pass as Chrome

2. Workspace detail — GET /workspace/<workspace_id>

Backend smoke: expect HTTP 200, content length > 5KB. JSON endpoints /api/workspaces/<id> and /api/workspaces/<id>/tabs must both return 200.

Chrome:

workspace detail / Chrome

  • Conversation list (left panel) renders with at least one row
  • Each row shows title, timestamp, model name
  • Clicking a conversation loads its bubbles in the right panel
  • Last-updated sort order is descending (newest first)
  • Search box at the top filters conversations as you type
  • No 404 / 500 in the network tab when switching conversations
  • Right panel stays inside viewport (regression check for the .main-content { min-width: 0 } fix landed in this PR — see §8)

Firefox:

workspace detail / Firefox

  • Same checks pass as Chrome

3. Conversation view — markdown / code / tools / thinking

Open any conversation that contains code blocks, tool calls, and a thinking block (the seeded cppa-cursor-browser PR review conversations are good candidates).

Markdown:

  • Headers #, ##, ### render at distinct sizes
  • Inline `code` renders in monospace with background tint
  • Fenced code blocks render with syntax highlighting (Prism) (backend-verified: bubble text payload contains fenced-code-block delimiters; conversation screenshot shows highlighted output)
  • Numbered + bulleted lists render with correct indentation
  • Inline links are clickable, open in a new tab
  • Tables render with cell borders

Tool calls:

  • Tool name shown in the bubble header (backend-verified: sampled bubble had toolCalls[0].name = "glob_file_search")
  • Tool input (params) shown in a collapsible / styled block (backend-verified: toolCalls[0] carried a non-empty parameters field)
  • Tool output (result) shown below the input (rendered in the conversation screenshot)
  • Tool status (success / error) visually distinguishable (backend-verified: toolCalls[0].status = "completed"; CSS rules .tool-call-status.completed / .error / .running in style.css)
  • Long tool outputs wrap or scroll, not overflow horizontally (.tool-call-content { overflow: auto; word-break: break-all } plus the .main-content { min-width: 0 } fix landed in this PR)

Thinking blocks:

  • Collapsible "Thinking" section is collapsed by default (verified in the workspace screenshot — Thinking 21s chip visible)
  • Backend data shape correct: a sampled bubble carries metadata.thinking = "The user is asking whether it's a good idea..." and metadata.thinkingDurationMs = 3569
  • ⏳ 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)
  • Duration (thinkingDurationMs) shown in human format (e.g. 4.2s) — visible as Thinking 21s in the workspace screenshot

XSS sanitization (regression check from test_xss_sanitization.py):

  • No raw <script> tags visible in any bubble
  • No onerror / onclick handlers fire on hover / click of bubble content

Chrome:

conversation view / Chrome

Firefox:

conversation view / Firefox

4. Search — GET /search + GET /api/search?q=...

Backend smoke:

  • /search (page) → HTTP 200
  • /api/search?q=<known-term>HTTP 200
  • /api/search (no q) → HTTP 400 with body {"error":"No search query provided"}

Chrome:

search results / Chrome

Firefox:

search results / Firefox

  • Search box at /search accepts input
  • Submitting an empty query shows a useful error, not a 500 page
  • A known-good query (e.g. project — returned 9 results in the screenshot) returns results
  • Each result shows: workspace name, chat title, snippet with the query highlighted
  • Clicking a result navigates to the correct conversation (backend-verified: /workspace/global?tab=<chatId> returns HTTP 200 with the workspace template; JS handles the ?tab= param client-side to scroll to the matching conversation)
  • No layout breakage with very long query strings (paste a 500-char query)

5. Config page — GET /config

Backend smoke: HTTP 200, content length > 5KB. /api/detect-environment must return HTTP 200.

Chrome:

config / Chrome

Firefox:

config / Firefox

  • Current workspace path shown
  • "Change workspace" form accepts a valid path and applies it
  • Invalid path (traversal, missing dir) is rejected with a clear error
  • Environment auto-detect indicator matches actual platform (Linux native, WSL, macOS, SSH remote, Windows)

6. Export functionality

Open any conversation, then trigger each export button. Each must produce a file that opens cleanly in its native viewer.

Format Button trigger Expected result
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.).
HTML "Export → HTML" .html with Prism-highlighted code; opens in browser
JSON "Export → JSON" .json is valid JSON parseable by jq .
CSV "Export → CSV" .csv opens in a spreadsheet; one row per bubble
PDF "Export → PDF" .pdf opens in Acrobat / Preview; pagination clean

Verified during this QA pass — all 5 buttons clicked, each file inspected:

Format File size Validation result
.md 587 KB UTF-8, starts with YAML frontmatter (title, created, conversation_id, models_used, token + cost stats)
.html 663 KB <!DOCTYPE html> + embedded CSS + dark-mode @media (prefers-color-scheme: dark)
.pdf 214 KB file reports "PDF document, version 1.3, 153 page(s)" — opens cleanly
.json 654 KB Valid JSON, top-level keys bubbles, codeBlockDiffs, id, metadata, timestamp, title
.csv 592 KB 391 rows (1 header + 390 bubbles), 21 columns covering tokens, thinking, tool calls

Backend endpoint check (run earlier in this QA pass):

POST /api/generate-pdf
  → HTTP 200, Content-Type: application/pdf, %PDF-1.3 magic, %%EOF terminator
  • All five formats download from Chrome
  • All five formats download from Firefox
  • PDF endpoint returns valid application/pdf over the wire
  • No silent failures — every clicked button produced a file
  • Cross-browser parity proven byte-identical for .md / .html / .json / .csvcmp -s returns equal between Chrome and Firefox outputs. The JS export pipeline in static/js/download.js is browser-agnostic.
  • PDF bytes differ across browsers but both are valid 153-page PDFs — expected because /api/generate-pdf embeds a fresh /CreationDate on each call.

7. Cross-browser parity

This section was initially drafted as a list of "weird browser things" but two of the four rows ended up testing features that don't exist in this codebase (per-bubble copy button and arrow-key sidebar navigation). Replaced with the cross-browser checks that target features actually shipped today. Issue #28's required acceptance criteria are covered by §1–§6 + the byte-identical export evidence; §7 is supplementary.

Check Chrome Firefox Evidence
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
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
Copy All button copies the whole chat as Markdown to the clipboard copyAllMarkdown() at download.js:286-298 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.
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.

Phantom rows removed (filed as enhancement ideas, not bugs):

  • Per-bubble copy-to-clipboard button — only copyAllMarkdown() exists today
  • Arrow-key keyboard navigation through the conversation list — no keydown arrow handler in static/js/*.js

8. Regression notes — fixes shipped in this PR

During the QA pass, two visual overflow bugs were found and fixed in this same PR (both narrow CSS changes, no JS or template churn):

  • .main-content grid column overflowing viewport on the right. The right-hand conversation panel (1fr grid column in .workspace-grid) had no explicit min-width: 0, so any unbreakable child (long code block, long URL, long tool-call-content) was pushing the column wider than the viewport. Header + title rendered fine because they live outside the grid. Fix: added .main-content { min-width: 0; } at static/css/style.css:316–321. Existing overflow-x: auto on .prose pre and word-break: break-all on .tool-call-content then take over inside the bubble.

  • .sidebar-item-time truncation gap. The chat-title row inside each sidebar item already truncates with text-overflow: ellipsis; white-space: nowrap;, but the time/model row beneath it had no overflow handling, so a long model badge or localised timestamp would overflow the fixed 280px sidebar column. Brad flagged the asymmetry during the PR review. Fix: mirror the title row's three properties on .sidebar-item-time at static/css/style.css:387–390. Same one-line shape as the title row; no other sidebar rules touched.

  • (visual) Post-fix screenshots in samples/qa/workspace-chrome.png, workspace-firefox.png, conversation-chrome.png, conversation-firefox.png were captured after the .main-content { min-width: 0 } fix landed — the conversation column stays inside the viewport in all four.

  • ⏳ The .sidebar-item-time truncation fix is invisible on current data (timestamps + model names fit today). The check is forward- looking: drop it if a future row exceeds 280px, the ellipsis should kick in instead of overflowing.

9. Sign-off

State at the time of PR submission (2026-05-14). Reviewer fills in the remaining row(s) before merge.

Item Status Notes
All 7 sections complete §1–§6 covered with (visual) + (probe) evidence; §7 row 4 (print preview) deferred as , non-blocking — see §7
Screenshots attached to PR 10 PNGs in samples/qa/, embedded inline in §1–§5
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
tests/web-ui-smoke.sh passes 11/11 probes, captured in CI + locally
1+ reviewer approval Pending — open question for the reviewer

For future passes: re-run this file from §0 onward whenever templates/*.html, static/{css,js}/*, or any route in api/ is touched. The point of a sign-off block isn't to be a one-shot artifact — it's to make the next QA pass start from a known baseline.