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