lighthouse 8.0.0-dev.20210709 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. package/docs/architecture.md +101 -0
  2. package/docs/authenticated-pages.md +44 -0
  3. package/docs/bug-labels.md +35 -0
  4. package/docs/configuration.md +213 -0
  5. package/docs/emulation.md +32 -0
  6. package/docs/error-reporting.md +42 -0
  7. package/docs/hacking-tips.md +55 -0
  8. package/docs/headless-chrome.md +119 -0
  9. package/docs/lantern.md +55 -0
  10. package/docs/new-audits.md +99 -0
  11. package/docs/performance-budgets.md +187 -0
  12. package/docs/plugins.md +374 -0
  13. package/docs/puppeteer.md +95 -0
  14. package/docs/readme.md +164 -0
  15. package/docs/recipes/auth/README.md +129 -0
  16. package/docs/recipes/auth/example-lh-auth.js +81 -0
  17. package/docs/recipes/auth/package.json +11 -0
  18. package/docs/recipes/auth/server/public/dashboard-unauthenticated.html +21 -0
  19. package/docs/recipes/auth/server/public/dashboard.html +25 -0
  20. package/docs/recipes/auth/server/public/home-unauthenticated.html +27 -0
  21. package/docs/recipes/auth/server/public/home.html +17 -0
  22. package/docs/recipes/auth/server/public/unauthenticated.html +22 -0
  23. package/docs/recipes/auth/server/server.js +85 -0
  24. package/docs/recipes/custom-audit/custom-config.js +36 -0
  25. package/docs/recipes/custom-audit/package.json +8 -0
  26. package/docs/recipes/custom-audit/readme.md +32 -0
  27. package/docs/recipes/custom-audit/searchable-audit.js +46 -0
  28. package/docs/recipes/custom-audit/searchable-gatherer.js +32 -0
  29. package/docs/recipes/custom-gatherer-puppeteer/custom-audit.js +34 -0
  30. package/{root.js → docs/recipes/custom-gatherer-puppeteer/custom-config.js} +23 -2
  31. package/docs/recipes/custom-gatherer-puppeteer/custom-gatherer.js +51 -0
  32. package/docs/recipes/custom-gatherer-puppeteer/package.json +13 -0
  33. package/docs/recipes/custom-gatherer-puppeteer/readme.md +7 -0
  34. package/docs/recipes/custom-gatherer-puppeteer/test.sh +9 -0
  35. package/docs/recipes/gulp/gulpfile.js +79 -0
  36. package/docs/recipes/gulp/package.json +12 -0
  37. package/docs/recipes/gulp/public/index.html +22 -0
  38. package/docs/recipes/gulp/readme.md +6 -0
  39. package/docs/recipes/integration-test/README.md +14 -0
  40. package/docs/recipes/integration-test/example-lh-auth.test.js +160 -0
  41. package/docs/recipes/integration-test/package.json +9 -0
  42. package/docs/recipes/lighthouse-plugin-example/audits/preload-as.js +46 -0
  43. package/docs/recipes/lighthouse-plugin-example/package.json +11 -0
  44. package/docs/recipes/lighthouse-plugin-example/plugin-recipe-screenshot.png +0 -0
  45. package/docs/recipes/lighthouse-plugin-example/plugin.js +24 -0
  46. package/docs/recipes/lighthouse-plugin-example/readme.md +53 -0
  47. package/docs/releasing.md +164 -0
  48. package/docs/scoring.md +79 -0
  49. package/docs/throttling.md +150 -0
  50. package/docs/understanding-results.md +209 -0
  51. package/docs/v8-perf-faq.md +244 -0
  52. package/docs/variability.md +150 -0
  53. package/jest.config.js +0 -3
  54. package/lighthouse-cli/bin.js +8 -6
  55. package/lighthouse-core/audits/accessibility/aria-command-name.js +1 -1
  56. package/lighthouse-core/audits/accessibility/aria-meter-name.js +1 -1
  57. package/lighthouse-core/audits/accessibility/aria-progressbar-name.js +1 -1
  58. package/lighthouse-core/audits/accessibility/aria-tooltip-name.js +1 -1
  59. package/lighthouse-core/audits/accessibility/aria-treeitem-name.js +1 -1
  60. package/lighthouse-core/audits/apple-touch-icon.js +0 -1
  61. package/lighthouse-core/audits/audit.js +3 -3
  62. package/lighthouse-core/audits/autocomplete.js +2 -2
  63. package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +14 -29
  64. package/lighthouse-core/audits/byte-efficiency/duplicated-javascript.js +2 -3
  65. package/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js +1 -1
  66. package/lighthouse-core/audits/byte-efficiency/legacy-javascript.js +2 -3
  67. package/lighthouse-core/audits/byte-efficiency/modern-image-formats.js +15 -55
  68. package/lighthouse-core/audits/byte-efficiency/offscreen-images.js +4 -8
  69. package/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js +8 -15
  70. package/lighthouse-core/audits/byte-efficiency/total-byte-weight.js +9 -10
  71. package/lighthouse-core/audits/byte-efficiency/unminified-css.js +1 -1
  72. package/lighthouse-core/audits/byte-efficiency/unminified-javascript.js +1 -1
  73. package/lighthouse-core/audits/byte-efficiency/unused-css-rules.js +1 -1
  74. package/lighthouse-core/audits/byte-efficiency/unused-javascript.js +1 -2
  75. package/lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js +2 -2
  76. package/lighthouse-core/audits/byte-efficiency/uses-optimized-images.js +1 -2
  77. package/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js +24 -46
  78. package/lighthouse-core/audits/byte-efficiency/uses-text-compression.js +1 -1
  79. package/lighthouse-core/audits/critical-request-chains.js +0 -1
  80. package/lighthouse-core/audits/csp-xss.js +1 -1
  81. package/lighthouse-core/audits/diagnostics.js +0 -1
  82. package/lighthouse-core/audits/dobetterweb/geolocation-on-start.js +0 -1
  83. package/lighthouse-core/audits/dobetterweb/inspector-issues.js +1 -1
  84. package/lighthouse-core/audits/dobetterweb/notification-on-start.js +0 -1
  85. package/lighthouse-core/audits/dobetterweb/uses-http2.js +0 -1
  86. package/lighthouse-core/audits/final-screenshot.js +4 -8
  87. package/lighthouse-core/audits/font-display.js +0 -1
  88. package/lighthouse-core/audits/installable-manifest.js +3 -4
  89. package/lighthouse-core/audits/largest-contentful-paint-element.js +0 -1
  90. package/lighthouse-core/audits/long-tasks.js +1 -1
  91. package/lighthouse-core/audits/maskable-icon.js +0 -1
  92. package/lighthouse-core/audits/metrics/first-contentful-paint-3g.js +2 -4
  93. package/lighthouse-core/audits/metrics/first-contentful-paint.js +2 -4
  94. package/lighthouse-core/audits/metrics/first-meaningful-paint.js +2 -4
  95. package/lighthouse-core/audits/metrics/interactive.js +2 -4
  96. package/lighthouse-core/audits/metrics/largest-contentful-paint.js +2 -4
  97. package/lighthouse-core/audits/metrics/max-potential-fid.js +2 -4
  98. package/lighthouse-core/audits/metrics/speed-index.js +2 -4
  99. package/lighthouse-core/audits/metrics/total-blocking-time.js +2 -10
  100. package/lighthouse-core/audits/metrics.js +2 -4
  101. package/lighthouse-core/audits/performance-budget.js +0 -1
  102. package/lighthouse-core/audits/predictive-perf.js +6 -9
  103. package/lighthouse-core/audits/preload-fonts.js +1 -11
  104. package/lighthouse-core/audits/preload-lcp-image.js +5 -18
  105. package/lighthouse-core/audits/redirects.js +8 -10
  106. package/lighthouse-core/audits/screenshot-thumbnails.js +13 -28
  107. package/lighthouse-core/audits/seo/canonical.js +1 -2
  108. package/lighthouse-core/audits/seo/font-size.js +4 -4
  109. package/lighthouse-core/audits/seo/hreflang.js +2 -3
  110. package/lighthouse-core/audits/seo/http-status-code.js +16 -21
  111. package/lighthouse-core/audits/seo/is-crawlable.js +3 -4
  112. package/lighthouse-core/audits/seo/robots-txt.js +2 -2
  113. package/lighthouse-core/audits/seo/tap-targets.js +5 -5
  114. package/lighthouse-core/audits/server-response-time.js +2 -20
  115. package/lighthouse-core/audits/splash-screen.js +0 -1
  116. package/lighthouse-core/audits/themed-omnibox.js +0 -1
  117. package/lighthouse-core/audits/third-party-facades.js +0 -1
  118. package/lighthouse-core/audits/third-party-summary.js +3 -1
  119. package/lighthouse-core/audits/timing-budget.js +2 -4
  120. package/lighthouse-core/audits/uses-rel-preconnect.js +9 -14
  121. package/lighthouse-core/audits/uses-rel-preload.js +2 -13
  122. package/lighthouse-core/computed/main-thread-tasks.js +2 -2
  123. package/lighthouse-core/computed/metrics/cumulative-layout-shift.js +3 -3
  124. package/lighthouse-core/computed/metrics/first-contentful-paint-all-frames.js +6 -6
  125. package/lighthouse-core/computed/metrics/first-contentful-paint.js +8 -9
  126. package/lighthouse-core/computed/metrics/first-meaningful-paint.js +9 -10
  127. package/lighthouse-core/computed/metrics/interactive.js +24 -25
  128. package/lighthouse-core/computed/metrics/lantern-first-contentful-paint.js +6 -6
  129. package/lighthouse-core/computed/metrics/lantern-first-meaningful-paint.js +6 -6
  130. package/lighthouse-core/computed/metrics/lantern-largest-contentful-paint.js +6 -6
  131. package/lighthouse-core/computed/metrics/lantern-metric.js +8 -16
  132. package/lighthouse-core/computed/metrics/largest-contentful-paint-all-frames.js +7 -7
  133. package/lighthouse-core/computed/metrics/largest-contentful-paint.js +9 -10
  134. package/lighthouse-core/computed/metrics/max-potential-fid.js +11 -8
  135. package/lighthouse-core/computed/metrics/metric.js +5 -32
  136. package/lighthouse-core/computed/metrics/speed-index.js +5 -6
  137. package/lighthouse-core/computed/metrics/timing-summary.js +45 -55
  138. package/lighthouse-core/computed/metrics/total-blocking-time.js +29 -36
  139. package/lighthouse-core/computed/page-dependency-graph.js +14 -14
  140. package/lighthouse-core/computed/resource-summary.js +7 -3
  141. package/lighthouse-core/computed/speedline.js +3 -3
  142. package/lighthouse-core/computed/trace-of-tab.js +86 -15
  143. package/lighthouse-core/computed/user-timings.js +5 -5
  144. package/lighthouse-core/config/default-config.js +0 -1
  145. package/lighthouse-core/fraggle-rock/config/config.js +7 -9
  146. package/lighthouse-core/fraggle-rock/config/default-config.js +2 -40
  147. package/lighthouse-core/fraggle-rock/config/filters.js +6 -39
  148. package/lighthouse-core/fraggle-rock/config/validation.js +4 -4
  149. package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +19 -54
  150. package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +10 -21
  151. package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +2 -2
  152. package/lighthouse-core/fraggle-rock/gather/snapshot-runner.js +2 -2
  153. package/lighthouse-core/fraggle-rock/gather/timespan-runner.js +2 -2
  154. package/lighthouse-core/gather/driver/prepare.js +0 -3
  155. package/lighthouse-core/gather/fetcher.js +2 -0
  156. package/lighthouse-core/gather/gather-runner.js +14 -2
  157. package/lighthouse-core/gather/gatherers/image-elements.js +61 -24
  158. package/lighthouse-core/gather/gatherers/inspector-issues.js +2 -2
  159. package/lighthouse-core/gather/gatherers/script-elements.js +12 -45
  160. package/lighthouse-core/gather/gatherers/seo/font-size.js +5 -5
  161. package/lighthouse-core/gather/gatherers/seo/tap-targets.js +12 -64
  162. package/lighthouse-core/gather/gatherers/service-worker.js +3 -20
  163. package/lighthouse-core/gather/gatherers/trace-compat.js +1 -1
  164. package/lighthouse-core/gather/gatherers/trace-elements.js +3 -15
  165. package/lighthouse-core/gather/gatherers/trace.js +4 -13
  166. package/lighthouse-core/gather/gatherers/viewport-dimensions.js +1 -1
  167. package/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js +2 -13
  168. package/lighthouse-core/lib/emulation.js +2 -0
  169. package/lighthouse-core/lib/i18n/i18n.js +2 -2
  170. package/lighthouse-core/lib/i18n/locales/ar-XB.json +141 -141
  171. package/lighthouse-core/lib/i18n/locales/ar.json +143 -143
  172. package/lighthouse-core/lib/i18n/locales/bg.json +143 -143
  173. package/lighthouse-core/lib/i18n/locales/ca.json +141 -141
  174. package/lighthouse-core/lib/i18n/locales/cs.json +141 -141
  175. package/lighthouse-core/lib/i18n/locales/da.json +141 -141
  176. package/lighthouse-core/lib/i18n/locales/de.json +142 -142
  177. package/lighthouse-core/lib/i18n/locales/el.json +141 -141
  178. package/lighthouse-core/lib/i18n/locales/en-GB.json +141 -141
  179. package/lighthouse-core/lib/i18n/locales/en-US.ctc.json +6659 -0
  180. package/lighthouse-core/lib/i18n/locales/en-US.json +144 -150
  181. package/lighthouse-core/lib/i18n/locales/en-XA.json +141 -141
  182. package/lighthouse-core/lib/i18n/locales/en-XL.ctc.json +6628 -0
  183. package/lighthouse-core/lib/i18n/locales/en-XL.json +144 -150
  184. package/lighthouse-core/lib/i18n/locales/es-419.json +141 -141
  185. package/lighthouse-core/lib/i18n/locales/es.json +141 -141
  186. package/lighthouse-core/lib/i18n/locales/fi.json +143 -143
  187. package/lighthouse-core/lib/i18n/locales/fil.json +142 -142
  188. package/lighthouse-core/lib/i18n/locales/fr.json +141 -141
  189. package/lighthouse-core/lib/i18n/locales/he.json +142 -142
  190. package/lighthouse-core/lib/i18n/locales/hi.json +143 -143
  191. package/lighthouse-core/lib/i18n/locales/hr.json +141 -141
  192. package/lighthouse-core/lib/i18n/locales/hu.json +143 -143
  193. package/lighthouse-core/lib/i18n/locales/id.json +143 -143
  194. package/lighthouse-core/lib/i18n/locales/it.json +143 -143
  195. package/lighthouse-core/lib/i18n/locales/ja.json +143 -143
  196. package/lighthouse-core/lib/i18n/locales/ko.json +143 -143
  197. package/lighthouse-core/lib/i18n/locales/lt.json +143 -143
  198. package/lighthouse-core/lib/i18n/locales/lv.json +143 -143
  199. package/lighthouse-core/lib/i18n/locales/nl.json +141 -141
  200. package/lighthouse-core/lib/i18n/locales/no.json +141 -141
  201. package/lighthouse-core/lib/i18n/locales/pl.json +141 -141
  202. package/lighthouse-core/lib/i18n/locales/pt-PT.json +141 -141
  203. package/lighthouse-core/lib/i18n/locales/pt.json +141 -141
  204. package/lighthouse-core/lib/i18n/locales/ro.json +144 -144
  205. package/lighthouse-core/lib/i18n/locales/ru.json +143 -143
  206. package/lighthouse-core/lib/i18n/locales/sk.json +142 -142
  207. package/lighthouse-core/lib/i18n/locales/sl.json +141 -141
  208. package/lighthouse-core/lib/i18n/locales/sr-Latn.json +143 -143
  209. package/lighthouse-core/lib/i18n/locales/sr.json +143 -143
  210. package/lighthouse-core/lib/i18n/locales/sv.json +142 -142
  211. package/lighthouse-core/lib/i18n/locales/ta.json +141 -141
  212. package/lighthouse-core/lib/i18n/locales/te.json +143 -143
  213. package/lighthouse-core/lib/i18n/locales/th.json +143 -143
  214. package/lighthouse-core/lib/i18n/locales/tr.json +143 -143
  215. package/lighthouse-core/lib/i18n/locales/uk.json +141 -141
  216. package/lighthouse-core/lib/i18n/locales/vi.json +143 -143
  217. package/lighthouse-core/lib/i18n/locales/zh-HK.json +141 -141
  218. package/lighthouse-core/lib/i18n/locales/zh-TW.json +143 -143
  219. package/lighthouse-core/lib/i18n/locales/zh.json +143 -143
  220. package/lighthouse-core/lib/lh-error.js +2 -2
  221. package/lighthouse-core/lib/minify-trace.js +1 -1
  222. package/lighthouse-core/lib/network-request.js +1 -17
  223. package/lighthouse-core/lib/page-functions.js +5 -6
  224. package/lighthouse-core/lib/rect-helpers.js +3 -3
  225. package/lighthouse-core/lib/sd-validation/assets/jsonldcontext.json +7137 -0
  226. package/lighthouse-core/lib/sd-validation/assets/schema-tree.json +9900 -0
  227. package/{report/report-assets.js → lighthouse-core/lib/sd-validation/helpers/walk-object.js} +20 -12
  228. package/lighthouse-core/lib/sd-validation/json-expander.js +56 -0
  229. package/lighthouse-core/lib/sd-validation/json-linter.js +49 -0
  230. package/lighthouse-core/lib/sd-validation/jsonld-keyword-validator.js +50 -0
  231. package/lighthouse-core/lib/sd-validation/line-number-from-jsonld-path.js +60 -0
  232. package/lighthouse-core/lib/sd-validation/schema-validator.js +146 -0
  233. package/lighthouse-core/lib/sd-validation/scripts/download-jsonldcontext.js +30 -0
  234. package/lighthouse-core/lib/sd-validation/scripts/generate-schema-tree.js +97 -0
  235. package/lighthouse-core/lib/sd-validation/sd-validation.js +77 -0
  236. package/lighthouse-core/lib/tappable-rects.js +1 -1
  237. package/lighthouse-core/lib/tracehouse/trace-processor.js +42 -116
  238. package/lighthouse-core/lib/url-shim.js +2 -29
  239. package/lighthouse-core/report/html/html-report-assets.js +38 -0
  240. package/{report/README.md → lighthouse-core/report/html/readme.md} +11 -7
  241. package/{report → lighthouse-core/report/html}/renderer/category-renderer.js +0 -0
  242. package/{report → lighthouse-core/report/html}/renderer/crc-details-renderer.js +0 -0
  243. package/{report → lighthouse-core/report/html}/renderer/details-renderer.js +1 -1
  244. package/{report → lighthouse-core/report/html}/renderer/dom.js +0 -0
  245. package/{report → lighthouse-core/report/html}/renderer/element-screenshot-renderer.js +0 -0
  246. package/{report → lighthouse-core/report/html}/renderer/i18n.js +1 -1
  247. package/{report → lighthouse-core/report/html}/renderer/logger.js +0 -0
  248. package/{report → lighthouse-core/report/html}/renderer/performance-category-renderer.js +0 -0
  249. package/{report → lighthouse-core/report/html}/renderer/psi.js +0 -0
  250. package/{report → lighthouse-core/report/html}/renderer/pwa-category-renderer.js +0 -0
  251. package/{report → lighthouse-core/report/html}/renderer/report-renderer.js +0 -0
  252. package/{report → lighthouse-core/report/html}/renderer/report-ui-features.js +3 -3
  253. package/{report → lighthouse-core/report/html}/renderer/snippet-renderer.js +0 -0
  254. package/{report → lighthouse-core/report/html}/renderer/text-encoding.js +0 -0
  255. package/{report → lighthouse-core/report/html}/renderer/util.js +4 -7
  256. package/{report/assets/styles.css → lighthouse-core/report/html/report-styles.css} +0 -0
  257. package/{report/assets/standalone-template.html → lighthouse-core/report/html/report-template.html} +41 -1
  258. package/{report/assets → lighthouse-core/report/html}/templates.html +0 -0
  259. package/{report → lighthouse-core/report}/report-generator.js +1 -1
  260. package/lighthouse-core/runner.js +1 -1
  261. package/package.json +12 -13
  262. package/readme.md +2 -2
  263. package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +2 -3
  264. package/third-party/chromium-synchronization/installability-errors-test.js +2 -2
  265. package/third-party/download-content-shell/download-content-shell.js +1 -2
  266. package/third-party/snyk/snapshot.json +1 -1
  267. package/tsconfig.json +1 -0
  268. package/types/artifacts.d.ts +21 -41
  269. package/types/audit.d.ts +0 -2
  270. package/types/config.d.ts +2 -16
  271. package/types/externs.d.ts +0 -1
  272. package/types/gatherer.d.ts +13 -13
  273. package/types/html-renderer.d.ts +14 -14
  274. package/types/i18n.d.ts +1 -1
  275. package/lighthouse-core/audits/byte-efficiency/uses-responsive-images-snapshot.js +0 -94
  276. package/lighthouse-core/computed/image-records.js +0 -62
  277. package/lighthouse-core/computed/metrics/navigation-metric.js +0 -46
  278. package/lighthouse-core/computed/processed-navigation.js +0 -21
  279. package/lighthouse-core/computed/processed-trace.js +0 -21
  280. package/lighthouse-core/gather/gatherers/gather-context.js +0 -25
  281. package/lighthouse-core/gather/gatherers/host-form-factor.js +0 -31
  282. package/lighthouse-core/gather/gatherers/host-user-agent.js +0 -29
  283. package/lighthouse-core/lib/lh-trace-processor.js +0 -46
  284. package/report/clients/standalone.js +0 -52
  285. package/report/test/renderer/category-renderer-test.js +0 -488
  286. package/report/test/renderer/crc-details-renderer-test.js +0 -115
  287. package/report/test/renderer/details-renderer-test.js +0 -843
  288. package/report/test/renderer/dom-test.js +0 -157
  289. package/report/test/renderer/element-screenshot-renderer-test.js +0 -189
  290. package/report/test/renderer/i18n-test.js +0 -146
  291. package/report/test/renderer/performance-category-renderer-test.js +0 -332
  292. package/report/test/renderer/psi-test.js +0 -152
  293. package/report/test/renderer/pwa-category-renderer-test.js +0 -303
  294. package/report/test/renderer/report-renderer-test.js +0 -325
  295. package/report/test/renderer/report-ui-features-test.js +0 -572
  296. package/report/test/renderer/snippet-renderer-test.js +0 -291
  297. package/report/test/renderer/text-encoding-test.js +0 -41
  298. package/report/test/renderer/util-test.js +0 -388
  299. package/report/test/report-generator-test.js +0 -145
