@@ -427,6 +427,97 @@ describe('Autocomplete', () => {
427
427
expect ( input ) . not . toHaveAttribute ( 'data-focused' ) ;
428
428
} ) ;
429
429
430
+ it ( 'should restore focus visible styles back to the input when typing forward results in only disabled items' , async function ( ) {
431
+ let { getByRole} = render (
432
+ < AutocompleteWrapper >
433
+ < StaticMenu disabledKeys = { [ '2' ] } />
434
+ </ AutocompleteWrapper >
435
+ ) ;
436
+
437
+ let input = getByRole ( 'searchbox' ) ;
438
+ await user . tab ( ) ;
439
+ expect ( document . activeElement ) . toBe ( input ) ;
440
+ expect ( input ) . toHaveAttribute ( 'data-focused' ) ;
441
+ expect ( input ) . toHaveAttribute ( 'data-focus-visible' ) ;
442
+
443
+ await user . keyboard ( 'Ba' ) ;
444
+ act ( ( ) => jest . runAllTimers ( ) ) ;
445
+ let menu = getByRole ( 'menu' ) ;
446
+ let options = within ( menu ) . getAllByRole ( 'menuitem' ) ;
447
+ let baz = options [ 1 ] ;
448
+ expect ( baz ) . toHaveTextContent ( 'Baz' ) ;
449
+ expect ( input ) . toHaveAttribute ( 'aria-activedescendant' , baz . id ) ;
450
+ expect ( baz ) . toHaveAttribute ( 'data-focus-visible' ) ;
451
+ expect ( input ) . not . toHaveAttribute ( 'data-focused' ) ;
452
+ expect ( input ) . not . toHaveAttribute ( 'data-focus-visible' ) ;
453
+
454
+ await user . keyboard ( 'r' ) ;
455
+ act ( ( ) => jest . runAllTimers ( ) ) ;
456
+ options = within ( menu ) . getAllByRole ( 'menuitem' ) ;
457
+ let bar = options [ 0 ] ;
458
+ expect ( bar ) . toHaveTextContent ( 'Bar' ) ;
459
+ expect ( input ) . not . toHaveAttribute ( 'aria-activedescendant' ) ;
460
+ expect ( bar ) . not . toHaveAttribute ( 'data-focus-visible' ) ;
461
+ expect ( input ) . toHaveAttribute ( 'data-focused' ) ;
462
+ expect ( input ) . toHaveAttribute ( 'data-focus-visible' ) ;
463
+ } ) ;
464
+
465
+ it ( 'should maintain focus styles on the input if typing forward results in an completely empty collection' , async function ( ) {
466
+ let { getByRole} = render (
467
+ < AutocompleteWrapper >
468
+ < StaticMenu />
469
+ </ AutocompleteWrapper >
470
+ ) ;
471
+
472
+ let input = getByRole ( 'searchbox' ) ;
473
+ await user . tab ( ) ;
474
+ expect ( document . activeElement ) . toBe ( input ) ;
475
+ expect ( input ) . toHaveAttribute ( 'data-focused' ) ;
476
+ expect ( input ) . toHaveAttribute ( 'data-focus-visible' ) ;
477
+
478
+ await user . keyboard ( 'Q' ) ;
479
+ act ( ( ) => jest . runAllTimers ( ) ) ;
480
+ let menu = getByRole ( 'menu' ) ;
481
+ let options = within ( menu ) . queryAllByRole ( 'menuitem' ) ;
482
+ expect ( options ) . toHaveLength ( 0 ) ;
483
+ expect ( input ) . toHaveAttribute ( 'data-focused' ) ;
484
+ expect ( input ) . toHaveAttribute ( 'data-focus-visible' ) ;
485
+ expect ( input ) . not . toHaveAttribute ( 'aria-activedescendant' ) ;
486
+ } ) ;
487
+
488
+ it ( 'should restore focus visible styles back to the input if the user types forward and backspaces in quick succession' , async function ( ) {
489
+ let { getByRole} = render (
490
+ < AutocompleteWrapper >
491
+ < StaticMenu />
492
+ </ AutocompleteWrapper >
493
+ ) ;
494
+
495
+ let input = getByRole ( 'searchbox' ) ;
496
+ await user . tab ( ) ;
497
+ expect ( document . activeElement ) . toBe ( input ) ;
498
+ expect ( input ) . toHaveAttribute ( 'data-focused' ) ;
499
+ expect ( input ) . toHaveAttribute ( 'data-focus-visible' ) ;
500
+
501
+ await user . keyboard ( 'F' ) ;
502
+ // If 500ms hasn't elapsed the aria-activedecendant hasn't been updated
503
+ act ( ( ) => jest . advanceTimersByTime ( 300 ) ) ;
504
+ let menu = getByRole ( 'menu' ) ;
505
+ let options = within ( menu ) . getAllByRole ( 'menuitem' ) ;
506
+ let foo = options [ 0 ] ;
507
+ expect ( foo ) . toHaveTextContent ( 'Foo' ) ;
508
+ expect ( input ) . not . toHaveAttribute ( 'aria-activedescendant' ) ;
509
+ expect ( foo ) . toHaveAttribute ( 'data-focus-visible' ) ;
510
+ expect ( input ) . not . toHaveAttribute ( 'data-focused' ) ;
511
+ expect ( input ) . not . toHaveAttribute ( 'data-focus-visible' ) ;
512
+
513
+ await user . keyboard ( '{Backspace}' ) ;
514
+ act ( ( ) => jest . runAllTimers ( ) ) ;
515
+ expect ( input ) . toHaveAttribute ( 'data-focused' ) ;
516
+ expect ( input ) . toHaveAttribute ( 'data-focus-visible' ) ;
517
+ expect ( input ) . not . toHaveAttribute ( 'aria-activedescendant' ) ;
518
+ expect ( foo ) . not . toHaveAttribute ( 'data-focus-visible' ) ;
519
+ } ) ;
520
+
430
521
it ( 'should work inside a Select' , async function ( ) {
431
522
let { getByRole} = render (
432
523
< Select >
0 commit comments