lighthouse 8.5.1-dev.20211012 → 8.5.1

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 (172) hide show
  1. package/dist/report/flow.js +149 -0
  2. package/dist/report/standalone.js +228 -0
  3. package/flow-report/assets/styles.css +9 -272
  4. package/flow-report/jest.config.js +1 -1
  5. package/flow-report/src/app.tsx +9 -31
  6. package/flow-report/src/common.tsx +7 -86
  7. package/flow-report/src/icons.tsx +3 -20
  8. package/flow-report/src/sidebar/sidebar.tsx +16 -11
  9. package/flow-report/src/summary/category.tsx +24 -42
  10. package/flow-report/src/summary/summary.tsx +29 -32
  11. package/flow-report/src/topbar.tsx +4 -54
  12. package/flow-report/src/util.ts +1 -26
  13. package/flow-report/src/wrappers/report-renderer.tsx +1 -1
  14. package/flow-report/src/wrappers/report.tsx +21 -6
  15. package/flow-report/test/app-test.tsx +13 -17
  16. package/flow-report/test/setup/env-setup.ts +0 -1
  17. package/flow-report/test/sidebar/flow-test.tsx +12 -6
  18. package/flow-report/test/sidebar/sidebar-test.tsx +13 -7
  19. package/flow-report/test/summary/category-test.tsx +34 -79
  20. package/flow-report/test/summary/summary-test.tsx +17 -11
  21. package/flow-report/test/util-test.tsx +12 -1
  22. package/flow-report/tsconfig.json +0 -1
  23. package/flow-report/types/flow-report.d.ts +1 -2
  24. package/jest.config.js +15 -1
  25. package/lighthouse-cli/bin.js +0 -5
  26. package/lighthouse-cli/cli-flags.js +3 -10
  27. package/lighthouse-cli/commands/commands.js +0 -1
  28. package/lighthouse-cli/run.js +2 -2
  29. package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +0 -0
  30. package/lighthouse-cli/test/smokehouse/report-assert.js +4 -20
  31. package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +1 -2
  32. package/lighthouse-core/audits/byte-efficiency/unused-javascript.js +1 -1
  33. package/lighthouse-core/audits/seo/crawlable-anchors.js +12 -10
  34. package/lighthouse-core/computed/js-bundles.js +2 -1
  35. package/lighthouse-core/computed/unused-javascript-summary.js +3 -3
  36. package/lighthouse-core/config/config.js +2 -2
  37. package/lighthouse-core/config/default-config.js +0 -5
  38. package/lighthouse-core/fraggle-rock/api.js +0 -10
  39. package/lighthouse-core/fraggle-rock/config/filters.js +3 -22
  40. package/lighthouse-core/fraggle-rock/gather/driver.js +0 -4
  41. package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +2 -2
  42. package/lighthouse-core/fraggle-rock/user-flow.js +6 -35
  43. package/lighthouse-core/gather/driver/navigation.js +0 -5
  44. package/lighthouse-core/gather/driver/prepare.js +0 -14
  45. package/lighthouse-core/gather/driver/storage.js +0 -5
  46. package/lighthouse-core/gather/gather-runner.js +2 -2
  47. package/lighthouse-core/gather/gatherers/dobetterweb/response-compression.js +1 -5
  48. package/lighthouse-core/gather/gatherers/full-page-screenshot.js +24 -30
  49. package/{shared/localization/i18n-module.js → lighthouse-core/lib/cdt/Common.js} +8 -3
  50. package/lighthouse-core/lib/cdt/SDK.js +123 -3
  51. package/lighthouse-core/lib/cdt/generated/SourceMap.js +312 -148
  52. package/lighthouse-core/lib/csp-evaluator.js +1 -2
  53. package/lighthouse-core/lib/i18n/README.md +6 -6
  54. package/lighthouse-core/lib/i18n/i18n.js +342 -9
  55. package/{shared/localization → lighthouse-core/lib/i18n}/locales/ar-XB.json +0 -0
  56. package/{shared/localization → lighthouse-core/lib/i18n}/locales/ar.json +0 -0
  57. package/{shared/localization → lighthouse-core/lib/i18n}/locales/bg.json +0 -0
  58. package/{shared/localization → lighthouse-core/lib/i18n}/locales/ca.json +0 -0
  59. package/{shared/localization → lighthouse-core/lib/i18n}/locales/cs.json +0 -0
  60. package/{shared/localization → lighthouse-core/lib/i18n}/locales/da.json +0 -0
  61. package/{shared/localization → lighthouse-core/lib/i18n}/locales/de.json +0 -0
  62. package/{shared/localization → lighthouse-core/lib/i18n}/locales/el.json +0 -0
  63. package/{shared/localization → lighthouse-core/lib/i18n}/locales/en-GB.json +0 -0
  64. package/{shared/localization → lighthouse-core/lib/i18n}/locales/en-US.json +0 -111
  65. package/{shared/localization → lighthouse-core/lib/i18n}/locales/en-XA.json +0 -0
  66. package/{shared/localization → lighthouse-core/lib/i18n}/locales/en-XL.json +0 -111
  67. package/{shared/localization → lighthouse-core/lib/i18n}/locales/es-419.json +0 -0
  68. package/{shared/localization → lighthouse-core/lib/i18n}/locales/es.json +0 -0
  69. package/{shared/localization → lighthouse-core/lib/i18n}/locales/fi.json +0 -0
  70. package/{shared/localization → lighthouse-core/lib/i18n}/locales/fil.json +0 -0
  71. package/{shared/localization → lighthouse-core/lib/i18n}/locales/fr.json +0 -0
  72. package/{shared/localization → lighthouse-core/lib/i18n}/locales/he.json +0 -0
  73. package/{shared/localization → lighthouse-core/lib/i18n}/locales/hi.json +0 -0
  74. package/{shared/localization → lighthouse-core/lib/i18n}/locales/hr.json +0 -0
  75. package/{shared/localization → lighthouse-core/lib/i18n}/locales/hu.json +0 -0
  76. package/{shared/localization → lighthouse-core/lib/i18n}/locales/id.json +0 -0
  77. package/{shared/localization → lighthouse-core/lib/i18n}/locales/it.json +0 -0
  78. package/{shared/localization → lighthouse-core/lib/i18n}/locales/ja.json +0 -0
  79. package/{shared/localization → lighthouse-core/lib/i18n}/locales/ko.json +0 -0
  80. package/{shared/localization → lighthouse-core/lib/i18n}/locales/lt.json +0 -0
  81. package/{shared/localization → lighthouse-core/lib/i18n}/locales/lv.json +0 -0
  82. package/{shared/localization → lighthouse-core/lib/i18n}/locales/nl.json +0 -0
  83. package/{shared/localization → lighthouse-core/lib/i18n}/locales/no.json +0 -0
  84. package/{shared/localization → lighthouse-core/lib/i18n}/locales/pl.json +0 -0
  85. package/{shared/localization → lighthouse-core/lib/i18n}/locales/pt-PT.json +0 -0
  86. package/{shared/localization → lighthouse-core/lib/i18n}/locales/pt.json +0 -0
  87. package/{shared/localization → lighthouse-core/lib/i18n}/locales/ro.json +0 -0
  88. package/{shared/localization → lighthouse-core/lib/i18n}/locales/ru.json +0 -0
  89. package/{shared/localization → lighthouse-core/lib/i18n}/locales/sk.json +0 -0
  90. package/{shared/localization → lighthouse-core/lib/i18n}/locales/sl.json +0 -0
  91. package/{shared/localization → lighthouse-core/lib/i18n}/locales/sr-Latn.json +0 -0
  92. package/{shared/localization → lighthouse-core/lib/i18n}/locales/sr.json +0 -0
  93. package/{shared/localization → lighthouse-core/lib/i18n}/locales/sv.json +0 -0
  94. package/{shared/localization → lighthouse-core/lib/i18n}/locales/ta.json +0 -0
  95. package/{shared/localization → lighthouse-core/lib/i18n}/locales/te.json +0 -0
  96. package/{shared/localization → lighthouse-core/lib/i18n}/locales/th.json +0 -0
  97. package/{shared/localization → lighthouse-core/lib/i18n}/locales/tr.json +0 -0
  98. package/{shared/localization → lighthouse-core/lib/i18n}/locales/uk.json +0 -0
  99. package/{shared/localization → lighthouse-core/lib/i18n}/locales/vi.json +0 -0
  100. package/{shared/localization → lighthouse-core/lib/i18n}/locales/zh-HK.json +0 -0
  101. package/{shared/localization → lighthouse-core/lib/i18n}/locales/zh-TW.json +0 -0
  102. package/{shared/localization → lighthouse-core/lib/i18n}/locales/zh.json +0 -0
  103. package/{shared/localization → lighthouse-core/lib/i18n}/locales.js +1 -2
  104. package/{shared/localization → lighthouse-core/lib/i18n}/swap-locale.js +7 -9
  105. package/lighthouse-core/lib/page-functions.js +4 -4
  106. package/lighthouse-core/lib/stack-packs.js +13 -1
  107. package/{shared → lighthouse-core/lib}/type-verifiers.js +0 -0
  108. package/lighthouse-core/runner.js +6 -6
  109. package/lighthouse-core/scripts/manual-chrome-launcher.js +1 -4
  110. package/lighthouse-core/util-commonjs.js +4 -20
  111. package/package.json +16 -19
  112. package/readme.md +1 -1
  113. package/report/assets/standalone-template.html +1 -0
  114. package/report/assets/styles.css +41 -16
  115. package/report/assets/templates.html +4 -42
  116. package/report/clients/psi.js +0 -1
  117. package/report/clients/standalone.js +2 -1
  118. package/report/generator/file-namer.js +8 -17
  119. package/report/generator/report-generator.js +1 -0
  120. package/report/renderer/category-renderer.js +16 -4
  121. package/report/renderer/components.js +71 -107
  122. package/report/renderer/dom.js +0 -19
  123. package/report/renderer/logger.js +2 -35
  124. package/report/renderer/performance-category-renderer.js +21 -23
  125. package/report/renderer/pwa-category-renderer.js +2 -1
  126. package/report/renderer/report-renderer.js +0 -21
  127. package/report/renderer/report-ui-features.js +19 -7
  128. package/report/renderer/util.js +4 -20
  129. package/report/test/clients/psi-test.js +4 -0
  130. package/report/test/generator/file-namer-test.js +2 -2
  131. package/report/test/renderer/category-renderer-test.js +1 -1
  132. package/report/test/renderer/performance-category-renderer-test.js +0 -12
  133. package/report/test/renderer/report-renderer-test.js +55 -0
  134. package/report/test/renderer/util-test.js +8 -68
  135. package/report/test-assets/faux-psi-template.html +1 -0
  136. package/report/tsconfig.json +1 -2
  137. package/report/types/html-renderer.d.ts +1 -2
  138. package/root.js +0 -18
  139. package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +3 -5
  140. package/third-party/chromium-synchronization/installability-errors-test.js +1 -2
  141. package/tsconfig-all.json +0 -1
  142. package/tsconfig-base.json +1 -1
  143. package/tsconfig.json +3 -2
  144. package/types/config.d.ts +0 -1
  145. package/types/externs.d.ts +0 -2
  146. package/types/lhr/flow.d.ts +0 -7
  147. package/types/lhr/i18n.d.ts +3 -0
  148. package/changelog.md +0 -5395
  149. package/flow-report/.eslintrc.cjs +0 -49
  150. package/flow-report/package.json +0 -4
  151. package/flow-report/src/header.tsx +0 -88
  152. package/flow-report/src/help-dialog.tsx +0 -120
  153. package/flow-report/src/i18n/i18n.tsx +0 -44
  154. package/flow-report/src/i18n/localized-strings.js +0 -11
  155. package/flow-report/src/i18n/ui-strings.js +0 -86
  156. package/flow-report/test/common-test.tsx +0 -89
  157. package/flow-report/test/header-test.tsx +0 -55
  158. package/flow-report/test/sample-flow.ts +0 -17
  159. package/flow-report/test/topbar-test.tsx +0 -68
  160. package/lighthouse-cli/commands/list-locales.js +0 -16
  161. package/lighthouse-core/lib/cdt/Platform.js +0 -55
  162. package/lighthouse-core/scripts/package.json +0 -4
  163. package/report/renderer/swap-locale-feature.js +0 -82
  164. package/report/test/renderer/report-renderer-axe-test.js +0 -86
  165. package/shared/localization/format.js +0 -422
  166. package/shared/localization/swap-flow-locale.js +0 -20
  167. package/shared/test/localization/format-test.js +0 -377
  168. package/shared/test/localization/locales-test.js +0 -47
  169. package/shared/test/localization/swap-locale-test.js +0 -140
  170. package/shared/tsconfig.json +0 -22
  171. package/shared/types/shared.d.ts +0 -24
  172. package/types/es-main.d.ts +0 -18
