lighthouse 9.5.0-dev.20230112 → 9.5.0-dev.20230113
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/cli/cli-flags.js +5 -1
- package/cli/test/smokehouse/core-tests.js +2 -0
- package/cli/test/smokehouse/report-assert.js +11 -7
- package/core/config/constants.js +1 -0
- package/core/config/default-config.js +0 -1
- package/core/config/filters.js +8 -4
- package/core/gather/gatherers/accessibility.js +15 -1
- package/core/gather/gatherers/full-page-screenshot.js +51 -40
- package/core/gather/gatherers/seo/tap-targets.js +39 -19
- package/core/legacy/config/config.js +8 -10
- package/core/legacy/gather/driver.js +0 -17
- package/core/legacy/gather/gather-runner.js +0 -6
- package/core/runner.js +2 -0
- package/core/util.cjs +30 -0
- package/dist/report/bundle.esm.js +40 -19
- package/dist/report/flow.js +5 -5
- package/dist/report/standalone.js +4 -4
- package/flow-report/src/common.tsx +3 -3
- package/flow-report/src/util.ts +0 -11
- package/flow-report/test/common-test.tsx +4 -7
- package/flow-report/test/summary/summary-test.tsx +1 -1
- package/package.json +1 -1
- package/readme.md +1 -0
- package/report/renderer/details-renderer.js +1 -2
- package/report/renderer/element-screenshot-renderer.js +4 -4
- package/report/renderer/report-renderer.js +3 -7
- package/report/renderer/report-ui-features.js +3 -7
- package/report/renderer/util.js +30 -0
- package/report/test/renderer/util-test.js +20 -0
- package/report/test-assets/faux-psi.js +3 -3
- package/types/artifacts.d.ts +1 -11
- package/types/lhr/audit-details.d.ts +0 -17
- package/types/lhr/lhr.d.ts +13 -0
- package/types/lhr/settings.d.ts +2 -0
- package/types/smokehouse.d.ts +2 -1
- package/core/audits/full-page-screenshot.js +0 -42
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -105,6 +105,7 @@ Configuration:
|
|
|
105
105
|
--only-categories Only run the specified categories. Available categories: accessibility, best-practices, performance, pwa, seo [array]
|
|
106
106
|
--skip-audits Run everything except these audits [array]
|
|
107
107
|
--budget-path The path to the budget.json file for LightWallet. [string]
|
|
108
|
+
--disable-full-page-screenshot Disables collection of the full page screenshot, which can be quite large [boolean]
|
|
108
109
|
|
|
109
110
|
Output:
|
|
110
111
|
--output Reporter for the results, supports multiple values. choices: "json", "html", "csv" [array] [default: ["html"]]
|
|
@@ -34,7 +34,7 @@ const URL_PREFIXES = ['http://', 'https://', 'data:'];
|
|
|
34
34
|
export class DetailsRenderer {
|
|
35
35
|
/**
|
|
36
36
|
* @param {DOM} dom
|
|
37
|
-
* @param {{fullPageScreenshot?: LH.
|
|
37
|
+
* @param {{fullPageScreenshot?: LH.Result.FullPageScreenshot}} [options]
|
|
38
38
|
*/
|
|
39
39
|
constructor(dom, options = {}) {
|
|
40
40
|
this._dom = dom;
|
|
@@ -60,7 +60,6 @@ export class DetailsRenderer {
|
|
|
60
60
|
// Internal-only details, not for rendering.
|
|
61
61
|
case 'screenshot':
|
|
62
62
|
case 'debugdata':
|
|
63
|
-
case 'full-page-screenshot':
|
|
64
63
|
case 'treemap-data':
|
|
65
64
|
return null;
|
|
66
65
|
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
* @property {DOM} dom
|
|
20
20
|
* @property {Element} rootEl
|
|
21
21
|
* @property {Element} overlayContainerEl
|
|
22
|
-
* @property {LH.
|
|
22
|
+
* @property {LH.Result.FullPageScreenshot} fullPageScreenshot
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
import {Util} from './util.js';
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* @param {LH.
|
|
28
|
+
* @param {LH.Result.FullPageScreenshot['screenshot']} screenshot
|
|
29
29
|
* @param {LH.Audit.Details.Rect} rect
|
|
30
30
|
* @return {boolean}
|
|
31
31
|
*/
|
|
@@ -131,7 +131,7 @@ export class ElementScreenshotRenderer {
|
|
|
131
131
|
* Allows for multiple Lighthouse reports to be rendered on the page, each with their
|
|
132
132
|
* own full page screenshot.
|
|
133
133
|
* @param {HTMLElement} el
|
|
134
|
-
* @param {LH.
|
|
134
|
+
* @param {LH.Result.FullPageScreenshot['screenshot']} screenshot
|
|
135
135
|
*/
|
|
136
136
|
static installFullPageScreenshot(el, screenshot) {
|
|
137
137
|
el.style.setProperty('--element-screenshot-url', `url('${screenshot.data}')`);
|
|
@@ -213,7 +213,7 @@ export class ElementScreenshotRenderer {
|
|
|
213
213
|
* Used to render both the thumbnail preview in details tables and the full-page screenshot in the lightbox.
|
|
214
214
|
* Returns null if element rect is outside screenshot bounds.
|
|
215
215
|
* @param {DOM} dom
|
|
216
|
-
* @param {LH.
|
|
216
|
+
* @param {LH.Result.FullPageScreenshot['screenshot']} screenshot
|
|
217
217
|
* @param {Rect} elementRectSC Region of screenshot to highlight.
|
|
218
218
|
* @param {Size} maxRenderSizeDC e.g. maxThumbnailSize or maxLightboxSize.
|
|
219
219
|
* @return {Element|null}
|
|
@@ -268,12 +268,8 @@ export class ReportRenderer {
|
|
|
268
268
|
Util.i18n = i18n;
|
|
269
269
|
Util.reportJson = report;
|
|
270
270
|
|
|
271
|
-
const fullPageScreenshot =
|
|
272
|
-
report.audits['full-page-screenshot']?.details &&
|
|
273
|
-
report.audits['full-page-screenshot'].details.type === 'full-page-screenshot' ?
|
|
274
|
-
report.audits['full-page-screenshot'].details : undefined;
|
|
275
271
|
const detailsRenderer = new DetailsRenderer(this._dom, {
|
|
276
|
-
fullPageScreenshot,
|
|
272
|
+
fullPageScreenshot: report.fullPageScreenshot ?? undefined,
|
|
277
273
|
});
|
|
278
274
|
|
|
279
275
|
const categoryRenderer = new CategoryRenderer(this._dom, detailsRenderer);
|
|
@@ -344,9 +340,9 @@ export class ReportRenderer {
|
|
|
344
340
|
reportSection.append(this._renderReportFooter(report));
|
|
345
341
|
reportContainer.append(headerContainer, reportSection);
|
|
346
342
|
|
|
347
|
-
if (fullPageScreenshot) {
|
|
343
|
+
if (report.fullPageScreenshot) {
|
|
348
344
|
ElementScreenshotRenderer.installFullPageScreenshot(
|
|
349
|
-
this._dom.rootEl, fullPageScreenshot.screenshot);
|
|
345
|
+
this._dom.rootEl, report.fullPageScreenshot.screenshot);
|
|
350
346
|
}
|
|
351
347
|
|
|
352
348
|
return reportFragment;
|
|
@@ -60,6 +60,7 @@ export class ReportUIFeatures {
|
|
|
60
60
|
*/
|
|
61
61
|
initFeatures(lhr) {
|
|
62
62
|
this.json = lhr;
|
|
63
|
+
this._fullPageScreenshot = Util.getFullPageScreenshot(lhr);
|
|
63
64
|
|
|
64
65
|
if (this._topbar) {
|
|
65
66
|
this._topbar.enable(lhr);
|
|
@@ -299,18 +300,13 @@ export class ReportUIFeatures {
|
|
|
299
300
|
* @param {Element} rootEl
|
|
300
301
|
*/
|
|
301
302
|
_setupElementScreenshotOverlay(rootEl) {
|
|
302
|
-
|
|
303
|
-
this.json.audits['full-page-screenshot'] &&
|
|
304
|
-
this.json.audits['full-page-screenshot'].details &&
|
|
305
|
-
this.json.audits['full-page-screenshot'].details.type === 'full-page-screenshot' &&
|
|
306
|
-
this.json.audits['full-page-screenshot'].details;
|
|
307
|
-
if (!fullPageScreenshot) return;
|
|
303
|
+
if (!this._fullPageScreenshot) return;
|
|
308
304
|
|
|
309
305
|
ElementScreenshotRenderer.installOverlayFeature({
|
|
310
306
|
dom: this._dom,
|
|
311
307
|
rootEl: rootEl,
|
|
312
308
|
overlayContainerEl: rootEl,
|
|
313
|
-
fullPageScreenshot,
|
|
309
|
+
fullPageScreenshot: this._fullPageScreenshot,
|
|
314
310
|
});
|
|
315
311
|
}
|
|
316
312
|
|
package/report/renderer/util.js
CHANGED
|
@@ -212,9 +212,39 @@ class Util {
|
|
|
212
212
|
});
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
+
// In 10.0, full-page-screenshot became a top-level property on the LHR.
|
|
216
|
+
if (clone.audits['full-page-screenshot']) {
|
|
217
|
+
const details = /** @type {LH.Result.FullPageScreenshot=} */ (
|
|
218
|
+
clone.audits['full-page-screenshot'].details);
|
|
219
|
+
if (details) {
|
|
220
|
+
clone.fullPageScreenshot = {
|
|
221
|
+
screenshot: details.screenshot,
|
|
222
|
+
nodes: details.nodes,
|
|
223
|
+
};
|
|
224
|
+
} else {
|
|
225
|
+
clone.fullPageScreenshot = null;
|
|
226
|
+
}
|
|
227
|
+
delete clone.audits['full-page-screenshot'];
|
|
228
|
+
}
|
|
229
|
+
|
|
215
230
|
return clone;
|
|
216
231
|
}
|
|
217
232
|
|
|
233
|
+
/**
|
|
234
|
+
* @param {LH.Result} lhr
|
|
235
|
+
* @return {LH.Result.FullPageScreenshot=}
|
|
236
|
+
*/
|
|
237
|
+
static getFullPageScreenshot(lhr) {
|
|
238
|
+
if (lhr.fullPageScreenshot) {
|
|
239
|
+
return lhr.fullPageScreenshot;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Prior to 10.0.
|
|
243
|
+
const details = /** @type {LH.Result.FullPageScreenshot=} */ (
|
|
244
|
+
lhr.audits['full-page-screenshot']?.details);
|
|
245
|
+
return details;
|
|
246
|
+
}
|
|
247
|
+
|
|
218
248
|
/**
|
|
219
249
|
* Used to determine if the "passed" for the purposes of showing up in the "failed" or "passed"
|
|
220
250
|
* sections of the report.
|
|
@@ -168,6 +168,26 @@ describe('util helpers', () => {
|
|
|
168
168
|
assert.deepStrictEqual(preparedResult.audits, sampleResult.audits);
|
|
169
169
|
});
|
|
170
170
|
|
|
171
|
+
it('moves full-page-screenshot audit', () => {
|
|
172
|
+
const clonedSampleResult = JSON.parse(JSON.stringify(sampleResult));
|
|
173
|
+
|
|
174
|
+
clonedSampleResult.audits['full-page-screenshot'] = {
|
|
175
|
+
details: {
|
|
176
|
+
type: 'full-page-screenshot',
|
|
177
|
+
...sampleResult.fullPageScreenshot,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
delete clonedSampleResult.fullPageScreenshot;
|
|
181
|
+
|
|
182
|
+
assert.ok(clonedSampleResult.audits['full-page-screenshot'].details.nodes); // Make sure something's being tested.
|
|
183
|
+
assert.notDeepStrictEqual(clonedSampleResult.audits, sampleResult.audits);
|
|
184
|
+
|
|
185
|
+
// Original audit results should be restored.
|
|
186
|
+
const preparedResult = Util.prepareReportResult(clonedSampleResult);
|
|
187
|
+
assert.deepStrictEqual(preparedResult.audits, sampleResult.audits);
|
|
188
|
+
assert.deepStrictEqual(preparedResult.fullPageScreenshot, sampleResult.fullPageScreenshot);
|
|
189
|
+
});
|
|
190
|
+
|
|
171
191
|
it('corrects performance category without hidden group', () => {
|
|
172
192
|
const clonedSampleResult = JSON.parse(JSON.stringify(sampleResult));
|
|
173
193
|
|
|
@@ -134,9 +134,9 @@ async function distinguishLHR(lhr, tabId) {
|
|
|
134
134
|
finalSSDetails.data = await decorateScreenshot(finalSSDetails.data, tabId);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
if (lhr.fullPageScreenshot) {
|
|
138
|
+
lhr.fullPageScreenshot.screenshot.data =
|
|
139
|
+
await decorateScreenshot(lhr.fullPageScreenshot.screenshot.data, tabId);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
package/types/artifacts.d.ts
CHANGED
|
@@ -146,7 +146,7 @@ export interface GathererArtifacts extends PublicGathererArtifacts,LegacyBaseArt
|
|
|
146
146
|
/** All the input elements, including associated form and label elements. */
|
|
147
147
|
Inputs: {inputs: Artifacts.InputElement[]; forms: Artifacts.FormElement[]; labels: Artifacts.LabelElement[]};
|
|
148
148
|
/** Screenshot of the entire page (rather than just the above the fold content). */
|
|
149
|
-
FullPageScreenshot:
|
|
149
|
+
FullPageScreenshot: LHResult.FullPageScreenshot | null;
|
|
150
150
|
/** Information about event listeners registered on the global object. */
|
|
151
151
|
GlobalListeners: Array<Artifacts.GlobalListener>;
|
|
152
152
|
/** The issues surfaced in the devtools Issues panel */
|
|
@@ -770,16 +770,6 @@ declare module Artifacts {
|
|
|
770
770
|
npm?: string;
|
|
771
771
|
}
|
|
772
772
|
|
|
773
|
-
interface FullPageScreenshot {
|
|
774
|
-
screenshot: {
|
|
775
|
-
/** Base64 image data URL. */
|
|
776
|
-
data: string;
|
|
777
|
-
width: number;
|
|
778
|
-
height: number;
|
|
779
|
-
};
|
|
780
|
-
nodes: Record<string, Rect>;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
773
|
interface TimingSummary {
|
|
784
774
|
firstContentfulPaint: number | undefined;
|
|
785
775
|
firstContentfulPaintTs: number | undefined;
|
|
@@ -15,7 +15,6 @@ type Details =
|
|
|
15
15
|
Details.List |
|
|
16
16
|
Details.Opportunity |
|
|
17
17
|
Details.Screenshot |
|
|
18
|
-
Details.FullPageScreenshot |
|
|
19
18
|
Details.Table;
|
|
20
19
|
|
|
21
20
|
// Details namespace.
|
|
@@ -79,22 +78,6 @@ declare module Details {
|
|
|
79
78
|
data: string;
|
|
80
79
|
}
|
|
81
80
|
|
|
82
|
-
/**
|
|
83
|
-
* A screenshot of the entire page, including width and height information,
|
|
84
|
-
* and the locations of interesting nodes.
|
|
85
|
-
* Used by element screenshots renderer.
|
|
86
|
-
*/
|
|
87
|
-
interface FullPageScreenshot {
|
|
88
|
-
type: 'full-page-screenshot';
|
|
89
|
-
screenshot: {
|
|
90
|
-
/** Base64 image data URL. */
|
|
91
|
-
data: string;
|
|
92
|
-
width: number;
|
|
93
|
-
height: number;
|
|
94
|
-
};
|
|
95
|
-
nodes: Record<string, Rect>;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
81
|
interface Rect {
|
|
99
82
|
width: number;
|
|
100
83
|
height: number;
|
package/types/lhr/lhr.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {Result as AuditResult} from './audit-result';
|
|
8
|
+
import AuditDetails from './audit-details.js';
|
|
8
9
|
import {ConfigSettings} from './settings';
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -55,6 +56,8 @@ interface Result {
|
|
|
55
56
|
};
|
|
56
57
|
/** An array containing the result of all stack packs. */
|
|
57
58
|
stackPacks?: Result.StackPack[];
|
|
59
|
+
/** Screenshot taken of the full page, with node rects referencing audit results. If there was an error with collection, this is null. If disabled via the disableFullPageScreenshot setting, this is undefined. */
|
|
60
|
+
fullPageScreenshot?: Result.FullPageScreenshot | null;
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
// Result namespace
|
|
@@ -138,6 +141,16 @@ declare module Result {
|
|
|
138
141
|
descriptions: Record<string, string>;
|
|
139
142
|
}
|
|
140
143
|
|
|
144
|
+
interface FullPageScreenshot {
|
|
145
|
+
screenshot: {
|
|
146
|
+
/** Base64 image data URL. */
|
|
147
|
+
data: string;
|
|
148
|
+
width: number;
|
|
149
|
+
height: number;
|
|
150
|
+
};
|
|
151
|
+
nodes: Record<string, AuditDetails.Rect>;
|
|
152
|
+
}
|
|
153
|
+
|
|
141
154
|
/**
|
|
142
155
|
* Info about an `LH.IcuMessage` value that was localized to a string when
|
|
143
156
|
* included in the LHR. Value is either a
|
package/types/lhr/settings.d.ts
CHANGED
|
@@ -112,6 +112,8 @@ export type ScreenEmulationSettings = {
|
|
|
112
112
|
cpuQuietThresholdMs?: number;
|
|
113
113
|
/** The URL to use for the "blank" neutral page in between navigations. Defaults to `about:blank`. */
|
|
114
114
|
blankPage?: string;
|
|
115
|
+
/** Disables collection of the full page screenshot, which can be rather large and possibly leave the page in an undesirable state. */
|
|
116
|
+
disableFullPageScreenshot?: boolean;
|
|
115
117
|
}
|
|
116
118
|
|
|
117
119
|
export interface ConfigSettings extends Required<SharedFlagsSettings> {
|
package/types/smokehouse.d.ts
CHANGED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license Copyright 2020 Google Inc. All Rights Reserved.
|
|
3
|
-
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
-
* 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.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import {Audit} from './audit.js';
|
|
8
|
-
|
|
9
|
-
class FullPageScreenshot extends Audit {
|
|
10
|
-
/**
|
|
11
|
-
* @return {LH.Audit.Meta}
|
|
12
|
-
*/
|
|
13
|
-
static get meta() {
|
|
14
|
-
return {
|
|
15
|
-
id: 'full-page-screenshot',
|
|
16
|
-
scoreDisplayMode: Audit.SCORING_MODES.INFORMATIVE,
|
|
17
|
-
title: 'Full-page screenshot',
|
|
18
|
-
description: 'A full-height screenshot of the final rendered page',
|
|
19
|
-
requiredArtifacts: ['FullPageScreenshot'],
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* @param {LH.Artifacts} artifacts
|
|
25
|
-
* @return {Promise<LH.Audit.Product>}
|
|
26
|
-
*/
|
|
27
|
-
static async audit(artifacts) {
|
|
28
|
-
if (!artifacts.FullPageScreenshot) {
|
|
29
|
-
return {score: 0, notApplicable: true};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return {
|
|
33
|
-
score: 1,
|
|
34
|
-
details: {
|
|
35
|
-
type: 'full-page-screenshot',
|
|
36
|
-
...artifacts.FullPageScreenshot,
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export default FullPageScreenshot;
|