happo 6.2.6 → 6.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/browser/main.js +10 -13
  2. package/dist/browser/main.js.map +2 -2
  3. package/dist/browser/takeDOMSnapshot.d.ts.map +1 -1
  4. package/dist/cli/cancelJob-6YMRZKZ6.js +10 -0
  5. package/dist/cli/{chunk-2GWYMCM5.js → chunk-AQSWKKBJ.js} +15 -11
  6. package/dist/cli/chunk-AQSWKKBJ.js.map +7 -0
  7. package/dist/cli/{chunk-UBNAHFZ5.js → chunk-H4SN6WPV.js} +2 -2
  8. package/dist/cli/{chunk-4SMOBHQY.js → chunk-HAOW7OPC.js} +2 -2
  9. package/dist/cli/{chunk-Q3DT6FIT.js → chunk-VGC6VLFX.js} +4 -4
  10. package/dist/cli/{chunk-Q3DT6FIT.js.map → chunk-VGC6VLFX.js.map} +1 -1
  11. package/dist/cli/{chunk-HFWMNEW7.js → chunk-VRKXLPSQ.js} +3 -3
  12. package/dist/cli/{chunk-56XY3V7T.js → chunk-WFRUGXXQ.js} +2 -2
  13. package/dist/cli/createAsyncComparison-O4TTQSO6.js +10 -0
  14. package/dist/cli/{createAsyncReport-EAFZGNCW.js → createAsyncReport-5E3IWVZX.js} +4 -4
  15. package/dist/cli/getFlakes-ITQLVM5D.js +73 -0
  16. package/dist/cli/getFlakes-ITQLVM5D.js.map +7 -0
  17. package/dist/cli/index.d.ts.map +1 -1
  18. package/dist/cli/main.js +186 -11
  19. package/dist/cli/main.js.map +2 -2
  20. package/dist/cli/package-BZTLWVDW.js +7 -0
  21. package/dist/cli/{prepareSnapRequests-FQJAOJNF.js → prepareSnapRequests-O2FC3E2P.js} +4 -4
  22. package/dist/cli/startJob-5JOX4R4S.js +10 -0
  23. package/dist/cli/telemetry.d.ts.map +1 -1
  24. package/dist/cli/{wrapper-LPL52GIF.js → wrapper-ZQOATRO2.js} +7 -7
  25. package/dist/config/index.d.ts +43 -0
  26. package/dist/config/index.d.ts.map +1 -1
  27. package/dist/config/index.js.map +2 -2
  28. package/dist/config/loadConfig.d.ts.map +1 -1
  29. package/dist/cypress/index.js +12 -14
  30. package/dist/cypress/index.js.map +3 -3
  31. package/dist/cypress/task.js +47 -3
  32. package/dist/cypress/task.js.map +2 -2
  33. package/dist/network/createAsyncComparison.d.ts.map +1 -1
  34. package/dist/network/getFlakes.d.ts +39 -0
  35. package/dist/network/getFlakes.d.ts.map +1 -0
  36. package/dist/playwright/index.js +47 -3
  37. package/dist/playwright/index.js.map +2 -2
  38. package/package.json +3 -3
  39. package/dist/cli/cancelJob-JVBWGU62.js +0 -10
  40. package/dist/cli/chunk-2GWYMCM5.js.map +0 -7
  41. package/dist/cli/createAsyncComparison-IVFALQTJ.js +0 -10
  42. package/dist/cli/package-LZDJBDUK.js +0 -7
  43. package/dist/cli/startJob-ZYTK6OMK.js +0 -10
  44. /package/dist/cli/{cancelJob-JVBWGU62.js.map → cancelJob-6YMRZKZ6.js.map} +0 -0
  45. /package/dist/cli/{chunk-UBNAHFZ5.js.map → chunk-H4SN6WPV.js.map} +0 -0
  46. /package/dist/cli/{chunk-4SMOBHQY.js.map → chunk-HAOW7OPC.js.map} +0 -0
  47. /package/dist/cli/{chunk-HFWMNEW7.js.map → chunk-VRKXLPSQ.js.map} +0 -0
  48. /package/dist/cli/{chunk-56XY3V7T.js.map → chunk-WFRUGXXQ.js.map} +0 -0
  49. /package/dist/cli/{createAsyncComparison-IVFALQTJ.js.map → createAsyncComparison-O4TTQSO6.js.map} +0 -0
  50. /package/dist/cli/{createAsyncReport-EAFZGNCW.js.map → createAsyncReport-5E3IWVZX.js.map} +0 -0
  51. /package/dist/cli/{package-LZDJBDUK.js.map → package-BZTLWVDW.js.map} +0 -0
  52. /package/dist/cli/{prepareSnapRequests-FQJAOJNF.js.map → prepareSnapRequests-O2FC3E2P.js.map} +0 -0
  53. /package/dist/cli/{startJob-ZYTK6OMK.js.map → startJob-5JOX4R4S.js.map} +0 -0
  54. /package/dist/cli/{wrapper-LPL52GIF.js.map → wrapper-ZQOATRO2.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../package.json"],
4
- "sourcesContent": ["{\n \"name\": \"happo\",\n \"version\": \"6.2.6\",\n \"description\": \"Catch unexpected visual and accessibility changes and UI bugs\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/happo/happo.git\"\n },\n \"bugs\": \"https://github.com/happo/happo/issues\",\n \"homepage\": \"https://happo.io\",\n \"bin\": {\n \"happo\": \"dist/cli/main.js\"\n },\n \"type\": \"module\",\n \"main\": \"./dist/config/index.js\",\n \"types\": \"./dist/config/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/config/index.d.ts\",\n \"default\": \"./dist/config/index.js\"\n },\n \"./cypress\": {\n \"types\": \"./dist/cypress/index.d.ts\",\n \"default\": \"./dist/cypress/index.js\"\n },\n \"./cypress/task\": {\n \"types\": \"./dist/cypress/task.d.ts\",\n \"default\": \"./dist/cypress/task.js\"\n },\n \"./playwright\": {\n \"types\": \"./dist/playwright/index.d.ts\",\n \"default\": \"./dist/playwright/index.js\"\n },\n \"./custom\": {\n \"types\": \"./dist/custom/index.d.ts\",\n \"default\": \"./dist/custom/index.js\"\n },\n \"./storybook/addon\": {\n \"types\": \"./dist/storybook/browser/addon.d.ts\",\n \"default\": \"./dist/storybook/browser/addon.js\"\n },\n \"./storybook/decorator\": {\n \"types\": \"./dist/storybook/browser/decorator.d.ts\",\n \"default\": \"./dist/storybook/browser/decorator.js\"\n },\n \"./storybook/preset\": {\n \"types\": \"./dist/storybook/preset.d.ts\",\n \"default\": \"./dist/storybook/preset.js\"\n },\n \"./storybook/register\": {\n \"types\": \"./dist/storybook/browser/register.d.ts\",\n \"default\": \"./dist/storybook/browser/register.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"preset.js\"\n ],\n \"scripts\": {\n \"all\": \"node ./scripts/allchecks.ts\",\n \"build\": \"pnpm build:types && pnpm build:dist\",\n \"build:custom\": \"esbuild src/custom/__happo__/index.ts --bundle --format=iife --global-name=happoCustom --outfile=tmp/happo-custom/bundle.js --platform=browser --target=esnext\",\n \"build:dist\": \"./scripts/build.ts\",\n \"build:types\": \"pnpm tsc --pretty\",\n \"build:watch\": \"tsc --build --watch\",\n \"clean\": \"rm -rf dist tmp/tsc tmp/happo-custom\",\n \"lint\": \"eslint .\",\n \"prepublishOnly\": \"pnpm clean && pnpm build\",\n \"storybook:dev\": \"storybook dev --config-dir src/storybook/__tests__/storybook-app -p ${PORT:-6007}\",\n \"test\": \"node --env-file-if-exists=.env.local ./scripts/test.ts\",\n \"test:custom\": \"pnpm build:dist && pnpm build:custom && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.custom.config.ts\",\n \"test:cypress\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.cypress.config.ts e2e -- cypress run -C src/cypress/__cypress__/cypress.config.ts\",\n \"test:cypress:open\": \"cypress open -C src/cypress/__cypress__/cypress.config.ts\",\n \"test:playwright\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.playwright.config.ts e2e -- playwright test\",\n \"test:storybook\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.storybook.config.ts\",\n \"test:pages\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.pages.config.ts\",\n \"tsc\": \"tsc --build tsconfig.json\"\n },\n \"browserslist\": {\n \"node\": [\n \"node 22\"\n ],\n \"browser\": [\n \"last 2 Chrome major versions\",\n \"last 2 Firefox major versions\",\n \"last 2 Safari major versions\",\n \"last 2 Edge major versions\"\n ],\n \"isomorphic\": [\n \"node 22\",\n \"last 2 Chrome major versions\",\n \"last 2 Firefox major versions\",\n \"last 2 Safari major versions\",\n \"last 2 Edge major versions\"\n ]\n },\n \"prettier\": {\n \"printWidth\": 85,\n \"singleQuote\": true,\n \"trailingComma\": \"all\",\n \"arrowParens\": \"always\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.36.0\",\n \"@playwright/test\": \"^1.55.1\",\n \"@reporters/github\": \"^1.11.0\",\n \"@storybook/builder-vite\": \"^10.0.1\",\n \"@storybook/react-vite\": \"^10.0.1\",\n \"@types/async-retry\": \"^1.4.9\",\n \"@types/base64-stream\": \"^1.0.5\",\n \"@types/jsdom\": \"^27.0.0\",\n \"@types/mime-types\": \"^3.0.1\",\n \"@types/multiparty\": \"^4.2.1\",\n \"@types/node\": \"^24.9.1\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@types/serve-handler\": \"^6.1.4\",\n \"cypress\": \"^15.5.0\",\n \"esbuild\": \"^0.27.0\",\n \"eslint\": \"^9.36.0\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-compat\": \"^6.0.2\",\n \"eslint-plugin-depend\": \"^1.3.1\",\n \"eslint-plugin-simple-import-sort\": \"^12.1.1\",\n \"eslint-plugin-unicorn\": \"^62.0.0\",\n \"jiti\": \"^2.6.0\",\n \"jsdom\": \"^27.0.0\",\n \"multiparty\": \"^4.2.3\",\n \"prettier\": \"^3.6.2\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"react-error-boundary\": \"^6.0.0\",\n \"serve-handler\": \"^6.1.6\",\n \"storybook\": \"^10.0.1\",\n \"typescript\": \"^5.9.2\",\n \"typescript-eslint\": \"^8.44.1\"\n },\n \"dependencies\": {\n \"async-retry\": \"^1.3.3\",\n \"base64-stream\": \"^1.0.0\",\n \"empathic\": \"^2.0.0\",\n \"fflate\": \"^0.8.2\",\n \"jose\": \"^6.1.0\",\n \"limit-concur\": \"^4.0.0\",\n \"mime-types\": \"^3.0.1\",\n \"srcset\": \"^5.0.2\"\n },\n \"storybook\": {\n \"displayName\": \"Happo\",\n \"icon\": \"https://happo.io/static/happo-hippo.png\",\n \"supportedFrameworks\": [\n \"angular\",\n \"ember\",\n \"html\",\n \"preact\",\n \"react\",\n \"react-native\",\n \"svelte\",\n \"vue\",\n \"web-components\"\n ],\n \"unsupportedFrameworks\": []\n },\n \"keywords\": [\n \"storybook-addon\",\n \"accessibility\",\n \"cypress\",\n \"playwright\",\n \"regression\",\n \"storybook\",\n \"test\",\n \"testing\",\n \"ui\",\n \"visual-regression\",\n \"visual\",\n \"vrt\"\n ],\n \"engines\": {\n \"node\": \"^22.18.0 || ^23.6.0 || >=24.0.0\"\n }\n}\n"],
4
+ "sourcesContent": ["{\n \"name\": \"happo\",\n \"version\": \"6.3.1\",\n \"description\": \"Catch unexpected visual and accessibility changes and UI bugs\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/happo/happo.git\"\n },\n \"bugs\": \"https://github.com/happo/happo/issues\",\n \"homepage\": \"https://happo.io\",\n \"bin\": {\n \"happo\": \"dist/cli/main.js\"\n },\n \"type\": \"module\",\n \"main\": \"./dist/config/index.js\",\n \"types\": \"./dist/config/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/config/index.d.ts\",\n \"default\": \"./dist/config/index.js\"\n },\n \"./cypress\": {\n \"types\": \"./dist/cypress/index.d.ts\",\n \"default\": \"./dist/cypress/index.js\"\n },\n \"./cypress/task\": {\n \"types\": \"./dist/cypress/task.d.ts\",\n \"default\": \"./dist/cypress/task.js\"\n },\n \"./playwright\": {\n \"types\": \"./dist/playwright/index.d.ts\",\n \"default\": \"./dist/playwright/index.js\"\n },\n \"./custom\": {\n \"types\": \"./dist/custom/index.d.ts\",\n \"default\": \"./dist/custom/index.js\"\n },\n \"./storybook/addon\": {\n \"types\": \"./dist/storybook/browser/addon.d.ts\",\n \"default\": \"./dist/storybook/browser/addon.js\"\n },\n \"./storybook/decorator\": {\n \"types\": \"./dist/storybook/browser/decorator.d.ts\",\n \"default\": \"./dist/storybook/browser/decorator.js\"\n },\n \"./storybook/preset\": {\n \"types\": \"./dist/storybook/preset.d.ts\",\n \"default\": \"./dist/storybook/preset.js\"\n },\n \"./storybook/register\": {\n \"types\": \"./dist/storybook/browser/register.d.ts\",\n \"default\": \"./dist/storybook/browser/register.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"preset.js\"\n ],\n \"scripts\": {\n \"all\": \"node ./scripts/allchecks.ts\",\n \"build\": \"pnpm build:types && pnpm build:dist\",\n \"build:custom\": \"esbuild src/custom/__happo__/index.ts --bundle --format=iife --global-name=happoCustom --outfile=tmp/happo-custom/bundle.js --platform=browser --target=esnext\",\n \"build:dist\": \"./scripts/build.ts\",\n \"build:types\": \"pnpm tsc --pretty\",\n \"build:watch\": \"tsc --build --watch\",\n \"clean\": \"rm -rf dist tmp/tsc tmp/happo-custom\",\n \"lint\": \"eslint .\",\n \"prepublishOnly\": \"pnpm clean && pnpm build\",\n \"storybook:dev\": \"storybook dev --config-dir src/storybook/__tests__/storybook-app -p ${PORT:-6007}\",\n \"test\": \"node --env-file-if-exists=.env.local ./scripts/test.ts\",\n \"test:custom\": \"pnpm build:dist && pnpm build:custom && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.custom.config.ts\",\n \"test:cypress\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.cypress.config.ts e2e -- cypress run -C src/cypress/__cypress__/cypress.config.ts\",\n \"test:cypress:open\": \"cypress open -C src/cypress/__cypress__/cypress.config.ts\",\n \"test:playwright\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.playwright.config.ts e2e -- playwright test\",\n \"test:storybook\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.storybook.config.ts\",\n \"test:pages\": \"pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.pages.config.ts\",\n \"tsc\": \"tsc --build tsconfig.json\"\n },\n \"browserslist\": {\n \"node\": [\n \"node 22\"\n ],\n \"browser\": [\n \"last 2 Chrome major versions\",\n \"last 2 Firefox major versions\",\n \"last 2 Safari major versions\",\n \"last 2 Edge major versions\"\n ],\n \"isomorphic\": [\n \"node 22\",\n \"last 2 Chrome major versions\",\n \"last 2 Firefox major versions\",\n \"last 2 Safari major versions\",\n \"last 2 Edge major versions\"\n ]\n },\n \"prettier\": {\n \"printWidth\": 85,\n \"singleQuote\": true,\n \"trailingComma\": \"all\",\n \"arrowParens\": \"always\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.36.0\",\n \"@playwright/test\": \"^1.55.1\",\n \"@reporters/github\": \"^1.11.0\",\n \"@storybook/builder-vite\": \"^10.0.1\",\n \"@storybook/react-vite\": \"^10.0.1\",\n \"@types/async-retry\": \"^1.4.9\",\n \"@types/base64-stream\": \"^1.0.5\",\n \"@types/jsdom\": \"^27.0.0\",\n \"@types/mime-types\": \"^3.0.1\",\n \"@types/multiparty\": \"^4.2.1\",\n \"@types/node\": \"^24.9.1\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@types/serve-handler\": \"^6.1.4\",\n \"cypress\": \"^15.5.0\",\n \"esbuild\": \"^0.27.0\",\n \"eslint\": \"^9.36.0\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-compat\": \"^6.0.2\",\n \"eslint-plugin-depend\": \"^1.3.1\",\n \"eslint-plugin-simple-import-sort\": \"^12.1.1\",\n \"eslint-plugin-unicorn\": \"^63.0.0\",\n \"jiti\": \"^2.6.0\",\n \"jsdom\": \"^28.0.0\",\n \"multiparty\": \"^4.2.3\",\n \"prettier\": \"^3.6.2\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"react-error-boundary\": \"^6.0.0\",\n \"serve-handler\": \"^6.1.6\",\n \"storybook\": \"^10.0.1\",\n \"typescript\": \"^5.9.2\",\n \"typescript-eslint\": \"^8.44.1\"\n },\n \"dependencies\": {\n \"async-retry\": \"^1.3.3\",\n \"base64-stream\": \"^1.0.0\",\n \"empathic\": \"^2.0.0\",\n \"fflate\": \"^0.8.2\",\n \"jose\": \"^6.1.0\",\n \"limit-concur\": \"^4.0.0\",\n \"mime-types\": \"^3.0.1\",\n \"srcset\": \"^5.0.2\"\n },\n \"storybook\": {\n \"displayName\": \"Happo\",\n \"icon\": \"https://happo.io/static/happo-hippo.png\",\n \"supportedFrameworks\": [\n \"angular\",\n \"ember\",\n \"html\",\n \"preact\",\n \"react\",\n \"react-native\",\n \"svelte\",\n \"vue\",\n \"web-components\"\n ],\n \"unsupportedFrameworks\": []\n },\n \"keywords\": [\n \"storybook-addon\",\n \"accessibility\",\n \"cypress\",\n \"playwright\",\n \"regression\",\n \"storybook\",\n \"test\",\n \"testing\",\n \"ui\",\n \"visual-regression\",\n \"visual\",\n \"vrt\"\n ],\n \"engines\": {\n \"node\": \"^22.18.0 || ^23.6.0 || >=24.0.0\"\n }\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-56XY3V7T.js";
3
+ } from "./chunk-WFRUGXXQ.js";
4
4
  import {
5
5
  ErrorWithStatusCode
6
- } from "./chunk-UBNAHFZ5.js";
6
+ } from "./chunk-H4SN6WPV.js";
7
7
 
