File tree 4 files changed +60
-5
lines changed 4 files changed +60
-5
lines changed Original file line number Diff line number Diff line change @@ -17,7 +17,7 @@ test('fires events when tabbing between two elements', () => {
17
17
userEvent . tab ( )
18
18
expect ( getEventSnapshot ( ) ) . toMatchInlineSnapshot ( `
19
19
Events fired on: div
20
-
20
+
21
21
input#a[value=""] - keydown: Tab (9)
22
22
input#a[value=""] - focusout
23
23
input#b[value=""] - focusin
@@ -45,7 +45,7 @@ test('does not change focus if default prevented on keydown', () => {
45
45
userEvent . tab ( )
46
46
expect ( getEventSnapshot ( ) ) . toMatchInlineSnapshot ( `
47
47
Events fired on: div
48
-
48
+
49
49
input#a[value=""] - keydown: Tab (9)
50
50
input#a[value=""] - keyup: Tab (9)
51
51
` )
@@ -418,6 +418,26 @@ test('should not focus disabled elements', () => {
418
418
expect ( five ) . toHaveFocus ( )
419
419
} )
420
420
421
+ test ( 'should not focus elements inside a hidden parent' , ( ) => {
422
+ setup ( `
423
+ <div>
424
+ <input data-testid="one" />
425
+ <div hidden="">
426
+ <button>click</button>
427
+ </div>
428
+ <input data-testid="three" />
429
+ </div>` )
430
+
431
+ const one = document . querySelector ( '[data-testid="one"]' )
432
+ const three = document . querySelector ( '[data-testid="three"]' )
433
+
434
+ userEvent . tab ( )
435
+ expect ( one ) . toHaveFocus ( )
436
+
437
+ userEvent . tab ( )
438
+ expect ( three ) . toHaveFocus ( )
439
+ } )
440
+
421
441
test ( 'should keep focus on the document if there are no enabled, focusable elements' , ( ) => {
422
442
setup ( `<button disabled>no clicky</button>` )
423
443
userEvent . tab ( )
Original file line number Diff line number Diff line change 1
- import { isInstanceOfElement } from '../utils'
1
+ import { screen } from '@testing-library/dom'
2
+ import { isInstanceOfElement , isVisible } from '../utils'
2
3
import { setup } from './helpers/utils'
3
4
4
5
// isInstanceOfElement can be removed once the peerDependency for @testing -library/dom is bumped to a version that includes https://github.com/testing-library/dom-testing-library/pull/885
@@ -71,3 +72,19 @@ describe('check element type per isInstanceOfElement', () => {
71
72
expect ( ( ) => isInstanceOfElement ( element , 'HTMLSpanElement' ) ) . toThrow ( )
72
73
} )
73
74
} )
75
+
76
+ test ( 'check if element is visible' , ( ) => {
77
+ setup ( `
78
+ <input data-testid="visibleInput"/>
79
+ <input data-testid="hiddenInput" hidden/>
80
+ <input data-testid="styledHiddenInput" style="display: none">
81
+ <input data-testid="styledDisplayedInput" hidden style="display: block"/>
82
+ <div style="display: none"><input data-testid="childInput" /></div>
83
+ ` )
84
+
85
+ expect ( isVisible ( screen . getByTestId ( 'visibleInput' ) ) ) . toBe ( true )
86
+ expect ( isVisible ( screen . getByTestId ( 'styledDisplayedInput' ) ) ) . toBe ( true )
87
+ expect ( isVisible ( screen . getByTestId ( 'styledHiddenInput' ) ) ) . toBe ( false )
88
+ expect ( isVisible ( screen . getByTestId ( 'childInput' ) ) ) . toBe ( false )
89
+ expect ( isVisible ( screen . getByTestId ( 'hiddenInput' ) ) ) . toBe ( false )
90
+ } )
Original file line number Diff line number Diff line change 1
1
import { fireEvent } from '@testing-library/dom'
2
- import { getActiveElement , FOCUSABLE_SELECTOR } from './utils'
2
+ import { getActiveElement , FOCUSABLE_SELECTOR , isVisible } from './utils'
3
3
import { focus } from './focus'
4
4
import { blur } from './blur'
5
5
@@ -31,7 +31,11 @@ function tab({shift = false, focusTrap} = {}) {
31
31
const enabledElements = [ ...focusableElements ] . filter (
32
32
el =>
33
33
el === previousElement ||
34
- ( el . getAttribute ( 'tabindex' ) !== '-1' && ! el . disabled ) ,
34
+ ( el . getAttribute ( 'tabindex' ) !== '-1' &&
35
+ ! el . disabled &&
36
+ // Hidden elements are not tabable
37
+ isVisible ( el )
38
+ ) ,
35
39
)
36
40
37
41
if ( enabledElements . length === 0 ) return
Original file line number Diff line number Diff line change @@ -293,6 +293,19 @@ function isClickableInput(element) {
293
293
)
294
294
}
295
295
296
+ function isVisible ( element ) {
297
+ const getComputedStyle = getWindowFromNode ( element ) . getComputedStyle
298
+
299
+ for ( ; element && element . ownerDocument ; element = element . parentNode ) {
300
+ const display = getComputedStyle ( element ) . display
301
+ if ( display === 'none' ) {
302
+ return false
303
+ }
304
+ }
305
+
306
+ return true
307
+ }
308
+
296
309
function eventWrapper ( cb ) {
297
310
let result
298
311
getConfig ( ) . eventWrapper ( ( ) => {
@@ -367,4 +380,5 @@ export {
367
380
getSelectionRange ,
368
381
isContentEditable ,
369
382
isInstanceOfElement ,
383
+ isVisible ,
370
384
}
You can’t perform that action at this time.
0 commit comments