Commit 387904a3 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

[layout test results.html] Add "Flagged only" checkbox after copy buttons

I often copy flagged tests. This can be achieved by clicking "Flagged"
then one of the copy buttons, but this is sometimes incovenient because
- "Flagged" query is interuptive because it resets the current filters
  making it difficult to return to where I was working on before
  clicking it;
- I often forgot to click the "Flagged" button before copying resulting
  all tests were rebaselined after pasting the list of tests into the
  command line.

Now add a "flagged only" checkbox to indicate whether to copy all or just
flagged tests.

Change-Id: I6a30e5070c724718bb59766f0535153849320d76
Reviewed-on: https://chromium-review.googlesource.com/820682
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarAleks Totic <atotic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#524323}
parent d4c5f5d3
...@@ -15,7 +15,11 @@ body { ...@@ -15,7 +15,11 @@ body {
button { button {
margin-top: 4px; margin-top: 4px;
} }
input {
vertical-align: middle;
margin-top: 0;
margin-bottom: 0;
}
p, h2, h3, h4 { p, h2, h3, h4 {
margin: 8px 0 4px 0; margin: 8px 0 4px 0;
} }
...@@ -142,11 +146,6 @@ p, h2, h3, h4 { ...@@ -142,11 +146,6 @@ p, h2, h3, h4 {
font-family: sans-serif; font-family: sans-serif;
font-size: smaller; font-size: smaller;
} }
#filters input {
vertical-align: middle;
margin-top: 0;
margin-bottom: 0;
}
.flag { .flag {
display: inline-block; display: inline-block;
...@@ -169,6 +168,10 @@ p, h2, h3, h4 { ...@@ -169,6 +168,10 @@ p, h2, h3, h4 {
color: gray; color: gray;
} }
#copied {
color: #4F8A10;
margin-left: 5px;
}
</style> </style>
<body> <body>
<h3>Test run summary <span id="builder_name"></span></h3> <h3>Test run summary <span id="builder_name"></span></h3>
...@@ -187,12 +190,12 @@ p, h2, h3, h4 { ...@@ -187,12 +190,12 @@ p, h2, h3, h4 {
<li><b>Tab</b> to select the next test. <li><b>Tab</b> to select the next test.
<li><b>Enter</b> to see test details. This will automatically close other details. <li><b>Enter</b> to see test details. This will automatically close other details.
<li><b>ctrl A</b> to select text of all tests for easy copying. <li><b>ctrl A</b> to select text of all tests for easy copying.
<li><b>f</b> to flag. <li><b>f</b> to flag/unflag a test.
</ul> </ul>
<p>Modifiers:</p> <p>Modifiers:</p>
<ul> <ul>
<li><b>Shift</b> hold shift key to keep other details open. <li><b>Shift</b> hold shift key to keep other details open.
<li><b>Meta</b> meta means all. Toggle all flags, open all results (max 100). <li><b>Meta</b> meta means all. Set/unset all flags or open/close all results (max 100).
</ul> </ul>
<p>This page lets you query and display test results.</p> <p>This page lets you query and display test results.</p>
...@@ -322,12 +325,12 @@ TestResult(CRASH) + TextExpectation(Failure) => [ Failure <b>Crash</b> ]</pre> ...@@ -322,12 +325,12 @@ TestResult(CRASH) + TextExpectation(Failure) => [ Failure <b>Crash</b> ]</pre>
<option value="crashsite">Crash site</option> <option value="crashsite">Crash site</option>
<option value="textmismatch">Text mismatch</option> <option value="textmismatch">Text mismatch</option>
</select> </select>
&nbsp;
<span style="margin-left: 20px"> <span style="margin-left: 20px">
<button id="copy_report" title="Copy the shown tests to clipboard in the current format" <button id="copy_report" title="Copy the shown/flagged tests to clipboard in the current format"
onclick="GUI.copyReport()" disabled>Copy report</button> onclick="GUI.copyResult(false)" disabled>Copy report</button>
<button id="copy_single_line" title="Copy the shown tests to clipboard in a single line for use in command lines." <button id="copy_single_line" title="Copy the shown/flagged tests to clipboard in a single line for use in command lines."
onclick="GUI.copySingleLine()" disabled>Copy single line</button> onclick="GUI.copyResult(true)" disabled>Copy single line</button>
<label id="flagged_only" class="hidden"><input id="flagged_only_checkbox" type="checkbox" checked>Flagged only</label>
<span id="copied" class="hidden">Copied.</span> <span id="copied" class="hidden">Copied.</span>
</span> </span>
</div> </div>
...@@ -378,8 +381,10 @@ class Traversal { ...@@ -378,8 +381,10 @@ class Traversal {
} }
traverse(filter, action) { traverse(filter, action) {
console.time("traverse");
action = action || function() {}; action = action || function() {};
this._helper(this.root, "", filter, action); this._helper(this.root, "", filter, action);
console.timeEnd("traverse");
} }
reset() { reset() {
...@@ -472,7 +477,8 @@ const Report = { ...@@ -472,7 +477,8 @@ const Report = {
}, },
printFlag: (test) => { printFlag: (test) => {
return `<div class="flag ${test.flagged ? "flagged" : ""}"></div>`; return `<div class="flag ${test.flagged ? "flagged" : ""}"
title="Hold Meta key to flag/unflag all tests."></div>`;
}, },
printPlainTest: (test, path, traversal) => { printPlainTest: (test, path, traversal) => {
...@@ -557,8 +563,7 @@ const Report = { ...@@ -557,8 +563,7 @@ const Report = {
report.appendChild(pre); report.appendChild(pre);
}, },
renderResultList: (html) => { renderResultList: (html, report) => {
let report = document.querySelector("#report");
if (report.childNodes.length === 0 && html.length === 0) { if (report.childNodes.length === 0 && html.length === 0) {
Report.indicateNone(report); Report.indicateNone(report);
return; return;
...@@ -599,8 +604,7 @@ const Report = { ...@@ -599,8 +604,7 @@ const Report = {
return container; return container;
}, },
renderGroup: (html, keyed_title, null_title) => { renderGroup: (html, report, keyed_title, null_title) => {
let report = document.querySelector("#report");
if (report.childNodes.length === 0 && html.length === 0) { if (report.childNodes.length === 0 && html.length === 0) {
Report.indicateNone(report); Report.indicateNone(report);
return; return;
...@@ -622,12 +626,12 @@ const Report = { ...@@ -622,12 +626,12 @@ const Report = {
renderMap[key].container.insertAdjacentHTML('beforeend', renderMap[key].html); renderMap[key].container.insertAdjacentHTML('beforeend', renderMap[key].html);
}, },
renderGroupCrashSite: (html) => { renderGroupCrashSite: (html, report) => {
Report.renderGroup(html, "Crash site", "Didn't crash"); Report.renderGroup(html, report, "Crash site", "Didn't crash");
}, },
renderGroupTextMismatch: (html) => { renderGroupTextMismatch: (html, report) => {
Report.renderGroup(html, "Text mismatch failure", "Didn't find text mismatch"); Report.renderGroup(html, report, "Text mismatch failure", "Didn't find text mismatch");
}, },
getTestById: (testId) => { getTestById: (testId) => {
...@@ -794,6 +798,7 @@ const Query = { ...@@ -794,6 +798,7 @@ const Query = {
// generateReport is async, returns promise. // generateReport is async, returns promise.
// promise id fullfilled when traversal completes. Display will continue async. // promise id fullfilled when traversal completes. Display will continue async.
generateReport: function(name, filter, report) { generateReport: function(name, filter, report) {
console.time("generateReport");
if (this.currentRAF) if (this.currentRAF)
window.cancelAnimationFrame(this.currentRAF); window.cancelAnimationFrame(this.currentRAF);
report = report || Report.getDefaultPrinter(); report = report || Report.getDefaultPrinter();
...@@ -816,15 +821,15 @@ const Query = { ...@@ -816,15 +821,15 @@ const Query = {
let callback = _ => { let callback = _ => {
this.currentRAF = null; this.currentRAF = null;
let html = traversal.html.slice(index, index + chunkSize); let html = traversal.html.slice(index, index + chunkSize);
report.render(html); report.render(html, document.querySelector("#report"));
index += chunkSize; index += chunkSize;
document.querySelector("#progress").style.width = Math.min((index / traversal.html.length * 100), 100) + "%"; document.querySelector("#progress").style.width = Math.min((index / traversal.html.length * 100), 100) + "%";
if (index < traversal.html.length) { if (index < traversal.html.length) {
this.currentRAF = window.requestAnimationFrame(callback); this.currentRAF = window.requestAnimationFrame(callback);
} else { } else {
document.querySelector("#report_count").innerText = traversal.filteredCount; document.querySelector("#report_count").innerText = traversal.filteredCount;
document.querySelector("#copy_report").disabled = traversal.html.length == 0; GUI.updateCopyButtons();
document.querySelector("#copy_single_line").disabled = traversal.html.length == 0; console.timeEnd("generateReport");
} }
}; };
window.setTimeout( _ => { window.setTimeout( _ => {
...@@ -1049,7 +1054,7 @@ const GUI = { ...@@ -1049,7 +1054,7 @@ const GUI = {
; // Clicks in anchor, input or result-frame should perform default action ; // Clicks in anchor, input or result-frame should perform default action
} else if (GUI.isFlag(ev.target)) { } else if (GUI.isFlag(ev.target)) {
GUI.toggleFlag(ev.target, ev); GUI.toggleFlag(ev.target, ev);
} else if (expectation) { } else if (expectation && window.getSelection().type != "Range") {
GUI.toggleResults(expectation, ev); GUI.toggleResults(expectation, ev);
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
...@@ -1140,22 +1145,50 @@ const GUI = { ...@@ -1140,22 +1145,50 @@ const GUI = {
}, 2000); }, 2000);
}, },
copyReport: function() { copyResult: function(asSingleLine) {
GUI.copyText(document.querySelector("#report")); console.time("copyResult");
}, let flaggedOnly = document.querySelector(".flagged") &&
document.querySelector("#flagged_only_checkbox").checked;
if (!flaggedOnly && !asSingleLine) {
GUI.copyText(document.querySelector("#report"));
return;
}
copySingleLine: function() { let printer = Report.getDefaultPrinter();
let singleLine = ""; let singleLine = "";
new Traversal(globalResults.tests).traverse(Query.lastReport.filter, (_, path) => { let traversal = new Traversal(globalResults.tests);
let pathParser = new PathParser(path); traversal.traverse(Query.lastReport.filter, (test, path) => {
singleLine += pathParser.dir + pathParser.file + " "; if (flaggedOnly && !test.flagged)
return;
if (asSingleLine) {
let pathParser = new PathParser(path);
singleLine += pathParser.dir + pathParser.file + " ";
} else {
printer.print(test, path, traversal);
}
}); });
let pre = document.createElement("pre"); let div = document.createElement("div");
pre.setAttribute("style", "overflow: hidden; color: white; height: 1px"); div.setAttribute("style", "overflow: hidden; color: white; height: 1px");
pre.textContent = singleLine; if (asSingleLine)
document.body.appendChild(pre); div.textContent = singleLine;
GUI.copyText(pre); else
document.body.removeChild(pre); printer.render(traversal.html, div);
document.body.appendChild(div);
GUI.copyText(div);
document.body.removeChild(div);
console.timeEnd("copyResult");
},
updateCopyButtons: function() {
let has_result = document.querySelector(".expect");
document.querySelector("#copy_report").disabled = !has_result;
document.querySelector("#copy_single_line").disabled = !has_result;
let flagged_only = document.querySelector("#flagged_only");
if (document.querySelector(".flagged"))
flagged_only.classList.remove("hidden");
else
flagged_only.classList.add("hidden");
}, },
printSummary: function (fullResults) { printSummary: function (fullResults) {
...@@ -1242,6 +1275,7 @@ const GUI = { ...@@ -1242,6 +1275,7 @@ const GUI = {
} }
} }
} }
GUI.updateCopyButtons();
}, },
toggleResults: function(expectation, event) { toggleResults: function(expectation, event) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment