44 logRoles ,
55 getImplicitAriaRoles ,
66 isInaccessible ,
7+ isSubtreeInaccessible ,
78} from '../role-helpers'
89import { render } from './helpers/test-utils'
910
@@ -25,7 +26,7 @@ function setup() {
2526 <a data-testid="invalid-link">invalid link</a>
2627
2728 <nav data-testid='a-nav' />
28-
29+
2930 <h1 data-testid='a-h1'>Main Heading</h1>
3031 <h2 data-testid='a-h2'>Sub Heading</h2>
3132 <h3 data-testid='a-h3'>Tertiary Heading</h3>
@@ -211,3 +212,74 @@ test.each([
211212
212213 expect ( isInaccessible ( container . querySelector ( 'button' ) ) ) . toBe ( expected )
213214} )
215+
216+ describe ( 'checkVisibility API integration' , ( ) => {
217+ let originalCheckVisibility
218+
219+ beforeEach ( ( ) => {
220+ // This may not exist depending on the environment
221+ originalCheckVisibility = Element . prototype . checkVisibility
222+ } )
223+
224+ afterEach ( ( ) => {
225+ if ( originalCheckVisibility ) {
226+ Element . prototype . checkVisibility = originalCheckVisibility
227+ } else {
228+ delete Element . prototype . checkVisibility
229+ }
230+ } )
231+
232+ test ( 'uses checkVisibility when available' , ( ) => {
233+ const mockCheckVisibility = jest . fn ( ) . mockReturnValue ( false )
234+ Element . prototype . checkVisibility = mockCheckVisibility
235+
236+ const { container} = render ( '<div><button>Test</button></div>' )
237+ const button = container . querySelector ( 'button' )
238+
239+ const result = isSubtreeInaccessible ( button )
240+
241+ expect ( mockCheckVisibility ) . toHaveBeenCalledWith ( {
242+ visibilityProperty : true ,
243+ opacityProperty : false ,
244+ } )
245+ expect ( result ) . toBe ( true )
246+ } )
247+
248+ test ( 'falls back to getComputedStyle when checkVisibility unavailable' , ( ) => {
249+ // Remove checkVisibility to test fallback
250+ delete Element . prototype . checkVisibility
251+
252+ const { container} = render ( '<button style="display: none;">Test</button>' )
253+ const button = container . querySelector ( 'button' )
254+
255+ expect ( isSubtreeInaccessible ( button ) ) . toBe ( true )
256+ } )
257+
258+ test ( 'checkVisibility and fallback produce same results' , ( ) => {
259+ const testCases = [
260+ '<div><button>Visible</button></div>' ,
261+ '<div style="display: none;"><button>Hidden</button></div>' ,
262+ '<div style="visibility: hidden;"><button>Hidden</button></div>' ,
263+ '<div hidden><button>Hidden</button></div>' ,
264+ '<div aria-hidden="true"><button>Hidden</button></div>' ,
265+ ]
266+
267+ testCases . forEach ( html => {
268+ const { container : container1 } = render ( html )
269+ const button1 = container1 . querySelector ( 'button' )
270+
271+ const resultWithAPI = isInaccessible ( button1 )
272+
273+ delete Element . prototype . checkVisibility
274+ const { container : container2 } = render ( html )
275+ const button2 = container2 . querySelector ( 'button' )
276+ const resultWithoutAPI = isInaccessible ( button2 )
277+
278+ expect ( resultWithAPI ) . toBe ( resultWithoutAPI )
279+
280+ if ( originalCheckVisibility ) {
281+ Element . prototype . checkVisibility = originalCheckVisibility
282+ }
283+ } )
284+ } )
285+ } )
0 commit comments