Add "VisibleOnly" key to search predicate
[WebKit-https.git] / LayoutTests / platform / mac / accessibility / search-predicate.html
1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
2 <html>
3 <head>
4 <script src="../../../fast/js/resources/js-test-pre.js"></script>
5 </head>
6 <body id="body">
7
8 <blockquote>first blockquote level 1</blockquote>
9 <blockquote>second blockquote level 1</blockquote>
10 <p style="color:black; font-family:sans-serif; font-weight:bold; text-decoration:underline;">sans-serif black bold text with underline</p>
11 <p style="color:blue; font-family:serif; font-style:italic;">serif blue italic text</p>
12 <form>
13 <input type="text" /><br />
14 <input type="checkbox" value="Checkbox" /> checkbox<br />
15 <input type="submit" value="Submit" />
16 </form>
17 <img id="image" src="resources/cake.png" alt="Test">
18 <h1>first heading level 1</h1>
19 <h1>second heading level 1</h1>
20 <h2>heading level 2</h2>
21 <h3>heading level 3</h3>
22 <h4>heading level 4</h4>
23 <h5>heading level 5</h5>
24 <h6>heading level 6</h6>
25 <p id="banner" role="banner">landmark</p>
26 <a href="#image">link</a>
27 <ol><li>list item</li></ol>
28 <p aria-live="polite">live region</p>
29 <ul role="radiogroup"><li role="radio">radio button</li></ul>
30 <table>
31 <thead><tr><td>first table heading level 1</td></tr></thead>
32 <tbody><tr><td>first table body level 1</td></tr></tbody>
33 </table>
34 <table>
35 <thead><tr><td>second table heading level 1</td></tr></thead>
36 <tbody><tr><td>second table body level 1</td></tr></tbody>
37 </table>
38
39 <h1>isVisible test start</h1>
40 <div id="group" style="overflow: scroll; width:100px; height:100px;">
41     <button id="button">test button 1</button><BR>
42     test test test test <br>
43     test test test test <br>
44     test test test test <br>
45     test test test test <br>
46     test test test test <br>
47     test test test test <br>
48     test test test test <br>
49     test test test test <br>
50     test test test test <br>
51     <button id="button">test button 2</button>
52 </div>
53 <button id="button">test button 3</button>
54
55     
56 <p id="description"></p>
57 <div id="console"></div>
58
59 <script>
60     description("This tests the ability to search for accessible elements by key or text.");
61     
62     if (window.accessibilityController) {
63         window.testRunner.keepWebHistory();
64         
65         document.getElementById("body").focus();
66         var containerElement = accessibilityController.focusedElement;
67         var startElement;
68         var resultElement;
69         var testButton2;
70
71         // Any element.
72         startElement = accessibilityController.focusedElement.childAtIndex(0);
73         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXAnyTypeSearchKey", "", false);
74         shouldBe("resultElement.role", "'AXRole: AXStaticText'");
75         shouldBe("resultElement.stringValue", "'AXValue: first blockquote level 1'");
76         
77         // Same level blockquote.
78         startElement = accessibilityController.focusedElement.childAtIndex(0);
79         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXBlockquoteSameLevelSearchKey", "", false);
80         shouldBe("resultElement.role", "'AXRole: AXGroup'");
81         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: second blockquote level 1'");
82         
83         // Blockquote.
84         startElement = accessibilityController.focusedElement.childAtIndex(0);
85         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXBlockquoteSearchKey", "", false);
86         shouldBe("resultElement.role", "'AXRole: AXGroup'");
87         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: second blockquote level 1'");
88         
89         // Bold font.
90         startElement = accessibilityController.focusedElement.childAtIndex(0);
91         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXBoldFontSearchKey", "", false);
92         shouldBe("resultElement.role", "'AXRole: AXGroup'");
93         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: sans-serif black bold text with underline'");
94         
95         // Button.
96         startElement = accessibilityController.focusedElement.childAtIndex(0);
97         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXButtonSearchKey", "", false);
98         shouldBe("resultElement.role", "'AXRole: AXButton'");
99         
100         // Check box.
101         startElement = accessibilityController.focusedElement.childAtIndex(0);
102         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXCheckBoxSearchKey", "", false);
103         shouldBe("resultElement.role", "'AXRole: AXCheckBox'");
104         
105         // Control.
106         startElement = accessibilityController.focusedElement.childAtIndex(0);
107         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXCheckBoxSearchKey", "", false);
108         shouldBe("resultElement.role", "'AXRole: AXCheckBox'");
109         
110         // Different type element.
111         startElement = accessibilityController.focusedElement.childAtIndex(0);
112         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXDifferentTypeSearchKey", "", false);
113         shouldBe("resultElement.role", "'AXRole: AXStaticText'");
114         shouldBe("resultElement.stringValue", "'AXValue: first blockquote level 1'");
115         
116         // Font change.
117         startElement = accessibilityController.focusedElement.childAtIndex(2);
118         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXFontChangeSearchKey", "", false);
119         shouldBe("resultElement.role", "'AXRole: AXGroup'");
120         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: serif blue italic text'");
121         
122         // Font color change.
123         startElement = accessibilityController.focusedElement.childAtIndex(2);
124         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXFontColorChangeSearchKey", "", false);
125         shouldBe("resultElement.role", "'AXRole: AXGroup'");
126         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: serif blue italic text'");
127         
128         // Graphic.
129         startElement = accessibilityController.focusedElement.childAtIndex(0);
130         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXGraphicSearchKey", "", false);
131         shouldBe("resultElement.role", "'AXRole: AXImage'");
132         
133         // Heading level 1.
134         startElement = accessibilityController.focusedElement.childAtIndex(0);
135         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingLevel1SearchKey", "", false);
136         shouldBe("resultElement.role", "'AXRole: AXHeading'");
137         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: first heading level 1'");
138         
139         // Heading level 2.
140         startElement = accessibilityController.focusedElement.childAtIndex(0);
141         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingLevel2SearchKey", "", false);
142         shouldBe("resultElement.role", "'AXRole: AXHeading'");
143         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 2'");
144         
145         // Heading level 3.
146         startElement = accessibilityController.focusedElement.childAtIndex(0);
147         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingLevel3SearchKey", "", false);
148         shouldBe("resultElement.role", "'AXRole: AXHeading'");
149         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 3'");
150         
151         // Heading level 4.
152         startElement = accessibilityController.focusedElement.childAtIndex(0);
153         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingLevel4SearchKey", "", false);
154         shouldBe("resultElement.role", "'AXRole: AXHeading'");
155         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 4'");
156         
157         // Heading level 5.
158         startElement = accessibilityController.focusedElement.childAtIndex(0);
159         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingLevel5SearchKey", "", false);
160         shouldBe("resultElement.role", "'AXRole: AXHeading'");
161         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 5'");
162         
163         // Heading level 6.
164         startElement = accessibilityController.focusedElement.childAtIndex(0);
165         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingLevel6SearchKey", "", false);
166         shouldBe("resultElement.role", "'AXRole: AXHeading'");
167         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 6'");
168         
169         // Same level heading.
170         startElement = accessibilityController.focusedElement.childAtIndex(6);
171         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingSameLevelSearchKey", "", false);
172         shouldBe("resultElement.role", "'AXRole: AXHeading'");
173         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: second heading level 1'");
174         
175         // Heading.
176         startElement = accessibilityController.focusedElement.childAtIndex(0);
177         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXHeadingSearchKey", "", false);
178         shouldBe("resultElement.role", "'AXRole: AXHeading'");
179         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: first heading level 1'");
180         
181         // Italic font.
182         startElement = accessibilityController.focusedElement.childAtIndex(0);
183         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXItalicFontSearchKey", "", false);
184         shouldBe("resultElement.role", "'AXRole: AXGroup'");
185         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: serif blue italic text'");
186         
187         // Landmark.
188         startElement = accessibilityController.focusedElement.childAtIndex(0);
189         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXLandmarkSearchKey", "", false);
190         shouldBe("resultElement.role", "'AXRole: AXGroup'");
191         shouldBe("resultElement.subrole", "'AXSubrole: AXLandmarkBanner'");
192         
193         // Link.
194         startElement = accessibilityController.focusedElement.childAtIndex(0);
195         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXLinkSearchKey", "", false);
196         shouldBe("resultElement.role", "'AXRole: AXLink'");
197         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: link'");
198         
199         // List.
200         startElement = accessibilityController.focusedElement.childAtIndex(0);
201         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXListSearchKey", "", false);
202         shouldBe("resultElement.role", "'AXRole: AXList'");
203         
204         // Live Region.
205         startElement = accessibilityController.focusedElement.childAtIndex(0);
206         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXLiveRegionSearchKey", "", false);
207         shouldBe("resultElement.role", "'AXRole: AXGroup'");
208         shouldBe("resultElement.stringAttributeValue('AXARIALive')", "'polite'");
209         
210         // Misspelled word.
211         // FIXME: Handle this search key.
212         
213         // Plain text.
214         startElement = accessibilityController.focusedElement.childAtIndex(0);
215         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXPlainTextSearchKey", "", false);
216         shouldBe("resultElement.role", "'AXRole: AXStaticText'");
217         shouldBe("resultElement.stringValue", "'AXValue: first blockquote level 1'");
218         
219         // Radio group.
220         startElement = accessibilityController.focusedElement.childAtIndex(0);
221         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXRadioGroupSearchKey", "", false);
222         shouldBe("resultElement.role", "'AXRole: AXRadioGroup'");
223         
224         // Same type element.
225         startElement = accessibilityController.focusedElement.childAtIndex(0);
226         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXSameTypeSearchKey", "", false);
227         shouldBe("resultElement.role", "'AXRole: AXGroup'");
228         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: second blockquote level 1'");
229         
230         // Static text.
231         startElement = accessibilityController.focusedElement.childAtIndex(0);
232         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXStaticTextSearchKey", "", false);
233         shouldBe("resultElement.role", "'AXRole: AXStaticText'");
234         shouldBe("resultElement.stringValue", "'AXValue: first blockquote level 1'");
235         
236         // Style change.
237         startElement = accessibilityController.focusedElement.childAtIndex(2);
238         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXStyleChangeSearchKey", "", false);
239         shouldBe("resultElement.role", "'AXRole: AXGroup'");
240         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: serif blue italic text'");
241         
242         // Same level table.
243         startElement = accessibilityController.focusedElement.childAtIndex(18);
244         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXTableSameLevelSearchKey", "", false);
245         shouldBe("resultElement.role", "'AXRole: AXTable'");
246         shouldBe("resultElement.childAtIndex(0).childAtIndex(0).childAtIndex(0).stringValue", "'AXValue: second table heading level 1'");
247         
248         // Table.
249         startElement = accessibilityController.focusedElement.childAtIndex(0);
250         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXTableSearchKey", "", false);
251         shouldBe("resultElement.role", "'AXRole: AXTable'");
252         shouldBe("resultElement.childAtIndex(0).childAtIndex(0).childAtIndex(0).stringValue", "'AXValue: first table heading level 1'");
253         
254         // Text field.
255         startElement = accessibilityController.focusedElement.childAtIndex(0);
256         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXTextFieldSearchKey", "", false);
257         shouldBe("resultElement.role", "'AXRole: AXTextField'");
258         
259         // Underline.
260         startElement = accessibilityController.focusedElement.childAtIndex(0);
261         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXUnderlineSearchKey", "", false);
262         shouldBe("resultElement.role", "'AXRole: AXGroup'");
263         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: sans-serif black bold text with underline'");
264         
265         // Unvisited link.
266         startElement = accessibilityController.focusedElement.childAtIndex(0);
267         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXUnvisitedLinkSearchKey", "", false);
268         shouldBe("resultElement.boolAttributeValue('AXVisited')", "false");
269         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: link'");
270         
271         // Visited link.
272         accessibilityController.focusedElement.childAtIndex(14).childAtIndex(0).press();
273         startElement = accessibilityController.focusedElement.childAtIndex(0);
274         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXVisitedLinkSearchKey", "", false);
275         shouldBe("resultElement.boolAttributeValue('AXVisited')", "true");
276         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: link'");
277         
278         // Previous text search.
279         startElement = accessibilityController.focusedElement.childAtIndex(10);
280         resultElement = containerElement.uiElementForSearchPredicate(startElement, false, "", "sans-serif black bold text with underline", false);
281         shouldBe("resultElement.role", "'AXRole: AXStaticText'");
282         shouldBe("resultElement.stringValue", "'AXValue: sans-serif black bold text with underline'");
283         
284         // Execute a search for the next heading level 2 or the next link.
285         startElement = accessibilityController.focusedElement.childAtIndex(0);
286         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, ["AXHeadingLevel2SearchKey", "AXLinkSearchKey"], "", false);
287         shouldBe("resultElement.role", "'AXRole: AXHeading'");
288         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 2'");
289         
290         // After finding the heading, execute the search again and we should find the link.
291         resultElement = containerElement.uiElementForSearchPredicate(resultElement, true, ["AXHeadingLevel2SearchKey", "AXLinkSearchKey"], "", false);
292         shouldBe("resultElement.role", "'AXRole: AXLink'");
293         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: link'");
294
295         // From the link, execute the search in reverse and we should land back on the heading.
296         resultElement = containerElement.uiElementForSearchPredicate(resultElement, false, ["AXHeadingLevel2SearchKey", "AXLinkSearchKey"], "", false);
297         shouldBe("resultElement.role", "'AXRole: AXHeading'");
298         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: heading level 2'");
299                
300         // Now, we need to test isVisible. Save off the first object
301         startElement = accessibilityController.focusedElement.childAtIndex(0);
302         
303         // Scroll all the way to the bottom of the content
304         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "", "test button 3", false);
305         shouldBe("resultElement.role", "'AXRole: AXButton'");
306         shouldBe("resultElement.title", "'AXTitle: test button 3'");
307         resultElement.scrollToMakeVisible();
308         
309         // find the start of the isVisible test section
310         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "", "isVisible test start", false);
311         shouldBe("resultElement.role", "'AXRole: AXHeading'");
312         shouldBe("resultElement.childAtIndex(0).stringValue", "'AXValue: isVisible test start'");       
313         
314         // save away the "isVisible test start" heading as the start element
315         startElement = resultElement;
316         
317         // If we don't care about visible only, then we should easily find 3 buttons
318         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXButtonSearchKey", "", false);
319         shouldBe("resultElement.role", "'AXRole: AXButton'");
320         shouldBe("resultElement.title", "'AXTitle: test button 1'");
321         
322         resultElement = containerElement.uiElementForSearchPredicate(resultElement, true, "AXButtonSearchKey", "", false);
323         shouldBe("resultElement.role", "'AXRole: AXButton'");
324         shouldBe("resultElement.title", "'AXTitle: test button 2'");
325         
326         // save away testButton2 so we can make it visible later
327         testButton2 = resultElement;
328
329         resultElement = containerElement.uiElementForSearchPredicate(resultElement, true, "AXButtonSearchKey", "", false);
330         shouldBe("resultElement.role", "'AXRole: AXButton'");
331         shouldBe("resultElement.title", "'AXTitle: test button 3'");
332
333         // if we care about visible only, then we should not find "test button 2"
334         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXButtonSearchKey", "", true);
335         shouldBe("resultElement.role", "'AXRole: AXButton'");
336         shouldBe("resultElement.title", "'AXTitle: test button 1'");
337         
338         resultElement = containerElement.uiElementForSearchPredicate(resultElement, true, "AXButtonSearchKey", "", true);
339         shouldBe("resultElement.role", "'AXRole: AXButton'");
340         shouldBe("resultElement.title", "'AXTitle: test button 3'");
341         
342         // now, scroll to the second button, and confirm that we don't see the first button
343         testButton2.scrollToMakeVisible();
344
345         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXButtonSearchKey", "", true);
346         shouldBe("resultElement.role", "'AXRole: AXButton'");
347         shouldBe("resultElement.title", "'AXTitle: test button 2'");
348         
349         resultElement = containerElement.uiElementForSearchPredicate(resultElement, true, "AXButtonSearchKey", "", true);
350         shouldBe("resultElement.role", "'AXRole: AXButton'");
351         shouldBe("resultElement.title", "'AXTitle: test button 3'");
352         
353         // Now since the page is scrolled to the bottom, the first visible button should be #2
354         startElement = accessibilityController.focusedElement.childAtIndex(0);
355         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXButtonSearchKey", "", true);
356         shouldBe("resultElement.role", "'AXRole: AXButton'");
357         shouldBe("resultElement.title", "'AXTitle: test button 2'");
358         
359         // lets scroll to the top of the page and ensure that the submit button is visible
360         startElement.scrollToMakeVisible();
361         resultElement = containerElement.uiElementForSearchPredicate(startElement, true, "AXButtonSearchKey", "", true);
362         shouldBe("resultElement.role", "'AXRole: AXButton'");
363         shouldBe("resultElement.title", "'AXTitle: Submit'");
364         
365         // there should be no more visible buttons
366         resultElement = containerElement.uiElementForSearchPredicate(resultElement, true, "AXButtonSearchKey", "", true);
367         shouldBe("resultElement.role", "'AXRole: '");
368         
369     }
370     
371 </script>
372
373 <script src="../../../fast/js/resources/js-test-post.js"></script>
374 </body>
375 </html>