test: frontend view and component coverage gaps (#716)#826
test: frontend view and component coverage gaps (#716)#826Chris0Jeky wants to merge 9 commits intomainfrom
Conversation
Adds 11 test cases covering item restore flow (success, cancel, error, partial failure), empty states for items and boards, refresh action, and entity type badge display. Closes part of #716
…lity Adds 16 test cases covering retry button, CSV export (enabled/disabled/ error), forecast section (loading, error, data, confidence band, caveats, assumptions, null date), and ARIA accessibility attributes. Closes part of #716
…anup Adds 12 test cases covering loading/error states, column creation flow (submit, empty name, cancel), column rendering order, fetchBoard and realtime lifecycle, and unmount cleanup. Closes part of #716
Adds 10 test cases covering approve action, apply-to-board action with confirmation, reject with reason, error toasts for failures, summary card counts, two-step flow indicator, and risk level badge rendering. Closes part of #716
…alth Adds 16 test cases covering message sending (success, empty, error), message display and role labels, session creation (with/without board, error), session list and switching, loading state, and LLM health states (unavailable, verify flow). Closes part of #716
…a11y Adds 21 test cases covering move-to column menu (show/hide, column listing, selection, escape close), blocked badge, label rendering with colors, selection state and aria-selected, click/keyboard events, tabindex, role, and description display. Closes part of #716
… a11y Adds 12 test cases covering empty state display, column rendering with card counts, drag state CSS classes (opacity, scale), drag event emissions, and ARIA role/label attributes on column wrappers. Closes part of #716
Adds 9 test cases covering all five action button emissions (capture, chat, review, inbox, addCard), review-first trust hint text, data-board-action-rail attribute, and primary button distinction. Closes part of #716
Adversarial Self-ReviewFindings1. Good: Meaningful interaction testing
2. Good: Error path coverage
3. Good: Accessibility assertions
4. Acceptable: Some tests check text content
5. Minor gap: No negative flow on BoardCanvas drag
6. No remaining issues requiring fixes. |
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive suite of unit and integration tests for various frontend components and views, including BoardActionRail, BoardCanvas, CardItem, ArchiveView, AutomationChatView, BoardView, MetricsView, and ReviewView. The feedback focuses on improving test reliability and robustness. Specifically, it recommends consistently unmounting wrappers when using attachTo: document.body to prevent DOM pollution, replacing brittle Promise.resolve() chains with flushPromises() for handling asynchronous UI updates, and adding explicit assertions before using non-null operators to ensure clearer failure messages.
| function mountView() { | ||
| return mount(BoardView, { | ||
| attachTo: document.body, | ||
| global: { | ||
| stubs: { | ||
| ColumnLane: { | ||
| props: ['column'], | ||
| template: '<div :data-column-id="column.id"><span>{{ column.name }}</span></div>', | ||
| }, | ||
| BoardSettingsModal: { template: '<div />' }, | ||
| LabelManagerModal: { template: '<div />' }, | ||
| StarterPackCatalogModal: { template: '<div />' }, | ||
| KeyboardShortcutsHelp: { template: '<div />' }, | ||
| FilterPanel: { template: '<div />' }, | ||
| CaptureModal: { template: '<div />' }, | ||
| }, | ||
| }, | ||
| }) | ||
| } |
There was a problem hiding this comment.
The mountView helper uses attachTo: document.body, but the tests do not consistently unmount the wrapper. This leads to DOM pollution where components from previous tests remain in the document, which can cause side effects (like duplicate IDs or roles) or slow down the test suite. It is recommended to store the wrapper and unmount it in an afterEach block, or avoid attachTo if not strictly necessary for these tests.
| async function waitForAsyncUi() { | ||
| await Promise.resolve() | ||
| await Promise.resolve() | ||
| } |
There was a problem hiding this comment.
Using multiple await Promise.resolve() calls to wait for asynchronous UI updates is brittle and relies on internal implementation details of the microtask queue. It is better to use flushPromises() from @vue/test-utils (after importing it), which waits for all pending promises to resolve, ensuring the component has finished its async lifecycle before assertions run.
async function waitForAsyncUi() {
await flushPromises()
}| const btn = wrapper.findAll('button').find((b) => b.text().trim() === 'Capture here') | ||
| await btn!.trigger('click') |
There was a problem hiding this comment.
Using the non-null assertion operator (!) on the result of find() is an anti-pattern in tests. If the button is missing due to a regression, the test will fail with a generic TypeError instead of a clear assertion failure. It is better to explicitly expect the element to be defined before interacting with it.
| const btn = wrapper.findAll('button').find((b) => b.text().trim() === 'Capture here') | |
| await btn!.trigger('click') | |
| const btn = wrapper.findAll('button').find((b) => b.text().trim() === 'Capture here') | |
| expect(btn).toBeDefined() | |
| await btn!.trigger('click') |
There was a problem hiding this comment.
Pull request overview
Adds targeted frontend unit tests to close coverage gaps for several high-impact views and board-related components, improving confidence in common user flows and UI states.
Changes:
- Added new coverage-focused specs for Review, Metrics, Board, Archive, and Automation Chat views.
- Added new coverage-focused specs for key board UI components (CardItem, BoardCanvas, BoardActionRail).
- Expanded assertions around loading/error/empty states and some accessibility attributes (ARIA roles/labels).
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/taskdeck-web/src/tests/views/ReviewView.coverage.spec.ts | Adds tests for proposal review flows (approve/apply/reject), summary cards, risk badges, and error handling. |
| frontend/taskdeck-web/src/tests/views/MetricsView.coverage.spec.ts | Adds tests for retry/export behaviors, forecast rendering states, and ARIA attributes. |
| frontend/taskdeck-web/src/tests/views/BoardView.coverage.spec.ts | Adds tests for board loading/error, column creation, column ordering, realtime lifecycle, and help callout. |
| frontend/taskdeck-web/src/tests/views/AutomationChatView.coverage.spec.ts | Adds tests for chat send flow, session creation/list/switching, loading state, and LLM health banners. |
| frontend/taskdeck-web/src/tests/views/ArchiveView.coverage.spec.ts | Adds tests for archive restore flows, loading/empty/error states, refresh behavior, and entity type badges. |
| frontend/taskdeck-web/src/tests/components/CardItem.coverage.spec.ts | Adds tests for card move menu behavior, blocked/labels rendering, selection/accessibility, and interactions. |
| frontend/taskdeck-web/src/tests/components/BoardCanvas.coverage.spec.ts | Adds tests for empty state, column lane rendering, DnD CSS classes and emitted events, and ARIA labeling. |
| frontend/taskdeck-web/src/tests/components/BoardActionRail.coverage.spec.ts | Adds tests for action button rendering/emissions and a few UI hints/attributes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| }) | ||
|
|
||
| it('shows sessions loading indicator when sessions are being fetched', async () => { | ||
| const deferred = createDeferred<typeof buildSession[]>() |
There was a problem hiding this comment.
createDeferred<typeof buildSession[]>() is typed as an array of the buildSession function type, not an array of session objects. This will fail TypeScript typechecking (and makes the deferred’s resolve signature wrong). Use createDeferred<ReturnType<typeof buildSession>[]>() (or a dedicated session type) instead.
| const deferred = createDeferred<typeof buildSession[]>() | |
| const deferred = createDeferred<ReturnType<typeof buildSession>[]>() |
| expect(restoreButton!.attributes('disabled')).toBeDefined() | ||
| }) | ||
|
|
||
| it('does not cancel board restore when confirm is cancelled', async () => { |
There was a problem hiding this comment.
Test name is misleading: it asserts that a board restore is not performed when the confirm dialog is cancelled (i.e., updateBoard is not called). Consider renaming to something like “does not restore board when confirm is cancelled” so the intent matches the assertions.
| it('does not cancel board restore when confirm is cancelled', async () => { | |
| it('does not restore board when confirm is cancelled', async () => { |
| function mountView() { | ||
| return mount(BoardView, { | ||
| attachTo: document.body, | ||
| global: { |
There was a problem hiding this comment.
mountView() uses attachTo: document.body, but the mounted wrappers in these tests aren’t unmounted afterward. That leaves DOM nodes/component instances around across tests and can cause flaky behavior (event listeners, timers, Teleports). Consider either removing attachTo (if not needed) or adding an afterEach that unmounts the wrapper(s).
Round 2 Adversarial ReviewCritical (CI-blocking)1. Lint failure: unused Fix: Remove Important2. BoardView tests: DOM pollution from
Compare with ReviewView.coverage.spec.ts which correctly stores the wrapper in Fix: Add 3. AutomationChatView: const deferred = createDeferred<typeof buildSession[]>()
This doesn't blow up at runtime because Fix: 4. async function waitForAsyncUi() {
await Promise.resolve()
await Promise.resolve()
}This is a fragile microtask tick hack. If the component adds another async step (e.g., a Not blocking, but inconsistency within a single PR is a maintenance risk. Minor5. Non-null assertions ( 6. ArchiveView test name: "does not cancel board restore when confirm is cancelled" 7. ReviewView: What Looks Good
|
- Remove unused `vi` import from CardItem.coverage.spec.ts (CI-blocking lint error) - Add afterEach wrapper cleanup to BoardView.coverage.spec.ts (prevents DOM pollution from attachTo: document.body) - Fix createDeferred generic type in AutomationChatView.coverage.spec.ts (ReturnType<typeof buildSession>[] instead of typeof buildSession[]) - Rename misleading test name in ArchiveView.coverage.spec.ts
Update STATUS.md, IMPLEMENTATION_MASTERPLAN.md, TESTING_GUIDE.md, and MANUAL_TEST_CHECKLIST.md for the supplementary test depth wave. - Add delivery entry 134 to masterplan for 6 parallel worktree PRs - Update test counts: backend ~4,479+, frontend ~2,454+, combined ~6,950+ - Add new TESTING_GUIDE section with run commands and test breakdowns - Add Z22 manual validation checklist for new test categories - Update date stamps to 2026-04-13
Summary
Closes #716
Test plan