Bug 1661760 - Part 2: Refactor mac basic text test. r=morgan

There are going to be a whole bunch of things we want to check for each
text marker in a document. I think loops should be avoided as much as possible,
but this lets us store a single array with everything we expect for each marker.

This is going to expand in the future.

Differential Revision: https://phabricator.services.mozilla.com/D90937
This commit is contained in:
Eitan Isaacson 2020-09-24 16:04:48 +00:00
parent 10d6dd02bc
commit f770fa368b
5 changed files with 754 additions and 255 deletions

View File

@ -3,6 +3,7 @@ skip-if = os != 'mac'
support-files = support-files =
head.js head.js
doc_aria_tabs.html doc_aria_tabs.html
doc_textmarker_test.html
!/accessible/tests/browser/shared-head.js !/accessible/tests/browser/shared-head.js
!/accessible/tests/browser/*.jsm !/accessible/tests/browser/*.jsm
!/accessible/tests/mochitest/*.js !/accessible/tests/mochitest/*.js
@ -34,3 +35,4 @@ skip-if = os == 'mac' && !debug #1648813
skip-if = os == 'mac' && debug # Bug 1664577 skip-if = os == 'mac' && debug # Bug 1664577
[browser_rotor.js] [browser_rotor.js]
[browser_rootgroup.js] [browser_rootgroup.js]
[browser_text_selection.js]

View File

@ -4,285 +4,58 @@
"use strict"; "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 }
);
function stringForRange(macDoc, range) { function testRangeAtMarker(macDoc, marker, attribute, expected, msg) {
return macDoc.getParameterizedAttributeValue( let range = macDoc.getParameterizedAttributeValue(attribute, marker);
"AXStringForTextMarkerRange", is(stringForRange(macDoc, range), expected, msg);
range
);
} }
function testUIElementAtMarker(macDoc, marker, expectedString) { function testUIElement(macDoc, marker, msg, expectedRole, expectedValue) {
let elem = macDoc.getParameterizedAttributeValue( let elem = macDoc.getParameterizedAttributeValue(
"AXUIElementForTextMarker", "AXUIElementForTextMarker",
marker marker
); );
is(elem.getAttributeValue("AXRole"), "AXStaticText"); is(
is(elem.getAttributeValue("AXValue"), expectedString); elem.getAttributeValue("AXRole"),
expectedRole,
`${msg}: element role matches`
);
is(elem.getAttributeValue("AXValue"), expectedValue, `${msg}: element value`);
let elemRange = macDoc.getParameterizedAttributeValue( let elemRange = macDoc.getParameterizedAttributeValue(
"AXTextMarkerRangeForUIElement", "AXTextMarkerRangeForUIElement",
elem elem
); );
is(stringForRange(macDoc, elemRange), expectedString); is(
stringForRange(macDoc, elemRange),
expectedValue,
`${msg}: element range matches element value`
);
} }
function testWordAtMarker( function testWords(macDoc, marker, msg, expectedLeft, expectedRight) {
macDoc, testRangeAtMarker(
marker, macDoc,
expectedLeft, marker,
expectedRight,
options = {}
) {
let left = macDoc.getParameterizedAttributeValue(
"AXLeftWordTextMarkerRangeForTextMarker", "AXLeftWordTextMarkerRangeForTextMarker",
marker
);
let right = macDoc.getParameterizedAttributeValue(
"AXRightWordTextMarkerRangeForTextMarker",
marker
);
(options.leftIs || is)(
stringForRange(macDoc, left),
expectedLeft, expectedLeft,
"Left word matches" `${msg}: left word matches`
); );
(options.rightIs || is)(
stringForRange(macDoc, right), testRangeAtMarker(
macDoc,
marker,
"AXRightWordTextMarkerRangeForTextMarker",
expectedRight, expectedRight,
"Right word matches" `${msg}: right word matches`
); );
} }
// Read-only tests
addAccessibleTask(`<p id="p">Hello World</p>`, async (browser, accDoc) => {
let macDoc = accDoc.nativeInterface.QueryInterface(
Ci.nsIAccessibleMacInterface
);
let startMarker = macDoc.getAttributeValue("AXStartTextMarker");
let endMarker = macDoc.getAttributeValue("AXEndTextMarker");
let range = macDoc.getParameterizedAttributeValue(
"AXTextMarkerRangeForUnorderedTextMarkers",
[startMarker, endMarker]
);
is(stringForRange(macDoc, range), "Hello World");
let evt = waitForMacEvent("AXSelectedTextChanged");
await SpecialPowers.spawn(browser, [], () => {
let p = content.document.getElementById("p");
let r = new content.Range();
r.setStart(p.firstChild, 1);
r.setEnd(p.firstChild, 8);
let s = content.getSelection();
s.addRange(r);
});
await evt;
range = macDoc.getAttributeValue("AXSelectedTextMarkerRange");
is(stringForRange(macDoc, range), "ello Wo");
let firstWordRange = macDoc.getParameterizedAttributeValue(
"AXRightWordTextMarkerRangeForTextMarker",
startMarker
);
is(stringForRange(macDoc, firstWordRange), "Hello");
evt = waitForMacEvent("AXSelectedTextChanged");
macDoc.setAttributeValue("AXSelectedTextMarkerRange", firstWordRange);
await evt;
range = macDoc.getAttributeValue("AXSelectedTextMarkerRange");
is(stringForRange(macDoc, range), "Hello");
});
addAccessibleTask(`<p>hello world goodbye</p>`, (browser, accDoc) => {
let macDoc = accDoc.nativeInterface.QueryInterface(
Ci.nsIAccessibleMacInterface
);
let marker = macDoc.getAttributeValue("AXStartTextMarker");
function testWordAndAdvance(left, right) {
testWordAtMarker(macDoc, marker, left, right);
marker = macDoc.getParameterizedAttributeValue(
"AXNextTextMarkerForTextMarker",
marker
);
}
testWordAndAdvance("hello", "hello");
testWordAndAdvance("hello", "hello");
testWordAndAdvance("hello", "hello");
testWordAndAdvance("hello", "hello");
testWordAndAdvance("hello", "hello");
testWordAndAdvance("hello", " ");
testWordAndAdvance(" ", "world");
testWordAndAdvance("world", "world");
testWordAndAdvance("world", "world");
testWordAndAdvance("world", "world");
testWordAndAdvance("world", "world");
testWordAndAdvance("world", " ");
testWordAndAdvance(" ", "goodbye");
testWordAndAdvance("goodbye", "goodbye");
testWordAndAdvance("goodbye", "goodbye");
testWordAndAdvance("goodbye", "goodbye");
testWordAndAdvance("goodbye", "goodbye");
testWordAndAdvance("goodbye", "goodbye");
testWordAndAdvance("goodbye", "goodbye");
testWordAndAdvance("goodbye", "");
ok(!marker, "Iterated through all markers");
testMarkerIntegrity(accDoc);
});
addAccessibleTask(
`<p>hello world <a href="#">i love you</a> goodbye</p>`,
(browser, accDoc) => {
let macDoc = accDoc.nativeInterface.QueryInterface(
Ci.nsIAccessibleMacInterface
);
let marker = macDoc.getAttributeValue("AXStartTextMarker");
function testWordAndAdvance(left, right, elemText) {
testWordAtMarker(macDoc, marker, left, right);
testUIElementAtMarker(macDoc, marker, elemText);
marker = macDoc.getParameterizedAttributeValue(
"AXNextTextMarkerForTextMarker",
marker
);
}
testWordAndAdvance("hello", "hello", "hello world ");
testWordAndAdvance("hello", "hello", "hello world ");
testWordAndAdvance("hello", "hello", "hello world ");
testWordAndAdvance("hello", "hello", "hello world ");
testWordAndAdvance("hello", "hello", "hello world ");
testWordAndAdvance("hello", " ", "hello world ");
testWordAndAdvance(" ", "world", "hello world ");
testWordAndAdvance("world", "world", "hello world ");
testWordAndAdvance("world", "world", "hello world ");
testWordAndAdvance("world", "world", "hello world ");
testWordAndAdvance("world", "world", "hello world ");
testWordAndAdvance("world", " ", "hello world ");
testWordAndAdvance(" ", "i", "i love you");
testWordAndAdvance("i", " ", "i love you");
testWordAndAdvance(" ", "love", "i love you");
testWordAndAdvance("love", "love", "i love you");
testWordAndAdvance("love", "love", "i love you");
testWordAndAdvance("love", "love", "i love you");
testWordAndAdvance("love", " ", "i love you");
testWordAndAdvance(" ", "you", "i love you");
testWordAndAdvance("you", "you", "i love you");
testWordAndAdvance("you", "you", "i love you");
testWordAndAdvance("you", " ", "i love you");
testWordAndAdvance(" ", "goodbye", " goodbye");
testWordAndAdvance("goodbye", "goodbye", " goodbye");
testWordAndAdvance("goodbye", "goodbye", " goodbye");
testWordAndAdvance("goodbye", "goodbye", " goodbye");
testWordAndAdvance("goodbye", "goodbye", " goodbye");
testWordAndAdvance("goodbye", "goodbye", " goodbye");
testWordAndAdvance("goodbye", "goodbye", " goodbye");
testWordAndAdvance("goodbye", "", " goodbye");
ok(!marker, "Iterated through all markers");
testMarkerIntegrity(accDoc);
}
);
addAccessibleTask(
`<p>hello <a href=#">wor</a>ld goodbye</p>`,
(browser, accDoc) => {
let macDoc = accDoc.nativeInterface.QueryInterface(
Ci.nsIAccessibleMacInterface
);
let marker = macDoc.getAttributeValue("AXStartTextMarker");
function getMarkerAtIndex(index) {
return macDoc.getParameterizedAttributeValue(
"AXTextMarkerForIndex",
index
);
}
testUIElementAtMarker(macDoc, marker, "hello ");
marker = getMarkerAtIndex(7);
testUIElementAtMarker(macDoc, marker, "wor");
let left = macDoc.getParameterizedAttributeValue(
"AXLeftWordTextMarkerRangeForTextMarker",
marker
);
let right = macDoc.getParameterizedAttributeValue(
"AXRightWordTextMarkerRangeForTextMarker",
marker
);
is(stringForRange(macDoc, left), "world", "Left word matches");
is(stringForRange(macDoc, right), "world", "Right word matches");
marker = macDoc.getParameterizedAttributeValue(
"AXNextTextMarkerForTextMarker",
marker
);
left = macDoc.getParameterizedAttributeValue(
"AXLeftWordTextMarkerRangeForTextMarker",
marker
);
right = macDoc.getParameterizedAttributeValue(
"AXRightWordTextMarkerRangeForTextMarker",
marker
);
is(stringForRange(macDoc, left), "world", "Left word matches");
is(stringForRange(macDoc, right), "world", "Right word matches");
marker = getMarkerAtIndex(14);
testUIElementAtMarker(macDoc, marker, "ld goodbye");
testMarkerIntegrity(accDoc);
}
);
addAccessibleTask(
`<ul><li>hello</li><li>world</li></ul>
<ul style="list-style: none;"><li>goodbye</li><li>universe</li></ul>`,
(browser, accDoc) => {
testMarkerIntegrity(accDoc);
}
);
addAccessibleTask(
`<div id="a">hello</div><div id="b">world</div>`,
(browser, accDoc) => {
testMarkerIntegrity(accDoc);
}
);
addAccessibleTask(
`<p style="width: 1rem">Lorem ipsum</p>`,
(browser, accDoc) => {
testMarkerIntegrity(accDoc);
}
);
addAccessibleTask(`<p>hello <input> world</p>`, (browser, accDoc) => {
testMarkerIntegrity(accDoc);
});
// Tests consistency in text markers between: // Tests consistency in text markers between:
// 1. "Linked list" forward navagation // 1. "Linked list" forward navagation
// 2. Getting markers by index // 2. Getting markers by index
// 3. "Linked list" reverse navagation // 3. "Linked list" reverse navagation
// For each iteration method check that the returned index is consistent // For each iteration method check that the returned index is consistent
function testMarkerIntegrity(accDoc) { function testMarkerIntegrity(accDoc, expectedMarkerValues) {
let macDoc = accDoc.nativeInterface.QueryInterface( let macDoc = accDoc.nativeInterface.QueryInterface(
Ci.nsIAccessibleMacInterface Ci.nsIAccessibleMacInterface
); );
@ -302,6 +75,19 @@ function testMarkerIntegrity(accDoc) {
`Correct index in "AXNextTextMarkerForTextMarker": ${count}` `Correct index in "AXNextTextMarkerForTextMarker": ${count}`
); );
testWords(
macDoc,
marker,
`At index ${count}`,
...expectedMarkerValues[count].words
);
testUIElement(
macDoc,
marker,
`At index ${count}`,
...expectedMarkerValues[count].element
);
marker = macDoc.getParameterizedAttributeValue( marker = macDoc.getParameterizedAttributeValue(
"AXNextTextMarkerForTextMarker", "AXNextTextMarkerForTextMarker",
marker marker
@ -319,6 +105,13 @@ function testMarkerIntegrity(accDoc) {
is(index, i, `Correct index in "AXTextMarkerForIndex": ${i}`); is(index, i, `Correct index in "AXTextMarkerForIndex": ${i}`);
} }
ok(!macDoc.getParameterizedAttributeValue(
"AXNextTextMarkerForTextMarker",
marker
),
"Iterated through all markers"
);
// Iterate backward with "AXPreviousTextMarkerForTextMarker" // Iterate backward with "AXPreviousTextMarkerForTextMarker"
marker = macDoc.getAttributeValue("AXEndTextMarker"); marker = macDoc.getAttributeValue("AXEndTextMarker");
while (marker) { while (marker) {
@ -340,3 +133,15 @@ function testMarkerIntegrity(accDoc) {
is(count, 0, "Iterated backward through all text markers"); is(count, 0, "Iterated backward through all text markers");
} }
addAccessibleTask("mac/doc_textmarker_test.html", async (browser, accDoc) => {
const expectedMarkerValues = await SpecialPowers.spawn(
browser,
[],
async () => {
return content.wrappedJSObject.EXPECTED;
}
);
testMarkerIntegrity(accDoc, expectedMarkerValues);
});

View File

@ -0,0 +1,49 @@
/* 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";
/**
* Test rotor with heading
*/
addAccessibleTask(`<p id="p">Hello World</p>`, async (browser, accDoc) => {
let macDoc = accDoc.nativeInterface.QueryInterface(
Ci.nsIAccessibleMacInterface
);
let startMarker = macDoc.getAttributeValue("AXStartTextMarker");
let endMarker = macDoc.getAttributeValue("AXEndTextMarker");
let range = macDoc.getParameterizedAttributeValue(
"AXTextMarkerRangeForUnorderedTextMarkers",
[startMarker, endMarker]
);
is(stringForRange(macDoc, range), "Hello World");
let evt = waitForMacEvent("AXSelectedTextChanged");
await SpecialPowers.spawn(browser, [], () => {
let p = content.document.getElementById("p");
let r = new content.Range();
r.setStart(p.firstChild, 1);
r.setEnd(p.firstChild, 8);
let s = content.getSelection();
s.addRange(r);
});
await evt;
range = macDoc.getAttributeValue("AXSelectedTextMarkerRange");
is(stringForRange(macDoc, range), "ello Wo");
let firstWordRange = macDoc.getParameterizedAttributeValue(
"AXRightWordTextMarkerRangeForTextMarker",
startMarker
);
is(stringForRange(macDoc, firstWordRange), "Hello");
evt = waitForMacEvent("AXSelectedTextChanged");
macDoc.setAttributeValue("AXSelectedTextMarkerRange", firstWordRange);
await evt;
range = macDoc.getAttributeValue("AXSelectedTextMarkerRange");
is(stringForRange(macDoc, range), "Hello");
});

