lighthouse 8.4.0 → 8.5.0-dev.20210921

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 (107) hide show
  1. package/changelog.md +79 -0
  2. package/flow-report/assets/styles.css +85 -61
  3. package/flow-report/src/app.tsx +6 -2
  4. package/flow-report/src/common.tsx +0 -41
  5. package/flow-report/src/icons.tsx +11 -0
  6. package/flow-report/src/summary/summary.tsx +32 -25
  7. package/flow-report/src/topbar.tsx +60 -0
  8. package/flow-report/src/util.ts +0 -1
  9. package/flow-report/src/wrappers/{gauge.tsx → category-score.tsx} +11 -5
  10. package/flow-report/test/summary/summary-test.tsx +3 -3
  11. package/flow-report/tsconfig.json +6 -22
  12. package/{lighthouse-core/gather/gatherers/gather-context.js → lighthouse-cli/.eslintrc.cjs} +20 -18
  13. package/lighthouse-cli/bin.js +31 -21
  14. package/lighthouse-cli/cli-flags.js +12 -7
  15. package/lighthouse-cli/commands/commands.js +2 -7
  16. package/lighthouse-cli/commands/list-audits.js +2 -2
  17. package/lighthouse-cli/commands/list-trace-categories.js +2 -2
  18. package/lighthouse-cli/index.js +3 -1
  19. package/lighthouse-cli/package.json +4 -0
  20. package/lighthouse-cli/printer.js +4 -3
  21. package/lighthouse-cli/run.js +14 -15
  22. package/lighthouse-cli/sentry-prompt.js +5 -6
  23. package/lighthouse-cli/test/smokehouse/frontends/back-compat-util.js +1 -1
  24. package/lighthouse-cli/test/smokehouse/frontends/lib.js +5 -4
  25. package/lighthouse-cli/test/smokehouse/frontends/node.js +1 -1
  26. package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +93 -14
  27. package/lighthouse-cli/test/smokehouse/lib/child-process-error.js +1 -1
  28. package/lighthouse-cli/test/smokehouse/lib/concurrent-mapper.js +1 -1
  29. package/lighthouse-cli/test/smokehouse/lib/local-console.js +1 -1
  30. package/lighthouse-cli/test/smokehouse/lighthouse-runners/bundle.js +20 -16
  31. package/lighthouse-cli/test/smokehouse/lighthouse-runners/cli.js +15 -12
  32. package/lighthouse-cli/test/smokehouse/report-assert.js +23 -13
  33. package/lighthouse-cli/test/smokehouse/smokehouse.js +32 -11
  34. package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +0 -2
  35. package/lighthouse-core/audits/byte-efficiency/uses-responsive-images-snapshot.js +6 -1
  36. package/lighthouse-core/audits/dobetterweb/js-libraries.js +5 -0
  37. package/lighthouse-core/audits/dobetterweb/uses-http2.js +1 -0
  38. package/lighthouse-core/audits/lcp-lazy-loaded.js +1 -0
  39. package/lighthouse-core/audits/oopif-iframe-test-audit.js +30 -0
  40. package/lighthouse-core/computed/metrics/metric.js +2 -1
  41. package/lighthouse-core/config/config-helpers.js +47 -3
  42. package/lighthouse-core/config/config.js +3 -46
  43. package/lighthouse-core/config/default-config.js +0 -1
  44. package/lighthouse-core/fraggle-rock/config/config.js +22 -4
  45. package/lighthouse-core/fraggle-rock/config/default-config.js +0 -9
  46. package/lighthouse-core/fraggle-rock/config/filters.js +3 -0
  47. package/lighthouse-core/fraggle-rock/config/validation.js +19 -1
  48. package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +8 -3
  49. package/lighthouse-core/fraggle-rock/gather/driver.js +10 -0
  50. package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +40 -19
  51. package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +3 -0
  52. package/lighthouse-core/fraggle-rock/gather/session.js +44 -1
  53. package/lighthouse-core/fraggle-rock/gather/snapshot-runner.js +4 -1
  54. package/lighthouse-core/fraggle-rock/gather/timespan-runner.js +5 -1
  55. package/lighthouse-core/gather/devtools-log.js +9 -3
  56. package/lighthouse-core/gather/driver/network-monitor.js +57 -13
  57. package/lighthouse-core/gather/driver/prepare.js +43 -17
  58. package/lighthouse-core/gather/driver/target-manager.js +125 -0
  59. package/lighthouse-core/gather/driver.js +20 -0
  60. package/lighthouse-core/gather/fetcher.js +2 -2
  61. package/lighthouse-core/gather/gather-runner.js +1 -1
  62. package/lighthouse-core/gather/gatherers/css-usage.js +0 -2
  63. package/lighthouse-core/gather/gatherers/devtools-log.js +11 -9
  64. package/lighthouse-core/gather/gatherers/js-usage.js +0 -1
  65. package/lighthouse-core/gather/gatherers/script-elements.js +4 -5
  66. package/lighthouse-core/gather/gatherers/seo/robots-txt.js +3 -3
  67. package/lighthouse-core/gather/gatherers/trace.js +4 -5
  68. package/lighthouse-core/index.js +4 -0
  69. package/lighthouse-core/lib/emulation.js +0 -1
  70. package/lighthouse-core/lib/i18n/locales/en-US.json +6 -0
  71. package/lighthouse-core/lib/i18n/locales/en-XL.json +6 -0
  72. package/lighthouse-core/lib/network-recorder.js +8 -0
  73. package/lighthouse-core/lib/proto-preprocessor.js +5 -10
  74. package/lighthouse-core/runner.js +1 -3
  75. package/package.json +12 -9
  76. package/readme.md +2 -0
  77. package/report/assets/styles.css +120 -12
  78. package/report/assets/templates.html +13 -0
  79. package/report/clients/psi.js +5 -1
  80. package/report/generator/tsconfig.json +5 -16
  81. package/report/renderer/category-renderer.js +58 -5
  82. package/report/renderer/components.js +25 -5
  83. package/report/renderer/performance-category-renderer.js +5 -5
  84. package/report/renderer/pwa-category-renderer.js +10 -0
  85. package/report/renderer/report-renderer.js +12 -3
  86. package/report/renderer/report-ui-features.js +1 -4
  87. package/report/test/renderer/category-renderer-test.js +19 -0
  88. package/report/tsconfig.json +6 -21
  89. package/report/types/report-result.d.ts +1 -1
  90. package/root.js +3 -1
  91. package/third-party/snyk/snapshot.json +2 -2
  92. package/tsconfig-all.json +15 -0
  93. package/tsconfig-base.json +24 -0
  94. package/tsconfig.json +8 -18
  95. package/types/artifacts.d.ts +7 -7
  96. package/types/config.d.ts +1 -1
  97. package/types/gatherer.d.ts +7 -1
  98. package/types/lhr/flow.d.ts +0 -1
  99. package/types/lhr/lhr.d.ts +5 -1
  100. package/types/lhr/tsconfig.json +4 -14
  101. package/types/protocol.d.ts +2 -0
  102. package/types/smokehouse.d.ts +2 -1
  103. package/dist/report/flow.js +0 -149
  104. package/dist/report/standalone.js +0 -228
  105. package/flow-report/test/common-test.tsx +0 -131
  106. package/lighthouse-core/gather/gatherers/host-form-factor.js +0 -31
  107. package/lighthouse-core/gather/gatherers/host-user-agent.js +0 -29
