UNPKG

axe-core

Version:

Accessibility engine for automated Web UI testing

1,096 lines (879 loc) • 46.5 kB
describe('text.accessibleTextVirtual', function() { 'use strict'; var fixture = document.getElementById('fixture'); var shadowSupport = axe.testUtils.shadowSupport; afterEach(function() { fixture.innerHTML = ''; axe._tree = null; }); it('is called through accessibleText with a DOM node', function() { var accessibleText = axe.commons.text.accessibleText; fixture.innerHTML = '<label><input type="button"></label>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = fixture.querySelector('input'); assert.equal(accessibleText(target), ''); }); it('should match the first example from the ARIA spec', function() { fixture.innerHTML = '<ul role="menubar">' + ' <!-- Rule 2A: "File" label via aria-labelledby -->' + ' <li role="menuitem" aria-haspopup="true" aria-labelledby="fileLabel" id="rule2a">' + ' <span id="fileLabel">File</span>' + ' <ul role="menu">' + ' <!-- Rule 2C: "New" label via Namefrom:contents -->' + ' <li role="menuitem" id="rule2c">New</li>' + ' <li role="menuitem">Open…</li>' + ' …' + ' </ul>' + ' </li>' + '</ul>'; axe._tree = axe.utils.getFlattenedTree(fixture); var rule2a = axe.utils.querySelectorAll(axe._tree, '#rule2a')[0]; var rule2c = axe.utils.querySelectorAll(axe._tree, '#rule2c')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(rule2a), 'File'); assert.equal(axe.commons.text.accessibleTextVirtual(rule2c), 'New'); }); it('should match the second example from the ARIA spec', function() { fixture.innerHTML = '<fieldset>' + ' <legend>Meeting alarms</legend>' + ' <!-- Rule 2A: "Beep" label given by native HTML label element -->' + ' <input type="checkbox" id="beep"> <label for="beep">Beep</label> <br>' + ' <input type="checkbox" id="mtgTitle"> <label for="mtgTitle">Display the meeting title</label> <br>' + ' <!-- Rule 2B -->' + ' <input type="checkbox" id="flash">' + ' <label for="flash">' + ' Flash the screen' + ' <!-- Rule 2A: label of text input given by aria-label, "Number of times to flash screen" -->' + ' <input type="text" value="3" size="2" id="numTimes" aria-label="Number of times to flash screen">' + ' times' + ' </label>' + '</fieldset>'; axe._tree = axe.utils.getFlattenedTree(fixture); var rule2a = axe.utils.querySelectorAll(axe._tree, '#beep')[0]; var rule2b = axe.utils.querySelectorAll(axe._tree, '#flash')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(rule2a), 'Beep'); assert.equal(axe.commons.text.accessibleTextVirtual(rule2b), 'Flash the screen 3 times'); }); it('should use aria-labelledby if present', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'aria-labelledby="t1label" aria-label="ARIA Label" id="t1"> of <i>everything</i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t1')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'This is a label'); }); it('should use recusive aria-labelledby properly', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'aria-labelledby="t1 t1label" aria-label="ARIA Label" id="t1"> of <i>everything</i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t1')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'ARIA Label This is a label'); }); it('should include hidden text referred to with aria-labelledby', function () { fixture.innerHTML = '<div id="t1label" style="display:none">This is a ' + '<span style="visibility:hidden">hidden </span>' + '<span aria-hidden="true">secret</span></div>'+ '<label for="t1">HTML Label</label>' + '<input type="text" id="t1" aria-labelledby="t1label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t1')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'This is a hidden secret'); }); it('should allow setting the initial inLabelledbyContext value', function () { fixture.innerHTML = '<label id="lbl1" style="display:none;">hidden label</label>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#lbl1')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target, false), ''); assert.equal(axe.commons.text.accessibleTextVirtual(target, true), 'hidden label'); }); it('should use aria-label if present with no labelledby', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'aria-label="ARIA Label" id="t1"> of <i>everything</i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t1')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'ARIA Label'); }); it('should use alt on imgs with no ARIA', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'id="t1"> of <i>everything</i></div>' + '<img alt="Alt text goes here" id="target">' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#target')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Alt text goes here'); }); it('should use alt on image inputs with no ARIA', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'id="t1"> of <i>everything</i></div>' + '<input type="image" alt="Alt text goes here" id="target">' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#target')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Alt text goes here'); }); it('should use not use alt on text inputs with no ARIA', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'id="t1"> of <i>everything</i></div>' + '<input type="text" alt="Alt text goes here" id="target">' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#target')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); it('should use HTML label if no ARIA information', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'id="t1"> of <i>everything</i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t1')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'HTML Label'); }); it('should handle last ditch title attribute', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'aria-labelledby="t1label" aria-label="ARIA Label" id="t1"> of <i title="italics"></i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t2label')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'This is This is a label of italics'); }); it('should handle totally empty elements', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'aria-labelledby="t1label" aria-label="ARIA Label" id="t1"> of <i></i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t2label')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'This is This is a label of'); }); it('should handle author name-from roles properly', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'aria-labelledby="t1label" aria-label="ARIA Label" id="t1"> of <i role="alert">everything</i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t2label')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'This is This is a label of'); }); it('should only show each node once when label is before input', function() { fixture.innerHTML = '<div id="target"><label for="tb1">My form input</label>' + '<input type="text" id="tb1"></div>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#target')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'My form input'); }); it('should only show each node once when label follows input', function() { fixture.innerHTML = '<div id="target">' + '<input type="text" id="tb1"></div>' + '<label for="tb1">My form input</label>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#target')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'My form input'); }); it('should handle nested inputs in normal context', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'aria-labelledby="t1label" aria-label="ARIA Label" id="t1"> of <i>everything</i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t2label')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'This is This is a label of everything'); }); it('should use handle nested inputs properly in labelledby context', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'aria-labelledby="t1label" aria-label="ARIA Label" id="t1"> of <i>everything</i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t2')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'This is the value of everything'); }); it('should use ignore hidden inputs', function() { fixture.innerHTML = '<div id="t2label">This is <input type="hidden" value="the value" ' + 'Label" id="t1"> of <i>everything</i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t2')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'This is of everything'); }); it('should use handle inputs with no type as if they were text inputs', function() { fixture.innerHTML = '<div id="t2label">This is <input value="the value" ' + 'aria-labelledby="t1label" aria-label="ARIA Label" id="t1"> of <i>everything</i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t2')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'This is the value of everything'); }); it('should use handle nested selects properly in labelledby context', function() { fixture.innerHTML = '<div id="t2label">This is <select multiple ' + 'aria-labelledby="t1label" aria-label="ARIA Label" id="t1">' + '<option selected>first</option><option>second</option><option selected>third</option>' + '</select> of <i>everything</i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t2')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'This is first third of everything'); }); it('should use handle nested textareas properly in labelledby context', function() { fixture.innerHTML = '<div id="t2label">This is <textarea ' + 'aria-labelledby="t1label" aria-label="ARIA Label" id="t1">the value</textarea> of <i>everything</i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t2')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'This is the value of everything'); }); it('should use handle ARIA labels properly in labelledby context', function() { fixture.innerHTML = '<div id="t2label">This <span aria-label="not a span">span</span>' + ' is <input type="text" value="the value" ' + 'aria-labelledby="t1label" aria-label="ARIA Label" id="t1"> of <i>everything</i></div>' + '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t2')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'This not a span is the value of everything'); }); it('should come up empty if input is labeled only by select options', function () { fixture.innerHTML = '<label for="target">' + '<select id="select">' + ' <option selected="selected">Chosen</option>' + ' <option>Not Selected</option>' + '</select>' + '</label>' + '<input id="target" type="text" />'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#target')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); it('should be empty if input is labeled by labeled select (ref\'d string labels have spotty support)', function () { fixture.innerHTML = '<label for="select">My Select</label>' + '<label for="target">' + '<select id="select">' + ' <option selected="selected">Chosen</option>' + ' <option>Not Selected</option>' + '</select>' + '</label>' + '<input id="target" type="text" />'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#target')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); it('should be empty for an empty label wrapping a select', function () { fixture.innerHTML = '<label>' + '<span class="label"></span>' + '<select id="target">' + '<option value="1" selected="selected">Please choose a region</option>' + '<option value="2">Coastal</option>' + '<option value="3">Forest</option>' + '<option value="4">Grasslands</option>' + '<option value="5">Mountains</option>' + '</select>' + '</label>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#target')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); it('should return select options if input is aria-labelled by a select', function () { fixture.innerHTML = '<label>' + '<select id="select">' + ' <option selected="selected">Chosen</option>' + ' <option>Not Selected</option>' + '</select>' + '</label>' + '<input aria-labelledby="select" type="text" id="target" />'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#target')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Chosen'); }); it('shoud properly fall back to title', function() { fixture.innerHTML = '<a href="#" role="presentation" title="Hello"></a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should give text even for role=presentation on anchors', function() { fixture.innerHTML = '<a href="#" role="presentation">Hello</a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should give text even for role=presentation on buttons', function() { fixture.innerHTML = '<button role="presentation">Hello</button>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'button')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should give text even for role=presentation on summary', function() { fixture.innerHTML = '<summary role="presentation">Hello</summary>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'summary')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('shoud properly fall back to title', function() { fixture.innerHTML = '<a href="#" role="none" title="Hello"></a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should give text even for role=none on anchors', function() { fixture.innerHTML = '<a href="#" role="none">Hello</a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should give text even for role=none on buttons', function() { fixture.innerHTML = '<button role="none">Hello</button>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'button')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should give text even for role=none on summary', function() { fixture.innerHTML = '<summary role="none">Hello</summary>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'summary')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should not add extra spaces around phrasing elements', function() { fixture.innerHTML = '<a href="#">Hello<span>World</span></a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'HelloWorld'); }); it('should add spaces around non-phrasing elements', function() { fixture.innerHTML = '<a href="#">Hello<div>World</div></a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should not look at scripts', function() { fixture.innerHTML = '<a href="#"><script> var ajiasdf = true; </script></a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); it('should use <label> for input buttons', function() { fixture.innerHTML = '<label><input type="button"></label>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); (shadowSupport.v1 ? it : xit)('should only find aria-labelledby element in the same context ', function() { fixture.innerHTML = '<div id="t2label">This is <input type="text" value="the value" ' + 'aria-labelledby="t1label" aria-label="ARIA Label" id="t1"> of <i>everything</i></div>' + '<div id="shadow"></div>'; var shadow = document.getElementById('shadow').attachShadow({ mode: 'open' }); shadow.innerHTML = '<div id="t1label">This is a <b>label</b></div>' + '<label for="t1">HTML Label</label>' + '<input type="text" id="t2" aria-labelledby="t2label">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, '#t1')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'ARIA Label'); }); (shadowSupport.v1 ? it : xit)('should find attributes within a shadow tree', function() { fixture.innerHTML = '<div id="shadow"></div>'; var shadow = document.getElementById('shadow').attachShadow({ mode: 'open' }); shadow.innerHTML = '<input type="text" id="t1" title="I will be king">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'I will be king'); }); (shadowSupport.v1 ? it : xit)('should find attributes within a slot on the shadow tree', function() { fixture.innerHTML = '<div id="shadow"><input type="text" id="t1" title="you will be queen"></div>'; var shadow = document.getElementById('shadow').attachShadow({ mode: 'open' }); shadow.innerHTML = '<slot></slot>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'you will be queen'); }); (shadowSupport.v1 ? it : xit)('should find fallback content for shadow DOM', function() { fixture.innerHTML = '<div id="shadow"></div>'; var shadow = document.getElementById('shadow').attachShadow({ mode: 'open' }); shadow.innerHTML = '<input type="text" id="t1">' + '<label for="t1"><slot>Fallback content heroes</slot></label>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Fallback content heroes'); }); describe('figure', function() { it('should check aria-labelledby', function() { fixture.innerHTML = '<div id="t1">Hello</div>' + '<figure aria-labelledby="t1">Not part of a11yName <figcaption>Fail</figcaption></figure>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'figure')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should check aria-label', function() { fixture.innerHTML = '<figure aria-label="Hello">Not part of a11yName <figcaption>Fail</figcaption></figure>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'figure')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should check the figures figcaption', function() { fixture.innerHTML = '<figure>Not part of a11yName <figcaption>Hello</figcaption></figure>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'figure')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should check title on figure', function() { fixture.innerHTML = '<figure title="Hello">Not part of a11yName <figcaption></figcaption></figure>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'figure')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should not visit innerText of figure', function() { fixture.innerHTML = '<figure>Hello<figcaption></figcaption></figure>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'figure')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); (shadowSupport.v1 ? it : xit)('should check within the composed (shadow) tree', function () { var node = document.createElement('div'); node.innerHTML = 'Hello'; var shadowRoot = node.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = '<figure>Not part of a11yName <figcaption><slot></slot></figcaption></figure>'; fixture.appendChild(node); axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'figure')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); }); describe('img', function() { it('should work with aria-labelledby attribute', function() { fixture.innerHTML = '<div id="t1">Hello</div><div id="t2">World</div>' + '<img aria-labelledby="t1 t2">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'img')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should work with aria-label attribute', function() { fixture.innerHTML = '<img aria-label="Hello World">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'img')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should work with alt attribute', function() { fixture.innerHTML = '<img alt="Hello World">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'img')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should work with title attribute', function() { fixture.innerHTML = '<img title="Hello World">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'img')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); }); describe('input buttons', function() { it('should find value for input type=button', function() { fixture.innerHTML = '<input type="button" value="Hello">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should find value for input type=reset', function() { fixture.innerHTML = '<input type="reset" value="Hello">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should find value for input type=submit', function() { fixture.innerHTML = '<input type="submit" value="Hello">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should provide a default value for input type="submit"', function() { fixture.innerHTML = '<input type="submit">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; // IE inserts this for us, thanks! assert.equal(axe.commons.text.accessibleTextVirtual(target), target.actualNode.value || 'Submit'); }); it('should provide a default value for input type="reset"', function() { fixture.innerHTML = '<input type="reset">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; var defaultText = axe.commons.text.accessibleTextVirtual(target); assert.isString(defaultText); // IE inserts this for us, thanks! assert.equal(defaultText, target.actualNode.value || 'Reset'); }); it('should find title for input type=button', function() { fixture.innerHTML = '<input type="button" title="Hello">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello'); }); it('should find title for input type=reset', function() { fixture.innerHTML = '<input type="reset" title="Hello">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; // IE does not use title; but will use default value instead assert.equal(axe.commons.text.accessibleTextVirtual(target), target.actualNode.value || 'Hello'); }); it('should find title for input type=submit', function() { fixture.innerHTML = '<input type="submit" title="Hello">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; // Again, default value takes precedence over title assert.equal(axe.commons.text.accessibleTextVirtual(target), target.actualNode.value || 'Hello'); }); }); describe('tables', function() { it('should work with aria-labelledby', function() { fixture.innerHTML = '<div id="t1">Hello</div><div id="t2">World</div>' + '<table aria-labelledby="t1 t2"></table>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'table')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should work with aria-label', function() { fixture.innerHTML = '<table aria-label="Hello World"></table>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'table')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should work with the caption element', function() { fixture.innerHTML = '<table><caption>Hello World</caption><tr><td>Stuff</td></tr></table>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'table')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should work with the title attribute', function() { fixture.innerHTML = '<table title="Hello World"></table>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'table')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should work with the summary attribute', function() { fixture.innerHTML = '<table summary="Hello World"></table>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'table')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should prefer title attribute over summary attribute', function() { fixture.innerHTML = '<table title="Hello World" summary="FAIL"></table>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'table')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); }); describe('text inputs', function() { var types = ['text', 'password', 'search', 'tel', 'email', 'url', null]; it('should find aria-labelledby', function() { types.forEach(function(type) { var t = type ? ' type="' + type + '"' : ''; fixture.innerHTML = '<div id="t1">Hello</div><div id="t2">World</div>' + '<input' + t + ' aria-labelledby="t1 t2">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World', type); }); }); it('should find aria-label', function() { types.forEach(function(type) { var t = type ? ' type="' + type + '"' : ''; fixture.innerHTML = '<input' + t + ' aria-label="Hello World">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World', type); }); }); it('should find an implicit label', function() { types.forEach(function(type) { var t = type ? ' type="' + type + '"' : ''; fixture.innerHTML = '<label for="t1">Hello World' + '<input' + t + '></label>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World', type); }); }); it('should find an explicit label', function() { types.forEach(function(type) { var t = type ? ' type="' + type + '"' : ''; fixture.innerHTML = '<label for="t1">Hello World</label>' + '<input' + t + ' id="t1">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World', type); }); }); // not implemented yet, doesn't work accross ATs it.skip('should find a placeholder attribute', function() { types.forEach(function(type) { var t = type ? ' type="' + type + '"' : ''; fixture.innerHTML = '<input' + t + ' placeholder="Hello World">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World', type); }); }); it('should find a title attribute', function() { types.forEach(function(type) { var t = type ? ' type="' + type + '"' : ''; fixture.innerHTML = '<input' + t + ' title="Hello World">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World', type); }); }); it('should otherwise be empty string', function() { types.forEach(function(type) { var t = type ? ' type="' + type + '"' : ''; fixture.innerHTML = '<input' + t + '>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); }); }); describe('textarea', function() { it('should find aria-labelledby', function() { fixture.innerHTML = '<div id="t1">Hello</div><div id="t2">World</div>' + '<textarea aria-labelledby="t1 t2"></textarea>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'textarea')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should find aria-label', function() { fixture.innerHTML = '<textarea aria-label="Hello World"></textarea>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'textarea')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should find an implicit label', function() { fixture.innerHTML = '<label for="t1">Hello World' + '<textarea></textarea></label>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'textarea')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should find an explicit label', function() { fixture.innerHTML = '<label for="t1">Hello World</label>' + '<textarea id="t1"></textarea>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'textarea')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); // not implemented yet, doesn't work accross ATs it.skip('should find a placeholder attribute', function() { fixture.innerHTML = '<textarea placeholder="Hello World"></textarea>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'textarea')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should find a title attribute', function() { fixture.innerHTML = '<textarea title="Hello World"></textarea>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'textarea')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should otherwise be empty string', function() { fixture.innerHTML = '<textarea></textarea>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'textarea')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); }); describe('image inputs', function() { it('should find aria-labelledby', function() { fixture.innerHTML = '<div id="t1">Hello</div><div id="t2">World</div>' + '<input type="image" aria-labelledby="t1 t2">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should find aria-label', function() { fixture.innerHTML = '<input type="image" aria-label="Hello World">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should find an alt attribute', function() { fixture.innerHTML = '<input type="image" alt="Hello World">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); // doesn't work consistently across ATs yet it.skip('should find a value attribute', function() { fixture.innerHTML = '<input type="image" value="Hello World">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should find a title attribute', function() { fixture.innerHTML = '<input type="image" title="Hello World">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should otherwise be empty string', function() { fixture.innerHTML = '<input type="image">'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'input')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); }); describe('a', function() { it('should find aria-labelledby', function() { fixture.innerHTML = '<div id="t1">Hello</div><div id="t2">World</div>' + '<a aria-labelledby="t1 t2"></a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should find aria-label', function() { fixture.innerHTML = '<a aria-label="Hello World"></a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should check subtree', function() { fixture.innerHTML = '<a><span>Hello<span> World</span></span></a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should find a title attribute', function() { fixture.innerHTML = '<a title="Hello World"></a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should otherwise be empty string', function() { fixture.innerHTML = '<a></a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); it('should use text from a table with a single cell and role=presentation', function() { fixture.innerHTML = '<a href="example.html">' + '<table role="presentation">' + '<tr>' + '<td>' + 'Descriptive Link Text' + '</td>' + '</tr>' + '</table>' + '</a>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'a')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Descriptive Link Text'); }); }); describe('button', function() { it('should find aria-labelledby', function() { fixture.innerHTML = '<div id="t1">Hello</div><div id="t2">World</div>' + '<button aria-labelledby="t1 t2"></button>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'button')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should find aria-label', function() { fixture.innerHTML = '<button aria-label="Hello World"></button>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'button')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should check subtree', function() { fixture.innerHTML = '<button><span>Hello<span> World</span></span></button>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'button')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should find a title attribute', function() { fixture.innerHTML = '<button title="Hello World"></button>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'button')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Hello World'); }); it('should otherwise be empty string', function() { fixture.innerHTML = '<button></button>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, 'button')[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); }); describe('text level semantics', function() { var tags = ['em', 'strong', 'small', 's', 'cite', 'q', 'dfn', 'abbr', 'time', 'code', 'var', 'samp', 'kbd', 'sub', 'sup', 'i', 'b', 'u', 'mark', 'ruby', 'rt', 'rp', 'bdi', 'bdo', 'br', 'wbr' ]; it('should find aria-labelledby', function() { tags.forEach(function(tag) { fixture.innerHTML = '<div id="t1">Hello</div><div id="t2">World</div>'; axe._tree = axe.utils.getFlattenedTree(fixture); var elm = document.createElement(tag); elm.setAttribute('aria-labelledby', 't1 t2'); elm.style.display = 'inline'; // Firefox hides some of these elements because reasons... fixture.appendChild(elm); axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.getNodeFromTree(axe._tree[0], elm); var result = axe.commons.text.accessibleTextVirtual(target); assert.equal(result, 'Hello World', tag); }); }); it('should find aria-label', function() { tags.forEach(function(tag) { var elm = document.createElement(tag); elm.setAttribute('aria-label', 'Hello World'); elm.style.display = 'inline'; // Firefox hack, see above fixture.appendChild(elm); axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.getNodeFromTree(axe._tree[0], elm); var result = axe.commons.text.accessibleTextVirtual(target); assert.equal(result, 'Hello World', tag); }); }); it('should find a title attribute', function() { tags.forEach(function(tag) { var elm = document.createElement(tag); elm.setAttribute('title', 'Hello World'); elm.style.display = 'inline'; // Firefox hack, see above fixture.appendChild(elm); axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.getNodeFromTree(axe._tree[0], elm); var result = axe.commons.text.accessibleTextVirtual(target); assert.equal(result, 'Hello World', tag); }); }); it('should otherwise be empty string', function() { tags.forEach(function(tag) { fixture.innerHTML = '<' + tag + '></' + tag + '>'; axe._tree = axe.utils.getFlattenedTree(fixture); var target = axe.utils.querySelectorAll(axe._tree, tag)[0]; assert.equal(axe.commons.text.accessibleTextVirtual(target), ''); }); }); }); });