happo 6.1.1 → 6.1.3

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 (39) hide show
  1. package/dist/cli/cancelJob-6HAWZO24.js +41 -0
  2. package/dist/cli/cancelJob-6HAWZO24.js.map +7 -0
  3. package/dist/cli/{chunk-7EFGHIJ4.js → chunk-IIM3SWVI.js} +2 -2
  4. package/dist/cli/chunk-IIM3SWVI.js.map +7 -0
  5. package/dist/cli/{chunk-5Q6ZJTDL.js → chunk-J542RNYK.js} +3 -3
  6. package/dist/cli/{chunk-5Q6ZJTDL.js.map → chunk-J542RNYK.js.map} +1 -1
  7. package/dist/cli/{chunk-DDC5URHF.js → chunk-L5HPPXAO.js} +3 -2
  8. package/dist/cli/{chunk-QHIVL6GP.js → chunk-QZGCAYHK.js} +2 -2
  9. package/dist/cli/createAsyncComparison-URQ67QOH.js +10 -0
  10. package/dist/cli/{createAsyncReport-3PTACG33.js → createAsyncReport-5DCCM7SL.js} +4 -4
  11. package/dist/cli/main.js +28 -12
  12. package/dist/cli/main.js.map +2 -2
  13. package/dist/cli/package-G75AVF5U.js +7 -0
  14. package/dist/cli/{prepareSnapRequests-H3UNIE4O.js → prepareSnapRequests-2MO5YYLT.js} +4 -4
  15. package/dist/cli/{startJob-EQDJEH4G.js → startJob-AWLKOPCZ.js} +4 -4
  16. package/dist/cli/{wrapper-RAJYXKL6.js → wrapper-O4GGK6IN.js} +5 -5
  17. package/dist/config/loadConfig.d.ts.map +1 -1
  18. package/dist/cypress/task.js +17 -2
  19. package/dist/cypress/task.js.map +2 -2
  20. package/dist/network/cancelJob.d.ts +1 -1
  21. package/dist/network/cancelJob.d.ts.map +1 -1
  22. package/dist/network/makeHappoAPIRequest.d.ts +1 -1
  23. package/dist/network/makeHappoAPIRequest.d.ts.map +1 -1
  24. package/dist/playwright/index.js +17 -2
  25. package/dist/playwright/index.js.map +2 -2
  26. package/package.json +2 -2
  27. package/dist/cli/cancelJob-3VTBAIZG.js +0 -28
  28. package/dist/cli/cancelJob-3VTBAIZG.js.map +0 -7
  29. package/dist/cli/chunk-7EFGHIJ4.js.map +0 -7
  30. package/dist/cli/createAsyncComparison-JYSUXA2H.js +0 -10
  31. package/dist/cli/package-AAAA77YQ.js +0 -7
  32. /package/dist/cli/{chunk-DDC5URHF.js.map → chunk-L5HPPXAO.js.map} +0 -0
  33. /package/dist/cli/{chunk-QHIVL6GP.js.map → chunk-QZGCAYHK.js.map} +0 -0
  34. /package/dist/cli/{createAsyncComparison-JYSUXA2H.js.map → createAsyncComparison-URQ67QOH.js.map} +0 -0
  35. /package/dist/cli/{createAsyncReport-3PTACG33.js.map → createAsyncReport-5DCCM7SL.js.map} +0 -0
  36. /package/dist/cli/{package-AAAA77YQ.js.map → package-G75AVF5U.js.map} +0 -0
  37. /package/dist/cli/{prepareSnapRequests-H3UNIE4O.js.map → prepareSnapRequests-2MO5YYLT.js.map} +0 -0
  38. /package/dist/cli/{startJob-EQDJEH4G.js.map → startJob-AWLKOPCZ.js.map} +0 -0
  39. /package/dist/cli/{wrapper-RAJYXKL6.js.map → wrapper-O4GGK6IN.js.map} +0 -0
