lighthouse 11.7.0-dev.20240409 → 11.7.0-dev.20240411

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 (134) hide show
  1. package/cli/cli-flags.js +3 -3
  2. package/cli/test/smokehouse/core-tests.js +0 -16
  3. package/cli/test/smokehouse/frontends/smokehouse-bin.js +2 -2
  4. package/core/audits/byte-efficiency/render-blocking-resources.js +25 -26
  5. package/core/audits/layout-shifts.js +1 -1
  6. package/core/computed/metrics/lantern-first-contentful-paint.js +3 -2
  7. package/core/computed/metrics/lantern-first-meaningful-paint.js +3 -2
  8. package/core/computed/metrics/lantern-interactive.js +3 -2
  9. package/core/computed/metrics/lantern-largest-contentful-paint.js +3 -2
  10. package/core/computed/metrics/lantern-max-potential-fid.js +3 -2
  11. package/core/computed/metrics/lantern-metric.d.ts +5 -0
  12. package/core/computed/metrics/lantern-metric.js +23 -1
  13. package/core/computed/metrics/lantern-speed-index.js +3 -2
  14. package/core/computed/navigation-insights.d.ts +36 -0
  15. package/core/computed/navigation-insights.js +35 -0
  16. package/core/computed/trace-engine-result.d.ts +16 -3
  17. package/core/computed/trace-engine-result.js +19 -14
  18. package/core/config/default-config.js +6 -51
  19. package/core/config/filters.js +0 -1
  20. package/core/gather/gatherers/root-causes.d.ts +2 -2
  21. package/core/gather/gatherers/root-causes.js +6 -5
  22. package/core/gather/gatherers/trace-elements.d.ts +2 -2
  23. package/core/gather/gatherers/trace-elements.js +2 -2
  24. package/core/lib/lantern/cpu-node.d.ts +7 -1
  25. package/core/lib/lantern/cpu-node.js +12 -2
  26. package/core/lib/lantern/lantern-error.d.ts +8 -0
  27. package/core/lib/lantern/lantern-error.js +9 -0
  28. package/core/lib/lantern/metrics/first-meaningful-paint.js +2 -4
  29. package/core/lib/lantern/metrics/interactive.js +1 -1
  30. package/core/lib/lantern/metrics/largest-contentful-paint.js +3 -3
  31. package/core/lib/lantern/network-node.js +28 -4
  32. package/core/lib/lantern/page-dependency-graph.js +14 -2
  33. package/core/lib/lantern/simulator/simulator.js +1 -1
  34. package/core/lib/lh-error.js +3 -3
  35. package/core/runner.js +0 -1
  36. package/dist/report/bundle.esm.js +11 -95
  37. package/dist/report/flow.js +16 -100
  38. package/dist/report/standalone.js +12 -96
  39. package/flow-report/src/help-dialog.tsx +0 -1
  40. package/flow-report/src/i18n/i18n.d.ts +0 -4
  41. package/flow-report/src/i18n/ui-strings.d.ts +0 -1
  42. package/flow-report/src/i18n/ui-strings.js +0 -2
  43. package/package.json +1 -1
  44. package/readme.md +2 -2
  45. package/report/assets/styles.css +1 -43
  46. package/report/assets/templates.html +0 -95
  47. package/report/renderer/components.d.ts +2 -2
  48. package/report/renderer/components.js +2 -103
  49. package/report/renderer/report-renderer.js +2 -12
  50. package/report/renderer/report-ui-features.js +1 -1
  51. package/report/renderer/report-utils.d.ts +0 -1
  52. package/report/renderer/report-utils.js +0 -3
  53. package/shared/localization/locales/ar-XB.json +0 -174
  54. package/shared/localization/locales/ar.json +0 -174
  55. package/shared/localization/locales/bg.json +0 -174
  56. package/shared/localization/locales/ca.json +0 -174
  57. package/shared/localization/locales/cs.json +0 -174
  58. package/shared/localization/locales/da.json +0 -174
  59. package/shared/localization/locales/de.json +0 -174
  60. package/shared/localization/locales/el.json +0 -174
  61. package/shared/localization/locales/en-GB.json +0 -174
  62. package/shared/localization/locales/en-US.json +0 -177
  63. package/shared/localization/locales/en-XA.json +0 -174
  64. package/shared/localization/locales/en-XL.json +0 -177
  65. package/shared/localization/locales/es-419.json +0 -174
  66. package/shared/localization/locales/es.json +0 -174
  67. package/shared/localization/locales/fi.json +0 -174
  68. package/shared/localization/locales/fil.json +0 -174
  69. package/shared/localization/locales/fr.json +0 -174
  70. package/shared/localization/locales/he.json +0 -174
  71. package/shared/localization/locales/hi.json +0 -174
  72. package/shared/localization/locales/hr.json +0 -174
  73. package/shared/localization/locales/hu.json +0 -174
  74. package/shared/localization/locales/id.json +0 -174
  75. package/shared/localization/locales/it.json +0 -174
  76. package/shared/localization/locales/ja.json +0 -174
  77. package/shared/localization/locales/ko.json +0 -174
  78. package/shared/localization/locales/lt.json +0 -174
  79. package/shared/localization/locales/lv.json +0 -174
  80. package/shared/localization/locales/nl.json +0 -174
  81. package/shared/localization/locales/no.json +0 -174
  82. package/shared/localization/locales/pl.json +0 -174
  83. package/shared/localization/locales/pt-PT.json +0 -174
  84. package/shared/localization/locales/pt.json +0 -174
  85. package/shared/localization/locales/ro.json +0 -174
  86. package/shared/localization/locales/ru.json +0 -174
  87. package/shared/localization/locales/sk.json +0 -174
  88. package/shared/localization/locales/sl.json +0 -174
  89. package/shared/localization/locales/sr-Latn.json +0 -174
  90. package/shared/localization/locales/sr.json +0 -174
  91. package/shared/localization/locales/sv.json +0 -174
  92. package/shared/localization/locales/ta.json +0 -174
  93. package/shared/localization/locales/te.json +0 -174
  94. package/shared/localization/locales/th.json +0 -174
  95. package/shared/localization/locales/tr.json +0 -174
  96. package/shared/localization/locales/uk.json +0 -174
  97. package/shared/localization/locales/vi.json +0 -174
  98. package/shared/localization/locales/zh-HK.json +0 -174
  99. package/shared/localization/locales/zh-TW.json +0 -174
  100. package/shared/localization/locales/zh.json +0 -174
  101. package/tsconfig.json +0 -1
  102. package/types/artifacts.d.ts +15 -90
  103. package/types/audit.d.ts +0 -10
  104. package/types/internal/smokehouse.d.ts +1 -1
  105. package/types/lhr/lhr.d.ts +0 -2
  106. package/core/audits/content-width.d.ts +0 -17
  107. package/core/audits/content-width.js +0 -76
  108. package/core/audits/installable-manifest.d.ts +0 -111
  109. package/core/audits/installable-manifest.js +0 -248
  110. package/core/audits/manual/pwa-cross-browser.d.ts +0 -12
  111. package/core/audits/manual/pwa-cross-browser.js +0 -40
  112. package/core/audits/manual/pwa-each-page-has-url.d.ts +0 -12
  113. package/core/audits/manual/pwa-each-page-has-url.js +0 -38
  114. package/core/audits/manual/pwa-page-transitions.d.ts +0 -12
  115. package/core/audits/manual/pwa-page-transitions.js +0 -38
  116. package/core/audits/maskable-icon.d.ts +0 -25
  117. package/core/audits/maskable-icon.js +0 -70
  118. package/core/audits/multi-check-audit.d.ts +0 -28
  119. package/core/audits/multi-check-audit.js +0 -82
  120. package/core/audits/splash-screen.d.ts +0 -37
  121. package/core/audits/splash-screen.js +0 -98
  122. package/core/audits/themed-omnibox.d.ts +0 -42
  123. package/core/audits/themed-omnibox.js +0 -102
  124. package/core/computed/manifest-values.d.ts +0 -24
  125. package/core/computed/manifest-values.js +0 -136
  126. package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.d.ts +0 -47
  127. package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js +0 -233
  128. package/core/gather/gatherers/installability-errors.d.ts +0 -17
  129. package/core/gather/gatherers/installability-errors.js +0 -56
  130. package/core/gather/gatherers/web-app-manifest.d.ts +0 -32
  131. package/core/gather/gatherers/web-app-manifest.js +0 -106
  132. package/report/renderer/pwa-category-renderer.d.ts +0 -55
  133. package/report/renderer/pwa-category-renderer.js +0 -184
  134. package/third-party/chromium-synchronization/installability-errors-test.js +0 -79
