Chromium Code Reviews| Index: LayoutTests/fast/harness/dashboard.html |
| diff --git a/LayoutTests/fast/harness/dashboard.html b/LayoutTests/fast/harness/dashboard.html |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..bbba5cecfcf1e0a41998c89875ef504bfe6df49d |
| --- /dev/null |
| +++ b/LayoutTests/fast/harness/dashboard.html |
| @@ -0,0 +1,808 @@ |
| +<!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
|
| +<style> |
| +html { |
| + height: 100%; |
| +} |
| +body { |
| + margin: 0; |
| + font-family: Helvetica, sans-serif; |
| + font-size: 11pt; |
| + display: -webkit-flex; |
| + -webkit-flex-direction: column; |
| + height: 100%; |
| +} |
| + |
| +body > * { |
| + margin-left: 4px; |
| + margin-top: 4px; |
| +} |
| + |
| +h1 { |
| + font-size: 14pt; |
| + margin-top: 1.5em; |
| +} |
| + |
| +p { |
| + margin-bottom: 0.3em; |
| +} |
| + |
| +tr { |
| + background-color: white; |
| +} |
| + |
| +tr:hover { |
| + background-color: #999999; |
| +} |
| + |
| +tr:not(.results-row) td { |
| + white-space: nowrap; |
| +} |
| + |
| +tr:not(.results-row) td:first-of-type { |
| + white-space: normal; |
| +} |
| + |
| +td:not(:first-of-type) { |
| + text-transform: lowercase; |
| +} |
| + |
| +td { |
| + padding: 1px 4px; |
| +} |
| + |
| +th:empty, td:empty { |
| + padding: 0; |
| +} |
| + |
| +th { |
| + -webkit-user-select: none; |
| + -moz-user-select: none; |
| +} |
| + |
| +.content-container { |
| + -webkit-flex: 1; |
| + min-height: -webkit-min-content; |
| + overflow: auto; |
| +} |
| + |
| +.note { |
| + color: gray; |
| + font-size: smaller; |
| +} |
| + |
| +.results-row { |
| + background-color: white; |
| +} |
| + |
| +.results-row iframe, .results-row img { |
| + width: 800px; |
| + height: 600px; |
| +} |
| + |
| +.results-row[data-expanded="false"] { |
| + display: none; |
| +} |
| + |
| +#toolbar { |
| + position: fixed; |
| + padding: 4px; |
| + top: 2px; |
| + right: 2px; |
| + text-align: right; |
| + background-color: rgba(255, 255, 255, 0.85); |
| + border: 1px solid silver; |
| + border-radius: 4px; |
| +} |
| + |
| +.expand-button { |
| + background-color: white; |
| + width: 11px; |
| + height: 12px; |
| + border: 1px solid gray; |
| + display: inline-block; |
| + margin: 0 3px 0 0; |
| + position: relative; |
| + cursor: default; |
| +} |
| + |
| +.current { |
| + color: red; |
| +} |
| + |
| +.current .expand-button { |
| + border-color: red; |
| +} |
| + |
| +.expand-button-text { |
| + position: absolute; |
| + top: -0.3em; |
| + left: 1px; |
| +} |
| + |
| +tbody .flag { |
| + display: none; |
| +} |
| + |
| +tbody.flagged .flag { |
| + display: inline; |
| +} |
| + |
| +.stopped-running-early-message { |
| + border: 3px solid #d00; |
| + font-weight: bold; |
| + display: inline-block; |
| + padding: 3px; |
| +} |
| + |
| +.result-container { |
| + display: inline-block; |
| + border: 1px solid gray; |
| + margin: 4px; |
| +} |
| + |
| +.result-container iframe, .result-container img { |
| + border: 0; |
| + vertical-align: top; |
| +} |
| + |
| +.label { |
| + padding-left: 3px; |
| + font-weight: bold; |
| + font-size: small; |
| + background-color: silver; |
| +} |
| + |
| +.pixel-zoom-container { |
| + position: fixed; |
| + top: 0; |
| + left: 0; |
| + width: 96%; |
| + margin: 10px; |
| + padding: 10px; |
| + display: -webkit-box; |
| + display: -moz-box; |
| + pointer-events: none; |
| + background-color: silver; |
| + border-radius: 20px; |
| + border: 1px solid gray; |
| + box-shadow: 0 0 5px rgba(0, 0, 0, 0.75); |
| +} |
| + |
| +.pixel-zoom-container > * { |
| + -webkit-box-flex: 1; |
| + -moz-box-flex: 1; |
| + border: 1px solid black; |
| + margin: 4px; |
| + overflow: hidden; |
| + background-color: white; |
| +} |
| + |
| +.pixel-zoom-container .scaled-image-container { |
| + position: relative; |
| + overflow: hidden; |
| + width: 100%; |
| + height: 400px; |
| +} |
| + |
| +.scaled-image-container > img { |
| + position: absolute; |
| + top: 0; |
| + left: 0; |
| + image-rendering: -webkit-optimize-contrast; |
| +} |
| +.test-pass { |
| + background-color:rgb(0,255,0); |
| +} |
| +.test-image-fail { |
| + background-color:rgb(0,128,255); |
| +} |
| +.test-text-fail { |
| + background-color:rgb(250,100,100); |
| +} |
| +.test-image-text-fail { |
| + background-color:rgb(161,128,250); |
| +} |
| +.test-flaky { |
| + background-color:rgb(255,0,255); |
| +} |
| +.test-missing { |
| + background-color:rgb(255,255,255); |
| +} |
| +.test-fail { |
| + background-color:rgb(255,0,0); |
| +} |
| + |
| +#flagged-tests { |
| + margin: 1px; |
| + padding: 5px; |
| + height: 100px; |
| +} |
| + |
| +#flagged-test-container h2 { |
| + display: inline-block; |
| + margin: 0 10px 0 0; |
| +} |
| +</style> |
| +<style id="unexpected-pass-style"></style> |
| +<style id="flaky-failures-style"></style> |
| +<style id="stderr-style"></style> |
| +<style id="unexpected-style"></style> |
| + |
| +<script> |
| +var g_state; |
| +function globalState() |
| +{ |
| + if (!g_state) { |
| + g_state = { |
| + crashTests: [], |
| + leakTests: [], |
| + flakyPassTests: [], |
| + hasHttpTests: false, |
| + hasImageFailures: false, |
| + hasTextFailures: false, |
| + missingResults: [], |
| + results: {}, |
| + failingTests: [], |
| + testsWithStderr: [], |
| + timeoutTests: [], |
| + unexpectedPassTests: [] |
| + } |
| + } |
| + return g_state; |
| +} |
| + |
| +function ADD_RESULTS(input) |
| +{ |
| + globalState().results = input; |
| +} |
| +</script> |
| + |
| +<script src="archived_results.json"></script> |
| + |
| +<script> |
| + |
| +function matchesSelector(node, selector) |
| +{ |
| + if (node.webkitMatchesSelector) |
| + return node.webkitMatchesSelector(selector); |
| + |
| + if (node.mozMatchesSelector) |
| + return node.mozMatchesSelector(selector); |
| +} |
| + |
| +function parentOfType(node, selector) |
| +{ |
| + while (node = node.parentNode) { |
| + if (matchesSelector(node, selector)) |
| + return node; |
| + } |
| + return null; |
| +} |
| + |
| +function remove(node) |
| +{ |
| + node.parentNode.removeChild(node); |
| +} |
| + |
| +function forEach(nodeList, handler) |
| +{ |
| + Array.prototype.forEach.call(nodeList, handler); |
| +} |
| + |
| +function resultIframe(src) |
| +{ |
| + // FIXME: use audio tags for AUDIO tests? |
| + var layoutTestsIndex = src.indexOf('LayoutTests'); |
| + var name; |
| + if (layoutTestsIndex != -1) { |
| + var hasTrac = src.indexOf('trac.webkit.org') != -1; |
| + 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
|
| + name = prefix + src.substring(layoutTestsIndex + 'LayoutTests/'.length); |
| + } else { |
| + var lastDashIndex = src.lastIndexOf('-pretty'); |
| + if (lastDashIndex == -1) |
| + lastDashIndex = src.lastIndexOf('-'); |
| + name = src.substring(lastDashIndex + 1); |
| + } |
| + |
| + var tagName = (src.lastIndexOf('.png') == -1) ? 'iframe' : 'img'; |
| + |
| + if (tagName != 'img') |
| + src += '?format=txt'; |
| + return '<div class=result-container><div class=label>' + name + '</div><' + tagName + ' src="' + src + '"></' + tagName + '></div>'; |
| +} |
| + |
| +function togglingImage(prefix) |
| +{ |
| + return '<div class=result-container><div class="label imageText"></div><img class=animatedImage data-prefix="' + |
| + prefix + '"></img></div>'; |
| +} |
| + |
| +function appendHTML(node, html) |
| +{ |
| + if (node.insertAdjacentHTML) |
| + node.insertAdjacentHTML('beforeEnd', html); |
| + else |
| + node.innerHTML += html; |
| +} |
| + |
| +function shouldUseTracLinks() |
|
Dirk Pranke
2014/07/15 20:50:00
same comment
|
| +{ |
| + return !globalState().results.layout_tests_dir || !location.toString().indexOf('file://') == 0; |
| +} |
| + |
| +function testLinkTarget(test) |
| +{ |
| + var target; |
| + if (shouldUseTracLinks()) { |
| + var revision = globalState().results.revision; |
| + target = 'http://src.chromium.org/viewvc/blink/trunk/LayoutTests/' + test; |
| + if (revision) |
| + target += '?pathrev=' + revision; |
| + target += '#l1'; |
| + } else |
| + target = globalState().results.layout_tests_dir + '/' + test; |
| + return target; |
| +} |
| + |
| +function testLink(test) |
| +{ |
| + var target = testLinkTarget(test); |
| + return '<a class=test-link href="' + target + '">' + test + '</a>'; |
| +} |
| + |
| +function resultLink(testPrefix, suffix, contents) |
| +{ |
| + return '<a class=result-link href="' + testPrefix + suffix + '" data-prefix="' + testPrefix + '">' + contents + '</a> '; |
| +} |
| + |
| +function processGlobalStateFor(testObject) |
| +{ |
| + var test = testObject.name; |
| + if (testObject.has_stderr) |
| + globalState().testsWithStderr.push(testObject); |
| + |
| + globalState().hasHttpTests = globalState().hasHttpTests || test.indexOf('http/') == 0; |
| + |
| + var actual = testObject.actual; |
| + var expected = testObject.expected || 'PASS'; |
| + |
| + if (actual == 'MISSING') { |
| + // FIXME: make sure that new-run-webkit-tests spits out an -actual.txt file for |
| + // tests with MISSING results. |
| + globalState().missingResults.push(testObject); |
| + return; |
| + } |
| + |
| + var actualTokens = actual.split(' '); |
| + var passedWithImageOnlyFailureInRetry = actualTokens[0] == 'TEXT' && actualTokens[1] == 'IMAGE'; |
| + if (actualTokens[1] && actual.indexOf('PASS') != -1 || (!globalState().results.pixel_tests_enabled && passedWithImageOnlyFailureInRetry)) { |
| + globalState().flakyPassTests.push(testObject); |
| + return; |
| + } |
| + |
| + if (actual == 'PASS' && expected != 'PASS') { |
| + if (expected != 'IMAGE' || (globalState().results.pixel_tests_enabled || testObject.reftest_type)) { |
| + globalState().unexpectedPassTests.push(testObject); |
| + } |
| + return; |
| + } |
| + |
| + if (actual == 'CRASH') { |
| + globalState().crashTests.push(testObject); |
| + return; |
| + } |
| + |
| + if (actual == 'LEAK') { |
| + globalState().leakTests.push(testObject); |
| + return; |
| + } |
| + |
| + if (actual == 'TIMEOUT') { |
| + globalState().timeoutTests.push(testObject); |
| + return; |
| + } |
| + |
| + globalState().failingTests.push(testObject); |
| +} |
| + |
| +function getResultLink(index) |
| +{ |
| + if(index < globalState().results.result_links.length) |
| + return globalState().results.result_links[index]; |
| + else |
| + return ''; |
| +} |
| + |
| +function processArchivedResults(archivedResults) |
| +{ |
| + var result = ''; |
| + var i = 1; |
| + for (var i = 0; i < archivedResults.length; i++) { |
| + switch(archivedResults[i]) { |
| + case "PASS": |
| + result += '<td class=test-pass>'; |
| + break; |
| + case "IMAGE": |
| + result += '<td class=test-image-fail>'; |
| + break; |
| + case "TEXT": |
| + result += '<td class=test-text-fail>'; |
| + break; |
| + case "IMAGE+TEXT": |
| + result += '<td class=test-image-text-fail>'; |
| + break; |
| + case "NOTFOUND": |
| + result += '<td class=test-missing>'; |
| + break; |
| + case "SKIP": |
| + result += '<td class=test-missing>'; |
| + break; |
| + default: |
| + result += '<td class=test-fail>'; |
| + } |
| + result += '<a href="' + getResultLink(i) + '">' + (i+1).toString() + '</a>' + '</td>'; |
| + } |
| + |
| + return result; |
| +} |
| + |
| +function tableRow(testObject) |
| +{ |
| + var row = '<tbody class="' + (testObject.is_unexpected ? '' : 'expected') + '"'; |
| + if (testObject.reftest_type && testObject.reftest_type.indexOf('!=') != -1) |
| + row += ' mismatchreftest=true'; |
| + row += '><tr>'; |
| + |
| + row += '<td>' + testLink(testObject.name) + '</td>'; |
| + |
| + var archivedResults = testObject.archived_results; |
| + row += processArchivedResults(archivedResults); |
| + row += '</tr></tbody>'; |
| + return row; |
| +} |
| + |
| +function forEachTest(handler, opt_tree, opt_prefix) |
| +{ |
| + var tree = opt_tree || globalState().results.tests; |
| + var prefix = opt_prefix || ''; |
| + |
| + for (var key in tree) { |
| + var newPrefix = prefix ? (prefix + '/' + key) : key; |
| + if ('actual' in tree[key]) { |
| + var testObject = tree[key]; |
| + testObject.name = newPrefix; |
| + handler(testObject); |
| + } else |
| + forEachTest(handler, tree[key], newPrefix); |
| + } |
| +} |
| + |
| +function hasUnexpected(tests) |
| +{ |
| + return tests.some(function (test) { return test.is_unexpected; }); |
| +} |
| + |
| +function updateTestlistCounts() |
| +{ |
| + forEach(document.querySelectorAll('.test-list-count'), function(count) { |
| + var container = parentOfType(count, 'div'); |
| + var testContainers; |
| + if (onlyShowUnexpectedFailures()) |
| + testContainers = container.querySelectorAll('tbody:not(.expected)'); |
| + else |
| + testContainers = container.querySelectorAll('tbody'); |
| + |
| + count.textContent = testContainers.length; |
| + |
| + }) |
| +} |
| + |
| +function testListHeaderHtml(header) |
| +{ |
| + return '<h1>' + header + ' (<span class=test-list-count></span>): </h1>'; |
| +} |
| + |
| +function testList(tests, header, tableId) |
| +{ |
| + tests.sort(); |
| + |
| + var html = '<div' + ((!hasUnexpected(tests) && tableId != 'stderr-table') ? ' class=expected' : '') + ' id=' + tableId + '>' + |
| + testListHeaderHtml(header) + '<table>'; |
| + |
| + // FIXME: Include this for all testLists. |
| + if (tableId == 'passes-table') |
| + html += '<thead><th>test</th><th>expected</th></thead>'; |
| + |
| + for (var i = 0; i < tests.length; i++) { |
| + var testObject = tests[i]; |
| + var test = testObject.name; |
| + html += '<tbody class="' + ((testObject.is_unexpected || tableId == 'stderr-table') ? '' : 'expected') + '"><tr><td>' + |
| + testLink(test) + |
| + '</td>'; |
| + |
| + html += processArchivedResults(testObject.archived_results) |
| + html += '</tr></tbody>'; |
| + } |
| + html += '</table></div>'; |
| + return html; |
| +} |
| + |
| +function toArray(nodeList) |
| +{ |
| + return Array.prototype.slice.call(nodeList); |
| +} |
| + |
| +function trim(string) |
| +{ |
| + return string.replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''); |
| +} |
| + |
| +// Just a namespace for code management. |
| +var TableSorter = {}; |
| + |
| +TableSorter._forwardArrow = '<svg style="width:10px;height:10px"><polygon points="0,0 10,0 5,10" style="fill:#ccc"></svg>'; |
| + |
| +TableSorter._backwardArrow = '<svg style="width:10px;height:10px"><polygon points="0,10 10,10 5,0" style="fill:#ccc"></svg>'; |
| + |
| +TableSorter._sortedContents = function(header, arrow) |
| +{ |
| + return arrow + ' ' + trim(header.textContent) + ' ' + arrow; |
| +} |
| + |
| +TableSorter._updateHeaderClassNames = function(newHeader) |
| +{ |
| + var sortHeader = document.querySelector('.sortHeader'); |
| + if (sortHeader) { |
| + if (sortHeader == newHeader) { |
| + var isAlreadyReversed = sortHeader.classList.contains('reversed'); |
| + if (isAlreadyReversed) |
| + sortHeader.classList.remove('reversed'); |
| + else |
| + sortHeader.classList.add('reversed'); |
| + } else { |
| + sortHeader.textContent = sortHeader.textContent; |
| + sortHeader.classList.remove('sortHeader'); |
| + sortHeader.classList.remove('reversed'); |
| + } |
| + } |
| + |
| + newHeader.classList.add('sortHeader'); |
| +} |
| + |
| +TableSorter._textContent = function(tbodyRow, column) |
| +{ |
| + return tbodyRow.querySelectorAll('td')[column].textContent; |
| +} |
| + |
| +TableSorter._sortRows = function(newHeader, reversed) |
| +{ |
| + var testsTable = document.getElementById('results-table'); |
| + var headers = toArray(testsTable.querySelectorAll('th')); |
| + var sortColumn = headers.indexOf(newHeader); |
| + |
| + var rows = toArray(testsTable.querySelectorAll('tbody')); |
| + |
| + rows.sort(function(a, b) { |
| + // Only need to support lexicographic sort for now. |
| + var aText = TableSorter._textContent(a, sortColumn); |
| + var bText = TableSorter._textContent(b, sortColumn); |
| + |
| + // Forward sort equal values by test name. |
| + if (sortColumn && aText == bText) { |
| + var aTestName = TableSorter._textContent(a, 0); |
| + var bTestName = TableSorter._textContent(b, 0); |
| + if (aTestName == bTestName) |
| + return 0; |
| + return aTestName < bTestName ? -1 : 1; |
| + } |
| + |
| + if (reversed) |
| + return aText < bText ? 1 : -1; |
| + else |
| + return aText < bText ? -1 : 1; |
| + }); |
| + |
| + for (var i = 0; i < rows.length; i++) |
| + testsTable.appendChild(rows[i]); |
| +} |
| + |
| +TableSorter.sortColumn = function(columnNumber) |
| +{ |
| + var newHeader = document.getElementById('results-table').querySelectorAll('th')[columnNumber]; |
| + TableSorter._sort(newHeader); |
| +} |
| + |
| +TableSorter.handleClick = function(e) |
| +{ |
| + var newHeader = e.target; |
| + if (newHeader.localName != 'th') |
| + return; |
| + TableSorter._sort(newHeader); |
| +} |
| + |
| +TableSorter._sort = function(newHeader) |
| +{ |
| + TableSorter._updateHeaderClassNames(newHeader); |
| + |
| + var reversed = newHeader.classList.contains('reversed'); |
| + var sortArrow = reversed ? TableSorter._backwardArrow : TableSorter._forwardArrow; |
| + newHeader.innerHTML = TableSorter._sortedContents(newHeader, sortArrow); |
| + |
| + TableSorter._sortRows(newHeader, reversed); |
| +} |
| + |
| +document.addEventListener('keypress', TestNavigator.handleKeyEvent, false); |
| + |
| +function onlyShowUnexpectedFailures() |
| +{ |
| + return !document.getElementById('show-expected-failures').checked; |
| +} |
| + |
| +function handleStderrChange() |
| +{ |
| + OptionWriter.save(); |
| + document.getElementById('stderr-style').textContent = document.getElementById('show-stderr').checked ? |
| + '' : '#stderr-table { display: none; }'; |
| +} |
| + |
| +function handleUnexpectedPassesChange() |
| +{ |
| + OptionWriter.save(); |
| + document.getElementById('unexpected-pass-style').textContent = document.getElementById('show-unexpected-passes').checked ? |
| + '' : '#passes-table { display: none; }'; |
| +} |
| + |
| +function handleFlakyFailuresChange() |
| +{ |
| + OptionWriter.save(); |
| + document.getElementById('flaky-failures-style').textContent = document.getElementById('show-flaky-failures').checked ? |
| + '' : '.flaky { display: none; }'; |
| +} |
| + |
| +function handleUnexpectedResultsChange() |
| +{ |
| + OptionWriter.save(); |
| + updateExpectedFailures(); |
| +} |
| + |
| +function updateExpectedFailures() |
| +{ |
| + document.getElementById('unexpected-style').textContent = onlyShowUnexpectedFailures() ? |
| + '.expected { display: none; }' : ''; |
| + |
| + updateTestlistCounts(); |
| + TestNavigator.onlyShowUnexpectedFailuresChanged(); |
| +} |
| + |
| +var OptionWriter = {}; |
| + |
| +OptionWriter._key = 'run-webkit-tests-options'; |
| + |
| +OptionWriter.save = function() |
| +{ |
| + var options = document.querySelectorAll('label input'); |
| + var data = {}; |
| + for (var i = 0, len = options.length; i < len; i++) { |
| + var option = options[i]; |
| + data[option.id] = option.checked; |
| + } |
| + localStorage.setItem(OptionWriter._key, JSON.stringify(data)); |
| +} |
| + |
| +OptionWriter.apply = function() |
| +{ |
| + var json = localStorage.getItem(OptionWriter._key); |
| + if (!json) { |
| + updateAllOptions(); |
| + return; |
| + } |
| + |
| + var data = JSON.parse(json); |
| + for (var id in data) { |
| + var input = document.getElementById(id); |
| + if (input) |
| + input.checked = data[id]; |
| + } |
| + updateAllOptions(); |
| +} |
| + |
| +function updateAllOptions() |
| +{ |
| + forEach(document.querySelectorAll('input'), function(input) { input.onchange(); }); |
| +} |
| + |
| +function failingTestsTable(tests, title, id) |
| +{ |
| + if (!tests.length) |
| + return ''; |
| + |
| + var numberofUnexpectedFailures = 0; |
| + var tableRowHtml = ''; |
| + for (var i = 0; i < tests.length; i++){ |
| + tableRowHtml += tableRow(tests[i]); |
| + if (tests[i].is_unexpected) |
| + numberofUnexpectedFailures++; |
| + } |
| + |
| + var className = ''; |
| + if (id) |
| + className += id.split('-')[0]; |
| + if (!hasUnexpected(tests)) |
| + className += ' expected'; |
| + |
| + var header = '<div'; |
| + if (className) |
| + header += ' class="' + className + '"'; |
| + |
| + header += '>' + testListHeaderHtml(title) + |
| + '<table id="' + id + '"><thead><tr>' + |
| + '<th>test</th>'; |
| + |
| + header += '</tr></thead>'; |
| + |
| + |
| + return header + tableRowHtml + '</table></div>'; |
| +} |
| + |
| +function generatePage() |
| +{ |
| + forEachTest(processGlobalStateFor); |
| + |
| + var html = '<div><div id=toolbar>' + |
| + '<div id=container>Show: '+ |
| + '<label><input id="show-expected-failures" type=checkbox onchange="handleUnexpectedResultsChange()">expected failures</label>' + |
| + '<label><input id="show-flaky-failures" type=checkbox onchange="handleFlakyFailuresChange()">flaky failures</label>' + |
| + '<label><input id="show-unexpected-passes" type=checkbox onchange="handleUnexpectedPassesChange()">unexpected passes</label>' + |
| + '<label><input id="show-stderr" type=checkbox onchange="handleStderrChange()">stderr</label>' + |
| + '</div></div>'; |
| + |
| + if (globalState().results.interrupted) |
| + html += "<p class='stopped-running-early-message'>Testing exited early.</p>" |
| + |
| + if (globalState().crashTests.length) |
| + html += testList(globalState().crashTests, 'Tests that crashed', 'crash-tests-table'); |
| + |
| + if (globalState().leakTests.length) |
| + html += testList(globalState().leakTests, 'Tests that leaked', 'leak-tests-table'); |
| + |
| + html += failingTestsTable(globalState().failingTests, |
| + 'Tests that failed text/pixel/audio diff', 'results-table'); |
| + |
| + html += failingTestsTable(globalState().missingResults, |
| + 'Tests that had no expected results (probably new)', 'missing-table'); |
| + |
| + if (globalState().timeoutTests.length) |
| + html += testList(globalState().timeoutTests, 'Tests that timed out', 'timeout-tests-table'); |
| + |
| + if (globalState().testsWithStderr.length) |
| + html += testList(globalState().testsWithStderr, 'Tests that had stderr output', 'stderr-table'); |
| + |
| + html += failingTestsTable(globalState().flakyPassTests, |
| + 'Flaky tests (failed the first run and passed on retry)', 'flaky-tests-table'); |
| + |
| + if (globalState().unexpectedPassTests.length) |
| + html += testList(globalState().unexpectedPassTests, 'Tests expected to fail but passed', 'passes-table'); |
| + |
| + html += '</div>'; |
| + |
| + |
| + document.body.innerHTML = html; |
| + |
| + if (document.getElementById('results-table')) { |
| + document.getElementById('results-table').addEventListener('click', TableSorter.handleClick, false); |
| + TableSorter.sortColumn(0); |
| + if (!globalState().hasTextFailures) |
| + document.getElementById('text-results-header').textContent = ''; |
| + if (!globalState().hasImageFailures) { |
| + document.getElementById('image-results-header').textContent = ''; |
| + parentOfType(document.getElementById('toggle-images'), 'label').style.display = 'none'; |
| + } |
| + } |
| + |
| + updateTestlistCounts(); |
| + |
| + OptionWriter.apply(); |
| +} |
| +</script> |
| +<body onload="generatePage()"></body> |