1+ import { render , screen , fireEvent } from '@testing-library/react' ;
2+ import userEvent from '@testing-library/user-event' ;
3+ import { BasicSelect } from '../components/common/BasicSelect' ;
4+
5+ describe ( 'BasicSelect' , ( ) => {
6+ const mockItems = [
7+ { label : 'Option 1' , value : '1' } ,
8+ { label : 'Option 2' , value : '2' } ,
9+ { label : 'Option 3' , value : '3' } ,
10+ ] ;
11+
12+ const mockOnChange = jest . fn ( ) ;
13+
14+ beforeEach ( ( ) => {
15+ jest . clearAllMocks ( ) ;
16+ } ) ;
17+
18+ it ( 'renders with placeholder and opens on click' , async ( ) => {
19+ render (
20+ < BasicSelect
21+ placeholder = "Select an option"
22+ items = { mockItems }
23+ onChange = { mockOnChange }
24+ />
25+ ) ;
26+
27+ expect ( screen . getByText ( 'Select an option' ) ) . toBeInTheDocument ( ) ;
28+
29+ await userEvent . click ( screen . getByRole ( 'combobox' ) ) ;
30+ expect ( screen . getByText ( 'Option 1' ) ) . toBeInTheDocument ( ) ;
31+ expect ( screen . getByText ( 'Option 2' ) ) . toBeInTheDocument ( ) ;
32+ expect ( screen . getByText ( 'Option 3' ) ) . toBeInTheDocument ( ) ;
33+ } ) ;
34+
35+ it ( 'allows selecting an option with click' , async ( ) => {
36+ render (
37+ < BasicSelect
38+ placeholder = "Select an option"
39+ items = { mockItems }
40+ onChange = { mockOnChange }
41+ />
42+ ) ;
43+
44+ await userEvent . click ( screen . getByRole ( 'combobox' ) ) ;
45+ await userEvent . click ( screen . getByText ( 'Option 2' ) ) ;
46+
47+ expect ( mockOnChange ) . toHaveBeenCalledWith ( '2' ) ;
48+ expect ( screen . queryByText ( 'Option 1' ) ) . not . toBeInTheDocument ( ) ; // Menu should close
49+ expect ( screen . getByText ( 'Option 2' ) ) . toBeInTheDocument ( ) ; // Selected value
50+ } ) ;
51+
52+ it ( 'navigates options with arrow keys and selects with Enter' , async ( ) => {
53+ render (
54+ < BasicSelect
55+ placeholder = "Select an option"
56+ items = { mockItems }
57+ onChange = { mockOnChange }
58+ />
59+ ) ;
60+
61+ const combobox = screen . getByRole ( 'combobox' ) ;
62+ await userEvent . click ( combobox ) ; // Open the select
63+
64+ // Navigate down to Option 2
65+ fireEvent . keyDown ( combobox , { key : 'ArrowDown' } ) ; // Focus Option 1
66+ fireEvent . keyDown ( combobox , { key : 'ArrowDown' } ) ; // Focus Option 2
67+
68+ // Select Option 2 with Enter
69+ fireEvent . keyDown ( combobox , { key : 'Enter' } ) ;
70+
71+ expect ( mockOnChange ) . toHaveBeenCalledWith ( '2' ) ;
72+ expect ( screen . queryByText ( 'Option 1' ) ) . not . toBeInTheDocument ( ) ; // Menu should close
73+ expect ( screen . getByText ( 'Option 2' ) ) . toBeInTheDocument ( ) ; // Selected value
74+ } ) ;
75+
76+ it ( 'closes the select with Escape key' , async ( ) => {
77+ render (
78+ < BasicSelect
79+ placeholder = "Select an option"
80+ items = { mockItems }
81+ onChange = { mockOnChange }
82+ />
83+ ) ;
84+
85+ const combobox = screen . getByRole ( 'combobox' ) ;
86+ await userEvent . click ( combobox ) ; // Open the select
87+
88+ expect ( screen . getByText ( 'Option 1' ) ) . toBeInTheDocument ( ) ; // Menu is open
89+
90+ fireEvent . keyDown ( combobox , { key : 'Escape' } ) ;
91+
92+ expect ( screen . queryByText ( 'Option 1' ) ) . not . toBeInTheDocument ( ) ; // Menu should close
93+ } ) ;
94+
95+ it ( 'should clear selection when allowEmpty is true and clear button is clicked' , async ( ) => {
96+ render (
97+ < BasicSelect
98+ placeholder = "Select an option"
99+ items = { mockItems }
100+ onChange = { mockOnChange }
101+ value = "1"
102+ allowEmpty = { true }
103+ />
104+ ) ;
105+
106+ expect ( screen . getByText ( 'Option 1' ) ) . toBeInTheDocument ( ) ;
107+
108+ const clearButton = screen . getByRole ( 'button' , { name : / c l e a r / i } ) ;
109+ await userEvent . click ( clearButton ) ;
110+
111+ expect ( mockOnChange ) . toHaveBeenCalledWith ( null ) ;
112+ expect ( screen . getByText ( 'Select an option' ) ) . toBeInTheDocument ( ) ;
113+ } ) ;
114+ } ) ;
0 commit comments