From ff0b1d52ae1367f95cb3a4e142c0e323f02191f5 Mon Sep 17 00:00:00 2001 From: Dave Lockhart Date: Thu, 6 Jul 2023 10:17:02 -0400 Subject: [PATCH] allow filtering on pass/fail and browser --- src/server/report/app.js | 170 ++++++++++++++++++++++++++--- src/server/report/index.html | 1 + src/server/report/test-result.js | 2 +- src/server/visual-diff-reporter.js | 14 ++- 4 files changed, 171 insertions(+), 16 deletions(-) diff --git a/src/server/report/app.js b/src/server/report/app.js index 0d5c0ec9..53a81e25 100644 --- a/src/server/report/app.js +++ b/src/server/report/app.js @@ -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; + } + 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; + } + 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; this._mode = 'sideBySide'; this._overlay = true; + this._updateFiles(); } connectedCallback() { super.connectedCallback(); @@ -65,18 +118,40 @@ class App extends LitElement { } } } else { - view = data.files.map(f => this._renderFile(f)); + if (this._files.length === 0) { + view = html`

No tests exist for the selected filters.

`; + } else { + view = this._files.map(f => this._renderFile(f)); + } } return html` -
-

Visual-diff Results

-
-
${view}
+
+ +
${view}
+
`; } _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; } @@ -84,13 +159,17 @@ class App extends LitElement { this._overlay = e.target.checked; } _renderFile(file) { + const renderBrowserCell = (b) => { + if (!this._filterBrowsers.includes(b.name)) return nothing; + return html`${b.name}`; + }; return html`

${file.name}

- - ${data.browsers.map(b => html``)} + + ${data.browsers.map(b => renderBrowserCell(b))} @@ -99,6 +178,46 @@ class App extends LitElement {
Test${b.name}Test
`; } + _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` +
`; + }; + + const renderBrowser = (b) => { + const browserData = data.browsers.find(data => data.name === b.name); + const result = `${(data.numTests - browserData.numFailed)}/${data.numTests}`; + return html` +
+ `; + }; + + return html` +
+ Test Status + ${statusFilters.map(f => renderStatusFilter(f))} +
+
+ Browsers + ${ data.browsers.map(b => renderBrowser(b))} +
+ `; + + } _renderTest(file, test) { return html`

${test.name} (${(test.results.length - test.numFailed)}/${test.results.length} passed)

@@ -119,15 +238,40 @@ class App extends LitElement { `; } _renderTestResultRow(file, test) { - const results = test.results.map(r => { - return html`${r.passed.toString()}`; + 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`${text}`; }); return html` - ${test.name} + ${test.name} ${results} `; } + _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); diff --git a/src/server/report/index.html b/src/server/report/index.html index c4c3f733..2389b10f 100644 --- a/src/server/report/index.html +++ b/src/server/report/index.html @@ -11,6 +11,7 @@ body { font-family: 'Roboto', sans-serif; font-size: 16px; + margin: 0; } diff --git a/src/server/report/test-result.js b/src/server/report/test-result.js index d2277f70..6f6f098b 100644 --- a/src/server/report/test-result.js +++ b/src/server/report/test-result.js @@ -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%; diff --git a/src/server/visual-diff-reporter.js b/src/server/visual-diff-reporter.js index dbf44bd3..6c625aa0 100644 --- a/src/server/visual-diff-reporter.js +++ b/src/server/visual-diff-reporter.js @@ -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 }; } @@ -52,7 +63,6 @@ function flattenResults(session, browserData, fileData) { const testData = fileData.tests.get(testName); if (!t.passed) { browserData.numFailed++; - fileData.numFailed++; testData.numFailed++; } testData.results.push({