@@ -4,110 +4,65 @@
4
4
  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
5
5
  */
6
6
 
7
- import {FunctionComponent} from 'preact';
7
+ import fs from 'fs';
8
+ import {dirname} from 'path';
9
+ import {fileURLToPath} from 'url';
10
+
8
11
  import {render} from '@testing-library/preact';
9
12
 
10
13
  import {SummaryTooltip} from '../../src/summary/category';
11
- import {flowResult} from '../sample-flow';
12
- import {I18nProvider} from '../../src/i18n/i18n';
13
- import {FlowResultContext} from '../../src/util';
14
-
15
- let wrapper: FunctionComponent;
14
+ import {Util} from '../../../report/renderer/util';
16
15
 
17
- beforeEach(() => {
18
- // Include sample flowResult for locale in I18nProvider.
19
- wrapper = ({children}) => (
20
- <FlowResultContext.Provider value={flowResult}>
21
- <I18nProvider>
22
- {children}
23
- </I18nProvider>
24
- </FlowResultContext.Provider>
25
- );
26
- });
16
+ const flowResult: LH.FlowResult = JSON.parse(
17
+ fs.readFileSync(
18
+ // eslint-disable-next-line max-len
19
+ `${dirname(fileURLToPath(import.meta.url))}/../../../lighthouse-core/test/fixtures/fraggle-rock/reports/sample-lhrs.json`,
20
+ 'utf-8'
21
+ )
22
+ );
27
23
 
