lighthouse 8.3.0-dev.20210904 → 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.
Files changed (196) hide show
  1. package/changelog.md +1 -1
  2. package/dist/report/standalone.js +196 -0
  3. package/jest.config.js +0 -4
  4. package/lighthouse-cli/cli-flags.js +6 -14
  5. package/lighthouse-cli/run.js +1 -1
  6. package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +3 -9
  7. package/lighthouse-cli/test/smokehouse/report-assert.js +16 -36
  8. package/lighthouse-core/audits/large-javascript-libraries.js +166 -0
  9. package/lighthouse-core/audits/seo/http-status-code.js +6 -2
  10. package/lighthouse-core/audits/viewport.js +1 -2
  11. package/lighthouse-core/config/config-helpers.js +75 -9
  12. package/lighthouse-core/config/config.js +50 -6
  13. package/lighthouse-core/config/constants.js +0 -1
  14. package/lighthouse-core/config/default-config.js +0 -3
  15. package/lighthouse-core/config/experimental-config.js +8 -0
  16. package/lighthouse-core/config/metrics-to-audits.js +0 -1
  17. package/lighthouse-core/fraggle-rock/config/config.js +4 -3
  18. package/lighthouse-core/fraggle-rock/config/default-config.js +1 -3
  19. package/lighthouse-core/fraggle-rock/config/validation.js +0 -201
  20. package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +0 -4
  21. package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +8 -16
  22. package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +0 -4
  23. package/lighthouse-core/fraggle-rock/gather/session.js +5 -30
  24. package/lighthouse-core/gather/driver/navigation.js +6 -7
  25. package/lighthouse-core/gather/driver/wait-for-condition.js +0 -27
  26. package/lighthouse-core/gather/fetcher.js +7 -17
  27. package/lighthouse-core/gather/gather-runner.js +0 -1
  28. package/lighthouse-core/gather/gatherers/seo/robots-txt.js +6 -2
  29. package/lighthouse-core/gather/gatherers/seo/tap-targets.js +2 -2
  30. package/lighthouse-core/gather/gatherers/stacks.js +1 -1
  31. package/lighthouse-core/lib/asset-saver.js +2 -2
  32. package/lighthouse-core/lib/cdt/SDK.js +0 -1
  33. package/lighthouse-core/lib/csp-evaluator.js +4 -17
  34. package/{report/generator → lighthouse-core/lib}/file-namer.js +0 -0
  35. package/lighthouse-core/lib/i18n/README.md +1 -1
  36. package/lighthouse-core/lib/i18n/i18n.js +7 -7
  37. package/lighthouse-core/lib/i18n/locales/ar-XB.json +18 -0
  38. package/lighthouse-core/lib/i18n/locales/ar.json +18 -0
  39. package/lighthouse-core/lib/i18n/locales/bg.json +18 -0
  40. package/lighthouse-core/lib/i18n/locales/ca.json +18 -0
  41. package/lighthouse-core/lib/i18n/locales/cs.json +18 -0
  42. package/lighthouse-core/lib/i18n/locales/da.json +18 -0
  43. package/lighthouse-core/lib/i18n/locales/de.json +18 -0
  44. package/lighthouse-core/lib/i18n/locales/el.json +18 -0
  45. package/lighthouse-core/lib/i18n/locales/en-GB.json +18 -0
  46. package/lighthouse-core/lib/i18n/locales/en-US.json +18 -18
  47. package/lighthouse-core/lib/i18n/locales/en-XA.json +18 -0
  48. package/lighthouse-core/lib/i18n/locales/en-XL.json +18 -18
  49. package/lighthouse-core/lib/i18n/locales/es-419.json +18 -0
  50. package/lighthouse-core/lib/i18n/locales/es.json +18 -0
  51. package/lighthouse-core/lib/i18n/locales/fi.json +18 -0
  52. package/lighthouse-core/lib/i18n/locales/fil.json +18 -0
  53. package/lighthouse-core/lib/i18n/locales/fr.json +18 -0
  54. package/lighthouse-core/lib/i18n/locales/he.json +18 -0
  55. package/lighthouse-core/lib/i18n/locales/hi.json +18 -0
  56. package/lighthouse-core/lib/i18n/locales/hr.json +18 -0
  57. package/lighthouse-core/lib/i18n/locales/hu.json +18 -0
  58. package/lighthouse-core/lib/i18n/locales/id.json +18 -0
  59. package/lighthouse-core/lib/i18n/locales/it.json +18 -0
  60. package/lighthouse-core/lib/i18n/locales/ja.json +18 -0
  61. package/lighthouse-core/lib/i18n/locales/ko.json +18 -0
  62. package/lighthouse-core/lib/i18n/locales/lt.json +18 -0
  63. package/lighthouse-core/lib/i18n/locales/lv.json +18 -0
  64. package/lighthouse-core/lib/i18n/locales/nl.json +18 -0
  65. package/lighthouse-core/lib/i18n/locales/no.json +18 -0
  66. package/lighthouse-core/lib/i18n/locales/pl.json +18 -0
  67. package/lighthouse-core/lib/i18n/locales/pt-PT.json +18 -0
  68. package/lighthouse-core/lib/i18n/locales/pt.json +18 -0
  69. package/lighthouse-core/lib/i18n/locales/ro.json +18 -0
  70. package/lighthouse-core/lib/i18n/locales/ru.json +18 -0
  71. package/lighthouse-core/lib/i18n/locales/sk.json +18 -0
  72. package/lighthouse-core/lib/i18n/locales/sl.json +18 -0
  73. package/lighthouse-core/lib/i18n/locales/sr-Latn.json +18 -0
  74. package/lighthouse-core/lib/i18n/locales/sr.json +18 -0
  75. package/lighthouse-core/lib/i18n/locales/sv.json +18 -0
  76. package/lighthouse-core/lib/i18n/locales/ta.json +18 -0
  77. package/lighthouse-core/lib/i18n/locales/te.json +18 -0
  78. package/lighthouse-core/lib/i18n/locales/th.json +18 -0
  79. package/lighthouse-core/lib/i18n/locales/tr.json +18 -0
  80. package/lighthouse-core/lib/i18n/locales/uk.json +18 -0
  81. package/lighthouse-core/lib/i18n/locales/vi.json +18 -0
  82. package/lighthouse-core/lib/i18n/locales/zh-HK.json +18 -0
  83. package/lighthouse-core/lib/i18n/locales/zh-TW.json +18 -0
  84. package/lighthouse-core/lib/i18n/locales/zh.json +18 -0
  85. package/lighthouse-core/lib/large-javascript-libraries/bundlephobia-database.json +62 -0
  86. package/lighthouse-core/lib/large-javascript-libraries/library-suggestions.js +20 -0
  87. package/lighthouse-core/lib/network-request.js +1 -3
  88. package/lighthouse-core/lib/traces/pwmetrics-events.js +2 -2
  89. package/lighthouse-core/lib/url-shim.js +1 -7
  90. package/lighthouse-core/runner.js +1 -4
  91. package/lighthouse-core/util-commonjs.js +2 -2
  92. package/now.json +1 -1
  93. package/package.json +13 -20
  94. package/report/README.md +2 -2
  95. package/report/assets/standalone-template.html +1 -0
  96. package/report/assets/styles.css +27 -23
  97. package/report/assets/templates.html +40 -37
  98. package/report/clients/bundle.js +0 -1
  99. package/report/{package.json → clients/package.json} +0 -0
  100. package/report/clients/psi.js +3 -13
  101. package/report/clients/standalone.js +1 -1
  102. package/report/{types/buffer.d.ts → clients/treemap.js} +13 -11
  103. package/report/renderer/category-renderer.js +2 -2
  104. package/report/renderer/components.js +48 -46
  105. package/report/renderer/crc-details-renderer.js +16 -16
  106. package/report/renderer/details-renderer.js +1 -1
  107. package/report/renderer/dom.js +0 -17
  108. package/report/renderer/element-screenshot-renderer.js +9 -9
  109. package/{flow-report/test/setup/global-setup.ts → report/renderer/file-namer.js} +2 -5
  110. package/report/renderer/logger.js +4 -4
  111. package/report/renderer/package.json +4 -0
  112. package/report/renderer/report-renderer.js +11 -4
  113. package/report/renderer/report-ui-features.js +656 -43
  114. package/report/renderer/text-encoding.js +1 -1
  115. package/report/renderer/util.js +2 -2
  116. package/report/{generator/report-assets.js → report-assets.js} +3 -9
  117. package/report/{generator/report-generator.js → report-generator.js} +9 -37
  118. package/report/test/clients/package.json +4 -0
  119. package/report/test/clients/psi-test.js +1 -3
  120. package/report/test/renderer/category-renderer-test.js +1 -2
  121. package/report/test/renderer/components-test.js +0 -35
  122. package/report/test/renderer/crc-details-renderer-test.js +4 -5
  123. package/report/test/renderer/details-renderer-test.js +1 -3
  124. package/report/test/renderer/dom-test.js +6 -8
  125. package/report/test/renderer/i18n-test.js +0 -1
  126. package/report/test/renderer/package.json +4 -0
  127. package/report/test/renderer/performance-category-renderer-test.js +2 -3
  128. package/report/test/renderer/pwa-category-renderer-test.js +1 -2
  129. package/report/test/renderer/report-renderer-test.js +0 -1
  130. package/report/test/renderer/report-ui-features-test.js +18 -20
  131. package/report/test/renderer/snippet-renderer-test.js +0 -1
  132. package/report/test/renderer/text-encoding-test.js +0 -2
  133. package/report/test/renderer/util-test.js +0 -1
  134. package/report/test/{generator/report-generator-test.js → report-generator-test.js} +2 -4
  135. package/third-party/chromium-synchronization/installability-errors-test.js +27 -28
  136. package/third-party/snyk/snapshot.json +0 -2
  137. package/tsconfig.json +5 -24
  138. package/types/artifacts.d.ts +18 -5
  139. package/types/{lhr/audit-details.d.ts → audit-details.d.ts} +3 -18
  140. package/types/audit.d.ts +58 -7
  141. package/types/{lhr/budget.d.ts → budget.d.ts} +0 -0
  142. package/types/bundle-phobia-cli/index.d.ts +40 -0
  143. package/types/config.d.ts +8 -3
  144. package/types/externs.d.ts +119 -5
  145. package/types/gatherer.d.ts +2 -3
  146. package/types/global-lh.d.ts +14 -16
  147. package/{report/types/report-result.d.ts → types/html-renderer.d.ts} +17 -8
  148. package/types/{lhr/i18n.d.ts → i18n.d.ts} +25 -2
  149. package/types/{lhr/lhr.d.ts → lhr.d.ts} +9 -41
  150. package/types/smokehouse.d.ts +3 -3
  151. package/types/{lhr/treemap.d.ts → treemap.d.ts} +3 -3
  152. package/flow-report/assets/standalone-flow-template.html +0 -38
  153. package/flow-report/assets/styles.css +0 -310
  154. package/flow-report/jest.config.js +0 -24
  155. package/flow-report/src/app.tsx +0 -40
  156. package/flow-report/src/common.tsx +0 -72
  157. package/flow-report/src/icons.tsx +0 -96
  158. package/flow-report/src/sidebar/flow.tsx +0 -72
  159. package/flow-report/src/sidebar/sidebar.tsx +0 -89
  160. package/flow-report/src/summary/summary.tsx +0 -178
  161. package/flow-report/src/util.ts +0 -160
  162. package/flow-report/src/wrappers/gauge.tsx +0 -40
  163. package/flow-report/src/wrappers/report-renderer.tsx +0 -46
  164. package/flow-report/src/wrappers/report.tsx +0 -71
  165. package/flow-report/standalone-flow.tsx +0 -23
  166. package/flow-report/test/app-test.tsx +0 -48
  167. package/flow-report/test/common-test.tsx +0 -131
  168. package/flow-report/test/setup/env-setup.ts +0 -25
  169. package/flow-report/test/sidebar/flow-test.tsx +0 -71
  170. package/flow-report/test/sidebar/sidebar-test.tsx +0 -53
  171. package/flow-report/test/summary/summary-test.tsx +0 -132
  172. package/flow-report/test/util-test.tsx +0 -109
  173. package/flow-report/tsconfig.json +0 -39
  174. package/flow-report/types/flow-report.d.ts +0 -27
  175. package/lighthouse-core/audits/lcp-lazy-loaded.js +0 -83
  176. package/report/.eslintrc.cjs +0 -33
  177. package/report/generator/README.md +0 -9
  178. package/report/generator/flow-report-assets.js +0 -20
  179. package/report/generator/package.json +0 -4
  180. package/report/generator/tsconfig.json +0 -28
  181. package/report/renderer/drop-down-menu.js +0 -215
  182. package/report/renderer/features-util.js +0 -26
  183. package/report/renderer/open-tab.js +0 -137
  184. package/report/renderer/topbar-features.js +0 -309
  185. package/report/test/generator/file-namer-test.js +0 -28
  186. package/report/test/generator/package.json +0 -4
  187. package/report/test-assets/faux-psi-template.html +0 -126
  188. package/report/test-assets/faux-psi.js +0 -92
  189. package/report/tsconfig.json +0 -39
  190. package/report/types/augment-dom.d.ts +0 -24
  191. package/report/types/html-renderer.d.ts +0 -28
  192. package/types/lhr/audit-result.d.ts +0 -59
  193. package/types/lhr/flow.d.ts +0 -16
  194. package/types/lhr/settings.d.ts +0 -105
  195. package/types/lhr/tsconfig.json +0 -24
  196. package/types/query-selector.d.ts +0 -36
