1781 lines
46 KiB
JavaScript
1781 lines
46 KiB
JavaScript
/* 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/states.js */
|
|
loadScripts({ name: "states.js", dir: MOCHITESTS_DIR });
|
|
|
|
ChromeUtils.defineESModuleGetters(this, {
|
|
PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs",
|
|
});
|
|
|
|
/**
|
|
* Test rotor with heading
|
|
*/
|
|
addAccessibleTask(
|
|
`<h1 id="hello">hello</h1><br><h2 id="world">world</h2><br>goodbye`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXHeadingSearchKey",
|
|
AXImmediateDescendantsOnly: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const headingCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(2, headingCount, "Found two headings");
|
|
|
|
const headings = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
const hello = getNativeInterface(accDoc, "hello");
|
|
const world = getNativeInterface(accDoc, "world");
|
|
is(
|
|
hello.getAttributeValue("AXTitle"),
|
|
headings[0].getAttributeValue("AXTitle"),
|
|
"Found correct first heading"
|
|
);
|
|
is(
|
|
world.getAttributeValue("AXTitle"),
|
|
headings[1].getAttributeValue("AXTitle"),
|
|
"Found correct second heading"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with heading and empty search text
|
|
*/
|
|
addAccessibleTask(
|
|
`<h1 id="hello">hello</h1><br><h2 id="world">world</h2><br>goodbye`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXHeadingSearchKey",
|
|
AXImmediateDescendantsOnly: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
AXSearchText: "",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const headingCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(headingCount, 2, "Found two headings");
|
|
|
|
const headings = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
const hello = getNativeInterface(accDoc, "hello");
|
|
const world = getNativeInterface(accDoc, "world");
|
|
is(
|
|
headings[0].getAttributeValue("AXTitle"),
|
|
hello.getAttributeValue("AXTitle"),
|
|
"Found correct first heading"
|
|
);
|
|
is(
|
|
headings[1].getAttributeValue("AXTitle"),
|
|
world.getAttributeValue("AXTitle"),
|
|
"Found correct second heading"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with articles
|
|
*/
|
|
addAccessibleTask(
|
|
`<article id="google">
|
|
<h2>Google Chrome</h2>
|
|
<p>Google Chrome is a web browser developed by Google, released in 2008. Chrome is the world's most popular web browser today!</p>
|
|
</article>
|
|
|
|
<article id="moz">
|
|
<h2>Mozilla Firefox</h2>
|
|
<p>Mozilla Firefox is an open-source web browser developed by Mozilla. Firefox has been the second most popular web browser since January, 2018.</p>
|
|
</article>
|
|
|
|
<article id="microsoft">
|
|
<h2>Microsoft Edge</h2>
|
|
<p>Microsoft Edge is a web browser developed by Microsoft, released in 2015. Microsoft Edge replaced Internet Explorer.</p>
|
|
</article> `,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXArticleSearchKey",
|
|
AXImmediateDescendantsOnly: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const articleCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(3, articleCount, "Found three articles");
|
|
|
|
const articles = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
const google = getNativeInterface(accDoc, "google");
|
|
const moz = getNativeInterface(accDoc, "moz");
|
|
const microsoft = getNativeInterface(accDoc, "microsoft");
|
|
|
|
is(
|
|
google.getAttributeValue("AXTitle"),
|
|
articles[0].getAttributeValue("AXTitle"),
|
|
"Found correct first article"
|
|
);
|
|
is(
|
|
moz.getAttributeValue("AXTitle"),
|
|
articles[1].getAttributeValue("AXTitle"),
|
|
"Found correct second article"
|
|
);
|
|
is(
|
|
microsoft.getAttributeValue("AXTitle"),
|
|
articles[2].getAttributeValue("AXTitle"),
|
|
"Found correct third article"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with tables
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<table id="shapes">
|
|
<tr>
|
|
<th>Shape</th>
|
|
<th>Color</th>
|
|
<th>Do I like it?</th>
|
|
</tr>
|
|
<tr>
|
|
<td>Triangle</td>
|
|
<td>Green</td>
|
|
<td>No</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Square</td>
|
|
<td>Red</td>
|
|
<td>Yes</td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
<table id="food">
|
|
<tr>
|
|
<th>Grocery Item</th>
|
|
<th>Quantity</th>
|
|
</tr>
|
|
<tr>
|
|
<td>Onions</td>
|
|
<td>2</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Yogurt</td>
|
|
<td>1</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Spinach</td>
|
|
<td>1</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Cherries</td>
|
|
<td>12</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Carrots</td>
|
|
<td>5</td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
<div role="table" id="ariaTable">
|
|
<div role="row">
|
|
<div role="cell">
|
|
I am a tiny aria table
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<br>
|
|
<table role="grid" id="grid">
|
|
<tr>
|
|
<th>A</th>
|
|
<th>B</th>
|
|
<th>C</th>
|
|
<th>D</th>
|
|
<th>E</th>
|
|
</tr>
|
|
<tr>
|
|
<th>F</th>
|
|
<th>G</th>
|
|
<th>H</th>
|
|
<th>I</th>
|
|
<th>J</th>
|
|
</tr>
|
|
</table>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXTableSearchKey",
|
|
AXImmediateDescendantsOnly: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const tableCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(tableCount, 3, "Found three tables");
|
|
|
|
const tables = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
const shapes = getNativeInterface(accDoc, "shapes");
|
|
const food = getNativeInterface(accDoc, "food");
|
|
const ariaTable = getNativeInterface(accDoc, "ariaTable");
|
|
|
|
is(
|
|
shapes.getAttributeValue("AXColumnCount"),
|
|
tables[0].getAttributeValue("AXColumnCount"),
|
|
"Found correct first table"
|
|
);
|
|
is(
|
|
food.getAttributeValue("AXColumnCount"),
|
|
tables[1].getAttributeValue("AXColumnCount"),
|
|
"Found correct second table"
|
|
);
|
|
is(
|
|
ariaTable.getAttributeValue("AXColumnCount"),
|
|
tables[2].getAttributeValue("AXColumnCount"),
|
|
"Found correct third table"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with landmarks
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<header id="header">
|
|
<h1>This is a heading within a header</h1>
|
|
</header>
|
|
|
|
<nav id="nav">
|
|
<a href="example.com">I am a link in a nav</a>
|
|
</nav>
|
|
|
|
<main id="main">
|
|
I am some text in a main element
|
|
</main>
|
|
|
|
<footer id="footer">
|
|
<h2>Heading in footer</h2>
|
|
</footer>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXLandmarkSearchKey",
|
|
AXImmediateDescendantsOnly: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const landmarkCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(4, landmarkCount, "Found four landmarks");
|
|
|
|
const landmarks = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
const header = getNativeInterface(accDoc, "header");
|
|
const nav = getNativeInterface(accDoc, "nav");
|
|
const main = getNativeInterface(accDoc, "main");
|
|
const footer = getNativeInterface(accDoc, "footer");
|
|
|
|
is(
|
|
header.getAttributeValue("AXSubrole"),
|
|
landmarks[0].getAttributeValue("AXSubrole"),
|
|
"Found correct first landmark"
|
|
);
|
|
is(
|
|
nav.getAttributeValue("AXSubrole"),
|
|
landmarks[1].getAttributeValue("AXSubrole"),
|
|
"Found correct second landmark"
|
|
);
|
|
is(
|
|
main.getAttributeValue("AXSubrole"),
|
|
landmarks[2].getAttributeValue("AXSubrole"),
|
|
"Found correct third landmark"
|
|
);
|
|
is(
|
|
footer.getAttributeValue("AXSubrole"),
|
|
landmarks[3].getAttributeValue("AXSubrole"),
|
|
"Found correct fourth landmark"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with aria landmarks
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<div id="banner" role="banner">
|
|
<h1>This is a heading within a banner</h1>
|
|
</div>
|
|
|
|
<div id="nav" role="navigation">
|
|
<a href="example.com">I am a link in a nav</a>
|
|
</div>
|
|
|
|
<div id="main" role="main">
|
|
I am some text in a main element
|
|
</div>
|
|
|
|
<div id="contentinfo" role="contentinfo">
|
|
<h2>Heading in contentinfo</h2>
|
|
</div>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXLandmarkSearchKey",
|
|
AXImmediateDescendantsOnly: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const landmarkCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(4, landmarkCount, "Found four landmarks");
|
|
|
|
const landmarks = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
const banner = getNativeInterface(accDoc, "banner");
|
|
const nav = getNativeInterface(accDoc, "nav");
|
|
const main = getNativeInterface(accDoc, "main");
|
|
const contentinfo = getNativeInterface(accDoc, "contentinfo");
|
|
|
|
is(
|
|
banner.getAttributeValue("AXSubrole"),
|
|
landmarks[0].getAttributeValue("AXSubrole"),
|
|
"Found correct first landmark"
|
|
);
|
|
is(
|
|
nav.getAttributeValue("AXSubrole"),
|
|
landmarks[1].getAttributeValue("AXSubrole"),
|
|
"Found correct second landmark"
|
|
);
|
|
is(
|
|
main.getAttributeValue("AXSubrole"),
|
|
landmarks[2].getAttributeValue("AXSubrole"),
|
|
"Found correct third landmark"
|
|
);
|
|
is(
|
|
contentinfo.getAttributeValue("AXSubrole"),
|
|
landmarks[3].getAttributeValue("AXSubrole"),
|
|
"Found correct fourth landmark"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with buttons
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<button id="button">hello world</button><br>
|
|
|
|
<input type="button" value="another kinda button" id="input"><br>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXButtonSearchKey",
|
|
AXImmediateDescendantsOnly: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const buttonCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(2, buttonCount, "Found two buttons");
|
|
|
|
const buttons = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
const button = getNativeInterface(accDoc, "button");
|
|
const input = getNativeInterface(accDoc, "input");
|
|
|
|
is(
|
|
button.getAttributeValue("AXRole"),
|
|
buttons[0].getAttributeValue("AXRole"),
|
|
"Found correct button"
|
|
);
|
|
is(
|
|
input.getAttributeValue("AXRole"),
|
|
buttons[1].getAttributeValue("AXRole"),
|
|
"Found correct input button"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with heading
|
|
*/
|
|
addAccessibleTask(
|
|
`<h1 id="hello">hello</h1><br><h2 id="world">world</h2><br>goodbye`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXHeadingSearchKey",
|
|
AXImmediateDescendants: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const headingCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(2, headingCount, "Found two headings");
|
|
|
|
const headings = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
const hello = getNativeInterface(accDoc, "hello");
|
|
const world = getNativeInterface(accDoc, "world");
|
|
is(
|
|
hello.getAttributeValue("AXTitle"),
|
|
headings[0].getAttributeValue("AXTitle"),
|
|
"Found correct first heading"
|
|
);
|
|
is(
|
|
world.getAttributeValue("AXTitle"),
|
|
headings[1].getAttributeValue("AXTitle"),
|
|
"Found correct second heading"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with buttons
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<form>
|
|
<h2>input[type=button]</h2>
|
|
<input type="button" value="apply" id="button1">
|
|
|
|
<h2>input[type=submit]</h2>
|
|
<input type="submit" value="submit now" id="submit">
|
|
|
|
<h2>input[type=image]</h2>
|
|
<input type="image" src="sample.jpg" alt="submit image" id="image">
|
|
|
|
<h2>input[type=reset]</h2>
|
|
<input type="reset" value="reset now" id="reset">
|
|
|
|
<h2>button element</h2>
|
|
<button id="button2">Submit button</button>
|
|
</form>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXControlSearchKey",
|
|
AXImmediateDescendants: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const controlsCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(5, controlsCount, "Found 5 controls");
|
|
|
|
const controls = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
const button1 = getNativeInterface(accDoc, "button1");
|
|
const submit = getNativeInterface(accDoc, "submit");
|
|
const image = getNativeInterface(accDoc, "image");
|
|
const reset = getNativeInterface(accDoc, "reset");
|
|
const button2 = getNativeInterface(accDoc, "button2");
|
|
|
|
is(
|
|
button1.getAttributeValue("AXTitle"),
|
|
controls[0].getAttributeValue("AXTitle"),
|
|
"Found correct first control"
|
|
);
|
|
is(
|
|
submit.getAttributeValue("AXTitle"),
|
|
controls[1].getAttributeValue("AXTitle"),
|
|
"Found correct second control"
|
|
);
|
|
is(
|
|
image.getAttributeValue("AXTitle"),
|
|
controls[2].getAttributeValue("AXTitle"),
|
|
"Found correct third control"
|
|
);
|
|
is(
|
|
reset.getAttributeValue("AXTitle"),
|
|
controls[3].getAttributeValue("AXTitle"),
|
|
"Found correct third control"
|
|
);
|
|
is(
|
|
button2.getAttributeValue("AXTitle"),
|
|
controls[4].getAttributeValue("AXTitle"),
|
|
"Found correct third control"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with inputs
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<input type="text" value="I'm a text field." id="text"><br>
|
|
<input type="text" value="me too" id="implText"><br>
|
|
<textarea id="textarea">this is some text in a text area</textarea><br>
|
|
<input type="tel" value="0000000000" id="tel"><br>
|
|
<input type="url" value="https://example.com" id="url"><br>
|
|
<input type="email" value="hi@example.com" id="email"><br>
|
|
<input type="password" value="blah" id="password"><br>
|
|
<input type="month" value="2020-01" id="month"><br>
|
|
<input type="week" value="2020-W01" id="week"><br>
|
|
<input type="number" value="12" id="number"><br>
|
|
<input type="range" value="12" min="0" max="20" id="range"><br>
|
|
<input type="date" value="2020-01-01" id="date"><br>
|
|
<input type="time" value="10:10:10" id="time"><br>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXControlSearchKey",
|
|
AXImmediateDescendants: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const controlsCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
is(13, controlsCount, "Found 13 controls");
|
|
// the extra controls here come from our time control
|
|
// we can't filter out its internal buttons/incrementors
|
|
// like we do with the date entry because the time entry
|
|
// doesn't have its own specific role -- its just a grouping.
|
|
|
|
const controls = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
const text = getNativeInterface(accDoc, "text");
|
|
const implText = getNativeInterface(accDoc, "implText");
|
|
const textarea = getNativeInterface(accDoc, "textarea");
|
|
const tel = getNativeInterface(accDoc, "tel");
|
|
const url = getNativeInterface(accDoc, "url");
|
|
const email = getNativeInterface(accDoc, "email");
|
|
const password = getNativeInterface(accDoc, "password");
|
|
const month = getNativeInterface(accDoc, "month");
|
|
const week = getNativeInterface(accDoc, "week");
|
|
const number = getNativeInterface(accDoc, "number");
|
|
const range = getNativeInterface(accDoc, "range");
|
|
|
|
const toCheck = [
|
|
text,
|
|
implText,
|
|
textarea,
|
|
tel,
|
|
url,
|
|
email,
|
|
password,
|
|
month,
|
|
week,
|
|
number,
|
|
range,
|
|
];
|
|
|
|
for (let i = 0; i < toCheck.length; i++) {
|
|
is(
|
|
toCheck[i].getAttributeValue("AXValue"),
|
|
controls[i].getAttributeValue("AXValue"),
|
|
"Found correct input control"
|
|
);
|
|
}
|
|
|
|
const date = getNativeInterface(accDoc, "date");
|
|
const time = getNativeInterface(accDoc, "time");
|
|
|
|
is(
|
|
date.getAttributeValue("AXRole"),
|
|
controls[11].getAttributeValue("AXRole"),
|
|
"Found corrent date editor"
|
|
);
|
|
|
|
is(
|
|
time.getAttributeValue("AXRole"),
|
|
controls[12].getAttributeValue("AXRole"),
|
|
"Found corrent time editor"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with groupings
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<fieldset>
|
|
<legend>Radios</legend>
|
|
<div role="radiogroup" id="radios">
|
|
<input id="radio1" type="radio" name="g1" checked="checked"> Radio 1
|
|
<input id="radio2" type="radio" name="g1"> Radio 2
|
|
</div>
|
|
</fieldset>
|
|
|
|
<fieldset id="checkboxes">
|
|
<legend>Checkboxes</legend>
|
|
<input id="checkbox1" type="checkbox" name="g2"> Checkbox 1
|
|
<input id="checkbox2" type="checkbox" name="g2" checked="checked">Checkbox 2
|
|
</fieldset>
|
|
|
|
<fieldset id="switches">
|
|
<legend>Switches</legend>
|
|
<input id="switch1" name="g3" role="switch" type="checkbox">Switch 1
|
|
<input checked="checked" id="switch2" name="g3" role="switch" type="checkbox">Switch 2
|
|
</fieldset>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXControlSearchKey",
|
|
AXImmediateDescendants: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const controlsCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(9, controlsCount, "Found 9 controls");
|
|
|
|
const controls = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
const radios = getNativeInterface(accDoc, "radios");
|
|
const radio1 = getNativeInterface(accDoc, "radio1");
|
|
const radio2 = getNativeInterface(accDoc, "radio2");
|
|
|
|
is(
|
|
radios.getAttributeValue("AXRole"),
|
|
controls[0].getAttributeValue("AXRole"),
|
|
"Found correct group of radios"
|
|
);
|
|
is(
|
|
radio1.getAttributeValue("AXRole"),
|
|
controls[1].getAttributeValue("AXRole"),
|
|
"Found correct radio 1"
|
|
);
|
|
is(
|
|
radio2.getAttributeValue("AXRole"),
|
|
controls[2].getAttributeValue("AXRole"),
|
|
"Found correct radio 2"
|
|
);
|
|
|
|
const checkboxes = getNativeInterface(accDoc, "checkboxes");
|
|
const checkbox1 = getNativeInterface(accDoc, "checkbox1");
|
|
const checkbox2 = getNativeInterface(accDoc, "checkbox2");
|
|
|
|
is(
|
|
checkboxes.getAttributeValue("AXRole"),
|
|
controls[3].getAttributeValue("AXRole"),
|
|
"Found correct group of checkboxes"
|
|
);
|
|
is(
|
|
checkbox1.getAttributeValue("AXRole"),
|
|
controls[4].getAttributeValue("AXRole"),
|
|
"Found correct checkbox 1"
|
|
);
|
|
is(
|
|
checkbox2.getAttributeValue("AXRole"),
|
|
controls[5].getAttributeValue("AXRole"),
|
|
"Found correct checkbox 2"
|
|
);
|
|
|
|
const switches = getNativeInterface(accDoc, "switches");
|
|
const switch1 = getNativeInterface(accDoc, "switch1");
|
|
const switch2 = getNativeInterface(accDoc, "switch2");
|
|
|
|
is(
|
|
switches.getAttributeValue("AXRole"),
|
|
controls[6].getAttributeValue("AXRole"),
|
|
"Found correct group of switches"
|
|
);
|
|
is(
|
|
switch1.getAttributeValue("AXRole"),
|
|
controls[7].getAttributeValue("AXRole"),
|
|
"Found correct switch 1"
|
|
);
|
|
is(
|
|
switch2.getAttributeValue("AXRole"),
|
|
controls[8].getAttributeValue("AXRole"),
|
|
"Found correct switch 2"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with misc controls
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<input role="spinbutton" id="spinbutton" type="number" value="25">
|
|
|
|
<details id="details">
|
|
<summary>Hello</summary>
|
|
world
|
|
</details>
|
|
|
|
<ul role="tree" id="tree">
|
|
<li role="treeitem">item1</li>
|
|
<li role="treeitem">item1</li>
|
|
</ul>
|
|
|
|
<a id="buttonMenu" role="button">Click Me</a>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXControlSearchKey",
|
|
AXImmediateDescendants: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const controlsCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(4, controlsCount, "Found 4 controls");
|
|
|
|
const controls = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
const spin = getNativeInterface(accDoc, "spinbutton");
|
|
const details = getNativeInterface(accDoc, "details");
|
|
const tree = getNativeInterface(accDoc, "tree");
|
|
const buttonMenu = getNativeInterface(accDoc, "buttonMenu");
|
|
|
|
is(
|
|
spin.getAttributeValue("AXRole"),
|
|
controls[0].getAttributeValue("AXRole"),
|
|
"Found correct spinbutton"
|
|
);
|
|
is(
|
|
details.getAttributeValue("AXRole"),
|
|
controls[1].getAttributeValue("AXRole"),
|
|
"Found correct details element"
|
|
);
|
|
is(
|
|
tree.getAttributeValue("AXRole"),
|
|
controls[2].getAttributeValue("AXRole"),
|
|
"Found correct tree"
|
|
);
|
|
is(
|
|
buttonMenu.getAttributeValue("AXRole"),
|
|
controls[3].getAttributeValue("AXRole"),
|
|
"Found correct button menu"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with links
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<a href="" id="empty">empty link</a>
|
|
<a href="http://www.example.com/" id="href">Example link</a>
|
|
<a id="noHref">link without href</a>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
let searchPred = {
|
|
AXSearchKey: "AXLinkSearchKey",
|
|
AXImmediateDescendants: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
let linkCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(2, linkCount, "Found two links");
|
|
|
|
let links = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
const empty = getNativeInterface(accDoc, "empty");
|
|
const href = getNativeInterface(accDoc, "href");
|
|
|
|
is(
|
|
empty.getAttributeValue("AXTitle"),
|
|
links[0].getAttributeValue("AXTitle"),
|
|
"Found correct first link"
|
|
);
|
|
is(
|
|
href.getAttributeValue("AXTitle"),
|
|
links[1].getAttributeValue("AXTitle"),
|
|
"Found correct second link"
|
|
);
|
|
|
|
// unvisited links
|
|
|
|
searchPred = {
|
|
AXSearchKey: "AXUnvisitedLinkSearchKey",
|
|
AXImmediateDescendants: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
linkCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
is(2, linkCount, "Found two links");
|
|
|
|
links = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
is(
|
|
empty.getAttributeValue("AXTitle"),
|
|
links[0].getAttributeValue("AXTitle"),
|
|
"Found correct first link"
|
|
);
|
|
is(
|
|
href.getAttributeValue("AXTitle"),
|
|
links[1].getAttributeValue("AXTitle"),
|
|
"Found correct second link"
|
|
);
|
|
|
|
// visited links
|
|
|
|
let stateChanged = waitForEvent(EVENT_STATE_CHANGE, "href");
|
|
|
|
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
|
await PlacesTestUtils.addVisits(["http://www.example.com/"]);
|
|
|
|
await stateChanged;
|
|
|
|
searchPred = {
|
|
AXSearchKey: "AXVisitedLinkSearchKey",
|
|
AXImmediateDescendants: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
linkCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(1, linkCount, "Found one link");
|
|
|
|
links = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
is(
|
|
href.getAttributeValue("AXTitle"),
|
|
links[0].getAttributeValue("AXTitle"),
|
|
"Found correct visited link"
|
|
);
|
|
|
|
// Ensure history is cleared before running again
|
|
await PlacesUtils.history.clear();
|
|
}
|
|
);
|
|
|
|
/*
|
|
* Test AXAnyTypeSearchKey with root group
|
|
*/
|
|
addAccessibleTask(
|
|
`<h1 id="hello">hello</h1><br><h2 id="world">world</h2><br>goodbye`,
|
|
(browser, accDoc) => {
|
|
let searchPred = {
|
|
AXSearchKey: "AXAnyTypeSearchKey",
|
|
AXImmediateDescendantsOnly: 1,
|
|
AXResultsLimit: 1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
let results = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(results.length, 1, "One result for root group");
|
|
is(
|
|
results[0].getAttributeValue("AXIdentifier"),
|
|
"root-group",
|
|
"Is generated root group"
|
|
);
|
|
|
|
searchPred.AXStartElement = results[0];
|
|
results = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(results.length, 0, "No more results past root group");
|
|
|
|
searchPred.AXDirection = "AXDirectionPrevious";
|
|
results = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(
|
|
results.length,
|
|
0,
|
|
"Searching backwards from root group should yield no results"
|
|
);
|
|
|
|
const rootGroup = webArea.getAttributeValue("AXChildren")[0];
|
|
is(
|
|
rootGroup.getAttributeValue("AXIdentifier"),
|
|
"root-group",
|
|
"Is generated root group"
|
|
);
|
|
|
|
searchPred = {
|
|
AXSearchKey: "AXAnyTypeSearchKey",
|
|
AXImmediateDescendantsOnly: 1,
|
|
AXResultsLimit: 1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
results = rootGroup.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
is(
|
|
results[0].getAttributeValue("AXRole"),
|
|
"AXHeading",
|
|
"Is first heading child"
|
|
);
|
|
},
|
|
{ contentDocBodyAttrs: { role: "application" } }
|
|
);
|
|
|
|
/**
|
|
* Test rotor with checkboxes
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<fieldset id="checkboxes">
|
|
<legend>Checkboxes</legend>
|
|
<input id="checkbox1" type="checkbox" name="g2"> Checkbox 1
|
|
<input id="checkbox2" type="checkbox" name="g2" checked="checked">Checkbox 2
|
|
<div id="checkbox3" role="checkbox">Checkbox 3</div>
|
|
<div id="checkbox4" role="checkbox" aria-checked="true">Checkbox 4</div>
|
|
</fieldset>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXCheckBoxSearchKey",
|
|
AXImmediateDescendantsOnly: 0,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const checkboxCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(4, checkboxCount, "Found 4 checkboxes");
|
|
|
|
const checkboxes = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
const checkbox1 = getNativeInterface(accDoc, "checkbox1");
|
|
const checkbox2 = getNativeInterface(accDoc, "checkbox2");
|
|
const checkbox3 = getNativeInterface(accDoc, "checkbox3");
|
|
const checkbox4 = getNativeInterface(accDoc, "checkbox4");
|
|
|
|
is(
|
|
checkbox1.getAttributeValue("AXValue"),
|
|
checkboxes[0].getAttributeValue("AXValue"),
|
|
"Found correct checkbox 1"
|
|
);
|
|
is(
|
|
checkbox2.getAttributeValue("AXValue"),
|
|
checkboxes[1].getAttributeValue("AXValue"),
|
|
"Found correct checkbox 2"
|
|
);
|
|
is(
|
|
checkbox3.getAttributeValue("AXValue"),
|
|
checkboxes[2].getAttributeValue("AXValue"),
|
|
"Found correct checkbox 3"
|
|
);
|
|
is(
|
|
checkbox4.getAttributeValue("AXValue"),
|
|
checkboxes[3].getAttributeValue("AXValue"),
|
|
"Found correct checkbox 4"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with radiogroups
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<div role="radiogroup" id="radios" aria-labelledby="desc">
|
|
<h1 id="desc">some radio buttons</h1>
|
|
<div id="radio1" role="radio"> Radio 1</div>
|
|
<div id="radio2" role="radio"> Radio 2</div>
|
|
</div>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXRadioGroupSearchKey",
|
|
AXImmediateDescendants: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const radiogroupCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(1, radiogroupCount, "Found 1 radio group");
|
|
|
|
const controls = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
const radios = getNativeInterface(accDoc, "radios");
|
|
|
|
is(
|
|
radios.getAttributeValue("AXDescription"),
|
|
controls[0].getAttributeValue("AXDescription"),
|
|
"Found correct group of radios"
|
|
);
|
|
}
|
|
);
|
|
|
|
/*
|
|
* Test rotor with inputs
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<input type="text" value="I'm a text field." id="text"><br>
|
|
<input type="text" value="me too" id="implText"><br>
|
|
<textarea id="textarea">this is some text in a text area</textarea><br>
|
|
<input type="tel" value="0000000000" id="tel"><br>
|
|
<input type="url" value="https://example.com" id="url"><br>
|
|
<input type="email" value="hi@example.com" id="email"><br>
|
|
<input type="password" value="blah" id="password"><br>
|
|
<input type="month" value="2020-01" id="month"><br>
|
|
<input type="week" value="2020-W01" id="week"><br>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXTextFieldSearchKey",
|
|
AXImmediateDescendants: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const textfieldCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
is(9, textfieldCount, "Found 9 fields");
|
|
|
|
const fields = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
const text = getNativeInterface(accDoc, "text");
|
|
const implText = getNativeInterface(accDoc, "implText");
|
|
const textarea = getNativeInterface(accDoc, "textarea");
|
|
const tel = getNativeInterface(accDoc, "tel");
|
|
const url = getNativeInterface(accDoc, "url");
|
|
const email = getNativeInterface(accDoc, "email");
|
|
const password = getNativeInterface(accDoc, "password");
|
|
const month = getNativeInterface(accDoc, "month");
|
|
const week = getNativeInterface(accDoc, "week");
|
|
|
|
const toCheck = [
|
|
text,
|
|
implText,
|
|
textarea,
|
|
tel,
|
|
url,
|
|
email,
|
|
password,
|
|
month,
|
|
week,
|
|
];
|
|
|
|
for (let i = 0; i < toCheck.length; i++) {
|
|
is(
|
|
toCheck[i].getAttributeValue("AXValue"),
|
|
fields[i].getAttributeValue("AXValue"),
|
|
"Found correct input control"
|
|
);
|
|
}
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with static text
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<h1>Hello I am a heading</h1>
|
|
This is some regular text.<p>this is some paragraph text</p><br>
|
|
This is a list:<ul>
|
|
<li>List item one</li>
|
|
<li>List item two</li>
|
|
</ul>
|
|
|
|
<a href="http://example.com">This is a link</a>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXStaticTextSearchKey",
|
|
AXImmediateDescendants: 0,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const textCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(7, textCount, "Found 7 pieces of text");
|
|
|
|
const text = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
is(
|
|
"Hello I am a heading",
|
|
text[0].getAttributeValue("AXValue"),
|
|
"Found correct text node for heading"
|
|
);
|
|
is(
|
|
"This is some regular text.",
|
|
text[1].getAttributeValue("AXValue"),
|
|
"Found correct text node"
|
|
);
|
|
is(
|
|
"this is some paragraph text",
|
|
text[2].getAttributeValue("AXValue"),
|
|
"Found correct text node for paragraph"
|
|
);
|
|
is(
|
|
"This is a list:",
|
|
text[3].getAttributeValue("AXValue"),
|
|
"Found correct text node for pre-list text node"
|
|
);
|
|
is(
|
|
"List item one",
|
|
text[4].getAttributeValue("AXValue"),
|
|
"Found correct text node for list item one"
|
|
);
|
|
is(
|
|
"List item two",
|
|
text[5].getAttributeValue("AXValue"),
|
|
"Found correct text node for list item two"
|
|
);
|
|
is(
|
|
"This is a link",
|
|
text[6].getAttributeValue("AXValue"),
|
|
"Found correct text node for link"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with lists
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<ul id="unordered">
|
|
<li>hello</li>
|
|
<li>world</li>
|
|
</ul>
|
|
|
|
<ol id="ordered">
|
|
<li>item one</li>
|
|
<li>item two</li>
|
|
</ol>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXListSearchKey",
|
|
AXImmediateDescendants: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const listCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
is(2, listCount, "Found 2 lists");
|
|
|
|
const lists = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
const ordered = getNativeInterface(accDoc, "ordered");
|
|
const unordered = getNativeInterface(accDoc, "unordered");
|
|
|
|
is(
|
|
unordered.getAttributeValue("AXChildren")[0].getAttributeValue("AXTitle"),
|
|
lists[0].getAttributeValue("AXChildren")[0].getAttributeValue("AXTitle"),
|
|
"Found correct unordered list"
|
|
);
|
|
is(
|
|
ordered.getAttributeValue("AXChildren")[0].getAttributeValue("AXTitle"),
|
|
lists[1].getAttributeValue("AXChildren")[0].getAttributeValue("AXTitle"),
|
|
"Found correct ordered list"
|
|
);
|
|
}
|
|
);
|
|
|
|
/*
|
|
* Test rotor with images
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<img id="img1" alt="image one" src="http://example.com/a11y/accessible/tests/mochitest/moz.png"><br>
|
|
<a href="http://example.com">
|
|
<img id="img2" alt="image two" src="http://example.com/a11y/accessible/tests/mochitest/moz.png">
|
|
</a>
|
|
<img src="" id="img3">
|
|
`,
|
|
(browser, accDoc) => {
|
|
let searchPred = {
|
|
AXSearchKey: "AXImageSearchKey",
|
|
AXImmediateDescendantsOnly: 0,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
let images = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
is(images.length, 3, "Found three images");
|
|
|
|
const img1 = getNativeInterface(accDoc, "img1");
|
|
const img2 = getNativeInterface(accDoc, "img2");
|
|
const img3 = getNativeInterface(accDoc, "img3");
|
|
|
|
is(
|
|
img1.getAttributeValue("AXDescription"),
|
|
images[0].getAttributeValue("AXDescription"),
|
|
"Found correct image"
|
|
);
|
|
|
|
is(
|
|
img2.getAttributeValue("AXDescription"),
|
|
images[1].getAttributeValue("AXDescription"),
|
|
"Found correct image"
|
|
);
|
|
|
|
is(
|
|
img3.getAttributeValue("AXDescription"),
|
|
images[2].getAttributeValue("AXDescription"),
|
|
"Found correct image"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with frames
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<iframe id="frame1" src="data:text/html,<h1>hello</h1>world"></iframe>
|
|
<iframe id="frame2" src="data:text/html,<iframe id='frame3' src='data:text/html,<h1>goodbye</h1>'>"></iframe>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXFrameSearchKey",
|
|
AXImmediateDescendantsOnly: 0,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const frameCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(3, frameCount, "Found 3 frames");
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test rotor with static text
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<h1>Hello I am a heading</h1>
|
|
This is some regular text.<p>this is some paragraph text</p><br>
|
|
This is a list:<ul>
|
|
<li>List item one</li>
|
|
<li>List item two</li>
|
|
</ul>
|
|
|
|
<a href="http://example.com">This is a link</a>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXStaticTextSearchKey",
|
|
AXImmediateDescendants: 0,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const textCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(7, textCount, "Found 7 pieces of text");
|
|
|
|
const text = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
is(
|
|
"Hello I am a heading",
|
|
text[0].getAttributeValue("AXValue"),
|
|
"Found correct text node for heading"
|
|
);
|
|
is(
|
|
"This is some regular text.",
|
|
text[1].getAttributeValue("AXValue"),
|
|
"Found correct text node"
|
|
);
|
|
is(
|
|
"this is some paragraph text",
|
|
text[2].getAttributeValue("AXValue"),
|
|
"Found correct text node for paragraph"
|
|
);
|
|
is(
|
|
"This is a list:",
|
|
text[3].getAttributeValue("AXValue"),
|
|
"Found correct text node for pre-list text node"
|
|
);
|
|
is(
|
|
"List item one",
|
|
text[4].getAttributeValue("AXValue"),
|
|
"Found correct text node for list item one"
|
|
);
|
|
is(
|
|
"List item two",
|
|
text[5].getAttributeValue("AXValue"),
|
|
"Found correct text node for list item two"
|
|
);
|
|
is(
|
|
"This is a link",
|
|
text[6].getAttributeValue("AXValue"),
|
|
"Found correct text node for link"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test search with non-webarea root
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<div id="searchroot"><p id="p1">hello</p><p id="p2">world</p></div>
|
|
<div><p>goodybe</p></div>
|
|
`,
|
|
async (browser, accDoc) => {
|
|
let searchPred = {
|
|
AXSearchKey: "AXAnyTypeSearchKey",
|
|
AXImmediateDescendantsOnly: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
|
|
const searchRoot = getNativeInterface(accDoc, "searchroot");
|
|
const resultCount = searchRoot.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(resultCount, 2, "Found 2 items");
|
|
|
|
const p1 = getNativeInterface(accDoc, "p1");
|
|
searchPred = {
|
|
AXSearchKey: "AXAnyTypeSearchKey",
|
|
AXImmediateDescendantsOnly: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
AXStartElement: p1,
|
|
};
|
|
|
|
let results = searchRoot.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
Assert.deepEqual(
|
|
results.map(r => r.getAttributeValue("AXDOMIdentifier")),
|
|
["p2"],
|
|
"Result is next group sibling"
|
|
);
|
|
|
|
searchPred = {
|
|
AXSearchKey: "AXAnyTypeSearchKey",
|
|
AXImmediateDescendantsOnly: 1,
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionPrevious",
|
|
};
|
|
|
|
results = searchRoot.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
Assert.deepEqual(
|
|
results.map(r => r.getAttributeValue("AXDOMIdentifier")),
|
|
["p2", "p1"],
|
|
"A reverse search should return groups in reverse"
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Test search text
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<p>It's about the future, isn't it?</p>
|
|
<p>Okay, alright, Saturday is good, Saturday's good, I could spend a week in 1955.</p>
|
|
<ul>
|
|
<li>I could hang out, you could show me around.</li>
|
|
<li>There's that word again, heavy.</li>
|
|
</ul>
|
|
`,
|
|
async (browser, f, accDoc) => {
|
|
let searchPred = {
|
|
AXSearchKey: "AXAnyTypeSearchKey",
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
AXSearchText: "could",
|
|
};
|
|
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
is(
|
|
webArea.getAttributeValue("AXRole"),
|
|
"AXWebArea",
|
|
"Got web area accessible"
|
|
);
|
|
|
|
const textSearchCount = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementCountForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
is(textSearchCount, 2, "Found 2 matching items in text search");
|
|
|
|
const results = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
info(results.map(r => r.getAttributeValue("AXMozDebugDescription")));
|
|
|
|
Assert.deepEqual(
|
|
results.map(r => r.getAttributeValue("AXValue")),
|
|
[
|
|
"Okay, alright, Saturday is good, Saturday's good, I could spend a week in 1955.",
|
|
"I could hang out, you could show me around.",
|
|
],
|
|
"Correct text search results"
|
|
);
|
|
},
|
|
{ topLevel: false, iframe: true, remoteIframe: true }
|
|
);
|
|
|
|
/**
|
|
* Test keyboard focusable search predicate
|
|
*/
|
|
addAccessibleTask(
|
|
`
|
|
<p>Hello, <a href="http://www.example.com/" id="href">Example link</a> <a id="noHref">link without href</a></p>
|
|
<input id="input">
|
|
<button id="button">Click me</button>
|
|
<div id="container" style="height: 10px; overflow: auto;"><div style="height: 100px;"></div></div>
|
|
`,
|
|
async (browser, f, accDoc) => {
|
|
const searchPred = {
|
|
AXSearchKey: "AXKeyboardFocusableSearchKey",
|
|
AXResultsLimit: -1,
|
|
AXDirection: "AXDirectionNext",
|
|
};
|
|
const webArea = accDoc.nativeInterface.QueryInterface(
|
|
Ci.nsIAccessibleMacInterface
|
|
);
|
|
|
|
const results = webArea.getParameterizedAttributeValue(
|
|
"AXUIElementsForSearchPredicate",
|
|
NSDictionary(searchPred)
|
|
);
|
|
|
|
Assert.deepEqual(
|
|
results.map(r => r.getAttributeValue("AXDOMIdentifier")),
|
|
["href", "input", "button"],
|
|
"Correct keyboard focusable search results"
|
|
);
|
|
},
|
|
{ topLevel: false, iframe: true, remoteIframe: true }
|
|
);
|