28
24
  describe('SummaryTooltip', () => {
29
25
  it('renders tooltip with rating', async () => {
30
- const category: any = {
31
- id: 'performance',
32
- score: 1,
33
- auditRefs: [
34
- {result: {score: 1, scoreDisplayMode: 'binary'}, weight: 1, group: 'diagnostics'},
35
- {result: {score: 1, scoreDisplayMode: 'binary'}, weight: 1, group: 'diagnostics'},
36
- {result: {score: 0, scoreDisplayMode: 'binary'}, weight: 1, group: 'diagnostics'},
37
- ],
38
- };
26
+ // Snapshot SEO
27
+ const reportResult = Util.prepareReportResult(flowResult.steps[2].lhr);
28
+ const category = reportResult.categories['seo'];
39
29
 
40
30
  const root = render(
41
- <SummaryTooltip category={category} gatherMode="snapshot"/>,
42
- {wrapper}
31
+ <SummaryTooltip category={category} gatherMode={reportResult.gatherMode}/>
43
32
  );
44
33
 
45
- expect(root.getByText('Average')).toBeTruthy();
46
- expect(() => root.getByText(/^[0-9]+$/)).toThrow();
47
- expect(root.getByText('2 audits passed / 3 passable audits')).toBeTruthy();
34
+ const rating = root.getByTestId('SummaryTooltip__rating');
35
+ expect(rating.classList).toContain('SummaryTooltip__rating--average');
36
+
37
+ expect(root.getByText('9 audits passed / 11 audits run')).toBeTruthy();
48
38
  });
49
39
 
50
40
  it('renders tooltip without rating', async () => {
51
- const category: any = {
52
- id: 'performance',
53
- score: 1,
54
- auditRefs: [
55
- {result: {score: 1, scoreDisplayMode: 'binary'}, weight: 0, group: 'diagnostics'},
56
- {result: {score: 1, scoreDisplayMode: 'binary'}, weight: 0, group: 'diagnostics'},
57
- {result: {score: 0, scoreDisplayMode: 'binary'}, weight: 0, group: 'diagnostics'},
58
- ],
59
- };
41
+ // Snapshot performance
42
+ const reportResult = Util.prepareReportResult(flowResult.steps[2].lhr);
43
+ const category = reportResult.categories['performance'];
60
44
 
61
45
  const root = render(
62
- <SummaryTooltip category={category} gatherMode="snapshot"/>,
63
- {wrapper}
46
+ <SummaryTooltip category={category} gatherMode={reportResult.gatherMode}/>
64
47
  );
65
48
 
66
- expect(() => root.getByText(/^(Average|Good|Poor)$/)).toThrow();
67
- expect(() => root.getByText(/^[0-9]+$/)).toThrow();
68
- expect(root.getByText('2 audits passed / 3 passable audits')).toBeTruthy();
49
+ expect(() => root.getByTestId('SummaryTooltip__rating')).toThrow();
50
+ expect(root.getByText('2 audits passed / 4 audits run')).toBeTruthy();
69
51
  });
70
52
 
71
53
  it('renders scored category tooltip with score', async () => {
72
- const category: any = {
73
- id: 'performance',
74
- score: 1,
75
- auditRefs: [
76
- {result: {score: 1, scoreDisplayMode: 'binary'}, weight: 1, group: 'diagnostics'},
77
- {result: {score: 1, scoreDisplayMode: 'binary'}, weight: 1, group: 'diagnostics'},
78
- {result: {score: 0, scoreDisplayMode: 'binary'}, weight: 1, group: 'diagnostics'},
79
- ],
80
- };
54
+ // Navigation performance
55
+ const reportResult = Util.prepareReportResult(flowResult.steps[0].lhr);
56
+ const category = reportResult.categories['performance'];
81
57
 
82
58
  const root = render(
83
- <SummaryTooltip category={category} gatherMode="navigation"/>,
84
- {wrapper}
59
+ <SummaryTooltip category={category} gatherMode={reportResult.gatherMode}/>
85
60
  );
86
61
 
87
- expect(root.getByText('Good')).toBeTruthy();
88
- expect(root.getByText('100')).toBeTruthy();
89
- expect(root.getByText('2 audits passed / 3 passable audits')).toBeTruthy();
90
- });
91
-
92
- it('renders informative audit count if any', async () => {
93
- const category: any = {
94
- id: 'performance',
95
- score: 1,
96
- auditRefs: [
97
- {result: {score: 1, scoreDisplayMode: 'binary'}, weight: 1, group: 'diagnostics'},
98
- {result: {score: 1, scoreDisplayMode: 'binary'}, weight: 1, group: 'diagnostics'},
99
- {result: {score: 0, scoreDisplayMode: 'informative'}, weight: 1, group: 'diagnostics'},
100
- ],
101
- };
102
-
103
- const root = render(
104
- <SummaryTooltip category={category} gatherMode="navigation"/>,
105
- {wrapper}
106
- );
62
+ const rating = root.getByTestId('SummaryTooltip__rating');
63
+ expect(rating.classList).toContain('SummaryTooltip__rating--pass');
64
+ expect(rating.textContent).toEqual('Good · 94');
107
65
 
108
- expect(root.getByText('Good')).toBeTruthy();
109
- expect(root.getByText('100')).toBeTruthy();
110
- expect(root.getByText('2 audits passed / 2 passable audits')).toBeTruthy();
111
- expect(root.getByText('1 informative audits')).toBeTruthy();
66
+ expect(root.getByText('41 audits passed / 58 audits run')).toBeTruthy();
112
67
  });
113
68
  });
