happo 6.2.1 → 6.2.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 (38) hide show
  1. package/dist/cli/{cancelJob-34KDCTGT.js → cancelJob-SCH4KW2U.js} +4 -4
  2. package/dist/cli/{chunk-ZXXG64S7.js → chunk-45CRUCYS.js} +4 -3
  3. package/dist/cli/chunk-45CRUCYS.js.map +7 -0
  4. package/dist/cli/{chunk-445APGT2.js → chunk-4JARS643.js} +2 -2
  5. package/dist/cli/{chunk-6MGOAPUC.js → chunk-F24YIN3G.js} +2 -2
  6. package/dist/cli/{chunk-OXPEW4ED.js → chunk-MGD7RXBX.js} +2 -2
  7. package/dist/cli/chunk-X4TE2VNY.js +124 -0
  8. package/dist/cli/chunk-X4TE2VNY.js.map +7 -0
  9. package/dist/cli/createAsyncComparison-2FVFP4R2.js +10 -0
  10. package/dist/cli/{createAsyncReport-QSCFNEYV.js → createAsyncReport-3MQXEVMB.js} +4 -4
  11. package/dist/cli/main.js +20 -10
  12. package/dist/cli/main.js.map +2 -2
  13. package/dist/cli/package-46PKZYUO.js +7 -0
  14. package/dist/cli/postGitHubComment-HUEB7LIV.js +7 -0
  15. package/dist/cli/postGitHubComment-HUEB7LIV.js.map +7 -0
  16. package/dist/cli/{prepareSnapRequests-D5UPE4KB.js → prepareSnapRequests-NUFQ2CFV.js} +4 -4
  17. package/dist/cli/{startJob-MKJ2YHWF.js → startJob-WHA3HOB4.js} +4 -4
  18. package/dist/cli/{wrapper-UVU6GCPM.js → wrapper-W3LDE6K7.js} +8 -127
  19. package/dist/cli/wrapper-W3LDE6K7.js.map +7 -0
  20. package/dist/cypress/task.js +3 -2
  21. package/dist/cypress/task.js.map +2 -2
  22. package/dist/playwright/index.js +3 -2
  23. package/dist/playwright/index.js.map +2 -2
  24. package/package.json +3 -2
  25. package/preset.js +5 -0
  26. package/dist/cli/chunk-ZXXG64S7.js.map +0 -7
  27. package/dist/cli/createAsyncComparison-43QCPIZG.js +0 -10
  28. package/dist/cli/package-ACDN7UPE.js +0 -7
  29. package/dist/cli/wrapper-UVU6GCPM.js.map +0 -7
  30. /package/dist/cli/{cancelJob-34KDCTGT.js.map → cancelJob-SCH4KW2U.js.map} +0 -0
  31. /package/dist/cli/{chunk-445APGT2.js.map → chunk-4JARS643.js.map} +0 -0
  32. /package/dist/cli/{chunk-6MGOAPUC.js.map → chunk-F24YIN3G.js.map} +0 -0
  33. /package/dist/cli/{chunk-OXPEW4ED.js.map → chunk-MGD7RXBX.js.map} +0 -0
  34. /package/dist/cli/{createAsyncComparison-43QCPIZG.js.map → createAsyncComparison-2FVFP4R2.js.map} +0 -0
  35. /package/dist/cli/{createAsyncReport-QSCFNEYV.js.map → createAsyncReport-3MQXEVMB.js.map} +0 -0
  36. /package/dist/cli/{package-ACDN7UPE.js.map → package-46PKZYUO.js.map} +0 -0
  37. /package/dist/cli/{prepareSnapRequests-D5UPE4KB.js.map → prepareSnapRequests-NUFQ2CFV.js.map} +0 -0
  38. /package/dist/cli/{startJob-MKJ2YHWF.js.map → startJob-WHA3HOB4.js.map} +0 -0
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-445APGT2.js";
3
+ } from "./chunk-4JARS643.js";
4
4
  import {
5
5
  ErrorWithStatusCode
6
- } from "./chunk-OXPEW4ED.js";
7
- import "./chunk-ZXXG64S7.js";
6
+ } from "./chunk-MGD7RXBX.js";
7
+ import "./chunk-45CRUCYS.js";
8
8
 
