diff --git a/cli/test/cli/__snapshots__/index-test.js.snap b/cli/test/cli/__snapshots__/index-test.js.snap index 5ccfbeeb47e6..9ec56e1989d7 100644 --- a/cli/test/cli/__snapshots__/index-test.js.snap +++ b/cli/test/cli/__snapshots__/index-test.js.snap @@ -187,6 +187,7 @@ Object { "mobile": true, "width": 360, }, + "skipAboutBlank": false, "skipAudits": null, "throttling": Object { "cpuSlowdownMultiplier": 4, @@ -359,6 +360,7 @@ Object { "mobile": true, "width": 360, }, + "skipAboutBlank": false, "skipAudits": null, "throttling": Object { "cpuSlowdownMultiplier": 4, diff --git a/core/config/config-helpers.js b/core/config/config-helpers.js index d4c2d280014c..4fc5ba1899ad 100644 --- a/core/config/config-helpers.js +++ b/core/config/config-helpers.js @@ -606,20 +606,6 @@ function deepCloneConfigJson(json) { return cloned; } -/** - * @param {LH.Flags} flags - * @return {LH.Config.FRContext} - */ -function flagsToFRContext(flags) { - return { - configPath: flags?.configPath, - settingsOverrides: flags, - logLevel: flags?.logLevel, - hostname: flags?.hostname, - port: flags?.port, - }; -} - export { deepClone, deepCloneConfigJson, @@ -631,5 +617,4 @@ export { resolveGathererToDefn, resolveModulePath, resolveSettings, - flagsToFRContext, }; diff --git a/core/config/constants.js b/core/config/constants.js index 9f2f582410e5..35c3ae89afc0 100644 --- a/core/config/constants.js +++ b/core/config/constants.js @@ -119,6 +119,7 @@ const defaultSettings = { onlyAudits: null, onlyCategories: null, skipAudits: null, + skipAboutBlank: false, }; /** @type {LH.Config.Pass} */ diff --git a/core/fraggle-rock/config/config.js b/core/fraggle-rock/config/config.js index bb8af0e5c4e6..79079eb304f0 100644 --- a/core/fraggle-rock/config/config.js +++ b/core/fraggle-rock/config/config.js @@ -40,8 +40,6 @@ const defaultConfigPath = path.join( '../../config/default-config.js' ); -/** @typedef {LH.Config.FRContext & {gatherMode: LH.Gatherer.GatherMode}} ConfigContext */ - /** * @param {LH.Config.Json|undefined} configJSON * @param {{configPath?: string}} context @@ -176,10 +174,10 @@ async function resolveArtifactsToDefns(artifacts, configDir) { * Overrides the settings that may not apply to the chosen gather mode. * * @param {LH.Config.Settings} settings - * @param {ConfigContext} context + * @param {LH.Gatherer.GatherMode} gatherMode */ -function overrideSettingsForGatherMode(settings, context) { - if (context.gatherMode === 'timespan') { +function overrideSettingsForGatherMode(settings, gatherMode) { + if (gatherMode === 'timespan') { if (settings.throttlingMethod === 'simulate') { settings.throttlingMethod = 'devtools'; } @@ -251,21 +249,22 @@ function resolveNavigationsToDefns(navigations, artifactDefns, settings) { } /** - * @param {LH.Config.Json|undefined} configJSON - * @param {ConfigContext} context + * @param {LH.Gatherer.GatherMode} gatherMode + * @param {LH.Config.Json=} configJSON + * @param {LH.Flags=} flags * @return {Promise<{config: LH.Config.FRConfig, warnings: string[]}>} */ -async function initializeConfig(configJSON, context) { +async function initializeConfig(gatherMode, configJSON, flags = {}) { const status = {msg: 'Initialize config', id: 'lh:config'}; log.time(status, 'verbose'); - let {configWorkingCopy, configDir} = resolveWorkingCopy(configJSON, context); // eslint-disable-line prefer-const + let {configWorkingCopy, configDir} = resolveWorkingCopy(configJSON, flags); configWorkingCopy = resolveExtensions(configWorkingCopy); - configWorkingCopy = await mergePlugins(configWorkingCopy, configDir, context.settingsOverrides); + configWorkingCopy = await mergePlugins(configWorkingCopy, configDir, flags); - const settings = resolveSettings(configWorkingCopy.settings || {}, context.settingsOverrides); - overrideSettingsForGatherMode(settings, context); + const settings = resolveSettings(configWorkingCopy.settings || {}, flags); + overrideSettingsForGatherMode(settings, gatherMode); const artifacts = await resolveArtifactsToDefns(configWorkingCopy.artifacts, configDir); const navigations = resolveNavigationsToDefns(configWorkingCopy.navigations, artifacts, settings); @@ -282,7 +281,7 @@ async function initializeConfig(configJSON, context) { const {warnings} = assertValidConfig(config); - config = filterConfigByGatherMode(config, context.gatherMode); + config = filterConfigByGatherMode(config, gatherMode); config = filterConfigByExplicitFilters(config, settings); log.timeEnd(status); diff --git a/core/fraggle-rock/gather/navigation-runner.js b/core/fraggle-rock/gather/navigation-runner.js index 2792f4300392..783fca4613cc 100644 --- a/core/fraggle-rock/gather/navigation-runner.js +++ b/core/fraggle-rock/gather/navigation-runner.js @@ -25,8 +25,6 @@ import Trace from '../../gather/gatherers/trace.js'; import DevtoolsLog from '../../gather/gatherers/devtools-log.js'; import NetworkRecords from '../../computed/network-records.js'; -/** @typedef {{skipAboutBlank?: boolean}} InternalOptions */ - /** * @typedef NavigationContext * @property {Driver} driver @@ -35,7 +33,6 @@ import NetworkRecords from '../../computed/network-records.js'; * @property {LH.NavigationRequestor} requestor * @property {LH.FRBaseArtifacts} baseArtifacts * @property {Map} computedCache - * @property {InternalOptions} [options] */ /** @typedef {Omit[0], 'phase'>} PhaseState */ @@ -44,12 +41,14 @@ const DEFAULT_HOSTNAME = '127.0.0.1'; const DEFAULT_PORT = 9222; /** - * @param {{driver: Driver, config: LH.Config.FRConfig, options?: InternalOptions}} args + * @param {{driver: Driver, config: LH.Config.FRConfig, requestor: LH.NavigationRequestor}} args * @return {Promise<{baseArtifacts: LH.FRBaseArtifacts}>} */ -async function _setup({driver, config, options}) { +async function _setup({driver, config, requestor}) { await driver.connect(); - if (!options?.skipAboutBlank) { + + // We can't trigger the navigation through user interaction if we reset the page before starting. + if (typeof requestor === 'string' && !config.settings.skipAboutBlank) { await gotoURL(driver, defaultNavigationConfig.blankPage, {waitUntil: ['navigated']}); } @@ -64,10 +63,12 @@ async function _setup({driver, config, options}) { * @param {NavigationContext} navigationContext * @return {Promise<{warnings: Array}>} */ -async function _setupNavigation({requestor, driver, navigation, config, options}) { - if (!options?.skipAboutBlank) { +async function _setupNavigation({requestor, driver, navigation, config}) { + // We can't trigger the navigation through user interaction if we reset the page before starting. + if (typeof requestor === 'string' && !config.settings.skipAboutBlank) { await gotoURL(driver, navigation.blankPage, {...navigation, waitUntil: ['navigated']}); } + const {warnings} = await prepare.prepareTargetForIndividualNavigation( driver.defaultSession, config.settings, @@ -249,10 +250,10 @@ async function _navigation(navigationContext) { } /** - * @param {{driver: Driver, config: LH.Config.FRConfig, requestor: LH.NavigationRequestor; baseArtifacts: LH.FRBaseArtifacts, computedCache: NavigationContext['computedCache'], options?: InternalOptions}} args + * @param {{driver: Driver, config: LH.Config.FRConfig, requestor: LH.NavigationRequestor; baseArtifacts: LH.FRBaseArtifacts, computedCache: NavigationContext['computedCache']}} args * @return {Promise<{artifacts: Partial}>} */ -async function _navigations({driver, config, requestor, baseArtifacts, computedCache, options}) { +async function _navigations({driver, config, requestor, baseArtifacts, computedCache}) { if (!config.navigations) throw new Error('No navigations configured'); /** @type {Partial} */ @@ -268,7 +269,6 @@ async function _navigations({driver, config, requestor, baseArtifacts, computedC config, baseArtifacts, computedCache, - options, }; let shouldHaltNavigations = false; @@ -300,25 +300,17 @@ async function _cleanup({requestedUrl, driver, config}) { /** * @param {LH.NavigationRequestor|undefined} requestor - * @param {{page?: LH.Puppeteer.Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}} options + * @param {{page?: LH.Puppeteer.Page, config?: LH.Config.Json, flags?: LH.Flags}} options * @return {Promise} */ async function navigationGather(requestor, options) { - const {configContext = {}} = options; - log.setLevel(configContext.logLevel || 'error'); + const {flags = {}} = options; + log.setLevel(flags.logLevel || 'error'); - const {config} = - await initializeConfig(options.config, {...configContext, gatherMode: 'navigation'}); + const {config} = await initializeConfig('navigation', options.config, flags); const computedCache = new Map(); - const internalOptions = { - skipAboutBlank: configContext.skipAboutBlank, - }; - // We can't trigger the navigation through user interaction if we reset the page before starting. const isCallback = typeof requestor === 'function'; - if (isCallback) { - internalOptions.skipAboutBlank = true; - } const runnerOptions = {config, computedCache}; const artifacts = await Runner.gather( @@ -329,7 +321,7 @@ async function navigationGather(requestor, options) { // For navigation mode, we shouldn't connect to a browser in audit mode, // therefore we connect to the browser in the gatherFn callback. if (!page) { - const {hostname = DEFAULT_HOSTNAME, port = DEFAULT_PORT} = configContext; + const {hostname = DEFAULT_HOSTNAME, port = DEFAULT_PORT} = flags; const browser = await puppeteer.connect({browserURL: `http://${hostname}:${port}`}); page = await browser.newPage(); } @@ -339,7 +331,6 @@ async function navigationGather(requestor, options) { driver, config, requestor: normalizedRequestor, - options: internalOptions, }; const {baseArtifacts} = await _setup(context); const {artifacts} = await _navigations({...context, baseArtifacts, computedCache}); diff --git a/core/fraggle-rock/gather/snapshot-runner.js b/core/fraggle-rock/gather/snapshot-runner.js index bcb9a3aa67a0..3235315f3ca8 100644 --- a/core/fraggle-rock/gather/snapshot-runner.js +++ b/core/fraggle-rock/gather/snapshot-runner.js @@ -13,15 +13,14 @@ import {initializeConfig} from '../config/config.js'; import {getBaseArtifacts, finalizeArtifacts} from './base-artifacts.js'; /** - * @param {{page: LH.Puppeteer.Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}} options + * @param {{page: LH.Puppeteer.Page, config?: LH.Config.Json, flags?: LH.Flags}} options * @return {Promise} */ async function snapshotGather(options) { - const {configContext = {}} = options; - log.setLevel(configContext.logLevel || 'error'); + const {flags = {}} = options; + log.setLevel(flags.logLevel || 'error'); - const {config} = - await initializeConfig(options.config, {...configContext, gatherMode: 'snapshot'}); + const {config} = await initializeConfig('snapshot', options.config, flags); const driver = new Driver(options.page); await driver.connect(); diff --git a/core/fraggle-rock/gather/timespan-runner.js b/core/fraggle-rock/gather/timespan-runner.js index a0a15c45072b..5289539ccfbd 100644 --- a/core/fraggle-rock/gather/timespan-runner.js +++ b/core/fraggle-rock/gather/timespan-runner.js @@ -14,15 +14,14 @@ import {initializeConfig} from '../config/config.js'; import {getBaseArtifacts, finalizeArtifacts} from './base-artifacts.js'; /** - * @param {{page: LH.Puppeteer.Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}} options + * @param {{page: LH.Puppeteer.Page, config?: LH.Config.Json, flags?: LH.Flags}} options * @return {Promise<{endTimespanGather(): Promise}>} */ async function startTimespanGather(options) { - const {configContext = {}} = options; - log.setLevel(configContext.logLevel || 'error'); + const {flags = {}} = options; + log.setLevel(flags.logLevel || 'error'); - const {config} = - await initializeConfig(options.config, {...configContext, gatherMode: 'timespan'}); + const {config} = await initializeConfig('timespan', options.config, flags); const driver = new Driver(options.page); await driver.connect(); diff --git a/core/fraggle-rock/user-flow.js b/core/fraggle-rock/user-flow.js index 788ae18e2852..0ca680a7b7dc 100644 --- a/core/fraggle-rock/user-flow.js +++ b/core/fraggle-rock/user-flow.js @@ -63,24 +63,22 @@ class UserFlow { */ _getNextNavigationOptions(stepOptions) { const options = {...this.options, ...stepOptions}; - const configContext = {...options.configContext}; - const settingsOverrides = {...configContext.settingsOverrides}; + const flags = {...options.flags}; - if (configContext.skipAboutBlank === undefined) { - configContext.skipAboutBlank = true; + if (flags.skipAboutBlank === undefined) { + flags.skipAboutBlank = true; } // On repeat navigations, we want to disable storage reset by default (i.e. it's not a cold load). const isSubsequentNavigation = this._gatherSteps .some(step => step.artifacts.GatherContext.gatherMode === 'navigation'); if (isSubsequentNavigation) { - if (settingsOverrides.disableStorageReset === undefined) { - settingsOverrides.disableStorageReset = true; + if (flags.disableStorageReset === undefined) { + flags.disableStorageReset = true; } } - configContext.settingsOverrides = settingsOverrides; - options.configContext = configContext; + options.flags = flags; return options; } @@ -96,7 +94,7 @@ class UserFlow { artifacts: gatherResult.artifacts, name: providedName || this._getDefaultStepName(gatherResult.artifacts), config: options.config, - configContext: options.configContext, + flags: options.flags, }; this._gatherSteps.push(gatherStep); this._gatherStepRunnerOptions.set(gatherStep, gatherResult.runnerOptions); @@ -246,7 +244,7 @@ async function auditGatherSteps(gatherSteps, options) { /** @type {LH.FlowResult['steps']} */ const steps = []; for (const gatherStep of gatherSteps) { - const {artifacts, name, configContext} = gatherStep; + const {artifacts, name, flags} = gatherStep; let runnerOptions = options.gatherStepRunnerOptions?.get(gatherStep); @@ -255,7 +253,7 @@ async function auditGatherSteps(gatherSteps, options) { // Step specific configs take precedence over a config for the entire flow. const configJson = gatherStep.config || options.config; const {gatherMode} = artifacts.GatherContext; - const {config} = await initializeConfig(configJson, {...configContext, gatherMode}); + const {config} = await initializeConfig(gatherMode, configJson, flags); runnerOptions = { config, computedCache: new Map(), diff --git a/core/index.js b/core/index.js index 70d659ba28d6..e1665078e99a 100644 --- a/core/index.js +++ b/core/index.js @@ -12,7 +12,6 @@ import {Config} from './config/config.js'; import URL from './lib/url-shim.js'; import * as fraggleRock from './fraggle-rock/api.js'; import {Driver} from './gather/driver.js'; -import {flagsToFRContext} from './config/config-helpers.js'; import {initializeConfig} from './fraggle-rock/config/config.js'; /** @typedef {import('./gather/connections/connection.js').Connection} Connection */ @@ -41,8 +40,7 @@ import {initializeConfig} from './fraggle-rock/config/config.js'; * @return {Promise} */ async function lighthouse(url, flags = {}, configJSON, page) { - const configContext = flagsToFRContext(flags); - return fraggleRock.navigation(url, {page, config: configJSON, configContext}); + return fraggleRock.navigation(url, {page, config: configJSON, flags}); } /** @@ -86,8 +84,7 @@ async function legacyNavigation(url, flags = {}, configJSON, userConnection) { * @return {Promise} */ async function generateConfig(configJson, flags = {}, gatherMode = 'navigation') { - const configContext = flagsToFRContext(flags); - const {config} = await initializeConfig(configJson, {...configContext, gatherMode}); + const {config} = await initializeConfig(gatherMode, configJson, flags); return config; } diff --git a/core/scripts/print-a11y-scoring.js b/core/scripts/print-a11y-scoring.js index 99a86de9896e..26dde9542c35 100644 --- a/core/scripts/print-a11y-scoring.js +++ b/core/scripts/print-a11y-scoring.js @@ -8,7 +8,7 @@ import {initializeConfig} from '../fraggle-rock/config/config.js'; -const {config} = await initializeConfig(undefined, {gatherMode: 'navigation'}); +const {config} = await initializeConfig('navigation'); if (!config.categories || !config.audits) throw new Error('wut'); const auditRefs = config.categories.accessibility.auditRefs; diff --git a/core/test/fixtures/fraggle-rock/artifacts/sample-flow-artifacts.json b/core/test/fixtures/fraggle-rock/artifacts/sample-flow-artifacts.json index cdf8b097ba86..0dc97b4a6731 100644 --- a/core/test/fixtures/fraggle-rock/artifacts/sample-flow-artifacts.json +++ b/core/test/fixtures/fraggle-rock/artifacts/sample-flow-artifacts.json @@ -163,7 +163,8 @@ "onlyCategories": null, "skipAudits": [ "uses-http2" - ] + ], + "skipAboutBlank": true }, "BenchmarkIndex": 2094, "HostUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4945.0 Safari/537.36", @@ -313239,9 +313240,8 @@ ] } }, - "configContext": { - "skipAboutBlank": true, - "settingsOverrides": {} + "flags": { + "skipAboutBlank": true } }, { @@ -313359,7 +313359,8 @@ "onlyCategories": null, "skipAudits": [ "uses-http2" - ] + ], + "skipAboutBlank": false }, "BenchmarkIndex": 2096.5, "HostUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4945.0 Safari/537.36", @@ -672706,7 +672707,8 @@ "onlyCategories": null, "skipAudits": [ "uses-http2" - ] + ], + "skipAboutBlank": false }, "BenchmarkIndex": 2206.5, "HostUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4945.0 Safari/537.36", @@ -675588,7 +675590,8 @@ "onlyCategories": null, "skipAudits": [ "uses-http2" - ] + ], + "skipAboutBlank": true }, "BenchmarkIndex": 2210.5, "HostUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4945.0 Safari/537.36", @@ -890325,11 +890328,9 @@ ] } }, - "configContext": { + "flags": { "skipAboutBlank": true, - "settingsOverrides": { - "disableStorageReset": true - } + "disableStorageReset": true } } ] 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..1cf9605635d2 100644 --- a/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json +++ b/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json @@ -3734,7 +3734,8 @@ "onlyCategories": null, "skipAudits": [ "uses-http2" - ] + ], + "skipAboutBlank": true }, "categories": { "performance": { @@ -9173,7 +9174,8 @@ "onlyCategories": null, "skipAudits": [ "uses-http2" - ] + ], + "skipAboutBlank": false }, "categories": { "performance": { @@ -12436,7 +12438,8 @@ "onlyCategories": null, "skipAudits": [ "uses-http2" - ] + ], + "skipAboutBlank": false }, "categories": { "performance": { @@ -17979,7 +17982,8 @@ "onlyCategories": null, "skipAudits": [ "uses-http2" - ] + ], + "skipAboutBlank": true }, "categories": { "performance": { diff --git a/core/test/fraggle-rock/config/config-test.js b/core/test/fraggle-rock/config/config-test.js index 9a7eb70afda6..6ed39b536258 100644 --- a/core/test/fraggle-rock/config/config-test.js +++ b/core/test/fraggle-rock/config/config-test.js @@ -25,13 +25,13 @@ describe('Fraggle Rock Config', () => { }); it('should throw if the config path is not absolute', async () => { - expect(initializeConfig(undefined, {gatherMode, configPath: '../relative/path'})) + expect(initializeConfig(gatherMode, undefined, {configPath: '../relative/path'})) .rejects.toThrow(/must be an absolute path/); }); it('should not mutate the original input', async () => { const configJson = {artifacts: [{id: 'Accessibility', gatherer: 'accessibility'}]}; - const {config} = await initializeConfig(configJson, {gatherMode}); + const {config} = await initializeConfig(gatherMode, configJson); expect(configJson).toEqual({artifacts: [{id: 'Accessibility', gatherer: 'accessibility'}]}); expect(config).not.toBe(configJson); expect(config).not.toEqual(configJson); @@ -39,7 +39,7 @@ describe('Fraggle Rock Config', () => { }); it('should use default config when none passed in', async () => { - const {config} = await initializeConfig(undefined, {gatherMode}); + const {config} = await initializeConfig(gatherMode); expect(config.settings).toMatchObject({formFactor: 'mobile'}); if (!config.audits) throw new Error('Did not define audits'); expect(config.audits.length).toBeGreaterThan(0); @@ -47,8 +47,9 @@ describe('Fraggle Rock Config', () => { it('should resolve settings with defaults', async () => { const {config} = await initializeConfig( + gatherMode, {settings: {output: 'csv', maxWaitForFcp: 1234}}, - {settingsOverrides: {maxWaitForFcp: 12345}, gatherMode} + {maxWaitForFcp: 12345} ); expect(config.settings).toMatchObject({ @@ -60,8 +61,9 @@ describe('Fraggle Rock Config', () => { it('should override throttlingMethod in timespan mode', async () => { const {config} = await initializeConfig( + 'timespan', undefined, - {settingsOverrides: {throttlingMethod: 'simulate'}, gatherMode: 'timespan'} + {throttlingMethod: 'simulate'} ); expect(config.settings).toMatchObject({ @@ -71,7 +73,7 @@ describe('Fraggle Rock Config', () => { it('should resolve artifact definitions', async () => { const configJson = {artifacts: [{id: 'Accessibility', gatherer: 'accessibility'}]}; - const {config} = await initializeConfig(configJson, {gatherMode}); + const {config} = await initializeConfig(gatherMode, configJson); expect(config).toMatchObject({ artifacts: [{id: 'Accessibility', gatherer: {path: 'accessibility'}}], @@ -82,7 +84,7 @@ describe('Fraggle Rock Config', () => { const nonFRGatherer = new BaseGatherer(); nonFRGatherer.getArtifact = jestMock.fn(); const configJson = {artifacts: [{id: 'LegacyGather', gatherer: {instance: nonFRGatherer}}]}; - expect(initializeConfig(configJson, {gatherMode})).rejects.toThrow(/FRGatherer gatherer/); + expect(initializeConfig(gatherMode, configJson)).rejects.toThrow(/FRGatherer gatherer/); }); it('should filter configuration by gatherMode', async () => { @@ -97,20 +99,17 @@ describe('Fraggle Rock Config', () => { ], }; - const {config} = await initializeConfig(configJson, {gatherMode: 'snapshot'}); + const {config} = await initializeConfig('snapshot', configJson); expect(config).toMatchObject({ artifacts: [{id: 'Accessibility', gatherer: {path: 'accessibility'}}], }); }); it('should filter configuration by only/skip filters', async () => { - const {config} = await initializeConfig(undefined, { - gatherMode: 'navigation', - settingsOverrides: { - onlyAudits: ['color-contrast'], - onlyCategories: ['seo'], - skipAudits: ['structured-data', 'robots-txt', 'largest-contentful-paint'], - }, + const {config} = await initializeConfig('navigation', undefined, { + onlyAudits: ['color-contrast'], + onlyCategories: ['seo'], + skipAudits: ['structured-data', 'robots-txt', 'largest-contentful-paint'], }); const auditIds = (config.audits || []).map(audit => audit.implementation.meta.id); @@ -121,10 +120,9 @@ describe('Fraggle Rock Config', () => { }); it('should support plugins', async () => { - const {config} = await initializeConfig(undefined, { - gatherMode: 'navigation', + const {config} = await initializeConfig('navigation', undefined, { configPath: `${LH_ROOT}/core/test/fixtures/config-plugins/`, - settingsOverrides: {plugins: ['lighthouse-plugin-simple']}, + plugins: ['lighthouse-plugin-simple'], }); expect(config).toMatchObject({ @@ -171,7 +169,7 @@ describe('Fraggle Rock Config', () => { }); it('should resolve artifact dependencies', async () => { - const {config} = await initializeConfig(configJson, {gatherMode: 'snapshot'}); + const {config} = await initializeConfig('snapshot', configJson); expect(config).toMatchObject({ artifacts: [ {id: 'Dependency', gatherer: {instance: dependencyGatherer}}, @@ -189,7 +187,7 @@ describe('Fraggle Rock Config', () => { }); it('should resolve artifact dependencies in navigations', async () => { - const {config} = await initializeConfig(configJson, {gatherMode: 'snapshot'}); + const {config} = await initializeConfig('snapshot', configJson); expect(config).toMatchObject({ navigations: [ {artifacts: [{id: 'Dependency'}]}, @@ -210,7 +208,7 @@ describe('Fraggle Rock Config', () => { it('should throw when dependencies are out of order in artifacts', () => { if (!configJson.artifacts) throw new Error('Failed to run beforeEach'); configJson.artifacts = [configJson.artifacts[1], configJson.artifacts[0]]; - expect(initializeConfig(configJson, {gatherMode: 'snapshot'})) + expect(initializeConfig('snapshot', configJson)) .rejects.toThrow(/Failed to find dependency/); }); @@ -218,7 +216,7 @@ describe('Fraggle Rock Config', () => { if (!configJson.navigations) throw new Error('Failed to run beforeEach'); const invalidNavigation = {id: 'default', artifacts: ['Dependent', 'Dependency']}; configJson.navigations = [invalidNavigation]; - expect(initializeConfig(configJson, {gatherMode: 'snapshot'})) + expect(initializeConfig('snapshot', configJson)) .rejects.toThrow(/Failed to find dependency/); }); @@ -226,33 +224,32 @@ describe('Fraggle Rock Config', () => { if (!configJson.navigations) throw new Error('Failed to run beforeEach'); const invalidNavigation = {id: 'default', artifacts: ['Dependent']}; configJson.navigations = [invalidNavigation]; - expect(initializeConfig(configJson, {gatherMode: 'snapshot'})) + expect(initializeConfig('snapshot', configJson)) .rejects.toThrow(/Failed to find dependency/); }); it('should throw when timespan needs snapshot', () => { dependentGatherer.meta.supportedModes = ['timespan']; dependencyGatherer.meta.supportedModes = ['snapshot']; - expect(initializeConfig(configJson, {gatherMode: 'navigation'})) + expect(initializeConfig('navigation', configJson)) .rejects.toThrow(/Dependency.*is invalid/); }); it('should throw when timespan needs navigation', () => { dependentGatherer.meta.supportedModes = ['timespan']; dependencyGatherer.meta.supportedModes = ['navigation']; - expect(initializeConfig(configJson, {gatherMode: 'navigation'})) + expect(initializeConfig('navigation', configJson)) .rejects.toThrow(/Dependency.*is invalid/); }); }); describe('.resolveNavigationsToDefns', () => { it('should resolve navigation definitions', async () => { - gatherMode = 'navigation'; const configJson = { artifacts: [{id: 'Accessibility', gatherer: 'accessibility'}], navigations: [{id: 'default', artifacts: ['Accessibility']}], }; - const {config} = await initializeConfig(configJson, {gatherMode}); + const {config} = await initializeConfig('navigation', configJson); expect(config).toMatchObject({ artifacts: [{id: 'Accessibility', gatherer: {path: 'accessibility'}}], @@ -267,7 +264,8 @@ describe('Fraggle Rock Config', () => { navigations: [{id: 'default', artifacts: ['Accessibility']}], }; - expect(initializeConfig(configJson, {gatherMode})).rejects.toThrow(/Cannot use navigations/); + expect(initializeConfig(gatherMode, configJson)) + .rejects.toThrow(/Cannot use navigations/); }); it('should throw when navigations use unrecognized artifacts', () => { @@ -276,7 +274,7 @@ describe('Fraggle Rock Config', () => { navigations: [{id: 'default', artifacts: ['Accessibility']}], }; - expect(initializeConfig(configJson, {gatherMode})).rejects.toThrow(/Unrecognized artifact/); + expect(initializeConfig(gatherMode, configJson)).rejects.toThrow(/Unrecognized artifact/); }); it('should set default properties on navigations', async () => { @@ -285,7 +283,7 @@ describe('Fraggle Rock Config', () => { artifacts: [{id: 'Accessibility', gatherer: 'accessibility'}], navigations: [{id: 'default', artifacts: ['Accessibility']}], }; - const {config} = await initializeConfig(configJson, {gatherMode}); + const {config} = await initializeConfig(gatherMode, configJson); expect(config).toMatchObject({ navigations: [ @@ -313,9 +311,8 @@ describe('Fraggle Rock Config', () => { ], }; - const {config} = await initializeConfig(configJson, { - gatherMode, - settingsOverrides: {throttlingMethod: 'devtools'}, + const {config} = await initializeConfig(gatherMode, configJson, { + throttlingMethod: 'devtools', }); expect(config).toMatchObject({ @@ -382,14 +379,14 @@ describe('Fraggle Rock Config', () => { }); it('should do nothing when not extending', async () => { - const {config} = await initializeConfig({ + const {config} = await initializeConfig('navigation', { artifacts: [ {id: 'Accessibility', gatherer: 'accessibility'}, ], navigations: [ {id: 'default', artifacts: ['Accessibility']}, ], - }, {gatherMode: 'navigation'}); + }); expect(config).toMatchObject({ audits: null, @@ -405,10 +402,10 @@ describe('Fraggle Rock Config', () => { it('should extend the default config with filters', async () => { const gatherMode = 'navigation'; - const {config} = await initializeConfig({ + const {config} = await initializeConfig(gatherMode, { extends: 'lighthouse:default', settings: {onlyCategories: ['accessibility']}, - }, {gatherMode}); + }); if (!config.artifacts) throw new Error(`No artifacts created`); if (!config.audits) throw new Error(`No audits created`); @@ -424,7 +421,7 @@ describe('Fraggle Rock Config', () => { }); it('should merge in artifacts', async () => { - const {config} = await initializeConfig(extensionConfig, {gatherMode: 'navigation'}); + const {config} = await initializeConfig('navigation', extensionConfig); if (!config.artifacts) throw new Error(`No artifacts created`); const hasExtraArtifact = config.artifacts.some(a => a.id === 'ExtraArtifact'); @@ -432,7 +429,7 @@ describe('Fraggle Rock Config', () => { }); it('should merge in navigations', async () => { - const {config} = await initializeConfig(extensionConfig, {gatherMode: 'navigation'}); + const {config} = await initializeConfig('navigation', extensionConfig); if (!config.navigations) throw new Error(`No navigations created`); expect(config.navigations).toHaveLength(1); @@ -442,7 +439,7 @@ describe('Fraggle Rock Config', () => { }); it('should merge in audits', async () => { - const {config} = await initializeConfig(extensionConfig, {gatherMode: 'navigation'}); + const {config} = await initializeConfig('navigation', extensionConfig); if (!config.audits) throw new Error(`No audits created`); const hasExtraAudit = config.audits. @@ -451,7 +448,7 @@ describe('Fraggle Rock Config', () => { }); it('should merge in categories', async () => { - const {config} = await initializeConfig(extensionConfig, {gatherMode: 'navigation'}); + const {config} = await initializeConfig('navigation', extensionConfig); if (!config.categories) throw new Error(`No categories created`); const hasCategory = config.categories.performance.auditRefs.some(a => a.id === 'extra-audit'); @@ -466,7 +463,7 @@ describe('Fraggle Rock Config', () => { navigations: [{id: 'default', loadFailureMode: 'warn'}], }; - const {config, warnings} = await initializeConfig(extensionConfig, {gatherMode: 'navigation'}); + const {config, warnings} = await initializeConfig('navigation', extensionConfig); const navigations = config.navigations; if (!navigations) throw new Error(`Failed to initialize navigations`); expect(warnings).toHaveLength(1); @@ -484,7 +481,7 @@ describe('Fraggle Rock Config', () => { // expect(initializeConfig(extensionConfig, {gatherMode: 'navigation'})) // .rejects.toThrow(/did not support any gather modes/); try { - await initializeConfig(extensionConfig, {gatherMode: 'navigation'}); + await initializeConfig('navigation', extensionConfig); throw new Error('did not throw'); } catch (err) { expect(err.message).toMatch(/did not support any gather modes/); @@ -509,7 +506,7 @@ describe('getConfigDisplayString', () => { ], }; - const {config} = await initializeConfig(configJson, {gatherMode: 'navigation'}); + const {config} = await initializeConfig('navigation', configJson); const printed = getConfigDisplayString(config); const printedConfig = JSON.parse(printed); @@ -525,7 +522,7 @@ describe('getConfigDisplayString', () => { }); it('returns localized category titles', async () => { - const {config} = await initializeConfig(undefined, {gatherMode: 'navigation'}); + const {config} = await initializeConfig('navigation'); const printed = getConfigDisplayString(config); const printedConfig = JSON.parse(printed); let localizableCount = 0; @@ -546,11 +543,11 @@ describe('getConfigDisplayString', () => { it('returns a valid ConfigJson that can make an identical Config', async () => { // depends on defaultConfig having a `path` for all gatherers and audits. - const {config: firstConfig} = await initializeConfig(undefined, {gatherMode: 'navigation'}); + const {config: firstConfig} = await initializeConfig('navigation'); const firstPrint = getConfigDisplayString(firstConfig); const {config: secondConfig} = - await initializeConfig(JSON.parse(firstPrint), {gatherMode: 'navigation'}); + await initializeConfig('navigation', JSON.parse(firstPrint)); const secondPrint = getConfigDisplayString(secondConfig); expect(firstPrint).toEqual(secondPrint); diff --git a/core/test/fraggle-rock/config/filters-test.js b/core/test/fraggle-rock/config/filters-test.js index 8161e43637d7..1626a2385720 100644 --- a/core/test/fraggle-rock/config/filters-test.js +++ b/core/test/fraggle-rock/config/filters-test.js @@ -554,7 +554,7 @@ describe('Fraggle Rock Config Filtering', () => { }); it('should preserve full-page-screenshot', async () => { - config = (await initializeConfig(undefined, {gatherMode: 'navigation'})).config; + config = (await initializeConfig('navigation')).config; const filtered = filters.filterConfigByExplicitFilters(config, { onlyAudits: ['color-contrast'], diff --git a/core/test/fraggle-rock/gather/base-artifacts-test.js b/core/test/fraggle-rock/gather/base-artifacts-test.js index a1050ef07e7f..0f5cdc6cbd22 100644 --- a/core/test/fraggle-rock/gather/base-artifacts-test.js +++ b/core/test/fraggle-rock/gather/base-artifacts-test.js @@ -30,20 +30,20 @@ describe('getBaseArtifacts', () => { }); it('should fetch benchmark index', async () => { - const {config} = await initializeConfig(undefined, {gatherMode: 'navigation'}); + const {config} = await initializeConfig('navigation'); const artifacts = await getBaseArtifacts(config, driverMock.asDriver(), {gatherMode}); expect(artifacts.BenchmarkIndex).toEqual(500); }); it('should fetch host user agent', async () => { - const {config} = await initializeConfig(undefined, {gatherMode: 'navigation'}); + const {config} = await initializeConfig('navigation'); const artifacts = await getBaseArtifacts(config, driverMock.asDriver(), {gatherMode}); expect(artifacts.HostUserAgent).toContain('Macintosh'); expect(artifacts.HostFormFactor).toEqual('desktop'); }); it('should return settings', async () => { - const {config} = await initializeConfig(undefined, {gatherMode: 'navigation'}); + const {config} = await initializeConfig('navigation'); const artifacts = await getBaseArtifacts(config, driverMock.asDriver(), {gatherMode}); expect(artifacts.settings).toEqual(config.settings); }); @@ -56,7 +56,7 @@ describe('finalizeArtifacts', () => { let gathererArtifacts = {}; beforeEach(async () => { - const {config} = await initializeConfig(undefined, {gatherMode}); + const {config} = await initializeConfig(gatherMode); const driver = getMockDriverForArtifacts().asDriver(); baseArtifacts = await getBaseArtifacts(config, driver, {gatherMode}); baseArtifacts.URL = {initialUrl: 'about:blank', finalUrl: 'https://example.com'}; diff --git a/core/test/fraggle-rock/gather/navigation-runner-test.js b/core/test/fraggle-rock/gather/navigation-runner-test.js index c424c44db538..b2d04ea78f13 100644 --- a/core/test/fraggle-rock/gather/navigation-runner-test.js +++ b/core/test/fraggle-rock/gather/navigation-runner-test.js @@ -104,7 +104,7 @@ describe('NavigationRunner', () => { beforeEach(async () => { requestedUrl = 'http://example.com'; requestor = requestedUrl; - config = (await initializeConfig(undefined, {gatherMode: 'navigation'})).config; + config = (await initializeConfig('navigation')).config; navigation = createNavigation().navigation; computedCache = new Map(); baseArtifacts = createMockBaseArtifacts(); @@ -126,12 +126,12 @@ describe('NavigationRunner', () => { }); it('should connect the driver', async () => { - await runner._setup({driver, config}); + await runner._setup({driver, config, requestor: requestedUrl}); expect(mockDriver.connect).toHaveBeenCalled(); }); - it('should navigate to the blank page', async () => { - await runner._setup({driver, config}); + it('should navigate to the blank page if requestor is a string', async () => { + await runner._setup({driver, config, requestor: requestedUrl}); expect(mocks.navigationMock.gotoURL).toHaveBeenCalledTimes(1); expect(mocks.navigationMock.gotoURL).toHaveBeenCalledWith( expect.anything(), @@ -140,17 +140,28 @@ describe('NavigationRunner', () => { ); }); - it('skip about:blank if option is true', async () => { + it('skip about:blank if using callback requestor', async () => { await runner._setup({ driver, config, - options: {skipAboutBlank: true}, + requestor: () => {}, + }); + expect(mocks.navigationMock.gotoURL).not.toHaveBeenCalled(); + }); + + it('skip about:blank if config option is set to true', async () => { + config.settings.skipAboutBlank = true; + + await runner._setup({ + driver, + config, + requestor: requestedUrl, }); expect(mocks.navigationMock.gotoURL).not.toHaveBeenCalled(); }); it('should collect base artifacts', async () => { - const {baseArtifacts} = await runner._setup({driver, config}); + const {baseArtifacts} = await runner._setup({driver, config, requestor: requestedUrl}); expect(baseArtifacts).toMatchObject({ URL: { initialUrl: '', @@ -160,14 +171,14 @@ describe('NavigationRunner', () => { }); it('should prepare the target for navigation', async () => { - await runner._setup({driver, config}); + await runner._setup({driver, config, requestor: requestedUrl}); expect(mocks.prepareMock.prepareTargetForNavigationMode).toHaveBeenCalledTimes(1); }); it('should prepare the target for navigation *after* base artifact collection', async () => { mockDriver._executionContext.evaluate.mockReset(); mockDriver._executionContext.evaluate.mockRejectedValue(new Error('Not available')); - const setupPromise = runner._setup({driver, config}); + const setupPromise = runner._setup({driver, config, requestor: requestedUrl}); await expect(setupPromise).rejects.toThrowError(/Not available/); expect(mocks.prepareMock.prepareTargetForNavigationMode).not.toHaveBeenCalled(); }); @@ -184,6 +195,7 @@ describe('NavigationRunner', () => { it('should navigate as many times as there are navigations', async () => { config = (await initializeConfig( + 'navigation', { ...config, navigations: [ @@ -192,8 +204,7 @@ describe('NavigationRunner', () => { {id: 'third', artifacts: ['ViewportDimensions']}, {id: 'fourth', artifacts: ['AnchorElements']}, ], - }, - {gatherMode: 'navigation'} + } )).config; await run(); @@ -206,13 +217,13 @@ describe('NavigationRunner', () => { requestedUrl = 'https://backfill.example.com'; requestor = () => {}; config = (await initializeConfig( + 'navigation', { ...config, navigations: [ {id: 'default', artifacts: ['FontSize']}, ], - }, - {gatherMode: 'navigation'} + } )).config; mocks.navigationMock.gotoURL.mockReturnValue({ requestedUrl, @@ -232,14 +243,14 @@ describe('NavigationRunner', () => { it('should merge artifacts between navigations', async () => { config = (await initializeConfig( + 'navigation', { ...config, navigations: [ {id: 'default', artifacts: ['FontSize']}, {id: 'second', artifacts: ['ConsoleMessages']}, ], - }, - {gatherMode: 'navigation'} + } )).config; // Both gatherers will error in these test conditions, but artifact errors @@ -252,14 +263,14 @@ describe('NavigationRunner', () => { it('should retain PageLoadError and associated warnings', async () => { config = (await initializeConfig( + 'navigation', { ...config, navigations: [ {id: 'default', loadFailureMode: 'fatal', artifacts: ['FontSize']}, {id: 'second', artifacts: ['ConsoleMessages']}, ], - }, - {gatherMode: 'navigation'} + } )).config; // Ensure the first real page load fails. @@ -310,7 +321,9 @@ describe('NavigationRunner', () => { expect(mocks.navigationMock.gotoURL).toHaveBeenCalledTimes(2); }); - it('skips about:blank if option is set to true', async () => { + it('skips about:blank if config option is set to true', async () => { + config.settings.skipAboutBlank = true; + const {artifacts} = await runner._navigation({ driver, config, @@ -318,7 +331,23 @@ describe('NavigationRunner', () => { requestor: requestedUrl, computedCache, baseArtifacts, - options: {skipAboutBlank: true}, + }); + const artifactIds = Object.keys(artifacts); + expect(artifactIds).toContain('Timespan'); + expect(artifactIds).toContain('Snapshot'); + + // Only once for the requested URL. + expect(mocks.navigationMock.gotoURL).toHaveBeenCalledTimes(1); + }); + + it('skips about:blank if using a callback requestor', async () => { + const {artifacts} = await runner._navigation({ + driver, + config, + navigation, + requestor: () => {}, + computedCache, + baseArtifacts, }); const artifactIds = Object.keys(artifacts); expect(artifactIds).toContain('Timespan'); @@ -567,24 +596,23 @@ describe('NavigationRunner', () => { }); it('should initialize config', async () => { - const settingsOverrides = { + const flags = { formFactor: /** @type {const} */ ('desktop'), maxWaitForLoad: 1234, screenEmulation: {mobile: false}, }; - const configContext = {settingsOverrides}; await runner.navigationGather( 'http://example.com', { page: mockDriver._page.asPage(), - configContext, + flags, } ); expect(mockRunner.gather.mock.calls[0][1]).toMatchObject({ config: { - settings: settingsOverrides, + settings: flags, }, }); }); diff --git a/core/test/fraggle-rock/gather/snapshot-runner-test.js b/core/test/fraggle-rock/gather/snapshot-runner-test.js index 753cf0baa983..3e8cae57ae13 100644 --- a/core/test/fraggle-rock/gather/snapshot-runner-test.js +++ b/core/test/fraggle-rock/gather/snapshot-runner-test.js @@ -101,19 +101,18 @@ describe('Snapshot Runner', () => { }); - it('should use configContext', async () => { - const settingsOverrides = { + it('should use flags', async () => { + const flags = { formFactor: /** @type {const} */ ('desktop'), maxWaitForLoad: 1234, screenEmulation: {mobile: false}, }; - const configContext = {settingsOverrides}; - await snapshotGather({page, config, configContext}); + await snapshotGather({page, config, flags}); expect(mockRunner.gather.mock.calls[0][1]).toMatchObject({ config: { - settings: settingsOverrides, + settings: flags, }, }); }); diff --git a/core/test/fraggle-rock/gather/timespan-runner-test.js b/core/test/fraggle-rock/gather/timespan-runner-test.js index 57dfd89e506c..6f3ae4beb27a 100644 --- a/core/test/fraggle-rock/gather/timespan-runner-test.js +++ b/core/test/fraggle-rock/gather/timespan-runner-test.js @@ -115,20 +115,19 @@ describe('Timespan Runner', () => { }); }); - it('should use configContext', async () => { - const settingsOverrides = { + it('should use flags', async () => { + const flags = { formFactor: /** @type {const} */ ('desktop'), maxWaitForLoad: 1234, screenEmulation: {mobile: false}, }; - const configContext = {settingsOverrides}; - const timespan = await startTimespanGather({page, config, configContext}); + const timespan = await startTimespanGather({page, config, flags}); await timespan.endTimespanGather(); expect(mockRunner.gather.mock.calls[0][1]).toMatchObject({ config: { - settings: settingsOverrides, + settings: flags, }, }); }); diff --git a/core/test/fraggle-rock/scenarios/disconnect-test-pptr.js b/core/test/fraggle-rock/scenarios/disconnect-test-pptr.js index 91629cc62cba..ba80de9198ba 100644 --- a/core/test/fraggle-rock/scenarios/disconnect-test-pptr.js +++ b/core/test/fraggle-rock/scenarios/disconnect-test-pptr.js @@ -31,8 +31,8 @@ describe('Disconnect', function() { const timespan = await lighthouse.startTimespan({ page: state.page, - configContext: { - settingsOverrides: {blockedUrlPatterns: ['*']}, + flags: { + blockedUrlPatterns: ['*'], }, }); diff --git a/core/test/fraggle-rock/user-flow-test.js b/core/test/fraggle-rock/user-flow-test.js index 03d0b7b35a7e..c51b2c4e7ce7 100644 --- a/core/test/fraggle-rock/user-flow-test.js +++ b/core/test/fraggle-rock/user-flow-test.js @@ -91,8 +91,8 @@ describe('UserFlow', () => { await flow.navigate('https://example.com/1', {stepName: 'My Step'}); - const configContext = {settingsOverrides: {maxWaitForLoad: 1000}}; - await flow.navigate('https://example.com/2', {configContext}); + const flags = {maxWaitForLoad: 1000}; + await flow.navigate('https://example.com/2', {flags}); await flow.navigate('https://example.com/3'); @@ -109,32 +109,32 @@ describe('UserFlow', () => { await flow.navigate('https://example.com/1'); // Try once when we have some other settings. - const configContext = {settingsOverrides: {maxWaitForLoad: 1000}}; - await flow.navigate('https://example.com/2', {configContext}); + const flags = {maxWaitForLoad: 1000}; + await flow.navigate('https://example.com/2', {flags}); // Try once when we don't have any other settings. await flow.navigate('https://example.com/3'); // Try once when we explicitly set it. - const configContextExplicit = {settingsOverrides: {disableStorageReset: false}}; - await flow.navigate('https://example.com/4', {configContext: configContextExplicit}); + const flagsExplicit = {disableStorageReset: false}; + await flow.navigate('https://example.com/4', {flags: flagsExplicit}); // Check that we have the property set. expect(navigationModule.navigationGather).toHaveBeenCalledTimes(4); /** @type {any[][]} */ const [[, call1], [, call2], [, call3], [, call4]] = navigationModule.navigationGather.mock.calls; - expect(call1).not.toHaveProperty('configContext.settingsOverrides.disableStorageReset'); - expect(call2).toHaveProperty('configContext.settingsOverrides.disableStorageReset'); - expect(call3).toHaveProperty('configContext.settingsOverrides.disableStorageReset'); - expect(call4).toHaveProperty('configContext.settingsOverrides.disableStorageReset'); - expect(call2.configContext.settingsOverrides.disableStorageReset).toBe(true); - expect(call3.configContext.settingsOverrides.disableStorageReset).toBe(true); - expect(call4.configContext.settingsOverrides.disableStorageReset).toBe(false); + expect(call1).not.toHaveProperty('flags.disableStorageReset'); + expect(call2).toHaveProperty('flags.disableStorageReset'); + expect(call3).toHaveProperty('flags.disableStorageReset'); + expect(call4).toHaveProperty('flags.disableStorageReset'); + expect(call2.flags.disableStorageReset).toBe(true); + expect(call3.flags.disableStorageReset).toBe(true); + expect(call4.flags.disableStorageReset).toBe(false); // Check that we didn't mutate the original objects. - expect(configContext).toEqual({settingsOverrides: {maxWaitForLoad: 1000}}); - expect(configContextExplicit).toEqual({settingsOverrides: {disableStorageReset: false}}); + expect(flags).toEqual({maxWaitForLoad: 1000}); + expect(flagsExplicit).toEqual({disableStorageReset: false}); }); it('should disable about:blank jumps by default', async () => { @@ -142,27 +142,27 @@ describe('UserFlow', () => { await flow.navigate('https://example.com/1'); // Try once when we have some other settings. - const configContext = {settingsOverrides: {maxWaitForLoad: 1000}}; - await flow.navigate('https://example.com/2', {configContext}); + const flags = {maxWaitForLoad: 1000}; + await flow.navigate('https://example.com/2', {flags}); // Try once when we explicitly set it. - const configContextExplicit = {skipAboutBlank: false}; - await flow.navigate('https://example.com/3', {configContext: configContextExplicit}); + const flagsExplicit = {skipAboutBlank: false}; + await flow.navigate('https://example.com/3', {flags: flagsExplicit}); // Check that we have the property set. expect(navigationModule.navigationGather).toHaveBeenCalledTimes(3); /** @type {any[][]} */ const [[, call1], [, call2], [, call3]] = navigationModule.navigationGather.mock.calls; - expect(call1).toHaveProperty('configContext.skipAboutBlank'); - expect(call2).toHaveProperty('configContext.skipAboutBlank'); - expect(call3).toHaveProperty('configContext.skipAboutBlank'); - expect(call1.configContext.skipAboutBlank).toBe(true); - expect(call2.configContext.skipAboutBlank).toBe(true); - expect(call3.configContext.skipAboutBlank).toBe(false); + expect(call1).toHaveProperty('flags.skipAboutBlank'); + expect(call2).toHaveProperty('flags.skipAboutBlank'); + expect(call3).toHaveProperty('flags.skipAboutBlank'); + expect(call1.flags.skipAboutBlank).toBe(true); + expect(call2.flags.skipAboutBlank).toBe(true); + expect(call3.flags.skipAboutBlank).toBe(false); // Check that we didn't mutate the original objects. - expect(configContext).toEqual({settingsOverrides: {maxWaitForLoad: 1000}}); - expect(configContextExplicit).toEqual({skipAboutBlank: false}); + expect(flags).toEqual({maxWaitForLoad: 1000}); + expect(flagsExplicit).toEqual({skipAboutBlank: false}); }); }); @@ -339,11 +339,9 @@ describe('UserFlow', () => { }, }; - /** @type {LH.Config.FRContext} */ - const snapshotContext = { - settingsOverrides: { - onlyCategories: ['accessibility'], - }, + /** @type {LH.Flags} */ + const snapshotFlags = { + onlyCategories: ['accessibility'], }; /** @type {LH.UserFlow.GatherStep[]} */ @@ -383,7 +381,7 @@ describe('UserFlow', () => { }, GatherContext: {gatherMode: 'snapshot'}, }, - configContext: snapshotContext, + flags: snapshotFlags, }, ]; diff --git a/core/test/lib/stack-packs-test.js b/core/test/lib/stack-packs-test.js index d749460e992e..999f9b740e4d 100644 --- a/core/test/lib/stack-packs-test.js +++ b/core/test/lib/stack-packs-test.js @@ -10,7 +10,7 @@ import {initializeConfig} from '../../fraggle-rock/config/config.js'; import {stackPacksToInclude} from '../../lib/stack-packs.js'; async function getAuditIds() { - const {config} = await initializeConfig(undefined, {gatherMode: 'navigation'}); + const {config} = await initializeConfig('navigation'); return config.audits.map(a => a.implementation.meta.id); } diff --git a/core/test/results/artifacts/artifacts.json b/core/test/results/artifacts/artifacts.json index fbb74d13eb75..0997e6c00cdc 100644 --- a/core/test/results/artifacts/artifacts.json +++ b/core/test/results/artifacts/artifacts.json @@ -169,7 +169,8 @@ "precomputedLanternData": null, "onlyAudits": null, "onlyCategories": null, - "skipAudits": null + "skipAudits": null, + "skipAboutBlank": false }, "URL": { "initialUrl": "about:blank", diff --git a/core/test/results/sample_v2.json b/core/test/results/sample_v2.json index 5bc95b035aef..e73848b988f4 100644 --- a/core/test/results/sample_v2.json +++ b/core/test/results/sample_v2.json @@ -5982,7 +5982,8 @@ "precomputedLanternData": null, "onlyAudits": null, "onlyCategories": null, - "skipAudits": null + "skipAudits": null, + "skipAboutBlank": false }, "categories": { "performance": { diff --git a/types/config.d.ts b/types/config.d.ts index b0f4047abfdf..d1e792fe8e04 100644 --- a/types/config.d.ts +++ b/types/config.d.ts @@ -57,19 +57,6 @@ declare module Config { groups: Record | null; } - /** - * Additional information about the context in which a Fraggle Rock config should be interpreted. - * This information is typically set by the CLI or other channel integrations. - */ - interface FRContext { - configPath?: string; - settingsOverrides?: SharedFlagsSettings & Pick; - skipAboutBlank?: boolean; - logLevel?: string; - hostname?: string; - port?: number; - } - interface SharedPassNavigationJson { /** * Controls the behavior when the navigation fails to complete (due to server error, no FCP, etc). diff --git a/types/lhr/settings.d.ts b/types/lhr/settings.d.ts index 858ac6a62df1..64c4587aee74 100644 --- a/types/lhr/settings.d.ts +++ b/types/lhr/settings.d.ts @@ -71,6 +71,8 @@ export type ScreenEmulationSettings = { disableStorageReset?: boolean; /** Flag indicating that Lighthouse should pause after page load to wait for the user's permission to continue the audit. */ debugNavigation?: boolean; + /** If set to true, will skip the initial navigation to about:blank. This option is ignored when using the legacy navigation runner. */ + skipAboutBlank?: boolean; /** How Lighthouse should interpret this run in regards to scoring performance metrics and skipping mobile-only tests in desktop. Must be set even if throttling/emulation is being applied outside of Lighthouse. */ formFactor?: 'mobile'|'desktop'; diff --git a/types/user-flow.d.ts b/types/user-flow.d.ts index ecff6163b301..c1bc68133423 100644 --- a/types/user-flow.d.ts +++ b/types/user-flow.d.ts @@ -10,7 +10,7 @@ declare module UserFlow { artifacts: LH.Artifacts; name: string; config?: LH.Config.Json; - configContext?: LH.Config.FRContext; + flags?: LH.Flags; } }