@@ -69,6 +69,21 @@ describe('<AutoComplete />', () => {
6969 expect ( onChange ) . toHaveBeenCalledWith ( 'Banana' ) ;
7070 } ) ;
7171
72+ it ( 'should expose combobox aria relationships when navigating options' , ( ) => {
73+ const { container } = render ( < AutoComplete options = { options } /> ) ;
74+ const input = container . querySelector ( 'input' ) as HTMLInputElement ;
75+ const wrapper = container . firstChild as HTMLElement ;
76+
77+ fireEvent . keyDown ( wrapper , { key : 'ArrowDown' } ) ;
78+
79+ const listboxId = input . getAttribute ( 'aria-controls' ) ;
80+ expect ( input ) . toHaveAttribute ( 'role' , 'combobox' ) ;
81+ expect ( input ) . toHaveAttribute ( 'aria-expanded' , 'true' ) ;
82+ expect ( listboxId ) . toBeTruthy ( ) ;
83+ expect ( input ) . toHaveAttribute ( 'aria-activedescendant' , `${ listboxId } -option-0` ) ;
84+ expect ( document . getElementById ( `${ listboxId } -option-0` ) ) . toHaveTextContent ( 'Apple' ) ;
85+ } ) ;
86+
7287 it ( 'should close on Escape' , ( ) => {
7388 const { container } = render ( < AutoComplete options = { options } defaultOpen /> ) ;
7489 const wrapper = container . firstChild as HTMLElement ;
@@ -126,6 +141,39 @@ describe('<AutoComplete />', () => {
126141 expect ( container . firstChild ) . toHaveClass ( 'ty-auto-complete_open' ) ;
127142 } ) ;
128143
144+ it ( 'should call onOpenChange when focus opens and outside click closes the popup' , async ( ) => {
145+ const onOpenChange = jest . fn ( ) ;
146+ const { container } = render (
147+ < div >
148+ < AutoComplete options = { options } onOpenChange = { onOpenChange } />
149+ < button > Outside</ button >
150+ </ div >
151+ ) ;
152+
153+ const input = container . querySelector ( 'input' ) as HTMLInputElement ;
154+ fireEvent . focus ( input ) ;
155+ expect ( onOpenChange ) . toHaveBeenCalledWith ( true ) ;
156+
157+ fireEvent . click ( screen . getByText ( 'Outside' ) ) ;
158+
159+ await waitFor ( ( ) => {
160+ expect ( onOpenChange ) . toHaveBeenCalledWith ( false ) ;
161+ } ) ;
162+ } ) ;
163+
164+ it ( 'should respect controlled open when Escape is pressed' , ( ) => {
165+ const onOpenChange = jest . fn ( ) ;
166+ const { container } = render (
167+ < AutoComplete options = { options } open = { true } onOpenChange = { onOpenChange } />
168+ ) ;
169+
170+ const wrapper = container . firstChild as HTMLElement ;
171+ fireEvent . keyDown ( wrapper , { key : 'Escape' } ) ;
172+
173+ expect ( container . firstChild ) . toHaveClass ( 'ty-auto-complete_open' ) ;
174+ expect ( onOpenChange ) . toHaveBeenCalledWith ( false ) ;
175+ } ) ;
176+
129177 it ( 'should call onSearch callback' , ( ) => {
130178 const onSearch = jest . fn ( ) ;
131179 const { container } = render ( < AutoComplete options = { options } onSearch = { onSearch } /> ) ;
0 commit comments