2020-08-04 16:32:10 -07:00
/ * *
* Copyright 2018 Google Inc . All rights reserved .
* Modifications copyright ( c ) Microsoft Corporation .
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
2020-09-02 21:43:38 -07:00
2023-05-16 03:13:58 -07:00
import os from 'os' ;
2021-05-06 07:08:22 -07:00
import { test as it , expect } from './pageTest' ;
2021-11-18 18:46:44 +01:00
import { chromiumVersionLessThan } from '../config/utils' ;
2020-08-04 16:32:10 -07:00
2022-03-10 19:42:52 +01:00
it ( 'should work @smoke' , async ( { page , browserName } ) = > {
2020-08-04 16:32:10 -07:00
await page . setContent ( `
< head >
< title > Accessibility Test < / title >
< / head >
< body >
< h1 > Inputs < / h1 >
< input placeholder = "Empty input" autofocus / >
< input placeholder = "readonly input" readonly / >
< input placeholder = "disabled input" disabled / >
< input aria-label = "Input with whitespace" value = " " / >
< input value = "value only" / >
< input aria-placeholder = "placeholder" value = "and a value" / >
< div aria-hidden = "true" id = "desc" > This is a description ! < / div >
< input aria-placeholder = "placeholder" value = "and a value" aria-describedby = "desc" / >
< / body > ` );
// autofocus happens after a delay in chrome these days
await page . waitForFunction ( ( ) = > document . activeElement . hasAttribute ( 'autofocus' ) ) ;
2021-05-13 10:22:23 -07:00
const golden = ( browserName === 'firefox' ) ? {
2020-08-04 16:32:10 -07:00
role : 'document' ,
name : 'Accessibility Test' ,
children : [
2021-09-27 18:58:08 +02:00
{ role : 'heading' , name : 'Inputs' , level : 1 } ,
{ role : 'textbox' , name : 'Empty input' , focused : true } ,
{ role : 'textbox' , name : 'readonly input' , readonly : true } ,
{ role : 'textbox' , name : 'disabled input' , disabled : true } ,
{ role : 'textbox' , name : 'Input with whitespace' , value : ' ' } ,
{ role : 'textbox' , name : '' , value : 'value only' } ,
{ role : 'textbox' , name : '' , value : 'and a value' } , // firefox doesn't use aria-placeholder for the name
{ role : 'textbox' , name : '' , value : 'and a value' , description : 'This is a description!' } , // and here
2020-08-04 16:32:10 -07:00
]
2021-05-13 10:22:23 -07:00
} : ( browserName === 'chromium' ) ? {
2020-08-04 16:32:10 -07:00
role : 'WebArea' ,
name : 'Accessibility Test' ,
children : [
2021-09-27 18:58:08 +02:00
{ role : 'heading' , name : 'Inputs' , level : 1 } ,
{ role : 'textbox' , name : 'Empty input' , focused : true } ,
{ role : 'textbox' , name : 'readonly input' , readonly : true } ,
{ role : 'textbox' , name : 'disabled input' , disabled : true } ,
{ role : 'textbox' , name : 'Input with whitespace' , value : ' ' } ,
{ role : 'textbox' , name : '' , value : 'value only' } ,
{ role : 'textbox' , name : 'placeholder' , value : 'and a value' } ,
{ role : 'textbox' , name : 'placeholder' , value : 'and a value' , description : 'This is a description!' } ,
2020-08-04 16:32:10 -07:00
]
} : {
role : 'WebArea' ,
name : 'Accessibility Test' ,
children : [
2021-09-27 18:58:08 +02:00
{ role : 'heading' , name : 'Inputs' , level : 1 } ,
{ role : 'textbox' , name : 'Empty input' , focused : true } ,
{ role : 'textbox' , name : 'readonly input' , readonly : true } ,
{ role : 'textbox' , name : 'disabled input' , disabled : true } ,
{ role : 'textbox' , name : 'Input with whitespace' , value : ' ' } ,
{ role : 'textbox' , name : '' , value : 'value only' } ,
{ role : 'textbox' , name : 'placeholder' , value : 'and a value' } ,
2023-05-16 03:13:58 -07:00
// due to frozen WebKit on macOS 11 we have the if/else here
{ role : 'textbox' , name : parseInt ( os . release ( ) , 10 ) >= 21 ? 'placeholder' : 'This is a description!' , value : 'and a value' } , // webkit uses the description over placeholder for the name
2020-08-04 16:32:10 -07:00
]
} ;
expect ( await page . accessibility . snapshot ( ) ) . toEqual ( golden ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should work with regular text' , async ( { page , browserName } ) = > {
2020-08-04 16:32:10 -07:00
await page . setContent ( ` <div>Hello World</div> ` ) ;
const snapshot = await page . accessibility . snapshot ( ) ;
expect ( snapshot . children [ 0 ] ) . toEqual ( {
2021-05-13 10:22:23 -07:00
role : browserName === 'firefox' ? 'text leaf' : 'text' ,
2020-08-04 16:32:10 -07:00
name : 'Hello World' ,
} ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'roledescription' , async ( { page } ) = > {
2021-08-30 19:51:06 +02:00
await page . setContent ( '<p tabIndex=-1 aria-roledescription="foo">Hi</p>' ) ;
2020-08-04 16:32:10 -07:00
const snapshot = await page . accessibility . snapshot ( ) ;
expect ( snapshot . children [ 0 ] . roledescription ) . toEqual ( 'foo' ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'orientation' , async ( { page } ) = > {
2020-08-04 16:32:10 -07:00
await page . setContent ( '<a href="" role="slider" aria-orientation="vertical">11</a>' ) ;
const snapshot = await page . accessibility . snapshot ( ) ;
expect ( snapshot . children [ 0 ] . orientation ) . toEqual ( 'vertical' ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'autocomplete' , async ( { page } ) = > {
2022-06-29 03:04:46 -07:00
await page . setContent ( '<div role="textbox" aria-autocomplete="list" aria-haspopup="menu">hi</div>' ) ;
2020-08-04 16:32:10 -07:00
const snapshot = await page . accessibility . snapshot ( ) ;
expect ( snapshot . children [ 0 ] . autocomplete ) . toEqual ( 'list' ) ;
2022-06-29 03:04:46 -07:00
expect ( snapshot . children [ 0 ] . haspopup ) . toEqual ( 'menu' ) ;
2020-08-04 16:32:10 -07:00
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'multiselectable' , async ( { page } ) = > {
2020-08-04 16:32:10 -07:00
await page . setContent ( '<div role="grid" tabIndex=-1 aria-multiselectable=true>hey</div>' ) ;
const snapshot = await page . accessibility . snapshot ( ) ;
expect ( snapshot . children [ 0 ] . multiselectable ) . toEqual ( true ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'keyshortcuts' , async ( { page } ) = > {
2020-08-04 16:32:10 -07:00
await page . setContent ( '<div role="grid" tabIndex=-1 aria-keyshortcuts="foo">hey</div>' ) ;
const snapshot = await page . accessibility . snapshot ( ) ;
expect ( snapshot . children [ 0 ] . keyshortcuts ) . toEqual ( 'foo' ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should not report text nodes inside controls' , async function ( { page , browserName } ) {
2020-08-04 16:32:10 -07:00
await page . setContent ( `
< div role = "tablist" >
< div role = "tab" aria-selected = "true" > < b > Tab1 < / b > < / div >
< div role = "tab" > Tab2 < / div >
< / div > ` );
const golden = {
2021-05-13 10:22:23 -07:00
role : browserName === 'firefox' ? 'document' : 'WebArea' ,
2020-08-04 16:32:10 -07:00
name : '' ,
children : [ {
role : 'tab' ,
name : 'Tab1' ,
selected : true
} , {
role : 'tab' ,
name : 'Tab2'
} ]
} ;
expect ( await page . accessibility . snapshot ( ) ) . toEqual ( golden ) ;
} ) ;
2024-02-12 17:37:45 +01:00
it ( 'rich text editable fields should have children' , async function ( { page , browserName , browserVersion , isWebView2 } ) {
2021-04-04 19:32:14 -07:00
it . skip ( browserName === 'webkit' , 'WebKit rich text accessibility is iffy' ) ;
2022-12-13 17:39:16 +01:00
it . skip ( isWebView2 , 'WebView2 is missing a Chromium fix' ) ;
2021-04-04 19:32:14 -07:00
2020-08-04 16:32:10 -07:00
await page . setContent ( `
< div contenteditable = "true" >
Edit this image : < img src = "fakeimage.png" alt = "my fake image" >
< / div > ` );
2021-05-13 10:22:23 -07:00
const golden = browserName === 'firefox' ? {
2020-08-04 16:32:10 -07:00
role : 'section' ,
name : '' ,
children : [ {
role : 'text leaf' ,
name : 'Edit this image: '
} , {
role : 'text' ,
name : 'my fake image'
} ]
} : {
role : 'generic' ,
name : '' ,
value : 'Edit this image: ' ,
children : [ {
role : 'text' ,
2022-09-28 03:13:07 -07:00
name : chromiumVersionLessThan ( browserVersion , '108.0.5325.0' ) ? 'Edit this image:' : 'Edit this image: '
2020-08-04 16:32:10 -07:00
} , {
2023-08-12 11:00:16 -07:00
role : chromiumVersionLessThan ( browserVersion , '117.0.5927.0' ) ? 'img' : 'image' ,
2020-08-04 16:32:10 -07:00
name : 'my fake image'
} ]
} ;
const snapshot = await page . accessibility . snapshot ( ) ;
expect ( snapshot . children [ 0 ] ) . toEqual ( golden ) ;
} ) ;
2020-08-28 13:53:47 -07:00
2024-02-12 17:37:45 +01:00
it ( 'rich text editable fields with role should have children' , async function ( { page , browserName , browserMajorVersion , browserVersion , isWebView2 } ) {
2021-05-13 10:22:23 -07:00
it . skip ( browserName === 'webkit' , 'WebKit rich text accessibility is iffy' ) ;
2022-12-14 09:47:42 +01:00
it . skip ( isWebView2 , 'WebView2 is missing a Chromium fix' ) ;
2021-04-04 19:32:14 -07:00
2020-08-04 16:32:10 -07:00
await page . setContent ( `
< div contenteditable = "true" role = 'textbox' >
Edit this image : < img src = "fakeimage.png" alt = "my fake image" >
< / div > ` );
2021-05-13 10:22:23 -07:00
const golden = browserName === 'firefox' ? {
2020-08-04 16:32:10 -07:00
role : 'textbox' ,
name : '' ,
value : 'Edit this image: my fake image' ,
children : [ {
role : 'text' ,
name : 'my fake image'
} ]
} : {
role : 'textbox' ,
name : '' ,
2021-05-13 10:22:23 -07:00
multiline : ( browserName === 'chromium' && browserMajorVersion >= 92 ) ? true : undefined ,
2020-08-04 16:32:10 -07:00
value : 'Edit this image: ' ,
2022-06-22 09:20:51 +02:00
children : ( chromiumVersionLessThan ( browserVersion , '104.0.1293.1' ) && browserName === 'chromium' ) ? [ {
2020-08-04 16:32:10 -07:00
role : 'text' ,
name : 'Edit this image:'
} , {
role : 'img' ,
name : 'my fake image'
2022-06-10 06:59:49 -07:00
} ] : [ {
role : 'text' ,
2022-09-28 03:13:07 -07:00
name : chromiumVersionLessThan ( browserVersion , '108.0.5325.0' ) ? 'Edit this image:' : 'Edit this image: '
2020-08-04 16:32:10 -07:00
} ]
} ;
const snapshot = await page . accessibility . snapshot ( ) ;
expect ( snapshot . children [ 0 ] ) . toEqual ( golden ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'non editable textbox with role and tabIndex and label should not have children' , async function ( { page , browserName } ) {
2020-08-04 16:32:10 -07:00
await page . setContent ( `
< div role = "textbox" tabIndex = 0 aria-checked = "true" aria-label = "my favorite textbox" >
this is the inner content
< img alt = "yo" src = "fakeimg.png" >
< / div > ` );
2021-05-13 10:22:23 -07:00
const golden = ( browserName === 'firefox' ) ? {
2020-08-04 16:32:10 -07:00
role : 'textbox' ,
name : 'my favorite textbox' ,
value : 'this is the inner content yo'
2021-05-13 10:22:23 -07:00
} : ( browserName === 'chromium' ) ? {
2020-08-04 16:32:10 -07:00
role : 'textbox' ,
name : 'my favorite textbox' ,
value : 'this is the inner content '
} : {
role : 'textbox' ,
name : 'my favorite textbox' ,
value : 'this is the inner content ' ,
} ;
const snapshot = await page . accessibility . snapshot ( ) ;
expect ( snapshot . children [ 0 ] ) . toEqual ( golden ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'checkbox with and tabIndex and label should not have children' , async function ( { page } ) {
2020-08-04 16:32:10 -07:00
await page . setContent ( `
< div role = "checkbox" tabIndex = 0 aria-checked = "true" aria-label = "my favorite checkbox" >
this is the inner content
< img alt = "yo" src = "fakeimg.png" >
< / div > ` );
const golden = {
role : 'checkbox' ,
name : 'my favorite checkbox' ,
checked : true
} ;
const snapshot = await page . accessibility . snapshot ( ) ;
expect ( snapshot . children [ 0 ] ) . toEqual ( golden ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'checkbox without label should not have children' , async ( { page , browserName } ) = > {
2020-08-04 16:32:10 -07:00
await page . setContent ( `
< div role = "checkbox" aria-checked = "true" >
this is the inner content
< img alt = "yo" src = "fakeimg.png" >
< / div > ` );
2021-05-13 10:22:23 -07:00
const golden = browserName === 'firefox' ? {
2020-08-04 16:32:10 -07:00
role : 'checkbox' ,
name : 'this is the inner content yo' ,
checked : true
} : {
role : 'checkbox' ,
name : 'this is the inner content yo' ,
checked : true
} ;
const snapshot = await page . accessibility . snapshot ( ) ;
expect ( snapshot . children [ 0 ] ) . toEqual ( golden ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should work a button' , async ( { page } ) = > {
2020-08-04 16:32:10 -07:00
await page . setContent ( ` <button>My Button</button> ` ) ;
const button = await page . $ ( 'button' ) ;
2021-09-27 18:58:08 +02:00
expect ( await page . accessibility . snapshot ( { root : button } ) ) . toEqual ( {
2020-08-04 16:32:10 -07:00
role : 'button' ,
name : 'My Button'
} ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should work an input' , async ( { page } ) = > {
2020-08-04 16:32:10 -07:00
await page . setContent ( ` <input title="My Input" value="My Value"> ` ) ;
const input = await page . $ ( 'input' ) ;
2021-09-27 18:58:08 +02:00
expect ( await page . accessibility . snapshot ( { root : input } ) ) . toEqual ( {
2020-08-04 16:32:10 -07:00
role : 'textbox' ,
name : 'My Input' ,
value : 'My Value'
} ) ;
} ) ;
2021-11-18 18:46:44 +01:00
it ( 'should work on a menu' , async ( { page , browserName , browserVersion } ) = > {
2020-08-04 16:32:10 -07:00
await page . setContent ( `
< div role = "menu" title = "My Menu" >
< div role = "menuitem" > First Item < / div >
< div role = "menuitem" > Second Item < / div >
< div role = "menuitem" > Third Item < / div >
< / div >
` );
const menu = await page . $ ( 'div[role="menu"]' ) ;
2021-09-27 18:58:08 +02:00
expect ( await page . accessibility . snapshot ( { root : menu } ) ) . toEqual ( {
2020-08-04 16:32:10 -07:00
role : 'menu' ,
name : 'My Menu' ,
children :
2022-08-18 20:12:33 +02:00
[ { role : 'menuitem' , name : 'First Item' } ,
2020-08-04 16:32:10 -07:00
{ role : 'menuitem' , name : 'Second Item' } ,
2022-08-18 20:12:33 +02:00
{ role : 'menuitem' , name : 'Third Item' } ] ,
2021-12-08 15:21:09 -08:00
orientation : ( browserName === 'webkit' || ( browserName === 'chromium' && ! chromiumVersionLessThan ( browserVersion , '98.0.1089' ) ) ) ? 'vertical' : undefined
2020-08-04 16:32:10 -07:00
} ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should return null when the element is no longer in DOM' , async ( { page } ) = > {
2020-08-04 16:32:10 -07:00
await page . setContent ( ` <button>My Button</button> ` ) ;
const button = await page . $ ( 'button' ) ;
await page . $eval ( 'button' , button = > button . remove ( ) ) ;
2021-09-27 18:58:08 +02:00
expect ( await page . accessibility . snapshot ( { root : button } ) ) . toEqual ( null ) ;
2020-08-04 16:32:10 -07:00
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should show uninteresting nodes' , async ( { page } ) = > {
2020-08-04 16:32:10 -07:00
await page . setContent ( `
< div id = "root" role = "textbox" >
< div >
hello
< div >
world
< / div >
< / div >
< / div >
` );
const root = await page . $ ( '#root' ) ;
2021-09-27 18:58:08 +02:00
const snapshot = await page . accessibility . snapshot ( { root , interestingOnly : false } ) ;
2020-08-04 16:32:10 -07:00
expect ( snapshot . role ) . toBe ( 'textbox' ) ;
expect ( snapshot . value ) . toContain ( 'hello' ) ;
expect ( snapshot . value ) . toContain ( 'world' ) ;
expect ( ! ! snapshot . children ) . toBe ( true ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should work when there is a title ' , async ( { page } ) = > {
2020-08-04 16:32:10 -07:00
await page . setContent ( `
< title > This is the title < / title >
< div > This is the content < / div >
` );
const snapshot = await page . accessibility . snapshot ( ) ;
expect ( snapshot . name ) . toBe ( 'This is the title' ) ;
expect ( snapshot . children [ 0 ] . name ) . toBe ( 'This is the content' ) ;
} ) ;
2024-02-12 21:12:31 +01:00
it ( 'should work with aria-invalid accessibility tree' , async ( { page , browserName , server } ) = > {
await page . goto ( server . EMPTY_PAGE ) ;
await page . setContent ( ` <a href="/hi" aria-invalid="true">WHO WE ARE</a> ` ) ;
expect ( await page . accessibility . snapshot ( ) ) . toEqual ( {
'role' : browserName === 'firefox' ? 'document' : 'WebArea' ,
'name' : '' ,
'children' : [
{
'role' : 'link' ,
'name' : 'WHO WE ARE' ,
'invalid' : 'true' ,
'value' : browserName === 'firefox' ? ` ${ server . PREFIX } /hi ` : undefined
}
]
} ) ;
} ) ;