Calendar Day
Wednesday, July 8, 2026 (PR 1 of 2)
Planned Effort
5 story points (Medium–High) — sprint item #3
Companion PR: Wednesday PR 2 (adversarial dispatch fixtures #4) — independent (frontend vs Python backend); can land in either order.
Problem
static/js/render/ contains 32 non-test source modules — 15 under tool_result/ and 14 under tool_use/, plus constants.js, registry.js, tool_types_manifest.js — but only 5 vitest files cover them: registry.test.js, tool_types_manifest.test.js, tool_result/file_read.test.js, tool_use/bash.test.js, tool_use/edit.test.js.
registry.test.js guards wiring and escaping at the registry boundary, but most per-renderer output paths have no behavioral test. Untrusted LLM/tool-result content flows through these renderers (sanitized via static/js/shared/markdown.js DOMPurify and shared/utils.js esc), so thin per-renderer coverage is a correctness and XSS-regression risk, not just a coverage-number gap.
Week 1 PR #105 added the frontend tool manifest; this issue closes the test gap on the render modules that manifest wires.
Goal
One merged PR that adds behavioral vitest coverage for the majority of tool_result/ and tool_use/ renderer modules, including sanitization assertions and raised coverage thresholds.
Scope
Touch points
static/js/render/tool_result/ — per-module vitest tests for representative fixtures (majority of 15 modules).
static/js/render/tool_use/ — per-module vitest tests (majority of 14 modules).
- Shared test helper — mount a renderer and return sanitized HTML; reduce per-test boilerplate.
- Fixture strategy — drive enumeration from
render/registry.js (TOOL_USE_RENDERERS / TOOL_RESULT_RENDERERS); reuse real-session-derived fixtures where possible.
vitest.config.js — meet or raise thresholds (current: lines 80 / functions 70 / branches 50).
- Extend
registry.test.js wiring guard rather than duplicating registry-level assertions in every file.
Per-renderer test expectations
- Representative input → expected rendered output.
- Empty/malformed input handling.
- XSS-safety: no raw HTML injection for renderers that emit markup via
shared/markdown.js.
Out of scope
- Backend
utils/tool_dispatch.py changes (Wednesday PR 2).
- New renderer features or visual redesign.
- Bundler introduction — keep zero-build ES modules.
Acceptance Criteria
Verification
cd C:\Users\Jasen\CppAliance\claude-code-chat-browser
npm ci
npm test
npm run test:coverage
Manual: open a session with diverse tool types (Bash, Read, Task, Grep, …) — spot-check rendered cards match pre-change behavior.
Calendar Day
Wednesday, July 8, 2026 (PR 1 of 2)
Planned Effort
5 story points (Medium–High) — sprint item #3
Companion PR: Wednesday PR 2 (adversarial dispatch fixtures #4) — independent (frontend vs Python backend); can land in either order.
Problem
static/js/render/contains 32 non-test source modules — 15 undertool_result/and 14 undertool_use/, plusconstants.js,registry.js,tool_types_manifest.js— but only 5 vitest files cover them:registry.test.js,tool_types_manifest.test.js,tool_result/file_read.test.js,tool_use/bash.test.js,tool_use/edit.test.js.registry.test.jsguards wiring and escaping at the registry boundary, but most per-renderer output paths have no behavioral test. Untrusted LLM/tool-result content flows through these renderers (sanitized viastatic/js/shared/markdown.jsDOMPurify andshared/utils.jsesc), so thin per-renderer coverage is a correctness and XSS-regression risk, not just a coverage-number gap.Week 1 PR #105 added the frontend tool manifest; this issue closes the test gap on the render modules that manifest wires.
Goal
One merged PR that adds behavioral vitest coverage for the majority of
tool_result/andtool_use/renderer modules, including sanitization assertions and raised coverage thresholds.Scope
Touch points
static/js/render/tool_result/— per-module vitest tests for representative fixtures (majority of 15 modules).static/js/render/tool_use/— per-module vitest tests (majority of 14 modules).render/registry.js(TOOL_USE_RENDERERS/TOOL_RESULT_RENDERERS); reuse real-session-derived fixtures where possible.vitest.config.js— meet or raise thresholds (current: lines 80 / functions 70 / branches 50).registry.test.jswiring guard rather than duplicating registry-level assertions in every file.Per-renderer test expectations
shared/markdown.js.Out of scope
utils/tool_dispatch.pychanges (Wednesday PR 2).Acceptance Criteria
tool_result/andtool_use/renderer modules have a vitest behavioral test.vitest.config.js.registry.test.jsrather than duplicating wiring guards.npm testand CI vitest job pass.Verification
Manual: open a session with diverse tool types (Bash, Read, Task, Grep, …) — spot-check rendered cards match pre-change behavior.