blob: 0acd90e8481c07de47da2e0d4c5a24a4a33c5ad4 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<script src="../../resources/accessibility-helper.js"></script>
</head>
<body id="body" role="group">
<blockquote>first blockquote level 1</blockquote>
<blockquote>second blockquote level 1</blockquote>
<p style="color:black; font-family:sans-serif; font-weight:bold; text-decoration:underline;">sans-serif black bold text with underline</p>
<p style="color:blue; font-family:serif; font-style:italic;">serif blue italic text</p>
<form>
<input type="text" /><br />
<input type="checkbox" value="Checkbox" /> checkbox<br />
<input type="submit" value="Submit" />
</form>
<img id="image" src="resources/cake.png" alt="Test">
<h1>first heading level 1</h1>
<h1>second heading level 1</h1>
<h2>heading level 2</h2>
<h3>heading level 3</h3>
<h4>heading level 4</h4>
<h5>heading level 5</h5>
<h6>heading level 6</h6>
<p id="banner" role="banner">landmark</p>
<a href="#image">link</a>
<ol><li>list item</li></ol>
<p aria-live="polite">live region</p>
<ul role="radiogroup"><li role="radio">radio button</li></ul>
<table>
<thead><tr><td>first table heading level 1</td></tr></thead>
<tbody><tr><td>first table body level 1</td></tr></tbody>
</table>
<table>
<thead><tr><td>second table heading level 1</td></tr></thead>
<tbody><tr><td>second table body level 1</td></tr></tbody>
</table>
<ul role="tree"><li role="treeitem">tree item</li></ul>
<h1>isVisible test start</h1>
<div id="group" style="overflow: scroll; width:100px; height:100px;">
<button id="button">test button 1</button><BR>
test test test test <br>
test test test test <br>
test test test test <br>
test test test test <br>
test test test test <br>
test test test test <br>
test test test test <br>
test test test test <br>
test test test test <br>
<button id="button">test button 2</button>
</div>
<button id="button">test button 3</button>
<p id="description"></p>
<div id="console"></div>
<script>
description("This tests the ability to search for accessible elements by key or text.");
if (window.accessibilityController) {
window.jsTestIsAsync = true;
window.containerElement = accessibilityController.accessibleElementById("body");
// Any element.
window.startElement = containerElement.childAtIndex(0);
window.resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXAnyTypeSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXStaticText'");
shouldBe("resultElement.stringValue", "'AXValue: first blockquote level 1'");
// Same level blockquote.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXBlockquoteSameLevelSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXGroup'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: second blockquote level 1'");
// Blockquote.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXBlockquoteSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXGroup'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: second blockquote level 1'");
// Bold font.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXBoldFontSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXGroup'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: sans-serif black bold text with underline'");
// Button.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXButtonSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXButton'");
// Check box.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXCheckBoxSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXCheckBox'");
// Control.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXCheckBoxSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXCheckBox'");
// Different type element.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXDifferentTypeSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXStaticText'");
shouldBe("resultElement.stringValue", "'AXValue: first blockquote level 1'");
// Font change.
startElement = containerElement.childAtIndex(2);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXFontChangeSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXGroup'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: serif blue italic text'");
// Font color change.
startElement = containerElement.childAtIndex(2);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXFontColorChangeSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXGroup'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: serif blue italic text'");
// Graphic.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXGraphicSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXImage'");
// Heading level 1.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingLevel1SearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXHeading'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: first heading level 1'");
// Heading level 2.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingLevel2SearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXHeading'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 2'");
// Heading level 3.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingLevel3SearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXHeading'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 3'");
// Heading level 4.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingLevel4SearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXHeading'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 4'");
// Heading level 5.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingLevel5SearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXHeading'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 5'");
// Heading level 6.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingLevel6SearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXHeading'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 6'");
// Same level heading.
startElement = containerElement.childAtIndex(6);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingSameLevelSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXHeading'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: second heading level 1'");
// Heading.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXHeading'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: first heading level 1'");
// Italic font.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXItalicFontSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXGroup'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: serif blue italic text'");
// Landmark.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXLandmarkSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXGroup'");
shouldBe("resultElement.subrole", "'AXSubrole: AXLandmarkBanner'");
// Link.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXLinkSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXLink'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: link'");
// List.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXListSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXList'");
// Live Region.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXLiveRegionSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXGroup'");
shouldBe("resultElement.stringAttributeValue('AXARIALive')", "'polite'");
// Misspelled word.
// FIXME: Handle this search key.
// Outline.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXOutlineSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXOutline'");
shouldBe("resultElement.childAtIndex(0).childAtIndex(0).stringValue", "'AXValue: tree item'");
// Plain text.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXPlainTextSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXStaticText'");
shouldBe("resultElement.stringValue", "'AXValue: first blockquote level 1'");
// Radio group.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXRadioGroupSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXRadioGroup'");
// Same type element.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXSameTypeSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXGroup'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: second blockquote level 1'");
// Static text.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXStaticTextSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXStaticText'");
shouldBe("resultElement.stringValue", "'AXValue: first blockquote level 1'");
// Style change.
startElement = containerElement.childAtIndex(2);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXStyleChangeSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXGroup'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: serif blue italic text'");
// Same level table.
startElement = containerElement.childAtIndex(18);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXTableSameLevelSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXTable'");
shouldBe("resultElement.childAtIndex(0).childAtIndex(0).childAtIndex(0).stringValue", "'AXValue: second table heading level 1'");
// Table.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXTableSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXTable'");
shouldBe("resultElement.childAtIndex(0).childAtIndex(0).childAtIndex(0).stringValue", "'AXValue: first table heading level 1'");
// Text field.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXTextFieldSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXTextField'");
// Underline.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXUnderlineSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXGroup'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: sans-serif black bold text with underline'");
// Unvisited link.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXUnvisitedLinkSearchKey", "", false);
shouldBe("resultElement.boolAttributeValue('AXVisited')", "false");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: link'");
// Previous text search.
startElement = containerElement.childAtIndex(10);
resultElement = containerElement.uiElementForSearchPredicate(startElement, false, "", "sans-serif black bold text with underline", false);
shouldBe("resultElement.role", "'AXRole: AXStaticText'");
shouldBe("resultElement.stringValue", "'AXValue: sans-serif black bold text with underline'");
// Execute a search for the next heading level 2 or the next link.
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, ["AXHeadingLevel2SearchKey", "AXLinkSearchKey"], "", false);
shouldBe("resultElement.role", "'AXRole: AXHeading'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 2'");
// After finding the heading, execute the search again and we should find the link.
resultElement = containerElement.uiElementForSearchPredicate(resultElement, true, ["AXHeadingLevel2SearchKey", "AXLinkSearchKey"], "", false);
shouldBe("resultElement.role", "'AXRole: AXLink'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: link'");
// From the link, execute the search in reverse and we should land back on the heading.
resultElement = containerElement.uiElementForSearchPredicate(resultElement, false, ["AXHeadingLevel2SearchKey", "AXLinkSearchKey"], "", false);
shouldBe("resultElement.role", "'AXRole: AXHeading'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 2'");
// Now, we need to test isVisible. Save off the first object
startElement = containerElement.childAtIndex(0);
// Scroll all the way to the bottom of the content
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "", "test button 3", false);
shouldBe("resultElement.role", "'AXRole: AXButton'");
shouldBe("resultElement.title", "'AXTitle: test button 3'");
setTimeout(async function() {
resultElement.scrollToMakeVisible();
await waitFor(() => {
return resultElement.isOnScreen;
});
// find the start of the isVisible test section
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "", "isVisible test start", false);
shouldBe("resultElement.role", "'AXRole: AXHeading'");
shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: isVisible test start'");
// save away the "isVisible test start" heading as the start element
startElement = resultElement;
// If we don't care about visible only, then we should easily find 3 buttons
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXButtonSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXButton'");
shouldBe("resultElement.title", "'AXTitle: test button 1'");
resultElement = containerElement.uiElementForSearchPredicate(resultElement, true, "AXButtonSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXButton'");
shouldBe("resultElement.title", "'AXTitle: test button 2'");
// save away testButton2 so we can make it visible later
window.testButton2 = resultElement;
resultElement = containerElement.uiElementForSearchPredicate(resultElement, true, "AXButtonSearchKey", "", false);
shouldBe("resultElement.role", "'AXRole: AXButton'");
shouldBe("resultElement.title", "'AXTitle: test button 3'");
// if we care about visible only, then we should not find "test button 2"
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXButtonSearchKey", "", true);
shouldBe("resultElement.role", "'AXRole: AXButton'");
shouldBe("resultElement.title", "'AXTitle: test button 1'");
resultElement = containerElement.uiElementForSearchPredicate(resultElement, true, "AXButtonSearchKey", "", true);
shouldBe("resultElement.role", "'AXRole: AXButton'");
shouldBe("resultElement.title", "'AXTitle: test button 3'");
// now, scroll to the second button, and confirm that we don't see the first button
testButton2.scrollToMakeVisible();
await waitFor(() => {
return testButton2.isOnScreen;
});
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXButtonSearchKey", "", true);
shouldBe("resultElement.role", "'AXRole: AXButton'");
shouldBe("resultElement.title", "'AXTitle: test button 2'");
resultElement = containerElement.uiElementForSearchPredicate(resultElement, true, "AXButtonSearchKey", "", true);
shouldBe("resultElement.role", "'AXRole: AXButton'");
shouldBe("resultElement.title", "'AXTitle: test button 3'");
// Now since the page is scrolled to the bottom, the first visible button should be #2
startElement = containerElement.childAtIndex(0);
resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXButtonSearchKey", "", true);
shouldBe("resultElement.role", "'AXRole: AXButton'");
shouldBe("resultElement.title", "'AXTitle: test button 2'");
finishJSTest();
}, 0);
}
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>