happo 6.0.4 → 6.0.6

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 (37) hide show
  1. package/dist/cli/{cancelJob-GCTVJGYB.js → cancelJob-NIUI7GBR.js} +4 -3
  2. package/dist/cli/{cancelJob-GCTVJGYB.js.map → cancelJob-NIUI7GBR.js.map} +1 -1
  3. package/dist/cli/{chunk-TPF2272Y.js → chunk-6SJAK2WZ.js} +2 -2
  4. package/dist/cli/chunk-BLNR2H52.js +51 -0
  5. package/dist/cli/chunk-BLNR2H52.js.map +7 -0
  6. package/dist/cli/{chunk-DYCU4INF.js → chunk-FCZLLRXU.js} +8 -8
  7. package/dist/cli/chunk-FCZLLRXU.js.map +7 -0
  8. package/dist/cli/{chunk-TCHC2O3E.js → chunk-NNZOCTDI.js} +3 -48
  9. package/dist/cli/chunk-NNZOCTDI.js.map +7 -0
  10. package/dist/cli/createAsyncComparison-DTUUZUEX.js +10 -0
  11. package/dist/cli/{createAsyncReport-ZIO2Q6SS.js → createAsyncReport-7QIIMSNX.js} +4 -3
  12. package/dist/cli/{createAsyncReport-ZIO2Q6SS.js.map → createAsyncReport-7QIIMSNX.js.map} +1 -1
  13. package/dist/cli/main.d.ts +2 -0
  14. package/dist/cli/main.d.ts.map +1 -0
  15. package/dist/cli/{index.js → main.js} +29 -24
  16. package/dist/cli/main.js.map +7 -0
  17. package/dist/cli/package-BYHQMCNB.js +7 -0
  18. package/dist/cli/{prepareSnapRequests-NPYZG2AI.js → prepareSnapRequests-T6RBWTYD.js} +4 -3
  19. package/dist/cli/{prepareSnapRequests-NPYZG2AI.js.map → prepareSnapRequests-T6RBWTYD.js.map} +1 -1
  20. package/dist/cli/{startJob-T3PWEYOP.js → startJob-74BLUAGF.js} +4 -3
  21. package/dist/cli/{startJob-T3PWEYOP.js.map → startJob-74BLUAGF.js.map} +1 -1
  22. package/dist/cli/{wrapper-WKKUKM7T.js → wrapper-IM3TNBSL.js} +5 -4
  23. package/dist/cli/{wrapper-WKKUKM7T.js.map → wrapper-IM3TNBSL.js.map} +1 -1
  24. package/dist/config/loadConfig.d.ts.map +1 -1
  25. package/dist/cypress/task.js +126 -120
  26. package/dist/cypress/task.js.map +3 -3
  27. package/dist/playwright/index.js +126 -120
  28. package/dist/playwright/index.js.map +3 -3
  29. package/package.json +7 -7
  30. package/dist/cli/chunk-DYCU4INF.js.map +0 -7
  31. package/dist/cli/chunk-TCHC2O3E.js.map +0 -7
  32. package/dist/cli/createAsyncComparison-5X5OBHF2.js +0 -9
  33. package/dist/cli/index.js.map +0 -7
  34. package/dist/cli/package-CB7WD7JO.js +0 -7
  35. /package/dist/cli/{chunk-TPF2272Y.js.map → chunk-6SJAK2WZ.js.map} +0 -0
  36. /package/dist/cli/{createAsyncComparison-5X5OBHF2.js.map → createAsyncComparison-DTUUZUEX.js.map} +0 -0
  37. /package/dist/cli/{package-CB7WD7JO.js.map → package-BYHQMCNB.js.map} +0 -0
@@ -10,119 +10,6 @@ import limitConcur from "limit-concur";
10
10
  // src/config/loadConfig.ts
11
11
  import fs from "node:fs";
12
12
  import { any as findAny } from "empathic/find";