View File

@ -0,0 +1,631 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
</head>
<body id="body">
<p>Bob Loblaw Lobs Law Bomb</p>
<p>I love all of my <a href="#">children</a> equally</p>
<p>This is the best free scr<a href="#">apbook</a>ing class I have ever taken</p>
<ul>
<li>Fried cheese with club sauce</li>
<li>Popcorn shrimp with club sauce</li>
<li>Chicken fingers with spicy club sauce</li>
</ul>
<ul style="list-style: none;"><li>Do not order the Skip's Scramble</li></ul>
<p style="width: 1rem">These are my awards, Mother. From Army.</p>
<p>I deceived you, <input> mom.</p>
<script>
"use strict";
window.EXPECTED = [
{ words: ["Bob", "Bob"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Bob", "Bob"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Bob", "Bob"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Bob", " "],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: [" ", "Loblaw"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Loblaw", "Loblaw"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Loblaw", "Loblaw"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Loblaw", "Loblaw"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Loblaw", "Loblaw"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Loblaw", "Loblaw"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Loblaw", " "],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: [" ", "Lobs"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Lobs", "Lobs"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Lobs", "Lobs"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Lobs", "Lobs"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Lobs", " "],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: [" ", "Law"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Law", "Law"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Law", "Law"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Law", " "],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: [" ", "Bomb"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Bomb", "Bomb"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Bomb", "Bomb"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Bomb", "Bomb"],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["Bomb", ""],
element: ["AXStaticText", "Bob Loblaw Lobs Law Bomb"] },
{ words: ["I", " "],
element: ["AXStaticText", "I love all of my "] },
{ words: [" ", "love"],
element: ["AXStaticText", "I love all of my "] },
{ words: ["love", "love"],
element: ["AXStaticText", "I love all of my "] },
{ words: ["love", "love"],
element: ["AXStaticText", "I love all of my "] },
{ words: ["love", "love"],
element: ["AXStaticText", "I love all of my "] },
{ words: ["love", " "],
element: ["AXStaticText", "I love all of my "] },
{ words: [" ", "all"],
element: ["AXStaticText", "I love all of my "] },
{ words: ["all", "all"],
element: ["AXStaticText", "I love all of my "] },
{ words: ["all", "all"],
element: ["AXStaticText", "I love all of my "] },
{ words: ["all", " "],
element: ["AXStaticText", "I love all of my "] },
{ words: [" ", "of"],
element: ["AXStaticText", "I love all of my "] },
{ words: ["of", "of"],
element: ["AXStaticText", "I love all of my "] },
{ words: ["of", " "],
element: ["AXStaticText", "I love all of my "] },
{ words: [" ", "my"],
element: ["AXStaticText", "I love all of my "] },
{ words: ["my", "my"],
element: ["AXStaticText", "I love all of my "] },
{ words: ["my", " "],
element: ["AXStaticText", "I love all of my "] },
{ words: [" ", "children"],
element: ["AXStaticText", "children"] },
{ words: ["children", "children"],
element: ["AXStaticText", "children"] },
{ words: ["children", "children"],
element: ["AXStaticText", "children"] },
{ words: ["children", "children"],
element: ["AXStaticText", "children"] },
{ words: ["children", "children"],
element: ["AXStaticText", "children"] },
{ words: ["children", "children"],
element: ["AXStaticText", "children"] },
{ words: ["children", "children"],
element: ["AXStaticText", "children"] },
{ words: ["children", "children"],
element: ["AXStaticText", "children"] },
{ words: ["children", " "],
element: ["AXStaticText", "children"] },
{ words: [" ", "equally"],
element: ["AXStaticText", " equally"] },
{ words: ["equally", "equally"],
element: ["AXStaticText", " equally"] },
{ words: ["equally", "equally"],
element: ["AXStaticText", " equally"] },
{ words: ["equally", "equally"],
element: ["AXStaticText", " equally"] },
{ words: ["equally", "equally"],
element: ["AXStaticText", " equally"] },
{ words: ["equally", "equally"],
element: ["AXStaticText", " equally"] },
{ words: ["equally", "equally"],
element: ["AXStaticText", " equally"] },
{ words: ["equally", ""],
element: ["AXStaticText", " equally"] },
{ words: ["This", "This"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["This", "This"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["This", "This"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["This", " "],
element: ["AXStaticText", "This is the best free scr"] },
{ words: [" ", "is"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["is", "is"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["is", " "],
element: ["AXStaticText", "This is the best free scr"] },
{ words: [" ", "the"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["the", "the"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["the", "the"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["the", " "],
element: ["AXStaticText", "This is the best free scr"] },
{ words: [" ", "best"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["best", "best"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["best", "best"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["best", "best"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["best", " "],
element: ["AXStaticText", "This is the best free scr"] },
{ words: [" ", "free"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["free", "free"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["free", "free"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["free", "free"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["free", " "],
element: ["AXStaticText", "This is the best free scr"] },
{ words: [" ", "scrapbooking"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["scrapbooking", "scrapbooking"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["scrapbooking", "scrapbooking"],
element: ["AXStaticText", "This is the best free scr"] },
{ words: ["scrapbooking", "scrapbooking"],
element: ["AXStaticText", "apbook"] },
{ words: ["scrapbooking", "scrapbooking"],
element: ["AXStaticText", "apbook"] },
{ words: ["scrapbooking", "scrapbooking"],
element: ["AXStaticText", "apbook"] },
{ words: ["scrapbooking", "scrapbooking"],
element: ["AXStaticText", "apbook"] },
{ words: ["scrapbooking", "scrapbooking"],
element: ["AXStaticText", "apbook"] },
{ words: ["scrapbooking", "scrapbooking"],
element: ["AXStaticText", "apbook"] },
{ words: ["scrapbooking", "scrapbooking"],
element: ["AXStaticText", "apbook"] },
{ words: ["scrapbooking", "scrapbooking"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["scrapbooking", "scrapbooking"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["scrapbooking", " "],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: [" ", "class"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["class", "class"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["class", "class"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["class", "class"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["class", "class"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["class", " "],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: [" ", "I"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["I", " "],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: [" ", "have"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["have", "have"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["have", "have"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["have", "have"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["have", " "],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: [" ", "ever"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["ever", "ever"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["ever", "ever"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["ever", "ever"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["ever", " "],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: [" ", "taken"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["taken", "taken"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["taken", "taken"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["taken", "taken"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["taken", "taken"],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["taken", "\u2022 "],
element: ["AXStaticText", "ing class I have ever taken"] },
{ words: ["Fried", "Fried"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["Fried", "Fried"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["Fried", "Fried"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["Fried", "Fried"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["Fried", " "],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: [" ", "cheese"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["cheese", "cheese"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["cheese", "cheese"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["cheese", "cheese"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["cheese", "cheese"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["cheese", "cheese"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["cheese", " "],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: [" ", "with"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["with", "with"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["with", "with"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["with", "with"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["with", " "],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: [" ", "club"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["club", "club"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["club", "club"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["club", "club"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["club", " "],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: [" ", "sauce"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["sauce", "sauce"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["sauce", "sauce"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["sauce", "sauce"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["sauce", "sauce"],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["sauce", "\u2022 "],
element: ["AXStaticText", "Fried cheese with club sauce"] },
{ words: ["Popcorn", "Popcorn"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["Popcorn", "Popcorn"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["Popcorn", "Popcorn"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["Popcorn", "Popcorn"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["Popcorn", "Popcorn"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["Popcorn", "Popcorn"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["Popcorn", " "],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: [" ", "shrimp"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["shrimp", "shrimp"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["shrimp", "shrimp"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["shrimp", "shrimp"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["shrimp", "shrimp"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["shrimp", "shrimp"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["shrimp", " "],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: [" ", "with"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["with", "with"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["with", "with"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["with", "with"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["with", " "],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: [" ", "club"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["club", "club"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["club", "club"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["club", "club"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["club", " "],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: [" ", "sauce"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["sauce", "sauce"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["sauce", "sauce"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["sauce", "sauce"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["sauce", "sauce"],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["sauce", "\u2022 "],
element: ["AXStaticText", "Popcorn shrimp with club sauce"] },
{ words: ["Chicken", "Chicken"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["Chicken", "Chicken"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["Chicken", "Chicken"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["Chicken", "Chicken"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["Chicken", "Chicken"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["Chicken", "Chicken"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["Chicken", " "],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: [" ", "fingers"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["fingers", "fingers"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["fingers", "fingers"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["fingers", "fingers"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["fingers", "fingers"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["fingers", "fingers"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["fingers", "fingers"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["fingers", " "],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: [" ", "with"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["with", "with"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["with", "with"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["with", "with"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["with", " "],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: [" ", "spicy"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["spicy", "spicy"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["spicy", "spicy"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["spicy", "spicy"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["spicy", "spicy"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["spicy", " "],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: [" ", "club"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["club", "club"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["club", "club"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["club", "club"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["club", " "],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: [" ", "sauce"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["sauce", "sauce"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["sauce", "sauce"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["sauce", "sauce"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["sauce", "sauce"],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["sauce", ""],
element: ["AXStaticText", "Chicken fingers with spicy club sauce"] },
{ words: ["Do", "Do"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Do", " "],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: [" ", "not"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["not", "not"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["not", "not"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["not", " "],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: [" ", "order"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["order", "order"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["order", "order"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["order", "order"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["order", "order"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["order", " "],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: [" ", "the"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["the", "the"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["the", "the"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["the", " "],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: [" ", "Skip'"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Skip'", "Skip'"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Skip'", "Skip'"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Skip'", "Skip'"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Skip'", "'"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Skip'", "s"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["s", " "],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: [" ", "Scramble"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Scramble", "Scramble"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Scramble", "Scramble"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Scramble", "Scramble"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Scramble", "Scramble"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Scramble", "Scramble"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Scramble", "Scramble"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Scramble", "Scramble"],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["Scramble", ""],
element: ["AXStaticText", "Do not order the Skip's Scramble"] },
{ words: ["These", "These"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["These", "These"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["These", "These"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["These", "These"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["These", " "],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: [" ", "are"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["are", "are"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["are", "are"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["are", " "],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: [" ", "my"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["my", "my"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["my", " "],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: [" ", "awards,"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["awards,", "awards,"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["awards,", "awards,"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["awards,", "awards,"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["awards,", "awards,"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["awards,", "awards,"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["awards,", "awards, "],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["awards,", " "],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: [" ", "Mother."],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["Mother.", "Mother."],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["Mother.", "Mother."],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["Mother.", "Mother."],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["Mother.", "Mother."],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["Mother.", "Mother."],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["Mother.", "Mother. "],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["Mother.", " "],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: [" ", "From"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["From", "From"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["From", "From"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["From", "From"],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["From", " "],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: [" ", "Army."],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["Army.", "Army."],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["Army.", "Army."],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["Army.", "Army."],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["Army.", "Army."],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["Army.", ""],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ words: ["I", " "],
element: ["AXStaticText", "I deceived you, "] },
{ words: [" ", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ words: ["deceived", " "],
element: ["AXStaticText", "I deceived you, "] },
{ words: [" ", "you,"],
element: ["AXStaticText", "I deceived you, "] },
{ words: ["you,", "you,"],
element: ["AXStaticText", "I deceived you, "] },
{ words: ["you,", "you,"],
element: ["AXStaticText", "I deceived you, "] },
{ words: ["you,", "you, mom."],
element: ["AXStaticText", "I deceived you, "] },
{ words: ["you,", " "],
element: ["AXStaticText", "I deceived you, "] },
{ words: [" ", " "],
element: ["AXTextField", ""] },
{ words: [" ", "mom."],
element: ["AXStaticText", " mom."] },
{ words: ["mom.", "mom."],
element: ["AXStaticText", " mom."] },
{ words: ["mom.", "mom."],
element: ["AXStaticText", " mom."] },
{ words: ["mom.", "mom."],
element: ["AXStaticText", " mom."] },
{ words: ["mom.", ""],
element: ["AXStaticText", " mom."] }];
</script>
</body>
</html>

View File

@ -4,7 +4,8 @@
"use strict"; "use strict";
/* exported getNativeInterface, waitForMacEventWithInfo, waitForMacEvent, NSRange, NSDictionary */ /* exported getNativeInterface, waitForMacEventWithInfo, waitForMacEvent,
NSRange, NSDictionary, stringForRange */
// Load the shared-head file first. // Load the shared-head file first.
/* import-globals-from ../shared-head.js */ /* import-globals-from ../shared-head.js */
@ -63,3 +64,14 @@ function NSDictionary(dict) {
object: dict, object: dict,
}; };
} }
function stringForRange(macDoc, range) {
if (!range) {
return "";
}
return macDoc.getParameterizedAttributeValue(
"AXStringForTextMarkerRange",
range
);
}