8
8
  // src/network/cancelJob.ts
9
9
  async function cancelJob(status, message, config, { beforeSha, afterSha, link }, logger) {
@@ -43,4 +43,4 @@ async function cancelJob(status, message, config, { beforeSha, afterSha, link },
43
43
  export {
44
44
  cancelJob
45
45
  };
46
- //# sourceMappingURL=chunk-HFWMNEW7.js.map
46
+ //# sourceMappingURL=chunk-VRKXLPSQ.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  fetchWithRetry
3
- } from "./chunk-UBNAHFZ5.js";
3
+ } from "./chunk-H4SN6WPV.js";
4
4
 
5
5
  // src/network/makeHappoAPIRequest.ts
6
6
  import { SignJWT } from "jose";
@@ -51,4 +51,4 @@ async function makeHappoAPIRequest({ url, path, method = "GET", formData, body }
51
51
  export {
52
52
  makeHappoAPIRequest
53
53
  };
54
- //# sourceMappingURL=chunk-56XY3V7T.js.map
54
+ //# sourceMappingURL=chunk-WFRUGXXQ.js.map
@@ -0,0 +1,10 @@
1
+ import {
2
+ createAsyncComparison
3
+ } from "./chunk-AQSWKKBJ.js";
4
+ import "./chunk-WFRUGXXQ.js";
5
+ import "./chunk-H4SN6WPV.js";
6
+ import "./chunk-VGC6VLFX.js";
7
+ export {
8
+ createAsyncComparison as default
9
+ };
10
+ //# sourceMappingURL=createAsyncComparison-O4TTQSO6.js.map
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-56XY3V7T.js";
4
- import "./chunk-UBNAHFZ5.js";
5
- import "./chunk-Q3DT6FIT.js";
3
+ } from "./chunk-WFRUGXXQ.js";
4
+ import "./chunk-H4SN6WPV.js";
5
+ import "./chunk-VGC6VLFX.js";
6
6
 
