[core-fe] canvas: extractReplyText coverage + extractMessageText bug fix #738

Open
core-fe wants to merge 6 commits from test/settings-tab-coverage into main

6 Commits

Author SHA1 Message Date
6f03da7daf chore: drop FilesToolbar + NotAvailablePanel test coverage
Some checks failed
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Blocked by required conditions
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Blocked by required conditions
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 20s
CI / Detect changes (pull_request) Successful in 57s
E2E API Smoke Test / detect-changes (pull_request) Successful in 59s
Harness Replays / detect-changes (pull_request) Successful in 28s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 24s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 1m10s
qa-review / approved (pull_request) Failing after 25s
security-review / approved (pull_request) Failing after 22s
gate-check-v3 / gate-check (pull_request) Failing after 40s
sop-checklist / all-items-acked (pull_request) acked: 0/7 — missing: comprehensive-testing, local-postgres-e2e, staging-smoke, +4
Runtime PR-Built Compatibility / detect-changes (pull_request) Successful in 57s
sop-checklist-gate / gate (pull_request) Successful in 21s
sop-tier-check / tier-check (pull_request) Successful in 18s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m33s
CI / Platform (Go) (pull_request) Successful in 13s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 4s
Harness Replays / Harness Replays (pull_request) Successful in 6s
CI / Python Lint & Test (pull_request) Successful in 23s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 16s
Runtime PR-Built Compatibility / PR-built wheel + import smoke (pull_request) Successful in 7s
Handlers Postgres Integration / detect-changes (pull_request) Failing after 11m1s
CI / Canvas (Next.js) (pull_request) Successful in 13m11s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
CI / all-required (pull_request) Successful in 2s
These files are covered by PR #783 (core-uiux, 22-file canvas coverage).
Removing from this branch to avoid merge conflict if #783 merges first.
The core PR scope remains: extractReplyText/deriveProvidersFromModels tests,
extractMessageText fix, and buildDeployMap coverage.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 06:22:20 +00:00
840a0e098b fix(canvas/test): buildDeployMap check() — fix vacuous test assertion
The check() helper had two bugs:
1. Type mismatch: `expected: Partial<OrgDeployState>` but callers pass
   `{ id: "X", ...state }` — the `id` field was never accounted for.
2. `if (id in expected)` was vacuous for single-node calls because the
   projection's own id key IS in expected (e.g. id="a" in {id:"a", ...}),
   and silently did nothing for multi-node calls.

Fix: type expected as `Record<string, Partial<OrgDeployState>>` mapping
node-id → expected state. Loop over result.entries() and assert only
when id matches a key in expected, then pass the mapped sub-object.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 06:22:20 +00:00
ffd0729b8a test(canvas): add buildDeployMap coverage — 19 cases (#742 follow-up)
buildDeployMap is the pure tree-computation core inside useOrgDeployState.
Export it and add isolated tests covering:

  §1  Empty projections → empty map
  §2  Single node, no parent, non-provisioning → unlocked root
  §3  Single node, no parent, provisioning → deploying root
  §4  Single node with existing parent → non-root, unlocked
  §5  parentId points to absent node → treated as root
  §6  Root (non-provisioning) + child → both unlocked
  §7  Root (provisioning) + child → root deploying, child locked
  §8  Three-level tree: provisioning grandparent → parent → child
  §9  DeletingIds on non-root → isLockedChild=true
  §10 DeletingIds on root → root locked, child unlocked
  §11 Two independent roots, only one provisioning
  §12 Root with 2 provisioning descendants → count=2
  §13 Non-root with provisioning status → isActivelyProvisioning=true
  §14 Deep 5-level chain, no provisioning → all unlocked
  §15 Deleting + provisioning: deleting takes isLockedChild
  §16 Child of provisioning root → isLockedChild=true
  §17 Deep chain (5 levels), no provisioning → all unlocked
  §18 Deep chain, middle node provisioning → single deploying root
  §19 parentId → ghost parent → treated as root

Key insight from §18: findRoot walks the parent chain via byId only, so
a node's subtree root is determined by which parent in byId is absent.
A provisioning node nested deep in a tree contributes to its nearest
byId-ancestor's provCount, not its own.

Issue: #742 (buildDeployMap unit tests, #2071 follow-up).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 06:22:20 +00:00
67789a0969 fix(canvas): extractMessageText prefers direct text over root.text
Cherry-picked from origin/fix/canvas-extractMessageText:

- ConversationTraceModal.extractMessageText: scan result.parts for the
  first direct text field and return it; only fall back to root.text
  when no direct text exists. Prior bug: joined ALL parts' text + root.text
  with newlines, causing "Direct text\nRoot text" concatenation.

- ConversationTraceModal.test.tsx: update "prefers parts[].text over
  parts[].root.text" test to expect "Direct text" (fixed behavior),
  add "falls back to root.text when no direct text exists" and
  "ignores subsequent parts root.text when direct text was found" cases.

- Spinner.test.tsx: add afterEach(cleanup) for DOM isolation, add
  getSvgClass helper, switch to getAttribute("class") + toContain()
  for SVG className assertions (SVGAnimatedString in jsdom ≠ string).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 06:22:20 +00:00
2d48bee328 chore: retrigger sop-checklist gate with updated body
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 06:22:20 +00:00
ddddb8a788 test(canvas/tabs): extractReplyText + deriveProvidersFromModels coverage
- extractReplyText.test.ts: 14 cases for A2A result-path text extractor
- deriveProvidersFromModels.test.ts: 9 cases for vendor-slug derivation
- FilesToolbar.test.tsx: 26 cases (cherry-picked from peer branch)
- NotAvailablePanel.test.tsx: 8 cases (cherry-picked from peer branch)
- Export ChatTab.extractReplyText + ConfigTab.deriveProvidersFromModels

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 06:22:20 +00:00