13
- var CONFIG_FILENAMES = [
14
- "happo.config.js",
15
- "happo.config.mjs",
16
- "happo.config.cjs",
17
- "happo.config.ts",
18
- "happo.config.mts",
19
- "happo.config.cts"
20
- ];
21
- var DEFAULT_ENDPOINT = "https://happo.io";
22
- function findConfigFile() {
23
- if (process.env.HAPPO_CONFIG_FILE) {
24
- return process.env.HAPPO_CONFIG_FILE;
25
- }
26
- const configFilePath = findAny(CONFIG_FILENAMES, { cwd: process.cwd() });
27
- if (!configFilePath) {
28
- throw new Error(
29
- "Happo config file could not be found. Please create a config file in the root of your project."
30
- );
31
- }
32
- return configFilePath;
33
- }
34
- function assertIsPullRequestTokenResponse(response) {
35
- if (typeof response !== "object" || response === null || !("secret" in response)) {
36
- throw new TypeError("Unexpected pull request token response");
37
- }
38
- }
39
- async function getPullRequestSecret(endpoint, prUrl) {
40
- const res = await fetch(`${endpoint}/api/pull-request-token`, {
41
- method: "POST",
42
- headers: { "Content-Type": "application/json" },
43
- body: JSON.stringify({ prUrl })
44
- });
45
- if (!res || !res.ok) {
46
- throw new Error(
47
- `Failed to get pull request secret: ${res.status} - ${await res.text()}`
48
- );
49
- }
50
- const json = await res.json();
51
- assertIsPullRequestTokenResponse(json);
52
- return json.secret;
53
- }
54
- async function loadConfigFile(configFilePath, environment, logger = console) {
55
- try {
56
- const stats = await fs.promises.stat(configFilePath);
57
- if (!stats.isFile()) {
58
- throw new Error(`Happo config file path is not a file: ${configFilePath}`);
59
- }
60
- } catch (error) {
61
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
62
- throw new Error(`Happo config file could not be found: ${configFilePath}`);
63
- }
64
- throw error;
65
- }
66
- const config = (await import(configFilePath)).default;
67
- if (!config.apiKey && process.env.HAPPO_API_KEY) {
68
- config.apiKey = process.env.HAPPO_API_KEY;
69
- }
70
- if (!config.apiSecret && process.env.HAPPO_API_SECRET) {
71
- config.apiSecret = process.env.HAPPO_API_SECRET;
72
- }
73
- if (!config.apiKey || !config.apiSecret) {
74
- const missing = [
75
- config.apiKey ? null : "apiKey",
76
- config.apiSecret ? null : "apiSecret"
77
- ].filter(Boolean).map((key) => `\`${key}\``).join(" and ");
78
- if (!environment?.link) {
79
- throw new Error(
80
- `Missing ${missing} in your Happo config. Reference yours at https://happo.io/settings`
81
- );
82
- }
83
- try {
84
- logger.log(
85
- `Missing ${missing} in Happo config. Falling back to pull-request authentication.`
86
- );
87
- config.apiKey = environment.link;
88
- config.apiSecret = await getPullRequestSecret(
89
- config.endpoint || DEFAULT_ENDPOINT,
90
- environment.link
91
- );
92
- } catch (e) {
93
- throw new Error("Failed to obtain temporary pull-request token", { cause: e });
94
- }
95
- }
96
- if (!config.targets) {
97
- config.targets = {
98
- chrome: {
99
- type: "chrome",
100
- viewport: "1024x768"
101
- }
102
- };
103
- }
104
- if (!config.integration) {
105
- config.integration = {
106
- type: "storybook"
107
- };
108
- }
109
- const allTargets = Object.values(config.targets);
110
- for (const target of allTargets) {
111
- target.viewport = target.viewport || "1024x768";
112
- target.freezeAnimations = target.freezeAnimations || "last-frame";
113
- target.prefersReducedMotion = target.prefersReducedMotion ?? true;
114
- }
115
- const configWithDefaults = {
116
- endpoint: DEFAULT_ENDPOINT,
117
- githubApiUrl: "https://api.github.com",
118
- targets: allTargets,
119
- ...config
120
- };
121
- return configWithDefaults;
122
- }
123
-
124
- // src/network/makeHappoAPIRequest.ts
125
- import { SignJWT } from "jose";
126
13
 
127
14
  // src/network/fetchWithRetry.ts
128
15
  import asyncRetry from "async-retry";
@@ -130,7 +17,7 @@ import asyncRetry from "async-retry";
130
17
  // package.json
