@monoes/monobrowse 1.0.11 → 1.0.13
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.
- package/dist/src/__tests__/adapters.test.js +5 -2
- package/dist/src/__tests__/adapters.test.js.map +1 -1
- package/dist/src/__tests__/batch-eval-parsing.test.js +4 -2
- package/dist/src/__tests__/batch-eval-parsing.test.js.map +1 -1
- package/dist/src/__tests__/box-model.test.js +9 -5
- package/dist/src/__tests__/box-model.test.js.map +1 -1
- package/dist/src/__tests__/browser-launch.test.d.ts +10 -0
- package/dist/src/__tests__/browser-launch.test.d.ts.map +1 -1
- package/dist/src/__tests__/browser-launch.test.js +17 -10
- package/dist/src/__tests__/browser-launch.test.js.map +1 -1
- package/dist/src/__tests__/cdp-client.test.js +9 -3
- package/dist/src/__tests__/cdp-client.test.js.map +1 -1
- package/dist/src/__tests__/close-browser.test.d.ts +13 -0
- package/dist/src/__tests__/close-browser.test.d.ts.map +1 -1
- package/dist/src/__tests__/close-browser.test.js +5 -5
- package/dist/src/__tests__/close-browser.test.js.map +1 -1
- package/dist/src/__tests__/console-log.test.js +17 -6
- package/dist/src/__tests__/console-log.test.js.map +1 -1
- package/dist/src/__tests__/find.test.js +26 -6
- package/dist/src/__tests__/find.test.js.map +1 -1
- package/dist/src/__tests__/frame-command.test.js +9 -3
- package/dist/src/__tests__/frame-command.test.js.map +1 -1
- package/dist/src/__tests__/open-url-navigate-error.test.js +1 -3
- package/dist/src/__tests__/open-url-navigate-error.test.js.map +1 -1
- package/dist/src/__tests__/output.test.js +1 -1
- package/dist/src/__tests__/output.test.js.map +1 -1
- package/dist/src/__tests__/profiler-heap.test.d.ts +2 -0
- package/dist/src/__tests__/profiler-heap.test.d.ts.map +1 -0
- package/dist/src/__tests__/profiler-heap.test.js +154 -0
- package/dist/src/__tests__/profiler-heap.test.js.map +1 -0
- package/dist/src/__tests__/reap-idle-browser.test.d.ts +15 -0
- package/dist/src/__tests__/reap-idle-browser.test.d.ts.map +1 -0
- package/dist/src/__tests__/reap-idle-browser.test.js +238 -0
- package/dist/src/__tests__/reap-idle-browser.test.js.map +1 -0
- package/dist/src/__tests__/ref-cache.test.js +18 -10
- package/dist/src/__tests__/ref-cache.test.js.map +1 -1
- package/dist/src/__tests__/report-a11y.test.d.ts +2 -0
- package/dist/src/__tests__/report-a11y.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-a11y.test.js +147 -0
- package/dist/src/__tests__/report-a11y.test.js.map +1 -0
- package/dist/src/__tests__/report-analyze.test.d.ts +2 -0
- package/dist/src/__tests__/report-analyze.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-analyze.test.js +157 -0
- package/dist/src/__tests__/report-analyze.test.js.map +1 -0
- package/dist/src/__tests__/report-budget.test.d.ts +2 -0
- package/dist/src/__tests__/report-budget.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-budget.test.js +80 -0
- package/dist/src/__tests__/report-budget.test.js.map +1 -0
- package/dist/src/__tests__/report-diff.test.d.ts +2 -0
- package/dist/src/__tests__/report-diff.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-diff.test.js +231 -0
- package/dist/src/__tests__/report-diff.test.js.map +1 -0
- package/dist/src/__tests__/report-evidence.test.d.ts +2 -0
- package/dist/src/__tests__/report-evidence.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-evidence.test.js +214 -0
- package/dist/src/__tests__/report-evidence.test.js.map +1 -0
- package/dist/src/__tests__/report-flake.test.d.ts +2 -0
- package/dist/src/__tests__/report-flake.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-flake.test.js +182 -0
- package/dist/src/__tests__/report-flake.test.js.map +1 -0
- package/dist/src/__tests__/report-history.test.d.ts +2 -0
- package/dist/src/__tests__/report-history.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-history.test.js +229 -0
- package/dist/src/__tests__/report-history.test.js.map +1 -0
- package/dist/src/__tests__/report-output.test.d.ts +2 -0
- package/dist/src/__tests__/report-output.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-output.test.js +169 -0
- package/dist/src/__tests__/report-output.test.js.map +1 -0
- package/dist/src/__tests__/report-png.test.d.ts +2 -0
- package/dist/src/__tests__/report-png.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-png.test.js +84 -0
- package/dist/src/__tests__/report-png.test.js.map +1 -0
- package/dist/src/__tests__/report-render-extras.test.d.ts +2 -0
- package/dist/src/__tests__/report-render-extras.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-render-extras.test.js +285 -0
- package/dist/src/__tests__/report-render-extras.test.js.map +1 -0
- package/dist/src/__tests__/report-render.test.d.ts +2 -0
- package/dist/src/__tests__/report-render.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-render.test.js +143 -0
- package/dist/src/__tests__/report-render.test.js.map +1 -0
- package/dist/src/__tests__/report-run.test.d.ts +2 -0
- package/dist/src/__tests__/report-run.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-run.test.js +234 -0
- package/dist/src/__tests__/report-run.test.js.map +1 -0
- package/dist/src/__tests__/session-state.test.d.ts +8 -0
- package/dist/src/__tests__/session-state.test.d.ts.map +1 -1
- package/dist/src/__tests__/session-state.test.js +10 -10
- package/dist/src/__tests__/session-state.test.js.map +1 -1
- package/dist/src/__tests__/snapshot.test.js +44 -14
- package/dist/src/__tests__/snapshot.test.js.map +1 -1
- package/dist/src/__tests__/storage-eval.test.js +14 -6
- package/dist/src/__tests__/storage-eval.test.js.map +1 -1
- package/dist/src/__tests__/tabs.test.js +25 -9
- package/dist/src/__tests__/tabs.test.js.map +1 -1
- package/dist/src/browser/action-builder/analyzer.d.ts +1 -1
- package/dist/src/browser/action-builder/analyzer.d.ts.map +1 -1
- package/dist/src/browser/action-builder/analyzer.js +25 -9
- package/dist/src/browser/action-builder/analyzer.js.map +1 -1
- package/dist/src/browser/action-builder/types.d.ts.map +1 -1
- package/dist/src/browser/actions.d.ts +1 -1
- package/dist/src/browser/actions.d.ts.map +1 -1
- package/dist/src/browser/actions.js +16 -6
- package/dist/src/browser/actions.js.map +1 -1
- package/dist/src/browser/adapters/gemini.d.ts.map +1 -1
- package/dist/src/browser/adapters/gemini.js.map +1 -1
- package/dist/src/browser/adapters/google.d.ts.map +1 -1
- package/dist/src/browser/adapters/google.js.map +1 -1
- package/dist/src/browser/adapters/index.d.ts.map +1 -1
- package/dist/src/browser/adapters/index.js +3 -3
- package/dist/src/browser/adapters/index.js.map +1 -1
- package/dist/src/browser/adapters/instagram.d.ts.map +1 -1
- package/dist/src/browser/adapters/instagram.js.map +1 -1
- package/dist/src/browser/adapters/linkedin.d.ts.map +1 -1
- package/dist/src/browser/adapters/linkedin.js.map +1 -1
- package/dist/src/browser/adapters/microsoft.d.ts.map +1 -1
- package/dist/src/browser/adapters/microsoft.js.map +1 -1
- package/dist/src/browser/adapters/x.d.ts.map +1 -1
- package/dist/src/browser/adapters/x.js.map +1 -1
- package/dist/src/browser/browser.d.ts +30 -0
- package/dist/src/browser/browser.d.ts.map +1 -1
- package/dist/src/browser/browser.js +122 -15
- package/dist/src/browser/browser.js.map +1 -1
- package/dist/src/browser/cdp.d.ts.map +1 -1
- package/dist/src/browser/cdp.js +21 -8
- package/dist/src/browser/cdp.js.map +1 -1
- package/dist/src/browser/console-log.d.ts.map +1 -1
- package/dist/src/browser/console-log.js +2 -2
- package/dist/src/browser/console-log.js.map +1 -1
- package/dist/src/browser/dashboard/server.d.ts.map +1 -1
- package/dist/src/browser/dashboard/server.js +29 -19
- package/dist/src/browser/dashboard/server.js.map +1 -1
- package/dist/src/browser/dashboard/ui.html +153 -165
- package/dist/src/browser/dialog.d.ts.map +1 -1
- package/dist/src/browser/dialog.js +3 -1
- package/dist/src/browser/dialog.js.map +1 -1
- package/dist/src/browser/emulation.d.ts.map +1 -1
- package/dist/src/browser/emulation.js +21 -6
- package/dist/src/browser/emulation.js.map +1 -1
- package/dist/src/browser/find.d.ts +4 -4
- package/dist/src/browser/find.d.ts.map +1 -1
- package/dist/src/browser/find.js +14 -6
- package/dist/src/browser/find.js.map +1 -1
- package/dist/src/browser/har.d.ts.map +1 -1
- package/dist/src/browser/har.js +14 -7
- package/dist/src/browser/har.js.map +1 -1
- package/dist/src/browser/index.d.ts +17 -16
- package/dist/src/browser/index.d.ts.map +1 -1
- package/dist/src/browser/index.js +17 -16
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/browser/network.d.ts.map +1 -1
- package/dist/src/browser/network.js +14 -4
- package/dist/src/browser/network.js.map +1 -1
- package/dist/src/browser/pdf.d.ts.map +1 -1
- package/dist/src/browser/pdf.js +3 -3
- package/dist/src/browser/pdf.js.map +1 -1
- package/dist/src/browser/profiler.d.ts.map +1 -1
- package/dist/src/browser/profiler.js +22 -20
- package/dist/src/browser/profiler.js.map +1 -1
- package/dist/src/browser/record.d.ts +1 -1
- package/dist/src/browser/record.d.ts.map +1 -1
- package/dist/src/browser/record.js +18 -7
- package/dist/src/browser/record.js.map +1 -1
- package/dist/src/browser/ref-cache.d.ts.map +1 -1
- package/dist/src/browser/ref-cache.js +9 -4
- package/dist/src/browser/ref-cache.js.map +1 -1
- package/dist/src/browser/screenshot.d.ts.map +1 -1
- package/dist/src/browser/screenshot.js +11 -7
- package/dist/src/browser/screenshot.js.map +1 -1
- package/dist/src/browser/session.d.ts +1 -1
- package/dist/src/browser/session.d.ts.map +1 -1
- package/dist/src/browser/session.js +27 -8
- package/dist/src/browser/session.js.map +1 -1
- package/dist/src/browser/snapshot.d.ts +1 -1
- package/dist/src/browser/snapshot.d.ts.map +1 -1
- package/dist/src/browser/snapshot.js +8 -4
- package/dist/src/browser/snapshot.js.map +1 -1
- package/dist/src/browser/storage.d.ts.map +1 -1
- package/dist/src/browser/storage.js.map +1 -1
- package/dist/src/browser/tabs.d.ts.map +1 -1
- package/dist/src/browser/tabs.js +9 -3
- package/dist/src/browser/tabs.js.map +1 -1
- package/dist/src/browser/trace.d.ts.map +1 -1
- package/dist/src/browser/trace.js +3 -3
- package/dist/src/browser/trace.js.map +1 -1
- package/dist/src/browser/types.d.ts.map +1 -1
- package/dist/src/browser/types.js +23 -4
- package/dist/src/browser/types.js.map +1 -1
- package/dist/src/browser/vitals.d.ts.map +1 -1
- package/dist/src/browser/vitals.js +1 -1
- package/dist/src/browser/vitals.js.map +1 -1
- package/dist/src/browser/wait.d.ts.map +1 -1
- package/dist/src/browser/wait.js +11 -5
- package/dist/src/browser/wait.js.map +1 -1
- package/dist/src/cli/action.d.ts.map +1 -1
- package/dist/src/cli/action.js +14 -11
- package/dist/src/cli/action.js.map +1 -1
- package/dist/src/cli/commands.d.ts.map +1 -1
- package/dist/src/cli/commands.js +707 -159
- package/dist/src/cli/commands.js.map +1 -1
- package/dist/src/cli/output.js +5 -5
- package/dist/src/cli/output.js.map +1 -1
- package/dist/src/cli/platform.d.ts.map +1 -1
- package/dist/src/cli/platform.js +15 -11
- package/dist/src/cli/platform.js.map +1 -1
- package/dist/src/cli/types.d.ts +1 -1
- package/dist/src/cli/types.d.ts.map +1 -1
- package/dist/src/cli.js +21 -9
- package/dist/src/cli.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/report/a11y.d.ts +52 -0
- package/dist/src/report/a11y.d.ts.map +1 -0
- package/dist/src/report/a11y.js +231 -0
- package/dist/src/report/a11y.js.map +1 -0
- package/dist/src/report/analyze.d.ts +20 -0
- package/dist/src/report/analyze.d.ts.map +1 -0
- package/dist/src/report/analyze.js +136 -0
- package/dist/src/report/analyze.js.map +1 -0
- package/dist/src/report/budget.d.ts +27 -0
- package/dist/src/report/budget.d.ts.map +1 -0
- package/dist/src/report/budget.js +143 -0
- package/dist/src/report/budget.js.map +1 -0
- package/dist/src/report/collect-a11y.d.ts +25 -0
- package/dist/src/report/collect-a11y.d.ts.map +1 -0
- package/dist/src/report/collect-a11y.js +154 -0
- package/dist/src/report/collect-a11y.js.map +1 -0
- package/dist/src/report/collect.d.ts +45 -0
- package/dist/src/report/collect.d.ts.map +1 -0
- package/dist/src/report/collect.js +275 -0
- package/dist/src/report/collect.js.map +1 -0
- package/dist/src/report/evidence.d.ts +80 -0
- package/dist/src/report/evidence.d.ts.map +1 -0
- package/dist/src/report/evidence.js +279 -0
- package/dist/src/report/evidence.js.map +1 -0
- package/dist/src/report/flake.d.ts +88 -0
- package/dist/src/report/flake.d.ts.map +1 -0
- package/dist/src/report/flake.js +232 -0
- package/dist/src/report/flake.js.map +1 -0
- package/dist/src/report/history.d.ts +85 -0
- package/dist/src/report/history.d.ts.map +1 -0
- package/dist/src/report/history.js +176 -0
- package/dist/src/report/history.js.map +1 -0
- package/dist/src/report/index.d.ts +102 -0
- package/dist/src/report/index.d.ts.map +1 -0
- package/dist/src/report/index.js +216 -0
- package/dist/src/report/index.js.map +1 -0
- package/dist/src/report/pixel-diff.d.ts +30 -0
- package/dist/src/report/pixel-diff.d.ts.map +1 -0
- package/dist/src/report/pixel-diff.js +175 -0
- package/dist/src/report/pixel-diff.js.map +1 -0
- package/dist/src/report/png.d.ts +28 -0
- package/dist/src/report/png.d.ts.map +1 -0
- package/dist/src/report/png.js +259 -0
- package/dist/src/report/png.js.map +1 -0
- package/dist/src/report/render-evidence.d.ts +16 -0
- package/dist/src/report/render-evidence.d.ts.map +1 -0
- package/dist/src/report/render-evidence.js +174 -0
- package/dist/src/report/render-evidence.js.map +1 -0
- package/dist/src/report/render-trend.d.ts +16 -0
- package/dist/src/report/render-trend.d.ts.map +1 -0
- package/dist/src/report/render-trend.js +194 -0
- package/dist/src/report/render-trend.js.map +1 -0
- package/dist/src/report/render.d.ts +21 -0
- package/dist/src/report/render.d.ts.map +1 -0
- package/dist/src/report/render.js +286 -0
- package/dist/src/report/render.js.map +1 -0
- package/dist/src/report/run-diff.d.ts +18 -0
- package/dist/src/report/run-diff.d.ts.map +1 -0
- package/dist/src/report/run-diff.js +51 -0
- package/dist/src/report/run-diff.js.map +1 -0
- package/dist/src/report/structure.d.ts +41 -0
- package/dist/src/report/structure.d.ts.map +1 -0
- package/dist/src/report/structure.js +210 -0
- package/dist/src/report/structure.js.map +1 -0
- package/dist/src/report/trend.d.ts +26 -0
- package/dist/src/report/trend.d.ts.map +1 -0
- package/dist/src/report/trend.js +164 -0
- package/dist/src/report/trend.js.map +1 -0
- package/dist/src/report/types.d.ts +320 -0
- package/dist/src/report/types.d.ts.map +1 -0
- package/dist/src/report/types.js +11 -0
- package/dist/src/report/types.js.map +1 -0
- package/dist/src/report/util.d.ts +17 -0
- package/dist/src/report/util.d.ts.map +1 -0
- package/dist/src/report/util.js +45 -0
- package/dist/src/report/util.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/__tests__/adapters.test.ts +15 -8
- package/src/__tests__/batch-eval-parsing.test.ts +4 -2
- package/src/__tests__/box-model.test.ts +9 -5
- package/src/__tests__/browser-launch.test.ts +26 -15
- package/src/__tests__/cdp-client.test.ts +25 -9
- package/src/__tests__/close-browser.test.ts +11 -6
- package/src/__tests__/console-log.test.ts +36 -13
- package/src/__tests__/find.test.ts +58 -20
- package/src/__tests__/frame-command.test.ts +12 -6
- package/src/__tests__/open-url-navigate-error.test.ts +2 -4
- package/src/__tests__/output.test.ts +1 -1
- package/src/__tests__/profiler-heap.test.ts +191 -0
- package/src/__tests__/reap-idle-browser.test.ts +276 -0
- package/src/__tests__/ref-cache.test.ts +25 -12
- package/src/__tests__/report-a11y.test.ts +180 -0
- package/src/__tests__/report-analyze.test.ts +202 -0
- package/src/__tests__/report-budget.test.ts +92 -0
- package/src/__tests__/report-diff.test.ts +272 -0
- package/src/__tests__/report-evidence.test.ts +276 -0
- package/src/__tests__/report-flake.test.ts +214 -0
- package/src/__tests__/report-history.test.ts +293 -0
- package/src/__tests__/report-output.test.ts +210 -0
- package/src/__tests__/report-png.test.ts +95 -0
- package/src/__tests__/report-render-extras.test.ts +315 -0
- package/src/__tests__/report-render.test.ts +175 -0
- package/src/__tests__/report-run.test.ts +264 -0
- package/src/__tests__/session-state.test.ts +40 -28
- package/src/__tests__/snapshot.test.ts +60 -21
- package/src/__tests__/storage-eval.test.ts +30 -16
- package/src/__tests__/tabs.test.ts +26 -10
- package/src/browser/action-builder/analyzer.ts +39 -15
- package/src/browser/action-builder/types.ts +45 -8
- package/src/browser/actions.ts +288 -123
- package/src/browser/adapters/gemini.ts +7 -3
- package/src/browser/adapters/google.ts +5 -3
- package/src/browser/adapters/index.ts +5 -4
- package/src/browser/adapters/instagram.ts +4 -2
- package/src/browser/adapters/linkedin.ts +4 -2
- package/src/browser/adapters/microsoft.ts +9 -5
- package/src/browser/adapters/x.ts +7 -3
- package/src/browser/browser.ts +188 -42
- package/src/browser/cdp.ts +43 -11
- package/src/browser/console-log.ts +24 -7
- package/src/browser/dashboard/server.ts +44 -25
- package/src/browser/dashboard/ui.html +153 -165
- package/src/browser/dialog.ts +25 -8
- package/src/browser/emulation.ts +86 -36
- package/src/browser/find.ts +110 -47
- package/src/browser/har.ts +58 -26
- package/src/browser/index.ts +17 -16
- package/src/browser/network.ts +147 -46
- package/src/browser/pdf.ts +4 -4
- package/src/browser/profiler.ts +39 -19
- package/src/browser/record.ts +38 -19
- package/src/browser/ref-cache.ts +38 -17
- package/src/browser/screenshot.ts +58 -32
- package/src/browser/session.ts +51 -18
- package/src/browser/snapshot.ts +34 -20
- package/src/browser/storage.ts +73 -17
- package/src/browser/tabs.ts +29 -17
- package/src/browser/trace.ts +14 -10
- package/src/browser/types.ts +23 -4
- package/src/browser/vitals.ts +33 -16
- package/src/browser/wait.ts +47 -21
- package/src/cli/action.ts +52 -21
- package/src/cli/commands.ts +1365 -385
- package/src/cli/output.ts +5 -5
- package/src/cli/platform.ts +44 -23
- package/src/cli/types.ts +1 -1
- package/src/cli.ts +34 -18
- package/src/index.ts +2 -2
- package/src/report/a11y.ts +242 -0
- package/src/report/analyze.ts +181 -0
- package/src/report/budget.ts +155 -0
- package/src/report/collect-a11y.ts +200 -0
- package/src/report/collect.ts +408 -0
- package/src/report/evidence.ts +379 -0
- package/src/report/flake.ts +303 -0
- package/src/report/history.ts +219 -0
- package/src/report/index.ts +307 -0
- package/src/report/pixel-diff.ts +197 -0
- package/src/report/png.ts +290 -0
- package/src/report/render-evidence.ts +194 -0
- package/src/report/render-trend.ts +225 -0
- package/src/report/render.ts +314 -0
- package/src/report/run-diff.ts +63 -0
- package/src/report/structure.ts +212 -0
- package/src/report/trend.ts +189 -0
- package/src/report/types.ts +356 -0
- package/src/report/util.ts +48 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report sections for the trend (RIG-13) and the run-to-run diff (RIG-10).
|
|
3
|
+
*
|
|
4
|
+
* Kept separate from render.ts purely for size. Same rules apply: no external
|
|
5
|
+
* resources, so the sparklines are hand-written inline SVG rather than a
|
|
6
|
+
* charting library, and the diff image is a `data:` URI.
|
|
7
|
+
*
|
|
8
|
+
* The design goal for the trend is legibility at a glance — the point of the
|
|
9
|
+
* feature is catching decay nobody noticed, which only works if the reader
|
|
10
|
+
* sees it without going looking.
|
|
11
|
+
*/
|
|
12
|
+
import { formatTrendDelta, formatTrendValue } from './trend.js';
|
|
13
|
+
import { escapeHtml } from './util.js';
|
|
14
|
+
/** Rows shown per diff category before the tail is summarised. */
|
|
15
|
+
const MAX_DIFF_ROWS = 20;
|
|
16
|
+
export const TREND_STYLES = `
|
|
17
|
+
.headlines{background:var(--warn-bg);border:1px solid var(--warn);color:var(--warn);
|
|
18
|
+
border-radius:10px;padding:12px 16px;margin:0 0 16px}
|
|
19
|
+
.headlines p{margin:0 0 6px;font-size:14px}
|
|
20
|
+
.headlines p:last-child{margin-bottom:0}
|
|
21
|
+
.spark{display:block}
|
|
22
|
+
.spark .line{fill:none;stroke:var(--muted);stroke-width:1.5}
|
|
23
|
+
.spark .dot{fill:var(--ink)}
|
|
24
|
+
.dir{font-weight:600}
|
|
25
|
+
.dir.regressed{color:var(--fail)}
|
|
26
|
+
.dir.improved{color:var(--pass)}
|
|
27
|
+
.dir.flat,.dir.new{color:var(--muted)}
|
|
28
|
+
.verdictstrip{display:flex;flex-wrap:wrap;gap:4px;margin:0 0 16px;padding:0;list-style:none}
|
|
29
|
+
.verdictstrip li{width:13px;height:13px;border-radius:3px;background:var(--pass)}
|
|
30
|
+
.verdictstrip li.fail{background:var(--fail)}
|
|
31
|
+
.difftag{display:inline-block;margin:0 8px 8px 0;padding:4px 10px;border-radius:999px;
|
|
32
|
+
font-size:12px;background:var(--panel);border:1px solid var(--line)}
|
|
33
|
+
.difftag b{font-variant-numeric:tabular-nums}
|
|
34
|
+
`.trim();
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Trend
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
/**
|
|
39
|
+
* A sparkline as inline SVG. Flat series are drawn down the middle rather
|
|
40
|
+
* than at y=0, which is what a naive min/max scale does when every value is
|
|
41
|
+
* identical and it reads as a cliff.
|
|
42
|
+
*/
|
|
43
|
+
function sparkline(series) {
|
|
44
|
+
const values = series.points.map((p) => p.value).filter((v) => v !== null);
|
|
45
|
+
if (values.length < 2)
|
|
46
|
+
return '<span style="color:var(--muted)">—</span>';
|
|
47
|
+
const width = 120;
|
|
48
|
+
const height = 24;
|
|
49
|
+
const min = Math.min(...values);
|
|
50
|
+
const max = Math.max(...values);
|
|
51
|
+
const span = max - min;
|
|
52
|
+
const x = (i) => (i / (values.length - 1)) * (width - 4) + 2;
|
|
53
|
+
const y = (v) => span === 0 ? height / 2 : height - 2 - ((v - min) / span) * (height - 4);
|
|
54
|
+
const points = values.map((v, i) => `${x(i).toFixed(1)},${y(v).toFixed(1)}`).join(' ');
|
|
55
|
+
const lastX = x(values.length - 1).toFixed(1);
|
|
56
|
+
const lastY = y(values[values.length - 1]).toFixed(1);
|
|
57
|
+
const label = `${series.label} over ${values.length} runs, ${formatTrendValue(series.unit, min)} to ${formatTrendValue(series.unit, max)}`;
|
|
58
|
+
return `<svg class="spark" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" role="img" aria-label="${escapeHtml(label)}">
|
|
59
|
+
<polyline class="line" points="${points}"/>
|
|
60
|
+
<circle class="dot" cx="${lastX}" cy="${lastY}" r="2.5"/>
|
|
61
|
+
</svg>`;
|
|
62
|
+
}
|
|
63
|
+
const DIRECTION_WORD = {
|
|
64
|
+
regressed: 'worse',
|
|
65
|
+
improved: 'better',
|
|
66
|
+
flat: 'steady',
|
|
67
|
+
new: 'first',
|
|
68
|
+
};
|
|
69
|
+
export function renderTrend(trend) {
|
|
70
|
+
if (!trend)
|
|
71
|
+
return '';
|
|
72
|
+
if (trend.runs === 0) {
|
|
73
|
+
return `<h2>Trend</h2><p class="empty">First recorded run for this URL — from the next run on, this section compares against it.</p>`;
|
|
74
|
+
}
|
|
75
|
+
const headlines = trend.headlines.length
|
|
76
|
+
? `<div class="headlines">${trend.headlines.map((h) => `<p>${escapeHtml(h)}</p>`).join('')}</div>`
|
|
77
|
+
: '';
|
|
78
|
+
const strip = `<ul class="verdictstrip" aria-label="Verdict per run, oldest first">${trend.verdictHistory
|
|
79
|
+
.map((v) => `<li class="${v.verdict}" title="${escapeHtml(`${v.capturedAt}: ${v.verdict}`)}"></li>`)
|
|
80
|
+
.join('')}</ul>`;
|
|
81
|
+
// A series nobody has ever measured is noise, not an absent trend.
|
|
82
|
+
const rows = trend.series
|
|
83
|
+
.filter((s) => s.points.some((p) => p.value !== null))
|
|
84
|
+
.map((s) => `<tr>
|
|
85
|
+
<td><b>${escapeHtml(s.label)}</b></td>
|
|
86
|
+
<td class="num mono">${escapeHtml(formatTrendValue(s.unit, s.previous))}</td>
|
|
87
|
+
<td class="num mono">${escapeHtml(formatTrendValue(s.unit, s.current))}</td>
|
|
88
|
+
<td class="num mono"><span class="dir ${s.direction}">${escapeHtml(formatTrendDelta(s.unit, s.deltaFromPrevious))}</span></td>
|
|
89
|
+
<td class="num mono">${escapeHtml(formatTrendDelta(s.unit, s.deltaFromOldest))}</td>
|
|
90
|
+
<td><span class="dir ${s.direction}">${DIRECTION_WORD[s.direction]}</span></td>
|
|
91
|
+
<td>${sparkline(s)}</td>
|
|
92
|
+
</tr>`)
|
|
93
|
+
.join('');
|
|
94
|
+
return `<h2>Trend — this run against the previous ${trend.runs}</h2>
|
|
95
|
+
${headlines}
|
|
96
|
+
${strip}
|
|
97
|
+
<table><thead><tr>
|
|
98
|
+
<th>Metric</th><th>Last run</th><th>This run</th><th>vs last</th>
|
|
99
|
+
<th>vs ${trend.runs} runs ago</th><th>Direction</th><th>History</th>
|
|
100
|
+
</tr></thead><tbody>${rows}</tbody></table>
|
|
101
|
+
<p class="note">Window starts ${escapeHtml(trend.windowFrom ?? 'unknown')}. Every metric here is lower-is-better, so a positive delta is a regression.</p>`;
|
|
102
|
+
}
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Diff
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
function nodeRows(nodes, kind) {
|
|
107
|
+
const shown = nodes.slice(0, MAX_DIFF_ROWS);
|
|
108
|
+
const rows = shown
|
|
109
|
+
.map((n) => `<tr>
|
|
110
|
+
<td>${escapeHtml(kind)}</td>
|
|
111
|
+
<td>${escapeHtml(n.role)}</td>
|
|
112
|
+
<td>${n.name ? escapeHtml(n.name) : '<span style="color:var(--muted)">(no accessible name)</span>'}</td>
|
|
113
|
+
<td class="wrap mono">${escapeHtml(n.path)}</td>
|
|
114
|
+
</tr>`)
|
|
115
|
+
.join('');
|
|
116
|
+
const rest = nodes.length - shown.length;
|
|
117
|
+
return rest > 0
|
|
118
|
+
? `${rows}<tr><td colspan="4" style="color:var(--muted)">…and ${rest} more ${escapeHtml(kind)}</td></tr>`
|
|
119
|
+
: rows;
|
|
120
|
+
}
|
|
121
|
+
function renderStructure(diff) {
|
|
122
|
+
const tags = [
|
|
123
|
+
`<span class="difftag"><b>${diff.gained.length}</b> gained</span>`,
|
|
124
|
+
`<span class="difftag"><b>${diff.lost.length}</b> lost</span>`,
|
|
125
|
+
`<span class="difftag"><b>${diff.renamed.length}</b> renamed</span>`,
|
|
126
|
+
`<span class="difftag"><b>${diff.moved.length}</b> moved</span>`,
|
|
127
|
+
`<span class="difftag"><b>${diff.unchanged}</b> unchanged</span>`,
|
|
128
|
+
].join('');
|
|
129
|
+
if (diff.changed === 0 && diff.moved.length === 0) {
|
|
130
|
+
return `${tags}<p class="empty">The accessibility tree is identical to the previous run.</p>`;
|
|
131
|
+
}
|
|
132
|
+
const renamedRows = diff.renamed
|
|
133
|
+
.slice(0, MAX_DIFF_ROWS)
|
|
134
|
+
.map((r) => `<tr>
|
|
135
|
+
<td>renamed</td>
|
|
136
|
+
<td>${escapeHtml(r.role)}</td>
|
|
137
|
+
<td>${escapeHtml(r.from ?? '(none)')} → <b>${escapeHtml(r.to ?? '(none)')}</b></td>
|
|
138
|
+
<td class="wrap mono">${escapeHtml(r.path)}</td>
|
|
139
|
+
</tr>`)
|
|
140
|
+
.join('');
|
|
141
|
+
const body = `${nodeRows(diff.gained, 'gained')}${nodeRows(diff.lost, 'lost')}${renamedRows}`;
|
|
142
|
+
return `${tags}
|
|
143
|
+
<table><thead><tr><th>Change</th><th>Role</th><th>Accessible name</th><th>Path</th></tr></thead>
|
|
144
|
+
<tbody>${body}</tbody></table>
|
|
145
|
+
<p class="note">Compared on the accessibility tree, not the DOM: a restyled class name is invisible here, while a control losing its label is not. Elements that only moved are counted but not listed.</p>`;
|
|
146
|
+
}
|
|
147
|
+
function renderPixels(diff) {
|
|
148
|
+
if (!diff.comparable)
|
|
149
|
+
return `<p class="empty">${escapeHtml(diff.note ?? 'Pixel diff unavailable.')}</p>`;
|
|
150
|
+
const pct = diff.changedPercent === 0
|
|
151
|
+
? '0'
|
|
152
|
+
: diff.changedPercent < 0.01
|
|
153
|
+
? '<0.01'
|
|
154
|
+
: diff.changedPercent.toFixed(2);
|
|
155
|
+
const size = diff.sizeChanged
|
|
156
|
+
? `<span class="difftag">size <b>${diff.previousSize?.width}×${diff.previousSize?.height}</b> → <b>${diff.currentSize?.width}×${diff.currentSize?.height}</b></span>`
|
|
157
|
+
: '';
|
|
158
|
+
const tags = `<span class="difftag"><b>${pct}%</b> of pixels changed</span>
|
|
159
|
+
<span class="difftag"><b>${diff.changedPixels.toLocaleString('en-US')}</b> of ${diff.totalPixels.toLocaleString('en-US')} pixels</span>${size}`;
|
|
160
|
+
if (!diff.diffDataUrl) {
|
|
161
|
+
return `${tags}<p class="empty">The screenshots are pixel-identical.</p>`;
|
|
162
|
+
}
|
|
163
|
+
const scaled = diff.scale
|
|
164
|
+
? ` Shown at 1/${diff.scale} scale; a change smaller than one output pixel is still marked.`
|
|
165
|
+
: '';
|
|
166
|
+
return `${tags}
|
|
167
|
+
<figure>
|
|
168
|
+
<figcaption>Changed pixels in magenta, over this run's screenshot.${escapeHtml(scaled)}</figcaption>
|
|
169
|
+
<img alt="Pixel differences against the previous run" src="${escapeHtml(diff.diffDataUrl)}">
|
|
170
|
+
</figure>
|
|
171
|
+
<p class="note">Per-channel tolerance is applied before counting, so anti-aliasing and font-hinting jitter do not register as change.</p>`;
|
|
172
|
+
}
|
|
173
|
+
export function renderDiff(diff) {
|
|
174
|
+
if (!diff)
|
|
175
|
+
return '';
|
|
176
|
+
const notes = diff.notes.length
|
|
177
|
+
? `<p class="note">${diff.notes.map((n) => escapeHtml(n)).join(' ')}</p>`
|
|
178
|
+
: '';
|
|
179
|
+
const structure = diff.structure
|
|
180
|
+
? `<h3 style="font-size:13px;color:var(--muted);margin:20px 0 8px">Structure</h3>${renderStructure(diff.structure)}`
|
|
181
|
+
: '';
|
|
182
|
+
const pixels = diff.pixels
|
|
183
|
+
? `<h3 style="font-size:13px;color:var(--muted);margin:24px 0 8px">Pixels</h3>${renderPixels(diff.pixels)}`
|
|
184
|
+
: '';
|
|
185
|
+
if (!structure && !pixels) {
|
|
186
|
+
return `<h2>Changes since the previous run</h2>${notes || '<p class="empty">Nothing could be compared against the previous run.</p>'}`;
|
|
187
|
+
}
|
|
188
|
+
return `<h2>Changes since the previous run</h2>
|
|
189
|
+
<p class="note">Compared against the run of ${escapeHtml(diff.previousCapturedAt)}.</p>
|
|
190
|
+
${structure}
|
|
191
|
+
${pixels}
|
|
192
|
+
${notes}`;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=render-trend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-trend.js","sourceRoot":"","sources":["../../../src/report/render-trend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders a Report as ONE self-contained HTML file: CSS inline, screenshots
|
|
3
|
+
* as `data:` URIs, no fonts, no CDN, no network access of any kind at view
|
|
4
|
+
* time. That is not a stylistic preference — it is what lets monomind's
|
|
5
|
+
* document pipeline ingest the file as an ordinary document, so test history
|
|
6
|
+
* becomes searchable, and what lets the report be mailed or archived and
|
|
7
|
+
* still render years later.
|
|
8
|
+
*
|
|
9
|
+
* Reading order matches how you triage: verdict, errors, failed requests,
|
|
10
|
+
* vitals, accessibility, screenshots.
|
|
11
|
+
*/
|
|
12
|
+
import type { FlakeReport } from './flake.js';
|
|
13
|
+
import type { Report } from './types.js';
|
|
14
|
+
import { escapeHtml } from './util.js';
|
|
15
|
+
export { escapeHtml };
|
|
16
|
+
export interface RenderOptions {
|
|
17
|
+
/** Present when the report came from `--repeat` (RIG-14). */
|
|
18
|
+
flake?: FlakeReport;
|
|
19
|
+
}
|
|
20
|
+
export declare function renderHtml(report: Report, options?: RenderOptions): string;
|
|
21
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/report/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,OAAO,KAAK,EAAe,MAAM,EAA4B,MAAM,YAAY,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,CAAC;AA6OtB,MAAM,WAAW,aAAa;IAC5B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAoD9E"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders a Report as ONE self-contained HTML file: CSS inline, screenshots
|
|
3
|
+
* as `data:` URIs, no fonts, no CDN, no network access of any kind at view
|
|
4
|
+
* time. That is not a stylistic preference — it is what lets monomind's
|
|
5
|
+
* document pipeline ingest the file as an ordinary document, so test history
|
|
6
|
+
* becomes searchable, and what lets the report be mailed or archived and
|
|
7
|
+
* still render years later.
|
|
8
|
+
*
|
|
9
|
+
* Reading order matches how you triage: verdict, errors, failed requests,
|
|
10
|
+
* vitals, accessibility, screenshots.
|
|
11
|
+
*/
|
|
12
|
+
import { budgetLabel } from './budget.js';
|
|
13
|
+
import { EVIDENCE_STYLES, renderEvidence, renderFlake } from './render-evidence.js';
|
|
14
|
+
import { renderDiff, renderTrend, TREND_STYLES } from './render-trend.js';
|
|
15
|
+
import { escapeHtml } from './util.js';
|
|
16
|
+
export { escapeHtml };
|
|
17
|
+
function ms(value) {
|
|
18
|
+
return value === undefined || !Number.isFinite(value) ? 'not measured' : `${Math.round(value)}ms`;
|
|
19
|
+
}
|
|
20
|
+
function vitalRating(metric, v) {
|
|
21
|
+
if (v === undefined || !Number.isFinite(v))
|
|
22
|
+
return 'none';
|
|
23
|
+
const scale = {
|
|
24
|
+
lcp: [2500, 4000],
|
|
25
|
+
fcp: [1800, 3000],
|
|
26
|
+
cls: [0.1, 0.25],
|
|
27
|
+
inp: [200, 500],
|
|
28
|
+
ttfb: [800, 1800],
|
|
29
|
+
};
|
|
30
|
+
const bounds = scale[metric];
|
|
31
|
+
if (!bounds)
|
|
32
|
+
return 'none';
|
|
33
|
+
return v <= bounds[0] ? 'good' : v <= bounds[1] ? 'mixed' : 'poor';
|
|
34
|
+
}
|
|
35
|
+
const STYLES = `
|
|
36
|
+
:root{
|
|
37
|
+
--bg:#fbfbfd; --panel:#fff; --ink:#15171c; --muted:#5d6470; --line:#e3e6ec;
|
|
38
|
+
--pass:#0f7b4f; --pass-bg:#e7f6ee; --fail:#b3261e; --fail-bg:#fdeceb;
|
|
39
|
+
--warn:#8a5a00; --warn-bg:#fff5e0; --code:#f3f4f7;
|
|
40
|
+
}
|
|
41
|
+
@media (prefers-color-scheme: dark){
|
|
42
|
+
:root{
|
|
43
|
+
--bg:#101317; --panel:#171b21; --ink:#e7eaf0; --muted:#98a1b0; --line:#262c35;
|
|
44
|
+
--pass:#57d69c; --pass-bg:#11291f; --fail:#ff9a92; --fail-bg:#2c1614;
|
|
45
|
+
--warn:#f0c168; --warn-bg:#2b2113; --code:#1d222a;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
*{box-sizing:border-box}
|
|
49
|
+
body{margin:0;padding:32px 16px 72px;background:var(--bg);color:var(--ink);
|
|
50
|
+
font:15px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;}
|
|
51
|
+
main{max-width:940px;margin:0 auto}
|
|
52
|
+
h1{font-size:22px;margin:0 0 4px;letter-spacing:-.01em}
|
|
53
|
+
h2{font-size:15px;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);
|
|
54
|
+
margin:36px 0 12px;font-weight:600}
|
|
55
|
+
a{color:inherit}
|
|
56
|
+
.sub{color:var(--muted);font-size:13px;margin:0 0 24px;word-break:break-all}
|
|
57
|
+
.verdict{border-radius:12px;padding:18px 20px;margin-bottom:8px;border:1px solid transparent}
|
|
58
|
+
.verdict.pass{background:var(--pass-bg);border-color:var(--pass);color:var(--pass)}
|
|
59
|
+
.verdict.fail{background:var(--fail-bg);border-color:var(--fail);color:var(--fail)}
|
|
60
|
+
.verdict .tag{font-size:26px;font-weight:700;letter-spacing:.02em}
|
|
61
|
+
.verdict .line{color:var(--ink);margin-top:6px;font-size:14px}
|
|
62
|
+
.stats{display:flex;flex-wrap:wrap;gap:8px;margin:16px 0 0;padding:0;list-style:none}
|
|
63
|
+
.stats li{background:var(--panel);border:1px solid var(--line);border-radius:8px;
|
|
64
|
+
padding:8px 12px;font-size:13px;color:var(--muted)}
|
|
65
|
+
.stats li b{display:block;font-size:18px;color:var(--ink)}
|
|
66
|
+
.stats li.bad b{color:var(--fail)}
|
|
67
|
+
table{width:100%;border-collapse:collapse;background:var(--panel);
|
|
68
|
+
border:1px solid var(--line);border-radius:10px;overflow:hidden;font-size:13px}
|
|
69
|
+
th,td{text-align:left;padding:9px 12px;border-bottom:1px solid var(--line);vertical-align:top}
|
|
70
|
+
th{color:var(--muted);font-weight:600;white-space:nowrap}
|
|
71
|
+
tr:last-child td{border-bottom:none}
|
|
72
|
+
td.num{text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums}
|
|
73
|
+
.wrap{word-break:break-all}
|
|
74
|
+
code,.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px}
|
|
75
|
+
code{background:var(--code);padding:1px 5px;border-radius:4px}
|
|
76
|
+
.pill{display:inline-block;padding:1px 7px;border-radius:999px;font-size:11px;
|
|
77
|
+
font-weight:600;text-transform:uppercase;letter-spacing:.04em}
|
|
78
|
+
.pill.error{background:var(--fail-bg);color:var(--fail)}
|
|
79
|
+
.pill.warning{background:var(--warn-bg);color:var(--warn)}
|
|
80
|
+
.pill.good{background:var(--pass-bg);color:var(--pass)}
|
|
81
|
+
.pill.mixed{background:var(--warn-bg);color:var(--warn)}
|
|
82
|
+
.pill.poor{background:var(--fail-bg);color:var(--fail)}
|
|
83
|
+
.pill.none{background:var(--code);color:var(--muted)}
|
|
84
|
+
.empty{color:var(--muted);font-size:13px;background:var(--panel);border:1px solid var(--line);
|
|
85
|
+
border-radius:10px;padding:12px}
|
|
86
|
+
.note{color:var(--muted);font-size:12px;margin-top:8px}
|
|
87
|
+
figure{margin:0 0 20px}
|
|
88
|
+
figcaption{color:var(--muted);font-size:12px;margin-bottom:6px}
|
|
89
|
+
img{max-width:100%;height:auto;display:block;border:1px solid var(--line);border-radius:10px}
|
|
90
|
+
footer{margin-top:40px;color:var(--muted);font-size:12px;border-top:1px solid var(--line);
|
|
91
|
+
padding-top:12px}
|
|
92
|
+
@media (max-width:640px){body{padding:20px 12px 48px}th,td{padding:8px}}
|
|
93
|
+
`.trim();
|
|
94
|
+
function emptyBlock(text) {
|
|
95
|
+
return `<p class="empty">${escapeHtml(text)}</p>`;
|
|
96
|
+
}
|
|
97
|
+
function renderVerdict(report) {
|
|
98
|
+
const pass = report.verdict === 'pass';
|
|
99
|
+
const headline = pass
|
|
100
|
+
? 'All budgets met.'
|
|
101
|
+
: `${report.failures.length} budget ${report.failures.length === 1 ? 'failure' : 'failures'}.`;
|
|
102
|
+
const rows = report.failures
|
|
103
|
+
.map((f) => `<tr>
|
|
104
|
+
<td>${escapeHtml(budgetLabel(f.budget))}</td>
|
|
105
|
+
<td class="num mono">${escapeHtml(f.expected)}</td>
|
|
106
|
+
<td class="num mono">${escapeHtml(f.actual)}</td>
|
|
107
|
+
<td class="wrap">${escapeHtml(f.detail ?? '')}</td>
|
|
108
|
+
</tr>`)
|
|
109
|
+
.join('');
|
|
110
|
+
const table = report.failures.length
|
|
111
|
+
? `<table><thead><tr><th>Budget</th><th>Expected</th><th>Actual</th><th>Evidence</th></tr></thead>
|
|
112
|
+
<tbody>${rows}</tbody></table>`
|
|
113
|
+
: '';
|
|
114
|
+
const unmeasured = report.unmeasured.length
|
|
115
|
+
? `<p class="note">Not measured on this run: ${escapeHtml(report.unmeasured.join(', '))} — the page never reported the metric, so its budget was neither met nor breached.</p>`
|
|
116
|
+
: '';
|
|
117
|
+
return `<section class="verdict ${pass ? 'pass' : 'fail'}">
|
|
118
|
+
<div class="tag">${pass ? 'PASS' : 'FAIL'}</div>
|
|
119
|
+
<div class="line">${escapeHtml(headline)}</div>
|
|
120
|
+
</section>
|
|
121
|
+
${table}
|
|
122
|
+
${unmeasured}`;
|
|
123
|
+
}
|
|
124
|
+
function renderStats(report) {
|
|
125
|
+
const c = report.counts;
|
|
126
|
+
const item = (label, value, bad) => `<li class="${bad ? 'bad' : ''}"><b>${value}</b>${escapeHtml(label)}</li>`;
|
|
127
|
+
return `<ul class="stats">
|
|
128
|
+
${item('console errors', c.consoleErrors, c.consoleErrors > 0)}
|
|
129
|
+
${item('page errors', c.pageErrors, c.pageErrors > 0)}
|
|
130
|
+
${item('failed requests', c.failedRequests, c.failedRequests > 0)}
|
|
131
|
+
${item('requests', c.requests, false)}
|
|
132
|
+
${item('a11y errors', c.a11yErrors, c.a11yErrors > 0)}
|
|
133
|
+
${item('a11y warnings', c.a11yWarnings, false)}
|
|
134
|
+
</ul>`;
|
|
135
|
+
}
|
|
136
|
+
function renderErrors(report) {
|
|
137
|
+
const rows = [];
|
|
138
|
+
for (const e of report.pageErrors) {
|
|
139
|
+
const where = e.url ? `${e.url}${e.lineNumber !== undefined ? `:${e.lineNumber}` : ''}` : '';
|
|
140
|
+
rows.push(`<tr>
|
|
141
|
+
<td><span class="pill error">uncaught</span></td>
|
|
142
|
+
<td class="wrap">${escapeHtml(e.text)}</td>
|
|
143
|
+
<td class="wrap mono">${escapeHtml(where)}</td>
|
|
144
|
+
</tr>`);
|
|
145
|
+
}
|
|
146
|
+
for (const m of report.console) {
|
|
147
|
+
if (m.type !== 'error' && m.type !== 'warn' && m.type !== 'warning')
|
|
148
|
+
continue;
|
|
149
|
+
const pill = m.type === 'error' ? 'error' : 'warning';
|
|
150
|
+
const where = m.url ? `${m.url}${m.lineNumber !== undefined ? `:${m.lineNumber}` : ''}` : '';
|
|
151
|
+
rows.push(`<tr>
|
|
152
|
+
<td><span class="pill ${pill}">console.${escapeHtml(m.type)}</span></td>
|
|
153
|
+
<td class="wrap">${escapeHtml(m.text)}</td>
|
|
154
|
+
<td class="wrap mono">${escapeHtml(where)}</td>
|
|
155
|
+
</tr>`);
|
|
156
|
+
}
|
|
157
|
+
if (!rows.length)
|
|
158
|
+
return emptyBlock('No console errors, warnings or uncaught exceptions.');
|
|
159
|
+
return `<table><thead><tr><th>Kind</th><th>Message</th><th>Source</th></tr></thead>
|
|
160
|
+
<tbody>${rows.join('')}</tbody></table>`;
|
|
161
|
+
}
|
|
162
|
+
function renderRequests(requests) {
|
|
163
|
+
const failed = requests.filter((r) => r.failed);
|
|
164
|
+
if (!failed.length)
|
|
165
|
+
return emptyBlock('Every request returned a successful response.');
|
|
166
|
+
const rows = failed
|
|
167
|
+
.map((r) => `<tr>
|
|
168
|
+
<td class="mono">${escapeHtml(r.status ?? '—')}</td>
|
|
169
|
+
<td class="mono">${escapeHtml(r.method)}</td>
|
|
170
|
+
<td class="wrap mono">${escapeHtml(r.url)}</td>
|
|
171
|
+
<td class="wrap">${escapeHtml(r.errorText ?? '')}</td>
|
|
172
|
+
</tr>`)
|
|
173
|
+
.join('');
|
|
174
|
+
return `<table><thead><tr><th>Status</th><th>Method</th><th>URL</th><th>Error</th></tr></thead>
|
|
175
|
+
<tbody>${rows}</tbody></table>`;
|
|
176
|
+
}
|
|
177
|
+
function renderVitals(report) {
|
|
178
|
+
const v = report.vitals;
|
|
179
|
+
const defs = [
|
|
180
|
+
['lcp', 'LCP', 'Largest Contentful Paint'],
|
|
181
|
+
['fcp', 'FCP', 'First Contentful Paint'],
|
|
182
|
+
['cls', 'CLS', 'Cumulative Layout Shift'],
|
|
183
|
+
['inp', 'INP', 'Interaction to Next Paint'],
|
|
184
|
+
['ttfb', 'TTFB', 'Time to First Byte'],
|
|
185
|
+
];
|
|
186
|
+
const rows = defs
|
|
187
|
+
.map(([key, short, long]) => {
|
|
188
|
+
const raw = v[key];
|
|
189
|
+
const rating = vitalRating(key, raw);
|
|
190
|
+
const shown = key === 'cls' ? (raw === undefined ? 'not measured' : raw.toFixed(3)) : ms(raw);
|
|
191
|
+
return `<tr>
|
|
192
|
+
<td><b>${short}</b> <span style="color:var(--muted)">${escapeHtml(long)}</span></td>
|
|
193
|
+
<td class="num mono">${escapeHtml(shown)}</td>
|
|
194
|
+
<td><span class="pill ${rating}">${rating === 'none' ? 'n/a' : rating}</span></td>
|
|
195
|
+
</tr>`;
|
|
196
|
+
})
|
|
197
|
+
.join('');
|
|
198
|
+
const load = `<tr><td>Load event</td><td class="num mono">${escapeHtml(ms(v.loadTime))}</td><td></td></tr>
|
|
199
|
+
<tr><td>DOM interactive</td><td class="num mono">${escapeHtml(ms(v.domInteractive))}</td><td></td></tr>
|
|
200
|
+
<tr><td>Resources</td><td class="num mono">${escapeHtml(v.resources ?? '—')}</td><td></td></tr>`;
|
|
201
|
+
return `<table><thead><tr><th>Metric</th><th>Value</th><th>Rating</th></tr></thead>
|
|
202
|
+
<tbody>${rows}${load}</tbody></table>`;
|
|
203
|
+
}
|
|
204
|
+
function renderA11y(findings) {
|
|
205
|
+
const disclaimer = '<p class="note">Colour contrast is not evaluated: it cannot be derived from the accessibility tree, and guessing it would be worse than omitting it.</p>';
|
|
206
|
+
if (!findings.length) {
|
|
207
|
+
return `${emptyBlock('No accessibility findings from the AX tree.')}${disclaimer}`;
|
|
208
|
+
}
|
|
209
|
+
const order = { error: 0, warning: 1 };
|
|
210
|
+
const rows = [...findings]
|
|
211
|
+
.sort((a, b) => order[a.impact] - order[b.impact])
|
|
212
|
+
.map((f) => `<tr>
|
|
213
|
+
<td><span class="pill ${f.impact}">${escapeHtml(f.impact)}</span></td>
|
|
214
|
+
<td class="mono">${escapeHtml(f.rule)}</td>
|
|
215
|
+
<td>${escapeHtml(f.role)}</td>
|
|
216
|
+
<td>${f.name ? escapeHtml(f.name) : '<span style="color:var(--muted)">(no accessible name)</span>'}</td>
|
|
217
|
+
<td class="wrap mono">${escapeHtml(f.locator)}</td>
|
|
218
|
+
<td class="wrap">${escapeHtml(f.detail)}</td>
|
|
219
|
+
</tr>`)
|
|
220
|
+
.join('');
|
|
221
|
+
return `<table><thead><tr><th>Impact</th><th>Rule</th><th>Role</th><th>Name</th><th>Locator</th><th>Detail</th></tr></thead>
|
|
222
|
+
<tbody>${rows}</tbody></table>${disclaimer}`;
|
|
223
|
+
}
|
|
224
|
+
function renderScreenshots(shots) {
|
|
225
|
+
if (!shots.length)
|
|
226
|
+
return emptyBlock('No screenshot was captured.');
|
|
227
|
+
return shots
|
|
228
|
+
.map((s) => `<figure>
|
|
229
|
+
<figcaption>${escapeHtml(s.label)} — ${s.width}×${s.height}</figcaption>
|
|
230
|
+
<img alt="${escapeHtml(`${s.label} screenshot`)}" src="${escapeHtml(s.dataUrl)}">
|
|
231
|
+
</figure>`)
|
|
232
|
+
.join('');
|
|
233
|
+
}
|
|
234
|
+
export function renderHtml(report, options = {}) {
|
|
235
|
+
const title = report.title || report.finalUrl || report.url;
|
|
236
|
+
const notes = report.notes.length
|
|
237
|
+
? `<h2>Run notes</h2><ul class="empty">${report.notes.map((n) => `<li>${escapeHtml(n)}</li>`).join('')}</ul>`
|
|
238
|
+
: '';
|
|
239
|
+
return `<!doctype html>
|
|
240
|
+
<html lang="en">
|
|
241
|
+
<head>
|
|
242
|
+
<meta charset="utf-8">
|
|
243
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
244
|
+
<meta name="color-scheme" content="light dark">
|
|
245
|
+
<title>${escapeHtml(`Page report — ${title}`)}</title>
|
|
246
|
+
<style>${STYLES}
|
|
247
|
+
${TREND_STYLES}
|
|
248
|
+
${EVIDENCE_STYLES}</style>
|
|
249
|
+
</head>
|
|
250
|
+
<body>
|
|
251
|
+
<main>
|
|
252
|
+
<h1>${escapeHtml(title)}</h1>
|
|
253
|
+
<p class="sub">${escapeHtml(report.finalUrl || report.url)} · captured ${escapeHtml(report.capturedAt)} · ${Math.round(report.durationMs)}ms</p>
|
|
254
|
+
|
|
255
|
+
${renderVerdict(report)}
|
|
256
|
+
${renderFlake(options.flake)}
|
|
257
|
+
${renderStats(report)}
|
|
258
|
+
|
|
259
|
+
${renderTrend(report.trend)}
|
|
260
|
+
${renderDiff(report.diff)}
|
|
261
|
+
|
|
262
|
+
<h2>Errors</h2>
|
|
263
|
+
${renderErrors(report)}
|
|
264
|
+
|
|
265
|
+
${renderEvidence(report.evidence)}
|
|
266
|
+
|
|
267
|
+
<h2>Failed requests</h2>
|
|
268
|
+
${renderRequests(report.requests)}
|
|
269
|
+
|
|
270
|
+
<h2>Web vitals</h2>
|
|
271
|
+
${renderVitals(report)}
|
|
272
|
+
|
|
273
|
+
<h2>Accessibility</h2>
|
|
274
|
+
${renderA11y(report.a11y)}
|
|
275
|
+
|
|
276
|
+
<h2>Screenshots</h2>
|
|
277
|
+
${renderScreenshots(report.screenshots)}
|
|
278
|
+
|
|
279
|
+
${notes}
|
|
280
|
+
<footer>Generated by monobrowse report — self-contained, no external resources.</footer>
|
|
281
|
+
</main>
|
|
282
|
+
</body>
|
|
283
|
+
</html>
|
|
284
|
+
`;
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/report/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE1E,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,SAAS,EAAE,CAAC,KAAc;IACxB,OAAO,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;AACpG,CAAC;AAED,SAAS,WAAW,CAAC,MAAc,EAAE,CAAU;IAC7C,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC1D,MAAM,KAAK,GAAqC;QAC9C,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACjB,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACjB,GAAG,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC;QAChB,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;QACf,IAAI,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC;KAClB,CAAC;IACF,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7B,IAAI,CAAC,MAAM;QAAE,OAAO,MAAM,CAAC;IAC3B,OAAO,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AACrE,CAAC;AAED,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Dd,CAAC,IAAI,EAAE,CAAC;AAET,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,oBAAoB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;AACpD,CAAC;AAED,SAAS,aAAa,CAAC,MAAc;IACnC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI;QACnB,CAAC,CAAC,kBAAkB;QACpB,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,WAAW,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC;IACjG,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ;SACzB,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;cACC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;+BAChB,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;+BACtB,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;2BACxB,UAAU,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC;YACzC,CACP;SACA,IAAI,CAAC,EAAE,CAAC,CAAC;IAEZ,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM;QAClC,CAAC,CAAC;gBACU,IAAI,kBAAkB;QAClC,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM;QACzC,CAAC,CAAC,6CAA6C,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,wFAAwF;QAC/K,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,2BAA2B,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;uBACnC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;wBACrB,UAAU,CAAC,QAAQ,CAAC;;IAExC,KAAK;IACL,UAAU,EAAE,CAAC;AACjB,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,KAAa,EAAE,GAAY,EAAE,EAAE,CAC1D,cAAc,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,KAAK,OAAO,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC;IAC7E,OAAO;MACH,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC;MAC5D,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;MACnD,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC;MAC/D,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC;MACnC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;MACnD,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,YAAY,EAAE,KAAK,CAAC;QAC1C,CAAC;AACT,CAAC;AAED,SAAS,YAAY,CAAC,MAAc;IAClC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7F,IAAI,CAAC,IAAI,CAAC;;yBAEW,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;8BACb,UAAU,CAAC,KAAK,CAAC;UACrC,CAAC,CAAC;IACV,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAC/B,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;YAAE,SAAS;QAC9E,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QACtD,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7F,IAAI,CAAC,IAAI,CAAC;8BACgB,IAAI,aAAa,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;yBACxC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;8BACb,UAAU,CAAC,KAAK,CAAC;UACrC,CAAC,CAAC;IACV,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,UAAU,CAAC,qDAAqD,CAAC,CAAC;IAC3F,OAAO;aACI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC;AAC7C,CAAC;AAED,SAAS,cAAc,CAAC,QAAwB;IAC9C,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,UAAU,CAAC,+CAA+C,CAAC,CAAC;IACvF,MAAM,IAAI,GAAG,MAAM;SAChB,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;yBACY,UAAU,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC;yBAC3B,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;8BACf,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC;yBACtB,UAAU,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC;UAC5C,CACL;SACA,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO;aACI,IAAI,kBAAkB,CAAC;AACpC,CAAC;AAED,SAAS,YAAY,CAAC,MAAc;IAClC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,MAAM,IAAI,GAAoC;QAC5C,CAAC,KAAK,EAAE,KAAK,EAAE,0BAA0B,CAAC;QAC1C,CAAC,KAAK,EAAE,KAAK,EAAE,wBAAwB,CAAC;QACxC,CAAC,KAAK,EAAE,KAAK,EAAE,yBAAyB,CAAC;QACzC,CAAC,KAAK,EAAE,KAAK,EAAE,2BAA2B,CAAC;QAC3C,CAAC,MAAM,EAAE,MAAM,EAAE,oBAAoB,CAAC;KACvC,CAAC;IACF,MAAM,IAAI,GAAG,IAAI;SACd,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;QAC1B,MAAM,GAAG,GAAG,CAAC,CAAC,GAAqB,CAAuB,CAAC;QAC3D,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;QAC9F,OAAO;iBACI,KAAK,yCAAyC,UAAU,CAAC,IAAI,CAAC;+BAChD,UAAU,CAAC,KAAK,CAAC;gCAChB,MAAM,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;YACjE,CAAC;IACT,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,MAAM,IAAI,GAAG,+CAA+C,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;uDACjC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;iDACtC,UAAU,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,qBAAqB,CAAC;IACnG,OAAO;aACI,IAAI,GAAG,IAAI,kBAAkB,CAAC;AAC3C,CAAC;AAED,SAAS,UAAU,CAAC,QAAuB;IACzC,MAAM,UAAU,GACd,0JAA0J,CAAC;IAC7J,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrB,OAAO,GAAG,UAAU,CAAC,6CAA6C,CAAC,GAAG,UAAU,EAAE,CAAC;IACrF,CAAC;IACD,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAW,CAAC;IAChD,MAAM,IAAI,GAAG,CAAC,GAAG,QAAQ,CAAC;SACvB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;SACjD,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;8BACiB,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;yBACtC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;YAC/B,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;YAClB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,8DAA8D;8BAC1E,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC;yBAC1B,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;UACnC,CACL;SACA,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO;aACI,IAAI,mBAAmB,UAAU,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAmB;IAC5C,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,UAAU,CAAC,6BAA6B,CAAC,CAAC;IACpE,OAAO,KAAK;SACT,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;oBACO,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM;kBAC9C,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,aAAa,CAAC,UAAU,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC;cACtE,CACT;SACA,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAOD,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,OAAO,GAAkB,EAAE;IACpE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,GAAG,CAAC;IAC5D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;QAC/B,CAAC,CAAC,uCAAuC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO;QAC7G,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;;;;;;SAMA,UAAU,CAAC,iBAAiB,KAAK,EAAE,CAAC;SACpC,MAAM;EACb,YAAY;EACZ,eAAe;;;;MAIX,UAAU,CAAC,KAAK,CAAC;iBACN,UAAU,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,GAAG,CAAC,eAAe,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC;;EAEvI,aAAa,CAAC,MAAM,CAAC;EACrB,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;EAC1B,WAAW,CAAC,MAAM,CAAC;;EAEnB,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC;EACzB,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;;;EAGvB,YAAY,CAAC,MAAM,CAAC;;EAEpB,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC;;;EAG/B,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC;;;EAG/B,YAAY,CAAC,MAAM,CAAC;;;EAGpB,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;;;EAGvB,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC;;EAErC,KAAK;;;;;CAKN,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assembles the run-to-run diff (RIG-10) from what the previous run left in
|
|
3
|
+
* the history directory: its structural signature (in the JSON record) and
|
|
4
|
+
* its screenshot (the sibling PNG).
|
|
5
|
+
*
|
|
6
|
+
* Every missing piece degrades into a note rather than an absent section, so
|
|
7
|
+
* a reader can tell "nothing changed" apart from "we could not check".
|
|
8
|
+
*/
|
|
9
|
+
import { type HistoryRun } from './history.js';
|
|
10
|
+
import { type PixelDiffOptions } from './pixel-diff.js';
|
|
11
|
+
import type { Report, RunDiff } from './types.js';
|
|
12
|
+
export interface BuildRunDiffOptions {
|
|
13
|
+
pixels?: PixelDiffOptions;
|
|
14
|
+
/** Set false to skip the pixel half entirely. */
|
|
15
|
+
comparePixels?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function buildRunDiff(dir: string, previous: HistoryRun | undefined, current: Report, options?: BuildRunDiffOptions): Promise<RunDiff | undefined>;
|
|
18
|
+
//# sourceMappingURL=run-diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-diff.d.ts","sourceRoot":"","sources":["../../../src/report/run-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,KAAK,gBAAgB,EAAa,MAAM,iBAAiB,CAAC;AAGnE,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,iDAAiD;IACjD,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,UAAU,GAAG,SAAS,EAChC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAoC9B"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assembles the run-to-run diff (RIG-10) from what the previous run left in
|
|
3
|
+
* the history directory: its structural signature (in the JSON record) and
|
|
4
|
+
* its screenshot (the sibling PNG).
|
|
5
|
+
*
|
|
6
|
+
* Every missing piece degrades into a note rather than an absent section, so
|
|
7
|
+
* a reader can tell "nothing changed" apart from "we could not check".
|
|
8
|
+
*/
|
|
9
|
+
import { loadRunScreenshot } from './history.js';
|
|
10
|
+
import { pixelDiff } from './pixel-diff.js';
|
|
11
|
+
import { pngFromDataUrl } from './png.js';
|
|
12
|
+
import { diffStructure } from './structure.js';
|
|
13
|
+
export async function buildRunDiff(dir, previous, current, options = {}) {
|
|
14
|
+
if (!previous)
|
|
15
|
+
return undefined;
|
|
16
|
+
const notes = [];
|
|
17
|
+
const diff = {
|
|
18
|
+
previousRunId: previous.id,
|
|
19
|
+
previousCapturedAt: previous.capturedAt,
|
|
20
|
+
notes,
|
|
21
|
+
};
|
|
22
|
+
if (previous.structure?.length && current.structure?.length) {
|
|
23
|
+
diff.structure = diffStructure(previous.structure, current.structure);
|
|
24
|
+
}
|
|
25
|
+
else if (!current.structure?.length) {
|
|
26
|
+
notes.push('No accessibility tree this run — structural diff skipped.');
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
notes.push('The previous run stored no structural signature — nothing to diff against.');
|
|
30
|
+
}
|
|
31
|
+
if (options.comparePixels !== false) {
|
|
32
|
+
const currentShot = current.screenshots.find((s) => s.label === 'page') ?? current.screenshots[0];
|
|
33
|
+
const previousPng = await loadRunScreenshot(dir, previous);
|
|
34
|
+
if (!previousPng) {
|
|
35
|
+
notes.push('The previous run archived no screenshot — pixel diff skipped.');
|
|
36
|
+
}
|
|
37
|
+
else if (!currentShot?.dataUrl) {
|
|
38
|
+
notes.push('No screenshot this run — pixel diff skipped.');
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
try {
|
|
42
|
+
diff.pixels = pixelDiff(previousPng, pngFromDataUrl(currentShot.dataUrl), options.pixels);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
notes.push(`Pixel diff failed: ${err.message}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return diff;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=run-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-diff.js","sourceRoot":"","sources":["../../../src/report/run-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAmB,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAyB,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAS/C,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAW,EACX,QAAgC,EAChC,OAAe,EACf,OAAO,GAAwB,EAAE;IAEjC,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEhC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAY;QACpB,aAAa,EAAE,QAAQ,CAAC,EAAE;QAC1B,kBAAkB,EAAE,QAAQ,CAAC,UAAU;QACvC,KAAK;KACN,CAAC;IAEF,IAAI,QAAQ,CAAC,SAAS,EAAE,MAAM,IAAI,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;QAC5D,IAAI,CAAC,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACxE,CAAC;SAAM,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;IAC1E,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;IAC3F,CAAC;IAED,IAAI,OAAO,CAAC,aAAa,KAAK,KAAK,EAAE,CAAC;QACpC,MAAM,WAAW,GACf,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAChF,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC3D,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;QAC9E,CAAC;aAAM,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,IAAI,CAAC;gBACH,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,WAAW,EAAE,cAAc,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAC5F,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,sBAAuB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|