diff --git a/lighthouse-core/config/default-config.js b/lighthouse-core/config/default-config.js index 9aa56fa235b4..cbc4936a2d14 100644 --- a/lighthouse-core/config/default-config.js +++ b/lighthouse-core/config/default-config.js @@ -356,6 +356,9 @@ const defaultConfig = { title: str_(UIStrings.diagnosticsGroupTitle), description: str_(UIStrings.diagnosticsGroupDescription), }, + 'filmstrip': { + title: '', + }, 'pwa-fast-reliable': { title: str_(UIStrings.pwaFastReliableGroupTitle), }, @@ -476,6 +479,7 @@ const defaultConfig = { {id: 'non-composited-animations', weight: 0, group: 'diagnostics'}, {id: 'unsized-images', weight: 0, group: 'diagnostics'}, {id: 'large-javascript-libraries', weight: 0, group: 'diagnostics'}, + {id: 'screenshot-thumbnails', weight: 0, group: 'filmstrip'}, // Audits past this point don't belong to a group and will not be shown automatically {id: 'network-requests', weight: 0}, {id: 'network-rtt', weight: 0}, @@ -483,7 +487,6 @@ const defaultConfig = { {id: 'main-thread-tasks', weight: 0}, {id: 'diagnostics', weight: 0}, {id: 'metrics', weight: 0}, - {id: 'screenshot-thumbnails', weight: 0}, {id: 'final-screenshot', weight: 0}, ], }, diff --git a/lighthouse-core/report/html/renderer/category-renderer.js b/lighthouse-core/report/html/renderer/category-renderer.js index 3d2549ac5bb6..d11ce74b3f59 100644 --- a/lighthouse-core/report/html/renderer/category-renderer.js +++ b/lighthouse-core/report/html/renderer/category-renderer.js @@ -424,6 +424,22 @@ class CategoryRenderer { } } + /** + * @param {LH.ReportResult.Category} category + * @param {Object} [groupDefinitions] + * @return {Element} + */ + render(category, groupDefinitions = {}) { + const element = this.dom.createElement('div', 'lh-category'); + this.createPermalinkSpan(element, category.id); + element.appendChild(this.renderCategoryHeader(category, groupDefinitions)); + + const clumpElems = this.renderClumps(category.auditRefs, groupDefinitions, + category.manualDescription); + element.append(...clumpElems); + return element; + } + /** * Renders a set of top level sections (clumps), under a status of failed, warning, * manual, passed, or notApplicable. The result ends up something like: @@ -442,14 +458,13 @@ class CategoryRenderer { * ├── audit 2 * ├── … * ⋮ - * @param {LH.ReportResult.Category} category - * @param {Object} [groupDefinitions] - * @return {Element} + * @param {Array} auditRefs + * @param {Record} groupDefinitions + * @param {LH.Result.Category['manualDescription']} [manualDescription] + * @return {Array} */ - render(category, groupDefinitions = {}) { - const element = this.dom.createElement('div', 'lh-category'); - this.createPermalinkSpan(element, category.id); - element.appendChild(this.renderCategoryHeader(category, groupDefinitions)); + renderClumps(auditRefs, groupDefinitions = {}, manualDescription) { + const clumpElems = []; // Top level clumps for audits, in order they will appear in the report. /** @type {Map>} */ @@ -461,7 +476,7 @@ class CategoryRenderer { clumps.set('notApplicable', []); // Sort audits into clumps. - for (const auditRef of category.auditRefs) { + for (const auditRef of auditRefs) { const clumpId = this._getClumpIdForAuditRef(auditRef); const clump = /** @type {Array} */ (clumps.get(clumpId)); // already defined clump.push(auditRef); @@ -475,16 +490,16 @@ class CategoryRenderer { if (clumpId === 'failed') { const clumpElem = this.renderUnexpandableClump(auditRefs, groupDefinitions); clumpElem.classList.add(`lh-clump--failed`); - element.appendChild(clumpElem); + clumpElems.push(clumpElem); continue; } - const description = clumpId === 'manual' ? category.manualDescription : undefined; + const description = clumpId === 'manual' ? manualDescription : undefined; const clumpElem = this.renderClump(clumpId, {auditRefs, description}); - element.appendChild(clumpElem); + clumpElems.push(clumpElem); } - return element; + return clumpElems; } /** diff --git a/lighthouse-core/report/html/renderer/performance-category-renderer.js b/lighthouse-core/report/html/renderer/performance-category-renderer.js index c0e8762aa4f9..d3e20e52b55a 100644 --- a/lighthouse-core/report/html/renderer/performance-category-renderer.js +++ b/lighthouse-core/report/html/renderer/performance-category-renderer.js @@ -210,23 +210,26 @@ class PerformanceCategoryRenderer extends CategoryRenderer { // Filmstrip const timelineEl = this.dom.createChildOf(element, 'div', 'lh-filmstrip-container'); - const thumbnailAudit = category.auditRefs.find(audit => audit.id === 'screenshot-thumbnails'); - const thumbnailResult = thumbnailAudit && thumbnailAudit.result; - if (thumbnailResult && thumbnailResult.details) { - timelineEl.id = thumbnailResult.id; - const filmstripEl = this.detailsRenderer.render(thumbnailResult.details); - filmstripEl && timelineEl.appendChild(filmstripEl); + // We only expect one of these, but the renderer will support multiple + const thumbnailAudits = category.auditRefs.filter(audit => audit.group === 'filmstrip'); + for (const thumbnailAudit of thumbnailAudits) { + const result = thumbnailAudit.result; + if (result && result.details) { + timelineEl.id = result.id; + const filmstripEl = this.detailsRenderer.render(result.details); + filmstripEl && timelineEl.appendChild(filmstripEl); + } } // Budgets /** @type {Array} */ const budgetTableEls = []; - ['performance-budget', 'timing-budget'].forEach((id) => { - const audit = category.auditRefs.find(audit => audit.id === id); + const budgetAudits = category.auditRefs.filter(audit => audit.group === 'budgets'); + budgetAudits.forEach(audit => { if (audit && audit.result.details) { const table = this.detailsRenderer.render(audit.result.details); if (table) { - table.id = id; + table.id = audit.id; table.classList.add('lh-audit'); budgetTableEls.push(table); } @@ -281,19 +284,14 @@ class PerformanceCategoryRenderer extends CategoryRenderer { element.appendChild(groupEl); } - // Passed audits - const passedAudits = category.auditRefs - .filter(audit => (audit.group === 'load-opportunities' || audit.group === 'diagnostics') && - Util.showAsPassed(audit.result)); - - if (!passedAudits.length) return element; + // Everything else (passed, passed with warnings, n/a) + const renderedAudits = [...metricAudits, ...thumbnailAudits, ...budgetAudits, + ...opportunityAudits, ...diagnosticAudits]; + const unrenderedAudits = category.auditRefs.filter(ref => !renderedAudits.includes(ref)); + const remainingAudits = unrenderedAudits.filter(ref => !!ref.group); - const clumpOpts = { - auditRefs: passedAudits, - groupDefinitions: groups, - }; - const passedElem = this.renderClump('passed', clumpOpts); - element.appendChild(passedElem); + const clumpElems = this.renderClumps(remainingAudits, groups); + element.append(...clumpElems); return element; } } diff --git a/lighthouse-core/test/report/html/renderer/performance-category-renderer-test.js b/lighthouse-core/test/report/html/renderer/performance-category-renderer-test.js index c3a0e2a351e5..3b6c77ac8103 100644 --- a/lighthouse-core/test/report/html/renderer/performance-category-renderer-test.js +++ b/lighthouse-core/test/report/html/renderer/performance-category-renderer-test.js @@ -69,7 +69,17 @@ describe('PerfCategoryRenderer', () => { it('renders the sections', () => { const categoryDOM = renderer.render(category, sampleResults.categoryGroups); const sections = categoryDOM.querySelectorAll('.lh-category > .lh-audit-group'); - assert.equal(sections.length, 5); + const sectionTitles = Array.from(sections).map(el => el.className); + expect(sectionTitles).toMatchInlineSnapshot(` +Array [ + "lh-audit-group lh-audit-group--metrics", + "lh-audit-group lh-audit-group--budgets", + "lh-audit-group lh-audit-group--load-opportunities", + "lh-audit-group lh-audit-group--diagnostics", + "lh-clump lh-audit-group lh-clump--passed", + "lh-clump lh-audit-group lh-clump--notapplicable", +] +`); }); it('renders the metrics', () => { @@ -166,11 +176,18 @@ describe('PerfCategoryRenderer', () => { const categoryDOM = renderer.render(category, sampleResults.categoryGroups); const passedSection = categoryDOM.querySelector('.lh-category > .lh-clump--passed'); - const passedAudits = category.auditRefs.filter(audit => - audit.group && audit.group !== 'metrics' && audit.id !== 'performance-budget' - && Util.showAsPassed(audit.result)); + const passedAuditIds = category.auditRefs.filter( + audit => + audit.group && + audit.group !== 'metrics' && + audit.id !== 'performance-budget' && + Util.showAsPassed(audit.result) && + audit.result.scoreDisplayMode !== 'notApplicable' + ).map(ref => ref.id); + const passedElements = passedSection.querySelectorAll('.lh-audit'); - assert.equal(passedElements.length, passedAudits.length); + const passedElemIds = Array.from(passedElements).map(el => el.id); + expect(passedAuditIds).toEqual(passedElemIds); }); // Unsupported by perf cat renderer right now. diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index 0f8c72460257..acd4b033425b 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -4538,6 +4538,11 @@ "weight": 0, "group": "diagnostics" }, + { + "id": "screenshot-thumbnails", + "weight": 0, + "group": "filmstrip" + }, { "id": "network-requests", "weight": 0 @@ -4562,10 +4567,6 @@ "id": "metrics", "weight": 0 }, - { - "id": "screenshot-thumbnails", - "weight": 0 - }, { "id": "final-screenshot", "weight": 0 @@ -5111,6 +5112,9 @@ "title": "Diagnostics", "description": "More information about the performance of your application. These numbers don't [directly affect](https://web.dev/performance-scoring/) the Performance score." }, + "filmstrip": { + "title": "" + }, "pwa-fast-reliable": { "title": "Fast and reliable" },