9
9
  // src/network/cancelJob.ts
10
10
  async function cancelJob(status, message, config, { beforeSha, afterSha, link }, logger) {
@@ -38,4 +38,4 @@ async function cancelJob(status, message, config, { beforeSha, afterSha, link },
38
38
  export {
39
39
  cancelJob as default
40
40
  };
41
- //# sourceMappingURL=cancelJob-34KDCTGT.js.map
41
+ //# sourceMappingURL=cancelJob-SCH4KW2U.js.map
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "happo",
4
- version: "6.2.1",
4
+ version: "6.2.3",
5
5
  description: "Catch unexpected visual and accessibility changes and UI bugs",
6
6
  license: "MIT",
7
7
  repository: {
@@ -55,7 +55,8 @@ var package_default = {
55
55
  }
56
56
  },
57
57
  files: [
58
- "dist"
58
+ "dist",
59
+ "preset.js"
59
60
  ],
60
61
  scripts: {
61
62
  all: "node ./scripts/allchecks.ts",
@@ -184,4 +185,4 @@ var package_default = {
184
185
  export {
185
186
  package_default
186
187
  };
187
- //# sourceMappingURL=chunk-ZXXG64S7.js.map
188
+ //# sourceMappingURL=chunk-45CRUCYS.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../package.json"],
4
+ "sourcesContent": ["{\n \"name\": \"happo\",\n \"version\": \"6.2.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 \"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"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  fetchWithRetry
3
- } from "./chunk-OXPEW4ED.js";
3
+ } from "./chunk-MGD7RXBX.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-445APGT2.js.map
54
+ //# sourceMappingURL=chunk-4JARS643.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-445APGT2.js";
3
+ } from "./chunk-4JARS643.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-6MGOAPUC.js.map
59
+ //# sourceMappingURL=chunk-F24YIN3G.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "./chunk-ZXXG64S7.js";
3
+ } from "./chunk-45CRUCYS.js";
4
4
 
5
5
  // src/network/fetchWithRetry.ts
6
6
  import asyncRetry from "async-retry";
@@ -94,4 +94,4 @@ export {
94
94
  ErrorWithStatusCode,
95
95
  fetchWithRetry
96
96
  };
97
- //# sourceMappingURL=chunk-OXPEW4ED.js.map
97
+ //# sourceMappingURL=chunk-MGD7RXBX.js.map
@@ -0,0 +1,124 @@
1
+ // src/network/postGitHubComment.ts
2
+ var REPO_URL_MATCHER = /https?:\/\/[^/]+\/([^/]+)\/([^/]+)\/pull\/([0-9]+)/;
3
+ var HAPPO_COMMENT_MARKER = "<!-- happo-comment -->";
4
+ var HAPPO_USER_AGENT = "Happo client";
5
+ async function deleteExistingComments(normalizedGithubApiUrl, owner, repo, prNumber, authHeader) {
6
+ const commentsRes = await fetch(
7
+ `${normalizedGithubApiUrl}/repos/${owner}/${repo}/issues/${prNumber}/comments`,
8
+ {
9
+ headers: {
10
+ "User-Agent": HAPPO_USER_AGENT,
11
+ Authorization: authHeader
12
+ },
13
+ method: "GET"
14
+ }
15
+ );
16
+ if (!commentsRes.ok) {
17
+ throw new Error(
18
+ `Failed to fetch existing comments: ${commentsRes.status} ${await commentsRes.text()}`
19
+ );
20
+ }
21
+ const comments = await commentsRes.json();
22
+ if (!Array.isArray(comments)) {
23
+ throw new TypeError("Comments is not an array");
24
+ }
25
+ const happoComments = comments.filter((comment) => {
26
+ if (typeof comment !== "object" || comment === null) {
27
+ return false;
28
+ }
29
+ if (!("body" in comment)) {
30
+ return false;
31
+ }
32
+ if (typeof comment.body !== "string") {
33
+ return false;
34
+ }
35
+ return comment.body.startsWith(HAPPO_COMMENT_MARKER);
36
+ });
37
+ console.log(
38
+ `[HAPPO] Found ${happoComments.length} happo comments to delete out of a total of ${comments.length} comments on the PR.`
39
+ );
40
+ await Promise.all(
41
+ happoComments.map(async (comment) => {
42
+ const res = await fetch(
43
+ `${normalizedGithubApiUrl}/repos/${owner}/${repo}/issues/comments/${comment.id}`,
44
+ {
45
+ method: "DELETE",
46
+ headers: {
47
+ "User-Agent": HAPPO_USER_AGENT,
48
+ Authorization: authHeader
49
+ }
50
+ }
51
+ );
52
+ if (!res.ok) {
53
+ throw new Error(`HTTP ${res.status}: ${await res.text()}`);
54
+ }
55
+ return res;
56
+ })
57
+ );
58
+ }
59
+ async function postGitHubComment({
60
+ githubApiUrl,
61
+ statusImageUrl,
62
+ compareUrl,
63
+ link,
64
+ authToken
65
+ }) {
66
+ const matches = link.match(REPO_URL_MATCHER);
67
+ if (!matches) {
68
+ console.log(
69
+ `[HAPPO] URL does not look like a github PR URL: ${link}. Skipping github comment posting...`
70
+ );
71
+ return false;
72
+ }
73
+ const owner = matches[1];
74
+ const repo = matches[2];
75
+ const prNumber = Number.parseInt(matches[3] || "", 10);
76
+ if (!owner) {
77
+ throw new Error("Missing owner");
78
+ }
79
+ if (!repo) {
80
+ throw new Error("Missing repo");
81
+ }
82
+ if (Number.isNaN(prNumber)) {
83
+ throw new TypeError("PR number is not a number");
84
+ }
85
+ const normalizedGithubApiUrl = githubApiUrl.replace(/\/$/, "");
86
+ const authHeader = `Bearer ${authToken}`;
87
+ console.log("[HAPPO] Deleting existing happo comments...");
88
+ await deleteExistingComments(
89
+ normalizedGithubApiUrl,
90
+ owner,
91
+ repo,
92
+ prNumber,
93
+ authHeader
94
+ );
95
+ const body = `${HAPPO_COMMENT_MARKER}
96
+ [![Happo status](${statusImageUrl})](${compareUrl})`;
97
+ const res = await fetch(
98
+ `${normalizedGithubApiUrl}/repos/${owner}/${repo}/issues/${prNumber}/comments`,
99
+ {
100
+ method: "POST",
101
+ headers: {
102
+ "User-Agent": HAPPO_USER_AGENT,
103
+ Authorization: authHeader,
104
+ "Content-Type": "application/json"
105
+ },
106
+ body: JSON.stringify({ body })
107
+ }
108
+ );
109
+ if (!res.ok) {
110
+ throw new Error(
111
+ `Failed to post github comment: ${res.status} ${await res.text()}`
112
+ );
113
+ }
114
+ console.log(
115
+ `[HAPPO] Posted github comment successfully. Response is`,
116
+ await res.json()
117
+ );
118
+ return true;
119
+ }
120
+
121
+ export {
122
+ postGitHubComment
123
+ };
124
+ //# sourceMappingURL=chunk-X4TE2VNY.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/network/postGitHubComment.ts"],
4
+ "sourcesContent": ["const REPO_URL_MATCHER = /https?:\\/\\/[^/]+\\/([^/]+)\\/([^/]+)\\/pull\\/([0-9]+)/;\n// https://github.com/lightstep/lightstep/pull/6555\n\nconst HAPPO_COMMENT_MARKER = '<!-- happo-comment -->';\n\nconst HAPPO_USER_AGENT = 'Happo client';\n\nasync function deleteExistingComments(\n normalizedGithubApiUrl: string,\n owner: string,\n repo: string,\n prNumber: number,\n authHeader: string,\n) {\n const commentsRes = await fetch(\n `${normalizedGithubApiUrl}/repos/${owner}/${repo}/issues/${prNumber}/comments`,\n {\n headers: {\n 'User-Agent': HAPPO_USER_AGENT,\n Authorization: authHeader,\n },\n method: 'GET',\n },\n );\n\n if (!commentsRes.ok) {\n throw new Error(\n `Failed to fetch existing comments: ${commentsRes.status} ${await commentsRes.text()}`,\n );\n }\n\n const comments = await commentsRes.json();\n if (!Array.isArray(comments)) {\n throw new TypeError('Comments is not an array');\n }\n const happoComments = comments.filter((comment: unknown) => {\n if (typeof comment !== 'object' || comment === null) {\n return false;\n }\n if (!('body' in comment)) {\n return false;\n }\n if (typeof comment.body !== 'string') {\n return false;\n }\n return comment.body.startsWith(HAPPO_COMMENT_MARKER);\n });\n\n console.log(\n `[HAPPO] Found ${happoComments.length} happo comments to delete out of a total of ${comments.length} comments on the PR.`,\n );\n\n await Promise.all(\n happoComments.map(async (comment) => {\n const res = await fetch(\n `${normalizedGithubApiUrl}/repos/${owner}/${repo}/issues/comments/${comment.id}`,\n {\n method: 'DELETE',\n headers: {\n 'User-Agent': HAPPO_USER_AGENT,\n Authorization: authHeader,\n },\n },\n );\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}: ${await res.text()}`);\n }\n return res;\n }),\n );\n}\n\ninterface PostGitHubCommentOptions {\n githubApiUrl: string;\n statusImageUrl: string;\n compareUrl: string;\n link: string;\n authToken?: string | undefined;\n}\n\nexport default async function postGitHubComment({\n githubApiUrl,\n statusImageUrl,\n compareUrl,\n link,\n authToken,\n}: PostGitHubCommentOptions): Promise<boolean> {\n const matches = link.match(REPO_URL_MATCHER);\n if (!matches) {\n console.log(\n `[HAPPO] URL does not look like a github PR URL: ${link}. Skipping github comment posting...`,\n );\n return false;\n }\n\n const owner = matches[1];\n const repo = matches[2];\n const prNumber = Number.parseInt(matches[3] || '', 10);\n\n if (!owner) {\n throw new Error('Missing owner');\n }\n if (!repo) {\n throw new Error('Missing repo');\n }\n if (Number.isNaN(prNumber)) {\n throw new TypeError('PR number is not a number');\n }\n\n const normalizedGithubApiUrl = githubApiUrl.replace(/\\/$/, '');\n\n const authHeader = `Bearer ${authToken}`;\n\n console.log('[HAPPO] Deleting existing happo comments...');\n await deleteExistingComments(\n normalizedGithubApiUrl,\n owner,\n repo,\n prNumber,\n authHeader,\n );\n\n const body = `${HAPPO_COMMENT_MARKER}\\n[![Happo status](${statusImageUrl})](${compareUrl})`;\n const res = await fetch(\n `${normalizedGithubApiUrl}/repos/${owner}/${repo}/issues/${prNumber}/comments`,\n {\n method: 'POST',\n headers: {\n 'User-Agent': HAPPO_USER_AGENT,\n Authorization: authHeader,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ body }),\n },\n );\n if (!res.ok) {\n throw new Error(\n `Failed to post github comment: ${res.status} ${await res.text()}`,\n );\n }\n\n console.log(\n `[HAPPO] Posted github comment successfully. Response is`,\n await res.json(),\n );\n\n return true;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,10 @@
1
+ import {
2
+ createAsyncComparison
3
+ } from "./chunk-F24YIN3G.js";
4
+ import "./chunk-4JARS643.js";
5
+ import "./chunk-MGD7RXBX.js";
6
+ import "./chunk-45CRUCYS.js";
7
+ export {
8
+ createAsyncComparison as default
9
+ };
10
+ //# sourceMappingURL=createAsyncComparison-2FVFP4R2.js.map
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  makeHappoAPIRequest
3
- } from "./chunk-445APGT2.js";
4
- import "./chunk-OXPEW4ED.js";
5
- import "./chunk-ZXXG64S7.js";
3
+ } from "./chunk-4JARS643.js";
4
+ import "./chunk-MGD7RXBX.js";
5
+ import "./chunk-45CRUCYS.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-QSCFNEYV.js.map
41
+ //# sourceMappingURL=createAsyncReport-3MQXEVMB.js.map
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-OXPEW4ED.js";
7
+ } from "./chunk-MGD7RXBX.js";
8
8
  import {
9
9
  package_default
10
- } from "./chunk-ZXXG64S7.js";
10
+ } from "./chunk-45CRUCYS.js";
11
11
 
