OLD | NEW |
---|---|
(Empty) | |
1 <!DOCTYPE html> | |
Dirk Pranke
2014/07/15 20:50:00
There's a fair amount of duplication between dashb
patro
2014/07/16 14:37:36
Yes both dashboard.html and results.html can share
| |
2 <style> | |
3 html { | |
4 height: 100%; | |
5 } | |
6 body { | |
7 margin: 0; | |
8 font-family: Helvetica, sans-serif; | |
9 font-size: 11pt; | |
10 display: -webkit-flex; | |
11 -webkit-flex-direction: column; | |
12 height: 100%; | |
13 } | |
14 | |
15 body > * { | |
16 margin-left: 4px; | |
17 margin-top: 4px; | |
18 } | |
19 | |
20 h1 { | |
21 font-size: 14pt; | |
22 margin-top: 1.5em; | |
23 } | |
24 | |
25 p { | |
26 margin-bottom: 0.3em; | |
27 } | |
28 | |
29 tr { | |
30 background-color: white; | |
31 } | |
32 | |
33 tr:hover { | |
34 background-color: #999999; | |
35 } | |
36 | |
37 tr:not(.results-row) td { | |
38 white-space: nowrap; | |
39 } | |
40 | |
41 tr:not(.results-row) td:first-of-type { | |
42 white-space: normal; | |
43 } | |
44 | |
45 td:not(:first-of-type) { | |
46 text-transform: lowercase; | |
47 } | |
48 | |
49 td { | |
50 padding: 1px 4px; | |
51 } | |
52 | |
53 th:empty, td:empty { | |
54 padding: 0; | |
55 } | |
56 | |
57 th { | |
58 -webkit-user-select: none; | |
59 -moz-user-select: none; | |
60 } | |
61 | |
62 .content-container { | |
63 -webkit-flex: 1; | |
64 min-height: -webkit-min-content; | |
65 overflow: auto; | |
66 } | |
67 | |
68 .note { | |
69 color: gray; | |
70 font-size: smaller; | |
71 } | |
72 | |
73 .results-row { | |
74 background-color: white; | |
75 } | |
76 | |
77 .results-row iframe, .results-row img { | |
78 width: 800px; | |
79 height: 600px; | |
80 } | |
81 | |
82 .results-row[data-expanded="false"] { | |
83 display: none; | |
84 } | |
85 | |
86 #toolbar { | |
87 position: fixed; | |
88 padding: 4px; | |
89 top: 2px; | |
90 right: 2px; | |
91 text-align: right; | |
92 background-color: rgba(255, 255, 255, 0.85); | |
93 border: 1px solid silver; | |
94 border-radius: 4px; | |
95 } | |
96 | |
97 .expand-button { | |
98 background-color: white; | |
99 width: 11px; | |
100 height: 12px; | |
101 border: 1px solid gray; | |
102 display: inline-block; | |
103 margin: 0 3px 0 0; | |
104 position: relative; | |
105 cursor: default; | |
106 } | |
107 | |
108 .current { | |
109 color: red; | |
110 } | |
111 | |
112 .current .expand-button { | |
113 border-color: red; | |
114 } | |
115 | |
116 .expand-button-text { | |
117 position: absolute; | |
118 top: -0.3em; | |
119 left: 1px; | |
120 } | |
121 | |
122 tbody .flag { | |
123 display: none; | |
124 } | |
125 | |
126 tbody.flagged .flag { | |
127 display: inline; | |
128 } | |
129 | |
130 .stopped-running-early-message { | |
131 border: 3px solid #d00; | |
132 font-weight: bold; | |
133 display: inline-block; | |
134 padding: 3px; | |
135 } | |
136 | |
137 .result-container { | |
138 display: inline-block; | |
139 border: 1px solid gray; | |
140 margin: 4px; | |
141 } | |
142 | |
143 .result-container iframe, .result-container img { | |
144 border: 0; | |
145 vertical-align: top; | |
146 } | |
147 | |
148 .label { | |
149 padding-left: 3px; | |
150 font-weight: bold; | |
151 font-size: small; | |
152 background-color: silver; | |
153 } | |
154 | |
155 .pixel-zoom-container { | |
156 position: fixed; | |
157 top: 0; | |
158 left: 0; | |
159 width: 96%; | |
160 margin: 10px; | |
161 padding: 10px; | |
162 display: -webkit-box; | |
163 display: -moz-box; | |
164 pointer-events: none; | |
165 background-color: silver; | |
166 border-radius: 20px; | |
167 border: 1px solid gray; | |
168 box-shadow: 0 0 5px rgba(0, 0, 0, 0.75); | |
169 } | |
170 | |
171 .pixel-zoom-container > * { | |
172 -webkit-box-flex: 1; | |
173 -moz-box-flex: 1; | |
174 border: 1px solid black; | |
175 margin: 4px; | |
176 overflow: hidden; | |
177 background-color: white; | |
178 } | |
179 | |
180 .pixel-zoom-container .scaled-image-container { | |
181 position: relative; | |
182 overflow: hidden; | |
183 width: 100%; | |
184 height: 400px; | |
185 } | |
186 | |
187 .scaled-image-container > img { | |
188 position: absolute; | |
189 top: 0; | |
190 left: 0; | |
191 image-rendering: -webkit-optimize-contrast; | |
192 } | |
193 .test-pass { | |
194 background-color:rgb(0,255,0); | |
195 } | |
196 .test-image-fail { | |
197 background-color:rgb(0,128,255); | |
198 } | |
199 .test-text-fail { | |
200 background-color:rgb(250,100,100); | |
201 } | |
202 .test-image-text-fail { | |
203 background-color:rgb(161,128,250); | |
204 } | |
205 .test-flaky { | |
206 background-color:rgb(255,0,255); | |
207 } | |
208 .test-missing { | |
209 background-color:rgb(255,255,255); | |
210 } | |
211 .test-fail { | |
212 background-color:rgb(255,0,0); | |
213 } | |
214 | |
215 #flagged-tests { | |
216 margin: 1px; | |
217 padding: 5px; | |
218 height: 100px; | |
219 } | |
220 | |
221 #flagged-test-container h2 { | |
222 display: inline-block; | |
223 margin: 0 10px 0 0; | |
224 } | |
225 </style> | |
226 <style id="unexpected-pass-style"></style> | |
227 <style id="flaky-failures-style"></style> | |
228 <style id="stderr-style"></style> | |
229 <style id="unexpected-style"></style> | |
230 | |
231 <script> | |
232 var g_state; | |
233 function globalState() | |
234 { | |
235 if (!g_state) { | |
236 g_state = { | |
237 crashTests: [], | |
238 leakTests: [], | |
239 flakyPassTests: [], | |
240 hasHttpTests: false, | |
241 hasImageFailures: false, | |
242 hasTextFailures: false, | |
243 missingResults: [], | |
244 results: {}, | |
245 failingTests: [], | |
246 testsWithStderr: [], | |
247 timeoutTests: [], | |
248 unexpectedPassTests: [] | |
249 } | |
250 } | |
251 return g_state; | |
252 } | |
253 | |
254 function ADD_RESULTS(input) | |
255 { | |
256 globalState().results = input; | |
257 } | |
258 </script> | |
259 | |
260 <script src="archived_results.json"></script> | |
261 | |
262 <script> | |
263 | |
264 function matchesSelector(node, selector) | |
265 { | |
266 if (node.webkitMatchesSelector) | |
267 return node.webkitMatchesSelector(selector); | |
268 | |
269 if (node.mozMatchesSelector) | |
270 return node.mozMatchesSelector(selector); | |
271 } | |
272 | |
273 function parentOfType(node, selector) | |
274 { | |
275 while (node = node.parentNode) { | |
276 if (matchesSelector(node, selector)) | |
277 return node; | |
278 } | |
279 return null; | |
280 } | |
281 | |
282 function remove(node) | |
283 { | |
284 node.parentNode.removeChild(node); | |
285 } | |
286 | |
287 function forEach(nodeList, handler) | |
288 { | |
289 Array.prototype.forEach.call(nodeList, handler); | |
290 } | |
291 | |
292 function resultIframe(src) | |
293 { | |
294 // FIXME: use audio tags for AUDIO tests? | |
295 var layoutTestsIndex = src.indexOf('LayoutTests'); | |
296 var name; | |
297 if (layoutTestsIndex != -1) { | |
298 var hasTrac = src.indexOf('trac.webkit.org') != -1; | |
299 var prefix = hasTrac ? 'trac.webkit.org/.../' : ''; | |
Dirk Pranke
2014/07/15 20:50:00
links to trac.webkit.org can't be right ... is thi
| |
300 name = prefix + src.substring(layoutTestsIndex + 'LayoutTests/'.length); | |
301 } else { | |
302 var lastDashIndex = src.lastIndexOf('-pretty'); | |
303 if (lastDashIndex == -1) | |
304 lastDashIndex = src.lastIndexOf('-'); | |
305 name = src.substring(lastDashIndex + 1); | |
306 } | |
307 | |
308 var tagName = (src.lastIndexOf('.png') == -1) ? 'iframe' : 'img'; | |
309 | |
310 if (tagName != 'img') | |
311 src += '?format=txt'; | |
312 return '<div class=result-container><div class=label>' + name + '</div><' + tagName + ' src="' + src + '"></' + tagName + '></div>'; | |
313 } | |
314 | |
315 function togglingImage(prefix) | |
316 { | |
317 return '<div class=result-container><div class="label imageText"></div><img class=animatedImage data-prefix="' + | |
318 prefix + '"></img></div>'; | |
319 } | |
320 | |
321 function appendHTML(node, html) | |
322 { | |
323 if (node.insertAdjacentHTML) | |
324 node.insertAdjacentHTML('beforeEnd', html); | |
325 else | |
326 node.innerHTML += html; | |
327 } | |
328 | |
329 function shouldUseTracLinks() | |
Dirk Pranke
2014/07/15 20:50:00
same comment
| |
330 { | |
331 return !globalState().results.layout_tests_dir || !location.toString().index Of('file://') == 0; | |
332 } | |
333 | |
334 function testLinkTarget(test) | |
335 { | |
336 var target; | |
337 if (shouldUseTracLinks()) { | |
338 var revision = globalState().results.revision; | |
339 target = 'http://src.chromium.org/viewvc/blink/trunk/LayoutTests/' + tes t; | |
340 if (revision) | |
341 target += '?pathrev=' + revision; | |
342 target += '#l1'; | |
343 } else | |
344 target = globalState().results.layout_tests_dir + '/' + test; | |
345 return target; | |
346 } | |
347 | |
348 function testLink(test) | |
349 { | |
350 var target = testLinkTarget(test); | |
351 return '<a class=test-link href="' + target + '">' + test + '</a>'; | |
352 } | |
353 | |
354 function resultLink(testPrefix, suffix, contents) | |
355 { | |
356 return '<a class=result-link href="' + testPrefix + suffix + '" data-prefix= "' + testPrefix + '">' + contents + '</a> '; | |
357 } | |
358 | |
359 function processGlobalStateFor(testObject) | |
360 { | |
361 var test = testObject.name; | |
362 if (testObject.has_stderr) | |
363 globalState().testsWithStderr.push(testObject); | |
364 | |
365 globalState().hasHttpTests = globalState().hasHttpTests || test.indexOf('htt p/') == 0; | |
366 | |
367 var actual = testObject.actual; | |
368 var expected = testObject.expected || 'PASS'; | |
369 | |
370 if (actual == 'MISSING') { | |
371 // FIXME: make sure that new-run-webkit-tests spits out an -actual.txt f ile for | |
372 // tests with MISSING results. | |
373 globalState().missingResults.push(testObject); | |
374 return; | |
375 } | |
376 | |
377 var actualTokens = actual.split(' '); | |
378 var passedWithImageOnlyFailureInRetry = actualTokens[0] == 'TEXT' && actualT okens[1] == 'IMAGE'; | |
379 if (actualTokens[1] && actual.indexOf('PASS') != -1 || (!globalState().resul ts.pixel_tests_enabled && passedWithImageOnlyFailureInRetry)) { | |
380 globalState().flakyPassTests.push(testObject); | |
381 return; | |
382 } | |
383 | |
384 if (actual == 'PASS' && expected != 'PASS') { | |
385 if (expected != 'IMAGE' || (globalState().results.pixel_tests_enabled || testObject.reftest_type)) { | |
386 globalState().unexpectedPassTests.push(testObject); | |
387 } | |
388 return; | |
389 } | |
390 | |
391 if (actual == 'CRASH') { | |
392 globalState().crashTests.push(testObject); | |
393 return; | |
394 } | |
395 | |
396 if (actual == 'LEAK') { | |
397 globalState().leakTests.push(testObject); | |
398 return; | |
399 } | |
400 | |
401 if (actual == 'TIMEOUT') { | |
402 globalState().timeoutTests.push(testObject); | |
403 return; | |
404 } | |
405 | |
406 globalState().failingTests.push(testObject); | |
407 } | |
408 | |
409 function getResultLink(index) | |
410 { | |
411 if(index < globalState().results.result_links.length) | |
412 return globalState().results.result_links[index]; | |
413 else | |
414 return ''; | |
415 } | |
416 | |
417 function processArchivedResults(archivedResults) | |
418 { | |
419 var result = ''; | |
420 var i = 1; | |
421 for (var i = 0; i < archivedResults.length; i++) { | |
422 switch(archivedResults[i]) { | |
423 case "PASS": | |
424 result += '<td class=test-pass>'; | |
425 break; | |
426 case "IMAGE": | |
427 result += '<td class=test-image-fail>'; | |
428 break; | |
429 case "TEXT": | |
430 result += '<td class=test-text-fail>'; | |
431 break; | |
432 case "IMAGE+TEXT": | |
433 result += '<td class=test-image-text-fail>'; | |
434 break; | |
435 case "NOTFOUND": | |
436 result += '<td class=test-missing>'; | |
437 break; | |
438 case "SKIP": | |
439 result += '<td class=test-missing>'; | |
440 break; | |
441 default: | |
442 result += '<td class=test-fail>'; | |
443 } | |
444 result += '<a href="' + getResultLink(i) + '">' + (i+1).toString() + '< /a>' + '</td>'; | |
445 } | |
446 | |
447 return result; | |
448 } | |
449 | |
450 function tableRow(testObject) | |
451 { | |
452 var row = '<tbody class="' + (testObject.is_unexpected ? '' : 'expected') + '"'; | |
453 if (testObject.reftest_type && testObject.reftest_type.indexOf('!=') != -1) | |
454 row += ' mismatchreftest=true'; | |
455 row += '><tr>'; | |
456 | |
457 row += '<td>' + testLink(testObject.name) + '</td>'; | |
458 | |
459 var archivedResults = testObject.archived_results; | |
460 row += processArchivedResults(archivedResults); | |
461 row += '</tr></tbody>'; | |
462 return row; | |
463 } | |
464 | |
465 function forEachTest(handler, opt_tree, opt_prefix) | |
466 { | |
467 var tree = opt_tree || globalState().results.tests; | |
468 var prefix = opt_prefix || ''; | |
469 | |
470 for (var key in tree) { | |
471 var newPrefix = prefix ? (prefix + '/' + key) : key; | |
472 if ('actual' in tree[key]) { | |
473 var testObject = tree[key]; | |
474 testObject.name = newPrefix; | |
475 handler(testObject); | |
476 } else | |
477 forEachTest(handler, tree[key], newPrefix); | |
478 } | |
479 } | |
480 | |
481 function hasUnexpected(tests) | |
482 { | |
483 return tests.some(function (test) { return test.is_unexpected; }); | |
484 } | |
485 | |
486 function updateTestlistCounts() | |
487 { | |
488 forEach(document.querySelectorAll('.test-list-count'), function(count) { | |
489 var container = parentOfType(count, 'div'); | |
490 var testContainers; | |
491 if (onlyShowUnexpectedFailures()) | |
492 testContainers = container.querySelectorAll('tbody:not(.expected)'); | |
493 else | |
494 testContainers = container.querySelectorAll('tbody'); | |
495 | |
496 count.textContent = testContainers.length; | |
497 | |
498 }) | |
499 } | |
500 | |
501 function testListHeaderHtml(header) | |
502 { | |
503 return '<h1>' + header + ' (<span class=test-list-count></span>): </h1>'; | |
504 } | |
505 | |
506 function testList(tests, header, tableId) | |
507 { | |
508 tests.sort(); | |
509 | |
510 var html = '<div' + ((!hasUnexpected(tests) && tableId != 'stderr-table') ? ' class=expected' : '') + ' id=' + tableId + '>' + | |
511 testListHeaderHtml(header) + '<table>'; | |
512 | |
513 // FIXME: Include this for all testLists. | |
514 if (tableId == 'passes-table') | |
515 html += '<thead><th>test</th><th>expected</th></thead>'; | |
516 | |
517 for (var i = 0; i < tests.length; i++) { | |
518 var testObject = tests[i]; | |
519 var test = testObject.name; | |
520 html += '<tbody class="' + ((testObject.is_unexpected || tableId == 'std err-table') ? '' : 'expected') + '"><tr><td>' + | |
521 testLink(test) + | |
522 '</td>'; | |
523 | |
524 html += processArchivedResults(testObject.archived_results) | |
525 html += '</tr></tbody>'; | |
526 } | |
527 html += '</table></div>'; | |
528 return html; | |
529 } | |
530 | |
531 function toArray(nodeList) | |
532 { | |
533 return Array.prototype.slice.call(nodeList); | |
534 } | |
535 | |
536 function trim(string) | |
537 { | |
538 return string.replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''); | |
539 } | |
540 | |
541 // Just a namespace for code management. | |
542 var TableSorter = {}; | |
543 | |
544 TableSorter._forwardArrow = '<svg style="width:10px;height:10px"><polygon points ="0,0 10,0 5,10" style="fill:#ccc"></svg>'; | |
545 | |
546 TableSorter._backwardArrow = '<svg style="width:10px;height:10px"><polygon point s="0,10 10,10 5,0" style="fill:#ccc"></svg>'; | |
547 | |
548 TableSorter._sortedContents = function(header, arrow) | |
549 { | |
550 return arrow + ' ' + trim(header.textContent) + ' ' + arrow; | |
551 } | |
552 | |
553 TableSorter._updateHeaderClassNames = function(newHeader) | |
554 { | |
555 var sortHeader = document.querySelector('.sortHeader'); | |
556 if (sortHeader) { | |
557 if (sortHeader == newHeader) { | |
558 var isAlreadyReversed = sortHeader.classList.contains('reversed'); | |
559 if (isAlreadyReversed) | |
560 sortHeader.classList.remove('reversed'); | |
561 else | |
562 sortHeader.classList.add('reversed'); | |
563 } else { | |
564 sortHeader.textContent = sortHeader.textContent; | |
565 sortHeader.classList.remove('sortHeader'); | |
566 sortHeader.classList.remove('reversed'); | |
567 } | |
568 } | |
569 | |
570 newHeader.classList.add('sortHeader'); | |
571 } | |
572 | |
573 TableSorter._textContent = function(tbodyRow, column) | |
574 { | |
575 return tbodyRow.querySelectorAll('td')[column].textContent; | |
576 } | |
577 | |
578 TableSorter._sortRows = function(newHeader, reversed) | |
579 { | |
580 var testsTable = document.getElementById('results-table'); | |
581 var headers = toArray(testsTable.querySelectorAll('th')); | |
582 var sortColumn = headers.indexOf(newHeader); | |
583 | |
584 var rows = toArray(testsTable.querySelectorAll('tbody')); | |
585 | |
586 rows.sort(function(a, b) { | |
587 // Only need to support lexicographic sort for now. | |
588 var aText = TableSorter._textContent(a, sortColumn); | |
589 var bText = TableSorter._textContent(b, sortColumn); | |
590 | |
591 // Forward sort equal values by test name. | |
592 if (sortColumn && aText == bText) { | |
593 var aTestName = TableSorter._textContent(a, 0); | |
594 var bTestName = TableSorter._textContent(b, 0); | |
595 if (aTestName == bTestName) | |
596 return 0; | |
597 return aTestName < bTestName ? -1 : 1; | |
598 } | |
599 | |
600 if (reversed) | |
601 return aText < bText ? 1 : -1; | |
602 else | |
603 return aText < bText ? -1 : 1; | |
604 }); | |
605 | |
606 for (var i = 0; i < rows.length; i++) | |
607 testsTable.appendChild(rows[i]); | |
608 } | |
609 | |
610 TableSorter.sortColumn = function(columnNumber) | |
611 { | |
612 var newHeader = document.getElementById('results-table').querySelectorAll('t h')[columnNumber]; | |
613 TableSorter._sort(newHeader); | |
614 } | |
615 | |
616 TableSorter.handleClick = function(e) | |
617 { | |
618 var newHeader = e.target; | |
619 if (newHeader.localName != 'th') | |
620 return; | |
621 TableSorter._sort(newHeader); | |
622 } | |
623 | |
624 TableSorter._sort = function(newHeader) | |
625 { | |
626 TableSorter._updateHeaderClassNames(newHeader); | |
627 | |
628 var reversed = newHeader.classList.contains('reversed'); | |
629 var sortArrow = reversed ? TableSorter._backwardArrow : TableSorter._forward Arrow; | |
630 newHeader.innerHTML = TableSorter._sortedContents(newHeader, sortArrow); | |
631 | |
632 TableSorter._sortRows(newHeader, reversed); | |
633 } | |
634 | |
635 document.addEventListener('keypress', TestNavigator.handleKeyEvent, false); | |
636 | |
637 function onlyShowUnexpectedFailures() | |
638 { | |
639 return !document.getElementById('show-expected-failures').checked; | |
640 } | |
641 | |
642 function handleStderrChange() | |
643 { | |
644 OptionWriter.save(); | |
645 document.getElementById('stderr-style').textContent = document.getElementByI d('show-stderr').checked ? | |
646 '' : '#stderr-table { display: none; }'; | |
647 } | |
648 | |
649 function handleUnexpectedPassesChange() | |
650 { | |
651 OptionWriter.save(); | |
652 document.getElementById('unexpected-pass-style').textContent = document.getE lementById('show-unexpected-passes').checked ? | |
653 '' : '#passes-table { display: none; }'; | |
654 } | |
655 | |
656 function handleFlakyFailuresChange() | |
657 { | |
658 OptionWriter.save(); | |
659 document.getElementById('flaky-failures-style').textContent = document.getEl ementById('show-flaky-failures').checked ? | |
660 '' : '.flaky { display: none; }'; | |
661 } | |
662 | |
663 function handleUnexpectedResultsChange() | |
664 { | |
665 OptionWriter.save(); | |
666 updateExpectedFailures(); | |
667 } | |
668 | |
669 function updateExpectedFailures() | |
670 { | |
671 document.getElementById('unexpected-style').textContent = onlyShowUnexpected Failures() ? | |
672 '.expected { display: none; }' : ''; | |
673 | |
674 updateTestlistCounts(); | |
675 TestNavigator.onlyShowUnexpectedFailuresChanged(); | |
676 } | |
677 | |
678 var OptionWriter = {}; | |
679 | |
680 OptionWriter._key = 'run-webkit-tests-options'; | |
681 | |
682 OptionWriter.save = function() | |
683 { | |
684 var options = document.querySelectorAll('label input'); | |
685 var data = {}; | |
686 for (var i = 0, len = options.length; i < len; i++) { | |
687 var option = options[i]; | |
688 data[option.id] = option.checked; | |
689 } | |
690 localStorage.setItem(OptionWriter._key, JSON.stringify(data)); | |
691 } | |
692 | |
693 OptionWriter.apply = function() | |
694 { | |
695 var json = localStorage.getItem(OptionWriter._key); | |
696 if (!json) { | |
697 updateAllOptions(); | |
698 return; | |
699 } | |
700 | |
701 var data = JSON.parse(json); | |
702 for (var id in data) { | |
703 var input = document.getElementById(id); | |
704 if (input) | |
705 input.checked = data[id]; | |
706 } | |
707 updateAllOptions(); | |
708 } | |
709 | |
710 function updateAllOptions() | |
711 { | |
712 forEach(document.querySelectorAll('input'), function(input) { input.onchange (); }); | |
713 } | |
714 | |
715 function failingTestsTable(tests, title, id) | |
716 { | |
717 if (!tests.length) | |
718 return ''; | |
719 | |
720 var numberofUnexpectedFailures = 0; | |
721 var tableRowHtml = ''; | |
722 for (var i = 0; i < tests.length; i++){ | |
723 tableRowHtml += tableRow(tests[i]); | |
724 if (tests[i].is_unexpected) | |
725 numberofUnexpectedFailures++; | |
726 } | |
727 | |
728 var className = ''; | |
729 if (id) | |
730 className += id.split('-')[0]; | |
731 if (!hasUnexpected(tests)) | |
732 className += ' expected'; | |
733 | |
734 var header = '<div'; | |
735 if (className) | |
736 header += ' class="' + className + '"'; | |
737 | |
738 header += '>' + testListHeaderHtml(title) + | |
739 '<table id="' + id + '"><thead><tr>' + | |
740 '<th>test</th>'; | |
741 | |
742 header += '</tr></thead>'; | |
743 | |
744 | |
745 return header + tableRowHtml + '</table></div>'; | |
746 } | |
747 | |
748 function generatePage() | |
749 { | |
750 forEachTest(processGlobalStateFor); | |
751 | |
752 var html = '<div><div id=toolbar>' + | |
753 '<div id=container>Show: '+ | |
754 '<label><input id="show-expected-failures" type=checkbox onchange="handl eUnexpectedResultsChange()">expected failures</label>' + | |
755 '<label><input id="show-flaky-failures" type=checkbox onchange="handleFl akyFailuresChange()">flaky failures</label>' + | |
756 '<label><input id="show-unexpected-passes" type=checkbox onchange="handl eUnexpectedPassesChange()">unexpected passes</label>' + | |
757 '<label><input id="show-stderr" type=checkbox onchange="handleStderrChan ge()">stderr</label>' + | |
758 '</div></div>'; | |
759 | |
760 if (globalState().results.interrupted) | |
761 html += "<p class='stopped-running-early-message'>Testing exited early.< /p>" | |
762 | |
763 if (globalState().crashTests.length) | |
764 html += testList(globalState().crashTests, 'Tests that crashed', 'crash- tests-table'); | |
765 | |
766 if (globalState().leakTests.length) | |
767 html += testList(globalState().leakTests, 'Tests that leaked', 'leak-tes ts-table'); | |
768 | |
769 html += failingTestsTable(globalState().failingTests, | |
770 'Tests that failed text/pixel/audio diff', 'results-table'); | |
771 | |
772 html += failingTestsTable(globalState().missingResults, | |
773 'Tests that had no expected results (probably new)', 'missing-table'); | |
774 | |
775 if (globalState().timeoutTests.length) | |
776 html += testList(globalState().timeoutTests, 'Tests that timed out', 'ti meout-tests-table'); | |
777 | |
778 if (globalState().testsWithStderr.length) | |
779 html += testList(globalState().testsWithStderr, 'Tests that had stderr o utput', 'stderr-table'); | |
780 | |
781 html += failingTestsTable(globalState().flakyPassTests, | |
782 'Flaky tests (failed the first run and passed on retry)', 'flaky-tests-t able'); | |
783 | |
784 if (globalState().unexpectedPassTests.length) | |
785 html += testList(globalState().unexpectedPassTests, 'Tests expected to f ail but passed', 'passes-table'); | |
786 | |
787 html += '</div>'; | |
788 | |
789 | |
790 document.body.innerHTML = html; | |
791 | |
792 if (document.getElementById('results-table')) { | |
793 document.getElementById('results-table').addEventListener('click', Table Sorter.handleClick, false); | |
794 TableSorter.sortColumn(0); | |
795 if (!globalState().hasTextFailures) | |
796 document.getElementById('text-results-header').textContent = ''; | |
797 if (!globalState().hasImageFailures) { | |
798 document.getElementById('image-results-header').textContent = ''; | |
799 parentOfType(document.getElementById('toggle-images'), 'label').styl e.display = 'none'; | |
800 } | |
801 } | |
802 | |
803 updateTestlistCounts(); | |
804 | |
805 OptionWriter.apply(); | |
806 } | |
807 </script> | |
808 <body onload="generatePage()"></body> | |
OLD | NEW |