diff --git a/core/audits/lcp-lazy-loaded.js b/core/audits/lcp-lazy-loaded.js index 7ce45af1e470..1a831dc0f08f 100644 --- a/core/audits/lcp-lazy-loaded.js +++ b/core/audits/lcp-lazy-loaded.js @@ -7,6 +7,8 @@ import {Audit} from './audit.js'; import * as i18n from '../lib/i18n/i18n.js'; +import ImageRecords from '../computed/image-records.js'; +import NetworkRecords from '../computed/network-records.js'; const UIStrings = { /** Title of a Lighthouse audit that provides detail on whether the largest above-the-fold image was loaded with sufficient priority. This descriptive title is shown to users when the image was loaded properly. */ @@ -30,7 +32,7 @@ class LargestContentfulPaintLazyLoaded extends Audit { failureTitle: str_(UIStrings.failureTitle), description: str_(UIStrings.description), supportedModes: ['navigation'], - requiredArtifacts: ['TraceElements', 'ViewportDimensions', 'ImageElements'], + requiredArtifacts: ['TraceElements', 'ViewportDimensions', 'ImageElements', 'devtoolsLogs'], }; } @@ -47,16 +49,22 @@ class LargestContentfulPaintLazyLoaded extends Audit { /** * @param {LH.Artifacts} artifacts - * @return {LH.Audit.Product} + * @param {LH.Audit.Context} context + * @return {Promise} */ - static audit(artifacts) { + static async audit(artifacts, context) { + const devtoolsLog = artifacts.devtoolsLogs[LargestContentfulPaintLazyLoaded.DEFAULT_PASS]; + const networkRecords = await NetworkRecords.request(devtoolsLog, context); + const images = await ImageRecords.request({ + ImageElements: artifacts.ImageElements, + networkRecords, + }, context); const lcpElement = artifacts.TraceElements .find(element => element.traceEventType === 'largest-contentful-paint'); - const lcpElementImage = lcpElement ? artifacts.ImageElements.find(elem => { + const lcpElementImage = lcpElement ? images.find(elem => { return elem.node.devtoolsNodePath === lcpElement.node.devtoolsNodePath; }) : undefined; - if (!lcpElementImage || !this.isImageInViewport(lcpElementImage, artifacts.ViewportDimensions)) { return {score: 1, notApplicable: true}; diff --git a/core/audits/preload-lcp-image.js b/core/audits/preload-lcp-image.js index cd871b260980..8f77ce986bd6 100644 --- a/core/audits/preload-lcp-image.js +++ b/core/audits/preload-lcp-image.js @@ -12,6 +12,8 @@ import MainResource from '../computed/main-resource.js'; import LanternLCP from '../computed/metrics/lantern-largest-contentful-paint.js'; import LoadSimulator from '../computed/load-simulator.js'; import {ByteEfficiencyAudit} from './byte-efficiency/byte-efficiency-audit.js'; +import ImageRecords from '../computed/image-records.js'; +import NetworkRecords from '../computed/network-records.js'; const UIStrings = { /** Title of a lighthouse audit that tells a user to preload an image in order to improve their LCP time. */ @@ -217,6 +219,11 @@ class PreloadLCPImageAudit extends Audit { const gatherContext = artifacts.GatherContext; const trace = artifacts.traces[PreloadLCPImageAudit.DEFAULT_PASS]; const devtoolsLog = artifacts.devtoolsLogs[PreloadLCPImageAudit.DEFAULT_PASS]; + const networkRecords = await NetworkRecords.request(devtoolsLog, context); + const images = await ImageRecords.request({ + ImageElements: artifacts.ImageElements, + networkRecords, + }, context); const URL = artifacts.URL; const metricData = {trace, devtoolsLog, gatherContext, settings: context.settings, URL}; const lcpElement = artifacts.TraceElements @@ -230,7 +237,7 @@ class PreloadLCPImageAudit extends Audit { const graph = lanternLCP.pessimisticGraph; // eslint-disable-next-line max-len - const {lcpNodeToPreload, initiatorPath} = PreloadLCPImageAudit.getLCPNodeToPreload(mainResource, graph, lcpElement, artifacts.ImageElements); + const {lcpNodeToPreload, initiatorPath} = PreloadLCPImageAudit.getLCPNodeToPreload(mainResource, graph, lcpElement, images); const {results, wastedMs} = PreloadLCPImageAudit.computeWasteWithGraph(lcpElement, lcpNodeToPreload, graph, simulator); diff --git a/core/computed/image-records.js b/core/computed/image-records.js index 5473d7c5c7a0..a9a77cd4c4c6 100644 --- a/core/computed/image-records.js +++ b/core/computed/image-records.js @@ -5,7 +5,6 @@ */ 'use strict'; -import URL from '../lib/url-shim.js'; import {makeComputedArtifact} from './computed-artifact.js'; class ImageRecords { @@ -39,12 +38,13 @@ class ImageRecords { for (const element of data.ImageElements) { const networkRecord = indexedNetworkRecords[element.src]; - const mimeType = networkRecord?.mimeType; + // Ignore if we aren't sure this is really an image. + // TODO: we should add something in tracing to get this straight from blink. + if (!networkRecord) continue; - // Don't change the guessed mime type if no mime type was found. imageRecords.push({ ...element, - mimeType: mimeType ? mimeType : URL.guessMimeType(element.src), + mimeType: networkRecord.mimeType, }); } diff --git a/core/test/audits/byte-efficiency/uses-responsive-images-test.js b/core/test/audits/byte-efficiency/uses-responsive-images-test.js index d765e916376e..398f78641622 100644 --- a/core/test/audits/byte-efficiency/uses-responsive-images-test.js +++ b/core/test/audits/byte-efficiency/uses-responsive-images-test.js @@ -278,6 +278,8 @@ describe('Page uses responsive images', () => { mimeType: 'image/png', resourceSize: 1024 * 100, transferSize: 0, + finished: true, + statusCode: 200, url: 'https://google.com/logo.png', }; const auditResult = await UsesResponsiveImagesAudit.audit_({ diff --git a/core/test/audits/lcp-lazy-loaded-test.js b/core/test/audits/lcp-lazy-loaded-test.js index a7f2617d5a46..05ab16906571 100644 --- a/core/test/audits/lcp-lazy-loaded-test.js +++ b/core/test/audits/lcp-lazy-loaded-test.js @@ -5,6 +5,8 @@ */ import LargestContentfulPaintLazyLoaded from '../../audits/lcp-lazy-loaded.js'; +import {createTestTrace} from '../create-test-trace.js'; +import {networkRecordsToDevtoolsLog} from '../network-records-to-devtools-log.js'; const SAMPLE_NODE = { devtoolsNodePath: '1,HTML,1,BODY,3,DIV,2,IMG', @@ -14,7 +16,7 @@ const SAMPLE_NODE = { }; function generateImage(loading, clientRectTop) { return { - src: 'test', + src: 'http://example.com/test.png', loading, clientRect: { top: clientRectTop, @@ -25,23 +27,41 @@ function generateImage(loading, clientRectTop) { node: SAMPLE_NODE, }; } + +/** + * @param {ImageElement[]} imageElements + */ +function createArtifacts(imageElements) { + const networkRecords = imageElements.map(e => ({ + url: e.src, + mimeType: 'image/png', + })); + return { + traces: { + [LargestContentfulPaintLazyLoaded.DEFAULT_PASS]: createTestTrace({ + traceEnd: 6e3, + largestContentfulPaint: 45e2, + }), + }, + devtoolsLogs: {[LargestContentfulPaintLazyLoaded.DEFAULT_PASS]: + networkRecordsToDevtoolsLog(networkRecords)}, + TraceElements: imageElements.length ? [{ + traceEventType: 'largest-contentful-paint', + node: SAMPLE_NODE, + }] : [], + ImageElements: imageElements, + ViewportDimensions: { + innerHeight: 500, + innerWidth: 300, + }, + }; +} + describe('Performance: lcp-lazy-loaded audit', () => { it('correctly surfaces the lazy loaded LCP element', async () => { - const artifacts = { - TraceElements: [{ - traceEventType: 'largest-contentful-paint', - node: SAMPLE_NODE, - }], - ImageElements: [ - generateImage('lazy', 0), - ], - ViewportDimensions: { - innerHeight: 500, - innerWidth: 300, - }, - }; - - const auditResult = await LargestContentfulPaintLazyLoaded.audit(artifacts); + const artifacts = createArtifacts([generateImage('lazy', 0)]); + const context = {settings: {}, computedCache: new Map()}; + const auditResult = await LargestContentfulPaintLazyLoaded.audit(artifacts, context); expect(auditResult.score).toEqual(0); expect(auditResult.details.items).toHaveLength(1); expect(auditResult.details.items[0].node.path).toEqual('1,HTML,1,BODY,3,DIV,2,IMG'); @@ -50,49 +70,24 @@ describe('Performance: lcp-lazy-loaded audit', () => { }); it('eager LCP element scores 1', async () => { - const artifacts = { - TraceElements: [{ - traceEventType: 'largest-contentful-paint', - node: SAMPLE_NODE, - }], - ImageElements: [ - generateImage('eager', 0), - ], - ViewportDimensions: { - innerHeight: 500, - innerWidth: 300, - }, - }; - const auditResult = await LargestContentfulPaintLazyLoaded.audit(artifacts); + const artifacts = createArtifacts([generateImage('eager', 0)]); + const context = {settings: {}, computedCache: new Map()}; + const auditResult = await LargestContentfulPaintLazyLoaded.audit(artifacts, context); expect(auditResult.score).toEqual(1); expect(auditResult.details.items).toHaveLength(1); }); it('not applicable when outside of viewport', async () => { - const artifacts = { - TraceElements: [{ - traceEventType: 'largest-contentful-paint', - node: SAMPLE_NODE, - }], - ImageElements: [ - generateImage('lazy', 700), - ], - ViewportDimensions: { - innerHeight: 500, - innerWidth: 300, - }, - }; - const auditResult = await LargestContentfulPaintLazyLoaded.audit(artifacts); + const artifacts = createArtifacts([generateImage('lazy', 700)]); + const context = {settings: {}, computedCache: new Map()}; + const auditResult = await LargestContentfulPaintLazyLoaded.audit(artifacts, context); expect(auditResult.notApplicable).toEqual(true); }); it('doesn\'t throw an error when there is nothing to show', async () => { - const artifacts = { - TraceElements: [], - ImageElements: [], - }; - - const auditResult = await LargestContentfulPaintLazyLoaded.audit(artifacts); + const artifacts = createArtifacts([]); + const context = {settings: {}, computedCache: new Map()}; + const auditResult = await LargestContentfulPaintLazyLoaded.audit(artifacts, context); expect(auditResult.score).toEqual(1); expect(auditResult.notApplicable).toEqual(true); }); diff --git a/core/test/audits/preload-lcp-image-test.js b/core/test/audits/preload-lcp-image-test.js index 34f68a80682f..b908ed31781a 100644 --- a/core/test/audits/preload-lcp-image-test.js +++ b/core/test/audits/preload-lcp-image-test.js @@ -82,6 +82,7 @@ describe('Performance: preload-lcp audit', () => { { requestId: '4', resourceType: 'Image', + mimeType: 'image/png', priority: 'High', isLinkPreload: false, startTime: 2, diff --git a/core/test/computed/image-records-test.js b/core/test/computed/image-records-test.js index 95938a23a900..e6b02236360c 100644 --- a/core/test/computed/image-records-test.js +++ b/core/test/computed/image-records-test.js @@ -22,7 +22,7 @@ function mockRequest(partial = {}) { */ function mockElement(partial = {}) { return { - src: 'https://example.com/img.png', + src: partial.src ?? 'https://example.com/img.png', srcset: '', displayedWidth: 200, displayedHeight: 200, @@ -159,14 +159,28 @@ describe('compute_', () => { expect(elements).toEqual([mockElement({mimeType: 'image/png'})]); }); - it('guess mime type if no request', async () => { + it('ignore image element if no valid record', async () => { const elements = await ImageRecords.compute_({ ImageElements: [ - mockElement(), + mockElement({src: 'https://example.com/img.png'}), + mockElement({src: 'https://example.com/img2.png'}), + ], + networkRecords: [ + mockRequest({ + mimeType: 'iam/trash', + url: 'https://example.com/img.png', + finished: true, + statusCode: 200, + }), + mockRequest({ + mimeType: 'image/png', + url: 'https://example.com/img2.png', + finished: true, + statusCode: 500, + }), ], - networkRecords: [], }); - expect(elements).toEqual([mockElement({mimeType: 'image/png'})]); + expect(elements).toEqual([]); }); }); diff --git a/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json b/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json index f67677a8c8bc..34d679408659 100644 --- a/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json +++ b/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json @@ -5311,73 +5311,73 @@ }, { "startTime": 104, - "name": "lh:audit:layout-shift-elements", + "name": "lh:computed:ImageRecords", "duration": 1, "entryType": "measure" }, { "startTime": 105, - "name": "lh:audit:long-tasks", + "name": "lh:audit:layout-shift-elements", "duration": 1, "entryType": "measure" }, { "startTime": 106, - "name": "lh:audit:no-unload-listeners", + "name": "lh:audit:long-tasks", "duration": 1, "entryType": "measure" }, { "startTime": 107, - "name": "lh:audit:non-composited-animations", + "name": "lh:audit:no-unload-listeners", "duration": 1, "entryType": "measure" }, { "startTime": 108, - "name": "lh:audit:unsized-images", + "name": "lh:audit:non-composited-animations", "duration": 1, "entryType": "measure" }, { "startTime": 109, - "name": "lh:audit:valid-source-maps", + "name": "lh:audit:unsized-images", "duration": 1, "entryType": "measure" }, { "startTime": 110, - "name": "lh:audit:preload-lcp-image", + "name": "lh:audit:valid-source-maps", "duration": 1, "entryType": "measure" }, { "startTime": 111, - "name": "lh:audit:csp-xss", + "name": "lh:audit:preload-lcp-image", "duration": 1, "entryType": "measure" }, { "startTime": 112, - "name": "lh:audit:full-page-screenshot", + "name": "lh:audit:csp-xss", "duration": 1, "entryType": "measure" }, { "startTime": 113, - "name": "lh:audit:script-treemap-data", + "name": "lh:audit:full-page-screenshot", "duration": 1, "entryType": "measure" }, { "startTime": 114, - "name": "lh:computed:ModuleDuplication", + "name": "lh:audit:script-treemap-data", "duration": 1, "entryType": "measure" }, { "startTime": 115, - "name": "lh:computed:UnusedJavascriptSummary", + "name": "lh:computed:ModuleDuplication", "duration": 1, "entryType": "measure" }, @@ -5461,433 +5461,433 @@ }, { "startTime": 129, - "name": "lh:audit:pwa-cross-browser", + "name": "lh:computed:UnusedJavascriptSummary", "duration": 1, "entryType": "measure" }, { "startTime": 130, - "name": "lh:audit:pwa-page-transitions", + "name": "lh:audit:pwa-cross-browser", "duration": 1, "entryType": "measure" }, { "startTime": 131, - "name": "lh:audit:pwa-each-page-has-url", + "name": "lh:audit:pwa-page-transitions", "duration": 1, "entryType": "measure" }, { "startTime": 132, - "name": "lh:audit:accesskeys", + "name": "lh:audit:pwa-each-page-has-url", "duration": 1, "entryType": "measure" }, { "startTime": 133, - "name": "lh:audit:aria-allowed-attr", + "name": "lh:audit:accesskeys", "duration": 1, "entryType": "measure" }, { "startTime": 134, - "name": "lh:audit:aria-command-name", + "name": "lh:audit:aria-allowed-attr", "duration": 1, "entryType": "measure" }, { "startTime": 135, - "name": "lh:audit:aria-hidden-body", + "name": "lh:audit:aria-command-name", "duration": 1, "entryType": "measure" }, { "startTime": 136, - "name": "lh:audit:aria-hidden-focus", + "name": "lh:audit:aria-hidden-body", "duration": 1, "entryType": "measure" }, { "startTime": 137, - "name": "lh:audit:aria-input-field-name", + "name": "lh:audit:aria-hidden-focus", "duration": 1, "entryType": "measure" }, { "startTime": 138, - "name": "lh:audit:aria-meter-name", + "name": "lh:audit:aria-input-field-name", "duration": 1, "entryType": "measure" }, { "startTime": 139, - "name": "lh:audit:aria-progressbar-name", + "name": "lh:audit:aria-meter-name", "duration": 1, "entryType": "measure" }, { "startTime": 140, - "name": "lh:audit:aria-required-attr", + "name": "lh:audit:aria-progressbar-name", "duration": 1, "entryType": "measure" }, { "startTime": 141, - "name": "lh:audit:aria-required-children", + "name": "lh:audit:aria-required-attr", "duration": 1, "entryType": "measure" }, { "startTime": 142, - "name": "lh:audit:aria-required-parent", + "name": "lh:audit:aria-required-children", "duration": 1, "entryType": "measure" }, { "startTime": 143, - "name": "lh:audit:aria-roles", + "name": "lh:audit:aria-required-parent", "duration": 1, "entryType": "measure" }, { "startTime": 144, - "name": "lh:audit:aria-toggle-field-name", + "name": "lh:audit:aria-roles", "duration": 1, "entryType": "measure" }, { "startTime": 145, - "name": "lh:audit:aria-tooltip-name", + "name": "lh:audit:aria-toggle-field-name", "duration": 1, "entryType": "measure" }, { "startTime": 146, - "name": "lh:audit:aria-treeitem-name", + "name": "lh:audit:aria-tooltip-name", "duration": 1, "entryType": "measure" }, { "startTime": 147, - "name": "lh:audit:aria-valid-attr-value", + "name": "lh:audit:aria-treeitem-name", "duration": 1, "entryType": "measure" }, { "startTime": 148, - "name": "lh:audit:aria-valid-attr", + "name": "lh:audit:aria-valid-attr-value", "duration": 1, "entryType": "measure" }, { "startTime": 149, - "name": "lh:audit:button-name", + "name": "lh:audit:aria-valid-attr", "duration": 1, "entryType": "measure" }, { "startTime": 150, - "name": "lh:audit:bypass", + "name": "lh:audit:button-name", "duration": 1, "entryType": "measure" }, { "startTime": 151, - "name": "lh:audit:color-contrast", + "name": "lh:audit:bypass", "duration": 1, "entryType": "measure" }, { "startTime": 152, - "name": "lh:audit:definition-list", + "name": "lh:audit:color-contrast", "duration": 1, "entryType": "measure" }, { "startTime": 153, - "name": "lh:audit:dlitem", + "name": "lh:audit:definition-list", "duration": 1, "entryType": "measure" }, { "startTime": 154, - "name": "lh:audit:document-title", + "name": "lh:audit:dlitem", "duration": 1, "entryType": "measure" }, { "startTime": 155, - "name": "lh:audit:duplicate-id-active", + "name": "lh:audit:document-title", "duration": 1, "entryType": "measure" }, { "startTime": 156, - "name": "lh:audit:duplicate-id-aria", + "name": "lh:audit:duplicate-id-active", "duration": 1, "entryType": "measure" }, { "startTime": 157, - "name": "lh:audit:form-field-multiple-labels", + "name": "lh:audit:duplicate-id-aria", "duration": 1, "entryType": "measure" }, { "startTime": 158, - "name": "lh:audit:frame-title", + "name": "lh:audit:form-field-multiple-labels", "duration": 1, "entryType": "measure" }, { "startTime": 159, - "name": "lh:audit:heading-order", + "name": "lh:audit:frame-title", "duration": 1, "entryType": "measure" }, { "startTime": 160, - "name": "lh:audit:html-has-lang", + "name": "lh:audit:heading-order", "duration": 1, "entryType": "measure" }, { "startTime": 161, - "name": "lh:audit:html-lang-valid", + "name": "lh:audit:html-has-lang", "duration": 1, "entryType": "measure" }, { "startTime": 162, - "name": "lh:audit:image-alt", + "name": "lh:audit:html-lang-valid", "duration": 1, "entryType": "measure" }, { "startTime": 163, - "name": "lh:audit:input-image-alt", + "name": "lh:audit:image-alt", "duration": 1, "entryType": "measure" }, { "startTime": 164, - "name": "lh:audit:label", + "name": "lh:audit:input-image-alt", "duration": 1, "entryType": "measure" }, { "startTime": 165, - "name": "lh:audit:link-name", + "name": "lh:audit:label", "duration": 1, "entryType": "measure" }, { "startTime": 166, - "name": "lh:audit:list", + "name": "lh:audit:link-name", "duration": 1, "entryType": "measure" }, { "startTime": 167, - "name": "lh:audit:listitem", + "name": "lh:audit:list", "duration": 1, "entryType": "measure" }, { "startTime": 168, - "name": "lh:audit:meta-refresh", + "name": "lh:audit:listitem", "duration": 1, "entryType": "measure" }, { "startTime": 169, - "name": "lh:audit:meta-viewport", + "name": "lh:audit:meta-refresh", "duration": 1, "entryType": "measure" }, { "startTime": 170, - "name": "lh:audit:object-alt", + "name": "lh:audit:meta-viewport", "duration": 1, "entryType": "measure" }, { "startTime": 171, - "name": "lh:audit:tabindex", + "name": "lh:audit:object-alt", "duration": 1, "entryType": "measure" }, { "startTime": 172, - "name": "lh:audit:td-headers-attr", + "name": "lh:audit:tabindex", "duration": 1, "entryType": "measure" }, { "startTime": 173, - "name": "lh:audit:th-has-data-cells", + "name": "lh:audit:td-headers-attr", "duration": 1, "entryType": "measure" }, { "startTime": 174, - "name": "lh:audit:valid-lang", + "name": "lh:audit:th-has-data-cells", "duration": 1, "entryType": "measure" }, { "startTime": 175, - "name": "lh:audit:video-caption", + "name": "lh:audit:valid-lang", "duration": 1, "entryType": "measure" }, { "startTime": 176, - "name": "lh:audit:custom-controls-labels", + "name": "lh:audit:video-caption", "duration": 1, "entryType": "measure" }, { "startTime": 177, - "name": "lh:audit:custom-controls-roles", + "name": "lh:audit:custom-controls-labels", "duration": 1, "entryType": "measure" }, { "startTime": 178, - "name": "lh:audit:focus-traps", + "name": "lh:audit:custom-controls-roles", "duration": 1, "entryType": "measure" }, { "startTime": 179, - "name": "lh:audit:focusable-controls", + "name": "lh:audit:focus-traps", "duration": 1, "entryType": "measure" }, { "startTime": 180, - "name": "lh:audit:interactive-element-affordance", + "name": "lh:audit:focusable-controls", "duration": 1, "entryType": "measure" }, { "startTime": 181, - "name": "lh:audit:logical-tab-order", + "name": "lh:audit:interactive-element-affordance", "duration": 1, "entryType": "measure" }, { "startTime": 182, - "name": "lh:audit:managed-focus", + "name": "lh:audit:logical-tab-order", "duration": 1, "entryType": "measure" }, { "startTime": 183, - "name": "lh:audit:offscreen-content-hidden", + "name": "lh:audit:managed-focus", "duration": 1, "entryType": "measure" }, { "startTime": 184, - "name": "lh:audit:use-landmarks", + "name": "lh:audit:offscreen-content-hidden", "duration": 1, "entryType": "measure" }, { "startTime": 185, - "name": "lh:audit:visual-order-follows-dom", + "name": "lh:audit:use-landmarks", "duration": 1, "entryType": "measure" }, { "startTime": 186, - "name": "lh:audit:uses-long-cache-ttl", + "name": "lh:audit:visual-order-follows-dom", "duration": 1, "entryType": "measure" }, { "startTime": 187, - "name": "lh:audit:total-byte-weight", + "name": "lh:audit:uses-long-cache-ttl", "duration": 1, "entryType": "measure" }, { "startTime": 188, - "name": "lh:audit:offscreen-images", + "name": "lh:audit:total-byte-weight", "duration": 1, "entryType": "measure" }, { "startTime": 189, - "name": "lh:audit:render-blocking-resources", + "name": "lh:audit:offscreen-images", "duration": 1, "entryType": "measure" }, { "startTime": 190, - "name": "lh:computed:UnusedCSS", + "name": "lh:audit:render-blocking-resources", "duration": 1, "entryType": "measure" }, { "startTime": 191, - "name": "lh:computed:FirstContentfulPaint", + "name": "lh:computed:UnusedCSS", "duration": 1, "entryType": "measure" }, { "startTime": 192, - "name": "lh:audit:unminified-css", + "name": "lh:computed:FirstContentfulPaint", "duration": 1, "entryType": "measure" }, { "startTime": 193, - "name": "lh:audit:unminified-javascript", + "name": "lh:audit:unminified-css", "duration": 1, "entryType": "measure" }, { "startTime": 194, - "name": "lh:audit:unused-css-rules", + "name": "lh:audit:unminified-javascript", "duration": 1, "entryType": "measure" }, { "startTime": 195, - "name": "lh:audit:unused-javascript", + "name": "lh:audit:unused-css-rules", "duration": 1, "entryType": "measure" }, { "startTime": 196, - "name": "lh:audit:modern-image-formats", + "name": "lh:audit:unused-javascript", "duration": 1, "entryType": "measure" }, { "startTime": 197, - "name": "lh:audit:uses-optimized-images", + "name": "lh:audit:modern-image-formats", "duration": 1, "entryType": "measure" }, { "startTime": 198, - "name": "lh:audit:uses-text-compression", + "name": "lh:audit:uses-optimized-images", "duration": 1, "entryType": "measure" }, { "startTime": 199, - "name": "lh:audit:uses-responsive-images", + "name": "lh:audit:uses-text-compression", "duration": 1, "entryType": "measure" }, { "startTime": 200, - "name": "lh:computed:ImageRecords", + "name": "lh:audit:uses-responsive-images", "duration": 1, "entryType": "measure" }, @@ -19544,73 +19544,73 @@ }, { "startTime": 102, - "name": "lh:audit:layout-shift-elements", + "name": "lh:computed:ImageRecords", "duration": 1, "entryType": "measure" }, { "startTime": 103, - "name": "lh:audit:long-tasks", + "name": "lh:audit:layout-shift-elements", "duration": 1, "entryType": "measure" }, { "startTime": 104, - "name": "lh:audit:no-unload-listeners", + "name": "lh:audit:long-tasks", "duration": 1, "entryType": "measure" }, { "startTime": 105, - "name": "lh:audit:non-composited-animations", + "name": "lh:audit:no-unload-listeners", "duration": 1, "entryType": "measure" }, { "startTime": 106, - "name": "lh:audit:unsized-images", + "name": "lh:audit:non-composited-animations", "duration": 1, "entryType": "measure" }, { "startTime": 107, - "name": "lh:audit:valid-source-maps", + "name": "lh:audit:unsized-images", "duration": 1, "entryType": "measure" }, { "startTime": 108, - "name": "lh:audit:preload-lcp-image", + "name": "lh:audit:valid-source-maps", "duration": 1, "entryType": "measure" }, { "startTime": 109, - "name": "lh:audit:csp-xss", + "name": "lh:audit:preload-lcp-image", "duration": 1, "entryType": "measure" }, { "startTime": 110, - "name": "lh:audit:full-page-screenshot", + "name": "lh:audit:csp-xss", "duration": 1, "entryType": "measure" }, { "startTime": 111, - "name": "lh:audit:script-treemap-data", + "name": "lh:audit:full-page-screenshot", "duration": 1, "entryType": "measure" }, { "startTime": 112, - "name": "lh:computed:ModuleDuplication", + "name": "lh:audit:script-treemap-data", "duration": 1, "entryType": "measure" }, { "startTime": 113, - "name": "lh:computed:UnusedJavascriptSummary", + "name": "lh:computed:ModuleDuplication", "duration": 1, "entryType": "measure" }, @@ -19688,433 +19688,433 @@ }, { "startTime": 126, - "name": "lh:audit:pwa-cross-browser", + "name": "lh:computed:UnusedJavascriptSummary", "duration": 1, "entryType": "measure" }, { "startTime": 127, - "name": "lh:audit:pwa-page-transitions", + "name": "lh:audit:pwa-cross-browser", "duration": 1, "entryType": "measure" }, { "startTime": 128, - "name": "lh:audit:pwa-each-page-has-url", + "name": "lh:audit:pwa-page-transitions", "duration": 1, "entryType": "measure" }, { "startTime": 129, - "name": "lh:audit:accesskeys", + "name": "lh:audit:pwa-each-page-has-url", "duration": 1, "entryType": "measure" }, { "startTime": 130, - "name": "lh:audit:aria-allowed-attr", + "name": "lh:audit:accesskeys", "duration": 1, "entryType": "measure" }, { "startTime": 131, - "name": "lh:audit:aria-command-name", + "name": "lh:audit:aria-allowed-attr", "duration": 1, "entryType": "measure" }, { "startTime": 132, - "name": "lh:audit:aria-hidden-body", + "name": "lh:audit:aria-command-name", "duration": 1, "entryType": "measure" }, { "startTime": 133, - "name": "lh:audit:aria-hidden-focus", + "name": "lh:audit:aria-hidden-body", "duration": 1, "entryType": "measure" }, { "startTime": 134, - "name": "lh:audit:aria-input-field-name", + "name": "lh:audit:aria-hidden-focus", "duration": 1, "entryType": "measure" }, { "startTime": 135, - "name": "lh:audit:aria-meter-name", + "name": "lh:audit:aria-input-field-name", "duration": 1, "entryType": "measure" }, { "startTime": 136, - "name": "lh:audit:aria-progressbar-name", + "name": "lh:audit:aria-meter-name", "duration": 1, "entryType": "measure" }, { "startTime": 137, - "name": "lh:audit:aria-required-attr", + "name": "lh:audit:aria-progressbar-name", "duration": 1, "entryType": "measure" }, { "startTime": 138, - "name": "lh:audit:aria-required-children", + "name": "lh:audit:aria-required-attr", "duration": 1, "entryType": "measure" }, { "startTime": 139, - "name": "lh:audit:aria-required-parent", + "name": "lh:audit:aria-required-children", "duration": 1, "entryType": "measure" }, { "startTime": 140, - "name": "lh:audit:aria-roles", + "name": "lh:audit:aria-required-parent", "duration": 1, "entryType": "measure" }, { "startTime": 141, - "name": "lh:audit:aria-toggle-field-name", + "name": "lh:audit:aria-roles", "duration": 1, "entryType": "measure" }, { "startTime": 142, - "name": "lh:audit:aria-tooltip-name", + "name": "lh:audit:aria-toggle-field-name", "duration": 1, "entryType": "measure" }, { "startTime": 143, - "name": "lh:audit:aria-treeitem-name", + "name": "lh:audit:aria-tooltip-name", "duration": 1, "entryType": "measure" }, { "startTime": 144, - "name": "lh:audit:aria-valid-attr-value", + "name": "lh:audit:aria-treeitem-name", "duration": 1, "entryType": "measure" }, { "startTime": 145, - "name": "lh:audit:aria-valid-attr", + "name": "lh:audit:aria-valid-attr-value", "duration": 1, "entryType": "measure" }, { "startTime": 146, - "name": "lh:audit:button-name", + "name": "lh:audit:aria-valid-attr", "duration": 1, "entryType": "measure" }, { "startTime": 147, - "name": "lh:audit:bypass", + "name": "lh:audit:button-name", "duration": 1, "entryType": "measure" }, { "startTime": 148, - "name": "lh:audit:color-contrast", + "name": "lh:audit:bypass", "duration": 1, "entryType": "measure" }, { "startTime": 149, - "name": "lh:audit:definition-list", + "name": "lh:audit:color-contrast", "duration": 1, "entryType": "measure" }, { "startTime": 150, - "name": "lh:audit:dlitem", + "name": "lh:audit:definition-list", "duration": 1, "entryType": "measure" }, { "startTime": 151, - "name": "lh:audit:document-title", + "name": "lh:audit:dlitem", "duration": 1, "entryType": "measure" }, { "startTime": 152, - "name": "lh:audit:duplicate-id-active", + "name": "lh:audit:document-title", "duration": 1, "entryType": "measure" }, { "startTime": 153, - "name": "lh:audit:duplicate-id-aria", + "name": "lh:audit:duplicate-id-active", "duration": 1, "entryType": "measure" }, { "startTime": 154, - "name": "lh:audit:form-field-multiple-labels", + "name": "lh:audit:duplicate-id-aria", "duration": 1, "entryType": "measure" }, { "startTime": 155, - "name": "lh:audit:frame-title", + "name": "lh:audit:form-field-multiple-labels", "duration": 1, "entryType": "measure" }, { "startTime": 156, - "name": "lh:audit:heading-order", + "name": "lh:audit:frame-title", "duration": 1, "entryType": "measure" }, { "startTime": 157, - "name": "lh:audit:html-has-lang", + "name": "lh:audit:heading-order", "duration": 1, "entryType": "measure" }, { "startTime": 158, - "name": "lh:audit:html-lang-valid", + "name": "lh:audit:html-has-lang", "duration": 1, "entryType": "measure" }, { "startTime": 159, - "name": "lh:audit:image-alt", + "name": "lh:audit:html-lang-valid", "duration": 1, "entryType": "measure" }, { "startTime": 160, - "name": "lh:audit:input-image-alt", + "name": "lh:audit:image-alt", "duration": 1, "entryType": "measure" }, { "startTime": 161, - "name": "lh:audit:label", + "name": "lh:audit:input-image-alt", "duration": 1, "entryType": "measure" }, { "startTime": 162, - "name": "lh:audit:link-name", + "name": "lh:audit:label", "duration": 1, "entryType": "measure" }, { "startTime": 163, - "name": "lh:audit:list", + "name": "lh:audit:link-name", "duration": 1, "entryType": "measure" }, { "startTime": 164, - "name": "lh:audit:listitem", + "name": "lh:audit:list", "duration": 1, "entryType": "measure" }, { "startTime": 165, - "name": "lh:audit:meta-refresh", + "name": "lh:audit:listitem", "duration": 1, "entryType": "measure" }, { "startTime": 166, - "name": "lh:audit:meta-viewport", + "name": "lh:audit:meta-refresh", "duration": 1, "entryType": "measure" }, { "startTime": 167, - "name": "lh:audit:object-alt", + "name": "lh:audit:meta-viewport", "duration": 1, "entryType": "measure" }, { "startTime": 168, - "name": "lh:audit:tabindex", + "name": "lh:audit:object-alt", "duration": 1, "entryType": "measure" }, { "startTime": 169, - "name": "lh:audit:td-headers-attr", + "name": "lh:audit:tabindex", "duration": 1, "entryType": "measure" }, { "startTime": 170, - "name": "lh:audit:th-has-data-cells", + "name": "lh:audit:td-headers-attr", "duration": 1, "entryType": "measure" }, { "startTime": 171, - "name": "lh:audit:valid-lang", + "name": "lh:audit:th-has-data-cells", "duration": 1, "entryType": "measure" }, { "startTime": 172, - "name": "lh:audit:video-caption", + "name": "lh:audit:valid-lang", "duration": 1, "entryType": "measure" }, { "startTime": 173, - "name": "lh:audit:custom-controls-labels", + "name": "lh:audit:video-caption", "duration": 1, "entryType": "measure" }, { "startTime": 174, - "name": "lh:audit:custom-controls-roles", + "name": "lh:audit:custom-controls-labels", "duration": 1, "entryType": "measure" }, { "startTime": 175, - "name": "lh:audit:focus-traps", + "name": "lh:audit:custom-controls-roles", "duration": 1, "entryType": "measure" }, { "startTime": 176, - "name": "lh:audit:focusable-controls", + "name": "lh:audit:focus-traps", "duration": 1, "entryType": "measure" }, { "startTime": 177, - "name": "lh:audit:interactive-element-affordance", + "name": "lh:audit:focusable-controls", "duration": 1, "entryType": "measure" }, { "startTime": 178, - "name": "lh:audit:logical-tab-order", + "name": "lh:audit:interactive-element-affordance", "duration": 1, "entryType": "measure" }, { "startTime": 179, - "name": "lh:audit:managed-focus", + "name": "lh:audit:logical-tab-order", "duration": 1, "entryType": "measure" }, { "startTime": 180, - "name": "lh:audit:offscreen-content-hidden", + "name": "lh:audit:managed-focus", "duration": 1, "entryType": "measure" }, { "startTime": 181, - "name": "lh:audit:use-landmarks", + "name": "lh:audit:offscreen-content-hidden", "duration": 1, "entryType": "measure" }, { "startTime": 182, - "name": "lh:audit:visual-order-follows-dom", + "name": "lh:audit:use-landmarks", "duration": 1, "entryType": "measure" }, { "startTime": 183, - "name": "lh:audit:uses-long-cache-ttl", + "name": "lh:audit:visual-order-follows-dom", "duration": 1, "entryType": "measure" }, { "startTime": 184, - "name": "lh:audit:total-byte-weight", + "name": "lh:audit:uses-long-cache-ttl", "duration": 1, "entryType": "measure" }, { "startTime": 185, - "name": "lh:audit:offscreen-images", + "name": "lh:audit:total-byte-weight", "duration": 1, "entryType": "measure" }, { "startTime": 186, - "name": "lh:audit:render-blocking-resources", + "name": "lh:audit:offscreen-images", "duration": 1, "entryType": "measure" }, { "startTime": 187, - "name": "lh:computed:UnusedCSS", + "name": "lh:audit:render-blocking-resources", "duration": 1, "entryType": "measure" }, { "startTime": 188, - "name": "lh:computed:FirstContentfulPaint", + "name": "lh:computed:UnusedCSS", "duration": 1, "entryType": "measure" }, { "startTime": 189, - "name": "lh:audit:unminified-css", + "name": "lh:computed:FirstContentfulPaint", "duration": 1, "entryType": "measure" }, { "startTime": 190, - "name": "lh:audit:unminified-javascript", + "name": "lh:audit:unminified-css", "duration": 1, "entryType": "measure" }, { "startTime": 191, - "name": "lh:audit:unused-css-rules", + "name": "lh:audit:unminified-javascript", "duration": 1, "entryType": "measure" }, { "startTime": 192, - "name": "lh:audit:unused-javascript", + "name": "lh:audit:unused-css-rules", "duration": 1, "entryType": "measure" }, { "startTime": 193, - "name": "lh:audit:modern-image-formats", + "name": "lh:audit:unused-javascript", "duration": 1, "entryType": "measure" }, { "startTime": 194, - "name": "lh:audit:uses-optimized-images", + "name": "lh:audit:modern-image-formats", "duration": 1, "entryType": "measure" }, { "startTime": 195, - "name": "lh:audit:uses-text-compression", + "name": "lh:audit:uses-optimized-images", "duration": 1, "entryType": "measure" }, { "startTime": 196, - "name": "lh:audit:uses-responsive-images", + "name": "lh:audit:uses-text-compression", "duration": 1, "entryType": "measure" }, { "startTime": 197, - "name": "lh:computed:ImageRecords", + "name": "lh:audit:uses-responsive-images", "duration": 1, "entryType": "measure" }, diff --git a/core/test/results/sample_v2.json b/core/test/results/sample_v2.json index 5bc95b035aef..e9ba51b478f7 100644 --- a/core/test/results/sample_v2.json +++ b/core/test/results/sample_v2.json @@ -7543,6 +7543,12 @@ "duration": 100, "entryType": "measure" }, + { + "startTime": 0, + "name": "lh:computed:ImageRecords", + "duration": 100, + "entryType": "measure" + }, { "startTime": 0, "name": "lh:audit:layout-shift-elements", @@ -8149,12 +8155,6 @@ "duration": 100, "entryType": "measure" }, - { - "startTime": 0, - "name": "lh:computed:ImageRecords", - "duration": 100, - "entryType": "measure" - }, { "startTime": 0, "name": "lh:audit:efficient-animated-content",