@@ -1,17 +0,0 @@
1
- export default InstallabilityErrors;
2
- declare class InstallabilityErrors extends BaseGatherer {
3
- /**
4
- * Creates an Artifacts.InstallabilityErrors, tranforming data from the protocol
5
- * for old versions of Chrome.
6
- * @param {LH.Gatherer.ProtocolSession} session
7
- * @return {Promise<LH.Artifacts['InstallabilityErrors']>}
8
- */
9
- static getInstallabilityErrors(session: LH.Gatherer.ProtocolSession): Promise<LH.Artifacts['InstallabilityErrors']>;
10
- /**
11
- * @param {LH.Gatherer.Context} context
12
- * @return {Promise<LH.Artifacts['InstallabilityErrors']>}
13
- */
14
- getArtifact(context: LH.Gatherer.Context): Promise<LH.Artifacts['InstallabilityErrors']>;
15
- }
16
- import BaseGatherer from '../base-gatherer.js';
17
- //# sourceMappingURL=installability-errors.d.ts.map
@@ -1,56 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2021 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- import log from 'lighthouse-logger';
8
-
9
- import BaseGatherer from '../base-gatherer.js';
10
-
11
- class InstallabilityErrors extends BaseGatherer {
12
- /** @type {LH.Gatherer.GathererMeta} */
13
- meta = {
14
- supportedModes: ['snapshot', 'navigation'],
15
- };
16
-
17
- /**
18
- * Creates an Artifacts.InstallabilityErrors, tranforming data from the protocol
19
- * for old versions of Chrome.
20
- * @param {LH.Gatherer.ProtocolSession} session
21
- * @return {Promise<LH.Artifacts['InstallabilityErrors']>}
22
- */
23
- static async getInstallabilityErrors(session) {
24
- const status = {
25
- msg: 'Get webapp installability errors',
26
- id: 'lh:gather:getInstallabilityErrors',
27
- };
28
- log.time(status);
29
- const response = await session.sendCommand('Page.getInstallabilityErrors');
30
-
31
- const errors = response.installabilityErrors;
32
-
33
- log.timeEnd(status);
34
- return {errors};
35
- }
36
-
37
- /**
38
- * @param {LH.Gatherer.Context} context
39
- * @return {Promise<LH.Artifacts['InstallabilityErrors']>}
40
- */
41
- async getArtifact(context) {
42
- const driver = context.driver;
43
-
44
- try {
45
- return await InstallabilityErrors.getInstallabilityErrors(driver.defaultSession);
46
- } catch {
47
- return {
48
- errors: [
49
- {errorId: 'protocol-timeout', errorArguments: []},
50
- ],
51
- };
52
- }
53
- }
54
- }
55
-
56
- export default InstallabilityErrors;
@@ -1,32 +0,0 @@
1
- export default WebAppManifest;
2
- declare class WebAppManifest extends BaseGatherer {
3
- /**
4
- * @param {LH.Gatherer.ProtocolSession} session
5
- * @return {Promise<{url: string, data: string}|null>}
6
- */
7
- static fetchAppManifest(session: LH.Gatherer.ProtocolSession): Promise<{
8
- url: string;
9
- data: string;
10
- } | null>;
11
- /**
12
- * Uses the debugger protocol to fetch the manifest from within the context of
13
- * the target page, reusing any credentials, emulation, etc, already established
14
- * there.
15
- *
16
- * Returns the parsed manifest or null if the page had no manifest. If the manifest
17
- * was unparseable as JSON, manifest.value will be undefined and manifest.warning
18
- * will have the reason. See manifest-parser.js for more information.
19
- *
20
- * @param {LH.Gatherer.ProtocolSession} session
21
- * @param {string} pageUrl
22
- * @return {Promise<LH.Artifacts.Manifest|null>}
23
- */
24
- static getWebAppManifest(session: LH.Gatherer.ProtocolSession, pageUrl: string): Promise<LH.Artifacts.Manifest | null>;
25
- /**
26
- * @param {LH.Gatherer.Context} context
27
- * @return {Promise<LH.Artifacts['WebAppManifest']>}
28
- */
29
- getArtifact(context: LH.Gatherer.Context): Promise<LH.Artifacts['WebAppManifest']>;
30
- }
31
- import BaseGatherer from '../base-gatherer.js';
32
- //# sourceMappingURL=web-app-manifest.d.ts.map
@@ -1,106 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2021 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- import log from 'lighthouse-logger';
8
-
9
- import {parseManifest} from '../../lib/manifest-parser.js';
10
- import BaseGatherer from '../base-gatherer.js';
11
-
12
- class WebAppManifest extends BaseGatherer {
13
- /** @type {LH.Gatherer.GathererMeta} */
14
- meta = {
15
- supportedModes: ['snapshot', 'navigation'],
16
- };
17
-
18
- /**
19
- * @param {LH.Gatherer.ProtocolSession} session
20
- * @return {Promise<{url: string, data: string}|null>}
21
- */
22
- static async fetchAppManifest(session) {
23
- // In all environments but LR, Page.getAppManifest finishes very quickly.
24
- // In LR, there is a bug that causes this command to hang until outgoing
25
- // requests finish. This has been seen in long polling (where it will never
26
- // return) and when other requests take a long time to finish. We allow 10 seconds
27
- // for outgoing requests to finish. Anything more, and we continue the run without
28
- // a manifest.
29
- // Googlers, see: http://b/124008171
30
- session.setNextProtocolTimeout(10000);
31
- let response;
32
- try {
33
- response = await session.sendCommand('Page.getAppManifest');
34
- } catch (err) {
35
- if (err.code === 'PROTOCOL_TIMEOUT') {
36
- // LR will timeout fetching the app manifest in some cases, move on without one.
37
- // https://github.com/GoogleChrome/lighthouse/issues/7147#issuecomment-461210921
38
- log.error('WebAppManifest', 'Failed fetching manifest', err);
39
- return null;
40
- }
41
-
42
- throw err;
43
- }
44
-
45
- let data = response.data;
46
-
47
- // We're not reading `response.errors` however it may contain critical and noncritical
48
- // errors from Blink's manifest parser:
49
- // https://chromedevtools.github.io/debugger-protocol-viewer/tot/Page/#type-AppManifestError
50
- if (!data) {
51
- // If the data is empty, the page had no manifest.
52
- return null;
53
- }
54
-
55
- const BOM_LENGTH = 3;
56
- const BOM_FIRSTCHAR = 65279;
57
- const isBomEncoded = data.charCodeAt(0) === BOM_FIRSTCHAR;
58
-
59
- if (isBomEncoded) {
60
- data = Buffer.from(data)
61
- .slice(BOM_LENGTH)
62
- .toString();
63
- }
64
-
65
- return {...response, data};
66
- }
67
-
68
- /**
69
- * Uses the debugger protocol to fetch the manifest from within the context of
70
- * the target page, reusing any credentials, emulation, etc, already established
71
- * there.
72
- *
73
- * Returns the parsed manifest or null if the page had no manifest. If the manifest
74
- * was unparseable as JSON, manifest.value will be undefined and manifest.warning
75
- * will have the reason. See manifest-parser.js for more information.
76
- *
77
- * @param {LH.Gatherer.ProtocolSession} session
78
- * @param {string} pageUrl
79
- * @return {Promise<LH.Artifacts.Manifest|null>}
80
- */
81
- static async getWebAppManifest(session, pageUrl) {
82
- const status = {msg: 'Get webapp manifest', id: 'lh:gather:getWebAppManifest'};
83
- log.time(status);
84
- const response = await WebAppManifest.fetchAppManifest(session);
85
- if (!response) return null;
86
- const manifest = parseManifest(response.data, response.url, pageUrl);
87
- log.timeEnd(status);
88
- return manifest;
89
- }
90
-
91
- /**
92
- * @param {LH.Gatherer.Context} context
93
- * @return {Promise<LH.Artifacts['WebAppManifest']>}
94
- */
95
- async getArtifact(context) {
96
- const driver = context.driver;
97
- const {finalDisplayedUrl} = context.baseArtifacts.URL;
98
- try {
99
- return await WebAppManifest.getWebAppManifest(driver.defaultSession, finalDisplayedUrl);
100
- } catch {
101
- return null;
102
- }
103
- }
104
- }
105
-
106
- export default WebAppManifest;
@@ -1,55 +0,0 @@
1
- export class PwaCategoryRenderer extends CategoryRenderer {
2
- /**
3
- * Alters SVG id references so multiple instances of an SVG element can coexist
4
- * in a single page. If `svgRoot` has a `<defs>` block, gives all elements defined
5
- * in it unique ids, then updates id references (`<use xlink:href="...">`,
6
- * `fill="url(#...)"`) to the altered ids in all descendents of `svgRoot`.
7
- * @param {SVGElement} svgRoot
8
- */
9
- static _makeSvgReferencesUnique(svgRoot: SVGElement): void;
10
- /**
11
- * @param {LH.ReportResult.Category} category
12
- * @param {Object<string, LH.Result.ReportGroup>} [groupDefinitions]
13
- * @return {Element}
14
- */
15
- render(category: LH.ReportResult.Category, groupDefinitions?: {
16
- [x: string]: import("../../types/lhr/lhr.js").default.ReportGroup;
17
- } | undefined): Element;
18
- /**
19
- * @param {LH.ReportResult.Category} category
20
- * @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
21
- * @return {DocumentFragment}
22
- */
23
- renderCategoryScore(category: LH.ReportResult.Category, groupDefinitions: Record<string, LH.Result.ReportGroup>): DocumentFragment;
24
- /**
25
- * Returns the group IDs found in auditRefs.
26
- * @param {Array<LH.ReportResult.AuditRef>} auditRefs
27
- * @return {!Set<string>}
28
- */
29
- _getGroupIds(auditRefs: Array<LH.ReportResult.AuditRef>): Set<string>;
30
- /**
31
- * Returns the group IDs whose audits are all considered passing.
32
- * @param {Array<LH.ReportResult.AuditRef>} auditRefs
33
- * @return {Set<string>}
34
- */
35
- _getPassingGroupIds(auditRefs: Array<LH.ReportResult.AuditRef>): Set<string>;
36
- /**
37
- * Returns a tooltip string summarizing group pass rates.
38
- * @param {Array<LH.ReportResult.AuditRef>} auditRefs
39
- * @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
40
- * @return {string}
41
- */
42
- _getGaugeTooltip(auditRefs: Array<LH.ReportResult.AuditRef>, groupDefinitions: Record<string, LH.Result.ReportGroup>): string;
43
- /**
44
- * Render non-manual audits in groups, giving a badge to any group that has
45
- * all passing audits.
46
- * @param {Array<LH.ReportResult.AuditRef>} auditRefs
47
- * @param {Object<string, LH.Result.ReportGroup>} groupDefinitions
48
- * @return {Element}
49
- */
50
- _renderAudits(auditRefs: Array<LH.ReportResult.AuditRef>, groupDefinitions: {
51
- [x: string]: LH.Result.ReportGroup;
52
- }): Element;
53
- }
54
- import { CategoryRenderer } from './category-renderer.js';
55
- //# sourceMappingURL=pwa-category-renderer.d.ts.map
@@ -1,184 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2018 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- import {CategoryRenderer} from './category-renderer.js';
8
- import {ReportUtils} from './report-utils.js';
9
- import {Globals} from './report-globals.js';
10
-
11
- export class PwaCategoryRenderer extends CategoryRenderer {
12
- /**
13
- * @param {LH.ReportResult.Category} category
14
- * @param {Object<string, LH.Result.ReportGroup>} [groupDefinitions]
15
- * @return {Element}
16
- */
17
- render(category, groupDefinitions = {}) {
18
- const categoryElem = this.dom.createElement('div', 'lh-category');
19
- categoryElem.id = category.id;
20
- // Deprecation warning banner.
21
- const pwaMessageContainer = this.dom.createComponent('warningsToplevel');
22
- const pwaMessageEl = this.dom.find('.lh-warnings__msg', pwaMessageContainer);
23
- pwaMessageEl.append(this.dom.convertMarkdownLinkSnippets(Globals.strings.pwaRemovalMessage));
24
-
25
- categoryElem.append(pwaMessageContainer);
26
- categoryElem.append(this.renderCategoryHeader(category, groupDefinitions));
27
-
28
- const auditRefs = category.auditRefs;
29
-
30
- // Regular audits aren't split up into pass/fail/notApplicable clumps, they're
31
- // all put in a top-level clump that isn't expandable/collapsible.
32
- const regularAuditRefs = auditRefs.filter(ref => ref.result.scoreDisplayMode !== 'manual');
33
- const auditsElem = this._renderAudits(regularAuditRefs, groupDefinitions);
34
- categoryElem.append(auditsElem);
35
-
36
- // Manual audits are still in a manual clump.
37
- const manualAuditRefs = auditRefs.filter(ref => ref.result.scoreDisplayMode === 'manual');
38
- const manualElem = this.renderClump('manual', {
39
- auditRefsOrEls: manualAuditRefs,
40
- description: category.manualDescription,
41
- openByDefault: true,
42
- });
43
- categoryElem.append(manualElem);
44
-
45
- return categoryElem;
46
- }
47
-
48
- /**
49
- * @param {LH.ReportResult.Category} category
50
- * @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
51
- * @return {DocumentFragment}
52
- */
53
- renderCategoryScore(category, groupDefinitions) {
54
- // Defer to parent-gauge style if category error.
55
- if (category.score === null) {
56
- return super.renderScoreGauge(category, groupDefinitions);
57
- }
58
-
59
- const tmpl = this.dom.createComponent('gaugePwa');
60
- const wrapper = this.dom.find('a.lh-gauge--pwa__wrapper', tmpl);
61
-
62
- // Correct IDs in case multiple instances end up in the page.
63
- const svgRoot = tmpl.querySelector('svg');
64
- if (!svgRoot) throw new Error('no SVG element found in PWA score gauge template');
65
- PwaCategoryRenderer._makeSvgReferencesUnique(svgRoot);
66
-
67
- const allGroups = this._getGroupIds(category.auditRefs);
68
- const passingGroupIds = this._getPassingGroupIds(category.auditRefs);
69
-
70
- if (passingGroupIds.size === allGroups.size) {
71
- wrapper.classList.add('lh-badged--all');
72
- } else {
73
- for (const passingGroupId of passingGroupIds) {
74
- wrapper.classList.add(`lh-badged--${passingGroupId}`);
75
- }
76
- }
77
-
78
- this.dom.find('.lh-gauge__label', tmpl).textContent = category.title;
79
- wrapper.title = this._getGaugeTooltip(category.auditRefs, groupDefinitions);
80
- return tmpl;
81
- }
82
-
83
- /**
84
- * Returns the group IDs found in auditRefs.
85
- * @param {Array<LH.ReportResult.AuditRef>} auditRefs
86
- * @return {!Set<string>}
87
- */
88
- _getGroupIds(auditRefs) {
89
- const groupIds = auditRefs.map(ref => ref.group).filter(/** @return {g is string} */ g => !!g);
90
- return new Set(groupIds);
91
- }
92
-
93
- /**
94
- * Returns the group IDs whose audits are all considered passing.
95
- * @param {Array<LH.ReportResult.AuditRef>} auditRefs
96
- * @return {Set<string>}
97
- */
98
- _getPassingGroupIds(auditRefs) {
99
- const uniqueGroupIds = this._getGroupIds(auditRefs);
100
-
101
- // Remove any that have a failing audit.
102
- for (const auditRef of auditRefs) {
103
- if (!ReportUtils.showAsPassed(auditRef.result) && auditRef.group) {
104
- uniqueGroupIds.delete(auditRef.group);
105
- }
106
- }
107
-
108
- return uniqueGroupIds;
109
- }
110
-
111
- /**
112
- * Returns a tooltip string summarizing group pass rates.
113
- * @param {Array<LH.ReportResult.AuditRef>} auditRefs
114
- * @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
115
- * @return {string}
116
- */
117
- _getGaugeTooltip(auditRefs, groupDefinitions) {
118
- const groupIds = this._getGroupIds(auditRefs);
119
-
120
- const tips = [];
121
- for (const groupId of groupIds) {
122
- const groupAuditRefs = auditRefs.filter(ref => ref.group === groupId);
123
- const auditCount = groupAuditRefs.length;
124
- const passedCount = groupAuditRefs.filter(ref => ReportUtils.showAsPassed(ref.result)).length;
125
-
126
- const title = groupDefinitions[groupId].title;
127
- tips.push(`${title}: ${passedCount}/${auditCount}`);
128
- }
129
-
130
- return tips.join(', ');
131
- }
132
-
133
- /**
134
- * Render non-manual audits in groups, giving a badge to any group that has
135
- * all passing audits.
136
- * @param {Array<LH.ReportResult.AuditRef>} auditRefs
137
- * @param {Object<string, LH.Result.ReportGroup>} groupDefinitions
138
- * @return {Element}
139
- */
140
- _renderAudits(auditRefs, groupDefinitions) {
141
- const auditsElem = this.renderUnexpandableClump(auditRefs, groupDefinitions);
142
-
143
- // Add a 'badged' class to group if all audits in that group pass.
144
- const passsingGroupIds = this._getPassingGroupIds(auditRefs);
145
- for (const groupId of passsingGroupIds) {
146
- const groupElem = this.dom.find(`.lh-audit-group--${groupId}`, auditsElem);
147
- groupElem.classList.add('lh-badged');
148
- }
149
-
150
- return auditsElem;
151
- }
152
-
153
- /**
154
- * Alters SVG id references so multiple instances of an SVG element can coexist
155
- * in a single page. If `svgRoot` has a `<defs>` block, gives all elements defined
156
- * in it unique ids, then updates id references (`<use xlink:href="...">`,
157
- * `fill="url(#...)"`) to the altered ids in all descendents of `svgRoot`.
158
- * @param {SVGElement} svgRoot
159
- */
160
- static _makeSvgReferencesUnique(svgRoot) {
161
- const defsEl = svgRoot.querySelector('defs');
162
- if (!defsEl) return;
163
-
164
- const idSuffix = Globals.getUniqueSuffix();
165
- const elementsToUpdate = defsEl.querySelectorAll('[id]');
166
- for (const el of elementsToUpdate) {
167
- const oldId = el.id;
168
- const newId = `${oldId}-${idSuffix}`;
169
- el.id = newId;
170
-
171
- // Update all <use>s.
172
- const useEls = svgRoot.querySelectorAll(`use[href="#${oldId}"]`);
173
- for (const useEl of useEls) {
174
- useEl.setAttribute('href', `#${newId}`);
175
- }
176
-
177
- // Update all fill="url(#...)"s.
178
- const fillEls = svgRoot.querySelectorAll(`[fill="url(#${oldId})"]`);
179
- for (const fillEl of fillEls) {
180
- fillEl.setAttribute('fill', `url(#${newId})`);
181
- }
182
- }
183
- }
184
- }
@@ -1,79 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2020 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
- 'use strict';
7
-
8
- import fetch from 'node-fetch';
9
-
10
- import {UIStrings} from '../../core/audits/installable-manifest.js';
11
-
12
- describe('installabilityErrors', () => {
13
- let chromiumErrorIds;
14
-
15
- before(async () => {
16
- const installableLoggingGitTilesUrl =
17
- 'https://chromium.googlesource.com/chromium/src/+/main/components/webapps/browser/installable/installable_logging.cc?format=TEXT';
18
- const resp = await fetch(installableLoggingGitTilesUrl);
19
- if (!resp.ok) {
20
- throw new Error(`Chromium source fetch failed: ${resp.status} ${resp.statusText}`);
21
- }
22
- const base64 = await resp.text();
23
- const buff = Buffer.from(base64, 'base64');
24
- const text = buff.toString('utf-8');
25
-
26
- // Apply some *beautiful* regexes to parse the C++ of https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/installable/installable_logging.cc
27
- const handledErrorConsts = [...text.matchAll(/error_id = (k.*?);/g)].map(([_, match]) => match);
28
- const errorConstsToIdsCode = [...text.matchAll(/static const char k.*?Id\[\](.|\n)*?;/g)].map(
29
- ([match]) => match.replace(/\n/, '')
30
- );
31
- const errorConstsToIds = errorConstsToIdsCode.map(txt => [
32
- txt.match(/char (k.*?)\[/)[1],
33
- txt.match(/ "(.*?)"/)[1],
34
- ]);
35
- const errorConstsToIdsDict = Object.fromEntries(errorConstsToIds);
36
-
37
- chromiumErrorIds = handledErrorConsts.map(varName => {
38
- if (!errorConstsToIdsDict[varName]) throw new Error(`Error const (${varName}) not found!`);
39
- return errorConstsToIdsDict[varName];
40
- }).sort();
41
- });
42
-
43
- it('should notify us if something changed', () => {
44
- expect(chromiumErrorIds).toMatchInlineSnapshot(`
45
- Array [
46
- "already-installed",
47
- "cannot-download-icon",
48
- "ids-do-not-match",
49
- "in-incognito",
50
- "manifest-display-not-supported",
51
- "manifest-display-override-not-supported",
52
- "manifest-location-changed",
53
- "manifest-missing-name-or-short-name",
54
- "manifest-missing-suitable-icon",
55
- "manifest-parsing-or-network-error",
56
- "no-acceptable-icon",
57
- "no-icon-available",
58
- "no-id-specified",
59
- "no-manifest",
60
- "no-url-for-service-worker",
61
- "not-from-secure-origin",
62
- "not-offline-capable",
63
- "pipeline-restarted",
64
- "platform-not-supported-on-android",
65
- "prefer-related-applications",
66
- "prefer-related-applications-only-beta-stable",
67
- "start-url-not-valid",
68
- "url-not-supported-for-webapk",
69
- ]
70
- `);
71
- });
72
-
73
- it('are each handled explicitly in the gatherer', () => {
74
- const errorStrings = Object.keys(UIStrings)
75
- .filter(key => chromiumErrorIds.includes(key))
76
- .sort();
77
- expect(errorStrings).toEqual(chromiumErrorIds);
78
- });
79
- });