lighthouse 9.5.0-dev.20221018 → 9.5.0-dev.20221019

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/core/api.js CHANGED
@@ -13,36 +13,40 @@ import {Runner} from './runner.js';
13
13
 
14
14
  /**
15
15
  * @param {LH.Puppeteer.Page} page
16
- * @param {ConstructorParameters<LH.UserFlow>[1]} [options]
16
+ * @param {LH.UserFlow.Options} [options]
17
17
  */
18
18
  async function startFlow(page, options) {
19
19
  return new UserFlow(page, options);
20
20
  }
21
21
 
22
22
  /**
23
- * @param {Parameters<navigationGather>} params
23
+ * @param {LH.Puppeteer.Page|undefined} page
24
+ * @param {LH.NavigationRequestor|undefined} requestor
25
+ * @param {{config?: LH.Config.Json, flags?: LH.Flags}} [options]
24
26
  * @return {Promise<LH.RunnerResult|undefined>}
25
27
  */
26
- async function navigation(...params) {
27
- const gatherResult = await navigationGather(...params);
28
+ async function navigation(page, requestor, options) {
29
+ const gatherResult = await navigationGather(page, requestor, options);
28
30
  return Runner.audit(gatherResult.artifacts, gatherResult.runnerOptions);
29
31
  }
30
32
 
31
33
  /**
32
- * @param {Parameters<snapshotGather>} params
34
+ * @param {LH.Puppeteer.Page} page
35
+ * @param {{config?: LH.Config.Json, flags?: LH.Flags}} [options]
33
36
  * @return {Promise<LH.RunnerResult|undefined>}
34
37
  */
35
- async function snapshot(...params) {
36
- const gatherResult = await snapshotGather(...params);
38
+ async function snapshot(page, options) {
39
+ const gatherResult = await snapshotGather(page, options);
37
40
  return Runner.audit(gatherResult.artifacts, gatherResult.runnerOptions);
38
41
  }
39
42
 
40
43
  /**
41
- * @param {Parameters<startTimespanGather>} params
44
+ * @param {LH.Puppeteer.Page} page
45
+ * @param {{config?: LH.Config.Json, flags?: LH.Flags}} [options]
42
46
  * @return {Promise<{endTimespan: () => Promise<LH.RunnerResult|undefined>}>}
43
47
  */
44
- async function startTimespan(...params) {
45
- const {endTimespanGather} = await startTimespanGather(...params);
48
+ async function startTimespan(page, options) {
49
+ const {endTimespanGather} = await startTimespanGather(page, options);
46
50
  const endTimespan = async () => {
47
51
  const gatherResult = await endTimespanGather();
48
52
  return Runner.audit(gatherResult.artifacts, gatherResult.runnerOptions);
@@ -36,6 +36,7 @@ class Bypass extends AxeAudit {
36
36
  title: str_(UIStrings.title),
37
37
  failureTitle: str_(UIStrings.failureTitle),
38
38
  description: str_(UIStrings.description),
39
+ scoreDisplayMode: AxeAudit.SCORING_MODES.INFORMATIVE,
39
40
  requiredArtifacts: ['Accessibility'],
40
41
  };
41
42
  }
@@ -38,6 +38,7 @@ class THHasDataCells extends AxeAudit {
38
38
  title: str_(UIStrings.title),
39
39
  failureTitle: str_(UIStrings.failureTitle),
40
40
  description: str_(UIStrings.description),
41
+ scoreDisplayMode: AxeAudit.SCORING_MODES.INFORMATIVE,
41
42
  requiredArtifacts: ['Accessibility'],
42
43
  };
43
44
  }
@@ -36,6 +36,7 @@ class VideoCaption extends AxeAudit {
36
36
  title: str_(UIStrings.title),
37
37
  failureTitle: str_(UIStrings.failureTitle),
38
38
  description: str_(UIStrings.description),
39
+ scoreDisplayMode: AxeAudit.SCORING_MODES.INFORMATIVE,
39
40
  requiredArtifacts: ['Accessibility'],
40
41
  };
41
42
  }
@@ -300,11 +300,12 @@ async function _cleanup({requestedUrl, driver, config}) {
300
300
  }
301
301
 
302
302
  /**
303
+ * @param {LH.Puppeteer.Page|undefined} page
303
304
  * @param {LH.NavigationRequestor|undefined} requestor
304
- * @param {{page?: LH.Puppeteer.Page, config?: LH.Config.Json, flags?: LH.Flags}} options
305
+ * @param {{config?: LH.Config.Json, flags?: LH.Flags}} [options]
305
306
  * @return {Promise<LH.Gatherer.FRGatherResult>}
306
307
  */
307
- async function navigationGather(requestor, options) {
308
+ async function navigationGather(page, requestor, options = {}) {
308
309
  const {flags = {}} = options;
309
310
  log.setLevel(flags.logLevel || 'error');
310
311
 
@@ -316,7 +317,6 @@ async function navigationGather(requestor, options) {
316
317
  const runnerOptions = {config, computedCache};
317
318
  const artifacts = await Runner.gather(
318
319
  async () => {
319
- let {page} = options;
320
320
  const normalizedRequestor = isCallback ? requestor : UrlUtils.normalizeUrl(requestor);
321
321
 
322
322
  // For navigation mode, we shouldn't connect to a browser in audit mode,
@@ -13,11 +13,12 @@ import {initializeConfig} from '../config/config.js';
13
13
  import {getBaseArtifacts, finalizeArtifacts} from './base-artifacts.js';
14
14
 
15
15
  /**
16
- * @param {{page: LH.Puppeteer.Page, config?: LH.Config.Json, flags?: LH.Flags}} options
16
+ * @param {LH.Puppeteer.Page} page
17
+ * @param {{config?: LH.Config.Json, flags?: LH.Flags}} [options]
17
18
  * @return {Promise<LH.Gatherer.FRGatherResult>}
18
19
  */
19
- async function snapshotGather(options) {
20
- const {page, flags = {}} = options;
20
+ async function snapshotGather(page, options = {}) {
21
+ const {flags = {}} = options;
21
22
  log.setLevel(flags.logLevel || 'error');
22
23
 
23
24
  const {config} = await initializeConfig('snapshot', options.config, flags);
@@ -14,11 +14,12 @@ import {initializeConfig} from '../config/config.js';
14
14
  import {getBaseArtifacts, finalizeArtifacts} from './base-artifacts.js';
15
15
 
16
16
  /**
17
- * @param {{page: LH.Puppeteer.Page, config?: LH.Config.Json, flags?: LH.Flags}} options
17
+ * @param {LH.Puppeteer.Page} page
18
+ * @param {{config?: LH.Config.Json, flags?: LH.Flags}} [options]
18
19
  * @return {Promise<{endTimespanGather(): Promise<LH.Gatherer.FRGatherResult>}>}
19
20
  */
20
- async function startTimespanGather(options) {
21
- const {page, flags = {}} = options;
21
+ async function startTimespanGather(page, options = {}) {
22
+ const {flags = {}} = options;
22
23
  log.setLevel(flags.logLevel || 'error');
23
24
 
24
25
  const {config} = await initializeConfig('timespan', options.config, flags);
package/core/index.js CHANGED
@@ -40,7 +40,7 @@ import {initializeConfig} from './config/config.js';
40
40
  * @return {Promise<LH.RunnerResult|undefined>}
41
41
  */
42
42
  async function lighthouse(url, flags = {}, configJSON, page) {
43
- return fraggleRock.navigation(url, {page, config: configJSON, flags});
43
+ return fraggleRock.navigation(page, url, {config: configJSON, flags});
44
44
  }
45
45
 
46
46
  /**
@@ -128,29 +128,6 @@ function assertValidGatherer(gathererInstance, gathererName) {
128
128
  }
129
129
  }
130
130
 
131
-
132
- /**
133
- * Validate the LH.Flags
134
- * @param {LH.Flags} flags
135
- */
136
- function assertValidFlags(flags) {
137
- // COMPAT: compatibility layer for devtools as it uses the old way and we need tests to pass
138
- // TODO(paulirish): remove this from LH once emulation refactor has rolled into DevTools
139
- // @ts-expect-error Deprecated flag
140
- if (flags.channel === 'devtools' && flags.internalDisableDeviceScreenEmulation) {
141
- // @ts-expect-error Deprecated flag
142
- flags.formFactor = flags.emulatedFormFactor;
143
- // @ts-expect-error Deprecated flag
144
- flags.emulatedFormFactor = flags.internalDisableDeviceScreenEmulation = undefined;
145
- }
146
-
147
-
148
- // @ts-expect-error Checking for removed flags
149
- if (flags.emulatedFormFactor || flags.internalDisableDeviceScreenEmulation) {
150
- throw new Error('Invalid emulation flag. Emulation configuration changed in LH 7.0. See https://github.com/GoogleChrome/lighthouse/blob/main/docs/emulation.md');
151
- }
152
- }
153
-
154
131
  /**
155
132
  * @implements {LH.Config.Config}
156
133
  */
@@ -193,9 +170,6 @@ class Config {
193
170
  // Validate and merge in plugins (if any).
194
171
  configJSON = await mergePlugins(configJSON, configDir, flags);
195
172
 
196
- if (flags) {
197
- assertValidFlags(flags);
198
- }
199
173
  const settings = resolveSettings(configJSON.settings || {}, flags);
200
174
 
201
175
  // Augment passes with necessary defaults and require gatherers.
package/core/user-flow.js CHANGED
@@ -11,21 +11,18 @@ import {navigationGather} from './gather/navigation-runner.js';
11
11
  import {Runner} from './runner.js';
12
12
  import {initializeConfig} from './config/config.js';
13
13
 
14
- /** @typedef {Parameters<snapshotGather>[0]} FrOptions */
15
- /** @typedef {Omit<FrOptions, 'page'> & {name?: string}} UserFlowOptions */
16
- /** @typedef {Omit<FrOptions, 'page'> & {stepName?: string}} StepOptions */
17
14
  /** @typedef {WeakMap<LH.UserFlow.GatherStep, LH.Gatherer.FRGatherResult['runnerOptions']>} GatherStepRunnerOptions */
18
15
 
19
16
  class UserFlow {
20
17
  /**
21
- * @param {FrOptions['page']} page
22
- * @param {UserFlowOptions=} options
18
+ * @param {LH.Puppeteer.Page} page
19
+ * @param {LH.UserFlow.Options} [options]
23
20
  */
24
21
  constructor(page, options) {
25
- /** @type {FrOptions} */
26
- this.options = {page, ...options};
27
- /** @type {string|undefined} */
28
- this.name = options?.name;
22
+ /** @type {LH.Puppeteer.Page} */
23
+ this._page = page;
24
+ /** @type {LH.UserFlow.Options|undefined} */
25
+ this._options = options;
29
26
  /** @type {LH.UserFlow.GatherStep[]} */
30
27
  this._gatherSteps = [];
31
28
  /** @type {GatherStepRunnerOptions} */
@@ -33,67 +30,37 @@ class UserFlow {
33
30
  }
34
31
 
35
32
  /**
36
- * @param {string} longUrl
37
- * @returns {string}
33
+ * @param {LH.UserFlow.StepFlags} [flags]
34
+ * @return {LH.UserFlow.StepFlags}
38
35
  */
39
- _shortenUrl(longUrl) {
40
- const url = new URL(longUrl);
41
- return `${url.hostname}${url.pathname}`;
42
- }
36
+ _getNextNavigationFlags(flags) {
37
+ const newStepFlags = {...flags};
43
38
 
44
- /**
45
- * @param {LH.Artifacts} artifacts
46
- * @return {string}
47
- */
48
- _getDefaultStepName(artifacts) {
49
- const shortUrl = this._shortenUrl(artifacts.URL.finalDisplayedUrl);
50
- switch (artifacts.GatherContext.gatherMode) {
51
- case 'navigation':
52
- return `Navigation report (${shortUrl})`;
53
- case 'timespan':
54
- return `Timespan report (${shortUrl})`;
55
- case 'snapshot':
56
- return `Snapshot report (${shortUrl})`;
57
- }
58
- }
59
-
60
- /**
61
- * @param {StepOptions=} stepOptions
62
- */
63
- _getNextNavigationOptions(stepOptions) {
64
- const options = {...this.options, ...stepOptions};
65
- const flags = {...options.flags};
66
-
67
- if (flags.skipAboutBlank === undefined) {
68
- flags.skipAboutBlank = true;
39
+ if (newStepFlags.skipAboutBlank === undefined) {
40
+ newStepFlags.skipAboutBlank = true;
69
41
  }
70
42
 
71
43
  // On repeat navigations, we want to disable storage reset by default (i.e. it's not a cold load).
72
44
  const isSubsequentNavigation = this._gatherSteps
73
45
  .some(step => step.artifacts.GatherContext.gatherMode === 'navigation');
74
46
  if (isSubsequentNavigation) {
75
- if (flags.disableStorageReset === undefined) {
76
- flags.disableStorageReset = true;
47
+ if (newStepFlags.disableStorageReset === undefined) {
48
+ newStepFlags.disableStorageReset = true;
77
49
  }
78
50
  }
79
51
 
80
- options.flags = flags;
81
-
82
- return options;
52
+ return newStepFlags;
83
53
  }
84
54
 
85
55
  /**
86
56
  *
87
57
  * @param {LH.Gatherer.FRGatherResult} gatherResult
88
- * @param {StepOptions} options
58
+ * @param {LH.UserFlow.StepFlags} [flags]
89
59
  */
90
- _addGatherStep(gatherResult, options) {
91
- const providedName = options?.stepName;
60
+ _addGatherStep(gatherResult, flags) {
92
61
  const gatherStep = {
93
62
  artifacts: gatherResult.artifacts,
94
- name: providedName || this._getDefaultStepName(gatherResult.artifacts),
95
- config: options.config,
96
- flags: options.flags,
63
+ flags,
97
64
  };
98
65
  this._gatherSteps.push(gatherStep);
99
66
  this._gatherStepRunnerOptions.set(gatherStep, gatherResult.runnerOptions);
@@ -101,23 +68,26 @@ class UserFlow {
101
68
 
102
69
  /**
103
70
  * @param {LH.NavigationRequestor} requestor
104
- * @param {StepOptions=} stepOptions
71
+ * @param {LH.UserFlow.StepFlags} [flags]
105
72
  */
106
- async navigate(requestor, stepOptions) {
73
+ async navigate(requestor, flags) {
107
74
  if (this.currentTimespan) throw new Error('Timespan already in progress');
108
75
  if (this.currentNavigation) throw new Error('Navigation already in progress');
109
76
 
110
- const options = this._getNextNavigationOptions(stepOptions);
111
- const gatherResult = await navigationGather(requestor, options);
77
+ const newStepFlags = this._getNextNavigationFlags(flags);
78
+ const gatherResult = await navigationGather(this._page, requestor, {
79
+ config: this._options?.config,
80
+ flags: newStepFlags,
81
+ });
112
82
 
113
- this._addGatherStep(gatherResult, options);
83
+ this._addGatherStep(gatherResult, newStepFlags);
114
84
  }
115
85
 
116
86
  /**
117
87
  * This is an alternative to `navigate()` that can be used to analyze a navigation triggered by user interaction.
118
88
  * For more on user triggered navigations, see https://github.com/GoogleChrome/lighthouse/blob/main/docs/user-flows.md#triggering-a-navigation-via-user-interactions.
119
89
  *
120
- * @param {StepOptions=} stepOptions
90
+ * @param {LH.UserFlow.StepFlags} [stepOptions]
121
91
  */
122
92
  async startNavigation(stepOptions) {
123
93
  /** @type {(value: () => void) => void} */
@@ -166,39 +136,43 @@ class UserFlow {
166
136
  }
167
137
 
168
138
  /**
169
- * @param {StepOptions=} stepOptions
139
+ * @param {LH.UserFlow.StepFlags} [flags]
170
140
  */
171
- async startTimespan(stepOptions) {
141
+ async startTimespan(flags) {
172
142
  if (this.currentTimespan) throw new Error('Timespan already in progress');
173
143
  if (this.currentNavigation) throw new Error('Navigation already in progress');
174
144
 
175
- const options = {...this.options, ...stepOptions};
176
- const timespan = await startTimespanGather(options);
177
- this.currentTimespan = {timespan, options};
145
+ const timespan = await startTimespanGather(this._page, {
146
+ config: this._options?.config,
147
+ flags: flags,
148
+ });
149
+ this.currentTimespan = {timespan, flags};
178
150
  }
179
151
 
180
152
  async endTimespan() {
181
153
  if (!this.currentTimespan) throw new Error('No timespan in progress');
182
154
  if (this.currentNavigation) throw new Error('Navigation already in progress');
183
155
 
184
- const {timespan, options} = this.currentTimespan;
156
+ const {timespan, flags} = this.currentTimespan;
185
157
  const gatherResult = await timespan.endTimespanGather();
186
158
  this.currentTimespan = undefined;
187
159
 
188
- this._addGatherStep(gatherResult, options);
160
+ this._addGatherStep(gatherResult, flags);
189
161
  }
190
162
 
191
163
  /**
192
- * @param {StepOptions=} stepOptions
164
+ * @param {LH.UserFlow.StepFlags} [flags]
193
165
  */
194
- async snapshot(stepOptions) {
166
+ async snapshot(flags) {
195
167
  if (this.currentTimespan) throw new Error('Timespan already in progress');
196
168
  if (this.currentNavigation) throw new Error('Navigation already in progress');
197
169
 
198
- const options = {...this.options, ...stepOptions};
199
- const gatherResult = await snapshotGather(options);
170
+ const gatherResult = await snapshotGather(this._page, {
171
+ config: this._options?.config,
172
+ flags: flags,
173
+ });
200
174
 
201
- this._addGatherStep(gatherResult, options);
175
+ this._addGatherStep(gatherResult, flags);
202
176
  }
203
177
 
204
178
  /**
@@ -206,8 +180,8 @@ class UserFlow {
206
180
  */
207
181
  async createFlowResult() {
208
182
  return auditGatherSteps(this._gatherSteps, {
209
- name: this.name,
210
- config: this.options.config,
183
+ name: this._options?.name,
184
+ config: this._options?.config,
211
185
  gatherStepRunnerOptions: this._gatherStepRunnerOptions,
212
186
  });
213
187
  }
@@ -226,11 +200,38 @@ class UserFlow {
226
200
  createArtifactsJson() {
227
201
  return {
228
202
  gatherSteps: this._gatherSteps,
229
- name: this.name,
203
+ name: this._options?.name,
230
204
  };
231
205
  }
232
206
  }
233
207
 
208
+ /**
209
+ * @param {string} longUrl
210
+ * @returns {string}
211
+ */
212
+ function shortenUrl(longUrl) {
213
+ const url = new URL(longUrl);
214
+ return `${url.hostname}${url.pathname}`;
215
+ }
216
+
217
+ /**
218
+ * @param {LH.Artifacts} artifacts
219
+ * @return {string}
220
+ */
221
+ function getDefaultStepName(artifacts) {
222
+ const shortUrl = shortenUrl(artifacts.URL.finalDisplayedUrl);
223
+ switch (artifacts.GatherContext.gatherMode) {
224
+ case 'navigation':
225
+ return `Navigation report (${shortUrl})`;
226
+ case 'timespan':
227
+ return `Timespan report (${shortUrl})`;
228
+ case 'snapshot':
229
+ return `Snapshot report (${shortUrl})`;
230
+ default:
231
+ throw new Error('Unsupported gather mode');
232
+ }
233
+ }
234
+
234
235
  /**
235
236
  * @param {Array<LH.UserFlow.GatherStep>} gatherSteps
236
237
  * @param {{name?: string, config?: LH.Config.Json, gatherStepRunnerOptions?: GatherStepRunnerOptions}} options
@@ -243,14 +244,15 @@ async function auditGatherSteps(gatherSteps, options) {
243
244
  /** @type {LH.FlowResult['steps']} */
244
245
  const steps = [];
245
246
  for (const gatherStep of gatherSteps) {
246
- const {artifacts, name, flags} = gatherStep;
247
+ const {artifacts, flags} = gatherStep;
248
+ const name = flags?.name || getDefaultStepName(artifacts);
247
249
 
248
250
  let runnerOptions = options.gatherStepRunnerOptions?.get(gatherStep);
249
251
 
250
252
  // If the gather step is not active, we must recreate the runner options.
251
253
  if (!runnerOptions) {
252
254
  // Step specific configs take precedence over a config for the entire flow.
253
- const configJson = gatherStep.config || options.config;
255
+ const configJson = options.config;
254
256
  const {gatherMode} = artifacts.GatherContext;
255
257
  const {config} = await initializeConfig(gatherMode, configJson, flags);
256
258
  runnerOptions = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lighthouse",
3
3
  "type": "module",
4
- "version": "9.5.0-dev.20221018",
4
+ "version": "9.5.0-dev.20221019",
5
5
  "description": "Automated auditing, performance metrics, and best practices for the web.",
6
6
  "main": "./core/index.js",
7
7
  "bin": {
@@ -95,7 +95,7 @@ describe('ReportGenerator', () => {
95
95
 
96
96
  category,score
97
97
  \\"performance\\",\\"0.26\\"
98
- \\"accessibility\\",\\"0.78\\"
98
+ \\"accessibility\\",\\"0.77\\"
99
99
  \\"best-practices\\",\\"0.27\\"
100
100
  \\"seo\\",\\"0.67\\"
101
101
  \\"pwa\\",\\"0.33\\"
@@ -296,7 +296,7 @@ describe('CategoryRenderer', () => {
296
296
  );
297
297
 
298
298
  const gauge = categoryDOM.querySelector('.lh-fraction__content');
299
- assert.equal(gauge.textContent.trim(), '13/18', 'fraction is included');
299
+ assert.equal(gauge.textContent.trim(), '12/17', 'fraction is included');
300
300
 
301
301
  const score = categoryDOM.querySelector('.lh-category-header');
302
302
  const title = score.querySelector('.lh-fraction__label');
@@ -6,11 +6,18 @@ declare module UserFlow {
6
6
  name?: string;
7
7
  }
8
8
 
9
+ export interface Options {
10
+ config: LH.Config.Json;
11
+ name?: string;
12
+ }
13
+
14
+ export interface StepFlags extends LH.Flags {
15
+ name?: string;
16
+ }
17
+
9
18
  export interface GatherStep {
10
19
  artifacts: LH.Artifacts;
11
- name: string;
12
- config?: LH.Config.Json;
13
- flags?: LH.Flags;
20
+ flags?: StepFlags;
14
21
  }
15
22
  }
16
23