7
7
  // src/network/createAsyncReport.ts
8
8
  function assertResultIsCreateAsyncReportResult(result) {
@@ -38,4 +38,4 @@ async function createAsyncReport(snapRequestIds, config, { afterSha, link, messa
38
38
  export {
39
39
  createAsyncReport as default
40
40
  };
41
- //# sourceMappingURL=createAsyncReport-EAFZGNCW.js.map
41
+ //# sourceMappingURL=createAsyncReport-5E3IWVZX.js.map
@@ -0,0 +1,73 @@
1
+ import {
2
+ makeHappoAPIRequest
3
+ } from "./chunk-WFRUGXXQ.js";
4
+ import "./chunk-H4SN6WPV.js";
5
+ import "./chunk-VGC6VLFX.js";
6
+
7
+ // src/network/getFlakes.ts
8
+ function formatFlakeOutput(flakes) {
9
+ if (flakes.length === 0) {
10
+ return "No flakes found.";
11
+ }
12
+ const lines = [
13
+ `Found ${flakes.length} flake${flakes.length === 1 ? "" : "s"}:`
14
+ ];
15
+ for (const flake of flakes) {
16
+ const parts = [
17
+ flake.component,
18
+ flake.variant,
19
+ flake.target
20
+ ].filter(Boolean);
21
+ const label = parts.length > 0 ? parts.join(" / ") : "Unknown flake";
22
+ const projectLabel = flake.project ? `[${flake.project}] ` : "";
23
+ const snapshotUrls = (flake.snapshots ?? []).map((snapshot) => snapshot.url).filter(Boolean);
24
+ const snapshotsLabel = snapshotUrls.length > 0 ? ` [${snapshotUrls.join(", ")}]` : "";
25
+ const comparisonLabel = flake.comparison?.url ? ` (${flake.comparison.url})` : "";
26
+ lines.push(
27
+ `- ${projectLabel}${label}${snapshotsLabel}${comparisonLabel}`
28
+ );
29
+ }
30
+ lines.push("Tip: use --format=json to see full details.");
31
+ return lines.join("\n");
32
+ }
33
+ async function getFlakes({ project, limit, page, component, variant, target, sha }, config, logger) {
34
+ const searchParams = new URLSearchParams();
35
+ if (project) {
36
+ searchParams.set("project", project);
37
+ }
38
+ if (limit) {
39
+ searchParams.set("limit", limit);
40
+ }
41
+ if (page) {
42
+ searchParams.set("page", page);
43
+ }
44
+ if (component) {
45
+ searchParams.set("component", component);
46
+ }
47
+ if (variant) {
48
+ searchParams.set("variant", variant);
49
+ }
50
+ if (target) {
51
+ searchParams.set("target", target);
52
+ }
53
+ if (sha) {
54
+ searchParams.set("sha", sha);
55
+ }
56
+ const query = searchParams.toString();
57
+ const path = query ? `/api/flake?${query}` : "/api/flake";
58
+ const response = await makeHappoAPIRequest(
59
+ { path, method: "GET" },
60
+ config,
61
+ { retryCount: 3 },
62
+ logger
63
+ );
64
+ if (!Array.isArray(response)) {
65
+ throw new TypeError("Expected flake response to be an array.");
66
+ }
67
+ return response;
68
+ }
69
+ export {
70
+ getFlakes as default,
71
+ formatFlakeOutput
72
+ };
73
+ //# sourceMappingURL=getFlakes-ITQLVM5D.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/network/getFlakes.ts"],
4
+ "sourcesContent": ["import type { ConfigWithDefaults } from '../config/index.ts';\nimport type { Logger } from '../isomorphic/types.ts';\nimport makeHappoAPIRequest from './makeHappoAPIRequest.ts';\n\nexport type FlakeEntry = {\n project?: string;\n component?: string;\n variant?: string;\n target?: string;\n snapshots?: Array<{\n url?: string;\n width?: number;\n height?: number;\n }>;\n comparison?: {\n sha1?: string;\n sha2?: string;\n status?: string;\n url?: string;\n createdAt?: string;\n diffs?: number;\n unchanged?: number;\n added?: number;\n deleted?: number;\n link?: string;\n message?: string;\n project?: string;\n };\n};\n\nexport type GetFlakesOptions = {\n project?: string | undefined;\n limit?: string | undefined;\n page?: string | undefined;\n component?: string | undefined;\n variant?: string | undefined;\n target?: string | undefined;\n sha?: string | undefined;\n};\n\nexport function formatFlakeOutput(flakes: Array<FlakeEntry>): string {\n if (flakes.length === 0) {\n return 'No flakes found.';\n }\n\n const lines = [\n `Found ${flakes.length} flake${flakes.length === 1 ? '' : 's'}:`,\n ];\n\n for (const flake of flakes) {\n const parts = [\n flake.component,\n flake.variant,\n flake.target,\n ].filter(Boolean);\n const label = parts.length > 0 ? parts.join(' / ') : 'Unknown flake';\n const projectLabel = flake.project ? `[${flake.project}] ` : '';\n const snapshotUrls = (flake.snapshots ?? [])\n .map((snapshot) => snapshot.url)\n .filter(Boolean) as Array<string>;\n const snapshotsLabel =\n snapshotUrls.length > 0 ? ` [${snapshotUrls.join(', ')}]` : '';\n const comparisonLabel = flake.comparison?.url\n ? ` (${flake.comparison.url})`\n : '';\n lines.push(\n `- ${projectLabel}${label}${snapshotsLabel}${comparisonLabel}`,\n );\n }\n\n lines.push('Tip: use --format=json to see full details.');\n\n return lines.join('\\n');\n}\n\nexport default async function getFlakes(\n { project, limit, page, component, variant, target, sha }: GetFlakesOptions,\n config: ConfigWithDefaults,\n logger: Logger,\n): Promise<Array<FlakeEntry>> {\n const searchParams = new URLSearchParams();\n if (project) {\n searchParams.set('project', project);\n }\n if (limit) {\n searchParams.set('limit', limit);\n }\n if (page) {\n searchParams.set('page', page);\n }\n if (component) {\n searchParams.set('component', component);\n }\n if (variant) {\n searchParams.set('variant', variant);\n }\n if (target) {\n searchParams.set('target', target);\n }\n if (sha) {\n searchParams.set('sha', sha);\n }\n\n const query = searchParams.toString();\n const path = (query ? `/api/flake?${query}` : '/api/flake') as `/api/${string}`;\n\n const response = await makeHappoAPIRequest(\n { path, method: 'GET' },\n config,\n { retryCount: 3 },\n logger,\n );\n\n if (!Array.isArray(response)) {\n throw new TypeError('Expected flake response to be an array.');\n }\n\n return response as Array<FlakeEntry>;\n}\n"],
5
+ "mappings": ";;;;;;;AAwCO,SAAS,kBAAkB,QAAmC;AACnE,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ;AAAA,IACZ,SAAS,OAAO,MAAM,SAAS,OAAO,WAAW,IAAI,KAAK,GAAG;AAAA,EAC/D;AAEA,aAAW,SAAS,QAAQ;AAC1B,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR,EAAE,OAAO,OAAO;AAChB,UAAM,QAAQ,MAAM,SAAS,IAAI,MAAM,KAAK,KAAK,IAAI;AACrD,UAAM,eAAe,MAAM,UAAU,IAAI,MAAM,OAAO,OAAO;AAC7D,UAAM,gBAAgB,MAAM,aAAa,CAAC,GACvC,IAAI,CAAC,aAAa,SAAS,GAAG,EAC9B,OAAO,OAAO;AACjB,UAAM,iBACJ,aAAa,SAAS,IAAI,KAAK,aAAa,KAAK,IAAI,CAAC,MAAM;AAC9D,UAAM,kBAAkB,MAAM,YAAY,MACtC,KAAK,MAAM,WAAW,GAAG,MACzB;AACJ,UAAM;AAAA,MACJ,KAAK,YAAY,GAAG,KAAK,GAAG,cAAc,GAAG,eAAe;AAAA,IAC9D;AAAA,EACF;AAEA,QAAM,KAAK,6CAA6C;AAExD,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,eAAO,UACL,EAAE,SAAS,OAAO,MAAM,WAAW,SAAS,QAAQ,IAAI,GACxD,QACA,QAC4B;AAC5B,QAAM,eAAe,IAAI,gBAAgB;AACzC,MAAI,SAAS;AACX,iBAAa,IAAI,WAAW,OAAO;AAAA,EACrC;AACA,MAAI,OAAO;AACT,iBAAa,IAAI,SAAS,KAAK;AAAA,EACjC;AACA,MAAI,MAAM;AACR,iBAAa,IAAI,QAAQ,IAAI;AAAA,EAC/B;AACA,MAAI,WAAW;AACb,iBAAa,IAAI,aAAa,SAAS;AAAA,EACzC;AACA,MAAI,SAAS;AACX,iBAAa,IAAI,WAAW,OAAO;AAAA,EACrC;AACA,MAAI,QAAQ;AACV,iBAAa,IAAI,UAAU,MAAM;AAAA,EACnC;AACA,MAAI,KAAK;AACP,iBAAa,IAAI,OAAO,GAAG;AAAA,EAC7B;AAEA,QAAM,QAAQ,aAAa,SAAS;AACpC,QAAM,OAAQ,QAAQ,cAAc,KAAK,KAAK;AAE9C,QAAM,WAAW,MAAM;AAAA,IACrB,EAAE,MAAM,QAAQ,MAAM;AAAA,IACtB;AAAA,IACA,EAAE,YAAY,EAAE;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG;AAC5B,UAAM,IAAI,UAAU,yCAAyC;AAAA,EAC/D;AAEA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AA+KrD,wBAAsB,IAAI,CACxB,OAAO,GAAE,KAAK,CAAC,MAAM,CAAgB,EACrC,MAAM,GAAE,MAAgB,GACvB,OAAO,CAAC,IAAI,CAAC,CA2Df"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAkOrD,wBAAsB,IAAI,CACxB,OAAO,GAAE,KAAK,CAAC,MAAM,CAAgB,EACrC,MAAM,GAAE,MAAgB,GACvB,OAAO,CAAC,IAAI,CAAC,CA4Ff"}
package/dist/cli/main.js CHANGED
@@ -4,10 +4,10 @@ import {
4
4
  } from "./chunk-JTRP4JVC.js";
5
5
  import {
6
6
  fetchWithRetry
7
- } from "./chunk-UBNAHFZ5.js";
7
+ } from "./chunk-H4SN6WPV.js";
8
8
  import {
9
9
  package_default
10
- } from "./chunk-Q3DT6FIT.js";
10
+ } from "./chunk-VGC6VLFX.js";
11
11
 
12
12
  // src/cli/index.ts
13
13
  import path3 from "node:path";
@@ -226,6 +226,44 @@ async function getFallbackApiToken(endpoint, environment, logger) {
226
226
  }
227
227
  return void 0;
228
228
  }
