diff options
Diffstat (limited to '')
8 files changed, 441 insertions, 0 deletions
diff --git a/accessible/tests/browser/states/browser.ini b/accessible/tests/browser/states/browser.ini new file mode 100644 index 0000000000..726c7f4f03 --- /dev/null +++ b/accessible/tests/browser/states/browser.ini @@ -0,0 +1,17 @@ +[DEFAULT] +support-files = + head.js + !/accessible/tests/browser/shared-head.js + !/accessible/tests/mochitest/*.js + !/accessible/tests/browser/*.jsm + +[browser_test_link.js] +skip-if = verify +[browser_test_visibility.js] +[browser_deck_has_out_of_process_iframe.js] +skip-if = (!debug && webrender && (os == 'win')) # bug 1584037 +support-files = + target.html + test_deck_has_out_of_process_iframe.xhtml +[browser_offscreen_element_in_out_of_process_iframe.js] +skip-if = (webrender && os == 'win') # bug 1580706 diff --git a/accessible/tests/browser/states/browser_deck_has_out_of_process_iframe.js b/accessible/tests/browser/states/browser_deck_has_out_of_process_iframe.js new file mode 100644 index 0000000000..155ac4c954 --- /dev/null +++ b/accessible/tests/browser/states/browser_deck_has_out_of_process_iframe.js @@ -0,0 +1,133 @@ +/* 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"; + +const { Preferences } = ChromeUtils.import( + "resource://gre/modules/Preferences.jsm" +); + +const DIRPATH = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + "" +); +const parentPATH = DIRPATH + "test_deck_has_out_of_process_iframe.xhtml"; +const iframePATH = DIRPATH + "target.html"; + +// XXX: Using external files here since using data URL breaks something, e.g. it +// makes querying the second iframe in a hidden deck failure for some reasons. +const parentURL = `http://example.com/${parentPATH}`; +const iframeURL = `http://example.org/${iframePATH}`; + +add_task(async function() { + if (Preferences.locked("fission.autostart")) { + ok( + true, + "fission.autostart pref is locked on this channel which means " + + "we don't need to run the following tests" + ); + return; + } + + const win = await BrowserTestUtils.openNewBrowserWindow({ + fission: true, + }); + + try { + const browser = win.gBrowser.selectedTab.linkedBrowser; + + BrowserTestUtils.loadURI(browser, parentURL); + await BrowserTestUtils.browserLoaded(browser, false, parentURL); + + async function setupIFrame(id, url) { + const iframe = content.document.getElementById(id); + + iframe.contentWindow.location = url; + await new Promise(resolve => { + iframe.addEventListener("load", resolve, { once: true }); + }); + + return iframe.browsingContext; + } + + async function spawnSelectDeck(index) { + async function selectDeck(i) { + const deck = content.document.getElementById("deck"); + + deck.setAttribute("selectedIndex", i); + await new Promise(resolve => { + content.window.addEventListener("MozAfterPaint", resolve, { + once: true, + }); + }); + return deck.selectedIndex; + } + await SpecialPowers.spawn(browser, [index], selectDeck); + + await waitForIFrameUpdates(); + } + + const firstIFrame = await SpecialPowers.spawn( + browser, + ["first", iframeURL], + setupIFrame + ); + const secondIFrame = await SpecialPowers.spawn( + browser, + ["second", iframeURL], + setupIFrame + ); + + await waitForIFrameUpdates(); + + await spawnTestStates( + firstIFrame, + "target", + 0, + nsIAccessibleStates.STATE_OFFSCREEN + ); + // Disable the check for the target element in the unselected pane of the + // deck, this should be fixed by bug 1578932. + // Note: As of now we can't use todo in the script transfered into the + // out-of-process. + //await spawnTestStates( + // secondIFrame, + // "target", + // nsIAccessibleStates.STATE_OFFSCREEN, + // nsIAccessibleStates.STATE_INVISIBLE + //); + + // Select the second panel. + await spawnSelectDeck(1); + await spawnTestStates( + firstIFrame, + "target", + nsIAccessibleStates.STATE_OFFSCREEN, + nsIAccessibleStates.STATE_INVISIBLE + ); + await spawnTestStates( + secondIFrame, + "target", + 0, + nsIAccessibleStates.STATE_OFFSCREEN + ); + + // Select the first panel again. + await spawnSelectDeck(0); + await spawnTestStates( + firstIFrame, + "target", + 0, + nsIAccessibleStates.STATE_OFFSCREEN + ); + await spawnTestStates( + secondIFrame, + "target", + nsIAccessibleStates.STATE_OFFSCREEN, + nsIAccessibleStates.STATE_INVISIBLE + ); + } finally { + await BrowserTestUtils.closeWindow(win); + } +}); diff --git a/accessible/tests/browser/states/browser_offscreen_element_in_out_of_process_iframe.js b/accessible/tests/browser/states/browser_offscreen_element_in_out_of_process_iframe.js new file mode 100644 index 0000000000..289d3fec9a --- /dev/null +++ b/accessible/tests/browser/states/browser_offscreen_element_in_out_of_process_iframe.js @@ -0,0 +1,98 @@ +/* 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"; + +const parentURL = + "data:text/html;charset=utf-8," + + '<div id="scroller" style="width: 300px; height: 300px; overflow-y: scroll; overflow-x: hidden;">' + + ' <div style="width: 100%; height: 1000px;"></div>' + + ' <iframe frameborder="0"/>' + + "</div>"; +const iframeURL = + "data:text/html;charset=utf-8," + + "<style>" + + " html,body {" + + " /* Convenient for calculation of element positions */" + + " margin: 0;" + + " padding: 0;" + + " }" + + "</style>" + + '<div id="target" style="width: 100px; height: 100px;">target</div>'; + +add_task(async function() { + const win = await BrowserTestUtils.openNewBrowserWindow({ + fission: true, + }); + + try { + const browser = win.gBrowser.selectedTab.linkedBrowser; + + BrowserTestUtils.loadURI(browser, parentURL); + await BrowserTestUtils.browserLoaded(browser, false, parentURL); + + async function setup(url) { + const iframe = content.document.querySelector("iframe"); + + iframe.contentWindow.location = url; + await new Promise(resolve => { + iframe.addEventListener("load", resolve, { once: true }); + }); + + return iframe.browsingContext; + } + + async function scrollTo(x, y) { + await SpecialPowers.spawn(browser, [x, y], async (scrollX, scrollY) => { + const scroller = content.document.getElementById("scroller"); + scroller.scrollTo(scrollX, scrollY); + await new Promise(resolve => { + scroller.addEventListener("scroll", resolve, { once: true }); + }); + }); + await waitForIFrameUpdates(); + } + + // Setup an out-of-process iframe which is initially scrolled out. + const iframe = await SpecialPowers.spawn(browser, [iframeURL], setup); + + await waitForIFrameA11yReady(iframe); + await spawnTestStates( + iframe, + "target", + nsIAccessibleStates.STATE_OFFSCREEN, + nsIAccessibleStates.STATE_INVISIBLE + ); + + // Scroll the iframe into view and the target element is also visible but + // the visible area height is 11px. + await scrollTo(0, 711); + await spawnTestStates( + iframe, + "target", + nsIAccessibleStates.STATE_OFFSCREEN, + nsIAccessibleStates.STATE_INVISIBLE + ); + + // Scroll to a position where the visible height is 13px. + await scrollTo(0, 713); + await spawnTestStates( + iframe, + "target", + 0, + nsIAccessibleStates.STATE_OFFSCREEN + ); + + // Scroll the iframe out again. + await scrollTo(0, 0); + await spawnTestStates( + iframe, + "target", + nsIAccessibleStates.STATE_OFFSCREEN, + nsIAccessibleStates.STATE_INVISIBLE + ); + } finally { + await BrowserTestUtils.closeWindow(win); + } +}); diff --git a/accessible/tests/browser/states/browser_test_link.js b/accessible/tests/browser/states/browser_test_link.js new file mode 100644 index 0000000000..f747a69971 --- /dev/null +++ b/accessible/tests/browser/states/browser_test_link.js @@ -0,0 +1,47 @@ +/* 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"; + +/* import-globals-from ../../mochitest/role.js */ +/* import-globals-from ../../mochitest/states.js */ +loadScripts( + { name: "role.js", dir: MOCHITESTS_DIR }, + { name: "states.js", dir: MOCHITESTS_DIR } +); + +async function runTests(browser, accDoc) { + let getAcc = id => findAccessibleChildByID(accDoc, id); + + // a: no traversed state + testStates(getAcc("link_traversed"), 0, 0, STATE_TRAVERSED); + + let onStateChanged = waitForEvent(EVENT_STATE_CHANGE, "link_traversed"); + let newWinOpened = BrowserTestUtils.waitForNewWindow(); + + await BrowserTestUtils.synthesizeMouse( + "#link_traversed", + 1, + 1, + { shiftKey: true }, + browser + ); + + await onStateChanged; + testStates(getAcc("link_traversed"), STATE_TRAVERSED); + + let newWin = await newWinOpened; + await BrowserTestUtils.closeWindow(newWin); +} + +/** + * Test caching of accessible object states + */ +addAccessibleTask( + ` + <a id="link_traversed" href="http://www.example.com" target="_top"> + example.com + </a>`, + runTests +); diff --git a/accessible/tests/browser/states/browser_test_visibility.js b/accessible/tests/browser/states/browser_test_visibility.js new file mode 100644 index 0000000000..572c6f57d3 --- /dev/null +++ b/accessible/tests/browser/states/browser_test_visibility.js @@ -0,0 +1,52 @@ +/* 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"; + +/* import-globals-from ../../mochitest/role.js */ +/* import-globals-from ../../mochitest/states.js */ +loadScripts( + { name: "role.js", dir: MOCHITESTS_DIR }, + { name: "states.js", dir: MOCHITESTS_DIR } +); + +async function runTest(browser, accDoc) { + let getAcc = id => findAccessibleChildByID(accDoc, id); + + testStates(getAcc("div"), 0, 0, STATE_INVISIBLE | STATE_OFFSCREEN); + + let input = getAcc("input_scrolledoff"); + testStates(input, STATE_OFFSCREEN, 0, STATE_INVISIBLE); + + // scrolled off item (twice) + let lastLi = getAcc("li_last"); + testStates(lastLi, STATE_OFFSCREEN, 0, STATE_INVISIBLE); + + // scroll into view the item + await SpecialPowers.spawn(browser, [], () => { + content.document.getElementById("li_last").scrollIntoView(true); + }); + testStates(lastLi, 0, 0, STATE_OFFSCREEN | STATE_INVISIBLE); + + // first item is scrolled off now (testcase for bug 768786) + let firstLi = getAcc("li_first"); + testStates(firstLi, STATE_OFFSCREEN, 0, STATE_INVISIBLE); + + let newTab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + // Accessibles in background tab should have offscreen state and no + // invisible state. + testStates(getAcc("div"), STATE_OFFSCREEN, 0, STATE_INVISIBLE); + BrowserTestUtils.removeTab(newTab); +} + +addAccessibleTask( + ` + <div id="div" style="border:2px solid blue; width: 500px; height: 110vh;"></div> + <input id="input_scrolledoff"> + <ul style="border:2px solid red; width: 100px; height: 50px; overflow: auto;"> + <li id="li_first">item1</li><li>item2</li><li>item3</li> + <li>item4</li><li>item5</li><li id="li_last">item6</li> + </ul>`, + runTest +); diff --git a/accessible/tests/browser/states/head.js b/accessible/tests/browser/states/head.js new file mode 100644 index 0000000000..f9d7393229 --- /dev/null +++ b/accessible/tests/browser/states/head.js @@ -0,0 +1,81 @@ +/* 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"; + +/* exported waitForIFrameA11yReady, waitForIFrameUpdates, spawnTestStates */ + +// Load the shared-head file first. +/* import-globals-from ../shared-head.js */ +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/accessible/tests/browser/shared-head.js", + this +); + +// Loading and common.js from accessible/tests/mochitest/ for all tests, as +// well as promisified-events.js. +loadScripts( + { name: "common.js", dir: MOCHITESTS_DIR }, + { name: "promisified-events.js", dir: MOCHITESTS_DIR } +); + +// This is another version of addA11yLoadEvent for fission. +async function waitForIFrameA11yReady(iFrameBrowsingContext) { + await SimpleTest.promiseFocus(window); + + await SpecialPowers.spawn(iFrameBrowsingContext, [], () => { + return new Promise(resolve => { + function waitForDocLoad() { + SpecialPowers.executeSoon(() => { + const acc = SpecialPowers.Cc[ + "@mozilla.org/accessibilityService;1" + ].getService(SpecialPowers.Ci.nsIAccessibilityService); + + const accDoc = acc.getAccessibleFor(content.document); + let state = {}; + accDoc.getState(state, {}); + if (state.value & SpecialPowers.Ci.nsIAccessibleStates.STATE_BUSY) { + SpecialPowers.executeSoon(waitForDocLoad); + return; + } + resolve(); + }, 0); + } + waitForDocLoad(); + }); + }); +} + +// A utility function to make sure the information of scroll position or visible +// area changes reach to out-of-process iframes. +async function waitForIFrameUpdates() { + // Wait for two frames since the information is notified via asynchronous IPC + // calls. + await new Promise(resolve => requestAnimationFrame(resolve)); + await new Promise(resolve => requestAnimationFrame(resolve)); +} + +// A utility function to test the state of |elementId| element in out-of-process +// |browsingContext|. +async function spawnTestStates(browsingContext, elementId, expectedStates) { + function testStates(id, expected, unexpected) { + const acc = SpecialPowers.Cc[ + "@mozilla.org/accessibilityService;1" + ].getService(SpecialPowers.Ci.nsIAccessibilityService); + const target = content.document.getElementById(id); + let state = {}; + acc.getAccessibleFor(target).getState(state, {}); + if (expected === 0) { + Assert.equal(state.value, expected); + } else { + Assert.ok(state.value & expected); + } + Assert.ok(!(state.value & unexpected)); + } + await SpecialPowers.spawn( + browsingContext, + [elementId, expectedStates], + testStates + ); +} diff --git a/accessible/tests/browser/states/target.html b/accessible/tests/browser/states/target.html new file mode 100644 index 0000000000..0412c13d53 --- /dev/null +++ b/accessible/tests/browser/states/target.html @@ -0,0 +1,3 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<div id="target">target</div> diff --git a/accessible/tests/browser/states/test_deck_has_out_of_process_iframe.xhtml b/accessible/tests/browser/states/test_deck_has_out_of_process_iframe.xhtml new file mode 100644 index 0000000000..72d93ca30a --- /dev/null +++ b/accessible/tests/browser/states/test_deck_has_out_of_process_iframe.xhtml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + title="XUL elements visibility states testing"> +<deck id="deck" selectedIndex="0"> + <iframe id="first" flex="1"/> + <iframe id="second" flex="1"/> +</deck> +</window> |