diff --git a/lighthouse-cli/test/smokehouse/a11y/expectations.js b/lighthouse-cli/test/smokehouse/a11y/expectations.js index d8692e30ef3e..9c84cf5c3598 100644 --- a/lighthouse-cli/test/smokehouse/a11y/expectations.js +++ b/lighthouse-cli/test/smokehouse/a11y/expectations.js @@ -8,9 +8,10 @@ /* eslint-disable max-len */ /** + * @type {Array} * Expected Lighthouse audit values for byte efficiency tests */ -module.exports = [ +const expectations = [ { lhr: { requestedUrl: 'http://localhost:10200/a11y/a11y_tester.html', @@ -462,3 +463,5 @@ module.exports = [ }, }, ]; + +module.exports = expectations; diff --git a/lighthouse-cli/test/smokehouse/byte-config.js b/lighthouse-cli/test/smokehouse/byte-config.js index d3b2977e408e..e41d5136fe59 100644 --- a/lighthouse-cli/test/smokehouse/byte-config.js +++ b/lighthouse-cli/test/smokehouse/byte-config.js @@ -6,9 +6,10 @@ 'use strict'; /** + * @type {LH.Config.Json} * Config file for running byte efficiency smokehouse audits. */ -module.exports = { +const config = { extends: 'lighthouse:full', settings: { onlyAudits: [ @@ -27,3 +28,5 @@ module.exports = { throttlingMethod: 'devtools', }, }; + +module.exports = config; diff --git a/lighthouse-cli/test/smokehouse/byte-efficiency/expectations.js b/lighthouse-cli/test/smokehouse/byte-efficiency/expectations.js index 722090bc0c1f..990fd774f502 100644 --- a/lighthouse-cli/test/smokehouse/byte-efficiency/expectations.js +++ b/lighthouse-cli/test/smokehouse/byte-efficiency/expectations.js @@ -6,9 +6,10 @@ 'use strict'; /** + * @type {Array} * Expected Lighthouse audit values for byte efficiency tests */ -module.exports = [ +const expectations = [ { lhr: { requestedUrl: 'http://localhost:10200/byte-efficiency/tester.html', @@ -150,3 +151,5 @@ module.exports = [ }, }, ]; + +module.exports = expectations; diff --git a/lighthouse-cli/test/smokehouse/dobetterweb/dbw-expectations.js b/lighthouse-cli/test/smokehouse/dobetterweb/dbw-expectations.js index d04756bba5f8..8e8c16fff37a 100644 --- a/lighthouse-cli/test/smokehouse/dobetterweb/dbw-expectations.js +++ b/lighthouse-cli/test/smokehouse/dobetterweb/dbw-expectations.js @@ -6,9 +6,10 @@ 'use strict'; /** + * @type {Array} * Expected Lighthouse audit values for Do Better Web tests. */ -module.exports = [ +const expectations = [ { artifacts: { Stacks: [{ @@ -278,3 +279,5 @@ module.exports = [ }, }, ]; + +module.exports = expectations; diff --git a/lighthouse-cli/test/smokehouse/error-expectations.js b/lighthouse-cli/test/smokehouse/error-expectations.js index b462fd665e41..586f60a8586b 100644 --- a/lighthouse-cli/test/smokehouse/error-expectations.js +++ b/lighthouse-cli/test/smokehouse/error-expectations.js @@ -12,9 +12,10 @@ const NONEMPTY_ARRAY = { }; /** + * @type {Array} * Expected Lighthouse audit values for sites with various errors. */ -module.exports = [ +const expectations = [ { lhr: { requestedUrl: 'http://localhost:10200/infinite-loop.html', @@ -84,3 +85,5 @@ module.exports = [ }, }, ]; + +module.exports = expectations; diff --git a/lighthouse-cli/test/smokehouse/perf/expectations.js b/lighthouse-cli/test/smokehouse/perf/expectations.js index 4ea41b4d5432..0ca81582ec81 100644 --- a/lighthouse-cli/test/smokehouse/perf/expectations.js +++ b/lighthouse-cli/test/smokehouse/perf/expectations.js @@ -6,6 +6,7 @@ 'use strict'; /** + * @type {Array} * Expected Lighthouse audit values for perf tests. */ module.exports = [ diff --git a/lighthouse-cli/test/smokehouse/perf/lantern-expectations.js b/lighthouse-cli/test/smokehouse/perf/lantern-expectations.js index 64b1ebc9fca2..e6ce9e2d6a9d 100644 --- a/lighthouse-cli/test/smokehouse/perf/lantern-expectations.js +++ b/lighthouse-cli/test/smokehouse/perf/lantern-expectations.js @@ -6,6 +6,7 @@ 'use strict'; /** + * @type {Array} * Expected Lighthouse audit values for lantern smoketests */ module.exports = [ diff --git a/lighthouse-cli/test/smokehouse/redirects/expectations.js b/lighthouse-cli/test/smokehouse/redirects/expectations.js index 6abd8c746fb8..06b66ac63746 100644 --- a/lighthouse-cli/test/smokehouse/redirects/expectations.js +++ b/lighthouse-cli/test/smokehouse/redirects/expectations.js @@ -5,12 +5,13 @@ */ 'use strict'; +const cacheBuster = Number(new Date()); + /** + * @type {Array} * Expected Lighthouse audit values for redirects tests */ -const cacheBuster = Number(new Date()); - -module.exports = [ +const expectations = [ { lhr: { requestedUrl: `http://localhost:10200/online-only.html?delay=500&redirect=%2Foffline-only.html%3Fcb=${cacheBuster}%26delay=500%26redirect%3D%2Fredirects-final.html`, @@ -46,3 +47,5 @@ module.exports = [ }, }, ]; + +module.exports = expectations; diff --git a/lighthouse-cli/test/smokehouse/run-smoke.js b/lighthouse-cli/test/smokehouse/run-smoke.js index f82e27d6489a..874d2fd5da5b 100644 --- a/lighthouse-cli/test/smokehouse/run-smoke.js +++ b/lighthouse-cli/test/smokehouse/run-smoke.js @@ -14,7 +14,7 @@ const log = require('lighthouse-logger'); /** @param {string} str */ const purpleify = str => `${log.purple}${str}${log.reset}`; -const SMOKETESTS = require('./smoke-test-dfns.js').SMOKE_TEST_DFNS; +const smokeTests = require('./smoke-test-dfns.js'); /** * Display smokehouse output from child process @@ -33,20 +33,19 @@ function displaySmokehouseOutput(result) { } /** - * Run smokehouse in child processes for selected smoketests + * Run smokehouse in child processes for the selected smoke tests * Display output from each as soon as they finish, but resolve function when ALL are complete - * @param {Array} smokes + * @param {Array} smokeTests * @return {Promise>} */ -async function runSmokehouse(smokes) { +async function runSmokehouse(smokeTests) { const cmdPromises = []; - for (const {id, expectations, config} of smokes) { + for (const {id} of smokeTests) { console.log(`${purpleify(id)} smoketest starting…`); console.time(`smoketest-${id}`); const cmd = [ 'node lighthouse-cli/test/smokehouse/smokehouse.js', - `--config-path=${config}`, - `--expectations-path=${expectations}`, + `--smoke-id=${id}`, ].join(' '); // The promise ensures we output immediately, even if the process errors @@ -72,18 +71,18 @@ async function runSmokehouse(smokes) { */ function getSmoketestBatches(argv) { let smokes = []; - const usage = ` ${log.dim}yarn smoke ${SMOKETESTS.map(t => t.id).join(' ')}${log.reset}\n`; + const usage = ` ${log.dim}yarn smoke ${smokeTests.map(t => t.id).join(' ')}${log.reset}\n`; if (argv.length === 0) { - smokes = SMOKETESTS; + smokes = smokeTests; console.log('Running ALL smoketests. Equivalent to:'); console.log(usage); } else { - smokes = SMOKETESTS.filter(test => argv.includes(test.id)); + smokes = smokeTests.filter(test => argv.includes(test.id)); console.log(`Running ONLY smoketests for: ${smokes.map(t => t.id).join(' ')}\n`); } - const unmatchedIds = argv.filter(requestedId => !SMOKETESTS.map(t => t.id).includes(requestedId)); + const unmatchedIds = argv.filter(requestedId => !smokeTests.map(t => t.id).includes(requestedId)); if (unmatchedIds.length) { console.log(log.redify(`Smoketests not found for: ${unmatchedIds.join(' ')}`)); console.log(usage); diff --git a/lighthouse-cli/test/smokehouse/seo/expectations.js b/lighthouse-cli/test/smokehouse/seo/expectations.js index 18c66eef53ea..1ecc918b4b53 100644 --- a/lighthouse-cli/test/smokehouse/seo/expectations.js +++ b/lighthouse-cli/test/smokehouse/seo/expectations.js @@ -4,8 +4,8 @@ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ 'use strict'; + const BASE_URL = 'http://localhost:10200/seo/'; -const URLSearchParams = require('url').URLSearchParams; /** * @param {[string, string][]} headers @@ -94,9 +94,10 @@ const passHeaders = headersParam([[ ]]); /** + * @type {Array} * Expected Lighthouse audit values for seo tests */ -module.exports = [ +const expectations = [ { lhr: { requestedUrl: BASE_URL + 'seo-tester.html?' + passHeaders, @@ -392,3 +393,5 @@ module.exports = [ }, }, ]; + +module.exports = expectations; diff --git a/lighthouse-cli/test/smokehouse/smoke-test-dfns.js b/lighthouse-cli/test/smokehouse/smoke-test-dfns.js index c12b14fcdffe..f5db176d9671 100644 --- a/lighthouse-cli/test/smokehouse/smoke-test-dfns.js +++ b/lighthouse-cli/test/smokehouse/smoke-test-dfns.js @@ -5,129 +5,77 @@ */ 'use strict'; -const path = require('path'); -const smokehouseDir = 'lighthouse-cli/test/smokehouse/'; - /** @type {Array} */ -const SMOKE_TEST_DFNS = [{ +const smokeTests = [{ id: 'a11y', - config: smokehouseDir + 'a11y/a11y-config.js', - expectations: 'a11y/expectations.js', + expectations: require('./a11y/expectations.js'), + config: require('./a11y/a11y-config.js'), batch: 'parallel-first', }, { id: 'errors', - expectations: smokehouseDir + 'error-expectations.js', - config: smokehouseDir + 'error-config.js', + expectations: require('./error-expectations.js'), + config: require('./error-config.js'), batch: 'errors', }, { id: 'oopif', - expectations: smokehouseDir + 'oopif-expectations.js', - config: smokehouseDir + 'oopif-config.js', + expectations: require('./oopif-expectations.js'), + config: require('./oopif-config.js'), batch: 'parallel-first', }, { id: 'pwa', - expectations: smokehouseDir + 'pwa-expectations.js', - config: smokehouseDir + 'pwa-config.js', + expectations: require('./pwa-expectations.js'), + config: require('./pwa-config.js'), batch: 'parallel-second', }, { id: 'pwa2', - expectations: smokehouseDir + 'pwa2-expectations.js', - config: smokehouseDir + 'pwa-config.js', + expectations: require('./pwa2-expectations.js'), + config: require('./pwa-config.js'), batch: 'parallel-second', }, { id: 'pwa3', - expectations: smokehouseDir + 'pwa3-expectations.js', - config: smokehouseDir + 'pwa-config.js', + expectations: require('./pwa3-expectations.js'), + config: require('./pwa-config.js'), batch: 'parallel-first', }, { id: 'dbw', - expectations: 'dobetterweb/dbw-expectations.js', - config: smokehouseDir + 'dbw-config.js', + expectations: require('./dobetterweb/dbw-expectations.js'), + config: require('./dbw-config.js'), batch: 'parallel-second', }, { id: 'redirects', - expectations: 'redirects/expectations.js', - config: smokehouseDir + 'redirects-config.js', + expectations: require('./redirects/expectations.js'), + config: require('./redirects-config.js'), batch: 'parallel-first', }, { id: 'seo', - expectations: 'seo/expectations.js', - config: smokehouseDir + 'seo-config.js', + expectations: require('./seo/expectations.js'), + config: require('./seo-config.js'), batch: 'parallel-first', }, { id: 'offline', - expectations: 'offline-local/offline-expectations.js', - config: smokehouseDir + 'offline-config.js', + expectations: require('./offline-local/offline-expectations.js'), + config: require('./offline-config.js'), batch: 'offline', }, { id: 'byte', - expectations: 'byte-efficiency/expectations.js', - config: smokehouseDir + 'byte-config.js', + expectations: require('./byte-efficiency/expectations.js'), + config: require('./byte-config.js'), batch: 'perf-opportunity', }, { id: 'perf', - expectations: 'perf/expectations.js', - config: 'perf/perf-config.js', + expectations: require('./perf/expectations.js'), + config: require('./perf/perf-config.js'), batch: 'perf-metric', }, { id: 'lantern', - expectations: 'perf/lantern-expectations.js', - config: smokehouseDir + 'lantern-config.js', + expectations: require('./perf/lantern-expectations.js'), + config: require('./lantern-config.js'), batch: 'parallel-first', }, { id: 'metrics', - expectations: 'tricky-metrics/expectations.js', - config: 'lighthouse-core/config/perf-config.js', + expectations: require('./tricky-metrics/expectations.js'), + config: require('../../../lighthouse-core/config/perf-config.js'), batch: 'parallel-second', }]; -/** - * Attempt to resolve a path relative to the smokehouse folder. - * If this fails, attempts to locate the path - * relative to the project root. - * @param {string} payloadPath - * @return {string} - */ -function resolveLocalOrProjectRoot(payloadPath) { - let resolved; - try { - resolved = require.resolve(__dirname + '/' + payloadPath); - } catch (e) { - const cwdPath = path.resolve(__dirname + '/../../../', payloadPath); - resolved = require.resolve(cwdPath); - } - - return resolved; -} - -/** - * @param {string} configPath - * @return {LH.Config.Json} - */ -function loadConfig(configPath) { - return require(configPath); -} - -/** - * @param {string} expectationsPath - * @return {Smokehouse.ExpectedRunnerResult[]} - */ -function loadExpectations(expectationsPath) { - return require(expectationsPath); -} - -function getSmokeTests() { - return SMOKE_TEST_DFNS.map(smokeTestDfn => { - return { - id: smokeTestDfn.id, - config: loadConfig(resolveLocalOrProjectRoot(smokeTestDfn.config)), - expectations: loadExpectations(resolveLocalOrProjectRoot(smokeTestDfn.expectations)), - batch: smokeTestDfn.batch, - }; - }); -} - -module.exports = { - SMOKE_TEST_DFNS, - getSmokeTests, -}; +module.exports = smokeTests; diff --git a/lighthouse-cli/test/smokehouse/smokehouse.js b/lighthouse-cli/test/smokehouse/smokehouse.js index c39b4f481997..f133da82822e 100755 --- a/lighthouse-cli/test/smokehouse/smokehouse.js +++ b/lighthouse-cli/test/smokehouse/smokehouse.js @@ -9,7 +9,6 @@ /* eslint-disable no-console */ const fs = require('fs'); -const path = require('path'); const spawnSync = require('child_process').spawnSync; const yargs = require('yargs'); const log = require('lighthouse-logger'); @@ -21,24 +20,6 @@ const assetSaver = require('../../../lighthouse-core/lib/asset-saver.js'); const PROTOCOL_TIMEOUT_EXIT_CODE = 67; const RETRIES = 3; -/** - * Attempt to resolve a path locally. If this fails, attempts to locate the path - * relative to the current working directory. - * @param {string} payloadPath - * @return {string} - */ -function resolveLocalOrCwd(payloadPath) { - let resolved; - try { - resolved = require.resolve('./' + payloadPath); - } catch (e) { - const cwdPath = path.resolve(process.cwd(), payloadPath); - resolved = require.resolve(cwdPath); - } - - return resolved; -} - /** * Launch Chrome and do a full Lighthouse run. * @param {string} url @@ -129,23 +110,28 @@ function runLighthouse(url, configPath, isDebug) { const cli = yargs .help('help') .describe({ - 'config-path': 'The path to the config JSON file', - 'expectations-path': 'The path to the expected audit results file', + 'smoke-id': 'The id of the smoke test to run', 'debug': 'Save the artifacts along with the output', }) - .require('config-path', true) - .require('expectations-path', true) + .require('smoke-id', true) .argv; -const configPath = resolveLocalOrCwd(cli['config-path']); -/** @type {Smokehouse.ExpectedRunnerResult[]} */ -const expectations = require(resolveLocalOrCwd(cli['expectations-path'])); +const smokeId = cli['smoke-id']; +const smokeTest = require('./smoke-test-dfns.js').find(smoke => smoke.id === smokeId); + +if (!smokeTest) { + process.exit(1); + throw new Error(`could not find smoke ${smokeId}`); +} + +const configPath = `./.tmp/smoke-config-${smokeTest.id}.json`; +fs.writeFileSync(configPath, JSON.stringify(smokeTest.config)); // Loop sequentially over expectations, comparing against Lighthouse run, and // reporting result. let passingCount = 0; let failingCount = 0; -expectations.forEach(expected => { +smokeTest.expectations.forEach(expected => { console.log(`Doing a run of '${expected.lhr.requestedUrl}'...`); const results = runLighthouse(expected.lhr.requestedUrl, configPath, cli.debug); diff --git a/lighthouse-cli/test/smokehouse/tricky-metrics/expectations.js b/lighthouse-cli/test/smokehouse/tricky-metrics/expectations.js index 1aafb8e72c71..730f0cd97c95 100644 --- a/lighthouse-cli/test/smokehouse/tricky-metrics/expectations.js +++ b/lighthouse-cli/test/smokehouse/tricky-metrics/expectations.js @@ -6,6 +6,7 @@ 'use strict'; /** + * @type {Array} * Expected Lighthouse audit values for tricky metrics tests */ module.exports = [ diff --git a/types/smokehouse.d.ts b/types/smokehouse.d.ts index aff8553841cd..a512b481d727 100644 --- a/types/smokehouse.d.ts +++ b/types/smokehouse.d.ts @@ -19,17 +19,26 @@ diff?: Difference | null; } - export type ExpectedLHR = Pick + interface ExpectedLHR { + audits: Record; + requestedUrl: string; + finalUrl: string; + runWarnings?: Array; + runtimeError?: { + code?: any; + message?: any; + }; + } export type ExpectedRunnerResult = { lhr: ExpectedLHR, - artifacts?: Partial + artifacts?: Partial> } export interface TestDfn { id: string; - expectations: string; - config: string; + expectations: ExpectedRunnerResult[]; + config: LH.Config.Json; batch: string; } }