# Agent 2: Search Debounce Test Plan ## Manual Testing Steps ### Test 1: Basic Debounce 1. Open any document in NaviDocs 2. Type "engine" in search box 3. **Expected**: See loading spinner appear after typing stops 4. **Expected**: Search executes 300ms after last keystroke 5. **Expected**: Results appear highlighted in document ### Test 2: Cancellation on New Input 1. Type "eng" 2. Wait 200ms (before search triggers) 3. Continue typing "ine" 4. **Expected**: Previous pending search is cancelled 5. **Expected**: New 300ms timer starts 6. **Expected**: Only one search executes (for "engine") ### Test 3: Minimum Query Length 1. Type "e" (1 character) 2. **Expected**: No search executes 3. **Expected**: No loading spinner 4. Type "n" (now "en", 2 characters) 5. **Expected**: Search triggers after 300ms 6. **Expected**: Results appear ### Test 4: Clear Search 1. Type "engine" and wait for results 2. Click the X (clear) button 3. **Expected**: Input clears immediately 4. **Expected**: Results clear immediately 5. **Expected**: No highlights remain ### Test 5: Backspace to < 2 Characters 1. Type "engine" and wait for results 2. Backspace to "en" 3. **Expected**: New search executes after 300ms 4. Backspace to "e" 5. **Expected**: Results clear immediately 6. **Expected**: No search executes ### Test 6: Loading Indicator 1. Type "engine" 2. **Expected**: Search button shows spinning icon 3. **Expected**: Button is disabled during search 4. **Expected**: Tooltip shows "Searching..." 5. Wait for search to complete 6. **Expected**: Search icon returns 7. **Expected**: Tooltip shows "Search" ### Test 7: Rapid Typing 1. Type "abcdefghijklmnop" quickly without pausing 2. **Expected**: Loading state appears 3. **Expected**: Only ONE search executes (after typing stops) 4. **Expected**: No multiple searches for intermediate strings ### Test 8: Enter Key Override 1. Type "eng" (3 characters) 2. Press Enter immediately (don't wait for debounce) 3. **Expected**: Search executes immediately 4. **Expected**: Debounce timer is bypassed ### Test 9: Multiple Cancel Operations 1. Type "test" 2. Before search executes, type "search" 3. Before that executes, clear input 4. **Expected**: No errors in console 5. **Expected**: All abort controllers cleaned up properly ### Test 10: Cross-Page Search Integration 1. Type "engine" and wait for results 2. **Expected**: Current page highlights appear 3. **Expected**: Background cross-page search starts 4. **Expected**: Total match count includes all pages 5. Navigate to next/previous match 6. **Expected**: Navigation works correctly ## Automated Test Scenarios (for future implementation) ```javascript describe('Search Debounce', () => { it('should debounce search by 300ms', async () => { // Type characters await typeText('engine') // Verify search hasn't executed yet expect(performSearch).not.toHaveBeenCalled() // Wait 300ms await delay(300) // Verify search executed expect(performSearch).toHaveBeenCalledTimes(1) }) it('should cancel previous search on new input', async () => { await typeText('eng') await delay(200) await typeText('ine') // Only one search should execute await delay(300) expect(performSearch).toHaveBeenCalledTimes(1) expect(performSearch).toHaveBeenCalledWith('engine') }) it('should not search for queries < 2 chars', async () => { await typeText('e') await delay(300) expect(performSearch).not.toHaveBeenCalled() }) it('should show loading indicator', async () => { await typeText('engine') expect(isSearching.value).toBe(true) expect(searchButton.querySelector('.animate-spin')).toBeInTheDocument() await delay(300) await waitFor(() => expect(isSearching.value).toBe(false)) }) }) ``` ## Performance Verification ### Metrics to Check - **Debounce delay**: Should be exactly 300ms - **Search cancellation**: Previous searches should abort properly - **Memory leaks**: No timers or controllers left hanging - **UI responsiveness**: No lag during typing - **Search execution**: Only one search per debounce period ### Console Checks ```javascript // Should see ONE log after typing "engine": console.log("Found X matches across Y pages") // Should NOT see: console.error("Search error:") console.warn("Failed to abort search") ``` ## Edge Cases ### Concurrent Operations - ✅ Typing while previous search is running - ✅ Clearing input while search is running - ✅ Navigating away while search is running - ✅ Closing document while search is running ### Boundary Conditions - ✅ Empty string → No search - ✅ 1 character → No search - ✅ 2 characters → Search executes - ✅ Very long query → Search executes normally ### State Cleanup - ✅ Timer cleared on new input - ✅ Abort controller cleared on completion - ✅ Loading state reset on error - ✅ All state reset on clear ## Success Criteria ✅ Search executes 300ms after user stops typing ✅ Loading indicator shows during search ✅ Previous searches cancel when new input arrives ✅ Results update in real-time ✅ Clearing input clears results immediately ✅ Queries < 2 characters don't trigger search ✅ No console errors ✅ No memory leaks ✅ Smooth user experience ## Known Limitations 1. **Debounce timing**: 300ms is hardcoded (could be configurable) 2. **Minimum query length**: 2 characters is hardcoded (could be configurable) 3. **No search history**: Previous searches not saved 4. **No smart cancellation**: Cancels even if query prefix matches ## Future Enhancements 1. Make debounce delay configurable via settings 2. Add search history dropdown 3. Implement smart cancellation (don't cancel if new query starts with old) 4. Add search suggestions/autocomplete 5. Persist search state across page navigation 6. Add keyboard shortcuts (Cmd+G for next match) 7. Add search within results filtering