229
+ function validateDeepCompareSettings(deepCompare, configFilePath) {
230
+ if (typeof deepCompare !== "object" || Array.isArray(deepCompare)) {
231
+ throw new TypeError(
232
+ `Invalid \`deepCompare\` in config file ${configFilePath}: must be an object, got: ${Array.isArray(deepCompare) ? "array" : typeof deepCompare}.`
233
+ );
234
+ }
235
+ const settings = deepCompare;
236
+ if (!("compareThreshold" in settings) || settings.compareThreshold === void 0) {
237
+ throw new TypeError(
238
+ `Invalid \`deepCompare\` in config file ${configFilePath}: \`compareThreshold\` is required.`
239
+ );
240
+ }
241
+ if (typeof settings.compareThreshold !== "number" || settings.compareThreshold < 0 || settings.compareThreshold > 1) {
242
+ throw new TypeError(
243
+ `Invalid \`deepCompare.compareThreshold\` in config file ${configFilePath}: must be a number between 0 and 1, got: ${JSON.stringify(settings.compareThreshold)}.`
244
+ );
245
+ }
246
+ if ("diffAlgorithm" in settings && settings.diffAlgorithm !== void 0 && (typeof settings.diffAlgorithm !== "string" || settings.diffAlgorithm !== "color-delta" && settings.diffAlgorithm !== "ssim")) {
247
+ throw new TypeError(
248
+ `Invalid \`deepCompare.diffAlgorithm\` in config file ${configFilePath}: must be "color-delta" or "ssim", got: ${JSON.stringify(settings.diffAlgorithm)}.`
249
+ );
250
+ }
251
+ if ("ignoreThreshold" in settings && settings.ignoreThreshold !== void 0 && (typeof settings.ignoreThreshold !== "number" || settings.ignoreThreshold < 0 || settings.ignoreThreshold > 1)) {
252
+ throw new TypeError(
253
+ `Invalid \`deepCompare.ignoreThreshold\` in config file ${configFilePath}: must be a number between 0 and 1, got: ${JSON.stringify(settings.ignoreThreshold)}.`
254
+ );
255
+ }
256
+ if ("ignoreWhitespace" in settings && settings.ignoreWhitespace !== void 0 && typeof settings.ignoreWhitespace !== "boolean") {
257
+ throw new TypeError(
258
+ `Invalid \`deepCompare.ignoreWhitespace\` in config file ${configFilePath}: must be a boolean, got: ${JSON.stringify(settings.ignoreWhitespace)}.`
259
+ );
260
+ }
261
+ if ("applyBlur" in settings && settings.applyBlur !== void 0 && typeof settings.applyBlur !== "boolean") {
262
+ throw new TypeError(
263
+ `Invalid \`deepCompare.applyBlur\` in config file ${configFilePath}: must be a boolean, got: ${JSON.stringify(settings.applyBlur)}.`
264
+ );
265
+ }
266
+ }
229
267
  async function loadConfigFile(configFilePath, environment, logger = console) {
230
268
  try {
231
269
  const stats = await fs.promises.stat(configFilePath);
@@ -312,6 +350,12 @@ async function loadConfigFile(configFilePath, environment, logger = console) {
312
350
  target.freezeAnimations = target.freezeAnimations || "last-frame";
313
351
  target.prefersReducedMotion = target.prefersReducedMotion ?? true;
314
352
  }
353
+ if (config.deepCompare !== void 0 && config.deepCompare !== null) {
354
+ validateDeepCompareSettings(config.deepCompare, configFilePath);
355
+ if (!config.deepCompare.diffAlgorithm) {
356
+ config.deepCompare.diffAlgorithm = "color-delta";
357
+ }
358
+ }
315
359
  const configWithDefaults = {
316
360
  endpoint: DEFAULT_ENDPOINT,
317
361
  githubApiUrl: "https://api.github.com",
@@ -954,7 +998,16 @@ async function parseFrames(stack, cwd = process.cwd()) {
954
998
  }
955
999
  return frames.toReversed();
956
1000
  }
1001
+ function isTestEnv(env = process.env) {
1002
+ return env.NODE_ENV === "test" || Boolean(env.JEST_WORKER_ID);
1003
+ }
957
1004
  function createReporter(opts = {}) {
1005
+ if (isTestEnv()) {
1006
+ return {
1007
+ async captureException() {
1008
+ }
1009
+ };
1010
+ }
958
1011
  const maxPerMinute = Math.max(1, opts.maxPerMinute ?? 10);
959
1012
  let sentThisMinute = 0;
960
1013
  let minuteTick = Date.now();
@@ -1000,7 +1053,7 @@ function createReporter(opts = {}) {
1000
1053
 
1001
1054
  // src/cli/index.ts
1002
1055
  async function getVersion() {
1003
- const packageJson = await import("./package-LZDJBDUK.js");
1056
+ const packageJson = await import("./package-BZTLWVDW.js");
1004
1057
  return packageJson.default.version;
1005
1058
  }
1006
1059
  function parseDashdashCommandParts(rawArgs) {
@@ -1010,6 +1063,35 @@ function parseDashdashCommandParts(rawArgs) {
1010
1063
  }
1011
1064
  return rawArgs.slice(dashdashIndex + 1);
1012
1065
  }
1066
+ var fallbackOptions = {
1067
+ allProjects: {
1068
+ type: "boolean"
1069
+ },
1070
+ format: {
1071
+ type: "string"
1072
+ },
1073
+ project: {
1074
+ type: "string"
1075
+ },
1076
+ limit: {
1077
+ type: "string"
1078
+ },
1079
+ page: {
1080
+ type: "string"
1081
+ },
1082
+ component: {
1083
+ type: "string"
1084
+ },
1085
+ variant: {
1086
+ type: "string"
1087
+ },
1088
+ target: {
1089
+ type: "string"
1090
+ },
1091
+ sha: {
1092
+ type: "string"
1093
+ }
1094
+ };
1013
1095
  function parseRawArgs(rawArgs) {
1014
1096
  const parsedArgs = parseArgs({
1015
1097
  args: rawArgs,
@@ -1058,7 +1140,8 @@ function parseRawArgs(rawArgs) {
1058
1140
  },
1059
1141
  githubToken: {
1060
1142
  type: "string"
1061
- }
1143
+ },
1144
+ ...fallbackOptions
1062
1145
  },
1063
1146
  allowPositionals: true
1064
1147
  });
@@ -1073,6 +1156,7 @@ Usage: happo [options]
1073
1156
  Commands:
1074
1157
  <default> Run happo tests
1075
1158
  finalize Finalize happo report for Cypress/Playwright tests running in parallel
1159
+ flake List reported flakes for a project
1076
1160
 
1077
1161
  Options:
1078
1162
  --config Path to happo config file
@@ -1091,6 +1175,17 @@ Options:
1091
1175
  --nonce <nonce> Nonce to use for Cypress/Playwright comparison
1092
1176
  --githubToken <token> GitHub token to use for posting Happo statuses as comments. Use in combination with the \`githubApiUrl\` configuration option. (default: auto-detected from environment)
1093
1177
 
1178
+ Flake command options:
1179
+ --allProjects List flakes across all projects (default: current project)
1180
+ --format <format> Output format for flake command (default: "human", use "json" for raw output)
1181
+ --project <name> Project to filter flakes for (default: project from config)
1182
+ --limit <number> Limit flake results (default: 100, max: 1000)
1183
+ --page <number> Page number for flakes (default: 1)
1184
+ --component <name> Filter flakes by component name
1185
+ --variant <name> Filter flakes by variant name
1186
+ --target <name> Filter flakes by target name
1187
+ --sha <sha> Filter flakes by before/after sha
1188
+
1094
1189
  Examples:
1095
1190
  happo
1096
1191
 
@@ -1109,6 +1204,13 @@ Examples:
1109
1204
 
1110
1205
  happo finalize
1111
1206
  happo finalize --nonce my-unique-nonce
1207
+
1208
+ happo flake
1209
+ happo flake --allProjects
1210
+ happo flake --format=json
1211
+ happo flake --project=test-project --limit=10 --page=2
1212
+ happo flake --component=button --variant=primary --target=chrome
1213
+ happo flake --sha=ff2df74c1730341240840010c7518b2c1f4b55cb
1112
1214
  `;
1113
1215
  function makeAbsolute(configFilePath) {
1114
1216
  if (configFilePath.startsWith(".")) {
@@ -1171,6 +1273,38 @@ async function main(rawArgs = process.argv, logger = console) {
1171
1273
  await handleFinalizeCommand(config, environment, logger);
1172
1274
  return;
1173
1275
  }
1276
+ if (command === "flake") {
1277
+ const flakeOptions = {};
1278
+ if (args.values.allProjects !== void 0) {
1279
+ flakeOptions.allProjects = args.values.allProjects;
1280
+ }
1281
+ if (args.values.format !== void 0) {
1282
+ flakeOptions.format = args.values.format;
1283
+ }
1284
+ if (args.values.project !== void 0) {
1285
+ flakeOptions.project = args.values.project;
1286
+ }
1287
+ if (args.values.limit !== void 0) {
1288
+ flakeOptions.limit = args.values.limit;
1289
+ }
1290
+ if (args.values.page !== void 0) {
1291
+ flakeOptions.page = args.values.page;
1292
+ }
1293
+ if (args.values.component !== void 0) {
1294
+ flakeOptions.component = args.values.component;
1295
+ }
1296
+ if (args.values.variant !== void 0) {
1297
+ flakeOptions.variant = args.values.variant;
1298
+ }
1299
+ if (args.values.target !== void 0) {
1300
+ flakeOptions.target = args.values.target;
1301
+ }
1302
+ if (args.values.sha !== void 0) {
1303
+ flakeOptions.sha = args.values.sha;
1304
+ }
1305
+ await handleFlakeCommand(config, flakeOptions, logger);
1306
+ return;
1307
+ }
1174
1308
  if (command === void 0) {
1175
1309
  await handleDefaultCommand(config, environment, logger);
1176
1310
  return;
@@ -1190,10 +1324,10 @@ async function main(rawArgs = process.argv, logger = console) {
1190
1324
  async function handleDefaultCommand(config, environment, logger) {
1191
1325
  logger.log("Running happo tests...");
1192
1326
  const [startJob, createAsyncComparison, createAsyncReport, prepareSnapRequests] = await Promise.all([
1193
- (await import("./startJob-ZYTK6OMK.js")).default,
1194
- (await import("./createAsyncComparison-IVFALQTJ.js")).default,
1195
- (await import("./createAsyncReport-EAFZGNCW.js")).default,
1196
- (await import("./prepareSnapRequests-FQJAOJNF.js")).default
1327
+ (await import("./startJob-5JOX4R4S.js")).default,
1328
+ (await import("./createAsyncComparison-O4TTQSO6.js")).default,
1329
+ (await import("./createAsyncReport-5E3IWVZX.js")).default,
1330
+ (await import("./prepareSnapRequests-O2FC3E2P.js")).default
1197
1331
  ]);
1198
1332
  await startJob(config, environment, logger);
1199
1333
  try {
@@ -1226,7 +1360,7 @@ async function handleDefaultCommand(config, environment, logger) {
1226
1360
  } catch (e) {
1227
1361
  const message = e instanceof Error ? e.message : String(e);
1228
1362
  logger.error(`${config.integration.type} run failed: ${message}`, e);
1229
- const cancelJob = (await import("./cancelJob-JVBWGU62.js")).default;
1363
+ const cancelJob = (await import("./cancelJob-6YMRZKZ6.js")).default;
1230
1364
  await cancelJob("failure", message, config, environment, logger);
1231
1365
  process.exitCode = 1;
1232
1366
  return;
@@ -1237,7 +1371,7 @@ async function handleFinalizeCommand(config, environment, logger) {
1237
1371
  logger.log("Config:", config);
1238
1372
  logger.log("Environment:", environment);
1239
1373
  try {
1240
- const finalizeAll = (await import("./wrapper-LPL52GIF.js")).finalizeAll;
1374
+ const finalizeAll = (await import("./wrapper-ZQOATRO2.js")).finalizeAll;
1241
1375
  await finalizeAll({ happoConfig: config, environment, logger });
1242
1376
  } catch (e) {
1243
1377
  logger.error(e instanceof Error ? e.message : String(e), e);
@@ -1247,6 +1381,47 @@ async function handleFinalizeCommand(config, environment, logger) {
1247
1381
  process.exitCode = 0;
1248
1382
  return;
1249
1383
  }
1384
+ async function handleFlakeCommand(config, {
1385
+ allProjects,
1386
+ format,
1387
+ project: projectOverride,
1388
+ limit,
1389
+ page,
1390
+ component,
1391
+ variant,
1392
+ target,
1393
+ sha
1394
+ }, logger) {
1395
+ if (format && (format !== "json" && format !== "human")) {
1396
+ logger.error(
1397
+ `Unsupported format: ${format}. Use --format=json for raw JSON output or --format=human for human-readable output.`
1398
+ );
1399
+ process.exitCode = 1;
1400
+ return;
1401
+ }
1402
+ const { default: getFlakes, formatFlakeOutput } = await import("./getFlakes-ITQLVM5D.js");
1403
+ const project = allProjects ? void 0 : projectOverride ?? config.project;
1404
+ const flakes = await getFlakes(
1405
+ {
1406
+ project,
1407
+ limit,
1408
+ page,
1409
+ component,
1410
+ variant,
1411
+ target,
1412
+ sha
1413
+ },
1414
+ config,
1415
+ logger
1416
+ );
1417
+ if (format === "json") {
1418
+ logger.log(JSON.stringify(flakes, null, 2));
1419
+ process.exitCode = 0;
1420
+ return;
1421
+ }
1422
+ logger.log(formatFlakeOutput(flakes));
1423
+ process.exitCode = 0;
1424
+ }
1250
1425
  var E2E_INTEGRATION_TYPES = ["cypress", "playwright"];
1251
1426
  async function handleE2ECommand(config, environment, dashdashCommandParts, configFilePath, logger) {
1252
1427
  if (!E2E_INTEGRATION_TYPES.includes(config.integration.type)) {
@@ -1266,7 +1441,7 @@ async function handleE2ECommand(config, environment, dashdashCommandParts, confi
1266
1441
  logger.log("Config:", config);
1267
1442
  logger.log("Environment:", environment);
1268
1443
  logger.log("Dashdash command parts:", dashdashCommandParts);
1269
- const runWithWrapper = (await import("./wrapper-LPL52GIF.js")).default;
1444
+ const runWithWrapper = (await import("./wrapper-ZQOATRO2.js")).default;
1270
1445
  const exitCode = await runWithWrapper(
1271
1446
  dashdashCommandParts,
1272
1447
  config,