package/changelog.md CHANGED
@@ -1,3 +1,82 @@
1
+ <a name="8.5.0"></a>
2
+ # 8.5.0 (2021-09-21)
3
+ [Full Changelog](https://github.com/GoogleChrome/lighthouse/compare/v8.4.0...v8.5.0)
4
+
5
+ We expect this release to ship in the DevTools of [Chrome 96](https://chromiumdash.appspot.com/schedule), and to PageSpeed Insights within 2 weeks.
6
+
7
+ ## New Contributors
8
+
9
+ Thanks to our new contributors 👽🐷🐰🐯🐻!
10
+
11
+ Konstantin Popov @KonstHardy
12
+ Can Umay @canumay
13
+
14
+ ## Core
15
+
16
+ * lazy-lcp: fix failureTitle in lcp-lazy-loaded ([#13049](https://github.com/GoogleChrome/lighthouse/pull/13049))
17
+ * tracing: remove cpu_profiler.hires ([#13056](https://github.com/GoogleChrome/lighthouse/pull/13056))
18
+ * tsc: add base tsconfig for config inheritance ([#13072](https://github.com/GoogleChrome/lighthouse/pull/13072))
19
+ * make main tsc compile cacheable ([#13069](https://github.com/GoogleChrome/lighthouse/pull/13069))
20
+
21
+ ## ⛏️👷 Fraggle Rock
22
+
23
+ Support for auditing user flows ([#11313](https://github.com/GoogleChrome/lighthouse/issues/11313))
24
+
25
+ * cleanup driver on run completion ([#13062](https://github.com/GoogleChrome/lighthouse/pull/13062))
26
+ * setup emulation and throttling for timespans ([#13058](https://github.com/GoogleChrome/lighthouse/pull/13058))
27
+ * support additionalTraceCategories ([#13030](https://github.com/GoogleChrome/lighthouse/pull/13030))
28
+ * add support for plugins ([#13028](https://github.com/GoogleChrome/lighthouse/pull/13028))
29
+ * move GatherContext to baseArtifacts ([#13033](https://github.com/GoogleChrome/lighthouse/pull/13033))
30
+ * preserve traces on failed page load ([#13027](https://github.com/GoogleChrome/lighthouse/pull/13027))
31
+ * move HostUserAgent/FormFactor back to base artifacts ([#12969](https://github.com/GoogleChrome/lighthouse/pull/12969))
32
+ * use devtools throttling by default in timespan mode ([#13013](https://github.com/GoogleChrome/lighthouse/pull/13013))
33
+ * collect OOPIF network data ([#12992](https://github.com/GoogleChrome/lighthouse/pull/12992))
34
+ * flow: summary sections ([#13086](https://github.com/GoogleChrome/lighthouse/pull/13086))
35
+ * flow: topbar ([#13065](https://github.com/GoogleChrome/lighthouse/pull/13065))
36
+
37
+ ## CLI
38
+
39
+ * convert to ES modules ([#13045](https://github.com/GoogleChrome/lighthouse/pull/13045))
40
+
41
+ ## Report
42
+
43
+ * make metric value more prominent in table ([#13036](https://github.com/GoogleChrome/lighthouse/pull/13036))
44
+ * 3p-filter: drop for/id as elements are already nested ([#13067](https://github.com/GoogleChrome/lighthouse/pull/13067))
45
+ * add gatherMode option to category score ([#13029](https://github.com/GoogleChrome/lighthouse/pull/13029))
46
+ * add fractional category scores ([#13009](https://github.com/GoogleChrome/lighthouse/pull/13009))
47
+
48
+ ## Deps
49
+
50
+ * update to latest @rollup/plugin-typescript ([#13075](https://github.com/GoogleChrome/lighthouse/pull/13075))
51
+ * snyk: update snyk snapshot ([#13019](https://github.com/GoogleChrome/lighthouse/pull/13019))
52
+
53
+ ## Clients
54
+
55
+ * lr: bundle smokehouse as commonjs ([#13074](https://github.com/GoogleChrome/lighthouse/pull/13074))
56
+ * add canonical link to viewer and treemap ([#13032](https://github.com/GoogleChrome/lighthouse/pull/13032))
57
+
58
+ ## Docs
59
+
60
+ * readme: add Peyk to the list of integrations ([#13055](https://github.com/GoogleChrome/lighthouse/pull/13055))
61
+
62
+ ## Tests
63
+
64
+ * add FR integration scenarios ([#13092](https://github.com/GoogleChrome/lighthouse/pull/13092))
65
+ * update SVGOMG expectations ([#13088](https://github.com/GoogleChrome/lighthouse/pull/13088))
66
+ * restore use of latest node 16 in CI ([#13079](https://github.com/GoogleChrome/lighthouse/pull/13079))
67
+ * eslint: trailing commas for import/export ([#13059](https://github.com/GoogleChrome/lighthouse/pull/13059))
68
+ * smokehouse: add flag for test sharding ([#13047](https://github.com/GoogleChrome/lighthouse/pull/13047))
69
+ * smokehouse: convert to ES modules ([#13046](https://github.com/GoogleChrome/lighthouse/pull/13046))
70
+ * fix flaky robots smoke failure ([#13031](https://github.com/GoogleChrome/lighthouse/pull/13031))
71
+ * smoke: upload smokehouse artifacts on failure ([#13010](https://github.com/GoogleChrome/lighthouse/pull/13010))
72
+
73
+ ## Misc
74
+
75
+ * build: fix minifyFileTransform stream bug in Node 16 ([#13073](https://github.com/GoogleChrome/lighthouse/pull/13073))
76
+ * fix typo in lighthouse-treemap/app/src/main.js ([#13076](https://github.com/GoogleChrome/lighthouse/pull/13076))
77
+ * proto: add i18n.icuMessagePaths ([#13068](https://github.com/GoogleChrome/lighthouse/pull/13068))
78
+ * remove all FR-COMPAT todos ([#13023](https://github.com/GoogleChrome/lighthouse/pull/13023))
79
+
1
80
  <a name="8.4.0"></a>
2
81
  # 8.4.0 (2021-09-08)
3
82
  [Full Changelog](https://github.com/GoogleChrome/lighthouse/compare/v8.3.0...v8.4.0)
@@ -8,8 +8,10 @@
8
8
  --app-font-size: 12px;
9
9
  --base-spacing: 16px;
10
10
  --category-summary-font-size: 18px;
11
+ --double-base-spacing: calc(var(--base-spacing) * 2);
11
12
  --gather-mode-icon-size: 16px;
12
13
  --half-base-spacing: calc(var(--base-spacing) / 2);
14
+ --separator-color: var(--color-gray-300);
13
15
  --sidebar-flow-step-navigation-font-size: 14px;
14
16
  --sidebar-selected-bg-color: #DDEEFF;
15
17
  --sidebar-summary-font-size: 14px;
@@ -17,18 +19,58 @@
17
19
  --summary-flow-step-label-font-size: 16px;
18
20
  --summary-subtitle-font-size: 16px;
19
21
  --summary-title-font-size: 32px;
22
+ --topbar-title-font-size: 14px;
20
23
  }
21
24
 
22
25
  .App {
23
26
  display: grid;
24
- grid-template-areas: "side report";
27
+ grid-template-areas:
28
+ "topbar topbar"
29
+ "sidebar content";
25
30
  grid-template-columns: min-content auto;
31
+ grid-template-rows: min-content auto;
26
32
  height: 100vh;
27
33
  max-width: 100vw;
28
34
  font-size: var(--app-font-size);
29
35
  }
36
+ .App--collapsed {
37
+ grid-template-columns: 0px auto;
38
+ }
39
+ .App--collapsed .Sidebar {
40
+ display: none;
41
+ }
42
+
43
+ .Topbar {
44
+ grid-area: topbar;
45
+ display: flex;
46
+ align-items: center;
47
+ border-bottom: 1px solid var(--separator-color);
48
+ }
49
+
50
+ .Topbar__menu {
51
+ padding: var(--base-spacing);
52
+ cursor: pointer;
53
+ display: flex;
54
+ -webkit-touch-callout: none;
55
+ -webkit-user-select: none;
56
+ -khtml-user-select: none;
57
+ -moz-user-select: none;
58
+ -ms-user-select: none;
59
+ user-select: none;
60
+ }
61
+
62
+ .Topbar__logo {
63
+ display: flex;
64
+ margin-right: var(--half-base-spacing);
65
+ }
66
+
67
+ .Topbar__title {
68
+ font-size: var(--topbar-title-font-size);
69
+ font-weight: bold;
70
+ }
30
71
 
31
72
  .Content {
73
+ grid-area: content;
32
74
  overflow-y: auto;
33
75
  }
34
76
 
@@ -48,59 +90,15 @@
48
90
  background-color: var(--color-blue-A700);
49
91
  }
50
92
 
51
- .CategoryRatio {
52
- justify-self: center;
53
- display: flex;
54
- align-items: center;
55
- justify-content: center;
56
- font-size: var(--category-summary-font-size);
57
- min-height: var(--gauge-circle-size);
58
- min-width: var(--gauge-circle-size);
59
- text-decoration: none;
60
- }
61
- .CategoryRatio::before {
62
- content: '';
63
- height: var(--score-icon-size);
64
- width: var(--score-icon-size);
65
- margin: var(--score-icon-margin);
66
- }
67
- .CategoryRatio--pass {
68
- color: var(--color-pass);
69
- }
70
- .CategoryRatio--pass::before {
71
- background-color: var(--color-pass);
72
- border-radius: 50%;
73
- }
74
- .CategoryRatio--average {
75
- color: var(--color-average);
76
- }
77
- .CategoryRatio--average::before {
78
- background-color: var(--color-average);
79
- }
80
- .CategoryRatio--fail {
81
- color: var(--color-fail);
82
- }
83
- .CategoryRatio--fail::before {
84
- border-left: calc(var(--score-icon-size) / 2) solid transparent;
85
- border-right: calc(var(--score-icon-size) / 2) solid transparent;
86
- border-bottom: var(--score-icon-size) solid var(--color-fail);
87
- }
88
- .CategoryRatio--null {
89
- color: var(--color-gray-700);
90
- }
91
- .CategoryRatio--null::before {
92
- border-radius: 50%;
93
- border: 2px solid var(--color-gray-700);
94
- }
95
-
96
93
  .Separator {
97
94
  height: 1px;
98
95
  width: 100%;
99
- background-color: var(--color-gray-300);
96
+ background-color: var(--separator-color);
100
97
  }
101
98
 
102
99
  .Sidebar {
103
- border-right: 1px solid var(--color-gray-300);
100
+ grid-area: sidebar;
101
+ border-right: 1px solid var(--separator-color);
104
102
  }
105
103
  .Sidebar a {
106
104
  color: var(--color-gray-800);
@@ -192,14 +190,21 @@
192
190
  }
193
191
 
194
192
  .Summary {
195
- margin: 0 auto;
196
- min-width: var(--report-width);
197
- width: max-content;
198
- max-width: 90%;
193
+ display: grid;
194
+ grid-template-columns: minmax(5%, 1fr) auto minmax(5%, 1fr);
195
+ justify-content: start;
196
+ width: 100%;
197
+ }
198
+ .Summary > * {
199
+ grid-column: 2;
200
+ }
201
+ .Summary > .Separator {
202
+ grid-column: 1 / span 3;
199
203
  }
200
204
 
201
205
  .SummaryHeader {
202
- margin: var(--base-spacing) 0;
206
+ margin: calc(var(--base-spacing) * 3) 0px;
207
+ width: 100%;
203
208
  }
204
209
 
205
210
  .SummaryHeader__title {
@@ -211,12 +216,26 @@
211
216
  font-size: var(--summary-subtitle-font-size);
212
217
  }
213
218
 
219
+ .SummarySectionHeader {
220
+ margin-top: var(--double-base-spacing);
221
+ }
222
+
223
+ .SummarySectionHeader__content {
224
+ margin: var(--base-spacing) 0px;
225
+ }
226
+
214
227
  .SummaryFlow {
215
228
  width: 100%;
229
+ max-width: max-content;
216
230
  display: grid;
217
231
  grid-auto-rows: min-content;
218
232
  grid-template-columns: min-content min-content 4fr 1fr 1fr 1fr 1fr;
219
233
  align-items: center;
234
+ margin: var(--base-spacing) 0px;
235
+ }
236
+ .SummaryFlow .lh-fraction__content {
237
+ padding: 0px;
238
+ min-width: unset;
220
239
  }
221
240
 
222
241
  /* Hide top segment of sidebar flow */
@@ -259,11 +278,18 @@
259
278
  }
260
279
 
261
280
  .SummaryFlowStep__label {
281
+ grid-column: 3;
282
+ margin: var(--half-base-spacing);
283
+ }
284
+
285
+ .SummaryFlowStep__mode {
286
+ color: var(--color-gray-700);
287
+ }
288
+
289
+ .SummaryFlowStep__link {
262
290
  font-size: var(--summary-flow-step-label-font-size);
263
291
  color: var(--color-gray-800);
264
292
  text-decoration: underline;
265
- grid-column: 3;
266
- margin: var(--half-base-spacing);
267
293
  }
268
294
 
269
295
  .SummaryCategory {
@@ -282,7 +308,8 @@
282
308
  align-items: center;
283
309
  justify-content: center;
284
310
  padding: var(--half-base-spacing);
285
- background-color: var(--color-gray-200);
311
+ background-color: var(--color-gray-100);
312
+ border-top: 1px solid var(--color-gray-300);
286
313
  text-align: center;
287
314
  }
288
315
  .SummaryNavigationHeader__url {
@@ -290,14 +317,11 @@
290
317
  text-align: left;
291
318
  }
292
319
 
293
- .SummaryFlowStep__divider {
320
+ .SummaryFlowStep__separator {
294
321
  display: contents;
295
322
  }
296
-
297
- .SummaryFlowStep__divider--line {
323
+ .SummaryFlowStep__separator > .Separator {
298
324
  grid-column-end: span 5;
299
- height: 1px;
300
- background-color: var(--color-gray-300);
301
325
  }
302
326
 
303
327
  .SummaryCategory__null {
@@ -5,12 +5,14 @@
5
5
  */
6
6
 
7
7
  import {FunctionComponent} from 'preact';
8
+ import {useState} from 'preact/hooks';
8
9
 
9
10
  import {ReportRendererProvider} from './wrappers/report-renderer';
10
11
  import {Sidebar} from './sidebar/sidebar';
11
12
  import {Summary} from './summary/summary';
12
- import {FlowResultContext, useCurrentLhr} from './util';
13
+ import {classNames, FlowResultContext, useCurrentLhr} from './util';
13
14
  import {Report} from './wrappers/report';
15
+ import {Topbar} from './topbar';
14
16
 
15
17
  const Content: FunctionComponent = () => {
16
18
  const currentLhr = useCurrentLhr();
@@ -27,10 +29,12 @@ const Content: FunctionComponent = () => {
27
29
  };
28
30
 
29
31
  export const App: FunctionComponent<{flowResult: LH.FlowResult}> = ({flowResult}) => {
32
+ const [collapsed, setCollapsed] = useState(false);
30
33
  return (
31
34
  <FlowResultContext.Provider value={flowResult}>
32
35
  <ReportRendererProvider>
33
- <div className="App">
36
+ <div className={classNames('App', {'App--collapsed': collapsed})}>
37
+ <Topbar onMenuClick={() => setCollapsed(c => !c)} />
34
38
  <Sidebar/>
35
39
  <Content/>
36
40
  </div>
@@ -6,49 +6,8 @@
6
6
 
7
7
  import {FunctionComponent} from 'preact';
8
8
 
9
- import {Util} from '../../report/renderer/util';
10
9
  import {NavigationIcon, SnapshotIcon, TimespanIcon} from './icons';
11
10
 
12
- /**
13
- * Summarizes the category as a ratio of passed audits to total audits.
14
- * The rating color and icon are calculated from the passed/total ratio, not the category score.
15
- * A category will be given a null rating and color if none of its audits are weighted.
16
- */
17
- export const CategoryRatio: FunctionComponent<{
18
- category: LH.ReportResult.Category,
19
- audits: LH.Result['audits'],
20
- href: string,
21
- }> = ({category, audits, href}) => {
22
- const numAudits = category.auditRefs.length;
23
-
24
- let numPassed = 0;
25
- let totalWeight = 0;
26
- for (const auditRef of category.auditRefs) {
27
- totalWeight += auditRef.weight;
28
- const audit = audits[auditRef.id];
29
- if (!audit) {
30
- console.warn(`Could not find score for audit '${auditRef.id}', treating as failed.`);
31
- continue;
32
- }
33
- if (Util.showAsPassed(audit)) numPassed++;
34
- }
35
-
36
- const ratio = numPassed / numAudits;
37
- let rating = Util.calculateRating(ratio);
38
-
39
- // If none of the available audits can affect the score, a rating isn't useful.
40
- // The flow report should display the ratio with neutral icon and coloring in this case.
41
- if (totalWeight === 0) {
42
- rating = 'null';
43
- }
44
-
45
- return (
46
- <a href={href} className={`CategoryRatio CategoryRatio--${rating}`} data-testid="CategoryRatio">
47
- {`${numPassed}/${numAudits}`}
48
- </a>
49
- );
50
- };
51
-
52
11
  export const Separator: FunctionComponent = () => {
53
12
  return <div className="Separator" role="separator"></div>;
54
13
  };
@@ -94,3 +94,14 @@ export const CpuIcon: FunctionComponent = () => {
94
94
  </svg>
95
95
  );
96
96
  };
97
+
98
+ export const HamburgerIcon: FunctionComponent = () => {
99
+ return (
100
+ <svg viewBox="0 0 18 12" width="18" height="12" role="img">
101
+ <rect width="18" height="2"></rect>
102
+ <rect y="5" width="18" height="2"></rect>
103
+ <rect y="10" width="18" height="2"></rect>
104
+ </svg>
105
+ );
106
+ };
107
+
@@ -7,14 +7,18 @@
7
7
  import {FunctionComponent} from 'preact';
8
8
  import {useMemo} from 'preact/hooks';
9
9
 
10
- import {Gauge} from '../wrappers/gauge';
11
- import {FlowSegment} from '../common';
12
- import {CategoryRatio} from '../common';
10
+ import {FlowSegment, Separator} from '../common';
13
11
  import {getScreenDimensions, getScreenshot, useDerivedStepNames, useFlowResult} from '../util';
14
12
  import {Util} from '../../../report/renderer/util';
13
+ import {CategoryScore} from '../wrappers/category-score';
15
14
 
16
15
  const DISPLAYED_CATEGORIES = ['performance', 'accessibility', 'best-practices', 'seo'];
17
16
  const THUMBNAIL_WIDTH = 50;
17
+ const MODE_DESCRIPTIONS: Record<LH.Result.GatherMode, string> = {
18
+ 'navigation': 'Page load',
19
+ 'timespan': 'User interactions',
20
+ 'snapshot': 'Captured state of page',
21
+ };
18
22
 
19
23
  const SummaryNavigationHeader: FunctionComponent<{url: string}> = ({url}) => {
20
24
  return (
@@ -30,27 +34,19 @@ const SummaryNavigationHeader: FunctionComponent<{url: string}> = ({url}) => {
30
34
  };
31
35
 
32
36
  const SummaryCategory: FunctionComponent<{
33
- gatherMode: LH.Result.GatherMode,
34
- audits: LH.ReportResult['audits'],
35
37
  category: LH.ReportResult.Category|undefined,
36
38
  href: string,
37
- }> = ({gatherMode, audits, category, href}) => {
39
+ gatherMode: LH.Result.GatherMode,
40
+ }> = ({category, href, gatherMode}) => {
38
41
  return (
39
42
  <div className="SummaryCategory">
40
43
  {
41
44
  category ?
42
- (
43
- gatherMode === 'navigation' ?
44
- <Gauge
45
- category={category}
46
- href={href}
47
- /> :
48
- <CategoryRatio
49
- category={category}
50
- audits={audits}
51
- href={href}
52
- />
53
- ) :
45
+ <CategoryScore
46
+ category={category}
47
+ href={href}
48
+ gatherMode={gatherMode}
49
+ /> :
54
50
  <div
55
51
  className="SummaryCategory__null"
56
52
  data-testid="SummaryCategory__null"
@@ -68,7 +64,6 @@ export const SummaryFlowStep: FunctionComponent<{
68
64
  label: string,
69
65
  hashIndex: number,
70
66
  }> = ({lhr, label, hashIndex}) => {
71
- // TODO(FR-COMPAT): Store report results globally.
72
67
  const reportResult = useMemo(() => Util.prepareReportResult(lhr), [lhr]);
73
68
 
74
69
  const screenshot = reportResult.gatherMode !== 'timespan' ? getScreenshot(reportResult) : null;
@@ -82,9 +77,9 @@ export const SummaryFlowStep: FunctionComponent<{
82
77
  {
83
78
  lhr.gatherMode === 'navigation' || hashIndex === 0 ?
84
79
  <SummaryNavigationHeader url={lhr.finalUrl}/> :
85
- <div className="SummaryFlowStep__divider">
80
+ <div className="SummaryFlowStep__separator">
86
81
  <FlowSegment/>
87
- <div className="SummaryFlowStep__divider--line"/>
82
+ <Separator/>
88
83
  </div>
89
84
  }
90
85
  <img
@@ -94,15 +89,17 @@ export const SummaryFlowStep: FunctionComponent<{
94
89
  style={{width: THUMBNAIL_WIDTH, maxHeight: thumbnailHeight}}
95
90
  />
96
91
  <FlowSegment mode={lhr.gatherMode}/>
97
- <a className="SummaryFlowStep__label" href={`#index=${hashIndex}`}>{label}</a>
92
+ <div className="SummaryFlowStep__label">
93
+ <div className="SummaryFlowStep__mode">{MODE_DESCRIPTIONS[lhr.gatherMode]}</div>
94
+ <a className="SummaryFlowStep__link" href={`#index=${hashIndex}`}>{label}</a>
95
+ </div>
98
96
  {
99
97
  DISPLAYED_CATEGORIES.map(c => (
100
98
  <SummaryCategory
101
99
  key={c}
102
- gatherMode={reportResult.gatherMode}
103
100
  category={reportResult.categories[c]}
104
- audits={reportResult.audits}
105
101
  href={`#index=${hashIndex}&anchor=${c}`}
102
+ gatherMode={lhr.gatherMode}
106
103
  />
107
104
  ))
108
105
  }
@@ -153,7 +150,6 @@ export const SummaryHeader: FunctionComponent = () => {
153
150
  }
154
151
  }
155
152
 
156
- // TODO(FR-COMPAT): Pluralize UI strings.
157
153
  const subtitleCounts = [];
158
154
  if (numNavigation) subtitleCounts.push(`${numNavigation} navigation reports`);
159
155
  if (numTimespan) subtitleCounts.push(`${numTimespan} timespan reports`);
@@ -168,10 +164,21 @@ export const SummaryHeader: FunctionComponent = () => {
168
164
  );
169
165
  };
170
166
 
167
+ const SummarySectionHeader: FunctionComponent = ({children}) => {
168
+ return (
169
+ <div className="SummarySectionHeader">
170
+ <div className="SummarySectionHeader__content">{children}</div>
171
+ <Separator/>
172
+ </div>
173
+ );
174
+ };
175
+
171
176
  export const Summary: FunctionComponent = () => {
172
177
  return (
173
178
  <div className="Summary" data-testid="Summary">
174
179
  <SummaryHeader/>
180
+ <Separator/>
181
+ <SummarySectionHeader>ALL REPORTS</SummarySectionHeader>
175
182
  <SummaryFlow/>
176
183
  </div>
177
184
  );
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @license Copyright 2021 The Lighthouse Authors. All Rights Reserved.
3
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
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
+ */
6
+
7
+ import {FunctionComponent, JSX} from 'preact';
8
+
9
+ import {HamburgerIcon} from './icons';
10
+
11
+ /* eslint-disable max-len */
12
+ const Logo: FunctionComponent = () => {
13
+ return (
14
+ <svg height="24" width="24" viewBox="0 0 24 24" role="img">
15
+ <defs>
16
+ <linearGradient x1="57.456%" y1="13.086%" x2="18.259%" y2="72.322%" id="Topbar__logo--a">
17
+ <stop stop-color="#262626" stop-opacity=".1" offset="0%"/>
18
+ <stop stop-color="#262626" stop-opacity="0" offset="100%"/>
19
+ </linearGradient>
20
+ <linearGradient x1="100%" y1="50%" x2="0%" y2="50%" id="Topbar__logo--b">
21
+ <stop stop-color="#262626" stop-opacity=".1" offset="0%"/>
22
+ <stop stop-color="#262626" stop-opacity="0" offset="100%"/>
23
+ </linearGradient>
24
+ <linearGradient x1="58.764%" y1="65.756%" x2="36.939%" y2="50.14%" id="Topbar__logo--c">
25
+ <stop stop-color="#262626" stop-opacity=".1" offset="0%"/>
26
+ <stop stop-color="#262626" stop-opacity="0" offset="100%"/>
27
+ </linearGradient>
28
+ <linearGradient x1="41.635%" y1="20.358%" x2="72.863%" y2="85.424%" id="Topbar__logo--d">
29
+ <stop stop-color="#FFF" stop-opacity=".1" offset="0%"/>
30
+ <stop stop-color="#FFF" stop-opacity="0" offset="100%"/>
31
+ </linearGradient>
32
+ </defs>
33
+ <g fill="none" fill-rule="evenodd">
34
+ <path d="M12 3l4.125 2.625v3.75H18v2.25h-1.688l1.5 9.375H6.188l1.5-9.375H6v-2.25h1.875V5.648L12 3zm2.201 9.938L9.54 14.633 9 18.028l5.625-2.062-.424-3.028zM12.005 5.67l-1.88 1.207v2.498h3.75V6.86l-1.87-1.19z" fill="#F44B21"/>
35
+ <path fill="#FFF" d="M14.201 12.938L9.54 14.633 9 18.028l5.625-2.062z"/>
36
+ <path d="M6 18c-2.042 0-3.95-.01-5.813 0l1.5-9.375h4.326L6 18z" fill="url(#Topbar__logo--a)" fill-rule="nonzero" transform="translate(6 3)"/>
37
+ <path fill="#FFF176" fill-rule="nonzero" d="M13.875 9.375v-2.56l-1.87-1.19-1.88 1.207v2.543z"/>
38
+ <path fill="url(#Topbar__logo--b)" fill-rule="nonzero" d="M0 6.375h6v2.25H0z" transform="translate(6 3)"/>
39
+ <path fill="url(#Topbar__logo--c)" fill-rule="nonzero" d="M6 6.375H1.875v-3.75L6 0z" transform="translate(6 3)"/>
40
+ <path fill="url(#Topbar__logo--d)" fill-rule="nonzero" d="M6 0l4.125 2.625v3.75H12v2.25h-1.688l1.5 9.375H.188l1.5-9.375H0v-2.25h1.875V2.648z" transform="translate(6 3)"/>
41
+ </g>
42
+ </svg>
43
+ );
44
+ };
45
+ /* eslint-enable max-len */
46
+
47
+ export const Topbar: FunctionComponent<{onMenuClick: JSX.MouseEventHandler<HTMLDivElement>}> =
48
+ ({onMenuClick}) => {
49
+ return (
50
+ <div className="Topbar">
51
+ <div className="Topbar__menu" onClick={onMenuClick} role="button">
52
+ <HamburgerIcon/>
53
+ </div>
54
+ <div className="Topbar__logo">
55
+ <Logo/>
56
+ </div>
57
+ <div className="Topbar__title">Lighthouse User Flow Report</div>
58
+ </div>
59
+ );
60
+ };
@@ -135,7 +135,6 @@ export function useDerivedStepNames() {
135
135
  let numTimespan = 1;
136
136
  let numSnapshot = 1;
137
137
 
138
- // TODO(FR-COMPAT): Override with a provided step name.
139
138
  return flowResult.lhrs.map((lhr, index) => {
140
139
  const shortUrl = shortenUrl(lhr.finalUrl);
141
140
 
@@ -9,17 +9,23 @@ import {useEffect, useLayoutEffect, useRef} from 'preact/hooks';
9
9
 
10
10
  import {useReportRenderer} from './report-renderer';
11
11
 
12
- export const Gauge: FunctionComponent<{category: LH.ReportResult.Category, href: string}> =
13
- ({category, href}) => {
12
+ export const CategoryScore: FunctionComponent<{
13
+ category: LH.ReportResult.Category,
14
+ href: string,
15
+ gatherMode: LH.Result.GatherMode,
16
+ }> = ({category, href, gatherMode}) => {
14
17
  const {categoryRenderer} = useReportRenderer();
15
18
  const ref = useRef<HTMLDivElement>(null);
16
19
 
17
20
  useLayoutEffect(() => {
18
- const el = categoryRenderer.renderScoreGauge(category, {});
21
+ const el = categoryRenderer.renderCategoryScore(category, {}, {gatherMode});
19
22
 
20
23
  // Category label is displayed in the navigation header.
21
- const label = el.querySelector('.lh-gauge__label');
24
+ const label = el.querySelector('.lh-gauge__label,.lh-fraction__label');
22
25
  if (label) label.remove();
26
+ // Background is displayed in individual reports, but not on the summary page.
27
+ const bg = el.querySelector('.lh-fraction__background');
28
+ if (bg) bg.remove();
23
29
 
24
30
  if (ref.current) ref.current.append(el);
25
31
  return () => {
@@ -35,6 +41,6 @@ export const Gauge: FunctionComponent<{category: LH.ReportResult.Category, href:
35
41
  }, [href]);
36
42
 
37
43
  return (
38
- <div ref={ref} data-testid="Gauge"/>
44
+ <div ref={ref} data-testid="CategoryScore"/>
39
45
  );
40
46
  };
@@ -62,7 +62,7 @@ describe('SummaryFlowStep', () => {
62
62
  const screenshot = root.getByTestId('SummaryFlowStep__screenshot') as HTMLImageElement;
63
63
  expect(screenshot.src).toMatch(/data:image\/jpeg;base64/);
64
64
 
65
- const gauges = root.getAllByTestId('Gauge');
65
+ const gauges = root.getAllByTestId('CategoryScore');
66
66
  expect(gauges).toHaveLength(4);
67
67
 
68
68
  const links = root.getAllByRole('link') as HTMLAnchorElement[];
@@ -90,7 +90,7 @@ describe('SummaryFlowStep', () => {
90
90
  expect(screenshot.src).toBeFalsy();
91
91
 
92
92
  expect(root.getByTestId('SummaryCategory__null'));
93
- const gauges = root.getAllByTestId('CategoryRatio');
93
+ const gauges = root.getAllByTestId('CategoryScore');
94
94
  expect(gauges).toHaveLength(3);
95
95
 
96
96
  const links = root.getAllByRole('link') as HTMLAnchorElement[];
@@ -117,7 +117,7 @@ describe('SummaryFlowStep', () => {
117
117
  const screenshot = root.getByTestId('SummaryFlowStep__screenshot') as HTMLImageElement;
118
118
  expect(screenshot.src).toMatch(/data:image\/jpeg;base64/);
119
119
 
120
- const gauges = root.getAllByTestId('CategoryRatio');
120
+ const gauges = root.getAllByTestId('CategoryScore');
121
121
  expect(gauges).toHaveLength(4);
122
122
 
123
123
  const links = root.getAllByRole('link') as HTMLAnchorElement[];