lighthouse 8.3.0-dev.20210907 → 8.3.0
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 +1 -1
- package/dist/report/standalone.js +196 -0
- package/jest.config.js +0 -4
- package/lighthouse-cli/cli-flags.js +6 -14
- package/lighthouse-cli/run.js +1 -1
- package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +3 -9
- package/lighthouse-cli/test/smokehouse/report-assert.js +16 -36
- package/lighthouse-core/audits/large-javascript-libraries.js +166 -0
- package/lighthouse-core/audits/seo/http-status-code.js +6 -2
- package/lighthouse-core/audits/viewport.js +1 -2
- package/lighthouse-core/config/config-helpers.js +75 -9
- package/lighthouse-core/config/config.js +50 -6
- package/lighthouse-core/config/constants.js +0 -1
- package/lighthouse-core/config/default-config.js +0 -3
- package/lighthouse-core/config/experimental-config.js +8 -0
- package/lighthouse-core/config/metrics-to-audits.js +0 -1
- package/lighthouse-core/fraggle-rock/config/config.js +4 -3
- package/lighthouse-core/fraggle-rock/config/default-config.js +1 -3
- package/lighthouse-core/fraggle-rock/config/validation.js +0 -201
- package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +0 -4
- package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +8 -16
- package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +0 -4
- package/lighthouse-core/fraggle-rock/gather/session.js +5 -30
- package/lighthouse-core/gather/driver/navigation.js +6 -7
- package/lighthouse-core/gather/driver/wait-for-condition.js +0 -27
- package/lighthouse-core/gather/fetcher.js +7 -17
- package/lighthouse-core/gather/gather-runner.js +0 -1
- package/lighthouse-core/gather/gatherers/seo/robots-txt.js +6 -2
- package/lighthouse-core/gather/gatherers/seo/tap-targets.js +2 -2
- package/lighthouse-core/gather/gatherers/stacks.js +1 -1
- package/lighthouse-core/lib/asset-saver.js +2 -2
- package/lighthouse-core/lib/cdt/SDK.js +0 -1
- package/lighthouse-core/lib/csp-evaluator.js +4 -17
- package/{report/generator → lighthouse-core/lib}/file-namer.js +0 -0
- package/lighthouse-core/lib/i18n/README.md +1 -1
- package/lighthouse-core/lib/i18n/i18n.js +7 -7
- package/lighthouse-core/lib/i18n/locales/ar-XB.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ar.json +18 -0
- package/lighthouse-core/lib/i18n/locales/bg.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ca.json +18 -0
- package/lighthouse-core/lib/i18n/locales/cs.json +18 -0
- package/lighthouse-core/lib/i18n/locales/da.json +18 -0
- package/lighthouse-core/lib/i18n/locales/de.json +18 -0
- package/lighthouse-core/lib/i18n/locales/el.json +18 -0
- package/lighthouse-core/lib/i18n/locales/en-GB.json +18 -0
- package/lighthouse-core/lib/i18n/locales/en-US.json +18 -18
- package/lighthouse-core/lib/i18n/locales/en-XA.json +18 -0
- package/lighthouse-core/lib/i18n/locales/en-XL.json +18 -18
- package/lighthouse-core/lib/i18n/locales/es-419.json +18 -0
- package/lighthouse-core/lib/i18n/locales/es.json +18 -0
- package/lighthouse-core/lib/i18n/locales/fi.json +18 -0
- package/lighthouse-core/lib/i18n/locales/fil.json +18 -0
- package/lighthouse-core/lib/i18n/locales/fr.json +18 -0
- package/lighthouse-core/lib/i18n/locales/he.json +18 -0
- package/lighthouse-core/lib/i18n/locales/hi.json +18 -0
- package/lighthouse-core/lib/i18n/locales/hr.json +18 -0
- package/lighthouse-core/lib/i18n/locales/hu.json +18 -0
- package/lighthouse-core/lib/i18n/locales/id.json +18 -0
- package/lighthouse-core/lib/i18n/locales/it.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ja.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ko.json +18 -0
- package/lighthouse-core/lib/i18n/locales/lt.json +18 -0
- package/lighthouse-core/lib/i18n/locales/lv.json +18 -0
- package/lighthouse-core/lib/i18n/locales/nl.json +18 -0
- package/lighthouse-core/lib/i18n/locales/no.json +18 -0
- package/lighthouse-core/lib/i18n/locales/pl.json +18 -0
- package/lighthouse-core/lib/i18n/locales/pt-PT.json +18 -0
- package/lighthouse-core/lib/i18n/locales/pt.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ro.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ru.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sk.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sl.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sr-Latn.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sr.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sv.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ta.json +18 -0
- package/lighthouse-core/lib/i18n/locales/te.json +18 -0
- package/lighthouse-core/lib/i18n/locales/th.json +18 -0
- package/lighthouse-core/lib/i18n/locales/tr.json +18 -0
- package/lighthouse-core/lib/i18n/locales/uk.json +18 -0
- package/lighthouse-core/lib/i18n/locales/vi.json +18 -0
- package/lighthouse-core/lib/i18n/locales/zh-HK.json +18 -0
- package/lighthouse-core/lib/i18n/locales/zh-TW.json +18 -0
- package/lighthouse-core/lib/i18n/locales/zh.json +18 -0
- package/lighthouse-core/lib/large-javascript-libraries/bundlephobia-database.json +62 -0
- package/lighthouse-core/lib/large-javascript-libraries/library-suggestions.js +20 -0
- package/lighthouse-core/lib/network-request.js +1 -3
- package/lighthouse-core/lib/traces/pwmetrics-events.js +2 -2
- package/lighthouse-core/lib/url-shim.js +1 -7
- package/lighthouse-core/runner.js +1 -4
- package/lighthouse-core/util-commonjs.js +2 -2
- package/now.json +1 -1
- package/package.json +13 -20
- package/report/README.md +2 -2
- package/report/assets/standalone-template.html +1 -0
- package/report/assets/styles.css +27 -23
- package/report/assets/templates.html +40 -37
- package/report/clients/bundle.js +0 -1
- package/report/{package.json → clients/package.json} +0 -0
- package/report/clients/psi.js +3 -13
- package/report/clients/standalone.js +1 -1
- package/report/{types/buffer.d.ts → clients/treemap.js} +13 -11
- package/report/renderer/category-renderer.js +2 -2
- package/report/renderer/components.js +48 -46
- package/report/renderer/crc-details-renderer.js +16 -16
- package/report/renderer/details-renderer.js +1 -1
- package/report/renderer/dom.js +0 -17
- package/report/renderer/element-screenshot-renderer.js +9 -9
- package/{flow-report/test/setup/global-setup.ts → report/renderer/file-namer.js} +2 -5
- package/report/renderer/logger.js +4 -4
- package/report/renderer/package.json +4 -0
- package/report/renderer/report-renderer.js +11 -4
- package/report/renderer/report-ui-features.js +656 -43
- package/report/renderer/text-encoding.js +1 -1
- package/report/renderer/util.js +2 -2
- package/report/{generator/report-assets.js → report-assets.js} +3 -9
- package/report/{generator/report-generator.js → report-generator.js} +9 -37
- package/report/test/clients/package.json +4 -0
- package/report/test/clients/psi-test.js +1 -3
- package/report/test/renderer/category-renderer-test.js +3 -8
- package/report/test/renderer/components-test.js +0 -35
- package/report/test/renderer/crc-details-renderer-test.js +4 -5
- package/report/test/renderer/details-renderer-test.js +1 -3
- package/report/test/renderer/dom-test.js +6 -8
- package/report/test/renderer/i18n-test.js +0 -1
- package/report/test/renderer/package.json +4 -0
- package/report/test/renderer/performance-category-renderer-test.js +27 -30
- package/report/test/renderer/pwa-category-renderer-test.js +1 -2
- package/report/test/renderer/report-renderer-test.js +0 -1
- package/report/test/renderer/report-ui-features-test.js +28 -20
- package/report/test/renderer/snippet-renderer-test.js +0 -1
- package/report/test/renderer/text-encoding-test.js +0 -2
- package/report/test/renderer/util-test.js +0 -1
- package/report/test/{generator/report-generator-test.js → report-generator-test.js} +7 -9
- package/third-party/chromium-synchronization/installability-errors-test.js +27 -28
- package/third-party/snyk/snapshot.json +0 -2
- package/tsconfig.json +5 -24
- package/types/artifacts.d.ts +18 -5
- package/types/{lhr/audit-details.d.ts → audit-details.d.ts} +3 -18
- package/types/audit.d.ts +58 -7
- package/types/{lhr/budget.d.ts → budget.d.ts} +0 -0
- package/types/bundle-phobia-cli/index.d.ts +40 -0
- package/types/config.d.ts +8 -3
- package/types/externs.d.ts +119 -5
- package/types/gatherer.d.ts +2 -3
- package/types/global-lh.d.ts +14 -16
- package/{report/types/report-result.d.ts → types/html-renderer.d.ts} +17 -8
- package/types/{lhr/i18n.d.ts → i18n.d.ts} +25 -2
- package/types/{lhr/lhr.d.ts → lhr.d.ts} +9 -41
- package/types/smokehouse.d.ts +3 -3
- package/types/{lhr/treemap.d.ts → treemap.d.ts} +3 -3
- package/flow-report/assets/standalone-flow-template.html +0 -38
- package/flow-report/assets/styles.css +0 -310
- package/flow-report/jest.config.js +0 -24
- package/flow-report/src/app.tsx +0 -40
- package/flow-report/src/common.tsx +0 -72
- package/flow-report/src/icons.tsx +0 -96
- package/flow-report/src/sidebar/flow.tsx +0 -72
- package/flow-report/src/sidebar/sidebar.tsx +0 -89
- package/flow-report/src/summary/summary.tsx +0 -178
- package/flow-report/src/util.ts +0 -160
- package/flow-report/src/wrappers/gauge.tsx +0 -40
- package/flow-report/src/wrappers/report-renderer.tsx +0 -46
- package/flow-report/src/wrappers/report.tsx +0 -71
- package/flow-report/standalone-flow.tsx +0 -23
- package/flow-report/test/app-test.tsx +0 -48
- package/flow-report/test/common-test.tsx +0 -131
- package/flow-report/test/setup/env-setup.ts +0 -25
- package/flow-report/test/sidebar/flow-test.tsx +0 -71
- package/flow-report/test/sidebar/sidebar-test.tsx +0 -53
- package/flow-report/test/summary/summary-test.tsx +0 -132
- package/flow-report/test/util-test.tsx +0 -109
- package/flow-report/tsconfig.json +0 -39
- package/flow-report/types/flow-report.d.ts +0 -27
- package/lighthouse-core/audits/lcp-lazy-loaded.js +0 -83
- package/report/.eslintrc.cjs +0 -33
- package/report/generator/README.md +0 -9
- package/report/generator/flow-report-assets.js +0 -20
- package/report/generator/package.json +0 -4
- package/report/generator/tsconfig.json +0 -28
- package/report/renderer/drop-down-menu.js +0 -215
- package/report/renderer/features-util.js +0 -26
- package/report/renderer/open-tab.js +0 -137
- package/report/renderer/topbar-features.js +0 -309
- package/report/test/generator/file-namer-test.js +0 -28
- package/report/test/generator/package.json +0 -4
- package/report/test-assets/faux-psi-template.html +0 -126
- package/report/test-assets/faux-psi.js +0 -92
- package/report/tsconfig.json +0 -39
- package/report/types/augment-dom.d.ts +0 -24
- package/report/types/html-renderer.d.ts +0 -28
- package/types/lhr/audit-result.d.ts +0 -59
- package/types/lhr/flow.d.ts +0 -16
- package/types/lhr/settings.d.ts +0 -105
- package/types/lhr/tsconfig.json +0 -24
- package/types/query-selector.d.ts +0 -36
package/report/renderer/util.js
CHANGED
|
@@ -388,7 +388,7 @@ export class Util {
|
|
|
388
388
|
}
|
|
389
389
|
|
|
390
390
|
/**
|
|
391
|
-
* @param {LH.
|
|
391
|
+
* @param {LH.Config.Settings} settings
|
|
392
392
|
* @return {!Array<{name: string, description: string}>}
|
|
393
393
|
*/
|
|
394
394
|
static getEnvironmentDisplayValues(settings) {
|
|
@@ -411,7 +411,7 @@ export class Util {
|
|
|
411
411
|
}
|
|
412
412
|
|
|
413
413
|
/**
|
|
414
|
-
* @param {LH.
|
|
414
|
+
* @param {LH.Config.Settings} settings
|
|
415
415
|
* @return {{deviceEmulation: string, networkThrottling: string, cpuThrottling: string}}
|
|
416
416
|
*/
|
|
417
417
|
static getEmulationDescriptions(settings) {
|
|
@@ -7,12 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
const fs = require('fs');
|
|
9
9
|
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
'utf8');
|
|
14
|
-
const REPORT_JAVASCRIPT = fs.readFileSync(__dirname + '/../../dist/report/standalone.js', 'utf8');
|
|
15
|
-
const REPORT_CSS = fs.readFileSync(__dirname + '/../assets/styles.css', 'utf8');
|
|
10
|
+
const REPORT_TEMPLATE = fs.readFileSync(__dirname + '/assets/standalone-template.html', 'utf8');
|
|
11
|
+
const REPORT_JAVASCRIPT = fs.readFileSync(__dirname + '/../dist/report/standalone.js', 'utf8');
|
|
12
|
+
const REPORT_CSS = fs.readFileSync(__dirname + '/assets/styles.css', 'utf8');
|
|
16
13
|
|
|
17
14
|
// Changes to this export interface should be reflected in build/build-dt-report-resources.js
|
|
18
15
|
// and clients/devtools-report-assets.js
|
|
@@ -20,7 +17,4 @@ module.exports = {
|
|
|
20
17
|
REPORT_TEMPLATE,
|
|
21
18
|
REPORT_JAVASCRIPT,
|
|
22
19
|
REPORT_CSS,
|
|
23
|
-
// Flow report assets are not needed for every bundle.
|
|
24
|
-
// Ignoring flow-report-assets.js (e.g. `browserify.ignore`) will remove the flow assets from the bundle.
|
|
25
|
-
...flowReportAssets,
|
|
26
20
|
};
|
|
@@ -7,9 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
const htmlReportAssets = require('./report-assets.js');
|
|
9
9
|
|
|
10
|
-
/** @typedef {import('../../types/lhr/lhr').default} LHResult */
|
|
11
|
-
/** @typedef {import('../../types/lhr/flow').default} FlowResult */
|
|
12
|
-
|
|
13
10
|
class ReportGenerator {
|
|
14
11
|
/**
|
|
15
12
|
* Replaces all the specified strings in source without serial replacements.
|
|
@@ -31,23 +28,15 @@ class ReportGenerator {
|
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
/**
|
|
34
|
-
*
|
|
35
|
-
* @
|
|
36
|
-
*/
|
|
37
|
-
static sanitizeJson(object) {
|
|
38
|
-
return JSON.stringify(object)
|
|
39
|
-
.replace(/</g, '\\u003c') // replaces opening script tags
|
|
40
|
-
.replace(/\u2028/g, '\\u2028') // replaces line separators ()
|
|
41
|
-
.replace(/\u2029/g, '\\u2029'); // replaces paragraph separators
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Returns the standalone report HTML as a string with the report JSON and renderer JS inlined.
|
|
46
|
-
* @param {LHResult} lhr
|
|
31
|
+
* Returns the report HTML as a string with the report JSON and renderer JS inlined.
|
|
32
|
+
* @param {LH.Result} lhr
|
|
47
33
|
* @return {string}
|
|
48
34
|
*/
|
|
49
35
|
static generateReportHtml(lhr) {
|
|
50
|
-
const sanitizedJson =
|
|
36
|
+
const sanitizedJson = JSON.stringify(lhr)
|
|
37
|
+
.replace(/</g, '\\u003c') // replaces opening script tags
|
|
38
|
+
.replace(/\u2028/g, '\\u2028') // replaces line separators ()
|
|
39
|
+
.replace(/\u2029/g, '\\u2029'); // replaces paragraph separators
|
|
51
40
|
// terser does its own sanitization, but keep this basic replace for when
|
|
52
41
|
// we want to generate a report without minification.
|
|
53
42
|
const sanitizedJavascript = htmlReportAssets.REPORT_JAVASCRIPT.replace(/<\//g, '\\u003c/');
|
|
@@ -59,23 +48,6 @@ class ReportGenerator {
|
|
|
59
48
|
]);
|
|
60
49
|
}
|
|
61
50
|
|
|
62
|
-
/**
|
|
63
|
-
* Returns the standalone flow report HTML as a string with the report JSON and renderer JS inlined.
|
|
64
|
-
* @param {FlowResult} flow
|
|
65
|
-
* @return {string}
|
|
66
|
-
*/
|
|
67
|
-
static generateFlowReportHtml(flow) {
|
|
68
|
-
const sanitizedJson = ReportGenerator.sanitizeJson(flow);
|
|
69
|
-
return ReportGenerator.replaceStrings(htmlReportAssets.FLOW_REPORT_TEMPLATE, [
|
|
70
|
-
/* eslint-disable max-len */
|
|
71
|
-
{search: '%%LIGHTHOUSE_FLOW_JSON%%', replacement: sanitizedJson},
|
|
72
|
-
{search: '%%LIGHTHOUSE_FLOW_JAVASCRIPT%%', replacement: htmlReportAssets.FLOW_REPORT_JAVASCRIPT},
|
|
73
|
-
{search: '/*%%LIGHTHOUSE_FLOW_CSS%%*/', replacement: htmlReportAssets.FLOW_REPORT_CSS},
|
|
74
|
-
{search: '/*%%LIGHTHOUSE_CSS%%*/', replacement: htmlReportAssets.REPORT_CSS},
|
|
75
|
-
/* eslint-enable max-len */
|
|
76
|
-
]);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
51
|
/**
|
|
80
52
|
* Converts the results to a CSV formatted string
|
|
81
53
|
* Each row describes the result of 1 audit with
|
|
@@ -85,7 +57,7 @@ class ReportGenerator {
|
|
|
85
57
|
* - the score type that is used for the audit
|
|
86
58
|
* - the score value of the audit
|
|
87
59
|
*
|
|
88
|
-
* @param {
|
|
60
|
+
* @param {LH.Result} lhr
|
|
89
61
|
* @return {string}
|
|
90
62
|
*/
|
|
91
63
|
static generateReportCSV(lhr) {
|
|
@@ -122,8 +94,8 @@ class ReportGenerator {
|
|
|
122
94
|
|
|
123
95
|
/**
|
|
124
96
|
* Creates the results output in a format based on the `mode`.
|
|
125
|
-
* @param {
|
|
126
|
-
* @param {
|
|
97
|
+
* @param {LH.Result} lhr
|
|
98
|
+
* @param {LH.Config.Settings['output']} outputModes
|
|
127
99
|
* @return {string|string[]}
|
|
128
100
|
*/
|
|
129
101
|
static generateReport(lhr, outputModes) {
|
|
@@ -7,9 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import {strict as assert} from 'assert';
|
|
9
9
|
import fs from 'fs';
|
|
10
|
-
|
|
11
10
|
import jsdom from 'jsdom';
|
|
12
|
-
|
|
13
11
|
import testUtils from '../../../lighthouse-core/test/test-utils.js';
|
|
14
12
|
import {prepareLabData} from '../../clients/psi.js';
|
|
15
13
|
import {Util} from '../../renderer/util.js';
|
|
@@ -29,7 +27,7 @@ const sampleResultsStr =
|
|
|
29
27
|
|
|
30
28
|
/* eslint-env jest */
|
|
31
29
|
|
|
32
|
-
describe('
|
|
30
|
+
describe('DOM', () => {
|
|
33
31
|
let document;
|
|
34
32
|
beforeAll(() => {
|
|
35
33
|
global.Util = Util;
|
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
/* eslint-env jest */
|
|
8
|
+
/* eslint-env jest, browser */
|
|
9
9
|
|
|
10
10
|
import {strict as assert} from 'assert';
|
|
11
11
|
|
|
12
12
|
import jsdom from 'jsdom';
|
|
13
|
-
|
|
14
13
|
import {Util} from '../../renderer/util.js';
|
|
15
14
|
import {I18n} from '../../renderer/i18n.js';
|
|
16
15
|
import {DOM} from '../../renderer/dom.js';
|
|
@@ -256,9 +255,7 @@ describe('CategoryRenderer', () => {
|
|
|
256
255
|
const categoryDOM = renderer.render(a11yCategory, sampleResults.categoryGroups);
|
|
257
256
|
const percentageEl = categoryDOM.querySelectorAll('.lh-gauge__percentage');
|
|
258
257
|
|
|
259
|
-
|
|
260
|
-
assert(!scoreText.includes('.'), 'score is integer');
|
|
261
|
-
assert(Number(scoreText) >= 0 && Number(scoreText) <= 100, 'score is 0-100');
|
|
258
|
+
assert.equal(percentageEl[0].textContent, '81', 'score shows a non-dash value');
|
|
262
259
|
});
|
|
263
260
|
});
|
|
264
261
|
|
|
@@ -273,9 +270,7 @@ describe('CategoryRenderer', () => {
|
|
|
273
270
|
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
274
271
|
|
|
275
272
|
const gauge = categoryDOM.querySelector('.lh-gauge__percentage');
|
|
276
|
-
|
|
277
|
-
assert(!scoreText.includes('.'), 'score is integer');
|
|
278
|
-
assert(Number(scoreText) >= 0 && Number(scoreText) <= 100, 'score is 0-100');
|
|
273
|
+
assert.equal(gauge.textContent.trim(), '81', 'score is 0-100');
|
|
279
274
|
|
|
280
275
|
const score = categoryDOM.querySelector('.lh-category-header');
|
|
281
276
|
const value = categoryDOM.querySelector('.lh-gauge__percentage');
|
|
@@ -8,10 +8,8 @@
|
|
|
8
8
|
/* eslint-env jest */
|
|
9
9
|
|
|
10
10
|
import fs from 'fs';
|
|
11
|
-
|
|
12
11
|
import jsdom from 'jsdom';
|
|
13
12
|
import expect from 'expect';
|
|
14
|
-
|
|
15
13
|
import {DOM} from '../../renderer/dom.js';
|
|
16
14
|
import {LH_ROOT} from '../../../root.js';
|
|
17
15
|
import {normalizeTextNodeText} from '../../../build/build-report-components.js';
|
|
@@ -85,39 +83,6 @@ async function assertDOMTreeMatches(tmplEl) {
|
|
|
85
83
|
}
|
|
86
84
|
}
|
|
87
85
|
|
|
88
|
-
const originalCreateElement = DOM.prototype.createElement;
|
|
89
|
-
const originalCreateElementNS = DOM.prototype.createElementNS;
|
|
90
|
-
beforeAll(() => {
|
|
91
|
-
/**
|
|
92
|
-
* @param {string} classNames
|
|
93
|
-
*/
|
|
94
|
-
function checkPrefix(classNames) {
|
|
95
|
-
if (!classNames) return;
|
|
96
|
-
|
|
97
|
-
for (const className of classNames.split(' ')) {
|
|
98
|
-
if (!className.startsWith('lh-')) {
|
|
99
|
-
throw new Error(`expected classname to start with lh-, got: ${className}`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
DOM.prototype.createElement = function(...args) {
|
|
105
|
-
const classNames = args[1];
|
|
106
|
-
checkPrefix(classNames);
|
|
107
|
-
return originalCreateElement.call(this, ...args);
|
|
108
|
-
};
|
|
109
|
-
DOM.prototype.createElementNS = function(...args) {
|
|
110
|
-
const classNames = args[2];
|
|
111
|
-
checkPrefix(classNames);
|
|
112
|
-
return originalCreateElementNS.call(this, ...args);
|
|
113
|
-
};
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
afterAll(() => {
|
|
117
|
-
DOM.prototype.createElement = originalCreateElement;
|
|
118
|
-
DOM.prototype.createElementNS = originalCreateElementNS;
|
|
119
|
-
});
|
|
120
|
-
|
|
121
86
|
for (const tmpEl of tmplEls) {
|
|
122
87
|
it(`${tmpEl.id} component matches HTML source`, async () => {
|
|
123
88
|
await assertDOMTreeMatches(tmpEl);
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
import {strict as assert} from 'assert';
|
|
11
11
|
|
|
12
12
|
import jsdom from 'jsdom';
|
|
13
|
-
|
|
14
13
|
import {Util} from '../../renderer/util.js';
|
|
15
14
|
import {I18n} from '../../renderer/i18n.js';
|
|
16
15
|
import {DOM} from '../../renderer/dom.js';
|
|
@@ -89,7 +88,7 @@ describe('DetailsRenderer', () => {
|
|
|
89
88
|
|
|
90
89
|
it('renders tree structure', () => {
|
|
91
90
|
const el = CriticalRequestChainRenderer.render(dom, DETAILS, detailsRenderer);
|
|
92
|
-
const chains = el.querySelectorAll('.
|
|
91
|
+
const chains = el.querySelectorAll('.crc-node');
|
|
93
92
|
|
|
94
93
|
// Main request
|
|
95
94
|
assert.equal(chains.length, 4, 'generates correct number of chain nodes');
|
|
@@ -100,14 +99,14 @@ describe('DetailsRenderer', () => {
|
|
|
100
99
|
assert.equal(chains[0].querySelector('.lh-text__url a').target, '_blank');
|
|
101
100
|
|
|
102
101
|
// Children
|
|
103
|
-
assert.ok(chains[1].querySelector('.
|
|
104
|
-
assert.equal(chains[1].querySelectorAll('.
|
|
102
|
+
assert.ok(chains[1].querySelector('.crc-node__tree-marker .vert-right'));
|
|
103
|
+
assert.equal(chains[1].querySelectorAll('.crc-node__tree-marker .right').length, 2);
|
|
105
104
|
assert.equal(chains[1].querySelector('.lh-text__url a').textContent, '/b.js');
|
|
106
105
|
assert.equal(chains[1].querySelector('.lh-text__url a').href, 'https://example.com/b.js');
|
|
107
106
|
assert.equal(chains[1].querySelector('.lh-text__url a').rel, 'noopener');
|
|
108
107
|
assert.equal(chains[1].querySelector('.lh-text__url a').target, '_blank');
|
|
109
108
|
assert.equal(chains[1].querySelector('.lh-text__url-host').textContent, '(example.com)');
|
|
110
|
-
const durationNodes = chains[1].querySelectorAll('.
|
|
109
|
+
const durationNodes = chains[1].querySelectorAll('.crc-node__chain-duration');
|
|
111
110
|
assert.equal(durationNodes[0].textContent, ' - 5,000\xa0ms, ');
|
|
112
111
|
// Note: actual transferSize is 2000 bytes but formatter formats to KiBs.
|
|
113
112
|
assert.equal(durationNodes[1].textContent, '1.95\xa0KiB');
|
|
@@ -6,9 +6,7 @@
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
8
|
import {strict as assert} from 'assert';
|
|
9
|
-
|
|
10
9
|
import jsdom from 'jsdom';
|
|
11
|
-
|
|
12
10
|
import {DOM} from '../../renderer/dom.js';
|
|
13
11
|
import {Util} from '../../renderer/util.js';
|
|
14
12
|
import {I18n} from '../../renderer/i18n.js';
|
|
@@ -111,7 +109,7 @@ describe('DetailsRenderer', () => {
|
|
|
111
109
|
|
|
112
110
|
const crcEl = renderer.render(details);
|
|
113
111
|
assert.ok(crcEl.classList.contains('lh-crc-container'));
|
|
114
|
-
assert.strictEqual(crcEl.querySelectorAll('.
|
|
112
|
+
assert.strictEqual(crcEl.querySelectorAll('.crc-node').length, 1);
|
|
115
113
|
});
|
|
116
114
|
|
|
117
115
|
it('renders opportunity details as a table', () => {
|
|
@@ -6,10 +6,9 @@
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
8
|
import {strict as assert} from 'assert';
|
|
9
|
-
|
|
10
9
|
import {jest} from '@jest/globals';
|
|
11
|
-
import jsdom from 'jsdom';
|
|
12
10
|
|
|
11
|
+
import jsdom from 'jsdom';
|
|
13
12
|
import {DOM} from '../../renderer/dom.js';
|
|
14
13
|
import {Util} from '../../renderer/util.js';
|
|
15
14
|
import {I18n} from '../../renderer/i18n.js';
|
|
@@ -20,16 +19,16 @@ describe('DOM', () => {
|
|
|
20
19
|
/** @type {DOM} */
|
|
21
20
|
let dom;
|
|
22
21
|
let window;
|
|
23
|
-
let nativeCreateObjectURL;
|
|
24
22
|
|
|
25
23
|
beforeAll(() => {
|
|
26
24
|
Util.i18n = new I18n('en', {...Util.UIStrings});
|
|
27
25
|
window = new jsdom.JSDOM().window;
|
|
28
26
|
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
// Make a lame "polyfill" since JSDOM doesn't have createObjectURL: https://github.com/jsdom/jsdom/issues/1721
|
|
28
|
+
const lameCOURL = jest.fn(_ => `https://fake-origin/blahblah-blobid`);
|
|
29
|
+
if (!URL.createObjectURL) {
|
|
30
|
+
URL.createObjectURL = lameCOURL;
|
|
31
|
+
}
|
|
33
32
|
|
|
34
33
|
dom = new DOM(window.document);
|
|
35
34
|
dom.setLighthouseChannel('someChannel');
|
|
@@ -37,7 +36,6 @@ describe('DOM', () => {
|
|
|
37
36
|
|
|
38
37
|
afterAll(() => {
|
|
39
38
|
Util.i18n = undefined;
|
|
40
|
-
URL.createObjectURL = nativeCreateObjectURL;
|
|
41
39
|
});
|
|
42
40
|
|
|
43
41
|
describe('createElement', () => {
|
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
/* eslint-env jest */
|
|
8
|
+
/* eslint-env jest, browser */
|
|
9
9
|
|
|
10
10
|
import {strict as assert} from 'assert';
|
|
11
11
|
|
|
12
12
|
import jsdom from 'jsdom';
|
|
13
|
-
|
|
14
13
|
import {Util} from '../../renderer/util.js';
|
|
15
14
|
import {I18n} from '../../renderer/i18n.js';
|
|
16
15
|
import URL from '../../../lighthouse-core/lib/url-shim.js';
|
|
@@ -88,11 +87,9 @@ describe('PerfCategoryRenderer', () => {
|
|
|
88
87
|
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
89
88
|
|
|
90
89
|
const oppAudits = category.auditRefs.filter(audit => audit.group === 'load-opportunities' &&
|
|
91
|
-
|
|
92
|
-
const oppElements =
|
|
93
|
-
|
|
94
|
-
expect(oppElements.length).toBeGreaterThan(0);
|
|
95
|
-
expect(oppElements.length).toMatchInlineSnapshot('7');
|
|
90
|
+
audit.result.score !== 1 && audit.result.scoreDisplayMode !== 'notApplicable');
|
|
91
|
+
const oppElements = categoryDOM.querySelectorAll('.lh-audit--load-opportunity');
|
|
92
|
+
assert.equal(oppElements.length, oppAudits.length);
|
|
96
93
|
|
|
97
94
|
const oppElement = oppElements[0];
|
|
98
95
|
const oppSparklineBarElement = oppElement.querySelector('.lh-sparkline__bar');
|
|
@@ -117,7 +114,7 @@ describe('PerfCategoryRenderer', () => {
|
|
|
117
114
|
|
|
118
115
|
const fakeCategory = Object.assign({}, category, {auditRefs: [auditWithError]});
|
|
119
116
|
const categoryDOM = renderer.render(fakeCategory, sampleResults.categoryGroups);
|
|
120
|
-
const tooltipEl = categoryDOM.querySelector('.lh-audit--load-opportunity .
|
|
117
|
+
const tooltipEl = categoryDOM.querySelector('.lh-audit--load-opportunity .tooltip--error');
|
|
121
118
|
assert.ok(tooltipEl, 'did not render error message');
|
|
122
119
|
assert.ok(/Yikes!!/.test(tooltipEl.textContent));
|
|
123
120
|
});
|
|
@@ -242,16 +239,16 @@ describe('PerfCategoryRenderer', () => {
|
|
|
242
239
|
const href = renderer._getScoringCalculatorHref(categoryClone.auditRefs);
|
|
243
240
|
const url = new URL(href);
|
|
244
241
|
expect(url.hash.split('&')).toMatchInlineSnapshot(`
|
|
245
|
-
Array [
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
]
|
|
254
|
-
`);
|
|
242
|
+
Array [
|
|
243
|
+
"#FCP=3969",
|
|
244
|
+
"SI=4417",
|
|
245
|
+
"LCP=4927",
|
|
246
|
+
"TTI=4927",
|
|
247
|
+
"TBT=117",
|
|
248
|
+
"CLS=0",
|
|
249
|
+
"FMP=3969",
|
|
250
|
+
]
|
|
251
|
+
`);
|
|
255
252
|
});
|
|
256
253
|
|
|
257
254
|
it('also appends device and version number', () => {
|
|
@@ -263,18 +260,18 @@ Array [
|
|
|
263
260
|
const url = new URL(href);
|
|
264
261
|
try {
|
|
265
262
|
expect(url.hash.split('&')).toMatchInlineSnapshot(`
|
|
266
|
-
Array [
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
]
|
|
277
|
-
`);
|
|
263
|
+
Array [
|
|
264
|
+
"#FCP=3969",
|
|
265
|
+
"SI=4417",
|
|
266
|
+
"LCP=4927",
|
|
267
|
+
"TTI=4927",
|
|
268
|
+
"TBT=117",
|
|
269
|
+
"CLS=0.42",
|
|
270
|
+
"FMP=3969",
|
|
271
|
+
"device=mobile",
|
|
272
|
+
"version=6.0.0",
|
|
273
|
+
]
|
|
274
|
+
`);
|
|
278
275
|
} finally {
|
|
279
276
|
Util.reportJson = null;
|
|
280
277
|
}
|
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
/* eslint-env jest */
|
|
8
|
+
/* eslint-env jest, browser */
|
|
9
9
|
|
|
10
10
|
import {strict as assert} from 'assert';
|
|
11
11
|
|
|
12
12
|
import jsdom from 'jsdom';
|
|
13
|
-
|
|
14
13
|
import {Util} from '../../renderer/util.js';
|
|
15
14
|
import {I18n} from '../../renderer/i18n.js';
|
|
16
15
|
import {DOM} from '../../renderer/dom.js';
|
|
@@ -8,10 +8,8 @@
|
|
|
8
8
|
/* eslint-env jest */
|
|
9
9
|
|
|
10
10
|
import {strict as assert} from 'assert';
|
|
11
|
-
|
|
12
11
|
import jsdom from 'jsdom';
|
|
13
|
-
|
|
14
|
-
import reportAssets from '../../generator/report-assets.js';
|
|
12
|
+
import reportAssets from '../../report-assets.js';
|
|
15
13
|
import {Util} from '../../renderer/util.js';
|
|
16
14
|
import {DOM} from '../../renderer/dom.js';
|
|
17
15
|
import {DetailsRenderer} from '../../renderer/details-renderer.js';
|
|
@@ -159,6 +157,16 @@ describe('ReportUIFeatures', () => {
|
|
|
159
157
|
},
|
|
160
158
|
},
|
|
161
159
|
];
|
|
160
|
+
// Sample json currently doesn't have any results for `unused-javascript`, so
|
|
161
|
+
// headings is empty. Can delete this block of code if that changes.
|
|
162
|
+
expect(lhr.audits['unused-javascript'].details.headings).toHaveLength(0);
|
|
163
|
+
lhr.audits['unused-javascript'].details.headings = [
|
|
164
|
+
/* t-disable max-len */
|
|
165
|
+
{key: 'url', valueType: 'url', subItemsHeading: {key: 'source', valueType: 'code'}},
|
|
166
|
+
{key: 'totalBytes', valueType: 'bytes', subItemsHeading: {key: 'sourceBytes'}},
|
|
167
|
+
{key: 'wastedBytes', valueType: 'bytes', subItemsHeading: {key: 'sourceWastedBytes'}},
|
|
168
|
+
/* eslint-enable max-len */
|
|
169
|
+
];
|
|
162
170
|
|
|
163
171
|
// Only third party URLs to test that checkbox is hidden
|
|
164
172
|
lhr.audits['render-blocking-resources'].details.items = [
|
|
@@ -276,7 +284,7 @@ describe('ReportUIFeatures', () => {
|
|
|
276
284
|
const lhr = JSON.parse(JSON.stringify(sampleResults));
|
|
277
285
|
lhr.categories.performance.score = 0.5;
|
|
278
286
|
const container = render(lhr);
|
|
279
|
-
assert.ok(container.querySelector('.
|
|
287
|
+
assert.ok(container.querySelector('.score100') === null, 'has no fireworks treatment');
|
|
280
288
|
});
|
|
281
289
|
|
|
282
290
|
it('should render an all 100 report with fireworks', () => {
|
|
@@ -285,7 +293,7 @@ describe('ReportUIFeatures', () => {
|
|
|
285
293
|
element.score = 1;
|
|
286
294
|
});
|
|
287
295
|
const container = render(lhr);
|
|
288
|
-
assert.ok(container.querySelector('.
|
|
296
|
+
assert.ok(container.querySelector('.score100'), 'has fireworks treatment');
|
|
289
297
|
});
|
|
290
298
|
|
|
291
299
|
it('should show fireworks for all 100s except PWA', () => {
|
|
@@ -296,7 +304,7 @@ describe('ReportUIFeatures', () => {
|
|
|
296
304
|
lhr.categories.pwa.score = 0;
|
|
297
305
|
|
|
298
306
|
const container = render(lhr);
|
|
299
|
-
assert.ok(container.querySelector('.
|
|
307
|
+
assert.ok(container.querySelector('.score100'), 'has fireworks treatment');
|
|
300
308
|
});
|
|
301
309
|
|
|
302
310
|
it('should not render fireworks if all core categories are not present', () => {
|
|
@@ -307,7 +315,7 @@ describe('ReportUIFeatures', () => {
|
|
|
307
315
|
element.score = 1;
|
|
308
316
|
});
|
|
309
317
|
const container = render(lhr);
|
|
310
|
-
assert.ok(container.querySelector('.
|
|
318
|
+
assert.ok(container.querySelector('.score100') === null, 'has no fireworks treatment');
|
|
311
319
|
});
|
|
312
320
|
});
|
|
313
321
|
|
|
@@ -334,32 +342,32 @@ describe('ReportUIFeatures', () => {
|
|
|
334
342
|
window = dom.document().defaultView;
|
|
335
343
|
const features = new ReportUIFeatures(dom);
|
|
336
344
|
features.initFeatures(sampleResults);
|
|
337
|
-
dropDown = features.
|
|
345
|
+
dropDown = features._dropDown;
|
|
338
346
|
});
|
|
339
347
|
|
|
340
348
|
it('click should toggle active class', () => {
|
|
341
349
|
dropDown._toggleEl.click();
|
|
342
|
-
assert.ok(dropDown._toggleEl.classList.contains('
|
|
350
|
+
assert.ok(dropDown._toggleEl.classList.contains('active'));
|
|
343
351
|
|
|
344
352
|
dropDown._toggleEl.click();
|
|
345
|
-
assert.ok(!dropDown._toggleEl.classList.contains('
|
|
353
|
+
assert.ok(!dropDown._toggleEl.classList.contains('active'));
|
|
346
354
|
});
|
|
347
355
|
|
|
348
356
|
|
|
349
357
|
it('Escape key removes active class', () => {
|
|
350
358
|
dropDown._toggleEl.click();
|
|
351
|
-
assert.ok(dropDown._toggleEl.classList.contains('
|
|
359
|
+
assert.ok(dropDown._toggleEl.classList.contains('active'));
|
|
352
360
|
|
|
353
361
|
const escape = new window.KeyboardEvent('keydown', {keyCode: /* ESC */ 27});
|
|
354
362
|
dom.document().dispatchEvent(escape);
|
|
355
|
-
assert.ok(!dropDown._toggleEl.classList.contains('
|
|
363
|
+
assert.ok(!dropDown._toggleEl.classList.contains('active'));
|
|
356
364
|
});
|
|
357
365
|
|
|
358
366
|
['ArrowUp', 'ArrowDown', 'Enter', ' '].forEach((code) => {
|
|
359
367
|
it(`'${code}' adds active class`, () => {
|
|
360
368
|
const event = new window.KeyboardEvent('keydown', {code});
|
|
361
369
|
dropDown._toggleEl.dispatchEvent(event);
|
|
362
|
-
assert.ok(dropDown._toggleEl.classList.contains('
|
|
370
|
+
assert.ok(dropDown._toggleEl.classList.contains('active'));
|
|
363
371
|
});
|
|
364
372
|
});
|
|
365
373
|
|
|
@@ -471,14 +479,14 @@ describe('ReportUIFeatures', () => {
|
|
|
471
479
|
describe('onMenuFocusOut', () => {
|
|
472
480
|
beforeEach(() => {
|
|
473
481
|
dropDown._toggleEl.click();
|
|
474
|
-
assert.ok(dropDown._toggleEl.classList.contains('
|
|
482
|
+
assert.ok(dropDown._toggleEl.classList.contains('active'));
|
|
475
483
|
});
|
|
476
484
|
|
|
477
485
|
it('should toggle active class when focus relatedTarget is null', () => {
|
|
478
486
|
const event = new window.FocusEvent('focusout', {relatedTarget: null});
|
|
479
487
|
dropDown.onMenuFocusOut(event);
|
|
480
488
|
|
|
481
|
-
assert.ok(!dropDown._toggleEl.classList.contains('
|
|
489
|
+
assert.ok(!dropDown._toggleEl.classList.contains('active'));
|
|
482
490
|
});
|
|
483
491
|
|
|
484
492
|
it('should toggle active class when focus relatedTarget is document.body', () => {
|
|
@@ -486,7 +494,7 @@ describe('ReportUIFeatures', () => {
|
|
|
486
494
|
const event = new window.FocusEvent('focusout', {relatedTarget});
|
|
487
495
|
dropDown.onMenuFocusOut(event);
|
|
488
496
|
|
|
489
|
-
assert.ok(!dropDown._toggleEl.classList.contains('
|
|
497
|
+
assert.ok(!dropDown._toggleEl.classList.contains('active'));
|
|
490
498
|
});
|
|
491
499
|
|
|
492
500
|
it('should toggle active class when focus relatedTarget is _toggleEl', () => {
|
|
@@ -494,7 +502,7 @@ describe('ReportUIFeatures', () => {
|
|
|
494
502
|
const event = new window.FocusEvent('focusout', {relatedTarget});
|
|
495
503
|
dropDown.onMenuFocusOut(event);
|
|
496
504
|
|
|
497
|
-
assert.ok(!dropDown._toggleEl.classList.contains('
|
|
505
|
+
assert.ok(!dropDown._toggleEl.classList.contains('active'));
|
|
498
506
|
});
|
|
499
507
|
|
|
500
508
|
it('should not toggle active class when focus relatedTarget is a menu item', () => {
|
|
@@ -502,7 +510,7 @@ describe('ReportUIFeatures', () => {
|
|
|
502
510
|
const event = new window.FocusEvent('focusout', {relatedTarget});
|
|
503
511
|
dropDown.onMenuFocusOut(event);
|
|
504
512
|
|
|
505
|
-
assert.ok(dropDown._toggleEl.classList.contains('
|
|
513
|
+
assert.ok(dropDown._toggleEl.classList.contains('active'));
|
|
506
514
|
});
|
|
507
515
|
});
|
|
508
516
|
});
|
|
@@ -512,10 +520,10 @@ describe('ReportUIFeatures', () => {
|
|
|
512
520
|
const lhr = JSON.parse(JSON.stringify(sampleResults));
|
|
513
521
|
|
|
514
522
|
expect(lhr.audits['script-treemap-data']).not.toBeUndefined();
|
|
515
|
-
expect(render(lhr).querySelector('.lh-button.
|
|
523
|
+
expect(render(lhr).querySelector('.lh-button.report-icon--treemap')).toBeTruthy();
|
|
516
524
|
|
|
517
525
|
delete lhr.audits['script-treemap-data'];
|
|
518
|
-
expect(render(lhr).querySelector('.lh-button.
|
|
526
|
+
expect(render(lhr).querySelector('.lh-button.report-icon--treemap')).toBeNull();
|
|
519
527
|
});
|
|
520
528
|
});
|
|
521
529
|
|