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