@@ -1,572 +0,0 @@
1
- /**
2
- * @license Copyright 2017 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
- 'use strict';
7
-
8
- /* eslint-env jest */
9
-
10
- const assert = require('assert').strict;
11
- const jsdom = require('jsdom');
12
- const reportAssets = require('../../report-assets.js');
13
- const Util = require('../../renderer/util.js');
14
- const I18n = require('../../renderer/i18n.js');
15
- const DOM = require('../../renderer/dom.js');
16
- const DetailsRenderer = require('../../renderer/details-renderer.js');
17
- const ReportUIFeatures = require('../../renderer/report-ui-features.js');
18
- const CategoryRenderer = require('../../renderer/category-renderer.js');
19
- const ElementScreenshotRenderer = require('../../renderer/element-screenshot-renderer.js');
20
- const RectHelpers = require('../../../lighthouse-core/lib/rect-helpers.js');
21
- const CriticalRequestChainRenderer = require('../../renderer/crc-details-renderer.js');
22
- const ReportRenderer = require('../../renderer/report-renderer.js');
23
- const sampleResultsOrig = require('../../../lighthouse-core/test/results/sample_v2.json');
24
-
25
- describe('ReportUIFeatures', () => {
26
- let sampleResults;
27
- let dom;
28
-
29
- /**
30
- * @param {LH.JSON} lhr
31
- * @return {HTMLElement}
32
- */
33
- function render(lhr) {
34
- const detailsRenderer = new DetailsRenderer(dom);
35
- const categoryRenderer = new CategoryRenderer(dom, detailsRenderer);
36
- const renderer = new ReportRenderer(dom, categoryRenderer);
37
- const reportUIFeatures = new ReportUIFeatures(dom);
38
- const container = dom.find('main', dom._document);
39
- renderer.renderReport(lhr, container);
40
- reportUIFeatures.initFeatures(lhr);
41
- return container;
42
- }
43
-
44
- beforeAll(() => {
45
- global.Util = Util;
46
- global.I18n = I18n;
47
- global.ReportUIFeatures = ReportUIFeatures;
48
- global.CriticalRequestChainRenderer = CriticalRequestChainRenderer;
49
- global.DetailsRenderer = DetailsRenderer;
50
- global.CategoryRenderer = CategoryRenderer;
51
- global.ElementScreenshotRenderer = ElementScreenshotRenderer;
52
- global.RectHelpers = RectHelpers;
53
-
54
- // lazy loaded because they depend on CategoryRenderer to be available globally
55
- global.PerformanceCategoryRenderer =
56
- require('../../renderer/performance-category-renderer.js');
57
- global.PwaCategoryRenderer =
58
- require('../../renderer/pwa-category-renderer.js');
59
-
60
- // Stub out matchMedia for Node.
61
- global.matchMedia = function() {
62
- return {
63
- addListener: function() {},
64
- };
65
- };
66
-
67
- const reportWithTemplates = reportAssets.REPORT_TEMPLATE
68
- .replace('%%LIGHTHOUSE_TEMPLATES%%', reportAssets.REPORT_TEMPLATES);
69
- const document = new jsdom.JSDOM(reportWithTemplates);
70
- global.self = document.window;
71
- global.self.matchMedia = function() {
72
- return {
73
- addListener: function() {},
74
- };
75
- };
76
-
77
- global.HTMLElement = document.window.HTMLElement;
78
- global.HTMLInputElement = document.window.HTMLInputElement;
79
-
80
- global.window = document.window;
81
- global.window.getComputedStyle = function() {
82
- return {
83
- marginTop: '10px',
84
- height: '10px',
85
- };
86
- };
87
-
88
- dom = new DOM(document.window.document);
89
- sampleResults = Util.prepareReportResult(sampleResultsOrig);
90
- render(sampleResults);
91
- });
92
-
93
- afterAll(() => {
94
- global.self = undefined;
95
- global.Util = undefined;
96
- global.I18n = undefined;
97
- global.ReportUIFeatures = undefined;
98
- global.matchMedia = undefined;
99
- global.CriticalRequestChainRenderer = undefined;
100
- global.DetailsRenderer = undefined;
101
- global.CategoryRenderer = undefined;
102
- global.ElementScreenshotRenderer = undefined;
103
- global.RectHelpers = undefined;
104
- global.PerformanceCategoryRenderer = undefined;
105
- global.PwaCategoryRenderer = undefined;
106
- global.window = undefined;
107
- global.HTMLElement = undefined;
108
- global.HTMLInputElement = undefined;
109
- });
110
-
111
- describe('initFeatures', () => {
112
- it('should init a report', () => {
113
- const container = render(sampleResults);
114
- assert.equal(dom.findAll('.lh-category', container).length, 5);
115
- });
116
-
117
- it('should init a report with a single category', () => {
118
- const lhr = JSON.parse(JSON.stringify(sampleResults));
119
- lhr.categories = {
120
- performance: lhr.categories.performance,
121
- };
122
- const container = render(lhr);
123
- assert.equal(dom.findAll('.lh-category', container).length, 1);
124
- });
125
-
126
- describe('third-party filtering', () => {
127
- let container;
128
-
129
- beforeAll(() => {
130
- const lhr = JSON.parse(JSON.stringify(sampleResults));
131
- lhr.requestedUrl = lhr.finalUrl = 'http://www.example.com';
132
- const webpAuditItemTemplate = {
133
- ...sampleResults.audits['modern-image-formats'].details.items[0],
134
- wastedBytes: 8.8 * 1024,
135
- };
136
- const renderBlockingAuditItemTemplate =
137
- sampleResults.audits['render-blocking-resources'].details.items[0];
138
- const textCompressionAuditItemTemplate =
139
- sampleResults.audits['uses-text-compression'].details.items[0];
140
-
141
- // Interleave first/third party URLs to test restoring order.
142
- lhr.audits['modern-image-formats'].details.items = [
143
- {
144
- ...webpAuditItemTemplate,
145
- url: 'http://www.cdn.com/img1.jpg', // Third party, will be filtered.
146
- },
147
- {
148
- ...webpAuditItemTemplate,
149
- url: 'http://www.example.com/img2.jpg', // First party, not filtered.
150
- },
151
- {
152
- ...webpAuditItemTemplate,
153
- url: 'http://www.notexample.com/img3.jpg', // Third party, will be filtered.
154
- },
155
- ];
156
-
157
- // Test sub-item rows.
158
- lhr.audits['unused-javascript'].details.items = [
159
- {
160
- ...webpAuditItemTemplate,
161
- url: 'http://www.cdn.com/script1.js', // Third party, will be filtered.
162
- subItems: {
163
- type: 'subitems',
164
- items: [
165
- {source: '1', sourceBytes: 1, sourceWastedBytes: 1},
166
- {source: '2', sourceBytes: 2, sourceWastedBytes: 2},
167
- ],
168
- },
169
- },
170
- {
171
- ...webpAuditItemTemplate,
172
- url: 'http://www.example.com/script2.js', // First party, not filtered.
173
- subItems: {
174
- type: 'subitems',
175
- items: [
176
- {source: '3', sourceBytes: 3, sourceWastedBytes: 3},
177
- {source: '4', sourceBytes: 4, sourceWastedBytes: 4},
178
- ],
179
- },
180
- },
181
- {
182
- ...webpAuditItemTemplate,
183
- url: 'http://www.notexample.com/script3.js', // Third party, will be filtered.
184
- subItems: {
185
- type: 'subitems',
186
- items: [
187
- {source: '5', sourceBytes: 5, sourceWastedBytes: 5},
188
- {source: '6', sourceBytes: 6, sourceWastedBytes: 6},
189
- ],
190
- },
191
- },
192
- ];
193
- // Sample json currently doesn't have any results for `unused-javascript`, so
194
- // headings is empty. Can delete this block of code if that changes.
195
- expect(lhr.audits['unused-javascript'].details.headings).toHaveLength(0);
196
- lhr.audits['unused-javascript'].details.headings = [
197
- /* t-disable max-len */
198
- {key: 'url', valueType: 'url', subItemsHeading: {key: 'source', valueType: 'code'}},
199
- {key: 'totalBytes', valueType: 'bytes', subItemsHeading: {key: 'sourceBytes'}},
200
- {key: 'wastedBytes', valueType: 'bytes', subItemsHeading: {key: 'sourceWastedBytes'}},
201
- /* eslint-enable max-len */
202
- ];
203
-
204
- // Only third party URLs to test that checkbox is hidden
205
- lhr.audits['render-blocking-resources'].details.items = [
206
- {
207
- ...renderBlockingAuditItemTemplate,
208
- url: 'http://www.cdn.com/script1.js', // Third party.
209
- },
210
- {
211
- ...renderBlockingAuditItemTemplate,
212
- url: 'http://www.google.com/script2.js', // Third party.
213
- },
214
- {
215
- ...renderBlockingAuditItemTemplate,
216
- url: 'http://www.notexample.com/script3.js', // Third party.
217
- },
218
- ];
219
-
220
- // Only first party URLs to test that checkbox is hidden
221
- lhr.audits['uses-text-compression'].details.items = [
222
- {
223
- ...textCompressionAuditItemTemplate,
224
- url: 'http://www.example.com/font1.ttf', // First party.
225
- },
226
- {
227
- ...textCompressionAuditItemTemplate,
228
- url: 'http://www.example.com/font2.ttf', // First party.
229
- },
230
- {
231
- ...textCompressionAuditItemTemplate,
232
- url: 'http://www.example.com/font3.ttf', // First party.
233
- },
234
- ];
235
-
236
- // render a report onto the UIFeature dom
237
- container = render(lhr);
238
- });
239
-
240
- it('filters out third party resources in on click', () => {
241
- const filterCheckbox = dom.find('#modern-image-formats .lh-3p-filter-input', container);
242
-
243
- function getUrlsInTable() {
244
- return dom
245
- .findAll('#modern-image-formats tr:not(.lh-row--hidden) .lh-text__url a:first-child', container) // eslint-disable-line max-len
246
- .map(el => el.textContent);
247
- }
248
-
249
- expect(getUrlsInTable()).toEqual(['/img1.jpg', '/img2.jpg', '/img3.jpg']);
250
- filterCheckbox.click();
251
- expect(getUrlsInTable()).toEqual(['/img2.jpg']);
252
- filterCheckbox.click();
253
- expect(getUrlsInTable()).toEqual(['/img1.jpg', '/img2.jpg', '/img3.jpg']);
254
- });
255
-
256
- it('filters out sub-item rows of third party resources on click', () => {
257
- dom.find('#unused-javascript', container);
258
- const filterCheckbox = dom.find('#unused-javascript .lh-3p-filter-input', container);
259
-
260
- function getRowIdentifiers() {
261
- return dom
262
- .findAll(
263
- '#unused-javascript tbody tr:not(.lh-row--hidden)', container)
264
- .map(el => el.textContent);
265
- }
266
-
267
- const initialExpected = [
268
- '/script1.js(www.cdn.com)24.0 KiB8.8 KiB',
269
- '10.0 KiB0.0 KiB',
270
- '20.0 KiB0.0 KiB',
271
- '/script2.js(www.example.com)24.0 KiB8.8 KiB',
272
- '30.0 KiB0.0 KiB',
273
- '40.0 KiB0.0 KiB',
274
- '/script3.js(www.notexample.com)24.0 KiB8.8 KiB',
275
- '50.0 KiB0.0 KiB',
276
- '60.0 KiB0.0 KiB',
277
- ];
278
-
279
- expect(getRowIdentifiers()).toEqual(initialExpected);
280
- filterCheckbox.click();
281
- expect(getRowIdentifiers()).toEqual([
282
- '/script2.js(www.example.com)24.0 KiB8.8 KiB',
283
- '30.0 KiB0.0 KiB',
284
- '40.0 KiB0.0 KiB',
285
- ]);
286
- filterCheckbox.click();
287
- expect(getRowIdentifiers()).toEqual(initialExpected);
288
- });
289
-
290
- it('adds no filter for audits in thirdPartyFilterAuditExclusions', () => {
291
- const checkboxClassName = 'lh-3p-filter-input';
292
-
293
- const yesCheckbox = dom.find(`#modern-image-formats .${checkboxClassName}`, container);
294
- expect(yesCheckbox).toBeTruthy();
295
-
296
- expect(() => dom.find(`#uses-rel-preconnect .${checkboxClassName}`, container))
297
- .toThrowError('query #uses-rel-preconnect .lh-3p-filter-input not found');
298
- });
299
-
300
- it('filter is disabled and checked for when just third party resources', () => {
301
- const filterCheckbox =
302
- dom.find('#render-blocking-resources .lh-3p-filter-input', container);
303
- expect(filterCheckbox.disabled).toEqual(true);
304
- expect(filterCheckbox.checked).toEqual(true);
305
- });
306
-
307
- it('filter is disabled and not checked for just first party resources', () => {
308
- const filterCheckbox = dom.find('#uses-text-compression .lh-3p-filter-input', container);
309
- expect(filterCheckbox.disabled).toEqual(true);
310
- expect(filterCheckbox.checked).toEqual(false);
311
- });
312
- });
313
- });
314
-
315
- describe('fireworks', () => {
316
- it('should render an non-all 100 report without fireworks', () => {
317
- const lhr = JSON.parse(JSON.stringify(sampleResults));
318
- lhr.categories.performance.score = 0.5;
319
- const container = render(lhr);
320
- assert.ok(container.querySelector('.score100') === null, 'has no fireworks treatment');
321
- });
322
-
323
- it('should render an all 100 report with fireworks', () => {
324
- const lhr = JSON.parse(JSON.stringify(sampleResults));
325
- Object.values(lhr.categories).forEach(element => {
326
- element.score = 1;
327
- });
328
- const container = render(lhr);
329
- assert.ok(container.querySelector('.score100'), 'has fireworks treatment');
330
- });
331
-
332
- it('should show fireworks for all 100s except PWA', () => {
333
- const lhr = JSON.parse(JSON.stringify(sampleResults));
334
- Object.values(lhr.categories).forEach(element => {
335
- element.score = 1;
336
- });
337
- lhr.categories.pwa.score = 0;
338
-
339
- const container = render(lhr);
340
- assert.ok(container.querySelector('.score100'), 'has fireworks treatment');
341
- });
342
-
343
- it('should not render fireworks if all core categories are not present', () => {
344
- const lhr = JSON.parse(JSON.stringify(sampleResults));
345
- delete lhr.categories.performance;
346
- delete lhr.categoryGroups.performace;
347
- Object.values(lhr.categories).forEach(element => {
348
- element.score = 1;
349
- });
350
- const container = render(lhr);
351
- assert.ok(container.querySelector('.score100') === null, 'has no fireworks treatment');
352
- });
353
- });
354
-
355
- describe('metric descriptions', () => {
356
- it('with no errors, hide by default', () => {
357
- const lhr = JSON.parse(JSON.stringify(sampleResults));
358
- const container = render(lhr);
359
- assert.ok(!container.querySelector('.lh-metrics-toggle__input').checked);
360
- });
361
-
362
- it('with error, show by default', () => {
363
- const lhr = JSON.parse(JSON.stringify(sampleResults));
364
- lhr.audits['first-contentful-paint'].errorMessage = 'Error.';
365
- const container = render(lhr);
366
- assert.ok(container.querySelector('.lh-metrics-toggle__input').checked);
367
- });
368
- });
369
-
370
- describe('tools button', () => {
371
- let window;
372
- let dropDown;
373
-
374
- beforeEach(() => {
375
- window = dom.document().defaultView;
376
- const features = new ReportUIFeatures(dom);
377
- features.initFeatures(sampleResults);
378
- dropDown = features._dropDown;
379
- });
380
-
381
- it('click should toggle active class', () => {
382
- dropDown._toggleEl.click();
383
- assert.ok(dropDown._toggleEl.classList.contains('active'));
384
-
385
- dropDown._toggleEl.click();
386
- assert.ok(!dropDown._toggleEl.classList.contains('active'));
387
- });
388
-
389
-
390
- it('Escape key removes active class', () => {
391
- dropDown._toggleEl.click();
392
- assert.ok(dropDown._toggleEl.classList.contains('active'));
393
-
394
- const escape = new window.KeyboardEvent('keydown', {keyCode: /* ESC */ 27});
395
- dom.document().dispatchEvent(escape);
396
- assert.ok(!dropDown._toggleEl.classList.contains('active'));
397
- });
398
-
399
- ['ArrowUp', 'ArrowDown', 'Enter', ' '].forEach((code) => {
400
- it(`'${code}' adds active class`, () => {
401
- const event = new window.KeyboardEvent('keydown', {code});
402
- dropDown._toggleEl.dispatchEvent(event);
403
- assert.ok(dropDown._toggleEl.classList.contains('active'));
404
- });
405
- });
406
-
407
- it('ArrowUp on the first menu element should focus the last element', () => {
408
- dropDown._toggleEl.click();
409
-
410
- const arrowUp = new window.KeyboardEvent('keydown', {bubbles: true, code: 'ArrowUp'});
411
- dropDown._menuEl.firstElementChild.dispatchEvent(arrowUp);
412
-
413
- assert.strictEqual(dom.document().activeElement, dropDown._menuEl.lastElementChild);
414
- });
415
-
416
- it('ArrowDown on the first menu element should focus the second element', () => {
417
- dropDown._toggleEl.click();
418
-
419
- const {nextElementSibling} = dropDown._menuEl.firstElementChild;
420
- const arrowDown = new window.KeyboardEvent('keydown', {bubbles: true, code: 'ArrowDown'});
421
- dropDown._menuEl.firstElementChild.dispatchEvent(arrowDown);
422
-
423
- assert.strictEqual(dom.document().activeElement, nextElementSibling);
424
- });
425
-
426
- it('Home on the last menu element should focus the first element', () => {
427
- dropDown._toggleEl.click();
428
-
429
- const {firstElementChild} = dropDown._menuEl;
430
- const home = new window.KeyboardEvent('keydown', {bubbles: true, code: 'Home'});
431
- dropDown._menuEl.lastElementChild.dispatchEvent(home);
432
-
433
- assert.strictEqual(dom.document().activeElement, firstElementChild);
434
- });
435
-
436
- it('End on the first menu element should focus the last element', () => {
437
- dropDown._toggleEl.click();
438
-
439
- const {lastElementChild} = dropDown._menuEl;
440
- const end = new window.KeyboardEvent('keydown', {bubbles: true, code: 'End'});
441
- dropDown._menuEl.firstElementChild.dispatchEvent(end);
442
-
443
- assert.strictEqual(dom.document().activeElement, lastElementChild);
444
- });
445
-
446
- describe('_getNextSelectableNode', () => {
447
- let createDiv;
448
-
449
- beforeAll(() => {
450
- createDiv = () => dom.document().createElement('div');
451
- });
452
-
453
- it('should return undefined when nodes is empty', () => {
454
- const nodes = [];
455
-
456
- const nextNode = dropDown._getNextSelectableNode(nodes);
457
-
458
- assert.strictEqual(nextNode, undefined);
459
- });
460
-
461
- it('should return the only node when start is defined', () => {
462
- const node = createDiv();
463
-
464
- const nextNode = dropDown._getNextSelectableNode([node], node);
465
-
466
- assert.strictEqual(nextNode, node);
467
- });
468
-
469
- it('should return first node when start is undefined', () => {
470
- const nodes = [createDiv(), createDiv()];
471
-
472
- const nextNode = dropDown._getNextSelectableNode(nodes);
473
-
474
- assert.strictEqual(nextNode, nodes[0]);
475
- });
476
-
477
- it('should return second node when start is first node', () => {
478
- const nodes = [createDiv(), createDiv()];
479
-
480
- const nextNode = dropDown._getNextSelectableNode(nodes, nodes[0]);
481
-
482
- assert.strictEqual(nextNode, nodes[1]);
483
- });
484
-
485
- it('should return first node when start is second node', () => {
486
- const nodes = [createDiv(), createDiv()];
487
-
488
- const nextNode = dropDown._getNextSelectableNode(nodes, nodes[1]);
489
-
490
- assert.strictEqual(nextNode, nodes[0]);
491
- });
492
-
493
- it('should skip the undefined node', () => {
494
- const nodes = [createDiv(), undefined, createDiv()];
495
-
496
- const nextNode = dropDown._getNextSelectableNode(nodes, nodes[0]);
497
-
498
- assert.strictEqual(nextNode, nodes[2]);
499
- });
500
-
501
- it('should skip the disabled node', () => {
502
- const disabledNode = createDiv();
503
- disabledNode.setAttribute('disabled', true);
504
- const nodes = [createDiv(), disabledNode, createDiv()];
505
-
506
- const nextNode = dropDown._getNextSelectableNode(nodes, nodes[0]);
507
-
508
- assert.strictEqual(nextNode, nodes[2]);
509
- });
510
- });
511
-
512
- describe('onMenuFocusOut', () => {
513
- beforeEach(() => {
514
- dropDown._toggleEl.click();
515
- assert.ok(dropDown._toggleEl.classList.contains('active'));
516
- });
517
-
518
- it('should toggle active class when focus relatedTarget is null', () => {
519
- const event = new window.FocusEvent('focusout', {relatedTarget: null});
520
- dropDown.onMenuFocusOut(event);
521
-
522
- assert.ok(!dropDown._toggleEl.classList.contains('active'));
523
- });
524
-
525
- it('should toggle active class when focus relatedTarget is document.body', () => {
526
- const relatedTarget = dom.document().body;
527
- const event = new window.FocusEvent('focusout', {relatedTarget});
528
- dropDown.onMenuFocusOut(event);
529
-
530
- assert.ok(!dropDown._toggleEl.classList.contains('active'));
531
- });
532
-
533
- it('should toggle active class when focus relatedTarget is _toggleEl', () => {
534
- const relatedTarget = dropDown._toggleEl;
535
- const event = new window.FocusEvent('focusout', {relatedTarget});
536
- dropDown.onMenuFocusOut(event);
537
-
538
- assert.ok(!dropDown._toggleEl.classList.contains('active'));
539
- });
540
-
541
- it('should not toggle active class when focus relatedTarget is a menu item', () => {
542
- const relatedTarget = dropDown._getNextMenuItem();
543
- const event = new window.FocusEvent('focusout', {relatedTarget});
544
- dropDown.onMenuFocusOut(event);
545
-
546
- assert.ok(dropDown._toggleEl.classList.contains('active'));
547
- });
548
- });
549
- });
550
-
551
- describe('treemap button', () => {
552
- it('should only show button if treemap data is available', () => {
553
- const lhr = JSON.parse(JSON.stringify(sampleResults));
554
-
555
- expect(lhr.audits['script-treemap-data']).not.toBeUndefined();
556
- expect(render(lhr).querySelector('.lh-button.report-icon--treemap')).toBeTruthy();
557
-
558
- delete lhr.audits['script-treemap-data'];
559
- expect(render(lhr).querySelector('.lh-button.report-icon--treemap')).toBeNull();
560
- });
561
- });
562
-
563
- describe('data-i18n', () => {
564
- it('should have only valid data-i18n values in template', () => {
565
- const container = render(sampleResults);
566
- for (const node of dom.findAll('[data-i18n]', container)) {
567
- const val = node.getAttribute('data-i18n');
568
- assert.ok(val in Util.UIStrings, `Invalid data-i18n value of: "${val}" not found.`);
569
- }
570
- });
571
- });
572
- });