@@ -5,7 +5,7 @@
5
5
  */
6
6
  'use strict';
7
7
 
8
- /* global CompressionStream */
8
+ /* global btoa atob window CompressionStream Response */
9
9
 
10
10
  const btoa_ = typeof btoa !== 'undefined' ?
11
11
  btoa :
@@ -388,7 +388,7 @@ export class Util {
388
388
  }
389
389
 
390
390
  /**
391
- * @param {LH.Result['configSettings']} settings
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.Result['configSettings']} settings
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 flowReportAssets = require('./flow-report-assets.js');
11
-
12
- const REPORT_TEMPLATE = fs.readFileSync(__dirname + '/../assets/standalone-template.html',
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
- * @param {unknown} object
35
- * @return {string}
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 = ReportGenerator.sanitizeJson(lhr);
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 {LHResult} lhr
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 {LHResult} lhr
126
- * @param {LHResult['configSettings']['output']} outputModes
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) {
@@ -0,0 +1,4 @@
1
+ {
2
+ "type": "module",
3
+ "//": "Any directory that uses `import ... from` or `export ...` must be type module. Temporary file until root package.json is type: module"
4
+ }
@@ -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('PSI', () => {
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';
@@ -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('.lh-crc-node');
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('.lh-crc-node__tree-marker .lh-vert-right'));
104
- assert.equal(chains[1].querySelectorAll('.lh-crc-node__tree-marker .lh-right').length, 2);
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('.lh-crc-node__chain-duration');
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('.lh-crc-node').length, 1);
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
- // The Node version of URL.createObjectURL isn't compatible with the jsdom blob type,
30
- // so we stub it.
31
- nativeCreateObjectURL = URL.createObjectURL;
32
- URL.createObjectURL = jest.fn(_ => `https://fake-origin/blahblah-blobid`);
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', () => {
@@ -6,7 +6,6 @@
6
6
  'use strict';
7
7
 
8
8
  import {strict as assert} from 'assert';
9
-
10
9
  import {Util} from '../../renderer/util.js';
11
10
  import {I18n} from '../../renderer/i18n.js';
12
11
  import {isNode12SmallIcu} from '../../../lighthouse-core/test/test-utils.js';
@@ -0,0 +1,4 @@
1
+ {
2
+ "type": "module",
3
+ "//": "Any directory that uses `import ... from` or `export ...` must be type module. Temporary file until root package.json is type: module"
4
+ }
@@ -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';
@@ -115,7 +114,7 @@ describe('PerfCategoryRenderer', () => {
115
114
 
116
115
  const fakeCategory = Object.assign({}, category, {auditRefs: [auditWithError]});
117
116
  const categoryDOM = renderer.render(fakeCategory, sampleResults.categoryGroups);
118
- const tooltipEl = categoryDOM.querySelector('.lh-audit--load-opportunity .lh-tooltip--error');
117
+ const tooltipEl = categoryDOM.querySelector('.lh-audit--load-opportunity .tooltip--error');
119
118
  assert.ok(tooltipEl, 'did not render error message');
120
119
  assert.ok(/Yikes!!/.test(tooltipEl.textContent));
121
120
  });
@@ -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';
@@ -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 URL from '../../../lighthouse-core/lib/url-shim.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';
@@ -286,7 +284,7 @@ describe('ReportUIFeatures', () => {
286
284
  const lhr = JSON.parse(JSON.stringify(sampleResults));
287
285
  lhr.categories.performance.score = 0.5;
288
286
  const container = render(lhr);
289
- assert.ok(container.querySelector('.lh-score100') === null, 'has no fireworks treatment');
287
+ assert.ok(container.querySelector('.score100') === null, 'has no fireworks treatment');
290
288
  });
291
289
 
292
290
  it('should render an all 100 report with fireworks', () => {
@@ -295,7 +293,7 @@ describe('ReportUIFeatures', () => {
295
293
  element.score = 1;
296
294
  });
297
295
  const container = render(lhr);
298
- assert.ok(container.querySelector('.lh-score100'), 'has fireworks treatment');
296
+ assert.ok(container.querySelector('.score100'), 'has fireworks treatment');
299
297
  });
300
298
 
301
299
  it('should show fireworks for all 100s except PWA', () => {
@@ -306,7 +304,7 @@ describe('ReportUIFeatures', () => {
306
304
  lhr.categories.pwa.score = 0;
307
305
 
308
306
  const container = render(lhr);
309
- assert.ok(container.querySelector('.lh-score100'), 'has fireworks treatment');
307
+ assert.ok(container.querySelector('.score100'), 'has fireworks treatment');
310
308
  });
311
309
 
312
310
  it('should not render fireworks if all core categories are not present', () => {
@@ -317,7 +315,7 @@ describe('ReportUIFeatures', () => {
317
315
  element.score = 1;
318
316
  });
319
317
  const container = render(lhr);
320
- assert.ok(container.querySelector('.lh-score100') === null, 'has no fireworks treatment');
318
+ assert.ok(container.querySelector('.score100') === null, 'has no fireworks treatment');
321
319
  });
322
320
  });
323
321
 
@@ -344,32 +342,32 @@ describe('ReportUIFeatures', () => {
344
342
  window = dom.document().defaultView;
345
343
  const features = new ReportUIFeatures(dom);
346
344
  features.initFeatures(sampleResults);
347
- dropDown = features._topbar._dropDownMenu;
345
+ dropDown = features._dropDown;
348
346
  });
349
347
 
350
348
  it('click should toggle active class', () => {
351
349
  dropDown._toggleEl.click();
352
- assert.ok(dropDown._toggleEl.classList.contains('lh-active'));
350
+ assert.ok(dropDown._toggleEl.classList.contains('active'));
353
351
 
354
352
  dropDown._toggleEl.click();
355
- assert.ok(!dropDown._toggleEl.classList.contains('lh-active'));
353
+ assert.ok(!dropDown._toggleEl.classList.contains('active'));
356
354
  });
357
355
 
358
356
 
359
357
  it('Escape key removes active class', () => {
360
358
  dropDown._toggleEl.click();
361
- assert.ok(dropDown._toggleEl.classList.contains('lh-active'));
359
+ assert.ok(dropDown._toggleEl.classList.contains('active'));
362
360
 
363
361
  const escape = new window.KeyboardEvent('keydown', {keyCode: /* ESC */ 27});