@@ -0,0 +1,41 @@
1
+ import {
2
+ makeHappoAPIRequest
3
+ } from "./chunk-IIM3SWVI.js";
4
+ import {
5
+ ErrorWithStatusCode
6
+ } from "./chunk-L5HPPXAO.js";
7
+ import "./chunk-J542RNYK.js";
8
+
9
+ // src/network/cancelJob.ts
10
+ async function cancelJob(status, message, config, { beforeSha, afterSha, link }, logger) {
11
+ try {
12
+ await makeHappoAPIRequest(
13
+ {
14
+ path: `/api/jobs/${beforeSha}/${afterSha}/cancel`,
15
+ method: "POST",
16
+ body: {
17
+ link,
18
+ message,
19
+ project: config.project,
20
+ status
21
+ }
22
+ },
23
+ config,
24
+ { retryCount: 5 },
25
+ logger
26
+ );
27
+ } catch (error) {
28
+ if (error instanceof ErrorWithStatusCode && error.statusCode === 409) {
29
+ logger.error(
30
+ "Skipping cancellation of Happo job because it has already been completed",
31
+ error
32
+ );
33
+ } else {
34
+ throw error;
35
+ }
36
+ }
37
+ }
38
+ export {
39
+ cancelJob as default
40
+ };
41
+ //# sourceMappingURL=cancelJob-6HAWZO24.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/network/cancelJob.ts"],
4
+ "sourcesContent": ["import type { ConfigWithDefaults } from '../config/index.ts';\nimport type { EnvironmentResult } from '../environment/index.ts';\nimport type { Logger } from '../isomorphic/types.ts';\nimport { ErrorWithStatusCode } from './fetchWithRetry.ts';\nimport makeHappoAPIRequest from './makeHappoAPIRequest.ts';\n\ntype Status = 'failure' | 'success';\n\n/**\n * Tell Happo that a job comparing two SHAs had to be cancelled for some reason.\n *\n * @see https://happo.io/docs/api#cancelJob\n */\nexport default async function cancelJob(\n status: Status,\n message: string,\n config: ConfigWithDefaults,\n { beforeSha, afterSha, link }: EnvironmentResult,\n logger: Logger,\n): Promise<void> {\n try {\n await makeHappoAPIRequest(\n {\n path: `/api/jobs/${beforeSha}/${afterSha}/cancel`,\n method: 'POST',\n body: {\n link,\n message,\n project: config.project,\n status,\n },\n },\n config,\n { retryCount: 5 },\n logger,\n );\n } catch (error) {\n if (error instanceof ErrorWithStatusCode && error.statusCode === 409) {\n // This API endpoint responds with a 409 when the job has already been\n // completed. This is expected behavior and we can just log the error and\n // continue.\n logger.error(\n 'Skipping cancellation of Happo job because it has already been completed',\n error,\n );\n } else {\n throw error;\n }\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;AAaA,eAAO,UACL,QACA,SACA,QACA,EAAE,WAAW,UAAU,KAAK,GAC5B,QACe;AACf,MAAI;AACF,UAAM;AAAA,MACJ;AAAA,QACE,MAAM,aAAa,SAAS,IAAI,QAAQ;AAAA,QACxC,QAAQ;AAAA,QACR,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA,SAAS,OAAO;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,MACA,EAAE,YAAY,EAAE;AAAA,MAChB;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,QAAI,iBAAiB,uBAAuB,MAAM,eAAe,KAAK;AAIpE,aAAO;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  fetchWithRetry
3
- } from "./chunk-DDC5URHF.js";
3
+ } from "./chunk-L5HPPXAO.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-7EFGHIJ4.js.map
54
+ //# sourceMappingURL=chunk-IIM3SWVI.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/network/makeHappoAPIRequest.ts"],
4
+ "sourcesContent": ["import { SignJWT } from 'jose';\n\nimport type { ConfigWithDefaults } from '../config/index.ts';\nimport type { Logger } from '../isomorphic/types.ts';\nimport fetchWithRetry from './fetchWithRetry.ts';\n\ntype FormDataValue = string | File | undefined;\n\nexport interface RequestAttributes {\n /**\n * The path to the API endpoint\n *\n * @example\n * '/api/snap-requests/with-results'\n */\n path?: `/api/${string}`;\n\n /**\n * The URL to fetch\n *\n * Prefer using the `path` property instead. If both are provided, the `path`\n * property will be used.\n */\n url?: string;\n\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE';\n formData?: Record<string, FormDataValue>;\n body?: unknown;\n json?: boolean;\n}\n\nexport interface MakeHappoAPIRequestOptions {\n /**\n * The timeout in milliseconds\n * @default 60_000\n */\n timeout?: number;\n\n /**\n * The number of times to retry the request\n * @default 0\n */\n retryCount?: number;\n\n /**\n * The minimum timeout in milliseconds\n * @default 1000\n */\n retryMinTimeout?: number;\n\n /**\n * The maximum timeout in milliseconds\n * @default Infinity\n */\n retryMaxTimeout?: number;\n}\n\nasync function signRequest(apiKey: string, apiSecret: string): Promise<string> {\n const encodedSecret = new TextEncoder().encode(apiSecret);\n return await new SignJWT({ key: apiKey })\n .setProtectedHeader({ alg: 'HS256', kid: apiKey })\n .sign(encodedSecret);\n}\n\nexport default async function makeHappoAPIRequest(\n { url, path, method = 'GET', formData, body }: RequestAttributes,\n { apiKey, apiSecret, endpoint }: ConfigWithDefaults,\n {\n retryCount = 0,\n timeout = 60_000,\n retryMinTimeout = 1000,\n retryMaxTimeout = Infinity,\n }: MakeHappoAPIRequestOptions,\n logger: Logger = console,\n): Promise<object | null> {\n const fetchURL = path ? new URL(path, endpoint) : url;\n\n if (!fetchURL) {\n throw new Error(\n 'No fetch URL provided. Either `path` (preferred) or `url` must be provided.',\n );\n }\n\n const signed = await signRequest(apiKey, apiSecret);\n\n const headers = {\n Authorization: `Bearer ${signed}`,\n };\n\n const response = await fetchWithRetry(\n fetchURL,\n {\n method,\n headers,\n formData,\n body,\n timeout,\n retryCount,\n retryMinTimeout,\n retryMaxTimeout,\n },\n logger,\n );\n\n if (response.status === 204) {\n return null;\n }\n\n // We expect API responses to be JSON, so let's parse it as JSON here for\n // convenience.\n const result = await response.json();\n\n if (typeof result !== 'object') {\n throw new TypeError(`Response is not an object: ${JSON.stringify(result)}`);\n }\n\n return result;\n}\n"],
5
+ "mappings": ";;;;;AAAA,SAAS,eAAe;AAyDxB,eAAe,YAAY,QAAgB,WAAoC;AAC7E,QAAM,gBAAgB,IAAI,YAAY,EAAE,OAAO,SAAS;AACxD,SAAO,MAAM,IAAI,QAAQ,EAAE,KAAK,OAAO,CAAC,EACrC,mBAAmB,EAAE,KAAK,SAAS,KAAK,OAAO,CAAC,EAChD,KAAK,aAAa;AACvB;AAEA,eAAO,oBACL,EAAE,KAAK,MAAM,SAAS,OAAO,UAAU,KAAK,GAC5C,EAAE,QAAQ,WAAW,SAAS,GAC9B;AAAA,EACE,aAAa;AAAA,EACb,UAAU;AAAA,EACV,kBAAkB;AAAA,EAClB,kBAAkB;AACpB,GACA,SAAiB,SACO;AACxB,QAAM,WAAW,OAAO,IAAI,IAAI,MAAM,QAAQ,IAAI;AAElD,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,YAAY,QAAQ,SAAS;AAElD,QAAM,UAAU;AAAA,IACd,eAAe,UAAU,MAAM;AAAA,EACjC;AAEA,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,EACF;AAEA,MAAI,SAAS,WAAW,KAAK;AAC3B,WAAO;AAAA,EACT;AAIA,QAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,MAAI,OAAO,WAAW,UAAU;AAC9B,UAAM,IAAI,UAAU,8BAA8B,KAAK,UAAU,MAAM,CAAC,EAAE;AAAA,EAC5E;AAEA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "happo",
4
- version: "6.1.1",
4
+ version: "6.1.3",
5
5
  description: "Catch unexpected visual and accessibility changes and UI bugs",
