Skip to content

feat(milestones): debounced search with request cancellation and state machine (#1102) - #1146

Open
Simultech369 wants to merge 4 commits into
Talenttrust:mainfrom
Simultech369:feat-1102-debounced-search
Open

Simultech369 wants to merge 4 commits into
Talenttrust:mainfrom
Simultech369:feat-1102-debounced-search

Conversation

@Simultech369

Copy link
Copy Markdown

Closes #1102

Description

This PR implements accessible, debounced search for the Milestones board with in-flight request cancellation, out-of-order race condition guards, and distinct loading/empty/error states.

Key Changes

  • Debounced Search Hook (src/hooks/useDebouncedMilestonesSearch.ts):
    • Implements input debouncing (300ms) to prevent per-keystroke querying.
    • AbortController cancellation for superseded requests when new search begins or query is cleared.
    • Monotonic request sequence token tracking (requestIdRef) guaranteeing that out-of-order responses (fast-then-slow) are cleanly dropped and only the newest result wins.
    • State machine: idle, loading, success, empty, and error with structured typed errors (MilestonesSearchError).
    • Exposes retry() for instantaneous retry without debounce delay, and clear() for zero-latency reset.
  • Search Query Normalization & Engine (src/lib/searchMilestones.ts):
    • Multi-field substring search across milestone title, description, status, payout amount, and currency.
    • Normalizes whitespace and Unicode case for accurate matching.
  • Accessible Search Bar UI (src/components/milestones/MilestoneSearchBar.tsx):
    • WCAG 2.1 AA compliant searchbox with role="searchbox" and aria-label="Search milestones".
    • aria-live="polite" region announcing search state, matching counts, and empty states to screen readers.
    • Inline clear button (✕) and spinner indicator during async queries.
    • Keyboard navigation: Escape key immediately clears search query.
  • Milestones Page Integration (src/app/milestones/page.tsx):
    • Integrated into toolbar with status filter and sort dropdowns.
    • Distinct EmptyState when query produces zero matches with a "Clear Search" action button.
    • Role="alert" error banner with a "Retry search" button on search failure.
  • Documentation (docs/milestones-debounced-search.md):
    • Full architectural overview of debouncing, cancellation tokens, state machine, and accessibility.

Test Coverage & Edge Cases

  • Unit tests (src/lib/__tests__/searchMilestones.test.ts): 10 tests verifying normalization, case insensitivity, multi-field matching, AbortSignal immediate and delayed cancellation, and structured error instances.
  • Hook tests (src/hooks/__tests__/useDebouncedMilestonesSearch.test.ts): 5 comprehensive tests with Jest fake timers covering:
    • Rapid typing (only 1 query after debounce pause).
    • Fast-then-slow out-of-order race guard (newest result wins).
    • Zero matches empty state.
    • Cleared input immediate reset.
    • Error state and retry functionality.
  • Integration tests (src/app/milestones/__tests__/milestones-search.integration.test.tsx): 7 end-to-end tests validating searchbox rendering, debounced filtering, empty state with action button, inline clear button, Escape key, filter combination, and error retry banner.

Verification

  • npm test: 26/26 search-related tests pass; all existing milestone tests pass.
  • npm run lint: 0 errors, 0 warnings.
  • npm run build: Turbopack Next.js production build passes cleanly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

debounced milestones board search with request cancellation

1 participant