@@ -102,4 +102,80 @@ describe('Locator.svelte', () => {
102102
103103 expect ( input . value ) . toBe ( '' ) ;
104104 } ) ;
105+
106+ it ( 'handles failed autocomplete fetch without rendering suggestions' , async ( ) => {
107+ const logMock = vi . spyOn ( console , 'log' ) . mockImplementation ( ( ) => undefined ) ;
108+
109+ vi . stubGlobal ( 'fetch' , vi . fn ( ( input : RequestInfo | URL ) => {
110+ const url = typeof input === 'string' ? input : input . toString ( ) ;
111+
112+ if ( url . includes ( 'limit=5' ) ) {
113+ return Promise . resolve ( {
114+ ok : false ,
115+ status : 500 ,
116+ json : ( ) => Promise . resolve ( [ ] ) ,
117+ } ) ;
118+ }
119+
120+ return Promise . resolve ( {
121+ ok : true ,
122+ status : 200 ,
123+ json : ( ) => Promise . resolve ( [ ] ) ,
124+ } ) ;
125+ } ) ) ;
126+
127+ render ( App as unknown as new ( ) => SvelteComponent , { target : document . body } ) ;
128+ const input = screen . getByPlaceholderText ( 'Search Location' ) as HTMLInputElement ;
129+
130+ await fireEvent . input ( input , { target : { value : 'Toronto' } } ) ;
131+ await Promise . resolve ( ) ;
132+
133+ expect ( logMock ) . toHaveBeenCalled ( ) ;
134+ expect ( screen . queryByRole ( 'listitem' ) ) . toBeNull ( ) ;
135+ logMock . mockRestore ( ) ;
136+ } ) ;
137+
138+ it ( 'alerts when geocoding returns no results' , async ( ) => {
139+ const alertMock = vi . fn ( ) ;
140+ vi . stubGlobal ( 'alert' , alertMock ) ;
141+
142+ vi . stubGlobal ( 'fetch' , vi . fn ( ( ) => {
143+ return Promise . resolve ( {
144+ ok : true ,
145+ status : 200 ,
146+ json : ( ) => Promise . resolve ( [ ] ) ,
147+ } ) ;
148+ } ) ) ;
149+
150+ render ( App as unknown as new ( ) => SvelteComponent , { target : document . body } ) ;
151+ const input = screen . getByPlaceholderText ( 'Search Location' ) as HTMLInputElement ;
152+ const button = screen . getByDisplayValue ( 'Submit' ) ;
153+
154+ await fireEvent . input ( input , { target : { value : 'Nowhere' } } ) ;
155+ vi . useFakeTimers ( ) ;
156+ await fireEvent . click ( button ) ;
157+ await vi . runAllTimersAsync ( ) ;
158+
159+ expect ( alertMock ) . toHaveBeenCalledWith ( 'No such location found.' ) ;
160+ } ) ;
161+
162+ it ( 'ignores unrelated key presses during navigation' , async ( ) => {
163+ render ( App as unknown as new ( ) => SvelteComponent , { target : document . body } ) ;
164+
165+ const input = screen . getByPlaceholderText ( 'Search Location' ) as HTMLInputElement ;
166+ await fireEvent . input ( input , { target : { value : '' } } ) ;
167+ await fireEvent . keyDown ( window , { key : 'Escape' } ) ;
168+
169+ expect ( input . value ) . toBe ( '' ) ;
170+ } ) ;
171+
172+ it ( 'returns early on ArrowDown with no suggestions' , async ( ) => {
173+ render ( App as unknown as new ( ) => SvelteComponent , { target : document . body } ) ;
174+ const input = screen . getByPlaceholderText ( 'Search Location' ) as HTMLInputElement ;
175+
176+ await fireEvent . input ( input , { target : { value : '' } } ) ;
177+ await fireEvent . keyDown ( window , { key : 'ArrowDown' } ) ;
178+
179+ expect ( input . value ) . toBe ( '' ) ;
180+ } ) ;
105181} ) ;
0 commit comments