6
6
  license: "MIT",
7
7
  repository: {
@@ -177,11 +177,11 @@ var package_default = {
177
177
  "vrt"
178
178
  ],
179
179
  engines: {
180
- node: ">=22"
180
+ node: "^22.18.0 || ^23.6.0 || >=24.0.0"
181
181
  }
182
182
  };
183
183
 
184
184
  export {
185
185
  package_default
186
186
  };
187
- //# sourceMappingURL=chunk-5Q6ZJTDL.js.map
187
+ //# sourceMappingURL=chunk-J542RNYK.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../package.json"],
4
- "sourcesContent": ["{\n \"name\": \"happo\",\n \"version\": \"6.1.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 ],\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\"\n }\n}\n"],
4
+ "sourcesContent": ["{\n \"name\": \"happo\",\n \"version\": \"6.1.3\",\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 ],\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"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "./chunk-5Q6ZJTDL.js";
3
+ } from "./chunk-J542RNYK.js";
4
4
 
5
5
  // src/network/fetchWithRetry.ts
6
6
  import asyncRetry from "async-retry";
@@ -91,6 +91,7 @@ async function fetchWithRetry(url, {
91
91
  }
92
92
 
93
93
  export {
94
+ ErrorWithStatusCode,
94
95
  fetchWithRetry
95
96
  };
96
- //# sourceMappingURL=chunk-DDC5URHF.js.map
97
+ //# sourceMappingURL=chunk-L5HPPXAO.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-7EFGHIJ4.js";
3
+ } from "./chunk-IIM3SWVI.js";
4
4
 
