Upstream version 7.35.139.0
[platform/framework/web/crosswalk.git] / src / content / browser / accessibility / dump_accessibility_tree_browsertest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <set>
6 #include <string>
7 #include <vector>
8
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/logging.h"
12 #include "base/path_service.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "content/browser/accessibility/accessibility_tree_formatter.h"
18 #include "content/browser/accessibility/browser_accessibility.h"
19 #include "content/browser/accessibility/browser_accessibility_manager.h"
20 #include "content/browser/renderer_host/render_view_host_impl.h"
21 #include "content/port/browser/render_widget_host_view_port.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/common/content_paths.h"
24 #include "content/public/common/content_switches.h"
25 #include "content/public/common/url_constants.h"
26 #include "content/public/test/content_browser_test.h"
27 #include "content/public/test/content_browser_test_utils.h"
28 #include "content/shell/browser/shell.h"
29 #include "content/test/accessibility_browser_test_utils.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 // TODO(aboxhall): Create expectations on Android for these
33 #if defined(OS_ANDROID)
34 #define MAYBE(x) DISABLED_##x
35 #else
36 #define MAYBE(x) x
37 #endif
38
39 namespace content {
40
41 namespace {
42
43 const char kCommentToken = '#';
44 const char kMarkSkipFile[] = "#<skip";
45 const char kMarkEndOfFile[] = "<-- End-of-file -->";
46 const char kSignalDiff[] = "*";
47
48 }  // namespace
49
50 typedef AccessibilityTreeFormatter::Filter Filter;
51
52 // This test takes a snapshot of the platform BrowserAccessibility tree and
53 // tests it against an expected baseline.
54 //
55 // The flow of the test is as outlined below.
56 // 1. Load an html file from chrome/test/data/accessibility.
57 // 2. Read the expectation.
58 // 3. Browse to the page and serialize the platform specific tree into a human
59 //    readable string.
60 // 4. Perform a comparison between actual and expected and fail if they do not
61 //    exactly match.
62 class DumpAccessibilityTreeTest : public ContentBrowserTest {
63  public:
64   // Utility helper that does a comment aware equality check.
65   // Returns array of lines from expected file which are different.
66   std::vector<int> DiffLines(const std::vector<std::string>& expected_lines,
67                              const std::vector<std::string>& actual_lines) {
68     int actual_lines_count = actual_lines.size();
69     int expected_lines_count = expected_lines.size();
70     std::vector<int> diff_lines;
71     int i = 0, j = 0;
72     while (i < actual_lines_count && j < expected_lines_count) {
73       if (expected_lines[j].size() == 0 ||
74           expected_lines[j][0] == kCommentToken) {
75         // Skip comment lines and blank lines in expected output.
76         ++j;
77         continue;
78       }
79
80       if (actual_lines[i] != expected_lines[j])
81         diff_lines.push_back(j);
82       ++i;
83       ++j;
84     }
85
86     // Actual file has been fully checked.
87     return diff_lines;
88   }
89
90   void AddDefaultFilters(std::vector<Filter>* filters) {
91     filters->push_back(Filter(base::ASCIIToUTF16("FOCUSABLE"), Filter::ALLOW));
92     filters->push_back(Filter(base::ASCIIToUTF16("READONLY"), Filter::ALLOW));
93     filters->push_back(Filter(base::ASCIIToUTF16("*=''"), Filter::DENY));
94   }
95
96   void ParseFilters(const std::string& test_html,
97                     std::vector<Filter>* filters) {
98     std::vector<std::string> lines;
99     base::SplitString(test_html, '\n', &lines);
100     for (std::vector<std::string>::const_iterator iter = lines.begin();
101          iter != lines.end();
102          ++iter) {
103       const std::string& line = *iter;
104       const std::string& allow_empty_str =
105           AccessibilityTreeFormatter::GetAllowEmptyString();
106       const std::string& allow_str =
107           AccessibilityTreeFormatter::GetAllowString();
108       const std::string& deny_str =
109           AccessibilityTreeFormatter::GetDenyString();
110       if (StartsWithASCII(line, allow_empty_str, true)) {
111         filters->push_back(
112           Filter(base::UTF8ToUTF16(line.substr(allow_empty_str.size())),
113                  Filter::ALLOW_EMPTY));
114       } else if (StartsWithASCII(line, allow_str, true)) {
115         filters->push_back(Filter(base::UTF8ToUTF16(
116                                       line.substr(allow_str.size())),
117                                   Filter::ALLOW));
118       } else if (StartsWithASCII(line, deny_str, true)) {
119         filters->push_back(Filter(base::UTF8ToUTF16(
120                                       line.substr(deny_str.size())),
121                                   Filter::DENY));
122       }
123     }
124   }
125
126   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
127     ContentBrowserTest::SetUpCommandLine(command_line);
128     // Enable <dialog>, which is used in some tests.
129     CommandLine::ForCurrentProcess()->AppendSwitch(
130         switches::kEnableExperimentalWebPlatformFeatures);
131   }
132
133   void RunTest(const base::FilePath::CharType* file_path);
134 };
135
136 void DumpAccessibilityTreeTest::RunTest(
137     const base::FilePath::CharType* file_path) {
138   NavigateToURL(shell(), GURL(kAboutBlankURL));
139
140   // Setup test paths.
141   base::FilePath dir_test_data;
142   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &dir_test_data));
143   base::FilePath test_path(
144       dir_test_data.Append(FILE_PATH_LITERAL("accessibility")));
145   ASSERT_TRUE(base::PathExists(test_path))
146       << test_path.LossyDisplayName();
147
148   base::FilePath html_file = test_path.Append(base::FilePath(file_path));
149   // Output the test path to help anyone who encounters a failure and needs
150   // to know where to look.
151   printf("Testing: %s\n", html_file.MaybeAsASCII().c_str());
152
153   std::string html_contents;
154   base::ReadFileToString(html_file, &html_contents);
155
156   // Read the expected file.
157   std::string expected_contents_raw;
158   base::FilePath expected_file =
159     base::FilePath(html_file.RemoveExtension().value() +
160                    AccessibilityTreeFormatter::GetExpectedFileSuffix());
161   base::ReadFileToString(expected_file, &expected_contents_raw);
162
163   // Tolerate Windows-style line endings (\r\n) in the expected file:
164   // normalize by deleting all \r from the file (if any) to leave only \n.
165   std::string expected_contents;
166   base::RemoveChars(expected_contents_raw, "\r", &expected_contents);
167
168   if (!expected_contents.compare(0, strlen(kMarkSkipFile), kMarkSkipFile)) {
169     printf("Skipping this test on this platform.\n");
170     return;
171   }
172
173   // Load the page.
174   base::string16 html_contents16;
175   html_contents16 = base::UTF8ToUTF16(html_contents);
176   GURL url = GetTestUrl("accessibility",
177                         html_file.BaseName().MaybeAsASCII().c_str());
178   AccessibilityNotificationWaiter waiter(
179       shell(), AccessibilityModeComplete,
180       ui::AX_EVENT_LOAD_COMPLETE);
181   NavigateToURL(shell(), url);
182   waiter.WaitForNotification();
183
184   RenderWidgetHostViewPort* host_view = RenderWidgetHostViewPort::FromRWHV(
185       shell()->web_contents()->GetRenderWidgetHostView());
186   AccessibilityTreeFormatter formatter(
187       host_view->GetBrowserAccessibilityManager()->GetRoot());
188
189   // Parse filters in the test file.
190   std::vector<Filter> filters;
191   AddDefaultFilters(&filters);
192   ParseFilters(html_contents, &filters);
193   formatter.SetFilters(filters);
194
195   // Perform a diff (or write the initial baseline).
196   base::string16 actual_contents_utf16;
197   formatter.FormatAccessibilityTree(&actual_contents_utf16);
198   std::string actual_contents = base::UTF16ToUTF8(actual_contents_utf16);
199   std::vector<std::string> actual_lines, expected_lines;
200   Tokenize(actual_contents, "\n", &actual_lines);
201   Tokenize(expected_contents, "\n", &expected_lines);
202   // Marking the end of the file with a line of text ensures that
203   // file length differences are found.
204   expected_lines.push_back(kMarkEndOfFile);
205   actual_lines.push_back(kMarkEndOfFile);
206
207   std::vector<int> diff_lines = DiffLines(expected_lines, actual_lines);
208   bool is_different = diff_lines.size() > 0;
209   EXPECT_FALSE(is_different);
210   if (is_different) {
211     // Mark the expected lines which did not match actual output with a *.
212     printf("* Line Expected\n");
213     printf("- ---- --------\n");
214     for (int line = 0, diff_index = 0;
215          line < static_cast<int>(expected_lines.size());
216          ++line) {
217       bool is_diff = false;
218       if (diff_index < static_cast<int>(diff_lines.size()) &&
219           diff_lines[diff_index] == line) {
220         is_diff = true;
221         ++diff_index;
222       }
223       printf("%1s %4d %s\n", is_diff? kSignalDiff : "", line + 1,
224              expected_lines[line].c_str());
225     }
226     printf("\nActual\n");
227     printf("------\n");
228     printf("%s\n", actual_contents.c_str());
229   }
230
231   if (!base::PathExists(expected_file)) {
232     base::FilePath actual_file =
233         base::FilePath(html_file.RemoveExtension().value() +
234                        AccessibilityTreeFormatter::GetActualFileSuffix());
235
236     EXPECT_TRUE(base::WriteFile(
237         actual_file, actual_contents.c_str(), actual_contents.size()));
238
239     ADD_FAILURE() << "No expectation found. Create it by doing:\n"
240                   << "mv " << actual_file.LossyDisplayName() << " "
241                   << expected_file.LossyDisplayName();
242   }
243 }
244
245 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityA) {
246   RunTest(FILE_PATH_LITERAL("a.html"));
247 }
248
249 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAddress) {
250   RunTest(FILE_PATH_LITERAL("address.html"));
251 }
252
253 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAName) {
254   RunTest(FILE_PATH_LITERAL("a-name.html"));
255 }
256
257 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityANoText) {
258   RunTest(FILE_PATH_LITERAL("a-no-text.html"));
259 }
260
261 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAOnclick) {
262   RunTest(FILE_PATH_LITERAL("a-onclick.html"));
263 }
264
265 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
266                        AccessibilityAriaApplication) {
267   RunTest(FILE_PATH_LITERAL("aria-application.html"));
268 }
269
270 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
271                        AccessibilityAriaAutocomplete) {
272   RunTest(FILE_PATH_LITERAL("aria-autocomplete.html"));
273 }
274
275 // crbug.com/98976 will cause new elements to be added to the Blink a11y tree
276 // Re-baseline after the Blink change goes in
277 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
278                        DISABLED_AccessibilityAriaCombobox) {
279   RunTest(FILE_PATH_LITERAL("aria-combobox.html"));
280 }
281
282 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
283                        MAYBE(AccessibilityAriaFlowto)) {
284   RunTest(FILE_PATH_LITERAL("aria-flowto.html"));
285 }
286
287 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaInvalid) {
288   RunTest(FILE_PATH_LITERAL("aria-invalid.html"));
289 }
290
291 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaLevel) {
292   RunTest(FILE_PATH_LITERAL("aria-level.html"));
293 }
294
295 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaMenu) {
296   RunTest(FILE_PATH_LITERAL("aria-menu.html"));
297 }
298
299 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
300                        AccessibilityAriaMenuitemradio) {
301   RunTest(FILE_PATH_LITERAL("aria-menuitemradio.html"));
302 }
303
304 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
305                        AccessibilityAriaPressed) {
306   RunTest(FILE_PATH_LITERAL("aria-pressed.html"));
307 }
308
309 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
310                        AccessibilityAriaProgressbar) {
311   RunTest(FILE_PATH_LITERAL("aria-progressbar.html"));
312 }
313
314 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
315                        AccessibilityAriaToolbar) {
316   RunTest(FILE_PATH_LITERAL("toolbar.html"));
317 }
318
319 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
320                        AccessibilityAriaValueMin) {
321   RunTest(FILE_PATH_LITERAL("aria-valuemin.html"));
322 }
323
324 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
325                        AccessibilityAriaValueMax) {
326   RunTest(FILE_PATH_LITERAL("aria-valuemax.html"));
327 }
328
329 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityArticle) {
330   RunTest(FILE_PATH_LITERAL("article.html"));
331 }
332
333 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAWithImg) {
334   RunTest(FILE_PATH_LITERAL("a-with-img.html"));
335 }
336
337 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBdo) {
338   RunTest(FILE_PATH_LITERAL("bdo.html"));
339 }
340
341 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBR) {
342   RunTest(FILE_PATH_LITERAL("br.html"));
343 }
344
345 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityButtonNameCalc) {
346   RunTest(FILE_PATH_LITERAL("button-name-calc.html"));
347 }
348
349 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCanvas) {
350   RunTest(FILE_PATH_LITERAL("canvas.html"));
351 }
352
353 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
354                        AccessibilityCheckboxNameCalc) {
355   RunTest(FILE_PATH_LITERAL("checkbox-name-calc.html"));
356 }
357
358 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDialog) {
359   RunTest(FILE_PATH_LITERAL("dialog.html"));
360 }
361
362 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDiv) {
363   RunTest(FILE_PATH_LITERAL("div.html"));
364 }
365
366 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDl) {
367   RunTest(FILE_PATH_LITERAL("dl.html"));
368 }
369
370 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
371                        AccessibilityContenteditableDescendants) {
372   RunTest(FILE_PATH_LITERAL("contenteditable-descendants.html"));
373 }
374
375 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityEm) {
376   RunTest(FILE_PATH_LITERAL("em.html"));
377 }
378
379 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityFooter) {
380   RunTest(FILE_PATH_LITERAL("footer.html"));
381 }
382
383 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityForm) {
384   RunTest(FILE_PATH_LITERAL("form.html"));
385 }
386
387 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityHeading) {
388   RunTest(FILE_PATH_LITERAL("heading.html"));
389 }
390
391 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityHR) {
392   RunTest(FILE_PATH_LITERAL("hr.html"));
393 }
394
395 // crbug.com/179717 and crbug.com/224659
396 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
397                        DISABLED_AccessibilityIframeCoordinates) {
398   RunTest(FILE_PATH_LITERAL("iframe-coordinates.html"));
399 }
400
401 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputButton) {
402   RunTest(FILE_PATH_LITERAL("input-button.html"));
403 }
404
405 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
406                        AccessibilityInputButtonInMenu) {
407   RunTest(FILE_PATH_LITERAL("input-button-in-menu.html"));
408 }
409
410 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputColor) {
411   RunTest(FILE_PATH_LITERAL("input-color.html"));
412 }
413
414 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
415                        AccessibilityInputImageButtonInMenu) {
416   RunTest(FILE_PATH_LITERAL("input-image-button-in-menu.html"));
417 }
418
419 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputRange) {
420   RunTest(FILE_PATH_LITERAL("input-range.html"));
421 }
422
423 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
424                        AccessibilityInputTextNameCalc) {
425   RunTest(FILE_PATH_LITERAL("input-text-name-calc.html"));
426 }
427
428 // crbug.com/98976 will cause new elements to be added to the Blink a11y tree
429 // Re-baseline after the Blink change goes in
430 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
431                        DISABLED_AccessibilityInputTypes) {
432   RunTest(FILE_PATH_LITERAL("input-types.html"));
433 }
434
435 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityLabel) {
436   RunTest(FILE_PATH_LITERAL("label.html"));
437 }
438
439 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityLandmark) {
440   RunTest(FILE_PATH_LITERAL("landmark.html"));
441 }
442
443 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityListMarkers) {
444   RunTest(FILE_PATH_LITERAL("list-markers.html"));
445 }
446
447 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
448                        AccessibilityModalDialogClosed) {
449   RunTest(FILE_PATH_LITERAL("modal-dialog-closed.html"));
450 }
451
452 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
453                        AccessibilityModalDialogOpened) {
454   RunTest(FILE_PATH_LITERAL("modal-dialog-opened.html"));
455 }
456
457 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
458                        AccessibilityModalDialogInIframeClosed) {
459   RunTest(FILE_PATH_LITERAL("modal-dialog-in-iframe-closed.html"));
460 }
461
462 // TODO(dmazzoni): fix this test after Blink change that broke it lands.
463 // http://crbug.com/353067
464 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
465                        DISABLED_AccessibilityModalDialogInIframeOpened) {
466   RunTest(FILE_PATH_LITERAL("modal-dialog-in-iframe-opened.html"));
467 }
468
469 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
470                        AccessibilityModalDialogStack) {
471   RunTest(FILE_PATH_LITERAL("modal-dialog-stack.html"));
472 }
473
474 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityP) {
475   RunTest(FILE_PATH_LITERAL("p.html"));
476 }
477
478 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityRegion) {
479   RunTest(FILE_PATH_LITERAL("region.html"));
480 }
481
482 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySelect) {
483   RunTest(FILE_PATH_LITERAL("select.html"));
484 }
485
486 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySpan) {
487   RunTest(FILE_PATH_LITERAL("span.html"));
488 }
489
490 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySpinButton) {
491   RunTest(FILE_PATH_LITERAL("spinbutton.html"));
492 }
493
494 // TODO(dmazzoni): Rebaseline this test after Blink rolls past r155083.
495 // See http://crbug.com/265619
496 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, DISABLED_AccessibilitySvg) {
497   RunTest(FILE_PATH_LITERAL("svg.html"));
498 }
499
500 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTab) {
501   RunTest(FILE_PATH_LITERAL("tab.html"));
502 }
503
504 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTableSimple) {
505   RunTest(FILE_PATH_LITERAL("table-simple.html"));
506 }
507
508 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTableSpans) {
509   RunTest(FILE_PATH_LITERAL("table-spans.html"));
510 }
511
512 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
513                        AccessibilityToggleButton) {
514   RunTest(FILE_PATH_LITERAL("togglebutton.html"));
515 }
516
517 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityUl) {
518   RunTest(FILE_PATH_LITERAL("ul.html"));
519 }
520
521 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityWbr) {
522   RunTest(FILE_PATH_LITERAL("wbr.html"));
523 }
524
525 }  // namespace content