364
362
  dom.document().dispatchEvent(escape);
365
- assert.ok(!dropDown._toggleEl.classList.contains('lh-active'));
363
+ assert.ok(!dropDown._toggleEl.classList.contains('active'));
366
364
  });
367
365
 
368
366
  ['ArrowUp', 'ArrowDown', 'Enter', ' '].forEach((code) => {
369
367
  it(`'${code}' adds active class`, () => {
370
368
  const event = new window.KeyboardEvent('keydown', {code});
371
369
  dropDown._toggleEl.dispatchEvent(event);
372
- assert.ok(dropDown._toggleEl.classList.contains('lh-active'));
370
+ assert.ok(dropDown._toggleEl.classList.contains('active'));
373
371
  });
374
372
  });
375
373
 
@@ -481,14 +479,14 @@ describe('ReportUIFeatures', () => {
481
479
  describe('onMenuFocusOut', () => {
482
480
  beforeEach(() => {
483
481
  dropDown._toggleEl.click();
484
- assert.ok(dropDown._toggleEl.classList.contains('lh-active'));
482
+ assert.ok(dropDown._toggleEl.classList.contains('active'));
485
483
  });
486
484
 
487
485
  it('should toggle active class when focus relatedTarget is null', () => {
488
486
  const event = new window.FocusEvent('focusout', {relatedTarget: null});
489
487
  dropDown.onMenuFocusOut(event);
490
488
 
491
- assert.ok(!dropDown._toggleEl.classList.contains('lh-active'));
489
+ assert.ok(!dropDown._toggleEl.classList.contains('active'));
492
490
  });
493
491
 
494
492
  it('should toggle active class when focus relatedTarget is document.body', () => {
@@ -496,7 +494,7 @@ describe('ReportUIFeatures', () => {
496
494
  const event = new window.FocusEvent('focusout', {relatedTarget});
497
495
  dropDown.onMenuFocusOut(event);
498
496
 
499
- assert.ok(!dropDown._toggleEl.classList.contains('lh-active'));
497
+ assert.ok(!dropDown._toggleEl.classList.contains('active'));
500
498
  });
501
499
 
502
500
  it('should toggle active class when focus relatedTarget is _toggleEl', () => {
@@ -504,7 +502,7 @@ describe('ReportUIFeatures', () => {
504
502
  const event = new window.FocusEvent('focusout', {relatedTarget});
505
503
  dropDown.onMenuFocusOut(event);
506
504
 
507
- assert.ok(!dropDown._toggleEl.classList.contains('lh-active'));
505
+ assert.ok(!dropDown._toggleEl.classList.contains('active'));
508
506
  });
509
507
 
510
508
  it('should not toggle active class when focus relatedTarget is a menu item', () => {
@@ -512,7 +510,7 @@ describe('ReportUIFeatures', () => {
512
510
  const event = new window.FocusEvent('focusout', {relatedTarget});
513
511
  dropDown.onMenuFocusOut(event);
514
512
 
515
- assert.ok(dropDown._toggleEl.classList.contains('lh-active'));
513
+ assert.ok(dropDown._toggleEl.classList.contains('active'));
516
514
  });
517
515
  });
518
516
  });
@@ -522,10 +520,10 @@ describe('ReportUIFeatures', () => {
522
520
  const lhr = JSON.parse(JSON.stringify(sampleResults));
523
521
 
524
522
  expect(lhr.audits['script-treemap-data']).not.toBeUndefined();
525
- expect(render(lhr).querySelector('.lh-button.lh-report-icon--treemap')).toBeTruthy();
523
+ expect(render(lhr).querySelector('.lh-button.report-icon--treemap')).toBeTruthy();
526
524
 
527
525
  delete lhr.audits['script-treemap-data'];
528
- expect(render(lhr).querySelector('.lh-button.lh-report-icon--treemap')).toBeNull();
526
+ expect(render(lhr).querySelector('.lh-button.report-icon--treemap')).toBeNull();
529
527
  });
530
528
  });
531
529
 
@@ -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';
@@ -6,9 +6,7 @@
6
6
  'use strict';
7
7
 
8
8
  import fs from 'fs';
9
-
10
9
  import pako from 'pako';
11
-
12
10
  import {TextEncoding} from '../../renderer/text-encoding.js';
13
11
  import {LH_ROOT} from '../../../root.js';
14
12
 
@@ -6,7 +6,6 @@
6
6
  'use strict';
7
7
 
8
8
  import {strict as assert} from 'assert';
9
-
10
9
  import {Util} from '../../renderer/util.js';
11
10
  import {I18n} from '../../renderer/i18n.js';
12
11
  import sampleResult from '../../../lighthouse-core/test/results/sample_v2.json';
@@ -7,12 +7,10 @@
7
7
 
8
8
  const assert = require('assert').strict;
9
9
  const fs = require('fs');
10
-
10
+ const ReportGenerator = require('../report-generator.js');
11
+ const sampleResults = require('../../lighthouse-core/test/results/sample_v2.json');
11
12
  const csvValidator = require('csv-validator');
12
13
 
13
- const ReportGenerator = require('../../generator/report-generator.js');
14
- const sampleResults = require('../../../lighthouse-core/test/results/sample_v2.json');
15
-
16
14
  /* eslint-env jest */
17
15
 
18
16
  describe('ReportGenerator', () => {
@@ -44,34 +44,33 @@ describe('installabilityErrors', () => {
44
44
 
45
45
  it('should notify us if something changed', () => {
46
46
  expect(chromiumErrorIds).toMatchInlineSnapshot(`
47
- Array [
48
- "already-installed",
49
- "cannot-download-icon",
50
- "ids-do-not-match",
51
- "in-incognito",
52
- "manifest-display-not-supported",
53
- "manifest-display-override-not-supported",
54
- "manifest-empty",
55
- "manifest-location-changed",
56
- "manifest-missing-name-or-short-name",
57
- "manifest-missing-suitable-icon",
58
- "no-acceptable-icon",
59
- "no-icon-available",
60
- "no-id-specified",
61
- "no-manifest",
62
- "no-matching-service-worker",
63
- "no-url-for-service-worker",
64
- "not-from-secure-origin",
65
- "not-offline-capable",
66
- "pipeline-restarted",
67
- "platform-not-supported-on-android",
68
- "prefer-related-applications",
69
- "prefer-related-applications-only-beta-stable",
70
- "start-url-not-valid",
71
- "url-not-supported-for-webapk",
72
- "warn-not-offline-capable",
73
- ]
74
- `);
47
+ Array [
48
+ "already-installed",
49
+ "cannot-download-icon",
50
+ "ids-do-not-match",
51
+ "in-incognito",
52
+ "manifest-display-not-supported",
53
+ "manifest-display-override-not-supported",
54
+ "manifest-empty",
55
+ "manifest-location-changed",
56
+ "manifest-missing-name-or-short-name",
57
+ "manifest-missing-suitable-icon",
58
+ "no-acceptable-icon",
59
+ "no-icon-available",
60
+ "no-id-specified",
61
+ "no-manifest",
62
+ "no-matching-service-worker",
63
+ "no-url-for-service-worker",
64
+ "not-from-secure-origin",
65
+ "not-offline-capable",
66
+ "platform-not-supported-on-android",
67
+ "prefer-related-applications",
68
+ "prefer-related-applications-only-beta-stable",
69
+ "start-url-not-valid",
70
+ "url-not-supported-for-webapk",
71
+ "warn-not-offline-capable",
72
+ ]
73
+ `);
75
74
  });
76
75
 
77
76
  it('are each handled explicitly in the gatherer', () => {
@@ -129,8 +129,6 @@
129
129
  {"id":"npm:mustache:20110814","severity":"medium","semver":{"vulnerable":["< 0.3.1"]}}
130
130
  ],
131
131
  "next":[
132
- {"id":"SNYK-JS-NEXT-1577139","severity":"medium","semver":{"vulnerable":[">=10.0.0 <11.1.1"]}},
133
- {"id":"SNYK-JS-NEXT-1540422","severity":"medium","semver":{"vulnerable":["<11.1.0"]}},
134
132
  {"id":"SNYK-JS-NEXT-1063481","severity":"medium","semver":{"vulnerable":[">=9.5.0 <9.5.4"]}},
135
133
  {"id":"SNYK-JS-NEXT-571938","severity":"high","semver":{"vulnerable":["<5.1.0"]}},
136
134
  {"id":"SNYK-JS-NEXT-561584","severity":"medium","semver":{"vulnerable":["<9.3.2"]}},