lighthouse 8.4.0 → 8.5.0-dev.20210921
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +79 -0
- package/flow-report/assets/styles.css +85 -61
- package/flow-report/src/app.tsx +6 -2
- package/flow-report/src/common.tsx +0 -41
- package/flow-report/src/icons.tsx +11 -0
- package/flow-report/src/summary/summary.tsx +32 -25
- package/flow-report/src/topbar.tsx +60 -0
- package/flow-report/src/util.ts +0 -1
- package/flow-report/src/wrappers/{gauge.tsx → category-score.tsx} +11 -5
- package/flow-report/test/summary/summary-test.tsx +3 -3
- package/flow-report/tsconfig.json +6 -22
- package/{lighthouse-core/gather/gatherers/gather-context.js → lighthouse-cli/.eslintrc.cjs} +20 -18
- package/lighthouse-cli/bin.js +31 -21
- package/lighthouse-cli/cli-flags.js +12 -7
- package/lighthouse-cli/commands/commands.js +2 -7
- package/lighthouse-cli/commands/list-audits.js +2 -2
- package/lighthouse-cli/commands/list-trace-categories.js +2 -2
- package/lighthouse-cli/index.js +3 -1
- package/lighthouse-cli/package.json +4 -0
- package/lighthouse-cli/printer.js +4 -3
- package/lighthouse-cli/run.js +14 -15
- package/lighthouse-cli/sentry-prompt.js +5 -6
- package/lighthouse-cli/test/smokehouse/frontends/back-compat-util.js +1 -1
- package/lighthouse-cli/test/smokehouse/frontends/lib.js +5 -4
- package/lighthouse-cli/test/smokehouse/frontends/node.js +1 -1
- package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +93 -14
- package/lighthouse-cli/test/smokehouse/lib/child-process-error.js +1 -1
- package/lighthouse-cli/test/smokehouse/lib/concurrent-mapper.js +1 -1
- package/lighthouse-cli/test/smokehouse/lib/local-console.js +1 -1
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/bundle.js +20 -16
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/cli.js +15 -12
- package/lighthouse-cli/test/smokehouse/report-assert.js +23 -13
- package/lighthouse-cli/test/smokehouse/smokehouse.js +32 -11
- package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +0 -2
- package/lighthouse-core/audits/byte-efficiency/uses-responsive-images-snapshot.js +6 -1
- package/lighthouse-core/audits/dobetterweb/js-libraries.js +5 -0
- package/lighthouse-core/audits/dobetterweb/uses-http2.js +1 -0
- package/lighthouse-core/audits/lcp-lazy-loaded.js +1 -0
- package/lighthouse-core/audits/oopif-iframe-test-audit.js +30 -0
- package/lighthouse-core/computed/metrics/metric.js +2 -1
- package/lighthouse-core/config/config-helpers.js +47 -3
- package/lighthouse-core/config/config.js +3 -46
- package/lighthouse-core/config/default-config.js +0 -1
- package/lighthouse-core/fraggle-rock/config/config.js +22 -4
- package/lighthouse-core/fraggle-rock/config/default-config.js +0 -9
- package/lighthouse-core/fraggle-rock/config/filters.js +3 -0
- package/lighthouse-core/fraggle-rock/config/validation.js +19 -1
- package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +8 -3
- package/lighthouse-core/fraggle-rock/gather/driver.js +10 -0
- package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +40 -19
- package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +3 -0
- package/lighthouse-core/fraggle-rock/gather/session.js +44 -1
- package/lighthouse-core/fraggle-rock/gather/snapshot-runner.js +4 -1
- package/lighthouse-core/fraggle-rock/gather/timespan-runner.js +5 -1
- package/lighthouse-core/gather/devtools-log.js +9 -3
- package/lighthouse-core/gather/driver/network-monitor.js +57 -13
- package/lighthouse-core/gather/driver/prepare.js +43 -17
- package/lighthouse-core/gather/driver/target-manager.js +125 -0
- package/lighthouse-core/gather/driver.js +20 -0
- package/lighthouse-core/gather/fetcher.js +2 -2
- package/lighthouse-core/gather/gather-runner.js +1 -1
- package/lighthouse-core/gather/gatherers/css-usage.js +0 -2
- package/lighthouse-core/gather/gatherers/devtools-log.js +11 -9
- package/lighthouse-core/gather/gatherers/js-usage.js +0 -1
- package/lighthouse-core/gather/gatherers/script-elements.js +4 -5
- package/lighthouse-core/gather/gatherers/seo/robots-txt.js +3 -3
- package/lighthouse-core/gather/gatherers/trace.js +4 -5
- package/lighthouse-core/index.js +4 -0
- package/lighthouse-core/lib/emulation.js +0 -1
- package/lighthouse-core/lib/i18n/locales/en-US.json +6 -0
- package/lighthouse-core/lib/i18n/locales/en-XL.json +6 -0
- package/lighthouse-core/lib/network-recorder.js +8 -0
- package/lighthouse-core/lib/proto-preprocessor.js +5 -10
- package/lighthouse-core/runner.js +1 -3
- package/package.json +12 -9
- package/readme.md +2 -0
- package/report/assets/styles.css +120 -12
- package/report/assets/templates.html +13 -0
- package/report/clients/psi.js +5 -1
- package/report/generator/tsconfig.json +5 -16
- package/report/renderer/category-renderer.js +58 -5
- package/report/renderer/components.js +25 -5
- package/report/renderer/performance-category-renderer.js +5 -5
- package/report/renderer/pwa-category-renderer.js +10 -0
- package/report/renderer/report-renderer.js +12 -3
- package/report/renderer/report-ui-features.js +1 -4
- package/report/test/renderer/category-renderer-test.js +19 -0
- package/report/tsconfig.json +6 -21
- package/report/types/report-result.d.ts +1 -1
- package/root.js +3 -1
- package/third-party/snyk/snapshot.json +2 -2
- package/tsconfig-all.json +15 -0
- package/tsconfig-base.json +24 -0
- package/tsconfig.json +8 -18
- package/types/artifacts.d.ts +7 -7
- package/types/config.d.ts +1 -1
- package/types/gatherer.d.ts +7 -1
- package/types/lhr/flow.d.ts +0 -1
- package/types/lhr/lhr.d.ts +5 -1
- package/types/lhr/tsconfig.json +4 -14
- package/types/protocol.d.ts +2 -0
- package/types/smokehouse.d.ts +2 -1
- package/dist/report/flow.js +0 -149
- package/dist/report/standalone.js +0 -228
- package/flow-report/test/common-test.tsx +0 -131
- package/lighthouse-core/gather/gatherers/host-form-factor.js +0 -31
- package/lighthouse-core/gather/gatherers/host-user-agent.js +0 -29
|
@@ -1,39 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
+
"extends": "../tsconfig-base.json",
|
|
2
3
|
"compilerOptions": {
|
|
3
|
-
"composite": true,
|
|
4
4
|
"outDir": "../.tmp/tsbuildinfo/flow-report",
|
|
5
|
-
"emitDeclarationOnly": false,
|
|
6
|
-
"declarationMap": true,
|
|
7
5
|
|
|
8
6
|
// Limit to base JS and DOM defs.
|
|
9
7
|
"lib": ["es2020", "dom", "dom.iterable"],
|
|
10
|
-
// Selectively include types from node_modules
|
|
8
|
+
// Selectively include types from node_modules/.
|
|
11
9
|
"types": ["node", "jest"],
|
|
12
|
-
"target": "es2020",
|
|
13
|
-
"module": "es2020",
|
|
14
|
-
"moduleResolution": "node",
|
|
15
|
-
"esModuleInterop": true,
|
|
16
|
-
|
|
17
|
-
"allowJs": true,
|
|
18
|
-
"checkJs": true,
|
|
19
|
-
"strict": true,
|
|
20
|
-
// TODO: remove the next line to be fully `strict`.
|
|
21
|
-
"useUnknownInCatchVariables": false,
|
|
22
|
-
|
|
23
|
-
// "listFiles": true,
|
|
24
|
-
// "noErrorTruncation": true,
|
|
25
|
-
"extendedDiagnostics": true,
|
|
26
10
|
|
|
27
11
|
"jsx": "react-jsx",
|
|
28
12
|
"jsxImportSource": "preact",
|
|
29
13
|
},
|
|
14
|
+
"references": [
|
|
15
|
+
{"path": "../types/lhr/"},
|
|
16
|
+
{"path": "../report"},
|
|
17
|
+
],
|
|
30
18
|
"include": [
|
|
31
19
|
"**/*.ts",
|
|
32
20
|
"**/*.tsx",
|
|
33
21
|
"./types",
|
|
34
22
|
],
|
|
35
|
-
"references": [
|
|
36
|
-
{"path": "../types/lhr/"},
|
|
37
|
-
{"path": "../report"},
|
|
38
|
-
],
|
|
39
23
|
}
|
|
@@ -5,21 +5,23 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
8
|
+
module.exports = {
|
|
9
|
+
env: {
|
|
10
|
+
browser: true,
|
|
11
|
+
},
|
|
12
|
+
rules: {
|
|
13
|
+
// TODO(esmodules): move to root eslint when all code is ESM
|
|
14
|
+
// or when this is resolved: https://github.com/import-js/eslint-plugin-import/issues/2214
|
|
15
|
+
'import/order': [2, {
|
|
16
|
+
'groups': [
|
|
17
|
+
'builtin',
|
|
18
|
+
'external',
|
|
19
|
+
['sibling', 'parent'],
|
|
20
|
+
'index',
|
|
21
|
+
'object',
|
|
22
|
+
'type',
|
|
23
|
+
],
|
|
24
|
+
'newlines-between': 'always',
|
|
25
|
+
}],
|
|
26
|
+
},
|
|
27
|
+
};
|
package/lighthouse-cli/bin.js
CHANGED
|
@@ -18,19 +18,23 @@
|
|
|
18
18
|
* cli-flags lh-core/index
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
21
|
+
import fs from 'fs';
|
|
22
|
+
import path from 'path';
|
|
23
|
+
import url from 'url';
|
|
24
|
+
|
|
25
|
+
import log from 'lighthouse-logger';
|
|
26
|
+
import updateNotifier from 'update-notifier';
|
|
27
|
+
|
|
28
|
+
import * as commands from './commands/commands.js';
|
|
29
|
+
import * as Printer from './printer.js';
|
|
30
|
+
import {getFlags} from './cli-flags.js';
|
|
31
|
+
import {runLighthouse} from './run.js';
|
|
32
|
+
import lighthouse from '../lighthouse-core/index.js';
|
|
33
|
+
import * as Sentry from '../lighthouse-core/lib/sentry.js';
|
|
34
|
+
import {askPermission} from './sentry-prompt.js';
|
|
35
|
+
import {LH_ROOT} from '../root.js';
|
|
36
|
+
|
|
37
|
+
const pkg = JSON.parse(fs.readFileSync(LH_ROOT + '/package.json', 'utf-8'));
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
40
|
* @return {boolean}
|
|
@@ -58,16 +62,22 @@ async function begin() {
|
|
|
58
62
|
commands.listTraceCategories();
|
|
59
63
|
}
|
|
60
64
|
|
|
61
|
-
const
|
|
65
|
+
const urlUnderTest = cliFlags._[0];
|
|
62
66
|
|
|
63
67
|
/** @type {LH.Config.Json|undefined} */
|
|
64
68
|
let configJson;
|
|
65
69
|
if (cliFlags.configPath) {
|
|
66
70
|
// Resolve the config file path relative to where cli was called.
|
|
67
71
|
cliFlags.configPath = path.resolve(process.cwd(), cliFlags.configPath);
|
|
68
|
-
|
|
72
|
+
|
|
73
|
+
if (cliFlags.configPath.endsWith('.json')) {
|
|
74
|
+
configJson = JSON.parse(fs.readFileSync(cliFlags.configPath, 'utf-8'));
|
|
75
|
+
} else {
|
|
76
|
+
const configModuleUrl = url.pathToFileURL(cliFlags.configPath).href;
|
|
77
|
+
configJson = (await import(configModuleUrl)).default;
|
|
78
|
+
}
|
|
69
79
|
} else if (cliFlags.preset) {
|
|
70
|
-
configJson =
|
|
80
|
+
configJson = (await import(`../lighthouse-core/config/${cliFlags.preset}-config.js`)).default;
|
|
71
81
|
}
|
|
72
82
|
|
|
73
83
|
if (cliFlags.budgetPath) {
|
|
@@ -88,7 +98,7 @@ async function begin() {
|
|
|
88
98
|
|
|
89
99
|
if (
|
|
90
100
|
cliFlags.output.length === 1 &&
|
|
91
|
-
cliFlags.output[0] ===
|
|
101
|
+
cliFlags.output[0] === Printer.OutputMode.json &&
|
|
92
102
|
!cliFlags.outputPath
|
|
93
103
|
) {
|
|
94
104
|
cliFlags.outputPath = 'stdout';
|
|
@@ -106,7 +116,7 @@ async function begin() {
|
|
|
106
116
|
}
|
|
107
117
|
|
|
108
118
|
if (cliFlags.printConfig) {
|
|
109
|
-
const config = generateConfig(configJson, cliFlags);
|
|
119
|
+
const config = lighthouse.generateConfig(configJson, cliFlags);
|
|
110
120
|
process.stdout.write(config.getPrintString());
|
|
111
121
|
return;
|
|
112
122
|
}
|
|
@@ -119,7 +129,7 @@ async function begin() {
|
|
|
119
129
|
}
|
|
120
130
|
if (cliFlags.enableErrorReporting) {
|
|
121
131
|
Sentry.init({
|
|
122
|
-
url,
|
|
132
|
+
url: urlUnderTest,
|
|
123
133
|
flags: cliFlags,
|
|
124
134
|
environmentData: {
|
|
125
135
|
name: 'redacted', // prevent sentry from using hostname
|
|
@@ -132,9 +142,9 @@ async function begin() {
|
|
|
132
142
|
});
|
|
133
143
|
}
|
|
134
144
|
|
|
135
|
-
return runLighthouse(
|
|
145
|
+
return runLighthouse(urlUnderTest, cliFlags, configJson);
|
|
136
146
|
}
|
|
137
147
|
|
|
138
|
-
|
|
148
|
+
export {
|
|
139
149
|
begin,
|
|
140
150
|
};
|
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
/* eslint-disable max-len */
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
|
|
12
|
+
import yargs from 'yargs';
|
|
13
|
+
import * as yargsHelpers from 'yargs/helpers';
|
|
14
|
+
|
|
15
|
+
import {isObjectOfUnknownValues} from '../lighthouse-core/lib/type-verifiers.js';
|
|
13
16
|
|
|
14
17
|
/**
|
|
15
18
|
* @param {string=} manualArgv
|
|
@@ -17,8 +20,10 @@ const {isObjectOfUnknownValues} = require('../lighthouse-core/lib/type-verifiers
|
|
|
17
20
|
* @return {LH.CliFlags}
|
|
18
21
|
*/
|
|
19
22
|
function getFlags(manualArgv, options = {}) {
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
const y = manualArgv ?
|
|
24
|
+
// @ts-expect-error - undocumented, but yargs() supports parsing a single `string`.
|
|
25
|
+
yargs(manualArgv) :
|
|
26
|
+
yargs(yargsHelpers.hideBin(process.argv));
|
|
22
27
|
|
|
23
28
|
let parser = y.help('help')
|
|
24
29
|
.showHelpOnFail(false, 'Specify --help for available options')
|
|
@@ -318,7 +323,7 @@ function getFlags(manualArgv, options = {}) {
|
|
|
318
323
|
throw new Error('Please provide a url');
|
|
319
324
|
})
|
|
320
325
|
.epilogue('For more information on Lighthouse, see https://developers.google.com/web/tools/lighthouse/.')
|
|
321
|
-
.wrap(
|
|
326
|
+
.wrap(y.terminalWidth());
|
|
322
327
|
|
|
323
328
|
if (options.noExitOnFailure) {
|
|
324
329
|
// Silence console.error() logging and don't process.exit().
|
|
@@ -499,6 +504,6 @@ function coerceScreenEmulation(value) {
|
|
|
499
504
|
return screenEmulationSettings;
|
|
500
505
|
}
|
|
501
506
|
|
|
502
|
-
|
|
507
|
+
export {
|
|
503
508
|
getFlags,
|
|
504
509
|
};
|
|
@@ -5,10 +5,5 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
module.exports = {
|
|
12
|
-
listAudits,
|
|
13
|
-
listTraceCategories,
|
|
14
|
-
};
|
|
8
|
+
export {listAudits} from './list-audits.js';
|
|
9
|
+
export {listTraceCategories} from './list-trace-categories.js';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
import lighthouse from '../../lighthouse-core/index.js';
|
|
9
9
|
|
|
10
10
|
function listAudits() {
|
|
11
11
|
const audits = lighthouse.getAuditList().map((i) => i.replace(/\.js$/, ''));
|
|
@@ -13,4 +13,4 @@ function listAudits() {
|
|
|
13
13
|
process.exit(0);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
export {listAudits};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
import lighthouse from '../../lighthouse-core/index.js';
|
|
9
9
|
|
|
10
10
|
function listTraceCategories() {
|
|
11
11
|
const traceCategories = lighthouse.traceCategories;
|
|
@@ -13,4 +13,4 @@ function listTraceCategories() {
|
|
|
13
13
|
process.exit(0);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
export {listTraceCategories};
|
package/lighthouse-cli/index.js
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
|
|
10
|
+
import log from 'lighthouse-logger';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* An enumeration of acceptable output modes:
|
|
@@ -91,7 +92,7 @@ function getValidOutputOptions() {
|
|
|
91
92
|
return Object.keys(OutputMode);
|
|
92
93
|
}
|
|
93
94
|
|
|
94
|
-
|
|
95
|
+
export {
|
|
95
96
|
checkOutputPath,
|
|
96
97
|
write,
|
|
97
98
|
OutputMode,
|
package/lighthouse-cli/run.js
CHANGED
|
@@ -7,20 +7,19 @@
|
|
|
7
7
|
|
|
8
8
|
/* eslint-disable no-console */
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
const psList = require('ps-list');
|
|
10
|
+
import path from 'path';
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
import psList from 'ps-list';
|
|
13
|
+
import * as ChromeLauncher from 'chrome-launcher';
|
|
14
|
+
import yargsParser from 'yargs-parser';
|
|
15
|
+
import log from 'lighthouse-logger';
|
|
16
|
+
import open from 'open';
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const URL = require('../lighthouse-core/lib/url-shim.js');
|
|
22
|
-
|
|
23
|
-
const open = require('open');
|
|
18
|
+
import * as Printer from './printer.js';
|
|
19
|
+
import lighthouse from '../lighthouse-core/index.js';
|
|
20
|
+
import {getFilenamePrefix} from '../report/generator/file-namer.js';
|
|
21
|
+
import * as assetSaver from '../lighthouse-core/lib/asset-saver.js';
|
|
22
|
+
import URL from '../lighthouse-core/lib/url-shim.js';
|
|
24
23
|
|
|
25
24
|
/** @typedef {Error & {code: string, friendlyMessage?: string}} ExitError */
|
|
26
25
|
|
|
@@ -203,8 +202,8 @@ async function potentiallyKillChrome(launchedChrome) {
|
|
|
203
202
|
* @return {Promise<LH.RunnerResult|undefined>}
|
|
204
203
|
*/
|
|
205
204
|
async function runLighthouseWithFraggleRock(url, flags, config, launchedChrome) {
|
|
206
|
-
const fraggleRock =
|
|
207
|
-
const puppeteer =
|
|
205
|
+
const fraggleRock = (await import('../lighthouse-core/fraggle-rock/api.js')).default;
|
|
206
|
+
const puppeteer = (await import('puppeteer')).default;
|
|
208
207
|
const browser = await puppeteer.connect({browserURL: `http://localhost:${launchedChrome.port}`});
|
|
209
208
|
const page = await browser.newPage();
|
|
210
209
|
flags.channel = 'fraggle-rock-cli';
|
|
@@ -272,7 +271,7 @@ async function runLighthouse(url, flags, config) {
|
|
|
272
271
|
}
|
|
273
272
|
}
|
|
274
273
|
|
|
275
|
-
|
|
274
|
+
export {
|
|
276
275
|
parseChromeFlags,
|
|
277
276
|
saveResults,
|
|
278
277
|
runLighthouse,
|
|
@@ -5,10 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const log = require('lighthouse-logger');
|
|
8
|
+
import Configstore from 'configstore';
|
|
9
|
+
import Confirm from 'enquirer';
|
|
10
|
+
import log from 'lighthouse-logger';
|
|
12
11
|
|
|
13
12
|
const MAXIMUM_WAIT_TIME = 20 * 1000;
|
|
14
13
|
|
|
@@ -29,7 +28,7 @@ function prompt() {
|
|
|
29
28
|
/** @type {NodeJS.Timer|undefined} */
|
|
30
29
|
let timeout;
|
|
31
30
|
|
|
32
|
-
const prompt = new Confirm({
|
|
31
|
+
const prompt = new Confirm.Confirm({
|
|
33
32
|
name: 'isErrorReportingEnabled',
|
|
34
33
|
initial: false,
|
|
35
34
|
message: MESSAGE,
|
|
@@ -75,6 +74,6 @@ function askPermission() {
|
|
|
75
74
|
}).catch(_ => false);
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
|
|
77
|
+
export {
|
|
79
78
|
askPermission,
|
|
80
79
|
};
|
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
|
|
14
14
|
/* eslint-disable no-console */
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
import cloneDeep from 'lodash.clonedeep';
|
|
17
|
+
|
|
18
|
+
import smokeTests from '../test-definitions/core-tests.js';
|
|
19
|
+
import {runSmokehouse} from '../smokehouse.js';
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* @param {Smokehouse.SmokehouseLibOptions} options
|
|
@@ -43,4 +44,4 @@ async function smokehouse(options) {
|
|
|
43
44
|
return runSmokehouse(modifiedTests, smokehouseOptions);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
export {smokehouse};
|
|
@@ -13,14 +13,22 @@
|
|
|
13
13
|
|
|
14
14
|
/* eslint-disable no-console */
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const {runSmokehouse} = require('../smokehouse.js');
|
|
21
|
-
const {updateTestDefnFormat} = require('./back-compat-util.js');
|
|
16
|
+
import {strict as assert} from 'assert';
|
|
17
|
+
import path from 'path';
|
|
18
|
+
import fs from 'fs';
|
|
19
|
+
import url from 'url';
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
import cloneDeep from 'lodash.clonedeep';
|
|
22
|
+
import yargs from 'yargs';
|
|
23
|
+
import * as yargsHelpers from 'yargs/helpers';
|
|
24
|
+
import log from 'lighthouse-logger';
|
|
25
|
+
|
|
26
|
+
import {runSmokehouse} from '../smokehouse.js';
|
|
27
|
+
import {updateTestDefnFormat} from './back-compat-util.js';
|
|
28
|
+
import {LH_ROOT} from '../../../../root.js';
|
|
29
|
+
|
|
30
|
+
const coreTestDefnsPath =
|
|
31
|
+
path.join(LH_ROOT, 'lighthouse-cli/test/smokehouse/test-definitions/core-tests.js');
|
|
24
32
|
|
|
25
33
|
/**
|
|
26
34
|
* Possible Lighthouse runners. Loaded dynamically so e.g. a CLI run isn't
|
|
@@ -72,6 +80,52 @@ function getDefinitionsToRun(allTestDefns, requestedIds, {invertMatch}) {
|
|
|
72
80
|
return smokes;
|
|
73
81
|
}
|
|
74
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Parses the cli `shardArg` flag into `shardNumber/shardTotal`. Splits
|
|
85
|
+
* `testDefns` into `shardTotal` shards and returns the `shardNumber`th shard.
|
|
86
|
+
* Shards will differ in size by at most 1.
|
|
87
|
+
* Shard params must be 1 ≤ shardNumber ≤ shardTotal.
|
|
88
|
+
* @param {Array<Smokehouse.TestDfn>} testDefns
|
|
89
|
+
* @param {string=} shardArg
|
|
90
|
+
* @return {Array<Smokehouse.TestDfn>}
|
|
91
|
+
*/
|
|
92
|
+
function getShardedDefinitions(testDefns, shardArg) {
|
|
93
|
+
if (!shardArg) return testDefns;
|
|
94
|
+
|
|
95
|
+
// eslint-disable-next-line max-len
|
|
96
|
+
const errorMessage = `'shard' must be of the form 'n/d' and n and d must be positive integers with 1 ≤ n ≤ d. Got '${shardArg}'`;
|
|
97
|
+
const match = /^(?<shardNumber>\d+)\/(?<shardTotal>\d+)$/.exec(shardArg);
|
|
98
|
+
assert(match && match.groups, errorMessage);
|
|
99
|
+
const shardNumber = Number(match.groups.shardNumber);
|
|
100
|
+
const shardTotal = Number(match.groups.shardTotal);
|
|
101
|
+
assert(shardNumber > 0 && Number.isInteger(shardNumber), errorMessage);
|
|
102
|
+
assert(shardTotal > 0 && Number.isInteger(shardTotal));
|
|
103
|
+
assert(shardNumber <= shardTotal, errorMessage);
|
|
104
|
+
|
|
105
|
+
// Array is sharded with `Math.ceil(length / shardTotal)` shards first
|
|
106
|
+
// and then the remaining `Math.floor(length / shardTotal) shards.
|
|
107
|
+
// e.g. `[0, 1, 2, 3]` split into 3 shards is `[[0, 1], [2], [3]]`.
|
|
108
|
+
const baseSize = Math.floor(testDefns.length / shardTotal);
|
|
109
|
+
const biggerSize = baseSize + 1;
|
|
110
|
+
const biggerShardCount = testDefns.length % shardTotal;
|
|
111
|
+
|
|
112
|
+
// Since we don't have tests for this file, construct all shards so correct
|
|
113
|
+
// structure can be asserted.
|
|
114
|
+
const shards = [];
|
|
115
|
+
let index = 0;
|
|
116
|
+
for (let i = 0; i < shardTotal; i++) {
|
|
117
|
+
const shardSize = i < biggerShardCount ? biggerSize : baseSize;
|
|
118
|
+
shards.push(testDefns.slice(index, index + shardSize));
|
|
119
|
+
index += shardSize;
|
|
120
|
+
}
|
|
121
|
+
assert.equal(shards.length, shardTotal);
|
|
122
|
+
assert.deepEqual(shards.flat(), testDefns);
|
|
123
|
+
|
|
124
|
+
const shardDefns = shards[shardNumber - 1];
|
|
125
|
+
console.log(`In this shard (${shardArg}), running: ${shardDefns.map(d => d.id).join(' ')}\n`);
|
|
126
|
+
return shardDefns;
|
|
127
|
+
}
|
|
128
|
+
|
|
75
129
|
/**
|
|
76
130
|
* Prune the `networkRequests` from the test expectations when `takeNetworkRequestUrls`
|
|
77
131
|
* is not defined. Custom servers may not have this method available in-process.
|
|
@@ -112,7 +166,8 @@ function pruneExpectedNetworkRequests(testDefns, takeNetworkRequestUrls) {
|
|
|
112
166
|
* CLI entry point.
|
|
113
167
|
*/
|
|
114
168
|
async function begin() {
|
|
115
|
-
const
|
|
169
|
+
const y = yargs(yargsHelpers.hideBin(process.argv));
|
|
170
|
+
const rawArgv = y
|
|
116
171
|
.help('help')
|
|
117
172
|
.usage('node $0 [<options>] <test-ids>')
|
|
118
173
|
.example('node $0 -j=1 pwa seo', 'run pwa and seo tests serially')
|
|
@@ -155,8 +210,13 @@ async function begin() {
|
|
|
155
210
|
default: false,
|
|
156
211
|
describe: 'Run all available tests except the ones provided',
|
|
157
212
|
},
|
|
213
|
+
'shard': {
|
|
214
|
+
type: 'string',
|
|
215
|
+
// eslint-disable-next-line max-len
|
|
216
|
+
describe: 'A argument of the form "n/d", which divides the selected tests into d groups and runs the nth group. n and d must be positive integers with 1 ≤ n ≤ d.',
|
|
217
|
+
},
|
|
158
218
|
})
|
|
159
|
-
.wrap(
|
|
219
|
+
.wrap(y.terminalWidth())
|
|
160
220
|
.argv;
|
|
161
221
|
|
|
162
222
|
// Augmenting yargs type with auto-camelCasing breaks in tsc@4.1.2 and @types/yargs@15.0.11,
|
|
@@ -170,16 +230,17 @@ async function begin() {
|
|
|
170
230
|
if (argv.runner === 'bundle') {
|
|
171
231
|
console.log('\n✨ Be sure to have recently run this: yarn build-all');
|
|
172
232
|
}
|
|
173
|
-
const
|
|
233
|
+
const {runLighthouse} = await import(runnerPath);
|
|
174
234
|
|
|
175
235
|
// Find test definition file and filter by requestedTestIds.
|
|
176
236
|
let testDefnPath = argv.testsPath || coreTestDefnsPath;
|
|
177
237
|
testDefnPath = path.resolve(process.cwd(), testDefnPath);
|
|
178
238
|
const requestedTestIds = argv._;
|
|
179
|
-
const rawTestDefns =
|
|
239
|
+
const {default: rawTestDefns} = await import(url.pathToFileURL(testDefnPath).href);
|
|
180
240
|
const allTestDefns = updateTestDefnFormat(rawTestDefns);
|
|
181
241
|
const invertMatch = argv.invertMatch;
|
|
182
|
-
const
|
|
242
|
+
const requestedTestDefns = getDefinitionsToRun(allTestDefns, requestedTestIds, {invertMatch});
|
|
243
|
+
const testDefns = getShardedDefinitions(requestedTestDefns, argv.shard);
|
|
183
244
|
|
|
184
245
|
let smokehouseResult;
|
|
185
246
|
let server;
|
|
@@ -189,7 +250,7 @@ async function begin() {
|
|
|
189
250
|
try {
|
|
190
251
|
// If running the core tests, spin up the test server.
|
|
191
252
|
if (testDefnPath === coreTestDefnsPath) {
|
|
192
|
-
({server, serverForOffline} =
|
|
253
|
+
({server, serverForOffline} = await import('../../fixtures/static-server.js'));
|
|
193
254
|
server.listen(10200, 'localhost');
|
|
194
255
|
serverForOffline.listen(10503, 'localhost');
|
|
195
256
|
takeNetworkRequestUrls = server.takeRequestUrls.bind(server);
|
|
@@ -201,7 +262,7 @@ async function begin() {
|
|
|
201
262
|
retries,
|
|
202
263
|
isDebug: argv.debug,
|
|
203
264
|
useFraggleRock: argv.fraggleRock,
|
|
204
|
-
lighthouseRunner,
|
|
265
|
+
lighthouseRunner: runLighthouse,
|
|
205
266
|
takeNetworkRequestUrls,
|
|
206
267
|
};
|
|
207
268
|
|
|
@@ -213,6 +274,24 @@ async function begin() {
|
|
|
213
274
|
|
|
214
275
|
if (!smokehouseResult.success) {
|
|
215
276
|
const failedTestResults = smokehouseResult.testResults.filter(r => r.failed);
|
|
277
|
+
|
|
278
|
+
// For CI, save failed runs to directory to be uploaded.
|
|
279
|
+
if (process.env.CI) {
|
|
280
|
+
const failuresDir = `${LH_ROOT}/.tmp/smokehouse-ci-failures`;
|
|
281
|
+
fs.mkdirSync(failuresDir, {recursive: true});
|
|
282
|
+
|
|
283
|
+
for (const testResult of failedTestResults) {
|
|
284
|
+
for (let i = 0; i < testResult.runs.length; i++) {
|
|
285
|
+
const run = testResult.runs[i];
|
|
286
|
+
fs.writeFileSync(`${failuresDir}/${testResult.id}-${i}.json`, JSON.stringify({
|
|
287
|
+
...run,
|
|
288
|
+
lighthouseLog: run.lighthouseLog.split('\n'),
|
|
289
|
+
assertionLog: run.assertionLog.split('\n'),
|
|
290
|
+
}, null, 2));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
216
295
|
const cmd = `yarn smoke ${failedTestResults.map(r => r.id).join(' ')}`;
|
|
217
296
|
console.log(`rerun failures: ${cmd}`);
|
|
218
297
|
}
|