[Molecule-Platform-Evolvement-Manager] Closes the third item from #2071 (Canvas test gaps follow-up). Builds on the A2AEdge tests in PR #2143. 10 cases across 4 buckets: **Render (2):** - Default pill with `Cancel (N)` text + correct ARIA label - Confirm dialog NOT visible until pill click **Pill click (3):** - Click flips to confirming view + stops propagation (so React Flow doesn't interpret the click as a node selection) - Confirm copy pluralizes correctly: count=1 → "Delete 1 workspace?", count>1 → "Delete N workspaces?". Negative assertion guards against the wrong-form regressing in either direction. **No / cancel-confirm (1):** - Click No → returns to pill, no API call, no store mutation **Yes / cascade-delete (4):** - Happy path: beginDelete locks the WHOLE subtree (root + children, NOT unrelated workspace) → api.del("/workspaces/<id>?confirm=true") → optimistic store filter strips subtree, keeps unrelated → success toast → endDelete in finally - WS-event race: WS_REMOVED handler clears the root mid-flight. The bail-out branch (`!postDeleteState.nodes.some(n => n.id === rootId)`) must NOT then run a second optimistic filter. Pre-fix the post-await subtree walk would miss any orphaned descendants whose parentId got reparented upward by handleCanvasEvent — pinned now. - Error path: api.del rejects → endDelete UNDOes the lock + error toast surfaces the message → subtree STAYS in the store so the user can retry / interact with the still-deploying nodes - Non-Error rejection (e.g. string thrown directly): toast surfaces the canned "Cancel failed" fallback instead of attempting `.message` ## Mocking - `@/lib/api`, `@/components/Toaster`: simple spy mocks - `@/store/canvas`: object that satisfies BOTH the selector pattern (`useCanvasStore(s => s.x)`) AND `getState()` / `setState()` since the cascade-delete handler walks the subtree via `getState()` and mutates via `setState()` for the optimistic removal. `vi.hoisted` preserves referential identity so the mock fns wired into the state object are observed by every consumer. ## Test plan - [x] All 10 cases pass locally (`vitest run OrgCancelButton.test.tsx` — ~990ms) - [x] No changes to the SUT — pure additive coverage - [ ] CI green ## #2071 progress after this PR - [x] useTemplateDeploy (PR #2121) - [x] A2AEdge (PR #2143) - [x] OrgCancelButton (this PR) - [ ] useDragHandlers — separate PR 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| __tests__ | ||
| app | ||
| components | ||
| hooks | ||
| lib | ||
| store | ||
| stores | ||
| styles | ||
| types | ||
| middleware.ts | ||