lighthouse 8.6.0-dev.20211023 → 8.6.0-dev.20211027
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/dist/report/flow.js +10 -10
- package/dist/report/standalone.js +2 -2
- package/flow-report/assets/styles.css +57 -1
- package/flow-report/src/i18n/ui-strings.js +2 -0
- package/flow-report/src/summary/category.tsx +73 -4
- package/flow-report/src/summary/summary.tsx +1 -0
- package/flow-report/src/wrappers/markdown.tsx +27 -0
- package/flow-report/test/summary/category-test.tsx +111 -19
- package/flow-report/test/wrappers/markdown-test.tsx +29 -0
- package/jest.config.js +2 -2
- package/lighthouse-core/audits/byte-efficiency/modern-image-formats.js +4 -2
- package/lighthouse-core/audits/byte-efficiency/offscreen-images.js +11 -10
- package/lighthouse-core/audits/byte-efficiency/uses-optimized-images.js +5 -3
- package/lighthouse-core/audits/byte-efficiency/uses-responsive-images-snapshot.js +2 -1
- package/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js +2 -1
- package/lighthouse-core/audits/image-aspect-ratio.js +4 -3
- package/lighthouse-core/audits/image-size-responsive.js +3 -2
- package/lighthouse-core/audits/preload-lcp-image.js +7 -5
- package/lighthouse-core/audits/script-treemap-data.js +1 -1
- package/lighthouse-core/audits/unsized-images.js +1 -2
- package/package.json +6 -5
- package/report/renderer/category-renderer.js +7 -0
- package/report/renderer/pwa-category-renderer.js +0 -10
- package/report/renderer/report-renderer.js +1 -1
- package/report/test/renderer/category-renderer-test.js +41 -0
- package/report/test/renderer/pwa-category-renderer-test.js +4 -4
- package/report/test/renderer/text-encoding-test.js +1 -1
- package/shared/localization/locales/ar-XB.json +8 -8
- package/shared/localization/locales/ar.json +8 -8
- package/shared/localization/locales/bg.json +8 -8
- package/shared/localization/locales/ca.json +8 -8
- package/shared/localization/locales/cs.json +8 -8
- package/shared/localization/locales/da.json +8 -8
- package/shared/localization/locales/de.json +8 -8
- package/shared/localization/locales/el.json +8 -8
- package/shared/localization/locales/en-GB.json +8 -8
- package/shared/localization/locales/en-US.json +27 -24
- package/shared/localization/locales/en-XA.json +8 -8
- package/shared/localization/locales/en-XL.json +27 -24
- package/shared/localization/locales/es-419.json +8 -8
- package/shared/localization/locales/es.json +8 -8
- package/shared/localization/locales/fi.json +8 -8
- package/shared/localization/locales/fil.json +8 -8
- package/shared/localization/locales/fr.json +8 -8
- package/shared/localization/locales/he.json +8 -8
- package/shared/localization/locales/hi.json +8 -8
- package/shared/localization/locales/hr.json +8 -8
- package/shared/localization/locales/hu.json +8 -8
- package/shared/localization/locales/id.json +8 -8
- package/shared/localization/locales/it.json +8 -8
- package/shared/localization/locales/ja.json +8 -8
- package/shared/localization/locales/ko.json +8 -8
- package/shared/localization/locales/lt.json +8 -8
- package/shared/localization/locales/lv.json +8 -8
- package/shared/localization/locales/nl.json +8 -8
- package/shared/localization/locales/no.json +8 -8
- package/shared/localization/locales/pl.json +8 -8
- package/shared/localization/locales/pt-PT.json +8 -8
- package/shared/localization/locales/pt.json +8 -8
- package/shared/localization/locales/ro.json +8 -8
- package/shared/localization/locales/ru.json +8 -8
- package/shared/localization/locales/sk.json +8 -8
- package/shared/localization/locales/sl.json +8 -8
- package/shared/localization/locales/sr-Latn.json +8 -8
- package/shared/localization/locales/sr.json +8 -8
- package/shared/localization/locales/sv.json +8 -8
- package/shared/localization/locales/ta.json +8 -8
- package/shared/localization/locales/te.json +8 -8
- package/shared/localization/locales/th.json +8 -8
- package/shared/localization/locales/tr.json +8 -8
- package/shared/localization/locales/uk.json +8 -8
- package/shared/localization/locales/vi.json +8 -8
- package/shared/localization/locales/zh-HK.json +8 -8
- package/shared/localization/locales/zh-TW.json +8 -8
- package/shared/localization/locales/zh.json +8 -8
- package/tsconfig-all.json +2 -2
- package/types/lhr/audit-details.d.ts +5 -5
|
@@ -37,7 +37,7 @@ const IGNORE_THRESHOLD_IN_BYTES = 2048;
|
|
|
37
37
|
const IGNORE_THRESHOLD_IN_PERCENT = 75;
|
|
38
38
|
const IGNORE_THRESHOLD_IN_MS = 50;
|
|
39
39
|
|
|
40
|
-
/** @typedef {{url: string, requestStartTime: number, totalBytes: number, wastedBytes: number, wastedPercent: number}} WasteResult */
|
|
40
|
+
/** @typedef {{node: LH.Audit.Details.NodeValue, url: string, requestStartTime: number, totalBytes: number, wastedBytes: number, wastedPercent: number}} WasteResult */
|
|
41
41
|
|
|
42
42
|
class OffscreenImages extends ByteEfficiencyAudit {
|
|
43
43
|
/**
|
|
@@ -100,6 +100,7 @@ class OffscreenImages extends ByteEfficiencyAudit {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
return {
|
|
103
|
+
node: ByteEfficiencyAudit.makeNodeItem(image.node),
|
|
103
104
|
url,
|
|
104
105
|
requestStartTime: networkRecord.startTime,
|
|
105
106
|
totalBytes,
|
|
@@ -184,26 +185,26 @@ class OffscreenImages extends ByteEfficiencyAudit {
|
|
|
184
185
|
|
|
185
186
|
/** @type {string[]} */
|
|
186
187
|
const warnings = [];
|
|
187
|
-
|
|
188
|
+
/** @type {Map<string, WasteResult>} */
|
|
189
|
+
const resultsMap = new Map();
|
|
190
|
+
for (const image of images) {
|
|
188
191
|
const processed = OffscreenImages.computeWaste(image, viewportDimensions, networkRecords);
|
|
189
192
|
if (processed === null) {
|
|
190
|
-
|
|
193
|
+
continue;
|
|
191
194
|
}
|
|
192
195
|
|
|
193
196
|
if (processed instanceof Error) {
|
|
194
197
|
warnings.push(processed.message);
|
|
195
198
|
Sentry.captureException(processed, {tags: {audit: this.meta.id}, level: 'warning'});
|
|
196
|
-
|
|
199
|
+
continue;
|
|
197
200
|
}
|
|
198
201
|
|
|
199
202
|
// If an image was used more than once, warn only about its least wasteful usage
|
|
200
|
-
const existing =
|
|
203
|
+
const existing = resultsMap.get(processed.url);
|
|
201
204
|
if (!existing || existing.wastedBytes > processed.wastedBytes) {
|
|
202
|
-
|
|
205
|
+
resultsMap.set(processed.url, processed);
|
|
203
206
|
}
|
|
204
|
-
|
|
205
|
-
return results;
|
|
206
|
-
}, /** @type {Map<string, WasteResult>} */ (new Map()));
|
|
207
|
+
}
|
|
207
208
|
|
|
208
209
|
const settings = context.settings;
|
|
209
210
|
|
|
@@ -233,7 +234,7 @@ class OffscreenImages extends ByteEfficiencyAudit {
|
|
|
233
234
|
|
|
234
235
|
/** @type {LH.Audit.Details.Opportunity['headings']} */
|
|
235
236
|
const headings = [
|
|
236
|
-
{key: '
|
|
237
|
+
{key: 'node', valueType: 'node', label: ''},
|
|
237
238
|
{key: 'url', valueType: 'url', label: str_(i18n.UIStrings.columnURL)},
|
|
238
239
|
{key: 'totalBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnResourceSize)},
|
|
239
240
|
{key: 'wastedBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnWastedBytes)},
|
|
@@ -76,10 +76,12 @@ class UsesOptimizedImages extends ByteEfficiencyAudit {
|
|
|
76
76
|
const imageElementsByURL = new Map();
|
|
77
77
|
imageElements.forEach(img => imageElementsByURL.set(img.src, img));
|
|
78
78
|
|
|
79
|
-
/** @type {Array<{url: string, fromProtocol: boolean, isCrossOrigin: boolean, totalBytes: number, wastedBytes: number}>} */
|
|
79
|
+
/** @type {Array<{node?: LH.Audit.Details.NodeValue, url: string, fromProtocol: boolean, isCrossOrigin: boolean, totalBytes: number, wastedBytes: number}>} */
|
|
80
80
|
const items = [];
|
|
81
81
|
const warnings = [];
|
|
82
82
|
for (const image of images) {
|
|
83
|
+
const imageElement = imageElementsByURL.get(image.url);
|
|
84
|
+
|
|
83
85
|
if (image.failed) {
|
|
84
86
|
warnings.push(`Unable to decode ${URL.getURLDisplayName(image.url)}`);
|
|
85
87
|
continue;
|
|
@@ -91,7 +93,6 @@ class UsesOptimizedImages extends ByteEfficiencyAudit {
|
|
|
91
93
|
let fromProtocol = true;
|
|
92
94
|
|
|
93
95
|
if (typeof jpegSize === 'undefined') {
|
|
94
|
-
const imageElement = imageElementsByURL.get(image.url);
|
|
95
96
|
if (!imageElement) {
|
|
96
97
|
warnings.push(`Unable to locate resource ${URL.getURLDisplayName(image.url)}`);
|
|
97
98
|
continue;
|
|
@@ -115,6 +116,7 @@ class UsesOptimizedImages extends ByteEfficiencyAudit {
|
|
|
115
116
|
const jpegSavings = UsesOptimizedImages.computeSavings({...image, jpegSize});
|
|
116
117
|
|
|
117
118
|
items.push({
|
|
119
|
+
node: imageElement ? ByteEfficiencyAudit.makeNodeItem(imageElement.node) : undefined,
|
|
118
120
|
url,
|
|
119
121
|
fromProtocol,
|
|
120
122
|
isCrossOrigin,
|
|
@@ -125,7 +127,7 @@ class UsesOptimizedImages extends ByteEfficiencyAudit {
|
|
|
125
127
|
|
|
126
128
|
/** @type {LH.Audit.Details.Opportunity['headings']} */
|
|
127
129
|
const headings = [
|
|
128
|
-
{key: '
|
|
130
|
+
{key: 'node', valueType: 'node', label: ''},
|
|
129
131
|
{key: 'url', valueType: 'url', label: str_(i18n.UIStrings.columnURL)},
|
|
130
132
|
{key: 'totalBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnResourceSize)},
|
|
131
133
|
{key: 'wastedBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnWastedBytes)},
|
|
@@ -70,6 +70,7 @@ class UsesResponsiveImagesSnapshot extends Audit {
|
|
|
70
70
|
if (actualPixels - usedPixels > IGNORE_THRESHOLD_IN_PIXELS) score = 0;
|
|
71
71
|
|
|
72
72
|
items.push({
|
|
73
|
+
node: Audit.makeNodeItem(image.node),
|
|
73
74
|
url: URL.elideDataURI(image.src),
|
|
74
75
|
displayedDimensions: `${displayed.width}x${displayed.height}`,
|
|
75
76
|
actualDimensions: `${actual.width}x${actual.height}`,
|
|
@@ -79,7 +80,7 @@ class UsesResponsiveImagesSnapshot extends Audit {
|
|
|
79
80
|
/** @type {LH.Audit.Details.Table['headings']} */
|
|
80
81
|
const headings = [
|
|
81
82
|
/* eslint-disable max-len */
|
|
82
|
-
{key: '
|
|
83
|
+
{key: 'node', itemType: 'node', text: ''},
|
|
83
84
|
{key: 'url', itemType: 'url', text: str_(i18n.UIStrings.columnURL)},
|
|
84
85
|
{key: 'displayedDimensions', itemType: 'text', text: str_(UIStrings.columnDisplayedDimensions)},
|
|
85
86
|
{key: 'actualDimensions', itemType: 'text', text: str_(UIStrings.columnActualDimensions)},
|
|
@@ -104,6 +104,7 @@ class UsesResponsiveImages extends ByteEfficiencyAudit {
|
|
|
104
104
|
const wastedBytes = Math.round(totalBytes * wastedRatio);
|
|
105
105
|
|
|
106
106
|
return {
|
|
107
|
+
node: ByteEfficiencyAudit.makeNodeItem(image.node),
|
|
107
108
|
url,
|
|
108
109
|
totalBytes,
|
|
109
110
|
wastedBytes,
|
|
@@ -158,7 +159,7 @@ class UsesResponsiveImages extends ByteEfficiencyAudit {
|
|
|
158
159
|
|
|
159
160
|
/** @type {LH.Audit.Details.Opportunity['headings']} */
|
|
160
161
|
const headings = [
|
|
161
|
-
{key: '
|
|
162
|
+
{key: 'node', valueType: 'node', label: ''},
|
|
162
163
|
{key: 'url', valueType: 'url', label: str_(i18n.UIStrings.columnURL)},
|
|
163
164
|
{key: 'totalBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnResourceSize)},
|
|
164
165
|
{key: 'wastedBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnWastedBytes)},
|
|
@@ -51,7 +51,7 @@ class ImageAspectRatio extends Audit {
|
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* @param {WellDefinedImage} image
|
|
54
|
-
* @return {{url: string, displayedAspectRatio: string, actualAspectRatio: string, doRatiosMatch: boolean}}
|
|
54
|
+
* @return {{url: string, node: LH.Audit.Details.NodeValue, displayedAspectRatio: string, actualAspectRatio: string, doRatiosMatch: boolean}}
|
|
55
55
|
*/
|
|
56
56
|
static computeAspectRatios(image) {
|
|
57
57
|
const url = URL.elideDataURI(image.src);
|
|
@@ -63,6 +63,7 @@ class ImageAspectRatio extends Audit {
|
|
|
63
63
|
|
|
64
64
|
return {
|
|
65
65
|
url,
|
|
66
|
+
node: Audit.makeNodeItem(image.node),
|
|
66
67
|
displayedAspectRatio: `${image.displayedWidth} x ${image.displayedHeight}
|
|
67
68
|
(${displayedAspectRatio.toFixed(2)})`,
|
|
68
69
|
actualAspectRatio: `${image.naturalDimensions.width} x ${image.naturalDimensions.height}
|
|
@@ -78,7 +79,7 @@ class ImageAspectRatio extends Audit {
|
|
|
78
79
|
static audit(artifacts) {
|
|
79
80
|
const images = artifacts.ImageElements;
|
|
80
81
|
|
|
81
|
-
/** @type {Array<{url: string, displayedAspectRatio: string, actualAspectRatio: string, doRatiosMatch: boolean}>} */
|
|
82
|
+
/** @type {Array<{url: string, node: LH.Audit.Details.NodeValue, displayedAspectRatio: string, actualAspectRatio: string, doRatiosMatch: boolean}>} */
|
|
82
83
|
const results = [];
|
|
83
84
|
images.filter(image => {
|
|
84
85
|
// - filter out css background images since we don't have a reliable way to tell if it's a
|
|
@@ -105,7 +106,7 @@ class ImageAspectRatio extends Audit {
|
|
|
105
106
|
|
|
106
107
|
/** @type {LH.Audit.Details.Table['headings']} */
|
|
107
108
|
const headings = [
|
|
108
|
-
{key: '
|
|
109
|
+
{key: 'node', itemType: 'node', text: ''},
|
|
109
110
|
{key: 'url', itemType: 'url', text: str_(i18n.UIStrings.columnURL)},
|
|
110
111
|
{key: 'displayedAspectRatio', itemType: 'text', text: str_(UIStrings.columnDisplayed)},
|
|
111
112
|
{key: 'actualAspectRatio', itemType: 'text', text: str_(UIStrings.columnActual)},
|
|
@@ -45,7 +45,7 @@ const LARGE_IMAGE_FACTOR = 0.75;
|
|
|
45
45
|
// considered SMALL.
|
|
46
46
|
const SMALL_IMAGE_THRESHOLD = 64;
|
|
47
47
|
|
|
48
|
-
/** @typedef {{url: string, elidedUrl: string, displayedSize: string, actualSize: string, actualPixels: number, expectedSize: string, expectedPixels: number}} Result */
|
|
48
|
+
/** @typedef {{url: string, node: LH.Audit.Details.NodeValue, elidedUrl: string, displayedSize: string, actualSize: string, actualPixels: number, expectedSize: string, expectedPixels: number}} Result */
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* @param {{top: number, bottom: number, left: number, right: number}} imageRect
|
|
@@ -147,6 +147,7 @@ function getResult(image, DPR) {
|
|
|
147
147
|
expectedImageSize(image.displayedWidth, image.displayedHeight, DPR);
|
|
148
148
|
return {
|
|
149
149
|
url: image.src,
|
|
150
|
+
node: Audit.makeNodeItem(image.node),
|
|
150
151
|
elidedUrl: URL.elideDataURI(image.src),
|
|
151
152
|
displayedSize: `${image.displayedWidth} x ${image.displayedHeight}`,
|
|
152
153
|
actualSize: `${image.naturalDimensions.width} x ${image.naturalDimensions.height}`,
|
|
@@ -263,7 +264,7 @@ class ImageSizeResponsive extends Audit {
|
|
|
263
264
|
|
|
264
265
|
/** @type {LH.Audit.Details.Table['headings']} */
|
|
265
266
|
const headings = [
|
|
266
|
-
{key: '
|
|
267
|
+
{key: 'node', itemType: 'node', text: ''},
|
|
267
268
|
{key: 'elidedUrl', itemType: 'url', text: str_(i18n.UIStrings.columnURL)},
|
|
268
269
|
{key: 'displayedSize', itemType: 'text', text: str_(UIStrings.columnDisplayed)},
|
|
269
270
|
{key: 'actualSize', itemType: 'text', text: str_(UIStrings.columnActual)},
|
|
@@ -106,13 +106,14 @@ class PreloadLCPImageAudit extends Audit {
|
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
108
|
* Computes the estimated effect of preloading the LCP image.
|
|
109
|
+
* @param {LH.Artifacts.TraceElement|undefined} lcpElement
|
|
109
110
|
* @param {LH.Gatherer.Simulation.GraphNetworkNode|undefined} lcpNode
|
|
110
111
|
* @param {LH.Gatherer.Simulation.GraphNode} graph
|
|
111
112
|
* @param {LH.Gatherer.Simulation.Simulator} simulator
|
|
112
|
-
* @return {{wastedMs: number, results: Array<{url: string, wastedMs: number}>}}
|
|
113
|
+
* @return {{wastedMs: number, results: Array<{node: LH.Audit.Details.NodeValue, url: string, wastedMs: number}>}}
|
|
113
114
|
*/
|
|
114
|
-
static computeWasteWithGraph(lcpNode, graph, simulator) {
|
|
115
|
-
if (!lcpNode) {
|
|
115
|
+
static computeWasteWithGraph(lcpElement, lcpNode, graph, simulator) {
|
|
116
|
+
if (!lcpElement || !lcpNode) {
|
|
116
117
|
return {
|
|
117
118
|
wastedMs: 0,
|
|
118
119
|
results: [],
|
|
@@ -185,6 +186,7 @@ class PreloadLCPImageAudit extends Audit {
|
|
|
185
186
|
return {
|
|
186
187
|
wastedMs,
|
|
187
188
|
results: [{
|
|
189
|
+
node: Audit.makeNodeItem(lcpElement.node),
|
|
188
190
|
url: lcpNode.record.url,
|
|
189
191
|
wastedMs,
|
|
190
192
|
}],
|
|
@@ -216,11 +218,11 @@ class PreloadLCPImageAudit extends Audit {
|
|
|
216
218
|
const lcpNode = PreloadLCPImageAudit.getLCPNodeToPreload(mainResource, graph, lcpElement, artifacts.ImageElements);
|
|
217
219
|
|
|
218
220
|
const {results, wastedMs} =
|
|
219
|
-
PreloadLCPImageAudit.computeWasteWithGraph(lcpNode, graph, simulator);
|
|
221
|
+
PreloadLCPImageAudit.computeWasteWithGraph(lcpElement, lcpNode, graph, simulator);
|
|
220
222
|
|
|
221
223
|
/** @type {LH.Audit.Details.Opportunity['headings']} */
|
|
222
224
|
const headings = [
|
|
223
|
-
{key: '
|
|
225
|
+
{key: 'node', valueType: 'node', label: ''},
|
|
224
226
|
{key: 'url', valueType: 'url', label: str_(i18n.UIStrings.columnURL)},
|
|
225
227
|
{key: 'wastedMs', valueType: 'timespanMs', label: str_(i18n.UIStrings.columnWastedMs)},
|
|
226
228
|
];
|
|
@@ -147,9 +147,8 @@ class UnsizedImages extends Audit {
|
|
|
147
147
|
|
|
148
148
|
/** @type {LH.Audit.Details.Table['headings']} */
|
|
149
149
|
const headings = [
|
|
150
|
-
{key: '
|
|
150
|
+
{key: 'node', itemType: 'node', text: ''},
|
|
151
151
|
{key: 'url', itemType: 'url', text: str_(i18n.UIStrings.columnURL)},
|
|
152
|
-
{key: 'node', itemType: 'node', text: str_(i18n.UIStrings.columnFailingElem)},
|
|
153
152
|
];
|
|
154
153
|
|
|
155
154
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lighthouse",
|
|
3
|
-
"version": "8.6.0-dev.
|
|
3
|
+
"version": "8.6.0-dev.20211027",
|
|
4
4
|
"description": "Automated auditing, performance metrics, and best practices for the web.",
|
|
5
5
|
"main": "./lighthouse-core/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"node": ">=14.15"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
+
"prepack": "yarn build-report --standalone --flow",
|
|
15
16
|
"build-all": "npm-run-posix-or-windows build-all:task",
|
|
16
17
|
"build-all:task": "yarn build-report && yarn build-cdt-lib && yarn build-devtools && (yarn build-extension & yarn build-lr & yarn build-viewer & yarn build-treemap & yarn build-smokehouse-bundle & wait) && yarn build-pack",
|
|
17
18
|
"build-all:task:windows": "yarn build-report && yarn build-cdt-lib && yarn build-extension && yarn build-devtools && yarn build-lr && yarn build-viewer && yarn build-treemap && yarn build-smokehouse-bundle",
|
|
@@ -38,8 +39,8 @@
|
|
|
38
39
|
"test": "yarn diff:sample-json && yarn lint --quiet && yarn unit && yarn type-check",
|
|
39
40
|
"test-bundle": "yarn smoke --runner bundle -j=1 --retries=2 --invert-match forms",
|
|
40
41
|
"test-clients": "yarn jest \"$PWD/clients/\" && yarn jest --testMatch=\"**/clients/test/**/*-test-pptr.js\"",
|
|
41
|
-
"test-viewer": "yarn unit-viewer && yarn jest --testMatch=\"**/
|
|
42
|
-
"test-treemap": "yarn unit-treemap && yarn jest --testMatch=\"**/
|
|
42
|
+
"test-viewer": "yarn unit-viewer && yarn jest --testMatch=\"**/viewer/**/*-test-pptr.js\"",
|
|
43
|
+
"test-treemap": "yarn unit-treemap && yarn jest --testMatch=\"**/treemap/**/*-test-pptr.js\"",
|
|
43
44
|
"test-lantern": "bash lighthouse-core/scripts/test-lantern.sh",
|
|
44
45
|
"test-legacy-javascript": "bash lighthouse-core/scripts/test-legacy-javascript.sh",
|
|
45
46
|
"test-docs": "yarn --cwd docs/recipes/ test",
|
|
@@ -47,8 +48,8 @@
|
|
|
47
48
|
"unit-core": "yarn jest \"lighthouse-core\"",
|
|
48
49
|
"unit-cli": "yarn jest \"lighthouse-cli/\"",
|
|
49
50
|
"unit-report": "yarn jest \"report/\"",
|
|
50
|
-
"unit-treemap": "yarn jest \"
|
|
51
|
-
"unit-viewer": "yarn jest \"
|
|
51
|
+
"unit-treemap": "yarn jest \"treemap/.*-test.js\"",
|
|
52
|
+
"unit-viewer": "yarn jest \"viewer/.*-test.js\"",
|
|
52
53
|
"unit-flow": "yarn jest \"flow-report/.*-test.[tj]s[x]?\"",
|
|
53
54
|
"unit": "yarn jest",
|
|
54
55
|
"unit:ci": "NODE_OPTIONS=--max-old-space-size=8192 npm run jest --ci .",
|
|
@@ -532,6 +532,13 @@ export class CategoryRenderer {
|
|
|
532
532
|
clumps.set(clumpId, clump);
|
|
533
533
|
}
|
|
534
534
|
|
|
535
|
+
// Sort audits by weight.
|
|
536
|
+
for (const auditRefs of clumps.values()) {
|
|
537
|
+
auditRefs.sort((a, b) => {
|
|
538
|
+
return b.weight - a.weight;
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
|
|
535
542
|
// Render each clump.
|
|
536
543
|
for (const [clumpId, auditRefs] of clumps) {
|
|
537
544
|
if (auditRefs.length === 0) continue;
|
|
@@ -47,16 +47,6 @@ export class PwaCategoryRenderer extends CategoryRenderer {
|
|
|
47
47
|
return categoryElem;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
/**
|
|
51
|
-
* Alias for backcompat.
|
|
52
|
-
* @param {LH.ReportResult.Category} category
|
|
53
|
-
* @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
|
|
54
|
-
* @return {DocumentFragment}
|
|
55
|
-
*/
|
|
56
|
-
renderScoreGauge(category, groupDefinitions) {
|
|
57
|
-
return this.renderCategoryScore(category, groupDefinitions);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
50
|
/**
|
|
61
51
|
* @param {LH.ReportResult.Category} category
|
|
62
52
|
* @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
|
|
@@ -212,7 +212,7 @@ export class ReportRenderer {
|
|
|
212
212
|
// The renderer for default categories is just the default CategoryRenderer.
|
|
213
213
|
// If the functions are equal, then renderer is an instance of CategoryRenderer.
|
|
214
214
|
// For example, the PWA category uses PwaCategoryRenderer, which overrides
|
|
215
|
-
// CategoryRenderer.
|
|
215
|
+
// CategoryRenderer.renderCategoryScore, so it would fail this check and be placed
|
|
216
216
|
// in the customGauges bucket.
|
|
217
217
|
defaultGauges.push(categoryGauge);
|
|
218
218
|
} else {
|
|
@@ -499,4 +499,45 @@ describe('CategoryRenderer', () => {
|
|
|
499
499
|
assert.ok(shouldBeWarning[0].textContent.includes(passingWarning));
|
|
500
500
|
});
|
|
501
501
|
});
|
|
502
|
+
|
|
503
|
+
it('renders audits by weight', () => {
|
|
504
|
+
const defaultAuditRef = {
|
|
505
|
+
title: '',
|
|
506
|
+
description: '',
|
|
507
|
+
scoreDisplayMode: 'numeric',
|
|
508
|
+
score: 0,
|
|
509
|
+
warnings: [],
|
|
510
|
+
};
|
|
511
|
+
const category = {
|
|
512
|
+
id: 'test',
|
|
513
|
+
title: 'Test',
|
|
514
|
+
score: 0,
|
|
515
|
+
auditRefs: [{
|
|
516
|
+
id: 'audit-1',
|
|
517
|
+
weight: 0,
|
|
518
|
+
result: {
|
|
519
|
+
id: 'audit-1',
|
|
520
|
+
...defaultAuditRef,
|
|
521
|
+
},
|
|
522
|
+
}, {
|
|
523
|
+
id: 'audit-2',
|
|
524
|
+
weight: 1,
|
|
525
|
+
result: {
|
|
526
|
+
id: 'audit-2',
|
|
527
|
+
...defaultAuditRef,
|
|
528
|
+
},
|
|
529
|
+
}, {
|
|
530
|
+
id: 'audit-3',
|
|
531
|
+
weight: 0.5,
|
|
532
|
+
result: {
|
|
533
|
+
id: 'audit-3',
|
|
534
|
+
...defaultAuditRef,
|
|
535
|
+
},
|
|
536
|
+
}],
|
|
537
|
+
};
|
|
538
|
+
const categoryDOM = renderer.render(category);
|
|
539
|
+
|
|
540
|
+
const auditEls = [...categoryDOM.querySelectorAll('.lh-audit')];
|
|
541
|
+
expect(auditEls.map(el => el.id)).toEqual(['audit-2', 'audit-3', 'audit-1']);
|
|
542
|
+
});
|
|
502
543
|
});
|
|
@@ -249,10 +249,10 @@ describe('PwaCategoryRenderer', () => {
|
|
|
249
249
|
});
|
|
250
250
|
});
|
|
251
251
|
|
|
252
|
-
describe('#
|
|
252
|
+
describe('#renderCategoryScore', () => {
|
|
253
253
|
it('renders an error score gauge in case of category error', () => {
|
|
254
254
|
category.score = null;
|
|
255
|
-
const badgeGauge = pwaRenderer.
|
|
255
|
+
const badgeGauge = pwaRenderer.renderCategoryScore(category, sampleResults.categoryGroups);
|
|
256
256
|
|
|
257
257
|
// Not a PWA gauge.
|
|
258
258
|
assert.strictEqual(badgeGauge.querySelector('.lh-gauge--pwa__wrapper'), null);
|
|
@@ -263,11 +263,11 @@ describe('PwaCategoryRenderer', () => {
|
|
|
263
263
|
});
|
|
264
264
|
|
|
265
265
|
it('renders score gauges with unique ids for items in <defs>', () => {
|
|
266
|
-
const gauge1 = pwaRenderer.
|
|
266
|
+
const gauge1 = pwaRenderer.renderCategoryScore(category, sampleResults.categoryGroups);
|
|
267
267
|
const gauge1Ids = [...gauge1.querySelectorAll('defs [id]')].map(el => el.id);
|
|
268
268
|
assert.ok(gauge1Ids.length > 2);
|
|
269
269
|
|
|
270
|
-
const gauge2 = pwaRenderer.
|
|
270
|
+
const gauge2 = pwaRenderer.renderCategoryScore(category, sampleResults.categoryGroups);
|
|
271
271
|
const gauge2Ids = [...gauge2.querySelectorAll('defs [id]')].map(el => el.id);
|
|
272
272
|
assert.ok(gauge2Ids.length === gauge1Ids.length);
|
|
273
273
|
|
|
@@ -41,6 +41,6 @@ describe('TextEncoding', () => {
|
|
|
41
41
|
await test('Some examples of emoji are 😃, 🧘🏻♂️, 🌍, 🍞, 🚗, 📞, 🎉, ♥️, 🍆, and 🏁.');
|
|
42
42
|
await test('.'.repeat(125183));
|
|
43
43
|
await test('😃'.repeat(125183));
|
|
44
|
-
await test(fs.readFileSync(LH_ROOT + '/
|
|
44
|
+
await test(fs.readFileSync(LH_ROOT + '/treemap/app/debug.json', 'utf-8'));
|
|
45
45
|
});
|
|
46
46
|
});
|
|
@@ -2069,28 +2069,28 @@
|
|
|
2069
2069
|
"lighthouse-core/lib/lh-error.js | urlInvalid": {
|
|
2070
2070
|
"message": "The URL you have provided appears to be invalid."
|
|
2071
2071
|
},
|
|
2072
|
-
"
|
|
2072
|
+
"treemap/app/src/util.js | allLabel": {
|
|
2073
2073
|
"message": "All"
|
|
2074
2074
|
},
|
|
2075
|
-
"
|
|
2075
|
+
"treemap/app/src/util.js | allScriptsDropdownLabel": {
|
|
2076
2076
|
"message": "All Scripts"
|
|
2077
2077
|
},
|
|
2078
|
-
"
|
|
2078
|
+
"treemap/app/src/util.js | coverageColumnName": {
|
|
2079
2079
|
"message": "Coverage"
|
|
2080
2080
|
},
|
|
2081
|
-
"
|
|
2081
|
+
"treemap/app/src/util.js | duplicateModulesLabel": {
|
|
2082
2082
|
"message": "Duplicate Modules"
|
|
2083
2083
|
},
|
|
2084
|
-
"
|
|
2084
|
+
"treemap/app/src/util.js | resourceBytesLabel": {
|
|
2085
2085
|
"message": "Resource Bytes"
|
|
2086
2086
|
},
|
|
2087
|
-
"
|
|
2087
|
+
"treemap/app/src/util.js | tableColumnName": {
|
|
2088
2088
|
"message": "Name"
|
|
2089
2089
|
},
|
|
2090
|
-
"
|
|
2090
|
+
"treemap/app/src/util.js | toggleTableButtonLabel": {
|
|
2091
2091
|
"message": "Toggle Table"
|
|
2092
2092
|
},
|
|
2093
|
-
"
|
|
2093
|
+
"treemap/app/src/util.js | unusedBytesLabel": {
|
|
2094
2094
|
"message": "Unused Bytes"
|
|
2095
2095
|
},
|
|
2096
2096
|
"node_modules/lighthouse-stack-packs/packs/amp.js | efficient-animated-content": {
|
|
@@ -2069,28 +2069,28 @@
|
|
|
2069
2069
|
"lighthouse-core/lib/lh-error.js | urlInvalid": {
|
|
2070
2070
|
"message": "يبدو أن عنوان URL الذي قدمته غير صحيح."
|
|
2071
2071
|
},
|
|
2072
|
-
"
|
|
2072
|
+
"treemap/app/src/util.js | allLabel": {
|
|
2073
2073
|
"message": "الكل"
|
|
2074
2074
|
},
|
|
2075
|
-
"
|
|
2075
|
+
"treemap/app/src/util.js | allScriptsDropdownLabel": {
|
|
2076
2076
|
"message": "جميع النصوص البرمجية"
|
|
2077
2077
|
},
|
|
2078
|
-
"
|
|
2078
|
+
"treemap/app/src/util.js | coverageColumnName": {
|
|
2079
2079
|
"message": "التغطية"
|
|
2080
2080
|
},
|
|
2081
|
-
"
|
|
2081
|
+
"treemap/app/src/util.js | duplicateModulesLabel": {
|
|
2082
2082
|
"message": "الوحدات المكرَّرة"
|
|
2083
2083
|
},
|
|
2084
|
-
"
|
|
2084
|
+
"treemap/app/src/util.js | resourceBytesLabel": {
|
|
2085
2085
|
"message": "حجم الموارد بوحدة البايت"
|
|
2086
2086
|
},
|
|
2087
|
-
"
|
|
2087
|
+
"treemap/app/src/util.js | tableColumnName": {
|
|
2088
2088
|
"message": "الاسم"
|
|
2089
2089
|
},
|
|
2090
|
-
"
|
|
2090
|
+
"treemap/app/src/util.js | toggleTableButtonLabel": {
|
|
2091
2091
|
"message": "تبديل الجدول"
|
|
2092
2092
|
},
|
|
2093
|
-
"
|
|
2093
|
+
"treemap/app/src/util.js | unusedBytesLabel": {
|
|
2094
2094
|
"message": "وحدات بايت غير المستخدمة"
|
|
2095
2095
|
},
|
|
2096
2096
|
"node_modules/lighthouse-stack-packs/packs/amp.js | efficient-animated-content": {
|
|
@@ -2069,28 +2069,28 @@
|
|
|
2069
2069
|
"lighthouse-core/lib/lh-error.js | urlInvalid": {
|
|
2070
2070
|
"message": "Предоставеният от вас URL адрес изглежда невалиден."
|
|
2071
2071
|
},
|
|
2072
|
-
"
|
|
2072
|
+
"treemap/app/src/util.js | allLabel": {
|
|
2073
2073
|
"message": "Всички"
|
|
2074
2074
|
},
|
|
2075
|
-
"
|
|
2075
|
+
"treemap/app/src/util.js | allScriptsDropdownLabel": {
|
|
2076
2076
|
"message": "Всички скриптове"
|
|
2077
2077
|
},
|
|
2078
|
-
"
|
|
2078
|
+
"treemap/app/src/util.js | coverageColumnName": {
|
|
2079
2079
|
"message": "Обхват"
|
|
2080
2080
|
},
|
|
2081
|
-
"
|
|
2081
|
+
"treemap/app/src/util.js | duplicateModulesLabel": {
|
|
2082
2082
|
"message": "Дублиращи се модули"
|
|
2083
2083
|
},
|
|
2084
|
-
"
|
|
2084
|
+
"treemap/app/src/util.js | resourceBytesLabel": {
|
|
2085
2085
|
"message": "Байтове на ресурсите"
|
|
2086
2086
|
},
|
|
2087
|
-
"
|
|
2087
|
+
"treemap/app/src/util.js | tableColumnName": {
|
|
2088
2088
|
"message": "Име"
|
|
2089
2089
|
},
|
|
2090
|
-
"
|
|
2090
|
+
"treemap/app/src/util.js | toggleTableButtonLabel": {
|
|
2091
2091
|
"message": "Превключване на таблицата"
|
|
2092
2092
|
},
|
|
2093
|
-
"
|
|
2093
|
+
"treemap/app/src/util.js | unusedBytesLabel": {
|
|
2094
2094
|
"message": "Неизползвани байтове"
|
|
2095
2095
|
},
|
|
2096
2096
|
"node_modules/lighthouse-stack-packs/packs/amp.js | efficient-animated-content": {
|
|
@@ -2069,28 +2069,28 @@
|
|
|
2069
2069
|
"lighthouse-core/lib/lh-error.js | urlInvalid": {
|
|
2070
2070
|
"message": "Sembla que l'URL que has proporcionat no és vàlid."
|
|
2071
2071
|
},
|
|
2072
|
-
"
|
|
2072
|
+
"treemap/app/src/util.js | allLabel": {
|
|
2073
2073
|
"message": "Tot"
|
|
2074
2074
|
},
|
|
2075
|
-
"
|
|
2075
|
+
"treemap/app/src/util.js | allScriptsDropdownLabel": {
|
|
2076
2076
|
"message": "Tots els scripts"
|
|
2077
2077
|
},
|
|
2078
|
-
"
|
|
2078
|
+
"treemap/app/src/util.js | coverageColumnName": {
|
|
2079
2079
|
"message": "Cobertura"
|
|
2080
2080
|
},
|
|
2081
|
-
"
|
|
2081
|
+
"treemap/app/src/util.js | duplicateModulesLabel": {
|
|
2082
2082
|
"message": "Mòduls duplicats"
|
|
2083
2083
|
},
|
|
2084
|
-
"
|
|
2084
|
+
"treemap/app/src/util.js | resourceBytesLabel": {
|
|
2085
2085
|
"message": "Bytes del recurs"
|
|
2086
2086
|
},
|
|
2087
|
-
"
|
|
2087
|
+
"treemap/app/src/util.js | tableColumnName": {
|
|
2088
2088
|
"message": "Nom"
|
|
2089
2089
|
},
|
|
2090
|
-
"
|
|
2090
|
+
"treemap/app/src/util.js | toggleTableButtonLabel": {
|
|
2091
2091
|
"message": "Commuta la taula"
|
|
2092
2092
|
},
|
|
2093
|
-
"
|
|
2093
|
+
"treemap/app/src/util.js | unusedBytesLabel": {
|
|
2094
2094
|
"message": "Bytes no utilitzats"
|
|
2095
2095
|
},
|
|
2096
2096
|
"node_modules/lighthouse-stack-packs/packs/amp.js | efficient-animated-content": {
|
|
@@ -2069,28 +2069,28 @@
|
|
|
2069
2069
|
"lighthouse-core/lib/lh-error.js | urlInvalid": {
|
|
2070
2070
|
"message": "Adresa URL, kterou jste poskytli, se zdá být neplatná."
|
|
2071
2071
|
},
|
|
2072
|
-
"
|
|
2072
|
+
"treemap/app/src/util.js | allLabel": {
|
|
2073
2073
|
"message": "Vše"
|
|
2074
2074
|
},
|
|
2075
|
-
"
|
|
2075
|
+
"treemap/app/src/util.js | allScriptsDropdownLabel": {
|
|
2076
2076
|
"message": "Všechna písma"
|
|
2077
2077
|
},
|
|
2078
|
-
"
|
|
2078
|
+
"treemap/app/src/util.js | coverageColumnName": {
|
|
2079
2079
|
"message": "Pokrytí"
|
|
2080
2080
|
},
|
|
2081
|
-
"
|
|
2081
|
+
"treemap/app/src/util.js | duplicateModulesLabel": {
|
|
2082
2082
|
"message": "Duplicitní moduly"
|
|
2083
2083
|
},
|
|
2084
|
-
"
|
|
2084
|
+
"treemap/app/src/util.js | resourceBytesLabel": {
|
|
2085
2085
|
"message": "Počet bajtů zdroje"
|
|
2086
2086
|
},
|
|
2087
|
-
"
|
|
2087
|
+
"treemap/app/src/util.js | tableColumnName": {
|
|
2088
2088
|
"message": "Název"
|
|
2089
2089
|
},
|
|
2090
|
-
"
|
|
2090
|
+
"treemap/app/src/util.js | toggleTableButtonLabel": {
|
|
2091
2091
|
"message": "Zobrazit nebo skrýt tabulku"
|
|
2092
2092
|
},
|
|
2093
|
-
"
|
|
2093
|
+
"treemap/app/src/util.js | unusedBytesLabel": {
|
|
2094
2094
|
"message": "Nevyužité bajty"
|
|
2095
2095
|
},
|
|
2096
2096
|
"node_modules/lighthouse-stack-packs/packs/amp.js | efficient-animated-content": {
|