131
18
  var package_default = {
132
19
  name: "happo",
133
- version: "6.0.4",
20
+ version: "6.0.6",
134
21
  description: "Catch unexpected visual and accessibility changes and UI bugs",
135
22
  license: "MIT",
136
23
  repository: {
@@ -140,7 +27,7 @@ var package_default = {
140
27
  bugs: "https://github.com/happo/happo/issues",
141
28
  homepage: "https://happo.io",
142
29
  bin: {
143
- happo: "dist/cli/index.js"
30
+ happo: "dist/cli/main.js"
144
31
  },
145
32
  type: "module",
146
33
  main: "./dist/config/index.js",
@@ -198,12 +85,12 @@ var package_default = {
198
85
  prepublishOnly: "pnpm clean && pnpm build",
199
86
  "storybook:dev": "storybook dev --config-dir src/storybook/__tests__/storybook-app -p ${PORT:-6007}",
200
87
  test: "node --env-file-if-exists=.env.local ./scripts/test.ts",
201
- "test:custom": "pnpm build:dist && pnpm build:custom && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.custom.config.ts",
202
- "test:cypress": "pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.cypress.config.ts e2e -- cypress run -C src/cypress/__cypress__/cypress.config.ts",
88
+ "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",
89
+ "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",
203
90
  "test:cypress:open": "cypress open -C src/cypress/__cypress__/cypress.config.ts",
204
- "test:playwright": "pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.playwright.config.ts e2e -- playwright test",
205
- "test:storybook": "pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.storybook.config.ts",
206
- "test:pages": "pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/index.js -c ./happoconfigs/happo.pages.config.ts",
91
+ "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",
92
+ "test:storybook": "pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.storybook.config.ts",
93
+ "test:pages": "pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.pages.config.ts",
207
94
  tsc: "tsc --build tsconfig.json"
208
95
  },
209
96
  browserslist: {
@@ -397,7 +284,126 @@ async function fetchWithRetry(url, {
397
284
  );
398
285
  }
399
286
 
287
+ // src/config/loadConfig.ts
288
+ var CONFIG_FILENAMES = [
289
+ "happo.config.js",
290
+ "happo.config.mjs",
291
+ "happo.config.cjs",
292
+ "happo.config.ts",
293
+ "happo.config.mts",
294
+ "happo.config.cts"
295
+ ];
296
+ var DEFAULT_ENDPOINT = "https://happo.io";
297
+ function findConfigFile() {
298
+ if (process.env.HAPPO_CONFIG_FILE) {
299
+ return process.env.HAPPO_CONFIG_FILE;
300
+ }
301
+ const configFilePath = findAny(CONFIG_FILENAMES, { cwd: process.cwd() });
302
+ if (!configFilePath) {
303
+ throw new Error(
304
+ "Happo config file could not be found. Please create a config file in the root of your project."
305
+ );
306
+ }
307
+ return configFilePath;
308
+ }
309
+ function assertIsPullRequestTokenResponse(response) {
310
+ if (typeof response !== "object" || response === null || !("secret" in response)) {
311
+ throw new TypeError("Unexpected pull request token response");
312
+ }
313
+ }
314
+ async function getPullRequestSecret(endpoint, prUrl, logger) {
315
+ const url = new URL("/api/pull-request-token", endpoint);
316
+ const res = await fetchWithRetry(
317
+ url,
318
+ {
319
+ method: "POST",
320
+ body: { prUrl },
321
+ retryCount: 3
322
+ },
323
+ logger
324
+ );
325
+ if (!res || !res.ok) {
326
+ throw new Error(
327
+ `Failed to get pull request secret: ${res.status} - ${await res.text()}`
328
+ );
329
+ }
330
+ const json = await res.json();
331
+ assertIsPullRequestTokenResponse(json);
332
+ return json.secret;
333
+ }
334
+ async function loadConfigFile(configFilePath, environment, logger = console) {
335
+ try {
336
+ const stats = await fs.promises.stat(configFilePath);
337
+ if (!stats.isFile()) {
338
+ throw new Error(`Happo config file path is not a file: ${configFilePath}`);
339
+ }
340
+ } catch (error) {
341
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
342
+ throw new Error(`Happo config file could not be found: ${configFilePath}`);
343
+ }
344
+ throw error;
345
+ }
346
+ const config = (await import(configFilePath)).default;
347
+ if (!config.apiKey && process.env.HAPPO_API_KEY) {
348
+ config.apiKey = process.env.HAPPO_API_KEY;
349
+ }
350
+ if (!config.apiSecret && process.env.HAPPO_API_SECRET) {
351
+ config.apiSecret = process.env.HAPPO_API_SECRET;
352
+ }
353
+ if (!config.apiKey || !config.apiSecret) {
354
+ const missing = [
355
+ config.apiKey ? null : "apiKey",
356
+ config.apiSecret ? null : "apiSecret"
357
+ ].filter(Boolean).map((key) => `\`${key}\``).join(" and ");
358
+ if (!environment?.link) {
359
+ throw new Error(
360
+ `Missing ${missing} in your Happo config. Reference yours at https://happo.io/settings`
361
+ );
362
+ }
363
+ try {
364
+ logger.log(
365
+ `Missing ${missing} in Happo config. Falling back to pull-request authentication.`
366
+ );
367
+ config.apiKey = environment.link;
368
+ config.apiSecret = await getPullRequestSecret(
369
+ config.endpoint || DEFAULT_ENDPOINT,
370
+ environment.link,
371
+ logger
372
+ );
373
+ } catch (e) {
374
+ throw new Error("Failed to obtain temporary pull-request token", { cause: e });
375
+ }
376
+ }
377
+ if (!config.targets) {
378
+ config.targets = {
379
+ chrome: {
380
+ type: "chrome",
381
+ viewport: "1024x768"
382
+ }
383
+ };
384
+ }
385
+ if (!config.integration) {
386
+ config.integration = {
387
+ type: "storybook"
388
+ };
389
+ }
390
+ const allTargets = Object.values(config.targets);
391
+ for (const target of allTargets) {
392
+ target.viewport = target.viewport || "1024x768";
393
+ target.freezeAnimations = target.freezeAnimations || "last-frame";
394
+ target.prefersReducedMotion = target.prefersReducedMotion ?? true;
395
+ }
396
+ const configWithDefaults = {
397
+ endpoint: DEFAULT_ENDPOINT,
398
+ githubApiUrl: "https://api.github.com",
399
+ targets: allTargets,
400
+ ...config
401
+ };
402
+ return configWithDefaults;
403
+ }
404
+
400
405
  // src/network/makeHappoAPIRequest.ts
406
+ import { SignJWT } from "jose";
401
407
  async function signRequest(apiKey, apiSecret) {
402
408
  const encodedSecret = new TextEncoder().encode(apiSecret);
403
409
  return await new SignJWT({ key: apiKey }).setProtectedHeader({ alg: "HS256", kid: apiKey }).sign(encodedSecret);