1- import { render , fireEvent , screen , waitFor } from '@testing-library/react' ;
1+ import { render , fireEvent , screen , waitFor , act } from '@testing-library/react' ;
22import Select from '../index' ;
33
44const { Option, OptGroup } = Select ;
@@ -7,6 +7,14 @@ const { Option, OptGroup } = Select;
77const getOptions = ( ) => document . querySelectorAll ( '.ty-select-option' ) ;
88
99describe ( '<Select />' , ( ) => {
10+ beforeEach ( ( ) => {
11+ jest . useFakeTimers ( ) ;
12+ } ) ;
13+
14+ afterEach ( ( ) => {
15+ jest . useRealTimers ( ) ;
16+ } ) ;
17+
1018 it ( 'should match the snapshot' , ( ) => {
1119 const { asFragment } = render (
1220 < Select >
@@ -157,6 +165,31 @@ describe('<Select />', () => {
157165 expect ( onSearch ) . toHaveBeenCalledWith ( 'test' ) ;
158166 } ) ;
159167
168+ it ( 'should focus the search input after opening' , ( ) => {
169+ const { container } = render (
170+ < Select showSearch >
171+ < Option value = "a" > Apple</ Option >
172+ < Option value = "b" > Banana</ Option >
173+ </ Select >
174+ ) ;
175+
176+ const selector = container . querySelector ( '.ty-select__selector' ) as HTMLElement ;
177+ fireEvent . click ( selector ) ;
178+
179+ act ( ( ) => {
180+ jest . runAllTimers ( ) ;
181+ } ) ;
182+
183+ const searchInput = container . querySelector ( '.ty-select__search' ) as HTMLInputElement ;
184+ expect ( searchInput ) . toHaveFocus ( ) ;
185+
186+ fireEvent . change ( searchInput , { target : { value : 'ban' } } ) ;
187+
188+ const options = getOptions ( ) ;
189+ expect ( options . length ) . toBe ( 1 ) ;
190+ expect ( options [ 0 ] ) . toHaveTextContent ( 'Banana' ) ;
191+ } ) ;
192+
160193 // Keyboard
161194 it ( 'should navigate with arrow keys and select with Enter' , ( ) => {
162195 const onChange = jest . fn ( ) ;
@@ -386,6 +419,55 @@ describe('<Select />', () => {
386419 expect ( onSelect ) . toHaveBeenCalledWith ( 'a' ) ;
387420 } ) ;
388421
422+ // scrollToSelected
423+ it ( 'should set scrollTop when dropdown opens with a selected value' , ( ) => {
424+ const options = Array . from ( { length : 50 } , ( _ , i ) => ( {
425+ value : `opt-${ i } ` ,
426+ label : `Option ${ i } ` ,
427+ } ) ) ;
428+
429+ const { container } = render ( < Select options = { options } defaultValue = "opt-40" /> ) ;
430+ const selector = container . querySelector ( '.ty-select__selector' ) as HTMLElement ;
431+
432+ // Mock offsetTop on selected option before opening
433+ const origDescriptor = Object . getOwnPropertyDescriptor ( HTMLElement . prototype , 'offsetTop' ) ;
434+ Object . defineProperty ( HTMLElement . prototype , 'offsetTop' , {
435+ configurable : true ,
436+ get ( ) {
437+ if ( this . getAttribute ?.( 'aria-selected' ) === 'true' ) return 400 ;
438+ return 0 ;
439+ } ,
440+ } ) ;
441+
442+ fireEvent . click ( selector ) ;
443+ jest . runAllTimers ( ) ;
444+
445+ const dropdown = document . querySelector ( '.ty-select__dropdown' ) as HTMLElement ;
446+ expect ( dropdown . scrollTop ) . toBe ( 400 ) ;
447+
448+ if ( origDescriptor ) {
449+ Object . defineProperty ( HTMLElement . prototype , 'offsetTop' , origDescriptor ) ;
450+ }
451+ } ) ;
452+
453+ it ( 'should not scroll when scrollToSelected is false' , ( ) => {
454+ const options = Array . from ( { length : 50 } , ( _ , i ) => ( {
455+ value : `opt-${ i } ` ,
456+ label : `Option ${ i } ` ,
457+ } ) ) ;
458+
459+ const { container } = render (
460+ < Select options = { options } defaultValue = "opt-40" scrollToSelected = { false } />
461+ ) ;
462+ const selector = container . querySelector ( '.ty-select__selector' ) as HTMLElement ;
463+ fireEvent . click ( selector ) ;
464+
465+ jest . runAllTimers ( ) ;
466+
467+ const dropdown = document . querySelector ( '.ty-select__dropdown' ) as HTMLElement ;
468+ expect ( dropdown . scrollTop ) . toBe ( 0 ) ;
469+ } ) ;
470+
389471 // Custom filter function
390472 it ( 'should support custom filterOption function' , ( ) => {
391473 const { container } = render (
0 commit comments