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,303 +0,0 @@
1
- /**
2
- * @license Copyright 2018 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, browser */
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 CategoryRenderer = require('../../renderer/category-renderer.js');
18
- const sampleResultsOrig = require('../../../lighthouse-core/test/results/sample_v2.json');
19
-
20
- describe('PwaCategoryRenderer', () => {
21
- let category;
22
- let pwaRenderer;
23
- let sampleResults;
24
-
25
- beforeAll(() => {
26
- global.Util = Util;
27
- global.Util.i18n = new I18n('en', {...Util.UIStrings});
28
- global.CategoryRenderer = CategoryRenderer;
29
-
30
- // Delayed so that CategoryRenderer is in global scope
31
- const PwaCategoryRenderer = require('../../renderer/pwa-category-renderer.js');
32
-
33
- const {document} = new jsdom.JSDOM(reportAssets.REPORT_TEMPLATES).window;
34
- const dom = new DOM(document);
35
- const detailsRenderer = new DetailsRenderer(dom);
36
- pwaRenderer = new PwaCategoryRenderer(dom, detailsRenderer);
37
-
38
- sampleResults = Util.prepareReportResult(sampleResultsOrig);
39
- });
40
-
41
- beforeEach(() => {
42
- // Clone category to allow modifications.
43
- const pwaCategory = sampleResults.categories.pwa;
44
- category = JSON.parse(JSON.stringify(pwaCategory));
45
- });
46
-
47
- afterAll(() => {
48
- global.Util.i18n = undefined;
49
- global.Util = undefined;
50
- global.CategoryRenderer = undefined;
51
- });
52
-
53
- it('renders the regular audits', () => {
54
- const categoryElem = pwaRenderer.render(category, sampleResults.categoryGroups);
55
- const allAuditElements = Array.from(categoryElem.querySelectorAll('.lh-audit'));
56
- const manualElements = Array.from(categoryElem.querySelectorAll('.lh-clump--manual .lh-audit'));
57
- const regularAuditElements = allAuditElements.filter(el => !manualElements.includes(el));
58
-
59
- const nonManualAudits = category.auditRefs
60
- .filter(audit => audit.result.scoreDisplayMode !== 'manual');
61
- assert.strictEqual(regularAuditElements.length, nonManualAudits.length);
62
- });
63
-
64
- it('renders the manual audits', () => {
65
- const categoryElem = pwaRenderer.render(category, sampleResults.categoryGroups);
66
- const manualElements = categoryElem.querySelectorAll('.lh-clump--manual .lh-audit');
67
-
68
- const manualAudits = category.auditRefs
69
- .filter(audit => audit.result.scoreDisplayMode === 'manual');
70
-
71
- assert.strictEqual(manualElements.length, manualAudits.length);
72
- });
73
-
74
- it('manual audits are the only clump', () => {
75
- const categoryElem = pwaRenderer.render(category, sampleResults.categoryGroups);
76
- const clumpElems = categoryElem.querySelectorAll('.lh-clump');
77
- assert.strictEqual(clumpElems.length, 1);
78
- assert.ok(clumpElems[0].classList.contains('lh-clump--manual'));
79
- });
80
-
81
- it('renders the audit groups', () => {
82
- const categoryGroupIds = new Set(category.auditRefs.filter(a => a.group).map(a => a.group));
83
- assert.strictEqual(categoryGroupIds.size, 2); // Ensure there's something to test.
84
-
85
- const categoryElem = pwaRenderer.render(category, sampleResults.categoryGroups);
86
-
87
- categoryGroupIds.forEach(groupId => {
88
- const selector = `.lh-audit-group--${groupId}`;
89
- // Expected that only the non-manual audits will be grouped.
90
- assert.strictEqual(categoryElem.querySelectorAll(selector).length, 1,
91
- `trouble with selector '${selector}'`);
92
- });
93
- });
94
-
95
- describe('badging groups', () => {
96
- let auditRefs;
97
- let groupIds;
98
-
99
- beforeEach(() => {
100
- auditRefs = category.auditRefs
101
- .filter(audit => audit.result.scoreDisplayMode !== 'manual');
102
-
103
- // Expect results to all be scorable or n/a
104
- for (const auditRef of auditRefs) {
105
- const matcher = expect.stringMatching(/(binary)|(notApplicable)/);
106
- expect(auditRef.result.scoreDisplayMode).toEqual(matcher);
107
- }
108
-
109
- groupIds = [...new Set(auditRefs.map(ref => ref.group))];
110
- });
111
-
112
- it('gives passing even if an audit is notApplicable', () => {
113
- const clone = JSON.parse(JSON.stringify(sampleResults));
114
- const category = clone.categories.pwa;
115
-
116
- // Set everything to passing, except redirects-http set to n/a (as it is on localhost)
117
- for (const auditRef of category.auditRefs) {
118
- auditRef.result.score = 1;
119
- auditRef.result.scoreDisplayMode = 'binary';
120
- }
121
- const audit = category.auditRefs.find(ref => ref.id === 'redirects-http');
122
- audit.result.scoreDisplayMode = 'notApplicable';
123
- audit.result.score = null;
124
-
125
- const categoryElem = pwaRenderer.render(category, clone.categoryGroups);
126
- const badgedElems = categoryElem.querySelectorAll(`.lh-audit-group--pwa-optimized.lh-badged`);
127
- expect(badgedElems.length).toEqual(1);
128
- });
129
-
130
- it('only gives a group a badge when all the group\'s audits are passing', () => {
131
- for (const auditRef of auditRefs) {
132
- auditRef.result.score = 0;
133
- auditRef.result.scoreDisplayMode = 'binary';
134
- }
135
-
136
- const targetGroupId = 'pwa-optimized';
137
- const targetGroupTitle = sampleResults.categoryGroups[targetGroupId].title;
138
- const targetAuditRefs = auditRefs.filter(ref => ref.group === targetGroupId);
139
-
140
- // Try every permutation of audit scoring.
141
- const totalPermutations = Math.pow(2, targetAuditRefs.length);
142
- for (let i = 0; i < totalPermutations; i++) {
143
- for (let j = 0; j < targetAuditRefs.length; j++) {
144
- // Set as passing if jth bit in i is set.
145
- targetAuditRefs[j].result.score = i >> j & 1;
146
- }
147
-
148
- const categoryElem = pwaRenderer.render(category, sampleResults.categoryGroups);
149
- const badgedElems = categoryElem.querySelectorAll(`.lh-badged`);
150
- const badgedScoreGauge =
151
- categoryElem.querySelector('.lh-gauge--pwa__wrapper[class*="lh-badged--"]');
152
-
153
- const tooltip = categoryElem.querySelector('.lh-gauge--pwa__wrapper').title;
154
- const targetGroupTip = tooltip.split(', ').find(tip => tip.startsWith(targetGroupTitle));
155
- assert.ok(targetGroupTip);
156
-
157
- // Only expect a badge (and badged gauge) on last permutation (all bits are set).
158
- if (i !== totalPermutations - 1) {
159
- assert.strictEqual(badgedElems.length, 0);
160
- assert.strictEqual(badgedScoreGauge, null);
161
-
162
- // Tooltip ends with passing/total.
163
- const passingCount = categoryElem.querySelectorAll(
164
- `.lh-audit-group--${targetGroupId} .lh-audit--pass`).length;
165
- assert.ok(targetGroupTip.endsWith(`${passingCount}/${targetAuditRefs.length}`));
166
- } else {
167
- assert.strictEqual(badgedElems.length, 1);
168
- assert.ok(badgedScoreGauge.classList.contains(`lh-badged--${targetGroupId}`));
169
-
170
- // Tooltip ends with total/total.
171
- assert.ok(targetGroupTip.endsWith(`${targetAuditRefs.length}/${targetAuditRefs.length}`));
172
- }
173
- }
174
- });
175
-
176
- it('renders all badges when all audits are passing', () => {
177
- for (const auditRef of auditRefs) {
178
- auditRef.result.score = 1;
179
- }
180
-
181
- const categoryElem = pwaRenderer.render(category, sampleResults.categoryGroups);
182
- assert.strictEqual(categoryElem.querySelectorAll('.lh-badged').length, groupIds.length);
183
-
184
- // Score gauge.
185
- const gaugeElem = categoryElem.querySelector('.lh-gauge--pwa__wrapper');
186
- assert.ok(gaugeElem.classList.contains('lh-badged--all'));
187
-
188
- // All tooltips should have x/x audits passed.
189
- const tips = gaugeElem.title.split(', ');
190
- assert.strictEqual(tips.length, groupIds.length);
191
- for (const tip of tips) {
192
- assert.ok(/(\d+)\/\1$/.test(tip));
193
- }
194
- });
195
-
196
- it('renders no badges when no audit groups are passing', () => {
197
- for (const auditRef of auditRefs) {
198
- auditRef.result.score = 0;
199
- auditRef.result.scoreDisplayMode = 'binary';
200
- }
201
-
202
- const categoryElem = pwaRenderer.render(category, sampleResults.categoryGroups);
203
- assert.strictEqual(categoryElem.querySelectorAll('.lh-badged').length, 0);
204
-
205
- // Score gauge.
206
- const gaugeElem = categoryElem.querySelector('.lh-gauge--pwa__wrapper');
207
- assert.ok(!gaugeElem.matches('.lh-gauge--pwa__wrapper[class*="lh-badged-"]'));
208
-
209
- // All tooltips should have 0/x audits passed.
210
- const tips = gaugeElem.title.split(', ');
211
- assert.strictEqual(tips.length, groupIds.length);
212
- for (const tip of tips) {
213
- assert.ok(/0\/\d+$/.test(tip));
214
- }
215
- });
216
-
217
- it('renders all but one badge when all groups but one are passing', () => {
218
- for (const auditRef of auditRefs) {
219
- auditRef.result.score = 1;
220
- }
221
- auditRefs[0].result.score = 0;
222
- const failingGroupId = auditRefs[0].group;
223
-
224
- const categoryElem = pwaRenderer.render(category, sampleResults.categoryGroups);
225
- const gaugeElem = categoryElem.querySelector('.lh-gauge--pwa__wrapper');
226
-
227
- const tips = gaugeElem.title.split(', ');
228
- assert.strictEqual(tips.length, groupIds.length);
229
-
230
- for (const groupId of groupIds) {
231
- const expectedCount = groupId === failingGroupId ? 0 : 1;
232
-
233
- // Individual group badges.
234
- const groupElems = categoryElem.querySelectorAll(`.lh-audit-group--${groupId}.lh-badged`);
235
- assert.strictEqual(groupElems.length, expectedCount);
236
-
237
- // Score gauge.
238
- if (groupId !== failingGroupId) {
239
- assert.ok(gaugeElem.classList.contains(`lh-badged--${groupId}`));
240
- }
241
-
242
- // Map back from groupId to groupTitle (used in tooltip).
243
- const groupTitle = sampleResults.categoryGroups[groupId].title;
244
- const groupTip = tips.find(tip => tip.startsWith(groupTitle));
245
- assert.ok(groupTip);
246
-
247
- // All tooltips should be x/x except for failingGroup, which should be (x-1)/x.
248
- if (groupId !== failingGroupId) {
249
- assert.ok(/(\d+)\/\1$/.test(groupTip));
250
- } else {
251
- const [, passingCount, totalCount] = /(\d+)\/(\d+)$/.exec(groupTip);
252
- assert.strictEqual(Number(passingCount) + 1, Number(totalCount));
253
- }
254
- }
255
- });
256
- });
257
-
258
- describe('#renderScoreGauge', () => {
259
- it('renders an error score gauge in case of category error', () => {
260
- category.score = null;
261
- const badgeGauge = pwaRenderer.renderScoreGauge(category, sampleResults.categoryGroups);
262
-
263
- // Not a PWA gauge.
264
- assert.strictEqual(badgeGauge.querySelector('.lh-gauge--pwa__wrapper'), null);
265
-
266
- const percentageElem = badgeGauge.querySelector('.lh-gauge__percentage');
267
- assert.strictEqual(percentageElem.textContent, '?');
268
- assert.strictEqual(percentageElem.title, Util.UIStrings.errorLabel);
269
- });
270
-
271
- it('renders score gauges with unique ids for items in <defs>', () => {
272
- const gauge1 = pwaRenderer.renderScoreGauge(category, sampleResults.categoryGroups);
273
- const gauge1Ids = [...gauge1.querySelectorAll('defs [id]')].map(el => el.id);
274
- assert.ok(gauge1Ids.length > 2);
275
-
276
- const gauge2 = pwaRenderer.renderScoreGauge(category, sampleResults.categoryGroups);
277
- const gauge2Ids = [...gauge2.querySelectorAll('defs [id]')].map(el => el.id);
278
- assert.ok(gauge2Ids.length === gauge1Ids.length);
279
-
280
- /** Returns whether id is used by at least one <use> or fill under `rootEl`. */
281
- function idInUseElOrFillAttr(rootEl, id) {
282
- const isUse = rootEl.querySelector(`use[href="#${id}"]`);
283
- const isFill = rootEl.querySelector(`[fill="url(#${id})"]`);
284
-
285
- return !!(isUse || isFill);
286
- }
287
-
288
- // Check that each gauge1 ID is actually used in gauge1 and isn't used in gauge2.
289
- for (const gauge1Id of gauge1Ids) {
290
- assert.equal(idInUseElOrFillAttr(gauge1, gauge1Id), true);
291
- assert.ok(!gauge2Ids.includes(gauge1Id));
292
- assert.equal(idInUseElOrFillAttr(gauge2, gauge1Id), false);
293
- }
294
-
295
- // And that the reverse is true for gauge2 IDs.
296
- for (const gauge2Id of gauge2Ids) {
297
- assert.equal(idInUseElOrFillAttr(gauge1, gauge2Id), false);
298
- assert.equal(idInUseElOrFillAttr(gauge2, gauge2Id), true);
299
- assert.ok(!gauge1Ids.includes(gauge2Id));
300
- }
301
- });
302
- });
303
- });
@@ -1,325 +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 URL = require('../../../lighthouse-core/lib/url-shim.js');
16
- const DOM = require('../../renderer/dom.js');
17
- const DetailsRenderer = require('../../renderer/details-renderer.js');
18
- const ReportUIFeatures = require('../../renderer/report-ui-features.js');
19
- const CategoryRenderer = require('../../renderer/category-renderer.js');
20
- const ElementScreenshotRenderer = require('../../renderer/element-screenshot-renderer.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
- const TIMESTAMP_REGEX = /\d+, \d{4}.*\d+:\d+/;
26
-
27
- describe('ReportRenderer', () => {
28
- let renderer;
29
- let sampleResults;
30
-
31
- beforeAll(() => {
32
- global.Util = Util;
33
- global.I18n = I18n;
34
- global.ReportUIFeatures = ReportUIFeatures;
35
- global.CriticalRequestChainRenderer = CriticalRequestChainRenderer;
36
- global.DetailsRenderer = DetailsRenderer;
37
- global.CategoryRenderer = CategoryRenderer;
38
- global.ElementScreenshotRenderer = ElementScreenshotRenderer;
39
-
40
- // lazy loaded because they depend on CategoryRenderer to be available globally
41
- global.PerformanceCategoryRenderer =
42
- require('../../renderer/performance-category-renderer.js');
43
- global.PwaCategoryRenderer = require('../../renderer/pwa-category-renderer.js');
44
-
45
- // Stub out matchMedia for Node.
46
- global.matchMedia = function() {
47
- return {
48
- addListener: function() {},
49
- };
50
- };
51
-
52
- const {window} = new jsdom.JSDOM(reportAssets.REPORT_TEMPLATES);
53
- global.self = window;
54
-
55
- const dom = new DOM(window.document);
56
- const detailsRenderer = new DetailsRenderer(dom);
57
- const categoryRenderer = new CategoryRenderer(dom, detailsRenderer);
58
- renderer = new ReportRenderer(dom, categoryRenderer);
59
- sampleResults = Util.prepareReportResult(sampleResultsOrig);
60
- });
61
-
62
- afterAll(() => {
63
- global.self = undefined;
64
- global.Util = undefined;
65
- global.I18n = undefined;
66
- global.ReportUIFeatures = undefined;
67
- global.matchMedia = undefined;
68
- global.CriticalRequestChainRenderer = undefined;
69
- global.DetailsRenderer = undefined;
70
- global.CategoryRenderer = undefined;
71
- global.ElementScreenshotRenderer = undefined;
72
- global.PerformanceCategoryRenderer = undefined;
73
- global.PwaCategoryRenderer = undefined;
74
- });
75
-
76
- describe('renderReport', () => {
77
- it('should render a report', () => {
78
- const container = renderer._dom._document.body;
79
- const output = renderer.renderReport(sampleResults, container);
80
- assert.ok(output.querySelector('.lh-header-container'), 'has a header');
81
- assert.ok(output.querySelector('.lh-report'), 'has report body');
82
- // 3 sets of gauges - one in sticky header, one in scores header, and one in each section.
83
- assert.equal(output.querySelectorAll('.lh-gauge__wrapper, .lh-gauge--pwa__wrapper').length,
84
- Object.keys(sampleResults.categories).length * 3, 'renders category gauges');
85
- });
86
-
87
- it('renders additional reports by replacing the existing one', () => {
88
- const container = renderer._dom._document.body;
89
- const oldReport = Array.from(renderer.renderReport(sampleResults, container).children);
90
- const newReport = Array.from(renderer.renderReport(sampleResults, container).children);
91
- assert.ok(!oldReport.find(node => container.contains(node)), 'old report was removed');
92
- assert.ok(newReport.find(node => container.contains(node)),
93
- 'new report appended to container');
94
- });
95
-
96
- it('renders a topbar', () => {
97
- const topbar = renderer._renderReportTopbar(sampleResults);
98
- assert.equal(topbar.querySelector('.lh-topbar__url').textContent, sampleResults.finalUrl);
99
- });
100
-
101
- it('renders a header', () => {
102
- const header = renderer._renderReportHeader();
103
- assert.ok(header.querySelector('.lh-scores-container'), 'contains score container');
104
- });
105
-
106
- it('renders score gauges in this order: default, pwa, plugins', () => {
107
- const sampleResultsCopy = JSON.parse(JSON.stringify(sampleResults));
108
- sampleResultsCopy.categories['lighthouse-plugin-someplugin'] = {
109
- id: 'lighthouse-plugin-someplugin',
110
- title: 'Some Plugin',
111
- auditRefs: [],
112
- };
113
-
114
- const container = renderer._dom._document.body;
115
- const output = renderer.renderReport(sampleResultsCopy, container);
116
-
117
- function isPWAGauge(el) {
118
- return el.querySelector('.lh-gauge__label').textContent === 'Progressive Web App';
119
- }
120
- function isPluginGauge(el) {
121
- return el.querySelector('.lh-gauge__label').textContent === 'Some Plugin';
122
- }
123
-
124
- const indexOfPwaGauge = Array.from(output
125
- .querySelectorAll('.lh-scores-header > a[class*="lh-gauge"]')).findIndex(isPWAGauge);
126
-
127
- const indexOfPluginGauge = Array.from(output
128
- .querySelectorAll('.lh-scores-header > a[class*="lh-gauge"]')).findIndex(isPluginGauge);
129
-
130
- const scoresHeaderElem = output.querySelector('.lh-scores-header');
131
- assert.equal(scoresHeaderElem.children.length - 2, indexOfPwaGauge);
132
- assert.equal(scoresHeaderElem.children.length - 1, indexOfPluginGauge);
133
- assert(indexOfPluginGauge > indexOfPwaGauge);
134
-
135
- for (let i = 0; i < scoresHeaderElem.children.length; i++) {
136
- const gauge = scoresHeaderElem.children[i];
137
-
138
- assert.ok(gauge.classList.contains('lh-gauge__wrapper'));
139
- if (i >= indexOfPluginGauge) {
140
- assert.ok(isPluginGauge(gauge));
141
- } else if (i >= indexOfPwaGauge) {
142
- assert.ok(isPWAGauge(gauge));
143
- }
144
- }
145
- });
146
-
147
- it('renders plugin score gauge', () => {
148
- const sampleResultsCopy = JSON.parse(JSON.stringify(sampleResults));
149
- sampleResultsCopy.categories['lighthouse-plugin-someplugin'] = {
150
- id: 'lighthouse-plugin-someplugin',
151
- title: 'Some Plugin',
152
- auditRefs: [],
153
- };
154
- const container = renderer._dom._document.body;
155
- const output = renderer.renderReport(sampleResultsCopy, container);
156
- const scoresHeaderElem = output.querySelector('.lh-scores-header');
157
-
158
- const gaugeCount = scoresHeaderElem.querySelectorAll('.lh-gauge').length;
159
- const pluginGaugeCount =
160
- scoresHeaderElem.querySelectorAll('.lh-gauge__wrapper--plugin').length;
161
-
162
- // 5 core categories + the 1 plugin.
163
- assert.equal(6, gaugeCount);
164
- assert.equal(1, pluginGaugeCount);
165
- });
166
-
167
- it('should not mutate a report object', () => {
168
- const container = renderer._dom._document.body;
169
- const originalResults = JSON.parse(JSON.stringify(sampleResults));
170
- renderer.renderReport(sampleResults, container);
171
- assert.deepStrictEqual(sampleResults, originalResults);
172
- }, 2000);
173
-
174
- it('renders no warning section when no lighthouseRunWarnings occur', () => {
175
- const warningResults = Object.assign({}, sampleResults, {runWarnings: []});
176
- const container = renderer._dom._document.body;
177
- const output = renderer.renderReport(warningResults, container);
178
- assert.strictEqual(output.querySelector('.lh-warnings--toplevel'), null);
179
- });
180
-
181
- it('renders a warning section', () => {
182
- const container = renderer._dom._document.body;
183
- const output = renderer.renderReport(sampleResults, container);
184
-
185
- const warningEls = output.querySelectorAll('.lh-warnings--toplevel > ul > li');
186
- assert.strictEqual(warningEls.length, sampleResults.runWarnings.length);
187
- });
188
-
189
- it('renders links in the warning section', () => {
190
- const warningResults = Object.assign({}, sampleResults, {
191
- runWarnings: ['[I am a link](https://example.com/)'],
192
- });
193
- const container = renderer._dom._document.body;
194
- const output = renderer.renderReport(warningResults, container);
195
-
196
- const warningEls = output.querySelectorAll('.lh-warnings--toplevel ul li a');
197
- expect(warningEls).toHaveLength(1);
198
- expect(warningEls[0].href).toEqual('https://example.com/');
199
- });
200
-
201
- it('renders a footer', () => {
202
- const footer = renderer._renderReportFooter(sampleResults);
203
- const footerContent = footer.querySelector('.lh-footer').textContent;
204
- assert.ok(/Generated by Lighthouse \d/.test(footerContent), 'includes lh version');
205
- assert.ok(footerContent.match(TIMESTAMP_REGEX), 'includes timestamp');
206
-
207
- // Check runtime settings were populated.
208
- const names = Array.from(footer.querySelectorAll('.lh-env__name'));
209
- const descriptions = Array.from(footer.querySelectorAll('.lh-env__description'));
210
- assert.ok(names.length >= 3);
211
- assert.ok(descriptions.length >= 3);
212
-
213
- const descriptionsTxt = descriptions.map(el => el.textContent).join('\n');
214
- expect(descriptionsTxt).toContain('Moto G4');
215
- expect(descriptionsTxt).toContain('RTT');
216
- expect(descriptionsTxt).toMatch(/\dx/);
217
- expect(descriptionsTxt).toContain(sampleResults.userAgent);
218
- });
219
- });
220
-
221
- it('can set a custom templateContext', () => {
222
- assert.equal(renderer._templateContext, renderer._dom.document());
223
-
224
- const {window} = new jsdom.JSDOM(reportAssets.REPORT_TEMPLATES);
225
- const otherDocument = window.document;
226
- renderer.setTemplateContext(otherDocument);
227
- assert.equal(renderer._templateContext, otherDocument);
228
- });
229
-
230
- it('should add LHR channel to doc link parameters', () => {
231
- const lhrChannel = sampleResults.configSettings.channel;
232
- // Make sure we have a channel in the LHR.
233
- assert.ok(lhrChannel.length > 2);
234
-
235
- const container = renderer._dom._document.body;
236
- const output = renderer.renderReport(sampleResults, container);
237
-
238
- const DOCS_ORIGINS = ['https://developers.google.com', 'https://web.dev'];
239
- const utmChannels = [...output.querySelectorAll('a[href*="utm_source=lighthouse"')]
240
- .map(a => new URL(a.href))
241
- .filter(url => DOCS_ORIGINS.includes(url.origin))
242
- .map(url => url.searchParams.get('utm_medium'));
243
-
244
- assert.ok(utmChannels.length > 100);
245
- for (const utmChannel of utmChannels) {
246
- assert.strictEqual(utmChannel, lhrChannel);
247
- }
248
- });
249
-
250
- it('renders `not_applicable` audits as `notApplicable`', () => {
251
- const clonedSampleResult = JSON.parse(JSON.stringify(sampleResultsOrig));
252
-
253
- let notApplicableCount = 0;
254
- Object.values(clonedSampleResult.audits).forEach(audit => {
255
- // The performance-budget audit is omitted from the DOM when it is not applicable
256
- if (audit.scoreDisplayMode === 'notApplicable' && audit.id !== 'performance-budget') {
257
- notApplicableCount++;
258
- audit.scoreDisplayMode = 'not_applicable';
259
- }
260
- });
261
-
262
- assert.ok(notApplicableCount > 20); // Make sure something's being tested.
263
-
264
- const container = renderer._dom._document.body;
265
- const reportElement = renderer.renderReport(sampleResults, container);
266
- const notApplicableElementCount = reportElement
267
- .querySelectorAll('.lh-audit--notapplicable').length;
268
- assert.strictEqual(notApplicableCount, notApplicableElementCount);
269
- });
270
-
271
- describe('axe-core', () => {
272
- let axe;
273
-
274
- beforeAll(() =>{
275
- // Needed by axe-core
276
- // https://github.com/dequelabs/axe-core/blob/581c441c/doc/examples/jsdom/test/a11y.js#L24
277
- global.window = global.self;
278
- global.Node = global.self.Node;
279
- global.Element = global.self.Element;
280
-
281
- // axe-core must be required after the global polyfills
282
- axe = require('axe-core');
283
- });
284
-
285
- afterAll(() => {
286
- global.window = undefined;
287
- global.Node = undefined;
288
- global.Element = undefined;
289
- });
290
-
291
- it('renders without axe violations', () => {
292
- const container = renderer._dom._document.createElement('main');
293
- const output = renderer.renderReport(sampleResults, container);
294
- renderer._dom._document.body.appendChild(container);
295
-
296
- const config = {
297
- rules: {
298
- // Reports may have duplicate ids
299
- // https://github.com/GoogleChrome/lighthouse/issues/9432
300
- 'duplicate-id': {enabled: false},
301
- 'duplicate-id-aria': {enabled: false},
302
- 'landmark-no-duplicate-contentinfo': {enabled: false},
303
- // The following rules are disable for axe-core + jsdom compatibility
304
- // https://github.com/dequelabs/axe-core/tree/b573b1c1/doc/examples/jest_react#to-run-the-example
305
- 'color-contrast': {enabled: false},
306
- 'link-in-text-block': {enabled: false},
307
- // Report has empty links prior to i18n-ing.
308
- 'link-name': {enabled: false},
309
- // May not be a real issue. https://github.com/dequelabs/axe-core/issues/2958
310
- 'nested-interactive': {enabled: false},
311
- },
312
- };
313
-
314
- return new Promise(resolve => {
315
- axe.run(output, config, (error, {violations}) => {
316
- expect(error).toBeNull();
317
- expect(violations).toEqual([]);
318
- resolve();
319
- });
320
- });
321
- // This test takes 40s on fast hardware, and 50-60s on GHA.
322
- // https://github.com/dequelabs/axe-core/tree/b573b1c1/doc/examples/jest_react#timeout-issues
323
- }, /* timeout= */ 100 * 1000);
324
- });
325
- });