Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / LayoutTests / fast / harness / resources / results-test.js
1 // To run these tests, load results.html in a browser.
2 // You should see a series of PASS lines.
3 if (window.testRunner)
4     testRunner.dumpAsText();
5
6 var testStyles = document.createElement('style');
7 testStyles.innerText = ".test-pass { color: green; } .test-fail { color: red; }";
8 document.querySelector('head').appendChild(testStyles);
9
10 var g_testIndex = 0;
11 var g_log = ["You should see a series of PASS lines."];
12
13 // Make async actually be sync for the sake of simpler testing.
14 function async(func, args)
15 {
16     func.apply(null, args);
17 }
18
19 function mockResults()
20 {
21     return {
22         tests: {},
23         "skipped": 0,
24         "num_regressions": 0,
25         "version": 0,
26         "num_passes": 0,
27         "fixable": 0,
28         "num_flaky": 0,
29         "layout_tests_dir": "/WEBKITROOT",
30         "has_pretty_patch": false,
31         "has_wdiff": false,
32         "revision": 12345,
33         "pixel_tests_enabled": true
34     };
35 }
36
37 function isFailureExpected(expected, actual)
38 {
39     var isExpected = true;
40     if (actual != 'SKIP') {
41         var expectedArray = expected.split(' ');
42         var actualArray = actual.split(' ');
43         for (var i = 0; i < actualArray.length; i++) {
44             var actualValue = actualArray[i];
45             if (expectedArray.indexOf(actualValue) == -1 &&
46                 (expectedArray.indexOf('FAIL') == -1 ||
47                  (actualValue != 'TEXT' && actualValue != 'IMAGE+TEXT' && actualValue != 'AUDIO')))
48                 isExpected = false;
49         }
50     }
51     return isExpected;
52 }
53
54 function mockExpectation(expected, actual)
55 {
56     return {
57         expected: expected,
58         time_ms: 1,
59         actual: actual,
60         has_stderr: false,
61         is_unexpected: !isFailureExpected(expected, actual)
62     };
63 }
64
65 function logPass(msg)
66 {
67     g_log.push('TEST-' + g_testIndex + ': <span class="test-pass">' + msg + '</span>')
68 }
69
70 function logFail(msg)
71 {
72     g_log.push('TEST-' + g_testIndex + ': <span class="test-fail">' + msg + '</span>')
73 }
74
75 function assertTrue(bool)
76 {
77     if (bool)
78         logPass('PASS');
79     else
80         logFail('FAIL');
81 }
82
83 function runTest(results, assertions, opt_localStorageValue)
84 {
85     document.body.innerHTML = '';
86     g_testIndex++;
87     g_state = undefined;
88     localStorage.setItem(OptionWriter._key, opt_localStorageValue || '');
89
90     try {
91         ADD_RESULTS(results);
92         originalGeneratePage();
93     } catch (e) {
94         logFail("FAIL: uncaught exception " + e.toString());
95     }
96     
97     try {
98         assertions();
99     } catch (e) {
100         logFail("FAIL: uncaught exception executing assertions " + e.toString());
101     }
102 }
103
104 function runDefaultSingleRowTest(test, expected, actual, isExpected, textResults, imageResults)
105 {
106     results = mockResults();
107     results.tests[test] = mockExpectation(expected, actual);
108     runSingleRowTest(results, isExpected, textResults, imageResults);
109 }
110
111 function runSingleRowTest(results, isExpected, textResults, imageResults)
112 {
113     for (var key in results.tests)
114         var test = key;
115     var expected = results.tests[test].expected;
116     var actual = results.tests[test].actual;
117     runTest(results, function() {
118         if (isExpected)
119             assertTrue(document.querySelector('tbody').className == 'expected');
120         else
121             assertTrue(document.querySelector('tbody').className.indexOf('expected') == -1);
122
123         assertTrue(document.querySelector('tbody td:nth-child(1)').textContent == '+' + test + ' \u2691');
124         assertTrue(document.querySelector('tbody td:nth-child(2)').textContent == textResults);
125         assertTrue(document.querySelector('tbody td:nth-child(3)').textContent == imageResults);
126         assertTrue(document.querySelector('tbody td:nth-child(4)').textContent == actual);
127         assertTrue(document.querySelector('tbody td:nth-child(5)').textContent == expected);
128     });
129     
130 }
131
132 function runTests()
133 {
134     var results = mockResults();
135     var subtree = results.tests['foo'] = {}
136     subtree['bar.html'] = mockExpectation('PASS', 'TEXT');
137     runTest(results, function() {
138         assertTrue(document.getElementById('image-results-header').textContent == '');
139         assertTrue(document.getElementById('text-results-header').textContent != '');
140     });
141
142     results = mockResults();
143     var subtree = results.tests['foo'] = {}
144     subtree['bar.html'] = mockExpectation('TEXT', 'MISSING');
145     subtree['bar.html'].is_missing_text = true;
146     subtree['bar.html'].is_missing_audio = true;
147     subtree['bar.html'].is_missing_image = true;
148     runTest(results, function() {
149         assertTrue(!document.getElementById('results-table'));
150         assertTrue(document.querySelector('#missing-table .test-link').textContent == 'foo/bar.html');
151         assertTrue(document.getElementsByClassName('result-link')[0].textContent == 'audio result');
152         assertTrue(document.getElementsByClassName('result-link')[1].textContent == 'result');
153         assertTrue(document.getElementsByClassName('result-link')[2].textContent == 'png result');
154     });
155
156     results = mockResults();
157     var subtree = results.tests['foo'] = {}
158     subtree['bar.html'] = mockExpectation('PASS', 'TEXT');
159     subtree['bar.html'].has_stderr = true;
160     runTest(results, function() {
161         assertTrue(document.getElementById('results-table'));
162         assertTrue(document.querySelector('#stderr-table .result-link').textContent == 'stderr');
163     });
164
165     results = mockResults();
166     var subtree = results.tests['foo'] = {}
167     subtree['bar.html'] = mockExpectation('TEXT', 'PASS');
168     subtree['bar1.html'] = mockExpectation('CRASH', 'PASS');
169     subtree['bar2.html'] = mockExpectation('IMAGE', 'PASS');
170     subtree['crash.html'] = mockExpectation('IMAGE', 'CRASH');
171     subtree['timeout.html'] = mockExpectation('IMAGE', 'TIMEOUT');
172     runTest(results, function() {
173         assertTrue(!document.getElementById('results-table'));
174
175         var testLinks = document.querySelectorAll('#passes-table .test-link');
176         assertTrue(testLinks[0].textContent == 'foo/bar.html');
177         assertTrue(testLinks[1].textContent == 'foo/bar1.html');
178         assertTrue(testLinks[2].textContent == 'foo/bar2.html');
179         
180         assertTrue(!document.querySelector('#passes-table .expand-button'));
181
182         var expectationTypes = document.querySelectorAll('#passes-table td:last-of-type');
183         assertTrue(expectationTypes[0].textContent == 'TEXT');
184         assertTrue(expectationTypes[1].textContent == 'CRASH');
185         assertTrue(expectationTypes[2].textContent == 'IMAGE');
186         
187         assertTrue(document.getElementById('crash-tests-table'));
188         assertTrue(document.getElementById('crash-tests-table').textContent.indexOf('crash log') != -1);
189         assertTrue(document.getElementById('timeout-tests-table'));
190         assertTrue(document.getElementById('timeout-tests-table').textContent.indexOf('expected actual diff') != -1);
191     });
192
193     function isExpanded(expandLink)
194     {
195         var enDash = '\u2013';
196         return expandLink.textContent == enDash;
197     }
198
199     function isCollapsed(expandLink)
200     {
201         return expandLink.textContent == '+';
202     }
203
204     results = mockResults();
205     var subtree = results.tests['foo'] = {}
206     subtree['bar.html'] = mockExpectation('TEXT', 'PASS');
207     subtree['bar-missing.html'] = mockExpectation('TEXT', 'MISSING');
208     subtree['bar-missing.html'].is_missing_text = true;
209     subtree['bar-stderr.html'] = mockExpectation('PASS', 'TEXT');
210     subtree['bar-stderr.html'].has_stderr = true;
211     subtree['bar-unexpected-pass.html'] = mockExpectation('TEXT', 'PASS');
212     runTest(results, function() {
213         assertTrue(document.querySelectorAll('tbody tr').length == 5);
214         expandAllExpectations();
215         assertTrue(document.querySelectorAll('tbody tr').length == 8);
216         var expandLinks = document.querySelectorAll('.expand-button-text');
217         for (var i = 0; i < expandLinks.length; i++)
218             assertTrue(isExpanded(expandLinks[i]));
219         
220         collapseAllExpectations();
221         // Collapsed expectations stay in the dom, but are display:none.
222         assertTrue(document.querySelectorAll('tbody tr').length == 8);
223         var expandLinks = document.querySelectorAll('.expand-button-text');
224         for (var i = 0; i < expandLinks.length; i++)
225             assertTrue(isCollapsed(expandLinks[i]));
226             
227         expandExpectations(expandLinks[1]);
228         assertTrue(isCollapsed(expandLinks[0]));
229         assertTrue(isExpanded(expandLinks[1]));
230
231         collapseExpectations(expandLinks[1]);
232         assertTrue(expandLinks[1].textContent == '+');
233     });
234
235     results = mockResults();
236     var subtree = results.tests['foo'] = {}
237     subtree['bar.html'] = mockExpectation('PASS', 'TEXT');
238     subtree['bar-expected-fail.html'] = mockExpectation('TEXT', 'TEXT');
239     runTest(results, function() {
240         assertTrue(document.querySelectorAll('.expected').length == 1);
241         assertTrue(document.querySelector('.expected .test-link').textContent == 'foo/bar-expected-fail.html');
242
243         assertTrue(window.getComputedStyle(document.querySelectorAll('tbody')[0], null)['display'] == 'none');
244
245         expandAllExpectations();
246         assertTrue(visibleExpandLinks().length == 1);
247         assertTrue(document.querySelectorAll('.results-row').length == 1);
248         assertTrue(window.getComputedStyle(document.querySelectorAll('tbody')[0], null)['display'] == 'none');
249         
250         document.getElementById('show-expected-failures').checked = true;
251         document.getElementById('show-expected-failures').onchange();
252
253         assertTrue(visibleExpandLinks().length == 2);
254         assertTrue(document.querySelectorAll('.results-row').length == 1);
255         assertTrue(window.getComputedStyle(document.querySelectorAll('tbody')[0], null)['display'] != 'none');
256         
257         expandAllExpectations();
258         assertTrue(document.querySelectorAll('.results-row').length == 2);
259         assertTrue(window.getComputedStyle(document.querySelectorAll('tbody')[0], null)['display'] != 'none');
260     });
261     
262     results = mockResults();
263     results.tests['only-expected-fail.html'] = mockExpectation('TEXT', 'TEXT');
264     runTest(results, function() {
265         assertTrue(window.getComputedStyle(document.getElementById('results-table').parentNode, null)['display'] == 'none');
266     });
267
268     runDefaultSingleRowTest('bar-skip.html', 'TEXT', 'SKIP', true, '', '');
269     runDefaultSingleRowTest('bar-flaky-fail.html', 'PASS FAIL', 'TEXT', true, 'expected actual diff ', '');
270     runDefaultSingleRowTest('bar-flaky-fail-unexpected.html', 'PASS TEXT', 'IMAGE', false, '', 'images diff ');
271     runDefaultSingleRowTest('bar-audio.html', 'TEXT', 'AUDIO', false, 'expected audio actual audio ', '');
272     runDefaultSingleRowTest('bar-image.html', 'TEXT', 'IMAGE', false, '', 'images diff ');
273     runDefaultSingleRowTest('bar-image-plus-text.html', 'TEXT', 'IMAGE+TEXT', false, 'expected actual diff ', 'images diff ');
274
275     // test the mapping for FAIL onto only ['TEXT', 'IMAGE+TEXT', 'AUDIO']
276     runDefaultSingleRowTest('bar-image.html', 'FAIL', 'IMAGE+TEXT', true, 'expected actual diff ', 'images diff ');
277     runDefaultSingleRowTest('bar-image.html', 'FAIL', 'AUDIO', true, 'expected audio actual audio ', '');
278     runDefaultSingleRowTest('bar-image.html', 'FAIL', 'TEXT', true, 'expected actual diff ', '');
279     runDefaultSingleRowTest('bar-image.html', 'FAIL', 'IMAGE', false, '', 'images diff ');
280
281     results = mockResults();
282     results.tests['bar-reftest.html'] = mockExpectation('PASS', 'IMAGE');
283     results.tests['bar-reftest.html'].reftest_type = ['=='];
284     runSingleRowTest(results, false, '', 'ref html images diff ');
285
286     results = mockResults();
287     results.tests['bar-reftest-mismatch.html'] = mockExpectation('PASS', 'IMAGE');
288     results.tests['bar-reftest-mismatch.html'].reftest_type = ['!='];
289     runSingleRowTest(results, false, '', 'ref mismatch html actual ');
290
291     results = mockResults();
292     results.tests['bar-reftest.html'] = mockExpectation('IMAGE', 'PASS');
293     results.tests['bar-reftest.html'].reftest_type = ['=='];
294     results.pixel_tests_enabled = false;
295     runTest(results, function() {
296         assertTrue(document.querySelector('tbody td:nth-child(1)').textContent == 'bar-reftest.html \u2691');
297     });
298
299     results = mockResults();
300     results.tests['bar-reftest-mismatch.html'] = mockExpectation('IMAGE', 'PASS');
301     results.tests['bar-reftest-mismatch.html'].reftest_type = ['!='];
302     results.pixel_tests_enabled = false;
303     runTest(results, function() {
304         assertTrue(document.querySelector('tbody td:nth-child(1)').textContent == 'bar-reftest-mismatch.html \u2691');
305     });
306
307     results = mockResults();
308     var subtree = results.tests['foo'] = {}
309     subtree['bar-flaky-pass.html'] = mockExpectation('PASS TEXT', 'PASS');
310     runTest(results, function() {
311         assertTrue(!document.getElementById('results-table'));
312         assertTrue(document.getElementById('passes-table'));
313         assertTrue(document.body.textContent.indexOf('foo/bar-flaky-pass.html') != -1);
314     });
315
316     results = mockResults();
317     var subtree = results.tests['foo'] = {}
318     subtree['bar-flaky-fail.html'] = mockExpectation('PASS TEXT', 'IMAGE PASS');
319     runTest(results, function() {
320         assertTrue(!document.getElementById('results-table'));
321         assertTrue(document.getElementById('flaky-tests-table'));
322         assertTrue(document.body.textContent.indexOf('bar-flaky-fail.html') != -1);
323     });
324
325     results = mockResults();
326     var subtree = results.tests['foo'] = {}
327     subtree['bar-flaky-expected.html'] = mockExpectation('PASS FAIL', 'PASS TEXT');
328     runTest(results, function() {
329         assertTrue(!document.getElementById('results-table'));
330         assertTrue(document.getElementById('flaky-tests-table'));
331         assertTrue(document.body.textContent.indexOf('bar-flaky-expected.html') != -1);
332         assertTrue(document.querySelector('tbody').className == 'expected');
333     });
334
335     results = mockResults();
336     var subtree = results.tests['foo'] = {}
337     subtree['bar-really-long-path-that-should-probably-wrap-because-otherwise-the-table-will-be-too-wide.html'] = mockExpectation('PASS', 'TEXT');
338     runTest(results, function() {
339         document.body.style.width = '800px';
340         var links = document.querySelectorAll('tbody a');
341         assertTrue(links[0].getClientRects().length == 2);
342         assertTrue(links[1].getClientRects().length == 1);
343         document.body.style.width = '';
344     });
345
346     results = mockResults();
347     var subtree = results.tests['foo'] = {}
348     subtree['bar.html'] = mockExpectation('TEXT', 'TEXT');
349     results.has_pretty_patch = true;
350     runTest(results, function() {
351         assertTrue(document.querySelector('tbody td:nth-child(2)').textContent.indexOf('pretty diff') != -1);
352         assertTrue(document.querySelector('tbody td:nth-child(2)').textContent.indexOf('wdiff') == -1);
353     });
354
355     results = mockResults();
356     var subtree = results.tests['foo'] = {}
357     subtree['bar.html'] = mockExpectation('TEXT', 'TEXT');
358     results.has_wdiff = true;
359     runTest(results, function() {
360         assertTrue(document.querySelector('tbody td:nth-child(2)').textContent.indexOf('wdiff') != -1);
361         assertTrue(document.querySelector('tbody td:nth-child(2)').textContent.indexOf('pretty diff') == -1);
362     });
363     
364     results = mockResults();
365     var subtree = results.tests['foo'] = {}
366     subtree['bar.html'] = mockExpectation('TEXT', 'PASS');
367     subtree['bar-1.html'] = mockExpectation('TEXT', 'CRASH');
368     subtree['bar-5.html'] = mockExpectation('TEXT', 'IMAGE+TEXT');
369     subtree['bar-3.html'] = mockExpectation('PASS', 'TEXT');
370     subtree['bar-2.html'] = mockExpectation('PASS', 'IMAGE');
371     runTest(results, function() {
372         // FIXME: This just ensures we don't get a JS error.
373         // Verify that the sort is correct and that inline expanded expectations
374         // move along with the test they're attached to.
375         TableSorter.sortColumn(0);
376         TableSorter.sortColumn(0);
377         TableSorter.sortColumn(1);
378         TableSorter.sortColumn(1);
379         TableSorter.sortColumn(2);
380         TableSorter.sortColumn(2);
381         TableSorter.sortColumn(3);
382         TableSorter.sortColumn(3);
383         TableSorter.sortColumn(4);
384         TableSorter.sortColumn(4);
385         TableSorter.sortColumn(0);
386         logPass('PASS');
387     });
388
389     results = mockResults();
390     var subtree = results.tests['foo'] = {}
391     subtree['bar-5.html'] = mockExpectation('TEXT', 'IMAGE+TEXT');
392     runTest(results, function() {
393         expandAllExpectations();
394         var png = document.querySelector('[src*="bar-5-expected.png"]');
395         var x = png.offsetLeft + 1;
396         var y = png.offsetTop + 1;
397         var mockEvent = {
398             target: png,
399             clientX: x,
400             clientY: y
401         }
402         PixelZoomer.showOnDelay = false;
403         PixelZoomer.handleMouseMove(mockEvent);
404         assertTrue(!!document.querySelector('.pixel-zoom-container'));
405         assertTrue(document.querySelectorAll('.zoom-image-container').length == 3);
406     });
407     
408     results = mockResults();
409     var subtree = results.tests['fullscreen'] = {}
410     subtree['full-screen-api.html'] = mockExpectation('TEXT', 'IMAGE+TEXT');
411     runTest(results, function() {
412         // Use a regexp to match windows and unix-style paths.
413         var expectedRegExp = new RegExp('^file.*' + results.layout_tests_dir + '/fullscreen/full-screen-api.html$');
414         assertTrue(expectedRegExp.exec(document.querySelector('tbody td:first-child a').href));
415     });
416
417     var oldShouldUseTracLinks = shouldUseTracLinks;
418     shouldUseTracLinks = function() { return true; };
419     
420     results = mockResults();
421     var subtree = results.tests['fullscreen'] = {}
422     subtree['full-screen-api.html'] = mockExpectation('TEXT', 'IMAGE+TEXT');
423     runTest(results, function() {
424         var expectedHref = 'http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fullscreen/full-screen-api.html?pathrev=' + results.revision +'#l1';
425         assertTrue(document.querySelector('tbody td:first-child a').href == expectedHref);
426     });
427
428     results = mockResults();
429     var subtree = results.tests['fullscreen'] = {}
430     subtree['full-screen-api.html'] = mockExpectation('TEXT', 'IMAGE+TEXT');
431     results.revision = '';
432     runTest(results, function() {
433         var expectedHref = 'http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fullscreen/full-screen-api.html#l1';
434         assertTrue(document.querySelector('tbody td:first-child a').href == expectedHref);
435     });
436
437     shouldUseTracLinks = oldShouldUseTracLinks;
438
439     results = mockResults();
440     results.tests['bar.html'] = mockExpectation('PASS', 'IMAGE');
441     runTest(results, function() {
442         assertTrue(document.querySelector('tbody td:nth-child(3)').textContent == 'images diff ');
443
444         document.getElementById('toggle-images').checked = false;
445         // FIXME: We shouldn't need to call updateTogglingImages. Setting checked above should call it.
446         updateTogglingImages();
447         // FIXME: We get extra spaces in the DOM every time we enable/disable image toggling.
448         assertTrue(document.querySelector('tbody td:nth-child(3)').textContent == 'expected actual  diff ');
449         
450         document.getElementById('toggle-images').checked = true;
451         updateTogglingImages();
452         assertTrue(document.querySelector('tbody td:nth-child(3)').textContent == ' images   diff ');
453     });
454     
455     results = mockResults();
456     results.tests['reading-options-from-localstorage.html'] = mockExpectation('IMAGE+TEXT', 'IMAGE+TEXT');
457     runTest(results, function() {
458         assertTrue(window.getComputedStyle(document.querySelector('tbody'), null)['display'] != 'none');
459         assertTrue(document.querySelector('tbody td:nth-child(3)').textContent == 'expected actual  diff ');
460     }, '{"toggle-images":false,"show-expected-failures":true}');
461
462     function enclosingNodeWithTagNameHasClassName(node, tagName, className) {
463         while (node && (!node.tagName || node.localName != tagName))
464             node = node.parentNode;
465         if (!node)
466             return false;
467         return node.className == className;
468     }
469
470     results = mockResults();
471     var subtree = results.tests['foo'] = {}
472     subtree['expected-to-pass-but-crashed.html'] = mockExpectation('PASS', 'CRASH');
473     subtree['expected-to-pass-or-crash-and-crashed.html'] = mockExpectation('PASS CRASH', 'CRASH');
474     subtree['expected-to-pass-but-timeouted.html'] = mockExpectation('PASS', 'CRASH');
475     subtree['expected-to-pass-or-timeout-and-timeouted.html'] = mockExpectation('PASS TIMEOUT', 'TIMEOUT');
476     subtree['expected-fail-but-passed.html'] = mockExpectation('FAIL', 'PASS');
477     subtree['expected-pass-or-fail-and-passed.html'] = mockExpectation('PASS FAIL', 'PASS');
478     runTest(results, function() {
479         assertTrue(!document.getElementById('results-table'));
480
481         var testLinks = document.querySelectorAll('.test-link');
482         assertTrue(testLinks[0].innerText == 'foo/expected-to-pass-but-crashed.html');
483         assertTrue(!enclosingNodeWithTagNameHasClassName(testLinks[0], 'tbody', 'expected'));
484         assertTrue(testLinks[1].innerText == 'foo/expected-to-pass-or-crash-and-crashed.html');
485         assertTrue(enclosingNodeWithTagNameHasClassName(testLinks[1], 'tbody', 'expected'));
486         assertTrue(!enclosingNodeWithTagNameHasClassName(testLinks[0], 'table', 'expected'));
487
488         assertTrue(testLinks[2].innerText == 'foo/expected-to-pass-but-timeouted.html');
489         assertTrue(!enclosingNodeWithTagNameHasClassName(testLinks[2], 'tbody', 'expected'));
490         assertTrue(testLinks[3].innerText == 'foo/expected-to-pass-or-timeout-and-timeouted.html');
491         assertTrue(enclosingNodeWithTagNameHasClassName(testLinks[3], 'tbody', 'expected'));
492         assertTrue(!enclosingNodeWithTagNameHasClassName(testLinks[2], 'table', 'expected'));
493
494         assertTrue(testLinks[4].innerText == 'foo/expected-fail-but-passed.html');
495         assertTrue(!enclosingNodeWithTagNameHasClassName(testLinks[4], 'tbody', 'expected'));
496         assertTrue(testLinks[5].innerText == 'foo/expected-pass-or-fail-and-passed.html');
497         assertTrue(enclosingNodeWithTagNameHasClassName(testLinks[5], 'tbody', 'expected'));
498         assertTrue(!enclosingNodeWithTagNameHasClassName(testLinks[4], 'table', 'expected'));
499     });
500
501     results = mockResults();
502     var subtree = results.tests['foo'] = {}
503     subtree['expected-to-pass-or-crash-and-crashed.html'] = mockExpectation('PASS CRASH', 'CRASH');
504     subtree['expected-to-pass-or-timeout-and-timeouted.html'] = mockExpectation('PASS TIMEOUT', 'TIMEOUT');
505     subtree['expected-pass-or-fail-and-passed.html'] = mockExpectation('PASS FAIL', 'PASS');
506     runTest(results, function() {
507         assertTrue(!document.getElementById('results-table'));
508
509         var testLinks = document.querySelectorAll('.test-link');
510         assertTrue(testLinks[0].innerText == 'foo/expected-to-pass-or-crash-and-crashed.html');
511         assertTrue(enclosingNodeWithTagNameHasClassName(testLinks[0], 'tbody', 'expected'));
512         assertTrue(enclosingNodeWithTagNameHasClassName(testLinks[0], 'div', 'expected'));
513
514         assertTrue(testLinks[1].innerText == 'foo/expected-to-pass-or-timeout-and-timeouted.html');
515         assertTrue(enclosingNodeWithTagNameHasClassName(testLinks[1], 'tbody', 'expected'));
516         assertTrue(enclosingNodeWithTagNameHasClassName(testLinks[1], 'div', 'expected'));
517
518         assertTrue(testLinks[2].innerText == 'foo/expected-pass-or-fail-and-passed.html');
519         assertTrue(enclosingNodeWithTagNameHasClassName(testLinks[2], 'tbody', 'expected'));
520         assertTrue(enclosingNodeWithTagNameHasClassName(testLinks[2], 'div', 'expected'));
521     });
522
523     results = mockResults();
524     var subtree = results.tests['foo'] = {}
525     subtree['bar.html'] = mockExpectation('TEXT', 'PASS');
526     subtree['crash.html'] = mockExpectation('IMAGE', 'CRASH');
527     subtree['flaky-fail.html'] = mockExpectation('PASS TEXT', 'IMAGE PASS');
528     runTest(results, function() {
529         assertTrue(!document.getElementById('results-table'));
530
531         var resultText = document.body.textContent;
532         assertTrue(resultText.indexOf('crash.html') != -1);
533         assertTrue(resultText.indexOf('flaky-fail.html') != -1);
534         assertTrue(resultText.indexOf('crash.html') < resultText.indexOf('flaky-fail.html'));
535     });
536
537     results = mockResults();
538     var subtree = results.tests['foo'] = {}
539     subtree['expected-missing.html'] = mockExpectation('MISSING', 'MISSING');
540     subtree['expected-missing.html'].is_missing_text = true;
541     subtree['expected-missing.html'].is_missing_image = true;
542     subtree['unexpected-missing.html'] = mockExpectation('PASS', 'MISSING');
543     subtree['unexpected-missing.html'].is_missing_text = true;
544     runTest(results, function() {
545         assertTrue(!document.getElementById('results-table'));
546         assertTrue(visibleExpandLinks().length == 1);
547         assertTrue(document.querySelector('#missing-table tbody.expected .test-link').textContent == 'foo/expected-missing.html');
548         assertTrue(document.querySelector('#missing-table tbody.expected').getElementsByClassName('result-link')[0].textContent == 'result');
549         assertTrue(document.querySelector('#missing-table tbody.expected').getElementsByClassName('result-link')[1].textContent == 'png result');
550         assertTrue(document.querySelector('#missing-table tbody:not(.expected) .test-link').textContent == 'foo/unexpected-missing.html');
551         assertTrue(document.querySelector('#missing-table tbody:not(.expected) .result-link').textContent == 'result');
552
553         document.getElementById('show-expected-failures').checked = true;
554         document.getElementById('show-expected-failures').onchange();
555         expandAllExpectations();
556         assertTrue(visibleExpandLinks().length == 2);
557     });
558     
559
560     results = mockResults();
561     var subtree = results.tests['foo'] = {}
562     subtree['bar.html'] = mockExpectation('TEXT', 'FAIL');
563     subtree['bar1.html'] = mockExpectation('TEXT', 'FAIL');
564     subtree['bar2.html'] = mockExpectation('TEXT', 'FAIL');
565
566     runTest(results, function() {
567         if (window.eventSender) {
568             eventSender.keyDown('k'); // previous
569             var testRows = document.querySelectorAll('#results-table tbody');
570             assertTrue(!testRows[0].classList.contains('current'));
571             assertTrue(!testRows[1].classList.contains('current'));
572             assertTrue(testRows[2].classList.contains('current'));
573         }
574     });
575
576     runTest(results, function() {
577         if (window.eventSender) {
578             eventSender.keyDown('j'); // next
579             var testRows = document.querySelectorAll('#results-table tbody');
580             assertTrue(testRows[0].classList.contains('current'));
581             assertTrue(!testRows[1].classList.contains('current'));
582             assertTrue(!testRows[2].classList.contains('current'));
583         }
584     });
585
586     results = mockResults();
587     var subtree = results.tests['foo'] = {}
588     subtree['bar.html'] = mockExpectation('TEXT', 'FAIL');
589     subtree['bar1.html'] = mockExpectation('TEXT', 'FAIL');
590     subtree['bar2.html'] = mockExpectation('TEXT', 'FAIL');
591     subtree['bar3.html'] = mockExpectation('TEXT', 'PASS');
592     subtree['bar4.html'] = mockExpectation('IMAGE', 'PASS');
593
594     runTest(results, function() {
595         assertTrue(document.getElementById('results-table'));
596         assertTrue(visibleExpandLinks().length == 3);
597         
598         if (window.eventSender) {
599             eventSender.keyDown('i', ["metaKey"]);
600             eventSender.keyDown('i', ["shiftKey"]);
601             eventSender.keyDown('i', ["ctrlKey"]);
602             var testRows = document.querySelectorAll('tbody');
603             assertTrue(!testRows[0].classList.contains('current'));
604             assertTrue(!testRows[1].classList.contains('current'));
605             assertTrue(!testRows[2].classList.contains('current'));
606
607             eventSender.keyDown('i'); // first
608             assertTrue(testRows[0].classList.contains('current'));
609             assertTrue(!testRows[1].classList.contains('current'));
610             assertTrue(!testRows[2].classList.contains('current'));
611
612             eventSender.keyDown('j', ["metaKey"]);
613             eventSender.keyDown('j', ["shiftKey"]);
614             eventSender.keyDown('j', ["ctrlKey"]);
615             assertTrue(testRows[0].classList.contains('current'));
616             assertTrue(!testRows[1].classList.contains('current'));
617             assertTrue(!testRows[2].classList.contains('current'));
618
619             eventSender.keyDown('j'); // next
620             assertTrue(!testRows[0].classList.contains('current'));
621             assertTrue(testRows[1].classList.contains('current'));
622             assertTrue(!testRows[2].classList.contains('current'));
623
624             eventSender.keyDown('k', ["metaKey"]);
625             eventSender.keyDown('k', ["shiftKey"]);
626             eventSender.keyDown('k', ["ctrlKey"]);
627             assertTrue(!testRows[0].classList.contains('current'));
628             assertTrue(testRows[1].classList.contains('current'));
629             assertTrue(!testRows[2].classList.contains('current'));
630
631             eventSender.keyDown('k'); // previous
632             assertTrue(testRows[0].classList.contains('current'));
633             assertTrue(!testRows[1].classList.contains('current'));
634             assertTrue(!testRows[2].classList.contains('current'));
635
636             eventSender.keyDown('l', ["metaKey"]);
637             eventSender.keyDown('l', ["shiftKey"]);
638             eventSender.keyDown('l', ["ctrlKey"]);
639             assertTrue(testRows[0].classList.contains('current'));
640             assertTrue(!testRows[1].classList.contains('current'));
641             assertTrue(!testRows[2].classList.contains('current'));
642
643             eventSender.keyDown('l'); // last
644             assertTrue(!testRows[0].classList.contains('current'));
645             assertTrue(!testRows[1].classList.contains('current'));
646             assertTrue(testRows[4].classList.contains('current'));
647
648             var flaggedTestsTextbox = document.getElementById('flagged-tests');
649
650             eventSender.keyDown('f'); // flag
651             assertTrue(flaggedTestsTextbox.innerText == 'foo/bar4.html');
652             eventSender.keyDown('f'); // unflag
653
654             eventSender.keyDown('i'); // first
655
656             eventSender.keyDown('e', ["metaKey"]);
657             eventSender.keyDown('e', ["shiftKey"]);
658             eventSender.keyDown('e', ["ctrlKey"]);
659             var expandLinks = document.querySelectorAll('.expand-button-text');
660             assertTrue(!isExpanded(expandLinks[0]));
661
662             eventSender.keyDown('e'); // expand
663             assertTrue(isExpanded(expandLinks[0]));
664
665             eventSender.keyDown('c', ["metaKey"]);
666             eventSender.keyDown('c', ["shiftKey"]);
667             eventSender.keyDown('c', ["ctrlKey"]);
668             assertTrue(isExpanded(expandLinks[0]));
669
670             eventSender.keyDown('c'); // collapse
671             assertTrue(isCollapsed(expandLinks[0]));
672
673             eventSender.keyDown('f', ["metaKey"]);
674             eventSender.keyDown('f', ["shiftKey"]);
675             eventSender.keyDown('f', ["ctrlKey"]);
676             assertTrue(flaggedTestsTextbox.innerText == '');
677
678             eventSender.keyDown('f'); // flag
679             assertTrue(flaggedTestsTextbox.innerText == 'foo/bar.html');
680
681             eventSender.keyDown('j'); // next
682             eventSender.keyDown('f'); // flag
683             assertTrue(flaggedTestsTextbox.innerText == 'foo/bar.html\nfoo/bar1.html');
684
685             document.getElementById('use-newlines').checked = false;
686             TestNavigator.updateFlaggedTests();
687             assertTrue(flaggedTestsTextbox.innerText == 'foo/bar.html foo/bar1.html');
688
689             eventSender.keyDown('f'); // unflag
690             assertTrue(flaggedTestsTextbox.innerText == 'foo/bar.html');
691
692             eventSender.keyDown('k'); // previous
693             eventSender.keyDown('f'); // flag
694             assertTrue(flaggedTestsTextbox.innerText == '');
695         }
696     });
697
698     results = mockResults();
699     var subtree = results.tests['foo'] = {}
700     subtree['bar.html'] = mockExpectation('TEXT', 'PASS');
701     subtree['bar-1.html'] = mockExpectation('TEXT', 'CRASH');
702     subtree['bar-2.html'] = mockExpectation('PASS', 'IMAGE');
703     subtree['bar-3.html'] = mockExpectation('PASS', 'TEXT');
704     subtree['bar-4.html'] = mockExpectation('TEXT', 'TEXT');
705     subtree['bar-5.html'] = mockExpectation('TEXT', 'IMAGE+TEXT');
706     subtree['bar-stderr-expected.html'] = mockExpectation('IMAGE', 'IMAGE');
707     subtree['bar-stderr-expected.html'].has_stderr = true;
708     subtree['bar-expected-timeout.html'] = mockExpectation('TIMEOUT', 'TIMEOUT');
709     subtree['bar-expected-crash.html'] = mockExpectation('CRASH', 'CRASH');
710     subtree['bar-missing.html'] = mockExpectation('TEXT', 'MISSING');
711     subtree['bar-missing.html'].is_missing_text = true;
712     runTest(results, function() {
713         var titles = document.getElementsByTagName('h1');
714         assertTrue(titles[0].textContent == 'Tests that crashed (1): flag all');
715         assertTrue(titles[1].textContent == 'Tests that failed text/pixel/audio diff (3): flag all');
716         assertTrue(titles[2].textContent == 'Tests that had no expected results (probably new) (1): flag all');
717         assertTrue(titles[3].textContent == 'Tests that timed out (0): flag all');
718         assertTrue(titles[4].textContent == 'Tests that had stderr output (1): flag all');
719         assertTrue(titles[5].textContent == 'Tests expected to fail but passed (1): flag all');
720
721         document.getElementById('show-expected-failures').checked = true;
722         document.getElementById('show-expected-failures').onchange();
723
724         assertTrue(titles[0].textContent == 'Tests that crashed (2): flag all');
725         assertTrue(titles[1].textContent == 'Tests that failed text/pixel/audio diff (5): flag all');
726         assertTrue(titles[2].textContent == 'Tests that had no expected results (probably new) (1): flag all');
727         assertTrue(titles[3].textContent == 'Tests that timed out (1): flag all');
728         assertTrue(titles[4].textContent == 'Tests that had stderr output (1): flag all');
729         assertTrue(titles[5].textContent == 'Tests expected to fail but passed (1): flag all');
730     });
731
732     results = mockResults();
733     var subtree = results.tests['foo'] = {}
734     subtree['bar.html'] = mockExpectation('', 'PASS TEXT');
735     subtree['bar-1.html'] = mockExpectation('', 'TEXT IMAGE');
736     subtree['bar-2.html'] = mockExpectation('IMAGE TEXT', 'TEXT IMAGE');
737     subtree['bar-3.html'] = mockExpectation('PASS TEXT', 'TEXT PASS');
738     runTest(results, function() {
739         var titles = document.getElementsByTagName('h1');
740         assertTrue(titles[0].textContent == 'Tests that failed text/pixel/audio diff (1): flag all');
741         assertTrue(titles[1].textContent =='Flaky tests (failed the first run and passed on retry) (1): flag all');
742
743         assertTrue(document.querySelectorAll('#results-table tbody').length == 2);
744         assertTrue(document.querySelectorAll('#flaky-tests-table tbody').length == 2);
745     });
746
747     results = mockResults();
748     var subtree = results.tests['foo'] = {}
749     subtree['bar.html'] = mockExpectation('TEXT', 'IMAGE');
750     subtree['bar1.html'] = mockExpectation('TEXT', 'TEXT');
751     subtree['bar2.html'] = mockExpectation('TEXT', 'TEXT');
752     runTest(results, function() {
753         flagAll(document.querySelector('.flag-all'));
754         var flaggedTestsTextbox = document.getElementById('flagged-tests');
755         assertTrue(flaggedTestsTextbox.innerText == 'foo/bar.html');
756
757         document.getElementById('show-expected-failures').checked = true;
758         document.getElementById('show-expected-failures').onchange();
759
760         flagAll(document.querySelector('.flag-all'));
761         assertTrue(flaggedTestsTextbox.innerText == 'foo/bar.html\nfoo/bar1.html\nfoo/bar2.html');
762
763         unflag(document.querySelector('.flag'));
764         assertTrue(flaggedTestsTextbox.innerText == 'foo/bar1.html\nfoo/bar2.html');
765     });
766
767     results = mockResults();
768     var subtree = results.tests['foo'] = {}
769     subtree['bar.html'] = mockExpectation('TEXT', 'IMAGE');
770     subtree['bar1.html'] = mockExpectation('TEXT', 'IMAGE');
771     runTest(results, function() {
772         flagAll(document.querySelector('.flag-all'));
773         var flaggedTestsTextbox = document.getElementById('flagged-tests');
774         assertTrue(flaggedTestsTextbox.innerText == 'foo/bar.html\nfoo/bar1.html');
775     }, '{"use-newlines":true}');
776
777     results = mockResults();
778     var subtree = results.tests['foo'] = {}
779     subtree['bar.html'] = mockExpectation('TEXT', 'IMAGE');
780     subtree['bar1.html'] = mockExpectation('TEXT', 'IMAGE');
781     runTest(results, function() {
782         flagAll(document.querySelector('.flag-all'));
783         var flaggedTestsTextbox = document.getElementById('flagged-tests');
784         assertTrue(flaggedTestsTextbox.innerText == 'foo/bar.html foo/bar1.html');
785     }, '{"use-newlines":false}');
786
787     results = mockResults();
788     results.tests['foo/bar-image.html'] = mockExpectation('PASS', 'TEXT IMAGE+TEXT');
789     results.pixel_tests_enabled = false;
790     runTest(results, function() {
791         assertTrue(document.querySelector('tbody td:nth-child(3) a').getAttribute('href') == 'retries/foo/bar-image-diffs.html');
792     });
793
794     results = mockResults();
795     results.tests['foo/bar-image.html'] = mockExpectation('PASS', 'TEXT IMAGE');
796     results.pixel_tests_enabled = false;
797     runTest(results, function() {
798         assertTrue(!document.getElementById('results-table'));
799         assertTrue(document.querySelector('#flaky-tests-table td:nth-child(3) a').getAttribute('href') == 'retries/foo/bar-image-diffs.html');
800     });
801
802     results = mockResults();
803     results.tests['foo'] = mockExpectation('PASS', 'TEXT');
804     results.tests['foo'].has_repaint_overlay = true;
805     runTest(results, function() {
806         assertTrue(document.querySelector('tbody td:nth-child(2)').textContent.indexOf('overlay') != -1);
807     })
808
809     document.body.innerHTML = '<pre>' + g_log.join('\n') + '</pre>';
810 }
811
812 var originalGeneratePage = generatePage;
813 generatePage = runTests;