Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow filtering on pass/fail and browser #57

Merged
merged 2 commits into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 157 additions & 13 deletions src/server/report/app.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,88 @@
import './test-result.js';
import { css, html, LitElement } from 'lit';
import { css, html, LitElement, nothing } from 'lit';
import data from './data.js';
import page from 'page';

const FILTER_STATUS = {
ALL: 'All',
PASSED: 'Passed',
FAILED: 'Failed'
};

class App extends LitElement {
static properties = {
_files: { state: true },
_filterFile: { state: true },
_filterTest: { state: true },
_mode: { state: true },
_overlay: { state: true }
};
static styles = [css`
.container {
display: grid;
grid-auto-flow: row;
grid-template-areas: "sidebar content";
grid-template-columns: 300px auto;
}
aside {
background-color: #fff;
border: 1px solid #e6e6e6;
box-shadow: 0 0 6px rgba(0,0,0,.07);
box-sizing: border-box;
grid-area: sidebar;
height: 100vh;
position: sticky;
top: 0;
z-index: 10;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stole most of these styles from the Daylight Site. They work for now and we can tweak them later!

aside > div {
padding: 10px;
}
main {
background-color: #fafafa;
grid-area: content;
}
main > div {
padding: 20px;
}
table {
background-color: #ffffff;
border-collapse: collapse;
}
td, th {
border: 1px solid #cdd5dc;
border: 1px solid #dfe6ef;
padding: 10px;
text-align: center;
}
thead th {
background-color: #f9fbff;
background-color: #f5f5f5;
}
tbody th {
font-weight: normal;
text-align: left;
}
td.passed {
background-color: #EFFFD9;
}
td.failed {
background-color: #FFEDE8;
}
dlockhart marked this conversation as resolved.
Show resolved Hide resolved
fieldset {
border: none;
margin-inline: 0;
padding-inline: 0;
}
fieldset > legend {
font-weight: bold;
}
`];
constructor() {
super();
this._filterBrowsers = data.browsers.map(b => b.name);
this._filterStatus = data.numFailed > 0 ? FILTER_STATUS.FAILED : FILTER_STATUS.ALL;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default to showing only failed tests, assuming there are any.

this._mode = 'sideBySide';
this._overlay = true;
this._updateFiles();
}
connectedCallback() {
super.connectedCallback();
Expand Down Expand Up @@ -65,32 +118,58 @@ class App extends LitElement {
}
}
} else {
view = data.files.map(f => this._renderFile(f));
if (this._files.length === 0) {
view = html`<p>No tests exist for the selected filters.</p>`;
} else {
view = this._files.map(f => this._renderFile(f));
}
}
return html`
<header>
<h1>Visual-diff Results</h1>
</header>
<main>${view}</main>
<div class="container">
<aside>
<div>
<h1>Visual-diff Results</h1>
${this._renderFilters()}
</div>
</aside>
<main><div>${view}</div></main>
</div>
`;
}
_goHome() {
page(this._root);
}
_handleFilterBrowserChange(e) {
const index = this._filterBrowsers.indexOf(e.target.value);
if (!e.target.checked && index > -1) {
this._filterBrowsers.splice(index, 1);
} else if (e.target.checked && index === -1) {
this._filterBrowsers.push(e.target.value);
}
this._updateFiles();
}
_handleFilterStatusChange(e) {
this._filterStatus = e.target.value;
this._updateFiles();
}
_handleModeChange(e) {
this._mode = e.target.options[e.target.selectedIndex].value;
}
_handleOverlayChange(e) {
this._overlay = e.target.checked;
}
_renderFile(file) {
const renderBrowserCell = (b) => {
if (!this._filterBrowsers.includes(b.name)) return nothing;
return html`<th>${b.name}</th>`;
};
return html`
<h2>${file.name}</h2>
<table>
<thead>
<tr>
<th>Test</th>
${data.browsers.map(b => html`<th>${b.name}</th>`)}
<th style="text-align: left;">Test</th>
${data.browsers.map(b => renderBrowserCell(b))}
</tr>
</thead>
<tbody>
Expand All @@ -99,6 +178,46 @@ class App extends LitElement {
</table>
`;
}
_renderFilters() {

const statusFilters = [
{ name: FILTER_STATUS.FAILED, count: data.numFailed },
{ name: FILTER_STATUS.PASSED, count: data.numTests - data.numFailed },
{ name: FILTER_STATUS.ALL, count: data.numTests }
];

const renderStatusFilter = (f) => {
if (f.count === 0) return nothing;
return html`
<label>
<input type="radio" name="status" value="${f.name}" ?checked="${this._filterStatus === f.name}" @click="${this._handleFilterStatusChange}">
${f.name} (${f.count})
</label><br>`;
};

const renderBrowser = (b) => {
const browserData = data.browsers.find(data => data.name === b.name);
const result = `${(data.numTests - browserData.numFailed)}/${data.numTests}`;
return html`
<label>
<input type="checkbox" value="${b.name}" ?checked="${this._filterBrowsers.includes(b.name)}" @click="${this._handleFilterBrowserChange}">
${b.name} (${result} passed)
</label><br>
`;
};

return html`
<fieldset>
<legend>Test Status</legend>
${statusFilters.map(f => renderStatusFilter(f))}
</fieldset>
<fieldset>
<legend>Browsers</legend>
${ data.browsers.map(b => renderBrowser(b))}
</fieldset>
`;

}
_renderTest(file, test) {
return html`
<h2>${test.name} (${(test.results.length - test.numFailed)}/${test.results.length} passed)</h2>
Expand All @@ -119,15 +238,40 @@ class App extends LitElement {
`;
}
_renderTestResultRow(file, test) {
const results = test.results.map(r => {
return html`<td>${r.passed.toString()}</td>`;
const results = data.browsers.map(b => {
if (!this._filterBrowsers.includes(b.name)) return nothing;
const result = test.results.find(r => r.name === b.name);
const passed = (result !== undefined) ? result.passed : true;
const text = passed ? 'passed' : 'failed';
return html`<td class="${text}">${text}</td>`;
});
return html`
<tr>
<th><a href="./?file=${encodeURIComponent(file.name)}&test=${encodeURIComponent(test.name)}">${test.name}</a></th>
<th style="text-align: left;"><a href="./?file=${encodeURIComponent(file.name)}&test=${encodeURIComponent(test.name)}">${test.name}</a></th>
${results}
</tr>
`;
}
_updateFiles() {
const files = [];
data.files.forEach(f => {
const tests = [];
f.tests.forEach(t => {
const results = t.results.filter(r => {
if (!this._filterBrowsers.includes(r.name)) return false;
if (!r.passed && this._filterStatus === FILTER_STATUS.PASSED) return false;
if (r.passed && this._filterStatus === FILTER_STATUS.FAILED) return false;
return true;
});
if (results.length > 0) {
tests.push({ ...t, results });
}
});
if (tests.length > 0) {
files.push({ ...f, tests });
}
});
this._files = files;
}
}
customElements.define('d2l-vdiff-report-app', App);
1 change: 1 addition & 0 deletions src/server/report/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
body {
font-family: 'Roboto', sans-serif;
font-size: 16px;
margin: 0;
}
</style>
</head>
Expand Down
2 changes: 1 addition & 1 deletion src/server/report/test-result.js
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes a bug Stacey noticed where the images always grow to fill the viewport. Now they'll fill the viewport but not exceed the actual size of the screenshots.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class TestResult extends LitElement {
gap: 10px;
}
.side-by-side > div {
flex: 0 1 50%;
flex: 0 1 auto;
}
img {
max-width: 100%;
Expand Down
14 changes: 12 additions & 2 deletions src/server/visual-diff-reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,18 @@ function createData(rootDir, sessions) {

});

return { files, browsers };
let numTests = 0, numFailed = 0;
files.forEach(f => {
numTests += f.tests.size;
f.tests.forEach(t => {
if (t.numFailed > 0) {
f.numFailed++;
numFailed++;
}
});
});

return { browsers, files, numFailed, numTests };

}

Expand All @@ -52,7 +63,6 @@ function flattenResults(session, browserData, fileData) {
const testData = fileData.tests.get(testName);
if (!t.passed) {
browserData.numFailed++;
fileData.numFailed++;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Counting it here caused it to think that a test failed 3 times if it failed in all 3 browsers, which isn't quite what I want to surface.

testData.numFailed++;
}
testData.results.push({
Expand Down