12
12
  // src/cli/index.ts
13
13
  import path3 from "node:path";
@@ -1000,7 +1000,7 @@ function createReporter(opts = {}) {
1000
1000
 
1001
1001
  // src/cli/index.ts
1002
1002
  async function getVersion() {
1003
- const packageJson = await import("./package-ACDN7UPE.js");
1003
+ const packageJson = await import("./package-46PKZYUO.js");
1004
1004
  return packageJson.default.version;
1005
1005
  }
1006
1006
  function parseDashdashCommandParts(rawArgs) {
@@ -1190,10 +1190,10 @@ async function main(rawArgs = process.argv, logger = console) {
1190
1190
  async function handleDefaultCommand(config, environment, logger) {
1191
1191
  logger.log("Running happo tests...");
1192
1192
  const [startJob, createAsyncComparison, createAsyncReport, prepareSnapRequests] = await Promise.all([
1193
- (await import("./startJob-MKJ2YHWF.js")).default,
1194
- (await import("./createAsyncComparison-43QCPIZG.js")).default,
1195
- (await import("./createAsyncReport-QSCFNEYV.js")).default,
1196
- (await import("./prepareSnapRequests-D5UPE4KB.js")).default
1193
+ (await import("./startJob-WHA3HOB4.js")).default,
1194
+ (await import("./createAsyncComparison-2FVFP4R2.js")).default,
1195
+ (await import("./createAsyncReport-3MQXEVMB.js")).default,
1196
+ (await import("./prepareSnapRequests-NUFQ2CFV.js")).default
1197
1197
  ]);
1198
1198
  await startJob(config, environment, logger);
1199
1199
  try {
@@ -1212,11 +1212,21 @@ async function handleDefaultCommand(config, environment, logger) {
1212
1212
  logger
1213
1213
  );
1214
1214
  logger.log(`[HAPPO] Async comparison URL: ${asyncComparison.compareUrl}`);
1215
+ if (environment.link && environment.githubToken && config.githubApiUrl) {
1216
+ const postGitHubComment = (await import("./postGitHubComment-HUEB7LIV.js")).default;
1217
+ await postGitHubComment({
1218
+ authToken: environment.githubToken,
1219
+ link: environment.link,
1220
+ statusImageUrl: asyncComparison.statusImageUrl,
1221
+ compareUrl: asyncComparison.compareUrl,
1222
+ githubApiUrl: config.githubApiUrl
1223
+ });
1224
+ }
1215
1225
  }
1216
1226
  } catch (e) {
1217
1227
  const message = e instanceof Error ? e.message : String(e);
1218
1228
  logger.error(`${config.integration.type} run failed: ${message}`, e);
1219
- const cancelJob = (await import("./cancelJob-34KDCTGT.js")).default;
1229
+ const cancelJob = (await import("./cancelJob-SCH4KW2U.js")).default;
1220
1230
  await cancelJob("failure", message, config, environment, logger);
1221
1231
  process.exitCode = 1;
1222
1232
  return;
@@ -1227,7 +1237,7 @@ async function handleFinalizeCommand(config, environment, logger) {
1227
1237
  logger.log("Config:", config);
1228
1238
  logger.log("Environment:", environment);
1229
1239
  try {
1230
- const finalizeAll = (await import("./wrapper-UVU6GCPM.js")).finalizeAll;
1240
+ const finalizeAll = (await import("./wrapper-W3LDE6K7.js")).finalizeAll;
1231
1241
  await finalizeAll({ happoConfig: config, environment, logger });
1232
1242
  } catch (e) {
1233
1243
  logger.error(e instanceof Error ? e.message : String(e), e);
@@ -1256,7 +1266,7 @@ async function handleE2ECommand(config, environment, dashdashCommandParts, confi
1256
1266
  logger.log("Config:", config);
1257
1267
  logger.log("Environment:", environment);
1258
1268
  logger.log("Dashdash command parts:", dashdashCommandParts);
1259
- const runWithWrapper = (await import("./wrapper-UVU6GCPM.js")).default;
1269
+ const runWithWrapper = (await import("./wrapper-W3LDE6K7.js")).default;
1260
1270
  const exitCode = await runWithWrapper(
1261
1271
  dashdashCommandParts,
1262
1272
  config,