11const { test, expect } = require ( '@playwright/test' ) ;
2-
32test . describe ( 'Search & Filter' , ( ) => {
43 test ( 'should show autocomplete suggestions on typing and filter cards by category' , async ( { page } ) => {
54 await page . goto ( '/' ) ;
6-
75 // Scroll to projects to show the sidebar search
86 const exploreBtn = page . locator ( '#exploreBtn' ) ;
97 await exploreBtn . click ( ) ;
10-
118 // Wait for sidebar to be active
129 await expect ( page . locator ( 'body' ) ) . toHaveClass ( / s i d e b a r - a c t i v e / ) ;
13-
1410 const searchInput = page . locator ( '#searchInput' ) ;
1511 const searchDropdown = page . locator ( '#searchDropdown' ) ;
1612 const resultsList = page . locator ( '#resultsList' ) ;
17-
1813 // Wait for the search input to become visible
1914 await expect ( searchInput ) . toBeVisible ( ) ;
20-
2115 // 1. Focus search input and type query
2216 await searchInput . focus ( ) ;
2317 await searchInput . fill ( '2048' ) ;
24-
2518 // Verify autocomplete dropdown is active and shows matching suggestions
2619 await expect ( searchDropdown ) . toHaveClass ( / a c t i v e / ) ;
2720 const suggestionText = resultsList . locator ( '.dropdown-item-text' ) ;
2821 await expect ( suggestionText ) . toContainText ( '2048' ) ;
29-
3022 // Clear search input to restore all cards
3123 await searchInput . fill ( '' ) ;
3224 await page . keyboard . press ( 'Enter' ) ;
33-
3425 // 2. Click category tab "games" from sidebar
3526 const gamesTab = page . locator ( '.sidebar-tab[data-category="games"]' ) ;
3627 await gamesTab . click ( ) ;
37-
3828 // Verify that the games tab has the active class
3929 await expect ( gamesTab ) . toHaveClass ( / a c t i v e / ) ;
40-
4130 // Verify only games category cards are displayed, and others are hidden
4231 const projectCards = page . locator ( '.project-card' ) ;
4332 const count = await projectCards . count ( ) ;
4433 expect ( count ) . toBeGreaterThan ( 0 ) ;
45-
4634 for ( let i = 0 ; i < count ; i ++ ) {
4735 const card = projectCards . nth ( i ) ;
4836 const isVisible = await card . isVisible ( ) ;
@@ -54,4 +42,44 @@ test.describe('Search & Filter', () => {
5442 }
5543 }
5644 } ) ;
57- } ) ;
45+
46+ test ( 'should support / shortcut, ignore / while typing, and clear on Escape' , async ( { page } ) => {
47+ await page . goto ( '/' ) ;
48+ const exploreBtn = page . locator ( '#exploreBtn' ) ;
49+ await exploreBtn . click ( ) ;
50+ await expect ( page . locator ( 'body' ) ) . toHaveClass ( / s i d e b a r - a c t i v e / ) ;
51+
52+ const searchInput = page . locator ( '#searchInput' ) ;
53+ const navSearchInput = page . locator ( '#navSearchInput' ) ;
54+ const searchDropdown = page . locator ( '#searchDropdown' ) ;
55+ await expect ( searchInput ) . toBeVisible ( ) ;
56+
57+ // The app focuses #navSearchInput preferentially when it exists,
58+ // falling back to #searchInput otherwise.
59+ const focusedAfterShortcut = ( await navSearchInput . count ( ) ) > 0
60+ ? navSearchInput
61+ : searchInput ;
62+
63+ // 1. Pressing "/" anywhere on the page (not focused in a field) should focus the search input
64+ await page . evaluate ( ( ) => document . activeElement && document . activeElement . blur ( ) ) ;
65+ await page . keyboard . press ( '/' ) ;
66+ await expect ( focusedAfterShortcut ) . toBeFocused ( ) ;
67+
68+ // 2. Typing "/" while already focused in a text field should NOT be intercepted
69+ // (i.e. it should be inserted as a literal character, not just re-focus/no-op)
70+ await searchInput . fill ( 'a/b' ) ;
71+ await expect ( searchInput ) . toHaveValue ( 'a/b' ) ;
72+
73+ // 3. Ctrl+K / Cmd+K should still focus the search input (existing shortcut, unchanged)
74+ await page . evaluate ( ( ) => document . activeElement && document . activeElement . blur ( ) ) ;
75+ await page . keyboard . press ( 'Control+k' ) ;
76+ await expect ( focusedAfterShortcut ) . toBeFocused ( ) ;
77+
78+ // 4. Escape should clear the input and close the dropdown
79+ await searchInput . fill ( '2048' ) ;
80+ await expect ( searchDropdown ) . toHaveClass ( / a c t i v e / ) ;
81+ await page . keyboard . press ( 'Escape' ) ;
82+ await expect ( searchInput ) . toHaveValue ( '' ) ;
83+ await expect ( searchDropdown ) . not . toHaveClass ( / a c t i v e / ) ;
84+ } ) ;
85+ } ) ;
0 commit comments