5
5
  // src/network/createAsyncComparison.ts
6
6
  function assertResultIsCreateAsyncComparisonResult(result) {
@@ -56,4 +56,4 @@ async function createAsyncComparison(config, {
56
56
  export {
57
57
  createAsyncComparison
58
58
  };
59
- //# sourceMappingURL=chunk-QHIVL6GP.js.map
59
+ //# sourceMappingURL=chunk-QZGCAYHK.js.map
@@ -0,0 +1,10 @@
1
+ import {
2
+ createAsyncComparison
3
+ } from "./chunk-QZGCAYHK.js";
4
+ import "./chunk-IIM3SWVI.js";
5
+ import "./chunk-L5HPPXAO.js";
6
+ import "./chunk-J542RNYK.js";
7
+ export {
8
+ createAsyncComparison as default
9
+ };
10
+ //# sourceMappingURL=createAsyncComparison-URQ67QOH.js.map
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-7EFGHIJ4.js";
4
- import "./chunk-DDC5URHF.js";
5
- import "./chunk-5Q6ZJTDL.js";
3
+ } from "./chunk-IIM3SWVI.js";
4
+ import "./chunk-L5HPPXAO.js";
5
+ import "./chunk-J542RNYK.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-3PTACG33.js.map
41
+ //# sourceMappingURL=createAsyncReport-5DCCM7SL.js.map
package/dist/cli/main.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  } from "./chunk-JTRP4JVC.js";
4
4
  import {
5
5
  fetchWithRetry
6
- } from "./chunk-DDC5URHF.js";
6
+ } from "./chunk-L5HPPXAO.js";
7
7
  import {
8
8
  package_default
9
- } from "./chunk-5Q6ZJTDL.js";
9
+ } from "./chunk-J542RNYK.js";
10
10
 
11
11
  // src/cli/index.ts
12
12
  import path3 from "node:path";
@@ -250,6 +250,21 @@ async function loadConfigFile(configFilePath, environment, logger = console) {
250
250
  }
251
251
  throw error;
252
252
  }