@@ -4,14 +4,24 @@
4
4
  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
5
5
  */
6
6
 
7
+ import fs from 'fs';
8
+ import {dirname} from 'path';
9
+ import {fileURLToPath} from 'url';
10
+
7
11
  import {render} from '@testing-library/preact';
8
12
  import {FunctionComponent} from 'preact';
9
13
 
10
- import {I18nProvider} from '../../src/i18n/i18n';
11
14
  import {SummaryHeader, SummaryFlowStep} from '../../src/summary/summary';
12
15
  import {FlowResultContext} from '../../src/util';
13
16
  import {ReportRendererProvider} from '../../src/wrappers/report-renderer';
14
- import {flowResult} from '../sample-flow';
17
+
18
+ const flowResult: LH.FlowResult = JSON.parse(
19
+ fs.readFileSync(
20
+ // eslint-disable-next-line max-len
21
+ `${dirname(fileURLToPath(import.meta.url))}/../../../lighthouse-core/test/fixtures/fraggle-rock/reports/sample-lhrs.json`,
22
+ 'utf-8'
23
+ )
24
+ );
15
25
 
16
26
  let wrapper: FunctionComponent;
17
27
 
@@ -19,9 +29,7 @@ beforeEach(() => {
19
29
  wrapper = ({children}) => (
20
30
  <FlowResultContext.Provider value={flowResult}>
21
31
  <ReportRendererProvider>
22
- <I18nProvider>
23
- {children}
24
- </I18nProvider>
32
+ {children}
25
33
  </ReportRendererProvider>
26
34
  </FlowResultContext.Provider>
27
35
  );
@@ -51,8 +59,7 @@ describe('SummaryFlowStep', () => {
51
59
 
52
60
  expect(root.getByText('Navigation (1)')).toBeTruthy();
53
61
 
54
- const screenshot =
55
- root.getByAltText('Screenshot of a page tested by Lighthouse') as HTMLImageElement;
62
+ const screenshot = root.getByTestId('SummaryFlowStep__screenshot') as HTMLImageElement;
56
63
  expect(screenshot.src).toMatch(/data:image\/jpeg;base64/);
57
64
 
58
65
  const gauges = root.getAllByTestId('CategoryScore');
@@ -60,7 +67,6 @@ describe('SummaryFlowStep', () => {
60
67
 
61
68
  const links = root.getAllByRole('link') as HTMLAnchorElement[];
62
69
  expect(links.map(a => a.href)).toEqual([
63
- 'https://www.mikescerealshack.co/',
64
70
  'file:///Users/example/report.html/#index=0',
65
71
  'file:///Users/example/report.html/#index=0&anchor=performance',
66
72
  'file:///Users/example/report.html/#index=0&anchor=accessibility',
@@ -80,7 +86,8 @@ describe('SummaryFlowStep', () => {
80
86
 
81
87
  expect(root.getByText('Timespan (1)')).toBeTruthy();
82
88
 
83
- expect(() => root.getByAltText('Screenshot of a page tested by Lighthouse')).toThrow();
89
+ const screenshot = root.getByTestId('SummaryFlowStep__screenshot') as HTMLImageElement;
90
+ expect(screenshot.src).toBeFalsy();
84
91
 
85
92
  // Accessibility and SEO are missing in timespan.
86
93
  const nullCategories = root.getAllByTestId('SummaryCategory__null');
@@ -108,8 +115,7 @@ describe('SummaryFlowStep', () => {
108
115
 
109
116
  expect(root.getByText('Snapshot (1)')).toBeTruthy();
110
117
 
111
- const screenshot =
112
- root.getByAltText('Screenshot of a page tested by Lighthouse') as HTMLImageElement;
118
+ const screenshot = root.getByTestId('SummaryFlowStep__screenshot') as HTMLImageElement;
113
119
  expect(screenshot.src).toMatch(/data:image\/jpeg;base64/);
114
120
 
115
121
  const gauges = root.getAllByTestId('CategoryScore');
@@ -4,13 +4,24 @@
4
4
  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
5
5
  */
6
6
 
7
+ import fs from 'fs';
8
+ import {dirname} from 'path';
9
+ import {fileURLToPath} from 'url';
10
+
7
11
  import {jest} from '@jest/globals';
8
12
  import {renderHook} from '@testing-library/preact-hooks';
9
13
  import {FunctionComponent} from 'preact';
10
14
  import {act} from 'preact/test-utils';
11
15
 
12
16
  import {FlowResultContext, useCurrentLhr} from '../src/util';
13
- import {flowResult} from './sample-flow';
17
+
18
+ const flowResult: LH.FlowResult = JSON.parse(
19
+ fs.readFileSync(
20
+ // eslint-disable-next-line max-len
21
+ `${dirname(fileURLToPath(import.meta.url))}/../../lighthouse-core/test/fixtures/fraggle-rock/reports/sample-lhrs.json`,
22
+ 'utf-8'
23
+ )
24
+ );
14
25
 
15
26
  let wrapper: FunctionComponent;
16
27
 
@@ -16,7 +16,6 @@
16
16
  {"path": "../report"},
17
17
  ],
18
18
  "include": [
19
- "**/*.js",
20
19
  "**/*.ts",
21
20
  "**/*.tsx",
22
21
  "./types",
@@ -19,9 +19,8 @@ declare global {
19
19
 
20
20
  // Expose global types in LH namespace.
21
21
  module LH {
22
+ export type FlowResult = FlowResult_;
22
23
  export type ConfigSettings = Settings.ConfigSettings;
23
-
24
- export import FlowResult = FlowResult_;
25
24
  }
26
25
  }
27
26
 
package/jest.config.js CHANGED
@@ -6,6 +6,18 @@
6
6
  'use strict';
7
7
 
8
8
  module.exports = {
9
+ collectCoverage: false,
10
+ coverageReporters: ['none'],
11
+ collectCoverageFrom: [
12
+ '**/lighthouse-core/**/*.js',
13
+ '**/lighthouse-cli/**/*.js',
14
+ '**/report/**/*.js',
15
+ '**/lighthouse-viewer/**/*.js',
16
+ ],
17
+ coveragePathIgnorePatterns: [
18
+ '/test/',
19
+ '/scripts/',
20
+ ],
9
21
  setupFilesAfterEnv: ['./lighthouse-core/test/test-utils.js'],
10
22
  testEnvironment: 'node',
11
23
  testMatch: [
@@ -14,10 +26,12 @@ module.exports = {
14
26
  '**/report/**/*-test.js',
15
27
  '**/lighthouse-core/test/fraggle-rock/**/*-test-pptr.js',
16
28
  '**/lighthouse-treemap/**/*-test.js',
29
+ '**/lighthouse-treemap/**/*-test-pptr.js',
17
30
  '**/lighthouse-viewer/**/*-test.js',
31
+ '**/lighthouse-viewer/**/*-test-pptr.js',
18
32
  '**/third-party/**/*-test.js',
19
33
  '**/clients/test/**/*-test.js',
20
- '**/shared/**/*-test.js',
34
+ '**/docs/**/*.test.js',
21
35
  ],
22
36
  transform: {},
23
37
  prettierPath: null,
@@ -61,11 +61,6 @@ async function begin() {
61
61
  commands.listAudits();
62
62
  }
63
63
 
64
- // Process terminating command
65
- if (cliFlags.listLocales) {
66
- commands.listLocales();
67
- }
68
-
69
64
  // Process terminating command
70
65
  if (cliFlags.listTraceCategories) {
71
66
  commands.listTraceCategories();
@@ -12,8 +12,7 @@ import fs from 'fs';
12
12
  import yargs from 'yargs';
13
13
  import * as yargsHelpers from 'yargs/helpers';
14
14
 
15
- import {LH_ROOT} from '../root.js';
16
- import {isObjectOfUnknownValues} from '../shared/type-verifiers.js';
15
+ import {isObjectOfUnknownValues} from '../lighthouse-core/lib/type-verifiers.js';
17
16
 
18
17
  /**
19
18
  * @param {string=} manualArgv
@@ -27,7 +26,6 @@ function getFlags(manualArgv, options = {}) {
27
26
  yargs(yargsHelpers.hideBin(process.argv));
28
27
 
29
28
  let parser = y.help('help')
30
- .version(JSON.parse(fs.readFileSync(`${LH_ROOT}/package.json`, 'utf-8')).version)
31
29
  .showHelpOnFail(false, 'Specify --help for available options')
32
30
 
33
31
  .usage('lighthouse <url> <options>')
@@ -105,11 +103,6 @@ function getFlags(manualArgv, options = {}) {
105
103
  default: false,
106
104
  describe: 'Prints a list of all available audits and exits',
107
105
  },
108
- 'list-locales': {
109
- type: 'boolean',
110
- default: false,
111
- describe: 'Prints a list of all supported locales and exits',
112
- },
113
106
  'list-trace-categories': {
114
107
  type: 'boolean',
115
108
  default: false,
@@ -215,7 +208,7 @@ function getFlags(manualArgv, options = {}) {
215
208
  },
216
209
  })
217
210
  .group([
218
- 'save-assets', 'list-all-audits', 'list-locales', 'list-trace-categories', 'print-config', 'additional-trace-categories',
211
+ 'save-assets', 'list-all-audits', 'list-trace-categories', 'print-config', 'additional-trace-categories',
219
212
  'config-path', 'preset', 'chrome-flags', 'port', 'hostname', 'form-factor', 'screenEmulation', 'emulatedUserAgent',
220
213
  'max-wait-for-load', 'enable-error-reporting', 'gather-mode', 'audit-mode',
221
214
  'only-audits', 'only-categories', 'skip-audits', 'budget-path',
@@ -319,7 +312,7 @@ function getFlags(manualArgv, options = {}) {
319
312
  // - We're just printing the config.
320
313
  // - We're in auditMode (and we have artifacts already)
321
314
  // If one of these don't apply, if no URL, stop the program and ask for one.
322
- const isPrintSomethingMode = argv.listAllAudits || argv.listLocales || argv.listTraceCategories || argv.printConfig;
315
+ const isPrintSomethingMode = argv.listAllAudits || argv.listTraceCategories || argv.printConfig;
323
316
  const isOnlyAuditMode = !!argv.auditMode && !argv.gatherMode;
324
317
  if (isPrintSomethingMode || isOnlyAuditMode) {
325
318
  return true;
@@ -7,4 +7,3 @@
7
7
 
8
8
  export {listAudits} from './list-audits.js';
9
9
  export {listTraceCategories} from './list-trace-categories.js';
10
- export {listLocales} from './list-locales.js';
@@ -17,7 +17,7 @@ import open from 'open';
17
17
 
18
18
  import * as Printer from './printer.js';
19
19
  import lighthouse from '../lighthouse-core/index.js';
20
- import {getLhrFilenamePrefix} from '../report/generator/file-namer.js';
20
+ import {getFilenamePrefix} from '../report/generator/file-namer.js';
21
21
  import * as assetSaver from '../lighthouse-core/lib/asset-saver.js';
22
22
  import URL from '../lighthouse-core/lib/url-shim.js';
23
23
 
@@ -137,7 +137,7 @@ async function saveResults(runnerResult, flags) {
137
137
  // Use the output path as the prefix for all generated files.
138
138
  // If no output path is set, generate a file prefix using the URL and date.
139
139
  const configuredPath = !flags.outputPath || flags.outputPath === 'stdout' ?
140
- getLhrFilenamePrefix(lhr) :
140
+ getFilenamePrefix(lhr) :
141
141
  flags.outputPath.replace(/\.\w{2,4}$/, '');
142
142
  const resolvedPath = path.resolve(cwd, configuredPath);
143
143
 
@@ -200,42 +200,26 @@ function pruneExpectations(localConsole, lhr, expected, reportOptions) {
200
200
  JSON.stringify(value, null, 2),
201
201
  `Actual Chromium version: ${getChromeVersion()}`,
202
202
  ].join(' '));
203
- if (Array.isArray(obj)) {
204
- obj.splice(Number(key), 1);
205
- } else {
206
- delete obj[key];
207
- }
203
+ delete obj[key];
208
204
  } else if (value._legacyOnly && isFraggleRock) {
209
205
  localConsole.log([
210
206
  `[${key}] marked legacy only but run is Fraggle Rock, pruning expectation:`,
211
207
  JSON.stringify(value, null, 2),
212
208
  ].join(' '));
213
- if (Array.isArray(obj)) {
214
- obj.splice(Number(key), 1);
215
- } else {
216
- delete obj[key];
217
- }
209
+ delete obj[key];
218
210
  } else if (value._fraggleRockOnly && !isFraggleRock) {
219
211
  localConsole.log([
220
212
  `[${key}] marked Fraggle Rock only but run is legacy, pruning expectation:`,
221
213
  JSON.stringify(value, null, 2),
222
214
  `Actual channel: ${lhr.configSettings.channel}`,
223
215
  ].join(' '));
224
- if (Array.isArray(obj)) {
225
- obj.splice(Number(key), 1);
226
- } else {
227
- delete obj[key];
228
- }
216
+ delete obj[key];
229
217
  } else if (value._skipInBundled && !isBundled) {
230
218
  localConsole.log([
231
219
  `[${key}] marked as skip in bundled and runner is bundled, pruning expectation:`,
232
220
  JSON.stringify(value, null, 2),
233
221
  ].join(' '));
234
- if (Array.isArray(obj)) {
235
- obj.splice(Number(key), 1);
236
- } else {
237
- delete obj[key];
238
- }
222
+ delete obj[key];
239
223
  } else {
240
224
  pruneRecursively(value);
241
225
  }
@@ -115,12 +115,11 @@ class UnusedBytes extends Audit {
115
115
  settings,
116
116
  };
117
117
  const networkRecords = await NetworkRecords.request(devtoolsLog, context);
118
- const hasContentfulRecords = networkRecords.some(record => record.transferSize);
119
118
 
120
119
  // Requesting load simulator requires non-empty network records.
121
120
  // Timespans are not guaranteed to have any network activity.
122
121
  // There are no bytes to be saved if no bytes were downloaded, so mark N/A if empty.
123
- if (!hasContentfulRecords && gatherContext.gatherMode === 'timespan') {
122
+ if (!networkRecords.length && gatherContext.gatherMode === 'timespan') {
124
123
  return {
125
124
  score: 1,
126
125
  notApplicable: true,
@@ -128,7 +128,7 @@ class UnusedJavaScript extends ByteEfficiencyAudit {
128
128
  })
129
129
  .filter(d => d.unused >= bundleSourceUnusedThreshold);
130
130
 
131
- const commonSourcePrefix = commonPrefix([...bundle.map.sourceInfos.keys()]);
131
+ const commonSourcePrefix = commonPrefix([...bundle.map._sourceInfos.keys()]);
132
132
  item.subItems = {
133
133
  type: 'subitems',
134
134
  items: topUnusedSourceSizes.map(({source, unused, total}) => {
@@ -31,7 +31,7 @@ class CrawlableAnchors extends Audit {
31
31
  title: str_(UIStrings.title),
32
32
  failureTitle: str_(UIStrings.failureTitle),
33
33
  description: str_(UIStrings.description),
34
- requiredArtifacts: ['AnchorElements', 'URL'],
34
+ requiredArtifacts: ['AnchorElements'],
35
35
  };
36
36
  }
37
37
 
@@ -39,12 +39,15 @@ class CrawlableAnchors extends Audit {
39
39
  * @param {LH.Artifacts} artifacts
40
40
  * @return {LH.Audit.Product}
41
41
  */
42
- static audit({AnchorElements: anchorElements, URL: url}) {
42
+ static audit({AnchorElements: anchorElements}) {
43
43
  const failingAnchors = anchorElements.filter(({
44
44
  rawHref,
45
+ listeners = [],
46
+ onclick = '',
45
47
  name = '',
46
48
  role = '',
47
49
  }) => {
50
+ onclick = onclick.replace( /\s/g, '');
48
51
  rawHref = rawHref.replace( /\s/g, '');
49
52
  name = name.trim();
50
53
  role = role.trim();
@@ -53,20 +56,19 @@ class CrawlableAnchors extends Audit {
53
56
  // Ignore mailto links even if they use one of the failing patterns. See https://github.com/GoogleChrome/lighthouse/issues/11443#issuecomment-694898412
54
57
  if (rawHref.startsWith('mailto:')) return;
55
58
 
59
+ const windowLocationRegExp = /window\.location=/;
60
+ const windowOpenRegExp = /window\.open\(/;
56
61
  const javaScriptVoidRegExp = /javascript:void(\(|)0(\)|)/;
57
62
 
58
63
  if (rawHref.startsWith('file:')) return true;
59
- if (name.length > 0) return;
64
+ if (windowLocationRegExp.test(onclick)) return true;
65
+ if (windowOpenRegExp.test(onclick)) return true;
66
+
67
+ const hasClickHandler = listeners.some(({type}) => type === 'click');
68
+ if (hasClickHandler || name.length > 0) return;
60
69
 
61
70
  if (rawHref === '') return true;
62
71
  if (javaScriptVoidRegExp.test(rawHref)) return true;
63
-
64
- // checking if rawHref is a valid
65
- try {
66
- new URL(rawHref, url.finalUrl);
67
- } catch (e) {
68
- return true;
69
- }
70
72
  });
71
73
 
72
74
  /** @type {LH.Audit.Details.Table['headings']} */
@@ -29,7 +29,8 @@ function computeGeneratedFileSizes(map, content) {
29
29
  const source = mapping.sourceURL;
30
30
  const lineNum = mapping.lineNumber;
31
31
  const colNum = mapping.columnNumber;
32
- const lastColNum = mapping.lastColumnNumber;
32
+ // @ts-expect-error: `lastColumnNumber` is not on types yet. This will eventually be added to CDT.
33
+ const lastColNum = /** @type {number=} */ (mapping.lastColumnNumber);
33
34
 
34
35
  // Webpack sometimes emits null mappings.
35
36
  // https://github.com/mozilla/source-map/pull/303
@@ -127,9 +127,9 @@ class UnusedJavascriptSummary {
127
127
  let offset = lineOffsets[mapping.lineNumber];
128
128
 
129
129
  offset += mapping.columnNumber;
130
- const lastColumnOfMapping = mapping.lastColumnNumber !== undefined ?
131
- mapping.lastColumnNumber - 1 :
132
- lineLengths[mapping.lineNumber];
130
+ const lastColumnOfMapping =
131
+ // @ts-expect-error: We will upstream lastColumnNumber to CDT eventually.
132
+ (mapping.lastColumnNumber - 1) || lineLengths[mapping.lineNumber];
133
133
  for (let i = mapping.columnNumber; i <= lastColumnOfMapping; i++) {
134
134
  if (wasteData.every(data => data.unusedByIndex[offset] === 1)) {
135
135
  const key = mapping.sourceURL || '(unmapped)';
@@ -8,7 +8,7 @@
8
8
  const defaultConfigPath = './default-config.js';
9
9
  const defaultConfig = require('./default-config.js');
10
10
  const constants = require('./constants.js');
11
- const format = require('../../shared/localization/format.js');
11
+ const i18n = require('./../lib/i18n/i18n.js');
12
12
  const validation = require('./../fraggle-rock/config/validation.js');
13
13
 
14
14
  const log = require('lighthouse-logger');
@@ -248,7 +248,7 @@ class Config {
248
248
  }
249
249
 
250
250
  // Printed config is more useful with localized strings.
251
- format.replaceIcuMessages(jsonConfig, jsonConfig.settings.locale);
251
+ i18n.replaceIcuMessages(jsonConfig, jsonConfig.settings.locale);
252
252
 
253
253
  return JSON.stringify(jsonConfig, null, 2);
254
254
  }
@@ -421,7 +421,6 @@ const defaultConfig = {
421
421
  categories: {
422
422
  'performance': {
423
423
  title: str_(UIStrings.performanceCategoryTitle),
424
- supportedModes: ['navigation', 'timespan', 'snapshot'],
425
424
  auditRefs: [
426
425
  {id: 'first-contentful-paint', weight: 10, group: 'metrics', acronym: 'FCP', relevantAudits: m2a.fcpRelevantAudits},
427
426
  {id: 'speed-index', weight: 10, group: 'metrics', acronym: 'SI'},
@@ -491,7 +490,6 @@ const defaultConfig = {
491
490
  title: str_(UIStrings.a11yCategoryTitle),
492
491
  description: str_(UIStrings.a11yCategoryDescription),
493
492
  manualDescription: str_(UIStrings.a11yCategoryManualDescription),
494
- supportedModes: ['navigation', 'snapshot'],
495
493
  // Audit weights are meant to match the aXe scoring system of
496
494
  // minor, moderate, serious, and critical.
497
495
  // See the audits listed at dequeuniversity.com/rules/axe/4.1.
@@ -556,7 +554,6 @@ const defaultConfig = {
556
554
  },
557
555
  'best-practices': {
558
556
  title: str_(UIStrings.bestPracticesCategoryTitle),
559
- supportedModes: ['navigation', 'timespan', 'snapshot'],
560
557
  auditRefs: [
561
558
  // Trust & Safety
562
559
  {id: 'is-on-https', weight: 1, group: 'best-practices-trust-safety'},
@@ -587,7 +584,6 @@ const defaultConfig = {
587
584
  title: str_(UIStrings.seoCategoryTitle),
588
585
  description: str_(UIStrings.seoCategoryDescription),
589
586
  manualDescription: str_(UIStrings.seoCategoryManualDescription),
590
- supportedModes: ['navigation', 'snapshot'],
591
587
  auditRefs: [
592
588
  {id: 'viewport', weight: 1, group: 'seo-mobile'},
593
589
  {id: 'document-title', weight: 1, group: 'seo-content'},
@@ -611,7 +607,6 @@ const defaultConfig = {
611
607
  title: str_(UIStrings.pwaCategoryTitle),
612
608
  description: str_(UIStrings.pwaCategoryDescription),
613
609
  manualDescription: str_(UIStrings.pwaCategoryManualDescription),
614
- supportedModes: ['navigation'],
615
610
  auditRefs: [
616
611
  // Installable
617
612
  {id: 'installable-manifest', weight: 2, group: 'pwa-installable'},
@@ -8,19 +8,9 @@
8
8
  const {snapshot} = require('./gather/snapshot-runner.js');
9
9
  const {startTimespan} = require('./gather/timespan-runner.js');
10
10
  const {navigation} = require('./gather/navigation-runner.js');
11
- const UserFlow = require('./user-flow.js');
12
-
13
- /**
14
- * @param {import('puppeteer').Page} page
15
- * @param {UserFlow.UserFlowOptions} [options]
16
- */
17
- async function startFlow(page, options) {
18
- return new UserFlow(page, options);
19
- }
20
11
 
21
12
  module.exports = {
22
13
  snapshot,
23
14
  startTimespan,
24
15
  navigation,
25
- startFlow,
26
16
  };