diff --git a/clients/test/lightrider/lightrider-entry-test.js b/clients/test/lightrider/lightrider-entry-test.js index 31224ae8048d..3859e14dc01d 100644 --- a/clients/test/lightrider/lightrider-entry-test.js +++ b/clients/test/lightrider/lightrider-entry-test.js @@ -65,8 +65,8 @@ describe('lightrider-entry', () => { const url = 'https://example.com'; await runLighthouseInLR(mockConnection, url, {}, {}); - const config = runStub.mock.calls[0][1].config; - assert.equal(config.settings.channel, 'lr'); + const resolvedConfig = runStub.mock.calls[0][1].resolvedConfig; + assert.equal(resolvedConfig.settings.channel, 'lr'); runStub.mockRestore(); }); @@ -79,8 +79,8 @@ describe('lightrider-entry', () => { const lrDevice = 'desktop'; await runLighthouseInLR(mockConnection, url, {}, {lrDevice}); - const config = runStub.mock.calls[0][1].config; - assert.equal(config.settings.formFactor, 'desktop'); + const resolvedConfig = runStub.mock.calls[0][1].resolvedConfig; + assert.equal(resolvedConfig.settings.formFactor, 'desktop'); runStub.mockRestore(); }); @@ -93,8 +93,8 @@ describe('lightrider-entry', () => { const lrDevice = 'mobile'; await runLighthouseInLR(mockConnection, url, {}, {lrDevice}); - const config = runStub.mock.calls[0][1].config; - assert.equal(config.settings.formFactor, 'mobile'); + const resolvedConfig = runStub.mock.calls[0][1].resolvedConfig; + assert.equal(resolvedConfig.settings.formFactor, 'mobile'); runStub.mockRestore(); }); @@ -112,9 +112,9 @@ describe('lightrider-entry', () => { }, }; await runLighthouseInLR(mockConnection, url, {}, {configOverride}); - const config = runStub.mock.calls[0][1].config; - assert.equal(config.settings.onlyAudits.length, 1); - assert.equal(config.settings.onlyAudits[0], 'network-requests'); + const resolvedConfig = runStub.mock.calls[0][1].resolvedConfig; + assert.equal(resolvedConfig.settings.onlyAudits.length, 1); + assert.equal(resolvedConfig.settings.onlyAudits[0], 'network-requests'); runStub.mockRestore(); }); diff --git a/core/config/config.js b/core/config/config.js index 934ccc910b41..2af15a10a321 100644 --- a/core/config/config.js +++ b/core/config/config.js @@ -238,7 +238,7 @@ function resolveFakeNavigations(artifactDefns, settings) { * @param {LH.Gatherer.GatherMode} gatherMode * @param {LH.Config.Json=} configJSON * @param {LH.Flags=} flags - * @return {Promise<{config: LH.Config.FRConfig, warnings: string[]}>} + * @return {Promise<{resolvedConfig: LH.Config.FRConfig, warnings: string[]}>} */ async function initializeConfig(gatherMode, configJSON, flags = {}) { const status = {msg: 'Initialize config', id: 'lh:config'}; @@ -257,7 +257,7 @@ async function initializeConfig(gatherMode, configJSON, flags = {}) { const navigations = resolveFakeNavigations(artifacts, settings); /** @type {LH.Config.FRConfig} */ - let config = { + let resolvedConfig = { artifacts, navigations, audits: await resolveAuditsToDefns(configWorkingCopy.audits, configDir), @@ -266,25 +266,25 @@ async function initializeConfig(gatherMode, configJSON, flags = {}) { settings, }; - const {warnings} = assertValidConfig(config); + const {warnings} = assertValidConfig(resolvedConfig); - config = filterConfigByGatherMode(config, gatherMode); - config = filterConfigByExplicitFilters(config, settings); + resolvedConfig = filterConfigByGatherMode(resolvedConfig, gatherMode); + resolvedConfig = filterConfigByExplicitFilters(resolvedConfig, settings); log.timeEnd(status); - return {config, warnings}; + return {resolvedConfig, warnings}; } /** - * @param {LH.Config.FRConfig} config + * @param {LH.Config.FRConfig} resolvedConfig * @return {string} */ -function getConfigDisplayString(config) { +function getConfigDisplayString(resolvedConfig) { /** @type {LH.Config.FRConfig} */ - const jsonConfig = JSON.parse(JSON.stringify(config)); + const resolvedConfigCopy = JSON.parse(JSON.stringify(resolvedConfig)); - if (jsonConfig.navigations) { - for (const navigation of jsonConfig.navigations) { + if (resolvedConfigCopy.navigations) { + for (const navigation of resolvedConfigCopy.navigations) { for (let i = 0; i < navigation.artifacts.length; ++i) { // @ts-expect-error Breaking the Config.AnyArtifactDefn type. navigation.artifacts[i] = navigation.artifacts[i].id; @@ -292,8 +292,8 @@ function getConfigDisplayString(config) { } } - if (jsonConfig.artifacts) { - for (const artifactDefn of jsonConfig.artifacts) { + if (resolvedConfigCopy.artifacts) { + for (const artifactDefn of resolvedConfigCopy.artifacts) { // @ts-expect-error Breaking the Config.AnyArtifactDefn type. artifactDefn.gatherer = artifactDefn.gatherer.path; // Dependencies are not declared on Config JSON @@ -301,8 +301,8 @@ function getConfigDisplayString(config) { } } - if (jsonConfig.audits) { - for (const auditDefn of jsonConfig.audits) { + if (resolvedConfigCopy.audits) { + for (const auditDefn of resolvedConfigCopy.audits) { // @ts-expect-error Breaking the Config.AuditDefn type. auditDefn.implementation = undefined; if (Object.keys(auditDefn.options).length === 0) { @@ -313,9 +313,9 @@ function getConfigDisplayString(config) { } // Printed config is more useful with localized strings. - format.replaceIcuMessages(jsonConfig, jsonConfig.settings.locale); + format.replaceIcuMessages(resolvedConfigCopy, resolvedConfigCopy.settings.locale); - return JSON.stringify(jsonConfig, null, 2); + return JSON.stringify(resolvedConfigCopy, null, 2); } export { diff --git a/core/config/filters.js b/core/config/filters.js index 3fe40e319241..4066ac384c02 100644 --- a/core/config/filters.js +++ b/core/config/filters.js @@ -257,19 +257,19 @@ function filterCategoriesByAvailableAudits(categories, availableAudits) { /** * Filters a config's artifacts, audits, and categories down to the set that supports the specified gather mode. * - * @param {LH.Config.FRConfig} config + * @param {LH.Config.FRConfig} resolvedConfig * @param {LH.Gatherer.GatherMode} mode * @return {LH.Config.FRConfig} */ -function filterConfigByGatherMode(config, mode) { - const artifacts = filterArtifactsByGatherMode(config.artifacts, mode); - const supportedAudits = filterAuditsByGatherMode(config.audits, mode); +function filterConfigByGatherMode(resolvedConfig, mode) { + const artifacts = filterArtifactsByGatherMode(resolvedConfig.artifacts, mode); + const supportedAudits = filterAuditsByGatherMode(resolvedConfig.audits, mode); const audits = filterAuditsByAvailableArtifacts(supportedAudits, artifacts || []); - const supportedCategories = filterCategoriesByGatherMode(config.categories, mode); + const supportedCategories = filterCategoriesByGatherMode(resolvedConfig.categories, mode); const categories = filterCategoriesByAvailableAudits(supportedCategories, audits || []); return { - ...config, + ...resolvedConfig, artifacts, audits, categories, @@ -280,22 +280,22 @@ function filterConfigByGatherMode(config, mode) { * Filters a config's artifacts, audits, and categories down to the requested set. * Skip audits overrides inclusion via `onlyAudits`/`onlyCategories`. * - * @param {LH.Config.FRConfig} config + * @param {LH.Config.FRConfig} resolvedConfig * @param {Pick} filters * @return {LH.Config.FRConfig} */ -function filterConfigByExplicitFilters(config, filters) { +function filterConfigByExplicitFilters(resolvedConfig, filters) { const {onlyAudits, onlyCategories, skipAudits} = filters; - warnOnUnknownOnlyCategories(config.categories, onlyCategories); + warnOnUnknownOnlyCategories(resolvedConfig.categories, onlyCategories); - let baseAuditIds = getAuditIdsInCategories(config.categories, undefined); + let baseAuditIds = getAuditIdsInCategories(resolvedConfig.categories, undefined); if (onlyCategories) { - baseAuditIds = getAuditIdsInCategories(config.categories, onlyCategories); + baseAuditIds = getAuditIdsInCategories(resolvedConfig.categories, onlyCategories); } else if (onlyAudits) { baseAuditIds = new Set(); - } else if (!config.categories || !Object.keys(config.categories).length) { - baseAuditIds = new Set(config.audits?.map(audit => audit.implementation.meta.id)); + } else if (!resolvedConfig.categories || !Object.keys(resolvedConfig.categories).length) { + baseAuditIds = new Set(resolvedConfig.audits?.map(audit => audit.implementation.meta.id)); } const auditIdsToKeep = new Set( @@ -306,17 +306,19 @@ function filterConfigByExplicitFilters(config, filters) { ].filter(auditId => !skipAudits || !skipAudits.includes(auditId)) ); - const audits = auditIdsToKeep.size && config.audits ? - config.audits.filter(audit => auditIdsToKeep.has(audit.implementation.meta.id)) : - config.audits; + const audits = auditIdsToKeep.size && resolvedConfig.audits ? + resolvedConfig.audits.filter(audit => auditIdsToKeep.has(audit.implementation.meta.id)) : + resolvedConfig.audits; - const availableCategories = filterCategoriesByAvailableAudits(config.categories, audits || []); + const availableCategories = + filterCategoriesByAvailableAudits(resolvedConfig.categories, audits || []); const categories = filterCategoriesByExplicitFilters(availableCategories, onlyCategories); - const artifacts = filterArtifactsByAvailableAudits(config.artifacts, audits); - const navigations = filterNavigationsByAvailableArtifacts(config.navigations, artifacts || []); + const artifacts = filterArtifactsByAvailableAudits(resolvedConfig.artifacts, audits); + const navigations = + filterNavigationsByAvailableArtifacts(resolvedConfig.navigations, artifacts || []); return { - ...config, + ...resolvedConfig, artifacts, navigations, audits, diff --git a/core/config/validation.js b/core/config/validation.js index 8f65057e853e..3641d0399918 100644 --- a/core/config/validation.js +++ b/core/config/validation.js @@ -247,22 +247,22 @@ function assertArtifactTopologicalOrder(navigations) { } /** - * @param {LH.Config.FRConfig} config + * @param {LH.Config.FRConfig} resolvedConfig * @return {{warnings: string[]}} */ -function assertValidConfig(config) { - const {warnings} = assertValidFRNavigations(config.navigations); +function assertValidConfig(resolvedConfig) { + const {warnings} = assertValidFRNavigations(resolvedConfig.navigations); - for (const artifactDefn of config.artifacts || []) { + for (const artifactDefn of resolvedConfig.artifacts || []) { assertValidFRGatherer(artifactDefn.gatherer); } - for (const auditDefn of config.audits || []) { + for (const auditDefn of resolvedConfig.audits || []) { assertValidAudit(auditDefn); } - assertValidCategories(config.categories, config.audits, config.groups); - assertValidSettings(config.settings); + assertValidCategories(resolvedConfig.categories, resolvedConfig.audits, resolvedConfig.groups); + assertValidSettings(resolvedConfig.settings); return {warnings}; } diff --git a/core/gather/base-artifacts.js b/core/gather/base-artifacts.js index 614b13784741..013ea93e2c8f 100644 --- a/core/gather/base-artifacts.js +++ b/core/gather/base-artifacts.js @@ -12,12 +12,12 @@ import { } from './driver/environment.js'; /** - * @param {LH.Config.FRConfig} config + * @param {LH.Config.FRConfig} resolvedConfig * @param {LH.Gatherer.FRTransitionalDriver} driver * @param {{gatherMode: LH.Gatherer.GatherMode}} context * @return {Promise} */ -async function getBaseArtifacts(config, driver, context) { +async function getBaseArtifacts(resolvedConfig, driver, context) { const BenchmarkIndex = await getBenchmarkIndex(driver.executionContext); const {userAgent} = await getBrowserVersion(driver.defaultSession); @@ -26,7 +26,7 @@ async function getBaseArtifacts(config, driver, context) { fetchTime: new Date().toJSON(), Timing: [], LighthouseRunWarnings: [], - settings: config.settings, + settings: resolvedConfig.settings, // Environment artifacts that can always be computed. BenchmarkIndex, HostUserAgent: userAgent, diff --git a/core/gather/navigation-runner.js b/core/gather/navigation-runner.js index 5fefa312a65a..2081c2b4430d 100644 --- a/core/gather/navigation-runner.js +++ b/core/gather/navigation-runner.js @@ -29,7 +29,7 @@ import {NetworkRecords} from '../computed/network-records.js'; * @typedef NavigationContext * @property {Driver} driver * @property {LH.Puppeteer.Page} page - * @property {LH.Config.FRConfig} config + * @property {LH.Config.FRConfig} resolvedConfig * @property {LH.Config.NavigationDefn} navigation * @property {LH.NavigationRequestor} requestor * @property {LH.FRBaseArtifacts} baseArtifacts @@ -42,20 +42,20 @@ const DEFAULT_HOSTNAME = '127.0.0.1'; const DEFAULT_PORT = 9222; /** - * @param {{driver: Driver, config: LH.Config.FRConfig, requestor: LH.NavigationRequestor}} args + * @param {{driver: Driver, resolvedConfig: LH.Config.FRConfig, requestor: LH.NavigationRequestor}} args * @return {Promise<{baseArtifacts: LH.FRBaseArtifacts}>} */ -async function _setup({driver, config, requestor}) { +async function _setup({driver, resolvedConfig, requestor}) { await driver.connect(); // We can't trigger the navigation through user interaction if we reset the page before starting. - if (typeof requestor === 'string' && !config.settings.skipAboutBlank) { + if (typeof requestor === 'string' && !resolvedConfig.settings.skipAboutBlank) { await gotoURL(driver, defaultNavigationConfig.blankPage, {waitUntil: ['navigated']}); } - const baseArtifacts = await getBaseArtifacts(config, driver, {gatherMode: 'navigation'}); + const baseArtifacts = await getBaseArtifacts(resolvedConfig, driver, {gatherMode: 'navigation'}); - await prepare.prepareTargetForNavigationMode(driver, config.settings); + await prepare.prepareTargetForNavigationMode(driver, resolvedConfig.settings); return {baseArtifacts}; } @@ -64,15 +64,15 @@ async function _setup({driver, config, requestor}) { * @param {NavigationContext} navigationContext * @return {Promise<{warnings: Array}>} */ -async function _setupNavigation({requestor, driver, navigation, config}) { +async function _setupNavigation({requestor, driver, navigation, resolvedConfig}) { // We can't trigger the navigation through user interaction if we reset the page before starting. - if (typeof requestor === 'string' && !config.settings.skipAboutBlank) { + if (typeof requestor === 'string' && !resolvedConfig.settings.skipAboutBlank) { await gotoURL(driver, navigation.blankPage, {...navigation, waitUntil: ['navigated']}); } const {warnings} = await prepare.prepareTargetForIndividualNavigation( driver.defaultSession, - config.settings, + resolvedConfig.settings, { ...navigation, requestor, @@ -94,14 +94,14 @@ async function _cleanupNavigation({driver}) { * @return {Promise<{requestedUrl: string, mainDocumentUrl: string, navigationError: LH.LighthouseError | undefined, warnings: Array}>} */ async function _navigate(navigationContext) { - const {driver, config, requestor} = navigationContext; + const {driver, resolvedConfig, requestor} = navigationContext; try { const {requestedUrl, mainDocumentUrl, warnings} = await gotoURL(driver, requestor, { ...navigationContext.navigation, - debugNavigation: config.settings.debugNavigation, - maxWaitForFcp: config.settings.maxWaitForFcp, - maxWaitForLoad: config.settings.maxWaitForLoad, + debugNavigation: resolvedConfig.settings.debugNavigation, + maxWaitForFcp: resolvedConfig.settings.maxWaitForFcp, + maxWaitForLoad: resolvedConfig.settings.maxWaitForLoad, waitUntil: navigationContext.navigation.pauseAfterFcpMs ? ['fcp', 'load'] : ['load'], }); return {requestedUrl, mainDocumentUrl, navigationError: undefined, warnings}; @@ -181,7 +181,7 @@ async function _computeNavigationResult( : navigationError; if (pageLoadError) { - const locale = navigationContext.config.settings.locale; + const locale = navigationContext.resolvedConfig.settings.locale; const localizedMessage = format.getFormatted(pageLoadError.friendlyMessage, locale); log.error('NavigationRunner', localizedMessage, navigateResult.requestedUrl); @@ -223,7 +223,7 @@ async function _navigation(navigationContext) { artifactDefinitions: navigationContext.navigation.artifacts, artifactState, baseArtifacts: navigationContext.baseArtifacts, - settings: navigationContext.config.settings, + settings: navigationContext.resolvedConfig.settings, }; const setupResult = await _setupNavigation(navigationContext); @@ -250,24 +250,33 @@ async function _navigation(navigationContext) { } /** - * @param {{driver: Driver, page: LH.Puppeteer.Page, config: LH.Config.FRConfig, requestor: LH.NavigationRequestor; baseArtifacts: LH.FRBaseArtifacts, computedCache: NavigationContext['computedCache']}} args + * @param {{driver: Driver, page: LH.Puppeteer.Page, resolvedConfig: LH.Config.FRConfig, requestor: LH.NavigationRequestor; baseArtifacts: LH.FRBaseArtifacts, computedCache: NavigationContext['computedCache']}} args * @return {Promise<{artifacts: Partial}>} */ -async function _navigations({driver, page, config, requestor, baseArtifacts, computedCache}) { - if (!config.navigations) throw new Error('No navigations configured'); +async function _navigations(args) { + const { + driver, + page, + resolvedConfig, + requestor, + baseArtifacts, + computedCache, + } = args; + + if (!resolvedConfig.navigations) throw new Error('No navigations configured'); /** @type {Partial} */ const artifacts = {}; /** @type {Array} */ const LighthouseRunWarnings = []; - for (const navigation of config.navigations) { + for (const navigation of resolvedConfig.navigations) { const navigationContext = { driver, page, navigation, requestor, - config, + resolvedConfig, baseArtifacts, computedCache, }; @@ -290,10 +299,10 @@ async function _navigations({driver, page, config, requestor, baseArtifacts, com } /** - * @param {{requestedUrl?: string, driver: Driver, config: LH.Config.FRConfig}} args + * @param {{requestedUrl?: string, driver: Driver, resolvedConfig: LH.Config.FRConfig}} args */ -async function _cleanup({requestedUrl, driver, config}) { - const didResetStorage = !config.settings.disableStorageReset && requestedUrl; +async function _cleanup({requestedUrl, driver, resolvedConfig}) { + const didResetStorage = !resolvedConfig.settings.disableStorageReset && requestedUrl; if (didResetStorage) await storage.clearDataForOrigin(driver.defaultSession, requestedUrl); await driver.disconnect(); @@ -306,15 +315,15 @@ async function _cleanup({requestedUrl, driver, config}) { * @return {Promise} */ async function navigationGather(page, requestor, options = {}) { - const {flags = {}} = options; + const {flags = {}, config} = options; log.setLevel(flags.logLevel || 'error'); - const {config} = await initializeConfig('navigation', options.config, flags); + const {resolvedConfig} = await initializeConfig('navigation', config, flags); const computedCache = new Map(); const isCallback = typeof requestor === 'function'; - const runnerOptions = {config, computedCache}; + const runnerOptions = {resolvedConfig, computedCache}; const artifacts = await Runner.gather( async () => { const normalizedRequestor = isCallback ? requestor : UrlUtils.normalizeUrl(requestor); @@ -330,7 +339,7 @@ async function navigationGather(page, requestor, options = {}) { const driver = new Driver(page); const context = { driver, - config, + resolvedConfig, requestor: normalizedRequestor, }; const {baseArtifacts} = await _setup(context); diff --git a/core/gather/snapshot-runner.js b/core/gather/snapshot-runner.js index 915fead36ae3..6cfec3679a2d 100644 --- a/core/gather/snapshot-runner.js +++ b/core/gather/snapshot-runner.js @@ -18,10 +18,10 @@ import {getBaseArtifacts, finalizeArtifacts} from './base-artifacts.js'; * @return {Promise} */ async function snapshotGather(page, options = {}) { - const {flags = {}} = options; + const {flags = {}, config} = options; log.setLevel(flags.logLevel || 'error'); - const {config} = await initializeConfig('snapshot', options.config, flags); + const {resolvedConfig} = await initializeConfig('snapshot', config, flags); const driver = new Driver(page); await driver.connect(); @@ -29,15 +29,16 @@ async function snapshotGather(page, options = {}) { const computedCache = new Map(); const url = await driver.url(); - const runnerOptions = {config, computedCache}; + const runnerOptions = {resolvedConfig, computedCache}; const artifacts = await Runner.gather( async () => { - const baseArtifacts = await getBaseArtifacts(config, driver, {gatherMode: 'snapshot'}); + const baseArtifacts = + await getBaseArtifacts(resolvedConfig, driver, {gatherMode: 'snapshot'}); baseArtifacts.URL = { finalDisplayedUrl: url, }; - const artifactDefinitions = config.artifacts || []; + const artifactDefinitions = resolvedConfig.artifacts || []; const artifactState = getEmptyArtifactState(); await collectPhaseArtifacts({ phase: 'getArtifact', @@ -48,7 +49,7 @@ async function snapshotGather(page, options = {}) { artifactDefinitions, artifactState, computedCache, - settings: config.settings, + settings: resolvedConfig.settings, }); await driver.disconnect(); diff --git a/core/gather/timespan-runner.js b/core/gather/timespan-runner.js index 30e11a1d2eb1..73c87705da9d 100644 --- a/core/gather/timespan-runner.js +++ b/core/gather/timespan-runner.js @@ -19,17 +19,17 @@ import {getBaseArtifacts, finalizeArtifacts} from './base-artifacts.js'; * @return {Promise<{endTimespanGather(): Promise}>} */ async function startTimespanGather(page, options = {}) { - const {flags = {}} = options; + const {flags = {}, config} = options; log.setLevel(flags.logLevel || 'error'); - const {config} = await initializeConfig('timespan', options.config, flags); + const {resolvedConfig} = await initializeConfig('timespan', config, flags); const driver = new Driver(page); await driver.connect(); /** @type {Map} */ const computedCache = new Map(); - const artifactDefinitions = config.artifacts || []; - const baseArtifacts = await getBaseArtifacts(config, driver, {gatherMode: 'timespan'}); + const artifactDefinitions = resolvedConfig.artifacts || []; + const baseArtifacts = await getBaseArtifacts(resolvedConfig, driver, {gatherMode: 'timespan'}); const artifactState = getEmptyArtifactState(); /** @type {Omit} */ const phaseOptions = { @@ -40,10 +40,10 @@ async function startTimespanGather(page, options = {}) { baseArtifacts, computedCache, gatherMode: 'timespan', - settings: config.settings, + settings: resolvedConfig.settings, }; - await prepareTargetForTimespanMode(driver, config.settings); + await prepareTargetForTimespanMode(driver, resolvedConfig.settings); await collectPhaseArtifacts({phase: 'startInstrumentation', ...phaseOptions}); await collectPhaseArtifacts({phase: 'startSensitiveInstrumentation', ...phaseOptions}); @@ -51,7 +51,7 @@ async function startTimespanGather(page, options = {}) { async endTimespanGather() { const finalDisplayedUrl = await driver.url(); - const runnerOptions = {config, computedCache}; + const runnerOptions = {resolvedConfig, computedCache}; const artifacts = await Runner.gather( async () => { baseArtifacts.URL = {finalDisplayedUrl}; diff --git a/core/index.js b/core/index.js index c822301f0f49..5501330ab686 100644 --- a/core/index.js +++ b/core/index.js @@ -63,9 +63,9 @@ async function legacyNavigation(url, flags = {}, configJSON, userConnection) { flags.logLevel = flags.logLevel || 'error'; log.setLevel(flags.logLevel); - const config = await Config.fromJson(configJSON, flags); + const resolvedConfig = await Config.fromJson(configJSON, flags); const computedCache = new Map(); - const options = {config, computedCache}; + const options = {resolvedConfig, computedCache}; const connection = userConnection || new CriConnection(flags.port, flags.hostname); // kick off a lighthouse run diff --git a/core/legacy/config/config.js b/core/legacy/config/config.js index 15f6487cbfe7..89d739348ef9 100644 --- a/core/legacy/config/config.js +++ b/core/legacy/config/config.js @@ -179,9 +179,9 @@ class Config { const audits = await Config.requireAudits(configJSON.audits, configDir); - const config = new Config(configJSON, {settings, passes, audits}); + const resolvedConfig = new Config(configJSON, {settings, passes, audits}); log.timeEnd(status); - return config; + return resolvedConfig; } /** diff --git a/core/runner.js b/core/runner.js index 8116b63ebe8a..f5135f9c7b90 100644 --- a/core/runner.js +++ b/core/runner.js @@ -34,12 +34,12 @@ class Runner { /** * @template {LH.Config.Config | LH.Config.FRConfig} TConfig * @param {LH.Artifacts} artifacts - * @param {{config: TConfig, driverMock?: Driver, computedCache: Map}} options + * @param {{resolvedConfig: TConfig, driverMock?: Driver, computedCache: Map}} options * @return {Promise} */ static async audit(artifacts, options) { - const {config, computedCache} = options; - const settings = config.settings; + const {resolvedConfig, computedCache} = options; + const settings = resolvedConfig.settings; try { const runnerStatus = {msg: 'Audit phase', id: 'lh:runner:audit'}; @@ -54,10 +54,10 @@ class Runner { // Potentially quit early if (settings.gatherMode && !settings.auditMode) return; - if (!config.audits) { + if (!resolvedConfig.audits) { throw new Error('No audits to evaluate.'); } - const auditResultsById = await Runner._runAudits(settings, config.audits, artifacts, + const auditResultsById = await Runner._runAudits(settings, resolvedConfig.audits, artifacts, lighthouseRunWarnings, computedCache); // LHR construction phase @@ -79,8 +79,8 @@ class Runner { /** @type {Record>} */ let categories = {}; - if (config.categories) { - categories = ReportScoring.scoreAllCategories(config.categories, auditResultsById); + if (resolvedConfig.categories) { + categories = ReportScoring.scoreAllCategories(resolvedConfig.categories, auditResultsById); } log.timeEnd(resultsStatus); @@ -108,7 +108,7 @@ class Runner { audits: auditResultsById, configSettings: settings, categories, - categoryGroups: config.groups || undefined, + categoryGroups: resolvedConfig.groups || undefined, stackPacks: stackPacks.getStackPacks(artifacts.Stacks), timing: this._getTiming(artifacts), i18n: { @@ -143,12 +143,12 @@ class Runner { * and -GA will run everything plus save artifacts and lhr to disk. * * @template {LH.Config.Config | LH.Config.FRConfig} TConfig - * @param {(runnerData: {config: TConfig, driverMock?: Driver}) => Promise} gatherFn - * @param {{config: TConfig, driverMock?: Driver, computedCache: Map}} options + * @param {(runnerData: {resolvedConfig: TConfig, driverMock?: Driver}) => Promise} gatherFn + * @param {{resolvedConfig: TConfig, driverMock?: Driver, computedCache: Map}} options * @return {Promise} */ static async gather(gatherFn, options) { - const settings = options.config.settings; + const settings = options.resolvedConfig.settings; // Either load saved artifacts from disk or from the browser. try { @@ -170,7 +170,7 @@ class Runner { log.time(runnerStatus, 'verbose'); artifacts = await gatherFn({ - config: options.config, + resolvedConfig: options.resolvedConfig, driverMock: options.driverMock, }); @@ -248,22 +248,22 @@ class Runner { /** * Establish connection, load page and collect all required artifacts * @param {string} requestedUrl - * @param {{config: Config, computedCache: Map, driverMock?: Driver}} runnerOpts + * @param {{resolvedConfig: Config, computedCache: Map, driverMock?: Driver}} runnerOpts * @param {Connection} connection * @return {Promise} */ static async _gatherArtifactsFromBrowser(requestedUrl, runnerOpts, connection) { - if (!runnerOpts.config.passes) { + if (!runnerOpts.resolvedConfig.passes) { throw new Error('No browser artifacts are either provided or requested.'); } const driver = runnerOpts.driverMock || new Driver(connection); const gatherOpts = { driver, requestedUrl, - settings: runnerOpts.config.settings, + settings: runnerOpts.resolvedConfig.settings, computedCache: runnerOpts.computedCache, }; - const artifacts = await GatherRunner.run(runnerOpts.config.passes, gatherOpts); + const artifacts = await GatherRunner.run(runnerOpts.resolvedConfig.passes, gatherOpts); return artifacts; } diff --git a/core/scripts/print-a11y-scoring.js b/core/scripts/print-a11y-scoring.js index 81f47aecd741..21c2a3c08230 100644 --- a/core/scripts/print-a11y-scoring.js +++ b/core/scripts/print-a11y-scoring.js @@ -8,10 +8,10 @@ import {initializeConfig} from '../config/config.js'; -const {config} = await initializeConfig('navigation'); -if (!config.categories || !config.audits) throw new Error('wut'); +const {resolvedConfig} = await initializeConfig('navigation'); +if (!resolvedConfig.categories || !resolvedConfig.audits) throw new Error('wut'); -const auditRefs = config.categories.accessibility.auditRefs; +const auditRefs = resolvedConfig.categories.accessibility.auditRefs; const sum = auditRefs.reduce((sum, item) => sum += item.weight, 0); const result = auditRefs .filter(a => a.weight) diff --git a/core/test/config/config-test.js b/core/test/config/config-test.js index 22e7d6b977d5..d0486e54f1f9 100644 --- a/core/test/config/config-test.js +++ b/core/test/config/config-test.js @@ -24,25 +24,25 @@ describe('Fraggle Rock Config', () => { gatherMode = 'snapshot'; }); - it('should throw if the config path is not absolute', async () => { + it('should throw if the resolvedConfig path is not absolute', async () => { await 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(gatherMode, configJson); + const {resolvedConfig} = await initializeConfig(gatherMode, configJson); expect(configJson).toEqual({artifacts: [{id: 'Accessibility', gatherer: 'accessibility'}]}); - expect(config).not.toBe(configJson); - expect(config).not.toEqual(configJson); - expect(config.artifacts).toMatchObject([{gatherer: {path: 'accessibility'}}]); + expect(resolvedConfig).not.toBe(configJson); + expect(resolvedConfig).not.toEqual(configJson); + expect(resolvedConfig.artifacts).toMatchObject([{gatherer: {path: 'accessibility'}}]); }); - it('should use default config when none passed in', async () => { - 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); + it('should use default resolvedConfig when none passed in', async () => { + const {resolvedConfig} = await initializeConfig(gatherMode); + expect(resolvedConfig.settings).toMatchObject({formFactor: 'mobile'}); + if (!resolvedConfig.audits) throw new Error('Did not define audits'); + expect(resolvedConfig.audits.length).toBeGreaterThan(0); }); it('should resolve settings with defaults', async () => { @@ -51,13 +51,13 @@ describe('Fraggle Rock Config', () => { extends: 'lighthouse:default', settings: {output: 'csv', maxWaitForFcp: 1234}, }; - const {config} = await initializeConfig( + const {resolvedConfig} = await initializeConfig( gatherMode, configJson, {maxWaitForFcp: 12345} ); - expect(config.settings).toMatchObject({ + expect(resolvedConfig.settings).toMatchObject({ formFactor: 'mobile', // inherit from default output: 'csv', // config-specific overrides maxWaitForFcp: 12345, // explicit overrides @@ -65,22 +65,22 @@ describe('Fraggle Rock Config', () => { }); it('should override throttlingMethod in timespan mode', async () => { - const {config} = await initializeConfig( + const {resolvedConfig} = await initializeConfig( 'timespan', undefined, {throttlingMethod: 'simulate'} ); - expect(config.settings).toMatchObject({ + expect(resolvedConfig.settings).toMatchObject({ throttlingMethod: 'devtools', }); }); it('should resolve artifact definitions', async () => { const configJson = {artifacts: [{id: 'Accessibility', gatherer: 'accessibility'}]}; - const {config} = await initializeConfig(gatherMode, configJson); + const {resolvedConfig} = await initializeConfig(gatherMode, configJson); - expect(config).toMatchObject({ + expect(resolvedConfig).toMatchObject({ artifacts: [{id: 'Accessibility', gatherer: {path: 'accessibility'}}], }); }); @@ -104,20 +104,20 @@ describe('Fraggle Rock Config', () => { ], }; - const {config} = await initializeConfig('snapshot', configJson); - expect(config).toMatchObject({ + const {resolvedConfig} = await initializeConfig('snapshot', configJson); + expect(resolvedConfig).toMatchObject({ artifacts: [{id: 'Accessibility', gatherer: {path: 'accessibility'}}], }); }); it('should filter configuration by only/skip filters', async () => { - const {config} = await initializeConfig('navigation', undefined, { + const {resolvedConfig} = 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); + const auditIds = (resolvedConfig.audits || []).map(audit => audit.implementation.meta.id); expect(auditIds).toContain('color-contrast'); // from onlyAudits expect(auditIds).toContain('document-title'); // from onlyCategories expect(auditIds).not.toContain('first-contentful-paint'); // from onlyCategories @@ -125,12 +125,12 @@ describe('Fraggle Rock Config', () => { }); it('should support plugins', async () => { - const {config} = await initializeConfig('navigation', undefined, { + const {resolvedConfig} = await initializeConfig('navigation', undefined, { configPath: `${LH_ROOT}/core/test/fixtures/config-plugins/`, plugins: ['lighthouse-plugin-simple'], }); - expect(config).toMatchObject({ + expect(resolvedConfig).toMatchObject({ categories: { 'lighthouse-plugin-simple': {title: 'Simple'}, }, @@ -170,8 +170,8 @@ describe('Fraggle Rock Config', () => { }); it('should resolve artifact dependencies', async () => { - const {config} = await initializeConfig('snapshot', configJson); - expect(config).toMatchObject({ + const {resolvedConfig} = await initializeConfig('snapshot', configJson); + expect(resolvedConfig).toMatchObject({ artifacts: [ {id: 'Dependency', gatherer: {instance: dependencyGatherer}}, { @@ -188,8 +188,8 @@ describe('Fraggle Rock Config', () => { }); it('should resolve artifact dependencies in navigations', async () => { - const {config} = await initializeConfig('snapshot', configJson); - expect(config).toMatchObject({ + const {resolvedConfig} = await initializeConfig('snapshot', configJson); + expect(resolvedConfig).toMatchObject({ navigations: [ { artifacts: [ @@ -233,9 +233,9 @@ describe('Fraggle Rock Config', () => { const configJson = { artifacts: [{id: 'Accessibility', gatherer: 'accessibility'}], }; - const {config} = await initializeConfig('navigation', configJson); + const {resolvedConfig} = await initializeConfig('navigation', configJson); - expect(config).toMatchObject({ + expect(resolvedConfig).toMatchObject({ artifacts: [{id: 'Accessibility', gatherer: {path: 'accessibility'}}], navigations: [ {id: 'default', artifacts: [{id: 'Accessibility', gatherer: {path: 'accessibility'}}]}, @@ -248,9 +248,9 @@ describe('Fraggle Rock Config', () => { const configJson = { artifacts: [{id: 'Accessibility', gatherer: 'accessibility'}], }; - const {config} = await initializeConfig(gatherMode, configJson); + const {resolvedConfig} = await initializeConfig(gatherMode, configJson); - expect(config).toMatchObject({ + expect(resolvedConfig).toMatchObject({ navigations: [ { id: 'default', @@ -274,11 +274,11 @@ describe('Fraggle Rock Config', () => { artifacts: [{id: 'Accessibility', gatherer: 'accessibility'}], }; - const {config} = await initializeConfig(gatherMode, configJson, { + const {resolvedConfig} = await initializeConfig(gatherMode, configJson, { throttlingMethod: 'devtools', }); - expect(config).toMatchObject({ + expect(resolvedConfig).toMatchObject({ navigations: [ { cpuQuietThresholdMs: 10_000, @@ -337,13 +337,13 @@ describe('Fraggle Rock Config', () => { }); it('should do nothing when not extending', async () => { - const {config} = await initializeConfig('navigation', { + const {resolvedConfig} = await initializeConfig('navigation', { artifacts: [ {id: 'Accessibility', gatherer: 'accessibility'}, ], }); - expect(config).toMatchObject({ + expect(resolvedConfig).toMatchObject({ audits: null, groups: null, artifacts: [ @@ -355,59 +355,64 @@ describe('Fraggle Rock Config', () => { }); }); - it('should extend the default config with filters', async () => { + it('should extend the default resolvedConfig with filters', async () => { const gatherMode = 'navigation'; - const {config} = await initializeConfig(gatherMode, { + const {resolvedConfig} = await initializeConfig(gatherMode, { extends: 'lighthouse:default', settings: {onlyCategories: ['accessibility']}, }); - if (!config.artifacts) throw new Error(`No artifacts created`); - if (!config.audits) throw new Error(`No audits created`); + if (!resolvedConfig.artifacts) throw new Error(`No artifacts created`); + if (!resolvedConfig.audits) throw new Error(`No audits created`); - const hasAccessibilityArtifact = config.artifacts.some(a => a.id === 'Accessibility'); - if (!hasAccessibilityArtifact) expect(config.artifacts).toContain('Accessibility'); + const hasAccessibilityArtifact = resolvedConfig.artifacts.some(a => a.id === 'Accessibility'); + if (!hasAccessibilityArtifact) expect(resolvedConfig.artifacts).toContain('Accessibility'); - const hasAccessibilityAudit = config.audits. + const hasAccessibilityAudit = resolvedConfig.audits. some(a => a.implementation.meta.id === 'color-contrast'); - if (!hasAccessibilityAudit) expect(config.audits).toContain('color-contrast'); + if (!hasAccessibilityAudit) expect(resolvedConfig.audits).toContain('color-contrast'); - expect(config.categories).toHaveProperty('accessibility'); - expect(config.categories).not.toHaveProperty('performance'); + expect(resolvedConfig.categories).toHaveProperty('accessibility'); + expect(resolvedConfig.categories).not.toHaveProperty('performance'); }); it('should merge in artifacts', async () => { - const {config} = await initializeConfig('navigation', extensionConfig); - if (!config.artifacts) throw new Error(`No artifacts created`); + const {resolvedConfig} = await initializeConfig('navigation', extensionConfig); + if (!resolvedConfig.artifacts) throw new Error(`No artifacts created`); - const hasExtraArtifact = config.artifacts.some(a => a.id === 'ExtraArtifact'); - if (!hasExtraArtifact) expect(config.artifacts).toContain('ExtraArtifact'); + const hasExtraArtifact = resolvedConfig.artifacts.some(a => a.id === 'ExtraArtifact'); + if (!hasExtraArtifact) expect(resolvedConfig.artifacts).toContain('ExtraArtifact'); }); it('should merge in navigations', async () => { - const {config} = await initializeConfig('navigation', extensionConfig); - if (!config.navigations) throw new Error(`No navigations created`); + const {resolvedConfig} = await initializeConfig('navigation', extensionConfig); + if (!resolvedConfig.navigations) throw new Error(`No navigations created`); - expect(config.navigations).toHaveLength(1); - const hasNavigation = config.navigations[0].artifacts. + expect(resolvedConfig.navigations).toHaveLength(1); + const hasNavigation = resolvedConfig.navigations[0].artifacts. some(a => a.id === 'ExtraArtifact'); - if (!hasNavigation) expect(config.navigations[0].artifacts).toContain('ExtraArtifact'); + if (!hasNavigation) { + expect(resolvedConfig.navigations[0].artifacts).toContain('ExtraArtifact'); + } }); it('should merge in audits', async () => { - const {config} = await initializeConfig('navigation', extensionConfig); - if (!config.audits) throw new Error(`No audits created`); + const {resolvedConfig} = await initializeConfig('navigation', extensionConfig); + if (!resolvedConfig.audits) throw new Error(`No audits created`); - const hasExtraAudit = config.audits. + const hasExtraAudit = resolvedConfig.audits. some(a => a.implementation.meta.id === 'extra-audit'); - if (!hasExtraAudit) expect(config.audits).toContain('extra-audit'); + if (!hasExtraAudit) expect(resolvedConfig.audits).toContain('extra-audit'); }); it('should merge in categories', async () => { - const {config} = await initializeConfig('navigation', extensionConfig); - if (!config.categories) throw new Error(`No categories created`); + const {resolvedConfig} = await initializeConfig('navigation', extensionConfig); + if (!resolvedConfig.categories) throw new Error(`No categories created`); - const hasCategory = config.categories.performance.auditRefs.some(a => a.id === 'extra-audit'); - if (!hasCategory) expect(config.categories.performance.auditRefs).toContain('extra-audit'); + const hasCategory = + resolvedConfig.categories.performance.auditRefs.some(a => a.id === 'extra-audit'); + if (!hasCategory) { + expect(resolvedConfig.categories.performance.auditRefs).toContain('extra-audit'); + } }); }); @@ -417,14 +422,14 @@ describe('Fraggle Rock Config', () => { extends: 'lighthouse:default', }; - const {config, warnings} = await initializeConfig('navigation', extensionConfig); - const navigations = config.navigations; + const {resolvedConfig, warnings} = await initializeConfig('navigation', extensionConfig); + const navigations = resolvedConfig.navigations; if (!navigations) throw new Error(`Failed to initialize navigations`); expect(warnings).toHaveLength(0); expect(navigations[0].loadFailureMode).toEqual('fatal'); }); - it('should validate the config with fatal errors', async () => { + it('should validate the resolvedConfig with fatal errors', async () => { /** @type {LH.Config.Json} */ const extensionConfig = { extends: 'lighthouse:default', @@ -453,8 +458,8 @@ describe('getConfigDisplayString', () => { ], }; - const {config} = await initializeConfig('navigation', configJson); - const printed = getConfigDisplayString(config); + const {resolvedConfig} = await initializeConfig('navigation', configJson); + const printed = getConfigDisplayString(resolvedConfig); const printedConfig = JSON.parse(printed); // Check that options weren't completely eliminated. @@ -469,8 +474,8 @@ describe('getConfigDisplayString', () => { }); it('returns localized category titles', async () => { - const {config} = await initializeConfig('navigation'); - const printed = getConfigDisplayString(config); + const {resolvedConfig} = await initializeConfig('navigation'); + const printed = getConfigDisplayString(resolvedConfig); const printedConfig = JSON.parse(printed); let localizableCount = 0; @@ -490,10 +495,10 @@ 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('navigation'); + const {resolvedConfig: firstConfig} = await initializeConfig('navigation'); const firstPrint = getConfigDisplayString(firstConfig); - const {config: secondConfig} = + const {resolvedConfig: secondConfig} = await initializeConfig('navigation', JSON.parse(firstPrint)); const secondPrint = getConfigDisplayString(secondConfig); diff --git a/core/test/config/filters-test.js b/core/test/config/filters-test.js index 0b22bb4a803b..12fbaf07ed34 100644 --- a/core/test/config/filters-test.js +++ b/core/test/config/filters-test.js @@ -393,10 +393,10 @@ describe('Fraggle Rock Config Filtering', () => { describe('filterConfigByExplicitFilters', () => { /** @type {LH.Config.FRConfig} */ - let config; + let resolvedConfig; beforeEach(() => { - config = { + resolvedConfig = { artifacts: navigationArtifacts, navigations, audits, @@ -407,7 +407,7 @@ describe('Fraggle Rock Config Filtering', () => { }); it('should filter via onlyAudits', () => { - const filtered = filters.filterConfigByExplicitFilters(config, { + const filtered = filters.filterConfigByExplicitFilters(resolvedConfig, { onlyAudits: ['snapshot'], onlyCategories: null, skipAudits: null, @@ -424,7 +424,7 @@ describe('Fraggle Rock Config Filtering', () => { }); it('should filter via skipAudits', () => { - const filtered = filters.filterConfigByExplicitFilters(config, { + const filtered = filters.filterConfigByExplicitFilters(resolvedConfig, { onlyAudits: null, onlyCategories: null, skipAudits: ['snapshot', 'navigation'], @@ -440,7 +440,7 @@ describe('Fraggle Rock Config Filtering', () => { }); it('should filter via onlyCategories', () => { - const filtered = filters.filterConfigByExplicitFilters(config, { + const filtered = filters.filterConfigByExplicitFilters(resolvedConfig, { onlyAudits: null, onlyCategories: ['timespan'], skipAudits: null, @@ -463,7 +463,7 @@ describe('Fraggle Rock Config Filtering', () => { const saveWarning = evt => warnings.push(evt); log.events.on('warning', saveWarning); - const filtered = filters.filterConfigByExplicitFilters(config, { + const filtered = filters.filterConfigByExplicitFilters(resolvedConfig, { onlyAudits: null, onlyCategories: ['timespan', 'thisIsNotACategory'], skipAudits: null, @@ -485,7 +485,7 @@ describe('Fraggle Rock Config Filtering', () => { }); it('should filter via a combination of filters', () => { - const filtered = filters.filterConfigByExplicitFilters(config, { + const filtered = filters.filterConfigByExplicitFilters(resolvedConfig, { onlyCategories: ['mixed'], onlyAudits: ['snapshot', 'timespan'], skipAudits: ['timespan', 'navigation'], @@ -500,15 +500,15 @@ describe('Fraggle Rock Config Filtering', () => { }); it('should filter out audits and artifacts not in the categories by default', () => { - config = { - ...config, + resolvedConfig = { + ...resolvedConfig, audits: [ ...audits, {implementation: NavigationOnlyAudit, options: {}}, ], }; - const filtered = filters.filterConfigByExplicitFilters(config, { + const filtered = filters.filterConfigByExplicitFilters(resolvedConfig, { onlyAudits: null, onlyCategories: null, skipAudits: null, @@ -526,8 +526,8 @@ describe('Fraggle Rock Config Filtering', () => { }); it('should keep all audits if there are no categories', () => { - config = { - ...config, + resolvedConfig = { + ...resolvedConfig, audits: [ ...audits, {implementation: NavigationOnlyAudit, options: {}}, @@ -535,7 +535,7 @@ describe('Fraggle Rock Config Filtering', () => { categories: {}, }; - const filtered = filters.filterConfigByExplicitFilters(config, { + const filtered = filters.filterConfigByExplicitFilters(resolvedConfig, { onlyAudits: null, onlyCategories: null, skipAudits: null, @@ -554,9 +554,9 @@ describe('Fraggle Rock Config Filtering', () => { }); it('should preserve full-page-screenshot', async () => { - config = (await initializeConfig('navigation')).config; + resolvedConfig = (await initializeConfig('navigation')).resolvedConfig; - const filtered = filters.filterConfigByExplicitFilters(config, { + const filtered = filters.filterConfigByExplicitFilters(resolvedConfig, { onlyAudits: ['color-contrast'], onlyCategories: null, skipAudits: null, diff --git a/core/test/gather/base-artifacts-test.js b/core/test/gather/base-artifacts-test.js index 0650e5aade4f..fd786d54ec0e 100644 --- a/core/test/gather/base-artifacts-test.js +++ b/core/test/gather/base-artifacts-test.js @@ -30,22 +30,22 @@ describe('getBaseArtifacts', () => { }); it('should fetch benchmark index', async () => { - const {config} = await initializeConfig('navigation'); - const artifacts = await getBaseArtifacts(config, driverMock.asDriver(), {gatherMode}); + const {resolvedConfig} = await initializeConfig('navigation'); + const artifacts = await getBaseArtifacts(resolvedConfig, driverMock.asDriver(), {gatherMode}); expect(artifacts.BenchmarkIndex).toEqual(500); }); it('should fetch host user agent', async () => { - const {config} = await initializeConfig('navigation'); - const artifacts = await getBaseArtifacts(config, driverMock.asDriver(), {gatherMode}); + const {resolvedConfig} = await initializeConfig('navigation'); + const artifacts = await getBaseArtifacts(resolvedConfig, driverMock.asDriver(), {gatherMode}); expect(artifacts.HostUserAgent).toContain('Macintosh'); expect(artifacts.HostFormFactor).toEqual('desktop'); }); it('should return settings', async () => { - const {config} = await initializeConfig('navigation'); - const artifacts = await getBaseArtifacts(config, driverMock.asDriver(), {gatherMode}); - expect(artifacts.settings).toEqual(config.settings); + const {resolvedConfig} = await initializeConfig('navigation'); + const artifacts = await getBaseArtifacts(resolvedConfig, driverMock.asDriver(), {gatherMode}); + expect(artifacts.settings).toEqual(resolvedConfig.settings); }); }); @@ -56,9 +56,9 @@ describe('finalizeArtifacts', () => { let gathererArtifacts = {}; beforeEach(async () => { - const {config} = await initializeConfig(gatherMode); + const {resolvedConfig} = await initializeConfig(gatherMode); const driver = getMockDriverForArtifacts().asDriver(); - baseArtifacts = await getBaseArtifacts(config, driver, {gatherMode}); + baseArtifacts = await getBaseArtifacts(resolvedConfig, driver, {gatherMode}); baseArtifacts.URL = {finalDisplayedUrl: 'https://example.com'}; gathererArtifacts = {}; }); diff --git a/core/test/gather/navigation-runner-test.js b/core/test/gather/navigation-runner-test.js index a15fef673be3..b560defe3a82 100644 --- a/core/test/gather/navigation-runner-test.js +++ b/core/test/gather/navigation-runner-test.js @@ -46,7 +46,7 @@ describe('NavigationRunner', () => { /** @type {LH.Puppeteer.Page} */ let page; /** @type {LH.Config.FRConfig} */ - let config; + let resolvedConfig; /** @type {LH.Config.NavigationDefn} */ let navigation; /** @type {Map} */ @@ -103,7 +103,7 @@ describe('NavigationRunner', () => { beforeEach(async () => { requestedUrl = 'http://example.com'; requestor = requestedUrl; - config = (await initializeConfig('navigation')).config; + resolvedConfig = (await initializeConfig('navigation')).resolvedConfig; navigation = createNavigation().navigation; computedCache = new Map(); baseArtifacts = createMockBaseArtifacts(); @@ -128,12 +128,12 @@ describe('NavigationRunner', () => { }); it('should connect the driver', async () => { - await runner._setup({driver, config, requestor: requestedUrl}); + await runner._setup({driver, resolvedConfig, requestor: requestedUrl}); expect(mockDriver.connect).toHaveBeenCalled(); }); it('should navigate to the blank page if requestor is a string', async () => { - await runner._setup({driver, config, requestor: requestedUrl}); + await runner._setup({driver, resolvedConfig, requestor: requestedUrl}); expect(mocks.navigationMock.gotoURL).toHaveBeenCalledTimes(1); expect(mocks.navigationMock.gotoURL).toHaveBeenCalledWith( expect.anything(), @@ -145,25 +145,26 @@ describe('NavigationRunner', () => { it('skip about:blank if using callback requestor', async () => { await runner._setup({ driver, - config, + resolvedConfig, requestor: () => {}, }); expect(mocks.navigationMock.gotoURL).not.toHaveBeenCalled(); }); it('skip about:blank if config option is set to true', async () => { - config.settings.skipAboutBlank = true; + resolvedConfig.settings.skipAboutBlank = true; await runner._setup({ driver, - config, + resolvedConfig, requestor: requestedUrl, }); expect(mocks.navigationMock.gotoURL).not.toHaveBeenCalled(); }); it('should collect base artifacts', async () => { - const {baseArtifacts} = await runner._setup({driver, config, requestor: requestedUrl}); + const {baseArtifacts} = + await runner._setup({driver, resolvedConfig, requestor: requestedUrl}); expect(baseArtifacts).toMatchObject({ URL: { finalDisplayedUrl: '', @@ -172,14 +173,14 @@ describe('NavigationRunner', () => { }); it('should prepare the target for navigation', async () => { - await runner._setup({driver, config, requestor: requestedUrl}); + await runner._setup({driver, resolvedConfig, 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, requestor: requestedUrl}); + const setupPromise = runner._setup({driver, resolvedConfig, requestor: requestedUrl}); await expect(setupPromise).rejects.toThrowError(/Not available/); expect(mocks.prepareMock.prepareTargetForNavigationMode).not.toHaveBeenCalled(); }); @@ -187,17 +188,17 @@ describe('NavigationRunner', () => { describe('_navigations', () => { const run = () => - runner._navigations({driver, page, config, requestor, computedCache, baseArtifacts}); + runner._navigations({driver, page, resolvedConfig, requestor, computedCache, baseArtifacts}); it('should throw if no navigations available', async () => { - config = {...config, navigations: null}; + resolvedConfig = {...resolvedConfig, navigations: null}; await expect(run()).rejects.toBeTruthy(); }); it('should navigate as many times as there are navigations', async () => { // initializeConfig always produces a single config navigation. // Artificially construct multiple navigations to test on the navigation runner. - const originalNavigation = config.navigations?.[0]; + const originalNavigation = resolvedConfig.navigations?.[0]; if (!originalNavigation) throw new Error('Should always have navigations'); const artifactDefns = originalNavigation.artifacts.filter(a => ['FontSize', 'ConsoleMessages', 'ViewportDimensions', 'AnchorElements'].includes(a.id) @@ -212,7 +213,7 @@ describe('NavigationRunner', () => { }); } - config.navigations = newNavigations; + resolvedConfig.navigations = newNavigations; await run(); const navigations = mocks.navigationMock.gotoURL.mock.calls; @@ -223,16 +224,16 @@ describe('NavigationRunner', () => { it('should backfill requested URL using a callback requestor', async () => { requestedUrl = 'https://backfill.example.com'; requestor = () => {}; - config = (await initializeConfig( + resolvedConfig = (await initializeConfig( 'navigation', { - ...config, + ...resolvedConfig, artifacts: [ {id: 'FontSize', gatherer: 'seo/font-size'}, {id: 'MetaElements', gatherer: 'meta-elements'}, ], } - )).config; + )).resolvedConfig; mocks.navigationMock.gotoURL.mockReturnValue({ requestedUrl, mainDocumentUrl: requestedUrl, @@ -251,15 +252,15 @@ describe('NavigationRunner', () => { it('should merge artifacts between navigations', async () => { // initializeConfig always produces a single config navigation. // Artificially construct multiple navigations to test on the navigation runner. - if (!config.navigations) throw new Error('Should always have navigations'); - const firstNavigation = config.navigations[0]; + if (!resolvedConfig.navigations) throw new Error('Should always have navigations'); + const firstNavigation = resolvedConfig.navigations[0]; const secondNavigation = {...firstNavigation, id: 'second'}; const fontSizeDef = firstNavigation.artifacts.find(a => a.id === 'FontSize'); const consoleMsgDef = firstNavigation.artifacts.find(a => a.id === 'ConsoleMessages'); if (!fontSizeDef || !consoleMsgDef) throw new Error('Artifact definitions not found'); secondNavigation.artifacts = [fontSizeDef]; firstNavigation.artifacts = [consoleMsgDef]; - config.navigations.push(secondNavigation); + resolvedConfig.navigations.push(secondNavigation); // Both gatherers will error in these test conditions, but artifact errors // will be merged into single `artifacts` object. @@ -270,16 +271,16 @@ describe('NavigationRunner', () => { }); it('should retain PageLoadError and associated warnings', async () => { - config = (await initializeConfig( + resolvedConfig = (await initializeConfig( 'navigation', { - ...config, + ...resolvedConfig, artifacts: [ {id: 'FontSize', gatherer: 'seo/font-size'}, {id: 'MetaElements', gatherer: 'meta-elements'}, ], } - )).config; + )).resolvedConfig; // Ensure the first real page load fails. mocks.navigationMock.gotoURL.mockImplementation((driver, url) => { @@ -312,7 +313,7 @@ describe('NavigationRunner', () => { const run = navigation => runner._navigation({ driver, page, - config, + resolvedConfig, navigation, requestor, computedCache, @@ -330,12 +331,12 @@ describe('NavigationRunner', () => { }); it('skips about:blank if config option is set to true', async () => { - config.settings.skipAboutBlank = true; + resolvedConfig.settings.skipAboutBlank = true; const {artifacts} = await runner._navigation({ driver, page, - config, + resolvedConfig, navigation, requestor: requestedUrl, computedCache, @@ -353,7 +354,7 @@ describe('NavigationRunner', () => { const {artifacts} = await runner._navigation({ driver, page, - config, + resolvedConfig, navigation, requestor: () => {}, computedCache, @@ -496,7 +497,7 @@ describe('NavigationRunner', () => { page, navigation, requestor: requestedUrl, - config, + resolvedConfig, computedCache, baseArtifacts, }); @@ -513,7 +514,7 @@ describe('NavigationRunner', () => { page, navigation, requestor: requestedUrl, - config, + resolvedConfig, computedCache, baseArtifacts, }); @@ -528,7 +529,7 @@ describe('NavigationRunner', () => { page, navigation, requestor: requestedUrl, - config, + resolvedConfig, computedCache, baseArtifacts, }); @@ -543,7 +544,7 @@ describe('NavigationRunner', () => { page, navigation, requestor, - config, + resolvedConfig, computedCache, baseArtifacts, }); @@ -585,14 +586,14 @@ describe('NavigationRunner', () => { describe('_cleanup', () => { it('should clear storage when storage was reset', async () => { - config.settings.disableStorageReset = false; - await runner._cleanup({requestedUrl, driver, config}); + resolvedConfig.settings.disableStorageReset = false; + await runner._cleanup({requestedUrl, driver, resolvedConfig}); expect(mocks.storageMock.clearDataForOrigin).toHaveBeenCalled(); }); it('should not clear storage when storage reset was disabled', async () => { - config.settings.disableStorageReset = true; - await runner._cleanup({requestedUrl, driver, config}); + resolvedConfig.settings.disableStorageReset = true; + await runner._cleanup({requestedUrl, driver, resolvedConfig}); expect(mocks.storageMock.clearDataForOrigin).not.toHaveBeenCalled(); }); }); @@ -620,7 +621,7 @@ describe('NavigationRunner', () => { ); expect(mockRunner.gather.mock.calls[0][1]).toMatchObject({ - config: { + resolvedConfig: { settings: flags, }, }); diff --git a/core/test/gather/snapshot-runner-test.js b/core/test/gather/snapshot-runner-test.js index 7ff62dbc208a..abdf8e275f75 100644 --- a/core/test/gather/snapshot-runner-test.js +++ b/core/test/gather/snapshot-runner-test.js @@ -103,7 +103,7 @@ describe('Snapshot Runner', () => { await snapshotGather(page, {config, flags}); expect(mockRunner.gather.mock.calls[0][1]).toMatchObject({ - config: { + resolvedConfig: { settings: flags, }, }); diff --git a/core/test/gather/timespan-runner-test.js b/core/test/gather/timespan-runner-test.js index 6f60168e1b2f..120da9a2ffc4 100644 --- a/core/test/gather/timespan-runner-test.js +++ b/core/test/gather/timespan-runner-test.js @@ -117,7 +117,7 @@ describe('Timespan Runner', () => { await timespan.endTimespanGather(); expect(mockRunner.gather.mock.calls[0][1]).toMatchObject({ - config: { + resolvedConfig: { settings: flags, }, }); diff --git a/core/test/lib/stack-packs-test.js b/core/test/lib/stack-packs-test.js index a2f75d5e9b56..34e0f6c90572 100644 --- a/core/test/lib/stack-packs-test.js +++ b/core/test/lib/stack-packs-test.js @@ -10,8 +10,8 @@ import {initializeConfig} from '../../config/config.js'; import {stackPacksToInclude} from '../../lib/stack-packs.js'; async function getAuditIds() { - const {config} = await initializeConfig('navigation'); - return config.audits.map(a => a.implementation.meta.id); + const {resolvedConfig} = await initializeConfig('navigation'); + return resolvedConfig.audits.map(a => a.implementation.meta.id); } describe('stack-packs lib', () => { diff --git a/core/test/runner-test.js b/core/test/runner-test.js index c7ef1eba6aa6..8aa8cdd0b3be 100644 --- a/core/test/runner-test.js +++ b/core/test/runner-test.js @@ -110,7 +110,7 @@ describe('Runner', () => { }); it('-G gathers, quits, and doesn\'t run audits', async () => { - const opts = {config: await generateConfig({gatherMode: artifactsPath}), driverMock}; + const opts = {resolvedConfig: await generateConfig({gatherMode: artifactsPath}), driverMock}; return runGatherAndAudit(createGatherFn(url), opts).then(_ => { expect(loadArtifactsSpy).not.toHaveBeenCalled(); expect(saveArtifactsSpy).toHaveBeenCalled(); @@ -130,7 +130,7 @@ describe('Runner', () => { // uses the files on disk from the -G test. ;) it('-A audits from saved artifacts and doesn\'t gather', async () => { - const opts = {config: await generateConfig({auditMode: artifactsPath}), driverMock}; + const opts = {resolvedConfig: await generateConfig({auditMode: artifactsPath}), driverMock}; return runGatherAndAudit(createGatherFn(), opts).then(_ => { expect(loadArtifactsSpy).toHaveBeenCalled(); expect(gatherRunnerRunSpy).not.toHaveBeenCalled(); @@ -143,7 +143,7 @@ describe('Runner', () => { it('-A throws if the settings change', async () => { // Change throttlingMethod from its default of 'simulate' const settings = {auditMode: artifactsPath, throttlingMethod: 'provided'}; - const opts = {config: await generateConfig(settings), driverMock}; + const opts = {resolvedConfig: await generateConfig(settings), driverMock}; try { await runGatherAndAudit(createGatherFn(), opts); assert.fail('should have thrown'); @@ -153,7 +153,7 @@ describe('Runner', () => { }); it('does not include a top-level runtimeError when gatherers were successful', async () => { - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/perflog/', }, @@ -162,13 +162,13 @@ describe('Runner', () => { ], }); - const {lhr} = await runGatherAndAudit(undefined, {config}); + const {lhr} = await runGatherAndAudit(undefined, {resolvedConfig}); assert.strictEqual(lhr.runtimeError, undefined); }); it('-GA is a normal run but it saves artifacts and LHR to disk', async () => { const settings = {auditMode: artifactsPath, gatherMode: artifactsPath}; - const opts = {config: await generateConfig(settings), driverMock}; + const opts = {resolvedConfig: await generateConfig(settings), driverMock}; return runGatherAndAudit(createGatherFn(url), opts).then(_ => { expect(loadArtifactsSpy).not.toHaveBeenCalled(); expect(gatherRunnerRunSpy).toHaveBeenCalled(); @@ -179,7 +179,7 @@ describe('Runner', () => { }); it('non -G/-A run doesn\'t save artifacts to disk', async () => { - const opts = {config: await generateConfig(), driverMock}; + const opts = {resolvedConfig: await generateConfig(), driverMock}; return runGatherAndAudit(createGatherFn(url), opts).then(_ => { expect(loadArtifactsSpy).not.toHaveBeenCalled(); expect(gatherRunnerRunSpy).toHaveBeenCalled(); @@ -207,7 +207,7 @@ describe('Runner', () => { settings: {gatherMode: artifactsPath}, passes: [{gatherers: [WarningAndErrorGatherer]}], }); - await runGatherAndAudit(createGatherFn(url), {config: gatherConfig, driverMock}); + await runGatherAndAudit(createGatherFn(url), {resolvedConfig: gatherConfig, driverMock}); // Artifacts are still localizable. const artifacts = assetSaver.loadArtifacts(resolvedPath); @@ -237,7 +237,7 @@ describe('Runner', () => { settings: {auditMode: artifactsPath}, audits: [{implementation: DummyAudit}], }); - const {lhr} = await runGatherAndAudit(createGatherFn(url), {config: auditConfig}); + const {lhr} = await runGatherAndAudit(createGatherFn(url), {resolvedConfig: auditConfig}); // Messages are now localized and formatted. expect(lhr.runWarnings[0]).toBe('Potential savings of 2 KiB'); @@ -251,7 +251,7 @@ describe('Runner', () => { it('expands gatherers', async () => { const url = 'https://example.com'; - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ passes: [{ gatherers: ['viewport-dimensions'], }], @@ -260,21 +260,21 @@ describe('Runner', () => { ], }); - return runGatherAndAudit(createGatherFn(url), {config, driverMock}).then(_ => { + return runGatherAndAudit(createGatherFn(url), {resolvedConfig, driverMock}).then(_ => { expect(gatherRunnerRunSpy).toHaveBeenCalled(); - assert.ok(typeof config.passes[0].gatherers[0] === 'object'); + assert.ok(typeof resolvedConfig.passes[0].gatherers[0] === 'object'); }); }); it('rejects when given neither passes nor artifacts', async () => { const url = 'https://example.com'; - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ audits: [ 'content-width', ], }); - return runGatherAndAudit(createGatherFn(url), {config, driverMock}) + return runGatherAndAudit(createGatherFn(url), {resolvedConfig, driverMock}) .then(_ => { assert.ok(false); }, err => { @@ -302,7 +302,7 @@ describe('Runner', () => { } } - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/empty-artifacts/', }, @@ -312,7 +312,7 @@ describe('Runner', () => { ], }); - return runGatherAndAudit({}, {url, config}).then(results => { + return runGatherAndAudit({}, {url, resolvedConfig}).then(results => { assert.equal(results.lhr.requestedUrl, url); assert.equal(results.lhr.audits['eavesdrop-audit'].score, 1); // assert that the options we received matched expectations @@ -321,7 +321,7 @@ describe('Runner', () => { }); it('accepts trace artifacts as paths and outputs appropriate data', async () => { - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/perflog/', }, @@ -330,7 +330,7 @@ describe('Runner', () => { ], }); - return runGatherAndAudit({}, {config, computedCache: new Map()}).then(results => { + return runGatherAndAudit({}, {resolvedConfig, computedCache: new Map()}).then(results => { const audits = results.lhr.audits; assert.equal(audits['user-timings'].displayValue, '2 user timings'); assert.deepStrictEqual(audits['user-timings'].details.items.map(i => i.startTime), @@ -340,7 +340,7 @@ describe('Runner', () => { it('rejects when given an invalid trace artifact', async () => { const url = 'https://example.com'; - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ passes: [{ recordTrace: true, gatherers: [], @@ -356,7 +356,7 @@ describe('Runner', () => { }, }); - return runGatherAndAudit({}, {url, config, driverMock: badTraceDriver}) + return runGatherAndAudit({}, {url, resolvedConfig, driverMock: badTraceDriver}) .then(_ => { assert.ok(false); }, _ => { @@ -365,7 +365,7 @@ describe('Runner', () => { }); it('finds correct timings for multiple gather/audit pairs run separately', async () => { - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ passes: [{ gatherers: ['viewport-dimensions'], }], @@ -373,8 +373,8 @@ describe('Runner', () => { 'content-width', ], }); - const options1 = {config, driverMock, computedCache: new Map()}; - const options2 = {config, driverMock, computedCache: new Map()}; + const options1 = {resolvedConfig, driverMock, computedCache: new Map()}; + const options2 = {resolvedConfig, driverMock, computedCache: new Map()}; const artifacts1 = await Runner.gather(createGatherFn('https://example.com'), options1); const artifacts2 = await Runner.gather(createGatherFn('https://google.com'), options2); @@ -394,7 +394,7 @@ describe('Runner', () => { describe('Bad required artifact handling', () => { it('outputs an error audit result when trace required but not provided', async () => { - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/empty-artifacts/', }, @@ -404,7 +404,7 @@ describe('Runner', () => { ], }); - const results = await runGatherAndAudit({}, {config}); + const results = await runGatherAndAudit({}, {resolvedConfig}); const auditResult = results.lhr.audits['user-timings']; assert.strictEqual(auditResult.score, null); assert.strictEqual(auditResult.scoreDisplayMode, 'error'); @@ -412,7 +412,7 @@ describe('Runner', () => { }); it('outputs an error audit result when devtoolsLog required but not provided', async () => { - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/empty-artifacts/', }, @@ -422,7 +422,7 @@ describe('Runner', () => { ], }); - const results = await runGatherAndAudit({}, {config}); + const results = await runGatherAndAudit({}, {resolvedConfig}); const auditResult = results.lhr.audits['is-on-https']; assert.strictEqual(auditResult.score, null); assert.strictEqual(auditResult.scoreDisplayMode, 'error'); @@ -430,7 +430,7 @@ describe('Runner', () => { }); it('outputs an error audit result when missing a required artifact', async () => { - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/empty-artifacts/', }, @@ -440,7 +440,7 @@ describe('Runner', () => { ], }); - return runGatherAndAudit({}, {config}).then(results => { + return runGatherAndAudit({}, {resolvedConfig}).then(results => { const auditResult = results.lhr.audits['content-width']; assert.strictEqual(auditResult.score, null); assert.strictEqual(auditResult.scoreDisplayMode, 'error'); @@ -464,7 +464,7 @@ describe('Runner', () => { await assetSaver.saveArtifacts(artifacts, resolvedPath); // Load artifacts via auditMode. - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: resolvedPath, }, @@ -474,7 +474,7 @@ describe('Runner', () => { ], }); - const results = await runGatherAndAudit({}, {config}); + const results = await runGatherAndAudit({}, {resolvedConfig}); const auditResult = results.lhr.audits['content-width']; assert.strictEqual(auditResult.score, null); assert.strictEqual(auditResult.scoreDisplayMode, 'error'); @@ -497,7 +497,7 @@ describe('Runner', () => { } const auditMockFn = SimpleAudit.audit = jestMock.fn().mockReturnValue({score: 1}); - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/alphabet-artifacts/', }, @@ -506,7 +506,7 @@ describe('Runner', () => { ], }); - const results = await runGatherAndAudit({}, {config}); + const results = await runGatherAndAudit({}, {resolvedConfig}); expect(results.lhr).toMatchObject({audits: {simple: {score: 1}}}); expect(auditMockFn).toHaveBeenCalled(); expect(auditMockFn.mock.calls[0][0]).toEqual({ @@ -530,7 +530,7 @@ describe('Runner', () => { } const auditMockFn = SimpleAudit.audit = jestMock.fn().mockReturnValue({score: 1}); - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/alphabet-artifacts/', }, @@ -539,7 +539,7 @@ describe('Runner', () => { ], }); - const results = await runGatherAndAudit({}, {config}); + const results = await runGatherAndAudit({}, {resolvedConfig}); expect(results.lhr).toMatchObject({audits: {simple: {score: 1}}}); expect(auditMockFn).toHaveBeenCalled(); expect(auditMockFn.mock.calls[0][0]).toEqual({ @@ -561,7 +561,7 @@ describe('Runner', () => { it('produces an error audit result when an audit throws an Error', async () => { const errorMessage = 'Audit yourself'; - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/empty-artifacts/', }, @@ -577,7 +577,7 @@ describe('Runner', () => { ], }); - return runGatherAndAudit({}, {config}).then(results => { + return runGatherAndAudit({}, {resolvedConfig}).then(results => { const auditResult = results.lhr.audits['throwy-audit']; assert.strictEqual(auditResult.score, null); assert.strictEqual(auditResult.scoreDisplayMode, 'error'); @@ -587,7 +587,7 @@ describe('Runner', () => { }); it('accepts devtoolsLog in artifacts', async () => { - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/perflog/', }, @@ -596,7 +596,7 @@ describe('Runner', () => { ], }); - return runGatherAndAudit({}, {config, computedCache: new Map()}).then(results => { + return runGatherAndAudit({}, {resolvedConfig, computedCache: new Map()}).then(results => { const audits = results.lhr.audits; assert.equal(audits['critical-request-chains'].displayValue, '5 chains found'); assert.equal(audits['critical-request-chains'].details.longestChain.transferSize, 2468); @@ -605,13 +605,13 @@ describe('Runner', () => { it('rejects when not given audits to run (and not -G)', async () => { const url = 'https://example.com'; - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ passes: [{ gatherers: ['viewport-dimensions'], }], }); - return runGatherAndAudit(createGatherFn(url), {config, driverMock}) + return runGatherAndAudit(createGatherFn(url), {resolvedConfig, driverMock}) .then(_ => { assert.ok(false); }, err => { @@ -621,7 +621,7 @@ describe('Runner', () => { it('returns data even if no config categories are provided', async () => { const url = 'https://example.com/'; - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ passes: [{ gatherers: ['viewport-dimensions'], }], @@ -630,7 +630,7 @@ describe('Runner', () => { ], }); - return runGatherAndAudit(createGatherFn(url), {config, driverMock}).then(results => { + return runGatherAndAudit(createGatherFn(url), {resolvedConfig, driverMock}).then(results => { assert.ok(results.lhr.lighthouseVersion); assert.ok(results.lhr.fetchTime); assert.equal(results.lhr.requestedUrl, url); @@ -641,7 +641,7 @@ describe('Runner', () => { it('returns categories', async () => { const url = 'https://example.com/'; - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ passes: [{ gatherers: ['viewport-dimensions'], }], @@ -659,7 +659,7 @@ describe('Runner', () => { }, }); - return runGatherAndAudit(createGatherFn(url), {config, driverMock}).then(results => { + return runGatherAndAudit(createGatherFn(url), {resolvedConfig, driverMock}).then(results => { expect(gatherRunnerRunSpy).toHaveBeenCalled(); assert.ok(results.lhr.lighthouseVersion); assert.ok(results.lhr.fetchTime); @@ -682,7 +682,7 @@ describe('Runner', () => { }); it('results include artifacts when given artifacts and audits', async () => { - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/perflog/', }, @@ -691,7 +691,7 @@ describe('Runner', () => { ], }); - return runGatherAndAudit({}, {config}).then(results => { + return runGatherAndAudit({}, {resolvedConfig}).then(results => { assert.strictEqual(results.artifacts.ViewportDimensions.innerWidth, 412); assert.strictEqual(results.artifacts.ViewportDimensions.innerHeight, 660); }); @@ -699,7 +699,7 @@ describe('Runner', () => { it('results include artifacts when given passes and audits', async () => { const url = 'https://example.com'; - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ passes: [{ passName: 'firstPass', gatherers: ['meta-elements', 'viewport-dimensions'], @@ -710,7 +710,7 @@ describe('Runner', () => { ], }); - return runGatherAndAudit(createGatherFn(url), {config, driverMock}).then(results => { + return runGatherAndAudit(createGatherFn(url), {resolvedConfig, driverMock}).then(results => { // User-specified artifact. assert.ok(results.artifacts.ViewportDimensions); @@ -722,14 +722,14 @@ describe('Runner', () => { }); it('includes any LighthouseRunWarnings from artifacts in output', async () => { - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/perflog/', }, audits: [], }); - return runGatherAndAudit(createGatherFn(), {config, driverMock}).then(results => { + return runGatherAndAudit(createGatherFn(), {resolvedConfig, driverMock}).then(results => { assert.deepStrictEqual(results.lhr.runWarnings, [ 'I\'m a warning!', 'Also a warning', @@ -740,7 +740,7 @@ describe('Runner', () => { it('includes any LighthouseRunWarnings from audits in LHR', async () => { const warningString = 'Really important audit warning!'; - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ settings: { auditMode: moduleDir + '/fixtures/artifacts/empty-artifacts/', }, @@ -760,7 +760,7 @@ describe('Runner', () => { ], }); - return runGatherAndAudit(createGatherFn(), {config, driverMock}).then(results => { + return runGatherAndAudit(createGatherFn(), {resolvedConfig, driverMock}).then(results => { assert.deepStrictEqual(results.lhr.runWarnings, [warningString]); }); }); @@ -801,8 +801,8 @@ describe('Runner', () => { }; it('includes a top-level runtimeError when a gatherer throws one', async () => { - const config = await Config.fromJson(configJson); - const {lhr} = await runGatherAndAudit(createGatherFn('https://example.com/'), {config, driverMock}); + const resolvedConfig = await Config.fromJson(configJson); + const {lhr} = await runGatherAndAudit(createGatherFn('https://example.com/'), {resolvedConfig, driverMock}); // Audit error included the runtimeError expect(lhr.audits['test-audit'].scoreDisplayMode).toEqual('error'); @@ -832,10 +832,10 @@ describe('Runner', () => { } }); - const config = await Config.fromJson(configJson); + const resolvedConfig = await Config.fromJson(configJson); const {lhr} = await runGatherAndAudit( createGatherFn(url), - {config, driverMock: errorDriverMock} + {resolvedConfig, driverMock: errorDriverMock} ); // Audit error still includes the gatherer runtimeError. @@ -860,7 +860,7 @@ describe('Runner', () => { }; try { - await runGatherAndAudit(createGatherFn('https://example.com/'), {driverMock: erroringDriver, config: await Config.fromJson()}); + await runGatherAndAudit(createGatherFn('https://example.com/'), {driverMock: erroringDriver, resolvedConfig: await Config.fromJson()}); assert.fail('should have thrown'); } catch (err) { assert.equal(err.code, LighthouseError.errors.PROTOCOL_TIMEOUT.code); @@ -871,7 +871,7 @@ describe('Runner', () => { it('can handle array of outputs', async () => { const url = 'https://example.com'; - const config = await Config.fromJson({ + const resolvedConfig = await Config.fromJson({ extends: 'lighthouse:default', settings: { onlyCategories: ['performance'], @@ -879,7 +879,7 @@ describe('Runner', () => { }, }); - const results = await runGatherAndAudit(createGatherFn(url), {config, driverMock}); + const results = await runGatherAndAudit(createGatherFn(url), {resolvedConfig, driverMock}); assert.ok(Array.isArray(results.report) && results.report.length === 2, 'did not return multiple reports'); assert.ok(JSON.parse(results.report[0]), 'did not return json output'); diff --git a/core/test/user-flow-test.js b/core/test/user-flow-test.js index a8ba306b1367..3accb69e8ee2 100644 --- a/core/test/user-flow-test.js +++ b/core/test/user-flow-test.js @@ -459,7 +459,7 @@ describe('UserFlow', () => { [ gatherSteps[0].artifacts, { - config: { + resolvedConfig: { settings: { skipAudits: ['uses-http2'], }, @@ -469,7 +469,7 @@ describe('UserFlow', () => { [ gatherSteps[1].artifacts, { - config: { + resolvedConfig: { settings: { onlyCategories: ['performance'], }, @@ -479,7 +479,7 @@ describe('UserFlow', () => { [ gatherSteps[2].artifacts, { - config: { + resolvedConfig: { settings: { onlyCategories: ['accessibility'], }, diff --git a/core/user-flow.js b/core/user-flow.js index e58bef8c3123..b189d460e137 100644 --- a/core/user-flow.js +++ b/core/user-flow.js @@ -323,9 +323,9 @@ async function auditGatherSteps(gatherSteps, options) { // Step specific configs take precedence over a config for the entire flow. const configJson = options.config; const {gatherMode} = artifacts.GatherContext; - const {config} = await initializeConfig(gatherMode, configJson, flags); + const {resolvedConfig} = await initializeConfig(gatherMode, configJson, flags); runnerOptions = { - config, + resolvedConfig, computedCache: new Map(), }; } diff --git a/types/gatherer.d.ts b/types/gatherer.d.ts index c4955b134aaa..32c6036ff3f2 100644 --- a/types/gatherer.d.ts +++ b/types/gatherer.d.ts @@ -67,7 +67,7 @@ declare module Gatherer { interface FRGatherResult { artifacts: Artifacts; runnerOptions: { - config: Config.FRConfig; + resolvedConfig: Config.FRConfig; computedCache: Map } }