253
+ if (config === null) {
254
+ throw new TypeError(
255
+ `Your Happo config file ${configFilePath} must have a default export that is an object, got: null.`
256
+ );
257
+ }
258
+ if (typeof config !== "object") {
259
+ throw new TypeError(
260
+ `Your Happo config file ${configFilePath} must have a default export that is an object, got: ${typeof config}.`
261
+ );
262
+ }
263
+ if (Array.isArray(config)) {
264
+ throw new TypeError(
265
+ `Your Happo config file ${configFilePath} must have a default export that is an object, got: array.`
266
+ );
267
+ }
253
268
  if (!config.apiKey && process.env.HAPPO_API_KEY) {
254
269
  config.apiKey = process.env.HAPPO_API_KEY;
255
270
  }
@@ -984,7 +999,7 @@ function createReporter(opts = {}) {
984
999
 
985
1000
  // src/cli/index.ts
986
1001
  async function getVersion() {
987
- const packageJson = await import("./package-AAAA77YQ.js");
1002
+ const packageJson = await import("./package-G75AVF5U.js");
988
1003
  return packageJson.default.version;
989
1004
  }
990
1005
  function parseDashdashCommandParts(rawArgs) {
@@ -1174,10 +1189,10 @@ async function main(rawArgs = process.argv, logger = console) {
1174
1189
  async function handleDefaultCommand(config, environment, logger) {
1175
1190
  logger.log("Running happo tests...");
1176
1191
  const [startJob, createAsyncComparison, createAsyncReport, prepareSnapRequests] = await Promise.all([
1177
- (await import("./startJob-EQDJEH4G.js")).default,
1178
- (await import("./createAsyncComparison-JYSUXA2H.js")).default,
1179
- (await import("./createAsyncReport-3PTACG33.js")).default,
1180
- (await import("./prepareSnapRequests-H3UNIE4O.js")).default
1192
+ (await import("./startJob-AWLKOPCZ.js")).default,
1193
+ (await import("./createAsyncComparison-URQ67QOH.js")).default,
1194
+ (await import("./createAsyncReport-5DCCM7SL.js")).default,
1195
+ (await import("./prepareSnapRequests-2MO5YYLT.js")).default
1181
1196
  ]);
1182
1197
  await startJob(config, environment, logger);
1183
1198
  try {
@@ -1198,9 +1213,10 @@ async function handleDefaultCommand(config, environment, logger) {
1198
1213
  logger.log(`[HAPPO] Async comparison URL: ${asyncComparison.compareUrl}`);
1199
1214
  }
1200
1215
  } catch (e) {
1201
- logger.error(e instanceof Error ? e.message : String(e), e);
1202
- const cancelJob = (await import("./cancelJob-3VTBAIZG.js")).default;
1203
- await cancelJob("failure", config, environment, logger);
1216
+ const message = e instanceof Error ? e.message : String(e);
1217
+ logger.error(`${config.integration.type} run failed: ${message}`, e);
1218
+ const cancelJob = (await import("./cancelJob-6HAWZO24.js")).default;
1219
+ await cancelJob("failure", message, config, environment, logger);
1204
1220
  process.exitCode = 1;
1205
1221
  return;
1206
1222
  }
@@ -1210,7 +1226,7 @@ async function handleFinalizeCommand(config, environment, logger) {
1210
1226
  logger.log("Config:", config);
1211
1227
  logger.log("Environment:", environment);
1212
1228
  try {
1213
- const finalizeAll = (await import("./wrapper-RAJYXKL6.js")).finalizeAll;
1229
+ const finalizeAll = (await import("./wrapper-O4GGK6IN.js")).finalizeAll;
1214
1230
  await finalizeAll({ happoConfig: config, environment, logger });
1215
1231
  } catch (e) {
1216
1232
  logger.error(e instanceof Error ? e.message : String(e), e);
@@ -1239,7 +1255,7 @@ async function handleE2ECommand(config, environment, dashdashCommandParts, confi
1239
1255
  logger.log("Config:", config);
1240
1256
  logger.log("Environment:", environment);
1241
1257
  logger.log("Dashdash command parts:", dashdashCommandParts);
1242
- const runWithWrapper = (await import("./wrapper-RAJYXKL6.js")).default;
1258
+ const runWithWrapper = (await import("./wrapper-O4GGK6IN.js")).default;
1243
1259
  const exitCode = await runWithWrapper(
1244
1260
  dashdashCommandParts,
1245
1261
  config,