diff --git a/lighthouse-core/fraggle-rock/config/filters.js b/lighthouse-core/fraggle-rock/config/filters.js index 4b9c0027f71c..f4beff315096 100644 --- a/lighthouse-core/fraggle-rock/config/filters.js +++ b/lighthouse-core/fraggle-rock/config/filters.js @@ -294,6 +294,8 @@ function filterConfigByExplicitFilters(config, filters) { baseAuditIds = getAuditIdsInCategories(config.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)); } const auditIdsToKeep = new Set( diff --git a/lighthouse-core/fraggle-rock/gather/navigation-runner.js b/lighthouse-core/fraggle-rock/gather/navigation-runner.js index bdcefbc27a80..e0d8e245f8e7 100644 --- a/lighthouse-core/fraggle-rock/gather/navigation-runner.js +++ b/lighthouse-core/fraggle-rock/gather/navigation-runner.js @@ -327,6 +327,7 @@ async function navigationGather(requestor, options) { const artifacts = await Runner.gather( async () => { let {page} = options; + const normalizedRequestor = isCallback ? requestor : URL.normalizeUrl(requestor); // For navigation mode, we shouldn't connect to a browser in audit mode, // therefore we connect to the browser in the gatherFn callback. @@ -340,7 +341,7 @@ async function navigationGather(requestor, options) { const context = { driver, config, - requestor: isCallback ? requestor : URL.normalizeUrl(requestor), + requestor: normalizedRequestor, options: internalOptions, }; const {baseArtifacts} = await _setup(context); diff --git a/lighthouse-core/test/fraggle-rock/config/filters-test.js b/lighthouse-core/test/fraggle-rock/config/filters-test.js index 847bb57a3e7d..6fcc55515470 100644 --- a/lighthouse-core/test/fraggle-rock/config/filters-test.js +++ b/lighthouse-core/test/fraggle-rock/config/filters-test.js @@ -525,6 +525,34 @@ describe('Fraggle Rock Config Filtering', () => { }); }); + it('should keep all audits if there are no categories', () => { + config = { + ...config, + audits: [ + ...audits, + {implementation: NavigationOnlyAudit, options: {}}, + ], + categories: {}, + }; + + const filtered = filters.filterConfigByExplicitFilters(config, { + onlyAudits: null, + onlyCategories: null, + skipAudits: null, + }); + expect(filtered).toMatchObject({ + navigations: [{id: 'firstPass'}], + artifacts: [{id: 'Snapshot'}, {id: 'Timespan'}], + audits: [ + {implementation: SnapshotAudit}, + {implementation: TimespanAudit}, + {implementation: NavigationAudit}, + {implementation: ManualAudit}, + {implementation: NavigationOnlyAudit}, + ], + }); + }); + it('should preserve full-page-screenshot', async () => { config = (await initializeConfig(undefined, {gatherMode: 'navigation'})).config; diff --git a/lighthouse-core/test/index-test.js b/lighthouse-core/test/index-test.js index b09bcdf72144..779208003a32 100644 --- a/lighthouse-core/test/index-test.js +++ b/lighthouse-core/test/index-test.js @@ -37,6 +37,113 @@ describe('Module Tests', function() { assert.notEqual(lighthouseTraceCategories.length, 0); }); + describe('lighthouse', () => { + it('should throw an error when the first parameter is not defined', async () => { + const resultPromise = lighthouse(); + await expect(resultPromise).rejects.toThrow(); + }); + + it('should throw an error when the first parameter is an empty string', async () => { + const resultPromise = lighthouse(''); + await expect(resultPromise).rejects.toThrow(); + }); + + it('should throw an error when the first parameter is not a string', async () => { + const resultPromise = lighthouse({}); + await expect(resultPromise).rejects.toThrow(); + }); + + it('should throw an error when the second parameter is not an object', async () => { + const resultPromise = lighthouse('chrome://version', 'flags'); + await expect(resultPromise).rejects.toThrow(); + }); + + it('should throw an error when the config is invalid', async () => { + const resultPromise = lighthouse('chrome://version', {}, {}); + await expect(resultPromise).rejects.toThrow(); + }); + + it('should throw an error when the config contains incorrect audits', async () => { + const resultPromise = lighthouse('chrome://version', {}, { + passes: [{ + gatherers: [ + 'script-elements', + ], + }], + audits: [ + 'fluff', + ], + }); + await expect(resultPromise).rejects.toThrow(); + }); + + it('should throw an error when the url is invalid', async () => { + const resultPromise = lighthouse('i-am-not-valid', {}, {}); + await expect(resultPromise).rejects.toThrow('INVALID_URL'); + }); + + it('should throw an error when the url is invalid protocol (file:///)', async () => { + const resultPromise = lighthouse('file:///a/fake/index.html', {}, {}); + await expect(resultPromise).rejects.toThrow('INVALID_URL'); + }); + + it('should return formatted LHR when given no categories', async () => { + const exampleUrl = 'https://www.reddit.com/r/nba'; + const result = await lighthouse(exampleUrl, { + output: 'html', + }, { + settings: { + auditMode: TEST_DIR + '/fixtures/artifacts/perflog/', + formFactor: 'mobile', + }, + artifacts: [ + {id: 'MetaElements', gatherer: 'meta-elements'}, + ], + audits: [ + 'viewport', + ], + }); + + assert.ok(/ 3, 'timing entries not populated'); + }); + + it('should specify the channel as node by default', async () => { + const exampleUrl = 'https://www.reddit.com/r/nba'; + const result = await lighthouse(exampleUrl, {}, { + settings: { + auditMode: TEST_DIR + '/fixtures/artifacts/perflog/', + formFactor: 'mobile', + }, + audits: [], + }); + assert.equal(result.lhr.configSettings.channel, 'node'); + }); + + it('lets consumers pass in a custom channel', async () => { + const exampleUrl = 'https://www.reddit.com/r/nba'; + const result = await lighthouse(exampleUrl, {}, { + settings: { + auditMode: TEST_DIR + '/fixtures/artifacts/perflog/', + formFactor: 'mobile', + channel: 'custom', + }, + audits: [], + }); + assert.equal(result.lhr.configSettings.channel, 'custom'); + }); + }); + describe('legacyNavigation', () => { it('should throw an error when the first parameter is not defined', function() { return legacyNavigation()