diff options
Diffstat (limited to 'accessible/tests/browser/e10s/browser_caching_name.js')
-rw-r--r-- | accessible/tests/browser/e10s/browser_caching_name.js | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/accessible/tests/browser/e10s/browser_caching_name.js b/accessible/tests/browser/e10s/browser_caching_name.js new file mode 100644 index 000000000..08e635014 --- /dev/null +++ b/accessible/tests/browser/e10s/browser_caching_name.js @@ -0,0 +1,434 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +'use strict'; + +/* global EVENT_REORDER, EVENT_TEXT_INSERTED */ + +loadScripts({ name: 'name.js', dir: MOCHITESTS_DIR }); + +/** + * Rules for name tests that are inspired by + * accessible/tests/mochitest/name/markuprules.xul + * + * Each element in the list of rules represents a name calculation rule for a + * particular test case. + * + * The rules have the following format: + * { attr } - calculated from attribute + * { elm } - calculated from another element + * { fromsubtree } - calculated from element's subtree + * + * + * Options include: + * * recreated - subrtee is recreated and the test should only continue + * after a reorder event + * * textchanged - text is inserted into a subtree and the test should only + * continue after a text inserted event + */ +const ARIARule = [{ attr: 'aria-labelledby' }, { attr: 'aria-label' }]; +const HTMLControlHeadRule = [...ARIARule, { elm: 'label', isSibling: true }]; +const rules = { + CSSContent: [{ elm: 'style', isSibling: true }, { fromsubtree: true }], + HTMLARIAGridCell: [...ARIARule, { fromsubtree: true }, { attr: 'title' }], + HTMLControl: [...HTMLControlHeadRule, { fromsubtree: true }, + { attr: 'title' }], + HTMLElm: [...ARIARule, { attr: 'title' }], + HTMLImg: [...ARIARule, { attr: 'alt', recreated: true }, { attr: 'title' }], + HTMLImgEmptyAlt: [...ARIARule, { attr: 'title' }, { attr: 'alt' }], + HTMLInputButton: [...HTMLControlHeadRule, { attr: 'value' }, + { attr: 'title' }], + HTMLInputImage: [...HTMLControlHeadRule, { attr: 'alt', recreated: true }, + { attr: 'value', recreated: true }, { attr: 'title' }], + HTMLInputImageNoValidSrc: [...HTMLControlHeadRule, + { attr: 'alt', recreated: true }, { attr: 'value', recreated: true }], + HTMLInputReset: [...HTMLControlHeadRule, + { attr: 'value', textchanged: true }], + HTMLInputSubmit: [...HTMLControlHeadRule, + { attr: 'value', textchanged: true }], + HTMLLink: [...ARIARule, { fromsubtree: true }, { attr: 'title' }], + HTMLLinkImage: [...ARIARule, { elm: 'img' }, { attr: 'title' }], + HTMLOption: [...ARIARule, { attr: 'label' }, { fromsubtree: true }, + { attr: 'title' }], + HTMLTable: [...ARIARule, { elm: 'caption' }, { attr: 'summary' }, + { attr: 'title' }] +}; + +const markupTests = [{ + id: 'btn', + ruleset: 'HTMLControl', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <label for="btn">test4</label> + <button id="btn" + aria-label="test1" + aria-labelledby="l1 l2" + title="test5">press me</button>`, + expected: ['test2 test3', 'test1', 'test4', 'press me', 'test5'] +}, { + id: 'btn', + ruleset: 'HTMLInputButton', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <label for="btn">test4</label> + <input id="btn" + type="button" + aria-label="test1" + aria-labelledby="l1 l2" + value="name from value" + alt="no name from al" + src="no name from src" + data="no name from data" + title="name from title"/>`, + expected: ['test2 test3', 'test1', 'test4', 'name from value', + 'name from title'] +}, { + id: 'btn-submit', + ruleset: 'HTMLInputSubmit', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <label for="btn-submit">test4</label> + <input id="btn-submit" + type="submit" + aria-label="test1" + aria-labelledby="l1 l2" + value="name from value" + alt="no name from atl" + src="no name from src" + data="no name from data" + title="no name from title"/>`, + expected: ['test2 test3', 'test1', 'test4', 'name from value'] +}, { + id: 'btn-reset', + ruleset: 'HTMLInputReset', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <label for="btn-reset">test4</label> + <input id="btn-reset" + type="reset" + aria-label="test1" + aria-labelledby="l1 l2" + value="name from value" + alt="no name from alt" + src="no name from src" + data="no name from data" + title="no name from title"/>`, + expected: ['test2 test3', 'test1', 'test4', 'name from value'] +}, { + id: 'btn-image', + ruleset: 'HTMLInputImage', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <label for="btn-image">test4</label> + <input id="btn-image" + type="image" + aria-label="test1" + aria-labelledby="l1 l2" + alt="name from alt" + value="name from value" + src="http://example.com/a11y/accessible/tests/mochitest/moz.png" + data="no name from data" + title="name from title"/>`, + expected: ['test2 test3', 'test1', 'test4', 'name from alt', + 'name from value', 'name from title'] +}, { + id: 'btn-image', + ruleset: 'HTMLInputImageNoValidSrc', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <label for="btn-image">test4</label> + <input id="btn-image" + type="image" + aria-label="test1" + aria-labelledby="l1 l2" + alt="name from alt" + value="name from value" + data="no name from data" + title="no name from title"/>`, + expected: ['test2 test3', 'test1', 'test4', 'name from alt', + 'name from value'] +}, { + id: 'opt', + ruleset: 'HTMLOption', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <select> + <option id="opt" + aria-label="test1" + aria-labelledby="l1 l2" + label="test4" + title="test5">option1</option> + <option>option2</option> + </select>`, + expected: ['test2 test3', 'test1', 'test4', 'option1', 'test5'] +}, { + id: 'img', + ruleset: 'HTMLImg', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <img id="img" + aria-label="Logo of Mozilla" + aria-labelledby="l1 l2" + alt="Mozilla logo" + title="This is a logo" + src="http://example.com/a11y/accessible/tests/mochitest/moz.png"/>`, + expected: ['test2 test3', 'Logo of Mozilla', 'Mozilla logo', 'This is a logo'] +}, { + id: 'imgemptyalt', + ruleset: 'HTMLImgEmptyAlt', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <img id="imgemptyalt" + aria-label="Logo of Mozilla" + aria-labelledby="l1 l2" + title="This is a logo" + alt="" + src="http://example.com/a11y/accessible/tests/mochitest/moz.png"/>`, + expected: ['test2 test3', 'Logo of Mozilla', 'This is a logo', ''] +}, { + id: 'tc', + ruleset: 'HTMLElm', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <label for="tc">test4</label> + <table> + <tr> + <td id="tc" + aria-label="test1" + aria-labelledby="l1 l2" + title="test5"> + <p>This is a paragraph</p> + <a href="#">This is a link</a> + <ul> + <li>This is a list</li> + </ul> + </td> + </tr> + </table>`, + expected: ['test2 test3', 'test1', 'test5'] +}, { + id: 'gc', + ruleset: 'HTMLARIAGridCell', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <label for="gc">test4</label> + <table> + <tr> + <td id="gc" + role="gridcell" + aria-label="test1" + aria-labelledby="l1 l2" + title="This is a paragraph This is a link This is a list"> + <p>This is a paragraph</p> + <a href="#">This is a link</a> + <ul> + <li>Listitem1</li> + <li>Listitem2</li> + </ul> + </td> + </tr> + </table>`, + expected: ['test2 test3', 'test1', 'This is a paragraph', + 'This is a paragraph This is a link This is a list'] +}, { + id: 't', + ruleset: 'HTMLTable', + markup: ` + <span id="l1">lby_tst6_1</span> + <span id="l2">lby_tst6_2</span> + <label for="t">label_tst6</label> + <table id="t" + aria-label="arialabel_tst6" + aria-labelledby="l1 l2" + summary="summary_tst6" + title="title_tst6"> + <caption>caption_tst6</caption> + <tr> + <td>cell1</td> + <td>cell2</td> + </tr> + </table>`, + expected: ['lby_tst6_1 lby_tst6_2', 'arialabel_tst6', 'caption_tst6', + 'summary_tst6', 'title_tst6'] +}, { + id: 'btn', + ruleset: 'CSSContent', + markup: ` + <style> + button::before { + content: "do not "; + } + </style> + <button id="btn">press me</button>`, + expected: ['do not press me', 'press me'] +}, { + // TODO: uncomment when Bug-1256382 is resoved. + // id: 'li', + // ruleset: 'CSSContent', + // markup: ` + // <style> + // ul { + // list-style-type: decimal; + // } + // </style> + // <ul id="ul"> + // <li id="li">Listitem</li> + // </ul>`, + // expected: ['1. Listitem', `${String.fromCharCode(0x2022)} Listitem`] +// }, { + id: 'a', + ruleset: 'HTMLLink', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <a id="a" + aria-label="test1" + aria-labelledby="l1 l2" + title="test4">test5</a>`, + expected: ['test2 test3', 'test1', 'test5', 'test4'] +}, { + id: 'a-img', + ruleset: 'HTMLLinkImage', + markup: ` + <span id="l1">test2</span> + <span id="l2">test3</span> + <a id="a-img" + aria-label="test1" + aria-labelledby="l1 l2" + title="test4"><img alt="test5"/></a>`, + expected: ['test2 test3', 'test1', 'test5', 'test4'] +}]; + +/** + * Wait for an accessible event to happen and, in case given accessible is + * defunct, update it to one that is attached to the accessible event. + * @param {Promise} onEvent accessible event promise + * @param {Object} target { acc, parent, id } structure that contains an + * accessible, its parent and its content element + * id. + */ +function* updateAccessibleIfNeeded(onEvent, target) { + let event = yield onEvent; + if (isDefunct(target.acc)) { + target.acc = findAccessibleChildByID(event.accessible, target.id); + } +} + +/** + * Test accessible name that is calculated from an attribute, remove the + * attribute before proceeding to the next name test. If attribute removal + * results in a reorder or text inserted event - wait for it. If accessible + * becomes defunct, update its reference using the one that is attached to one + * of the above events. + * @param {Object} browser current "tabbrowser" element + * @param {Object} target { acc, parent, id } structure that contains an + * accessible, its parent and its content element + * id. + * @param {Object} rule current attr rule for name calculation + * @param {[type]} expected expected name value + */ +function* testAttrRule(browser, target, rule, expected) { + testName(target.acc, expected); + let onEvent; + if (rule.recreated) { + onEvent = waitForEvent(EVENT_REORDER, target.parent); + } else if (rule.textchanged) { + onEvent = waitForEvent(EVENT_TEXT_INSERTED, target.id); + } + yield invokeSetAttribute(browser, target.id, rule.attr); + if (onEvent) { + yield updateAccessibleIfNeeded(onEvent, target); + } +} + +/** + * Test accessible name that is calculated from an element name, remove the + * element before proceeding to the next name test. If element removal results + * in a reorder event - wait for it. If accessible becomes defunct, update its + * reference using the one that is attached to a possible reorder event. + * @param {Object} browser current "tabbrowser" element + * @param {Object} target { acc, parent, id } structure that contains an + * accessible, its parent and its content element + * id. + * @param {Object} rule current elm rule for name calculation + * @param {[type]} expected expected name value + */ +function* testElmRule(browser, target, rule, expected) { + testName(target.acc, expected); + let onEvent = waitForEvent(EVENT_REORDER, rule.isSibling ? + target.parent : target.id); + yield ContentTask.spawn(browser, rule.elm, elm => + content.document.querySelector(`${elm}`).remove()); + yield updateAccessibleIfNeeded(onEvent, target); +} + +/** + * Test accessible name that is calculated from its subtree, remove the subtree + * and wait for a reorder event before proceeding to the next name test. If + * accessible becomes defunct, update its reference using the one that is + * attached to a reorder event. + * @param {Object} browser current "tabbrowser" element + * @param {Object} target { acc, parent, id } structure that contains an + * accessible, its parent and its content element + * id. + * @param {Object} rule current subtree rule for name calculation + * @param {[type]} expected expected name value + */ +function* testSubtreeRule(browser, target, rule, expected) { + testName(target.acc, expected); + let onEvent = waitForEvent(EVENT_REORDER, target.id); + yield ContentTask.spawn(browser, target.id, id => { + let elm = content.document.getElementById(id); + while (elm.firstChild) { + elm.removeChild(elm.firstChild); + } + }); + yield updateAccessibleIfNeeded(onEvent, target); +} + +/** + * Iterate over a list of rules and test accessible names for each one of the + * rules. + * @param {Object} browser current "tabbrowser" element + * @param {Object} target { acc, parent, id } structure that contains an + * accessible, its parent and its content element + * id. + * @param {Array} ruleset A list of rules to test a target with + * @param {Array} expected A list of expected name value for each rule + */ +function* testNameRule(browser, target, ruleset, expected) { + for (let i = 0; i < ruleset.length; ++i) { + let rule = ruleset[i]; + let testFn; + if (rule.attr) { + testFn = testAttrRule; + } else if (rule.elm) { + testFn = testElmRule; + } else if (rule.fromsubtree) { + testFn = testSubtreeRule; + } + yield testFn(browser, target, rule, expected[i]); + } +} + +markupTests.forEach(({ id, ruleset, markup, expected }) => + addAccessibleTask(markup, function*(browser, accDoc) { + // Find a target accessible from an accessible subtree. + let acc = findAccessibleChildByID(accDoc, id); + // Find target's parent accessible from an accessible subtree. + let parent = getAccessibleDOMNodeID(acc.parent); + let target = { id, parent, acc }; + yield testNameRule(browser, target, rules[ruleset], expected); + })); |