diff --git a/core/test/computed/metrics/interactive-test.js b/core/test/computed/metrics/interactive-test.js index 42defd1f70..43955365bc 100644 --- a/core/test/computed/metrics/interactive-test.js +++ b/core/test/computed/metrics/interactive-test.js @@ -7,17 +7,31 @@ import assert from 'assert/strict'; import {Interactive} from '../../../computed/metrics/interactive.js'; -import {getURLArtifactFromDevtoolsLog, readJson} from '../../test-utils.js'; - -const trace = readJson('../../fixtures/traces/progressive-app-m60.json', import.meta); -const devtoolsLog = readJson('../../fixtures/traces/progressive-app-m60.devtools.log.json', import.meta); +import {getURLArtifactFromDevtoolsLog, loadTraceFixture} from '../../test-utils.js'; +const {trace, devtoolsLog} = loadTraceFixture('progressive-app-m60'); const URL = getURLArtifactFromDevtoolsLog(devtoolsLog); -function generateNetworkRecords(records, timeOrigin) { +/** + * Simple wrapper to just coerce return type to LanternMetric. + * @param {LH.Artifacts.MetricComputationDataInput} data + * @param {LH.Artifacts.ComputedContext} context + * @return {Promise} + */ +async function getResult(data, context) { + const result = await Interactive.request(data, context); + return /** @type {LH.Artifacts.LanternMetric} */ (result); +} + +/** + * @param {Array & {start: number, end: number}>} partialRecords + * @param {number} timeOrigin + * @return {LH.Artifacts.NetworkRequest[]} + */ +function generateNetworkRecords(partialRecords, timeOrigin) { const timeOriginInMs = timeOrigin / 1000; - return records.map(item => { - return { + return partialRecords.map(item => { + const record = { protocol: 'http', failed: item.failed || false, statusCode: item.statusCode || 200, @@ -26,16 +40,20 @@ function generateNetworkRecords(records, timeOrigin) { startTime: (item.start + timeOriginInMs) / 1000, endTime: item.end === -1 ? -1 : (item.end + timeOriginInMs) / 1000, }; + return /** @type {LH.Artifacts.NetworkRequest} */ (record); }); } + describe('Metrics: TTI', () => { + /** @type {{gatherMode: LH.Result.GatherMode}} */ const gatherContext = {gatherMode: 'navigation'}; it('should compute a simulated value', async () => { - const settings = {throttlingMethod: 'simulate'}; + const settings = /** @type {LH.Config.Settings} */ ( + {throttlingMethod: 'simulate'} + ); const context = {settings, computedCache: new Map()}; - const result = await Interactive.request({trace, devtoolsLog, gatherContext, settings, URL}, - context); + const result = await getResult({trace, devtoolsLog, gatherContext, settings, URL}, context); expect({ timing: Math.round(result.timing), @@ -49,9 +67,11 @@ describe('Metrics: TTI', () => { }); it('should compute an observed value (desktop)', async () => { - const settings = {throttlingMethod: 'provided', formFactor: 'desktop'}; + const settings = /** @type {LH.Config.Settings} */ ( + {throttlingMethod: 'provided', formFactor: 'desktop'} + ); const context = {settings, computedCache: new Map()}; - const result = await Interactive.request({trace, devtoolsLog, gatherContext, settings}, + const result = await getResult({trace, devtoolsLog, gatherContext, settings, URL}, context); assert.equal(Math.round(result.timing), 1582); @@ -59,9 +79,11 @@ describe('Metrics: TTI', () => { }); it('should compute an observed value (mobile)', async () => { - const settings = {throttlingMethod: 'provided', formFactor: 'mobile'}; + const settings = /** @type {LH.Config.Settings} */ ( + {throttlingMethod: 'provided', formFactor: 'mobile'} + ); const context = {settings, computedCache: new Map()}; - const result = await Interactive.request({trace, devtoolsLog, gatherContext, settings}, + const result = await getResult({trace, devtoolsLog, gatherContext, settings, URL}, context); assert.equal(Math.round(result.timing), 1582); @@ -73,12 +95,12 @@ describe('Metrics: TTI', () => { const timeOrigin = 220023532; const firstContentfulPaint = 2500 * 1000 + timeOrigin; const traceEnd = 10000 * 1000 + timeOrigin; - const processedTrace = {timestamps: {timeOrigin, firstContentfulPaint, traceEnd}}; - - const cpu = []; + const processedTrace = /** @type {LH.Artifacts.ProcessedNavigation} */ ( + {timestamps: {timeOrigin, firstContentfulPaint, traceEnd}} + ); const network = generateNetworkRecords([], timeOrigin); - const result = Interactive.findOverlappingQuietPeriods(cpu, network, processedTrace); + const result = Interactive.findOverlappingQuietPeriods([], network, processedTrace); assert.deepEqual(result.cpuQuietPeriod, {start: 0, end: traceEnd / 1000}); assert.deepEqual(result.networkQuietPeriod, {start: 0, end: traceEnd / 1000}); }); @@ -87,13 +109,13 @@ describe('Metrics: TTI', () => { const timeOrigin = 220023532; const firstContentfulPaint = 2500 * 1000 + timeOrigin; const traceEnd = 5000 * 1000 + timeOrigin; - const processedTrace = {timestamps: {timeOrigin, firstContentfulPaint, traceEnd}}; - - const cpu = []; + const processedTrace = /** @type {LH.Artifacts.ProcessedNavigation} */ ( + {timestamps: {timeOrigin, firstContentfulPaint, traceEnd}} + ); const network = generateNetworkRecords([], timeOrigin); assert.throws(() => { - Interactive.findOverlappingQuietPeriods(cpu, network, processedTrace); + Interactive.findOverlappingQuietPeriods([], network, processedTrace); }, /NO.*IDLE_PERIOD/); }); @@ -101,9 +123,10 @@ describe('Metrics: TTI', () => { const timeOrigin = 220023532; const firstContentfulPaint = 2500 * 1000 + timeOrigin; const traceEnd = 10000 * 1000 + timeOrigin; - const processedTrace = {timestamps: {timeOrigin, firstContentfulPaint, traceEnd}}; + const processedTrace = /** @type {LH.Artifacts.ProcessedNavigation} */ ( + {timestamps: {timeOrigin, firstContentfulPaint, traceEnd}} + ); - const cpu = []; const network = generateNetworkRecords([ {start: 1400, end: 1900}, {start: 2000, end: 9000}, @@ -112,7 +135,7 @@ describe('Metrics: TTI', () => { ], timeOrigin); assert.throws(() => { - Interactive.findOverlappingQuietPeriods(cpu, network, processedTrace); + Interactive.findOverlappingQuietPeriods([], network, processedTrace); }, /NO.*NETWORK_IDLE_PERIOD/); }); @@ -120,7 +143,9 @@ describe('Metrics: TTI', () => { const timeOrigin = 220023532; const firstContentfulPaint = 2500 * 1000 + timeOrigin; const traceEnd = 10000 * 1000 + timeOrigin; - const processedTrace = {timestamps: {timeOrigin, firstContentfulPaint, traceEnd}}; + const processedTrace = /** @type {LH.Artifacts.ProcessedNavigation} */ ( + {timestamps: {timeOrigin, firstContentfulPaint, traceEnd}} + ); const cpu = [ {start: 3000, end: 8000}, @@ -138,9 +163,10 @@ describe('Metrics: TTI', () => { const timeOrigin = 220023532; const firstContentfulPaint = 2500 * 1000 + timeOrigin; const traceEnd = 10000 * 1000 + timeOrigin; - const processedTrace = {timestamps: {timeOrigin, firstContentfulPaint, traceEnd}}; + const processedTrace = /** @type {LH.Artifacts.ProcessedNavigation} */ ( + {timestamps: {timeOrigin, firstContentfulPaint, traceEnd}} + ); - const cpu = []; let network = generateNetworkRecords([ {start: 0, end: -1, finished: false}, {start: 0, end: 11000, failed: true}, @@ -150,7 +176,7 @@ describe('Metrics: TTI', () => { // Triple the requests to ensure it's not just the 2-quiet kicking in network = network.concat(network).concat(network); - const result = Interactive.findOverlappingQuietPeriods(cpu, network, processedTrace); + const result = Interactive.findOverlappingQuietPeriods([], network, processedTrace); assert.deepEqual(result.cpuQuietPeriod, {start: 0, end: traceEnd / 1000}); assert.deepEqual(result.networkQuietPeriod, {start: 0, end: traceEnd / 1000}); }); @@ -159,7 +185,9 @@ describe('Metrics: TTI', () => { const timeOrigin = 220023532; const firstContentfulPaint = 10000 * 1000 + timeOrigin; const traceEnd = 45000 * 1000 + timeOrigin; - const processedTrace = {timestamps: {timeOrigin, firstContentfulPaint, traceEnd}}; + const processedTrace = /** @type {LH.Artifacts.ProcessedNavigation} */ ( + {timestamps: {timeOrigin, firstContentfulPaint, traceEnd}} + ); const cpu = [ // quiet period before FMP diff --git a/core/test/test-utils.js b/core/test/test-utils.js index 9416a3db03..059d0a3573 100644 --- a/core/test/test-utils.js +++ b/core/test/test-utils.js @@ -106,6 +106,18 @@ function loadSourceMapAndUsageFixture(name) { }; } +/** + * @param {string} name + * @return {{devtoolsLog: LH.DevtoolsLog, trace: LH.Trace}} + */ +function loadTraceFixture(name) { + const dir = `${LH_ROOT}/core/test/fixtures/traces`; + return { + devtoolsLog: JSON.parse(fs.readFileSync(`${dir}/${name}.devtools.log.json`, 'utf-8')), + trace: JSON.parse(fs.readFileSync(`${dir}/${name}.json`, 'utf-8')), + }; +} + /** * @template {unknown[]} TParams * @template TReturn @@ -337,6 +349,7 @@ export { createDecomposedPromise, flushAllTimersAndMicrotasks, makeMocksForGatherRunner, + loadTraceFixture, fnAny, mockCommands, createScript, diff --git a/tsconfig.json b/tsconfig.json index 1c7794a665..d3a94cd3cb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -105,8 +105,9 @@ ], "files": [ // Opt-in to typechecking for some core tests and test-support files. - "core/test/audits/script-treemap-data-test.js", "cli/test/fixtures/static-server.js", + "core/test/audits/script-treemap-data-test.js", + "core/test/computed/metrics/interactive-test.js", "core/test/fixtures/config-plugins/lighthouse-plugin-simple/plugin-simple.js", ], }