happo 6.9.0 → 6.10.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 (95) hide show
  1. package/dist/cli/cancelJob-4I7RBUQG.js +10 -0
  2. package/dist/cli/{chunk-P4EXA4AX.js → chunk-64XRFVHC.js} +8 -4
  3. package/dist/cli/chunk-64XRFVHC.js.map +7 -0
  4. package/dist/cli/{chunk-J2EA5OBW.js → chunk-GG7D7TQZ.js} +2 -2
  5. package/dist/cli/chunk-ML3Z5Z22.js +44 -0
  6. package/dist/cli/chunk-ML3Z5Z22.js.map +7 -0
  7. package/dist/cli/{chunk-BK32666K.js → chunk-OCKO64S4.js} +3 -3
  8. package/dist/cli/{chunk-R6YURZXU.js → chunk-RJXHIGT5.js} +2 -2
  9. package/dist/cli/{chunk-BESQLM5F.js → chunk-UTRRH3WF.js} +2 -2
  10. package/dist/cli/{chunk-CVX5DVCT.js → chunk-XZTQZZFK.js} +2 -2
  11. package/dist/cli/createAsyncComparison-WLPUS2NJ.js +10 -0
  12. package/dist/cli/{createAsyncReport-4ZD53TJC.js → createAsyncReport-2ZTQOHDA.js} +4 -4
  13. package/dist/cli/createExtendsReportSnapRequest-4ZSBNCPL.js +32 -0
  14. package/dist/cli/createExtendsReportSnapRequest-4ZSBNCPL.js.map +7 -0
  15. package/dist/cli/findBaselineReport-2SHS2OH7.js +36 -0
  16. package/dist/cli/findBaselineReport-2SHS2OH7.js.map +7 -0
  17. package/dist/cli/{getFlakes-6ZGTWZTM.js → getFlakes-DLKH2VLM.js} +4 -4
  18. package/dist/cli/index.d.ts.map +1 -1
  19. package/dist/cli/main.js +160 -19
  20. package/dist/cli/main.js.map +3 -3
  21. package/dist/cli/package-TU7REKQ6.js +7 -0
  22. package/dist/cli/parseOptions.d.ts +6 -0
  23. package/dist/cli/parseOptions.d.ts.map +1 -1
  24. package/dist/cli/{prepareSnapRequests-2LHSGFZV.js → prepareSnapRequests-WBXFGB4B.js} +170 -65
  25. package/dist/cli/prepareSnapRequests-WBXFGB4B.js.map +7 -0
  26. package/dist/cli/startJob-33HGTT4N.js +10 -0
  27. package/dist/cli/{wrapper-7RE2N7Y3.js → wrapper-CCHBHKT2.js} +45 -26
  28. package/dist/cli/wrapper-CCHBHKT2.js.map +7 -0
  29. package/dist/config/index.d.ts +0 -8
  30. package/dist/config/index.d.ts.map +1 -1
  31. package/dist/config/index.js.map +2 -2
  32. package/dist/custom/index.d.ts.map +1 -1
  33. package/dist/custom/index.js +70 -14
  34. package/dist/custom/index.js.map +3 -3
  35. package/dist/cypress/chunk-TYBGAHYH.js +69 -0
  36. package/dist/cypress/chunk-TYBGAHYH.js.map +7 -0
  37. package/dist/cypress/index.d.ts.map +1 -1
  38. package/dist/cypress/index.js +14 -4
  39. package/dist/cypress/index.js.map +2 -2
  40. package/dist/cypress/task.d.ts +4 -2
  41. package/dist/cypress/task.d.ts.map +1 -1
  42. package/dist/cypress/task.js +25 -6
  43. package/dist/cypress/task.js.map +4 -4
  44. package/dist/e2e/wrapper.d.ts +1 -1
  45. package/dist/e2e/wrapper.d.ts.map +1 -1
  46. package/dist/environment/index.d.ts +2 -1
  47. package/dist/environment/index.d.ts.map +1 -1
  48. package/dist/isomorphic/parseOnly.d.ts +15 -0
  49. package/dist/isomorphic/parseOnly.d.ts.map +1 -0
  50. package/dist/isomorphic/parseSkip.d.ts +28 -0
  51. package/dist/isomorphic/parseSkip.d.ts.map +1 -0
  52. package/dist/isomorphic/types.d.ts +11 -0
  53. package/dist/isomorphic/types.d.ts.map +1 -1
  54. package/dist/network/createExtendsReportSnapRequest.d.ts +4 -0
  55. package/dist/network/createExtendsReportSnapRequest.d.ts.map +1 -0
  56. package/dist/network/findBaselineReport.d.ts +5 -0
  57. package/dist/network/findBaselineReport.d.ts.map +1 -0
  58. package/dist/network/prepareSnapRequests.d.ts +9 -1
  59. package/dist/network/prepareSnapRequests.d.ts.map +1 -1
  60. package/dist/playwright/index.d.ts.map +1 -1
  61. package/dist/playwright/index.js +59 -3
  62. package/dist/playwright/index.js.map +3 -3
  63. package/dist/storybook/browser/register.d.ts +2 -1
  64. package/dist/storybook/browser/register.d.ts.map +1 -1
  65. package/dist/storybook/browser/register.js +5 -1
  66. package/dist/storybook/browser/register.js.map +2 -2
  67. package/dist/storybook/index.d.ts +9 -1
  68. package/dist/storybook/index.d.ts.map +1 -1
  69. package/dist/storybook/index.js +134 -42
  70. package/dist/storybook/index.js.map +4 -4
  71. package/dist/storybook/isomorphic/types.d.ts +4 -0
  72. package/dist/storybook/isomorphic/types.d.ts.map +1 -1
  73. package/dist/storybook/resolveStoryFileItems.d.ts +21 -0
  74. package/dist/storybook/resolveStoryFileItems.d.ts.map +1 -0
  75. package/package.json +7 -3
  76. package/dist/cli/cancelJob-Y4WJCCU6.js +0 -10
  77. package/dist/cli/chunk-P4EXA4AX.js.map +0 -7
  78. package/dist/cli/createAsyncComparison-CQLGQXY2.js +0 -10
  79. package/dist/cli/package-4NRNRUE3.js +0 -7
  80. package/dist/cli/prepareSnapRequests-2LHSGFZV.js.map +0 -7
  81. package/dist/cli/startJob-JAO5FUA2.js +0 -10
  82. package/dist/cli/wrapper-7RE2N7Y3.js.map +0 -7
  83. package/dist/cypress/chunk-RKK2MPML.js +0 -20
  84. package/dist/cypress/chunk-RKK2MPML.js.map +0 -7
  85. /package/dist/cli/{cancelJob-Y4WJCCU6.js.map → cancelJob-4I7RBUQG.js.map} +0 -0
  86. /package/dist/cli/{chunk-J2EA5OBW.js.map → chunk-GG7D7TQZ.js.map} +0 -0
  87. /package/dist/cli/{chunk-BK32666K.js.map → chunk-OCKO64S4.js.map} +0 -0
  88. /package/dist/cli/{chunk-R6YURZXU.js.map → chunk-RJXHIGT5.js.map} +0 -0
  89. /package/dist/cli/{chunk-BESQLM5F.js.map → chunk-UTRRH3WF.js.map} +0 -0
  90. /package/dist/cli/{chunk-CVX5DVCT.js.map → chunk-XZTQZZFK.js.map} +0 -0
  91. /package/dist/cli/{createAsyncComparison-CQLGQXY2.js.map → createAsyncComparison-WLPUS2NJ.js.map} +0 -0
  92. /package/dist/cli/{createAsyncReport-4ZD53TJC.js.map → createAsyncReport-2ZTQOHDA.js.map} +0 -0
  93. /package/dist/cli/{getFlakes-6ZGTWZTM.js.map → getFlakes-DLKH2VLM.js.map} +0 -0
  94. /package/dist/cli/{package-4NRNRUE3.js.map → package-TU7REKQ6.js.map} +0 -0
  95. /package/dist/cli/{startJob-JAO5FUA2.js.map → startJob-33HGTT4N.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import type { Channel } from 'storybook/internal/channels';
2
2
  import type { StoryStore } from 'storybook/internal/preview-api';
3
- import type { SkipItems } from '../isomorphic/types.ts';
3
+ import type { OnlyItems, SkipItems } from '../isomorphic/types.ts';
4
4
  interface HappoTime {
5
5
  originalDateNow: typeof Date.now;
6
6
  originalSetTimeout: typeof setTimeout;
@@ -8,6 +8,7 @@ interface HappoTime {
8
8
  declare global {
9
9
  var happoTime: HappoTime | undefined;
10
10
  var happoSkipped: SkipItems | undefined;
11
+ var happoOnly: OnlyItems | null | undefined;
11
12
  var __IS_HAPPO_RUN: boolean | undefined;
12
13
  var __STORYBOOK_CLIENT_API__: {
13
14
  _storyStore: StoryStore<any>;
@@ -1 +1 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../src/storybook/browser/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAOjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGxD,UAAU,SAAS;IACjB,eAAe,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC;IACjC,kBAAkB,EAAE,OAAO,UAAU,CAAC;CACvC;AAED,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IACrC,IAAI,YAAY,EAAE,SAAS,GAAG,SAAS,CAAC;IACxC,IAAI,cAAc,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,IAAI,wBAAwB,EACxB;QAEE,WAAW,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;KAC9B,GACD,SAAS,CAAC;IACd,IAAI,qBAAqB,EACrB;QAEE,eAAe,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;KAClC,GACD,SAAS,CAAC;IACd,IAAI,4BAA4B,EAAE,OAAO,GAAG,SAAS,CAAC;CACvD;AA2bD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CA2B5D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEnD;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE1D;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GACvD,IAAI,CAEN;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEnE;AAED,eAAO,MAAM,UAAU,QAAO,OAA6C,CAAC"}
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../src/storybook/browser/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAOjE,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGnE,UAAU,SAAS;IACjB,eAAe,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC;IACjC,kBAAkB,EAAE,OAAO,UAAU,CAAC;CACvC;AAED,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IACrC,IAAI,YAAY,EAAE,SAAS,GAAG,SAAS,CAAC;IACxC,IAAI,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5C,IAAI,cAAc,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,IAAI,wBAAwB,EACxB;QAEE,WAAW,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;KAC9B,GACD,SAAS,CAAC;IACd,IAAI,qBAAqB,EACrB;QAEE,eAAe,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;KAClC,GACD,SAAS,CAAC;IACd,IAAI,4BAA4B,EAAE,OAAO,GAAG,SAAS,CAAC;CACvD;AAmcD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CA2B5D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEnD;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE1D;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GACvD,IAAI,CAEN;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEnE;AAED,eAAO,MAAM,UAAU,QAAO,OAA6C,CAAC"}
@@ -249,11 +249,15 @@ globalThis.happo.nextExample = async () => {
249
249
  let variant = rawVariant;
250
250
  try {
251
251
  if (globalThis.happoSkipped && globalThis.happoSkipped.some(
252
- (item) => item.component === component && item.variant === variant
252
+ (item) => item.component === component && (item.variant === void 0 || item.variant === variant)
253
253
  )) {
254
254
  console.log(`Skipping ${component}, ${variant} since it is in the skip list`);
255
255
  return { component, variant, skipped: true };
256
256
  }
257
+ if (globalThis.happoOnly && !globalThis.happoOnly.some((item) => item.component === component)) {
258
+ console.log(`Skipping ${component}, ${variant} since it is not in the only list`);
259
+ return { component, variant, skipped: true };
260
+ }
257
261
  const docsRootElement = document.getElementById("docs-root");
258
262
  if (docsRootElement) {
259
263
  docsRootElement.dataset.happoIgnore = "true";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/storybook/browser/register.ts"],
4
- "sourcesContent": ["import type { Channel } from 'storybook/internal/channels';\nimport type { StoryStore } from 'storybook/internal/preview-api';\n\nimport type {\n InitConfig,\n NextExampleResult,\n WindowHappo,\n} from '../../isomorphic/types.ts';\nimport type { SkipItems } from '../isomorphic/types.ts';\nimport { SB_ROOT_ELEMENT_SELECTOR } from './constants.ts';\n\ninterface HappoTime {\n originalDateNow: typeof Date.now;\n originalSetTimeout: typeof setTimeout;\n}\n\ndeclare global {\n var happoTime: HappoTime | undefined;\n var happoSkipped: SkipItems | undefined;\n var __IS_HAPPO_RUN: boolean | undefined;\n var __STORYBOOK_CLIENT_API__:\n | {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _storyStore: StoryStore<any>;\n }\n | undefined;\n var __STORYBOOK_PREVIEW__:\n | {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n storyStoreValue: StoryStore<any>;\n }\n | undefined;\n var __STORYBOOK_ADDONS_CHANNEL__: Channel | undefined;\n}\n\nconst time = globalThis.happoTime || {\n originalDateNow: Date.now,\n originalSetTimeout: globalThis.setTimeout.bind(globalThis),\n};\n\nconst STORY_STORE_TIMEOUT = 10_000;\n\ntype HookFunction = ({\n rootElement,\n}: {\n rootElement: HTMLElement;\n}) => void | Promise<void>;\n\ninterface Example {\n component: string;\n variant: string;\n storyId: string;\n delay: number;\n waitForContent: string | undefined;\n waitFor: () => boolean;\n beforeScreenshot: HookFunction;\n afterScreenshot: HookFunction;\n targets: Array<string>;\n theme?: string;\n}\n\nlet renderTimeoutMs = 2000;\nlet examples: Array<Example>;\nlet currentIndex = 0;\nlet defaultDelay: number;\nlet themeSwitcher: (theme: string, channel: Channel) => Promise<void>;\nlet forcedHappoScreenshotSteps:\n | Array<{ stepLabel: string; done: boolean }>\n | undefined;\nlet shouldWaitForCompletedEvent = true;\n\nclass ForcedHappoScreenshot extends Error {\n type: string;\n step: string;\n\n constructor(stepLabel: string) {\n super(`Forced screenshot with label \"${stepLabel}\"`);\n this.name = 'ForcedHappoScreenshot';\n this.type = 'ForcedHappoScreenshot';\n this.step = stepLabel;\n }\n}\n\nasync function waitForWaitFor(\n waitFor: () => boolean,\n start = time.originalDateNow(),\n): Promise<void> {\n const duration = time.originalDateNow() - start;\n if (!waitFor() && duration < renderTimeoutMs) {\n return new Promise((resolve) =>\n time.originalSetTimeout(() => resolve(waitForWaitFor(waitFor, start)), 50),\n );\n }\n\n return;\n}\n\n/**\n * Type safe function to check if a value is defined\n *\n * @example\n * const filtered = values.filter(isDefined);\n */\nfunction isDefined<T>(value: T): value is NonNullable<T> {\n if (value === undefined) {\n return false;\n }\n if (value === null) {\n return false;\n }\n return true;\n}\n\nasync function getStoryStore(startTime = time.originalDateNow()) {\n const duration = time.originalDateNow() - startTime;\n if (duration >= STORY_STORE_TIMEOUT) {\n throw new Error(\n `Timeout: Could not find Storybook Client API after ${STORY_STORE_TIMEOUT}ms`,\n );\n }\n\n const { __STORYBOOK_CLIENT_API__: clientApi, __STORYBOOK_PREVIEW__: preview } =\n globalThis;\n\n if (clientApi && clientApi._storyStore) {\n return clientApi._storyStore;\n }\n if (preview && preview.storyStoreValue) {\n return preview.storyStoreValue;\n }\n\n // Wait 100ms and try again\n await new Promise((resolve) => time.originalSetTimeout(resolve, 100));\n return getStoryStore(startTime);\n}\n\nasync function getExamples(): Promise<Array<Example>> {\n const storyStore = await getStoryStore();\n\n if (!storyStore) {\n throw new Error('Could not get Storybook story store');\n }\n\n if (!storyStore.extract) {\n throw new Error('Missing Storybook Client API');\n }\n\n if (storyStore.cacheAllCSFFiles) {\n await storyStore.cacheAllCSFFiles();\n }\n\n return Object.values(storyStore.extract())\n .map(({ id, kind, story, parameters }) => {\n if (parameters.happo === false) {\n return;\n }\n let delay = defaultDelay;\n let waitForContent;\n let waitFor;\n let beforeScreenshot;\n let afterScreenshot;\n let targets;\n let themes;\n if (typeof parameters.happo === 'object' && parameters.happo !== null) {\n delay = parameters.happo.delay || defaultDelay;\n waitForContent = parameters.happo.waitForContent;\n waitFor = parameters.happo.waitFor;\n beforeScreenshot = parameters.happo.beforeScreenshot;\n afterScreenshot = parameters.happo.afterScreenshot;\n targets = parameters.happo.targets;\n themes = parameters.happo.themes;\n }\n return {\n component: kind,\n variant: story,\n storyId: id,\n delay,\n waitForContent,\n waitFor,\n beforeScreenshot,\n afterScreenshot,\n targets,\n themes,\n };\n })\n .filter(isDefined)\n .reduce<Array<Example>>((result, { themes, ...rest }) => {\n if (themes) {\n for (const theme of themes) {\n result.push({\n ...rest,\n variant: `${rest.variant} [${theme}]`,\n theme,\n });\n }\n } else {\n result.push(rest);\n }\n\n return result;\n }, [])\n .toSorted((a, b) => {\n const aCompare = `${a.component}-${a.theme}-${a.storyId}`;\n const bCompare = `${b.component}-${b.theme}-${b.storyId}`;\n if (aCompare === bCompare) {\n return 0;\n }\n return aCompare < bCompare ? -1 : 1;\n });\n}\n\nfunction filterExamples(\n all: Array<Example>,\n initConfig: InitConfig,\n): Array<Example> {\n const { chunk, targetName, only } = initConfig;\n\n if (chunk) {\n const examplesPerChunk = Math.ceil(all.length / chunk.total);\n const startIndex = chunk.index * examplesPerChunk;\n const endIndex = startIndex + examplesPerChunk;\n all = all.slice(startIndex, endIndex);\n }\n\n if (targetName) {\n all = all.filter((e) => {\n if (!e.targets || !Array.isArray(e.targets)) {\n // This story hasn't been filtered for specific targets\n return true;\n }\n\n return e.targets.includes(targetName);\n });\n }\n\n if (only) {\n all = all.filter(\n (e) => e.component === only.component && e.variant === only.variant,\n );\n }\n\n return all;\n}\n\nglobalThis.happo = globalThis.happo || ({} as WindowHappo);\n\nglobalThis.happo.init = async (config: InitConfig) => {\n examples = filterExamples(await getExamples(), config);\n};\n\ninterface Story {\n kind: string;\n story: string;\n storyId: string;\n}\n\nfunction renderStory(\n story: Story,\n { force = false } = {},\n): Promise<{ pausedAtStep?: { stepLabel: string; done: boolean } }> {\n const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__;\n\n if (!channel) {\n throw new Error('Missing Storybook Addons Channel');\n }\n\n let isPlaying = false;\n let loadingCount = 0;\n\n return new Promise((resolve) => {\n const timeout = time.originalSetTimeout(resolve, renderTimeoutMs);\n function handleRenderPhaseChanged(ev: { storyId: string; newPhase: string }) {\n if (!channel) {\n throw new Error('Missing Storybook Addons Channel');\n }\n\n if (ev.storyId !== story.storyId) {\n console.log(\n `Skipping render phase event (${ev.newPhase}) because story IDs don't match. Current storyId: ${story.storyId}, event storyId: ${ev.storyId}`,\n );\n return;\n }\n\n if (ev.newPhase === 'loading') {\n loadingCount++;\n }\n\n if (ev.newPhase === 'finished' || ev.newPhase === 'aborted') {\n loadingCount--;\n }\n\n if (ev.newPhase === 'finished') {\n if (loadingCount > 0) {\n console.log(\n `Skipping finished event because loadingCount is ${loadingCount} for story ${story.storyId}`,\n );\n return;\n }\n\n channel.off('storyRenderPhaseChanged', handleRenderPhaseChanged);\n clearTimeout(timeout);\n\n if (isPlaying && forcedHappoScreenshotSteps) {\n const pausedAtStep = forcedHappoScreenshotSteps.at(-1);\n\n if (pausedAtStep && !pausedAtStep.done) {\n return resolve({ pausedAtStep });\n }\n }\n\n return resolve({});\n }\n\n if (ev.newPhase === 'playing') {\n isPlaying = true;\n }\n }\n\n if (shouldWaitForCompletedEvent) {\n channel.on('storyRenderPhaseChanged', handleRenderPhaseChanged);\n }\n\n if (force) {\n channel.emit('forceRemount', story);\n } else {\n channel.emit('setCurrentStory', story);\n }\n\n if (!shouldWaitForCompletedEvent) {\n time.originalSetTimeout(() => {\n clearTimeout(timeout);\n resolve({});\n }, 0);\n }\n });\n}\n\nfunction assertHTMLElement(element: Element | null): asserts element is HTMLElement {\n if (element === null) {\n throw new Error('element cannot be null');\n }\n if (!(element instanceof HTMLElement)) {\n throw new TypeError('element must be an HTMLElement');\n }\n}\n\nglobalThis.happo.nextExample = async (): Promise<NextExampleResult | undefined> => {\n if (!examples) {\n throw new Error(\n 'Missing examples. Make sure to call the init function before calling nextExample.',\n );\n }\n\n if (currentIndex >= examples.length) {\n return;\n }\n\n const example = examples[currentIndex];\n if (!example) {\n throw new Error(`Missing example at index ${currentIndex}`);\n }\n\n const {\n component,\n variant: rawVariant,\n storyId,\n delay,\n waitForContent,\n waitFor,\n beforeScreenshot,\n theme,\n } = example;\n\n let pausedAtStep;\n let variant = rawVariant;\n\n try {\n if (\n globalThis.happoSkipped &&\n globalThis.happoSkipped.some(\n (item) => item.component === component && item.variant === variant,\n )\n ) {\n console.log(`Skipping ${component}, ${variant} since it is in the skip list`);\n return { component, variant, skipped: true };\n }\n\n const docsRootElement = document.getElementById('docs-root');\n if (docsRootElement) {\n docsRootElement.dataset.happoIgnore = 'true';\n }\n\n const rootElement = document.querySelector(SB_ROOT_ELEMENT_SELECTOR);\n assertHTMLElement(rootElement);\n rootElement.dataset.happoIgnore = 'true';\n\n const { afterScreenshot } = examples[currentIndex - 1] || {};\n if (afterScreenshot && typeof afterScreenshot === 'function') {\n try {\n await afterScreenshot({ rootElement });\n } catch (e) {\n console.error('Failed to invoke afterScreenshot hook', e);\n }\n }\n\n const renderResult = await renderStory(\n {\n kind: component,\n story: rawVariant,\n storyId,\n },\n { force: !!forcedHappoScreenshotSteps },\n );\n\n pausedAtStep = renderResult.pausedAtStep;\n\n if (pausedAtStep) {\n variant = `${variant}-${pausedAtStep.stepLabel}`;\n } else {\n forcedHappoScreenshotSteps = undefined;\n }\n\n const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__;\n if (!channel) {\n throw new Error('Missing Storybook Addons Channel');\n }\n\n if (theme && themeSwitcher) {\n await themeSwitcher(theme, channel);\n }\n\n if (/sb-show-errordisplay/.test(document.body.className)) {\n // It's possible that the error is from unmounting the previous story. We\n // can try re-rendering in this case.\n channel.emit('forceReRender');\n }\n\n if (beforeScreenshot && typeof beforeScreenshot === 'function') {\n try {\n await beforeScreenshot({ rootElement });\n } catch (e) {\n console.error('Failed to invoke beforeScreenshot hook', e);\n }\n }\n\n await new Promise((resolve) => time.originalSetTimeout(resolve, delay));\n\n if (waitFor) {\n await waitForWaitFor(waitFor);\n }\n\n const highlightsRootElement = document.querySelector(\n '#storybook-highlights-root',\n );\n if (\n highlightsRootElement &&\n (highlightsRootElement instanceof HTMLElement ||\n highlightsRootElement instanceof SVGElement ||\n highlightsRootElement instanceof MathMLElement)\n ) {\n highlightsRootElement.dataset.happoIgnore = 'true';\n }\n\n return { component, variant, waitForContent };\n } catch (e) {\n console.warn(e);\n return { component, variant };\n } finally {\n if (pausedAtStep) {\n pausedAtStep.done = true;\n } else {\n currentIndex++;\n }\n }\n};\n\nexport function forceHappoScreenshot(stepLabel: string): void {\n if (!examples) {\n console.log(\n `Ignoring forceHappoScreenshot with step label \"${stepLabel}\" since we are not currently rendering for Happo`,\n );\n return;\n }\n\n if (!stepLabel) {\n throw new Error(\n 'Missing stepLabel argument. Make sure to pass a string as the first argument to this function. E.g. `forceHappoScreenshot(\"modal open\")`',\n );\n }\n\n if (\n forcedHappoScreenshotSteps &&\n forcedHappoScreenshotSteps.some((s) => s.stepLabel === stepLabel)\n ) {\n // ignore, this step has already been handled\n return;\n }\n\n forcedHappoScreenshotSteps = forcedHappoScreenshotSteps || [];\n forcedHappoScreenshotSteps.push({ stepLabel, done: false });\n\n console.log('Forcing happo screenshot', stepLabel);\n throw new ForcedHappoScreenshot(stepLabel);\n}\n\nexport function setDefaultDelay(delay: number): void {\n defaultDelay = delay;\n}\n\nexport function setRenderTimeoutMs(timeoutMs: number): void {\n renderTimeoutMs = timeoutMs;\n}\n\nexport function setThemeSwitcher(\n func: (theme: string, channel: Channel) => Promise<void>,\n): void {\n themeSwitcher = func;\n}\n\nexport function setShouldWaitForCompletedEvent(swfce: boolean): void {\n shouldWaitForCompletedEvent = swfce;\n}\n\nexport const isHappoRun = (): boolean => globalThis.__IS_HAPPO_RUN ?? false;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Channel } from 'storybook/internal/channels';\nimport type { StoryStore } from 'storybook/internal/preview-api';\n\nimport type {\n InitConfig,\n NextExampleResult,\n WindowHappo,\n} from '../../isomorphic/types.ts';\nimport type { OnlyItems, SkipItems } from '../isomorphic/types.ts';\nimport { SB_ROOT_ELEMENT_SELECTOR } from './constants.ts';\n\ninterface HappoTime {\n originalDateNow: typeof Date.now;\n originalSetTimeout: typeof setTimeout;\n}\n\ndeclare global {\n var happoTime: HappoTime | undefined;\n var happoSkipped: SkipItems | undefined;\n var happoOnly: OnlyItems | null | undefined;\n var __IS_HAPPO_RUN: boolean | undefined;\n var __STORYBOOK_CLIENT_API__:\n | {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _storyStore: StoryStore<any>;\n }\n | undefined;\n var __STORYBOOK_PREVIEW__:\n | {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n storyStoreValue: StoryStore<any>;\n }\n | undefined;\n var __STORYBOOK_ADDONS_CHANNEL__: Channel | undefined;\n}\n\nconst time = globalThis.happoTime || {\n originalDateNow: Date.now,\n originalSetTimeout: globalThis.setTimeout.bind(globalThis),\n};\n\nconst STORY_STORE_TIMEOUT = 10_000;\n\ntype HookFunction = ({\n rootElement,\n}: {\n rootElement: HTMLElement;\n}) => void | Promise<void>;\n\ninterface Example {\n component: string;\n variant: string;\n storyId: string;\n delay: number;\n waitForContent: string | undefined;\n waitFor: () => boolean;\n beforeScreenshot: HookFunction;\n afterScreenshot: HookFunction;\n targets: Array<string>;\n theme?: string;\n}\n\nlet renderTimeoutMs = 2000;\nlet examples: Array<Example>;\nlet currentIndex = 0;\nlet defaultDelay: number;\nlet themeSwitcher: (theme: string, channel: Channel) => Promise<void>;\nlet forcedHappoScreenshotSteps:\n | Array<{ stepLabel: string; done: boolean }>\n | undefined;\nlet shouldWaitForCompletedEvent = true;\n\nclass ForcedHappoScreenshot extends Error {\n type: string;\n step: string;\n\n constructor(stepLabel: string) {\n super(`Forced screenshot with label \"${stepLabel}\"`);\n this.name = 'ForcedHappoScreenshot';\n this.type = 'ForcedHappoScreenshot';\n this.step = stepLabel;\n }\n}\n\nasync function waitForWaitFor(\n waitFor: () => boolean,\n start = time.originalDateNow(),\n): Promise<void> {\n const duration = time.originalDateNow() - start;\n if (!waitFor() && duration < renderTimeoutMs) {\n return new Promise((resolve) =>\n time.originalSetTimeout(() => resolve(waitForWaitFor(waitFor, start)), 50),\n );\n }\n\n return;\n}\n\n/**\n * Type safe function to check if a value is defined\n *\n * @example\n * const filtered = values.filter(isDefined);\n */\nfunction isDefined<T>(value: T): value is NonNullable<T> {\n if (value === undefined) {\n return false;\n }\n if (value === null) {\n return false;\n }\n return true;\n}\n\nasync function getStoryStore(startTime = time.originalDateNow()) {\n const duration = time.originalDateNow() - startTime;\n if (duration >= STORY_STORE_TIMEOUT) {\n throw new Error(\n `Timeout: Could not find Storybook Client API after ${STORY_STORE_TIMEOUT}ms`,\n );\n }\n\n const { __STORYBOOK_CLIENT_API__: clientApi, __STORYBOOK_PREVIEW__: preview } =\n globalThis;\n\n if (clientApi && clientApi._storyStore) {\n return clientApi._storyStore;\n }\n if (preview && preview.storyStoreValue) {\n return preview.storyStoreValue;\n }\n\n // Wait 100ms and try again\n await new Promise((resolve) => time.originalSetTimeout(resolve, 100));\n return getStoryStore(startTime);\n}\n\nasync function getExamples(): Promise<Array<Example>> {\n const storyStore = await getStoryStore();\n\n if (!storyStore) {\n throw new Error('Could not get Storybook story store');\n }\n\n if (!storyStore.extract) {\n throw new Error('Missing Storybook Client API');\n }\n\n if (storyStore.cacheAllCSFFiles) {\n await storyStore.cacheAllCSFFiles();\n }\n\n return Object.values(storyStore.extract())\n .map(({ id, kind, story, parameters }) => {\n if (parameters.happo === false) {\n return;\n }\n let delay = defaultDelay;\n let waitForContent;\n let waitFor;\n let beforeScreenshot;\n let afterScreenshot;\n let targets;\n let themes;\n if (typeof parameters.happo === 'object' && parameters.happo !== null) {\n delay = parameters.happo.delay || defaultDelay;\n waitForContent = parameters.happo.waitForContent;\n waitFor = parameters.happo.waitFor;\n beforeScreenshot = parameters.happo.beforeScreenshot;\n afterScreenshot = parameters.happo.afterScreenshot;\n targets = parameters.happo.targets;\n themes = parameters.happo.themes;\n }\n return {\n component: kind,\n variant: story,\n storyId: id,\n delay,\n waitForContent,\n waitFor,\n beforeScreenshot,\n afterScreenshot,\n targets,\n themes,\n };\n })\n .filter(isDefined)\n .reduce<Array<Example>>((result, { themes, ...rest }) => {\n if (themes) {\n for (const theme of themes) {\n result.push({\n ...rest,\n variant: `${rest.variant} [${theme}]`,\n theme,\n });\n }\n } else {\n result.push(rest);\n }\n\n return result;\n }, [])\n .toSorted((a, b) => {\n const aCompare = `${a.component}-${a.theme}-${a.storyId}`;\n const bCompare = `${b.component}-${b.theme}-${b.storyId}`;\n if (aCompare === bCompare) {\n return 0;\n }\n return aCompare < bCompare ? -1 : 1;\n });\n}\n\nfunction filterExamples(\n all: Array<Example>,\n initConfig: InitConfig,\n): Array<Example> {\n const { chunk, targetName, only } = initConfig;\n\n if (chunk) {\n const examplesPerChunk = Math.ceil(all.length / chunk.total);\n const startIndex = chunk.index * examplesPerChunk;\n const endIndex = startIndex + examplesPerChunk;\n all = all.slice(startIndex, endIndex);\n }\n\n if (targetName) {\n all = all.filter((e) => {\n if (!e.targets || !Array.isArray(e.targets)) {\n // This story hasn't been filtered for specific targets\n return true;\n }\n\n return e.targets.includes(targetName);\n });\n }\n\n if (only) {\n all = all.filter(\n (e) => e.component === only.component && e.variant === only.variant,\n );\n }\n\n return all;\n}\n\nglobalThis.happo = globalThis.happo || ({} as WindowHappo);\n\nglobalThis.happo.init = async (config: InitConfig) => {\n examples = filterExamples(await getExamples(), config);\n};\n\ninterface Story {\n kind: string;\n story: string;\n storyId: string;\n}\n\nfunction renderStory(\n story: Story,\n { force = false } = {},\n): Promise<{ pausedAtStep?: { stepLabel: string; done: boolean } }> {\n const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__;\n\n if (!channel) {\n throw new Error('Missing Storybook Addons Channel');\n }\n\n let isPlaying = false;\n let loadingCount = 0;\n\n return new Promise((resolve) => {\n const timeout = time.originalSetTimeout(resolve, renderTimeoutMs);\n function handleRenderPhaseChanged(ev: { storyId: string; newPhase: string }) {\n if (!channel) {\n throw new Error('Missing Storybook Addons Channel');\n }\n\n if (ev.storyId !== story.storyId) {\n console.log(\n `Skipping render phase event (${ev.newPhase}) because story IDs don't match. Current storyId: ${story.storyId}, event storyId: ${ev.storyId}`,\n );\n return;\n }\n\n if (ev.newPhase === 'loading') {\n loadingCount++;\n }\n\n if (ev.newPhase === 'finished' || ev.newPhase === 'aborted') {\n loadingCount--;\n }\n\n if (ev.newPhase === 'finished') {\n if (loadingCount > 0) {\n console.log(\n `Skipping finished event because loadingCount is ${loadingCount} for story ${story.storyId}`,\n );\n return;\n }\n\n channel.off('storyRenderPhaseChanged', handleRenderPhaseChanged);\n clearTimeout(timeout);\n\n if (isPlaying && forcedHappoScreenshotSteps) {\n const pausedAtStep = forcedHappoScreenshotSteps.at(-1);\n\n if (pausedAtStep && !pausedAtStep.done) {\n return resolve({ pausedAtStep });\n }\n }\n\n return resolve({});\n }\n\n if (ev.newPhase === 'playing') {\n isPlaying = true;\n }\n }\n\n if (shouldWaitForCompletedEvent) {\n channel.on('storyRenderPhaseChanged', handleRenderPhaseChanged);\n }\n\n if (force) {\n channel.emit('forceRemount', story);\n } else {\n channel.emit('setCurrentStory', story);\n }\n\n if (!shouldWaitForCompletedEvent) {\n time.originalSetTimeout(() => {\n clearTimeout(timeout);\n resolve({});\n }, 0);\n }\n });\n}\n\nfunction assertHTMLElement(element: Element | null): asserts element is HTMLElement {\n if (element === null) {\n throw new Error('element cannot be null');\n }\n if (!(element instanceof HTMLElement)) {\n throw new TypeError('element must be an HTMLElement');\n }\n}\n\nglobalThis.happo.nextExample = async (): Promise<NextExampleResult | undefined> => {\n if (!examples) {\n throw new Error(\n 'Missing examples. Make sure to call the init function before calling nextExample.',\n );\n }\n\n if (currentIndex >= examples.length) {\n return;\n }\n\n const example = examples[currentIndex];\n if (!example) {\n throw new Error(`Missing example at index ${currentIndex}`);\n }\n\n const {\n component,\n variant: rawVariant,\n storyId,\n delay,\n waitForContent,\n waitFor,\n beforeScreenshot,\n theme,\n } = example;\n\n let pausedAtStep;\n let variant = rawVariant;\n\n try {\n if (\n globalThis.happoSkipped &&\n globalThis.happoSkipped.some(\n (item) => item.component === component && (item.variant === undefined || item.variant === variant),\n )\n ) {\n console.log(`Skipping ${component}, ${variant} since it is in the skip list`);\n return { component, variant, skipped: true };\n }\n\n if (\n globalThis.happoOnly &&\n !globalThis.happoOnly.some((item) => item.component === component)\n ) {\n console.log(`Skipping ${component}, ${variant} since it is not in the only list`);\n return { component, variant, skipped: true };\n }\n\n const docsRootElement = document.getElementById('docs-root');\n if (docsRootElement) {\n docsRootElement.dataset.happoIgnore = 'true';\n }\n\n const rootElement = document.querySelector(SB_ROOT_ELEMENT_SELECTOR);\n assertHTMLElement(rootElement);\n rootElement.dataset.happoIgnore = 'true';\n\n const { afterScreenshot } = examples[currentIndex - 1] || {};\n if (afterScreenshot && typeof afterScreenshot === 'function') {\n try {\n await afterScreenshot({ rootElement });\n } catch (e) {\n console.error('Failed to invoke afterScreenshot hook', e);\n }\n }\n\n const renderResult = await renderStory(\n {\n kind: component,\n story: rawVariant,\n storyId,\n },\n { force: !!forcedHappoScreenshotSteps },\n );\n\n pausedAtStep = renderResult.pausedAtStep;\n\n if (pausedAtStep) {\n variant = `${variant}-${pausedAtStep.stepLabel}`;\n } else {\n forcedHappoScreenshotSteps = undefined;\n }\n\n const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__;\n if (!channel) {\n throw new Error('Missing Storybook Addons Channel');\n }\n\n if (theme && themeSwitcher) {\n await themeSwitcher(theme, channel);\n }\n\n if (/sb-show-errordisplay/.test(document.body.className)) {\n // It's possible that the error is from unmounting the previous story. We\n // can try re-rendering in this case.\n channel.emit('forceReRender');\n }\n\n if (beforeScreenshot && typeof beforeScreenshot === 'function') {\n try {\n await beforeScreenshot({ rootElement });\n } catch (e) {\n console.error('Failed to invoke beforeScreenshot hook', e);\n }\n }\n\n await new Promise((resolve) => time.originalSetTimeout(resolve, delay));\n\n if (waitFor) {\n await waitForWaitFor(waitFor);\n }\n\n const highlightsRootElement = document.querySelector(\n '#storybook-highlights-root',\n );\n if (\n highlightsRootElement &&\n (highlightsRootElement instanceof HTMLElement ||\n highlightsRootElement instanceof SVGElement ||\n highlightsRootElement instanceof MathMLElement)\n ) {\n highlightsRootElement.dataset.happoIgnore = 'true';\n }\n\n return { component, variant, waitForContent };\n } catch (e) {\n console.warn(e);\n return { component, variant };\n } finally {\n if (pausedAtStep) {\n pausedAtStep.done = true;\n } else {\n currentIndex++;\n }\n }\n};\n\nexport function forceHappoScreenshot(stepLabel: string): void {\n if (!examples) {\n console.log(\n `Ignoring forceHappoScreenshot with step label \"${stepLabel}\" since we are not currently rendering for Happo`,\n );\n return;\n }\n\n if (!stepLabel) {\n throw new Error(\n 'Missing stepLabel argument. Make sure to pass a string as the first argument to this function. E.g. `forceHappoScreenshot(\"modal open\")`',\n );\n }\n\n if (\n forcedHappoScreenshotSteps &&\n forcedHappoScreenshotSteps.some((s) => s.stepLabel === stepLabel)\n ) {\n // ignore, this step has already been handled\n return;\n }\n\n forcedHappoScreenshotSteps = forcedHappoScreenshotSteps || [];\n forcedHappoScreenshotSteps.push({ stepLabel, done: false });\n\n console.log('Forcing happo screenshot', stepLabel);\n throw new ForcedHappoScreenshot(stepLabel);\n}\n\nexport function setDefaultDelay(delay: number): void {\n defaultDelay = delay;\n}\n\nexport function setRenderTimeoutMs(timeoutMs: number): void {\n renderTimeoutMs = timeoutMs;\n}\n\nexport function setThemeSwitcher(\n func: (theme: string, channel: Channel) => Promise<void>,\n): void {\n themeSwitcher = func;\n}\n\nexport function setShouldWaitForCompletedEvent(swfce: boolean): void {\n shouldWaitForCompletedEvent = swfce;\n}\n\nexport const isHappoRun = (): boolean => globalThis.__IS_HAPPO_RUN ?? false;\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,15 @@
1
1
  import type { StorybookIntegration } from '../config/index.ts';
2
+ import type { OnlyItem, SkipItem } from '../isomorphic/types.ts';
2
3
  export interface BuildStorybookPackageResult {
3
4
  packageDir: string;
4
5
  estimatedSnapsCount?: number;
6
+ resolvedSkip?: Array<{
7
+ component: string;
8
+ variant?: string;
9
+ }>;
5
10
  }
6
- export default function buildStorybookPackage({ configDir, staticDir, outputDir, usePrebuiltPackage, skip, }: Omit<StorybookIntegration, 'type'>): Promise<BuildStorybookPackageResult>;
11
+ export default function buildStorybookPackage({ configDir, staticDir, outputDir, usePrebuiltPackage, skip, only, }: Omit<StorybookIntegration, 'type'> & {
12
+ skip?: Array<SkipItem>;
13
+ only?: Array<OnlyItem>;
14
+ }): Promise<BuildStorybookPackageResult>;
7
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storybook/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AA+F/D,MAAM,WAAW,2BAA2B;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAA8B,qBAAqB,CAAC,EAClD,SAAwB,EACxB,SAAS,EACT,SAAkB,EAClB,kBAA0B,EAC1B,IAAI,GACL,EAAE,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,2BAA2B,CAAC,CA6C3E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storybook/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAkFjE,MAAM,WAAW,2BAA2B;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/D;AAED,wBAA8B,qBAAqB,CAAC,EAClD,SAAwB,EACxB,SAAS,EACT,SAAkB,EAClB,kBAA0B,EAC1B,IAAI,EACJ,IAAI,GACL,EAAE,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,GAAG;IACtC,IAAI,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvB,IAAI,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;CACxB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAkHvC"}
@@ -1,8 +1,27 @@
1
1
  // src/storybook/index.ts
2
2
  import { spawn } from "node:child_process";
3
- import fs4 from "node:fs";
3
+ import fs3 from "node:fs";
4
4
  import path4 from "node:path";
5
5
 
6
+ // src/isomorphic/parseSkip.ts
7
+ function toSkipSet(items) {
8
+ const componentOnly = /* @__PURE__ */ new Set();
9
+ const componentVariant = /* @__PURE__ */ new Set();
10
+ for (const item of items) {
11
+ if (!("component" in item)) continue;
12
+ const { component, variant } = item;
13
+ if (variant === void 0) {
14
+ componentOnly.add(component);
15
+ } else {
16
+ componentVariant.add(`${component}\0${variant}`);
17
+ }
18
+ }
19
+ return [componentOnly, componentVariant];
20
+ }
21
+ function isInSkipSet([componentOnly, componentVariant], component, variant) {
22
+ return componentOnly.has(component) || componentVariant.has(`${component}\0${variant}`);
23
+ }
24
+
6
25
  // src/storybook/getStorybookBuildCommandParts.ts
7
26
  import fs from "node:fs";
8
27
  import path from "node:path";
@@ -38,27 +57,11 @@ function getStorybookBuildCommandParts(packageJsonPath = path.join(process.cwd()
38
57
  return ["storybook", "build"];
39
58
  }
40
59
 
41
- // src/storybook/getStorybookStoryCount.ts
60
+ // src/storybook/getStorybookVersionFromPackageJson.ts
42
61
  import fs2 from "node:fs";
43
62
  import path2 from "node:path";
44
- async function getStorybookStoryCount(packageDir) {
45
- const indexPath = path2.join(packageDir, "index.json");
46
- try {
47
- const content = await fs2.promises.readFile(indexPath, "utf8");
48
- const data = JSON.parse(content);
49
- const entries = data.entries ?? data.stories ?? {};
50
- return Object.values(entries).filter((e) => e.type === "story").length;
51
- } catch (error) {
52
- console.warn("Failed to get estimated snaps count from Storybook:", error);
53
- return void 0;
54
- }
55
- }
56
-
57
- // src/storybook/getStorybookVersionFromPackageJson.ts
58
- import fs3 from "node:fs";
59
- import path3 from "node:path";
60
- function getStorybookVersionFromPackageJson(packageJsonPath = path3.join(process.cwd(), "package.json")) {
61
- const data = fs3.readFileSync(packageJsonPath, "utf8");
63
+ function getStorybookVersionFromPackageJson(packageJsonPath = path2.join(process.cwd(), "package.json")) {
64
+ const data = fs2.readFileSync(packageJsonPath, "utf8");
62
65
  const packageJson = JSON.parse(data);
63
66
  const combinedDependencies = {
64
67
  ...packageJson.dependencies,
@@ -79,18 +82,55 @@ function getStorybookVersionFromPackageJson(packageJsonPath = path3.join(process
79
82
  }
80
83
  }
81
84
 
82
- // src/storybook/index.ts
83
- var { HAPPO_DEBUG: HAPPO_DEBUG2 } = process.env;
84
- function assertSkippedIsSkipItems(skipped) {
85
- if (!Array.isArray(skipped)) {
86
- throw new TypeError(`The \`skip\` option didn't provide an array`);
85
+ // src/storybook/resolveStoryFileItems.ts
86
+ import path3 from "node:path";
87
+ function resolveStoryFileItems(skip, entries) {
88
+ const fileToComponents = /* @__PURE__ */ new Map();
89
+ for (const entry of Object.values(entries)) {
90
+ if (!entry.importPath || !entry.title) continue;
91
+ const normalized = normalizeImportPath(entry.importPath);
92
+ let set = fileToComponents.get(normalized);
93
+ if (!set) {
94
+ set = /* @__PURE__ */ new Set();
95
+ fileToComponents.set(normalized, set);
96
+ }
97
+ set.add(entry.title);
87
98
  }
88
- if (skipped.some((item) => !item.component || !item.variant)) {
89
- throw new Error(
90
- `Each item provided by the \`skip\` option needs a \`component\` and a \`variant\` property`
91
- );
99
+ const resolved = [];
100
+ for (const item of skip) {
101
+ if ("component" in item) {
102
+ resolved.push(item);
103
+ continue;
104
+ }
105
+ const normalizedFile = normalizeImportPath(item.storyFile);
106
+ let components = fileToComponents.get(normalizedFile);
107
+ if (!components) {
108
+ const resolvedFile = path3.resolve(item.storyFile);
109
+ for (const [normalizedImport, titles] of fileToComponents) {
110
+ if (path3.resolve(normalizedImport) === resolvedFile) {
111
+ components = titles;
112
+ break;
113
+ }
114
+ }
115
+ }
116
+ if (components) {
117
+ for (const component of components) {
118
+ resolved.push({ component });
119
+ }
120
+ } else {
121
+ console.warn(
122
+ `[HAPPO] Could not find any stories for storyFile '${item.storyFile}' in the Storybook index`
123
+ );
124
+ }
92
125
  }
126
+ return resolved;
127
+ }
128
+ function normalizeImportPath(p) {
129
+ return p.startsWith("./") ? p.slice(2) : p;
93
130
  }
131
+
132
+ // src/storybook/index.ts
133
+ var { HAPPO_DEBUG: HAPPO_DEBUG2 } = process.env;
94
134
  function resolveBuildCommandParts() {
95
135
  const version = getStorybookVersionFromPackageJson();
96
136
  if (version < 9) {
@@ -105,7 +145,7 @@ async function buildStorybook({
105
145
  staticDir,
106
146
  outputDir
107
147
  }) {
108
- await fs4.promises.rm(outputDir, { recursive: true, force: true });
148
+ await fs3.promises.rm(outputDir, { recursive: true, force: true });
109
149
  const buildCommandParts = resolveBuildCommandParts();
110
150
  if (!buildCommandParts[0]) {
111
151
  throw new Error("Failed to resolve build command parts");
@@ -120,7 +160,7 @@ async function buildStorybook({
120
160
  if (staticDir) {
121
161
  params.push("--static-dir", staticDir);
122
162
  }
123
- let binary = fs4.existsSync("yarn.lock") ? "yarn" : "npx";
163
+ let binary = fs3.existsSync("yarn.lock") ? "yarn" : "npx";
124
164
  if (buildCommandParts[0].includes("node_modules")) {
125
165
  binary = buildCommandParts[0];
126
166
  params.shift();
@@ -136,7 +176,7 @@ async function buildStorybook({
136
176
  spawned.on("exit", (code) => {
137
177
  if (code === 0) {
138
178
  try {
139
- fs4.unlinkSync(path4.join(outputDir, "project.json"));
179
+ fs3.unlinkSync(path4.join(outputDir, "project.json"));
140
180
  } catch (error) {
141
181
  console.warn(
142
182
  `Ignoring error when attempting to remove project.json: ${error}`
@@ -154,39 +194,91 @@ async function buildStorybookPackage({
154
194
  staticDir,
155
195
  outputDir = ".out",
156
196
  usePrebuiltPackage = false,
157
- skip
197
+ skip,
198
+ only
158
199
  }) {
159
200
  if (!usePrebuiltPackage) {
160
201
  await buildStorybook({ configDir, staticDir, outputDir });
161
202
  }
162
203
  const iframePath = path4.join(outputDir, "iframe.html");
163
- if (!fs4.existsSync(iframePath)) {
204
+ if (!fs3.existsSync(iframePath)) {
164
205
  throw new Error(
165
206
  "Failed to build static storybook package (missing iframe.html)"
166
207
  );
167
208
  }
168
209
  try {
169
- const skipped = typeof skip === "function" ? await skip() : Array.isArray(skip) ? skip : [];
170
- assertSkippedIsSkipItems(skipped);
171
- const iframeContent = await fs4.promises.readFile(iframePath, "utf8");
172
- await fs4.promises.writeFile(
210
+ const iframeContent = await fs3.promises.readFile(iframePath, "utf8");
211
+ let estimatedSnapsCount;
212
+ let resolvedSkip;
213
+ let resolvedOnly;
214
+ const indexPath = path4.join(outputDir, "index.json");
215
+ try {
216
+ const indexContent = await fs3.promises.readFile(indexPath, "utf8");
217
+ const indexData = JSON.parse(indexContent);
218
+ const entries = indexData.entries ?? indexData.stories ?? {};
219
+ const storyEntries = Object.values(entries).filter((e) => e.type === "story");
220
+ estimatedSnapsCount = storyEntries.length;
221
+ if (skip !== void 0) {
222
+ resolvedSkip = resolveStoryFileItems(skip, entries);
223
+ const skipSet = toSkipSet(resolvedSkip);
224
+ estimatedSnapsCount = storyEntries.filter(
225
+ (e) => !isInSkipSet(skipSet, e.title ?? "", e.name ?? "")
226
+ ).length;
227
+ }
228
+ if (only !== void 0) {
229
+ resolvedOnly = resolveStoryFileItems(only, entries).map(
230
+ ({ component }) => ({ component })
231
+ );
232
+ if (resolvedOnly.length === 0) {
233
+ console.warn(
234
+ "[HAPPO] --only: no matching stories found in Storybook index. Generating a full report instead."
235
+ );
236
+ resolvedOnly = void 0;
237
+ } else {
238
+ const onlyComponents = new Set(resolvedOnly.map((item) => item.component));
239
+ estimatedSnapsCount = storyEntries.filter(
240
+ (e) => onlyComponents.has(e.title ?? "")
241
+ ).length;
242
+ const allComponents = /* @__PURE__ */ new Set();
243
+ for (const e of storyEntries) {
244
+ if (e.title) allComponents.add(e.title);
245
+ }
246
+ resolvedSkip = [...allComponents].filter((c) => !onlyComponents.has(c)).map((component) => ({ component }));
247
+ }
248
+ }
249
+ } catch (error) {
250
+ console.warn("[HAPPO] Failed to read Storybook index.json:", error);
251
+ if (skip !== void 0) {
252
+ resolvedSkip = skip.filter(
253
+ (item) => "component" in item
254
+ );
255
+ }
256
+ if (only !== void 0) {
257
+ const componentOnly = only.filter(
258
+ (item) => "component" in item
259
+ );
260
+ resolvedOnly = componentOnly.length > 0 ? componentOnly : void 0;
261
+ }
262
+ }
263
+ await fs3.promises.writeFile(
173
264
  iframePath,
174
265
  iframeContent.replace(
175
266
  "<head>",
176
267
  `<head>
177
268
  <meta name="viewport" content="width=device-width, initial-scale=1">
178
269
  <script type="text/javascript">window.__IS_HAPPO_RUN = true;</script>
179
- <script type="text/javascript">window.happoSkipped = ${JSON.stringify(
180
- skipped
181
- )};</script>
270
+ <script type="text/javascript">window.happoSkipped = ${JSON.stringify(resolvedSkip ?? []).replaceAll(/<\/script>/gi, String.raw`<\/script>`)};</script>
271
+ <script type="text/javascript">window.happoOnly = ${JSON.stringify(resolvedOnly ?? null).replaceAll(/<\/script>/gi, String.raw`<\/script>`)};</script>
182
272
  `
183
273
  )
184
274
  );
185
- const estimatedSnapsCount = await getStorybookStoryCount(outputDir);
186
275
  const result = { packageDir: outputDir };
187
276
  if (estimatedSnapsCount != null) {
188
277
  result.estimatedSnapsCount = estimatedSnapsCount;
189
278
  }
279
+ if (resolvedSkip !== void 0) {
280
+ result.resolvedSkip = resolvedSkip;
281
+ }
190
282
  return result;
191
283
  } catch (e) {
192
284
  console.error(e);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/storybook/index.ts", "../../src/storybook/getStorybookBuildCommandParts.ts", "../../src/storybook/getStorybookStoryCount.ts", "../../src/storybook/getStorybookVersionFromPackageJson.ts"],
4
- "sourcesContent": ["import { spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { StorybookIntegration } from '../config/index.ts';\nimport getStorybookBuildCommandParts from './getStorybookBuildCommandParts.ts';\nimport getStorybookStoryCount from './getStorybookStoryCount.ts';\nimport getStorybookVersionFromPackageJson from './getStorybookVersionFromPackageJson.ts';\nimport type { SkipItems } from './isomorphic/types.ts';\n\nconst { HAPPO_DEBUG } = process.env;\n\nfunction assertSkippedIsSkipItems(skipped: unknown): asserts skipped is SkipItems {\n if (!Array.isArray(skipped)) {\n throw new TypeError(`The \\`skip\\` option didn't provide an array`);\n }\n\n if (skipped.some((item) => !item.component || !item.variant)) {\n throw new Error(\n `Each item provided by the \\`skip\\` option needs a \\`component\\` and a \\`variant\\` property`,\n );\n }\n}\n\nfunction resolveBuildCommandParts() {\n const version = getStorybookVersionFromPackageJson();\n\n if (version < 9) {\n throw new Error(\n `Storybook v${version} is not supported. Please update storybook to v9 or later.`,\n );\n }\n\n return getStorybookBuildCommandParts();\n}\n\nasync function buildStorybook({\n configDir,\n staticDir,\n outputDir,\n}: {\n configDir: string;\n staticDir?: string | undefined;\n outputDir: string;\n}): Promise<void> {\n await fs.promises.rm(outputDir, { recursive: true, force: true });\n\n const buildCommandParts = resolveBuildCommandParts();\n\n if (!buildCommandParts[0]) {\n throw new Error('Failed to resolve build command parts');\n }\n\n const params = [\n ...buildCommandParts,\n '--output-dir',\n outputDir,\n '--config-dir',\n configDir,\n ];\n\n if (staticDir) {\n params.push('--static-dir', staticDir);\n }\n\n let binary = fs.existsSync('yarn.lock') ? 'yarn' : 'npx';\n\n if (buildCommandParts[0].includes('node_modules')) {\n binary = buildCommandParts[0];\n params.shift(); // remove binary from params\n }\n\n if (HAPPO_DEBUG) {\n console.log(`[happo] Using build command \\`${binary} ${params.join(' ')}\\``);\n }\n\n return new Promise((resolve, reject) => {\n const spawned = spawn(binary, params, {\n stdio: 'inherit',\n shell: process.platform == 'win32',\n });\n\n spawned.on('exit', (code) => {\n if (code === 0) {\n try {\n fs.unlinkSync(path.join(outputDir, 'project.json'));\n } catch (error) {\n console.warn(\n `Ignoring error when attempting to remove project.json: ${error}`,\n );\n }\n resolve();\n } else {\n reject(new Error('Failed to build static storybook package'));\n }\n });\n });\n}\n\nexport interface BuildStorybookPackageResult {\n packageDir: string;\n estimatedSnapsCount?: number;\n}\n\nexport default async function buildStorybookPackage({\n configDir = '.storybook',\n staticDir,\n outputDir = '.out',\n usePrebuiltPackage = false,\n skip,\n}: Omit<StorybookIntegration, 'type'>): Promise<BuildStorybookPackageResult> {\n if (!usePrebuiltPackage) {\n await buildStorybook({ configDir, staticDir, outputDir });\n }\n\n const iframePath = path.join(outputDir, 'iframe.html');\n if (!fs.existsSync(iframePath)) {\n throw new Error(\n 'Failed to build static storybook package (missing iframe.html)',\n );\n }\n\n try {\n const skipped =\n typeof skip === 'function' ? await skip() : Array.isArray(skip) ? skip : [];\n\n assertSkippedIsSkipItems(skipped);\n\n const iframeContent = await fs.promises.readFile(iframePath, 'utf8');\n\n await fs.promises.writeFile(\n iframePath,\n iframeContent.replace(\n '<head>',\n `<head>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <script type=\"text/javascript\">window.__IS_HAPPO_RUN = true;</script>\n <script type=\"text/javascript\">window.happoSkipped = ${JSON.stringify(\n skipped,\n )};</script>\n `,\n ),\n );\n\n const estimatedSnapsCount = await getStorybookStoryCount(outputDir);\n\n const result: BuildStorybookPackageResult = { packageDir: outputDir };\n if (estimatedSnapsCount != null) {\n result.estimatedSnapsCount = estimatedSnapsCount;\n }\n return result;\n } catch (e) {\n console.error(e);\n throw e;\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\n\nconst { HAPPO_DEBUG } = process.env;\n\nexport default function getStorybookBuildCommandParts(\n packageJsonPath: string = path.join(process.cwd(), 'package.json'),\n): [string, string] {\n try {\n const data = fs.readFileSync(packageJsonPath, 'utf8');\n const packageJson = JSON.parse(data);\n\n if (packageJson.scripts.storybook) {\n if (HAPPO_DEBUG) {\n console.log(\n '[happo] Found `storybook` script in package.json. Will attempt to use binary found at `node_modules/.bin/storybook` instead',\n );\n }\n\n const pathToStorybookCommand = path.join(\n process.cwd(),\n 'node_modules',\n '.bin',\n 'storybook',\n );\n\n if (fs.existsSync(pathToStorybookCommand)) {\n return [pathToStorybookCommand, 'build'];\n }\n }\n } catch (e) {\n if (HAPPO_DEBUG) {\n console.log(\n '[happo] Caught error when resolving Storybook build command parts. Will use default.',\n e,\n );\n }\n }\n\n return ['storybook', 'build'];\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\n\ninterface StorybookIndexEntry {\n type: string;\n}\n\ninterface StorybookIndex {\n entries?: Record<string, StorybookIndexEntry>;\n stories?: Record<string, StorybookIndexEntry>;\n}\n\n/**\n * Reads the storybook index.json from the given package directory and returns\n * the total number of story entries (excluding docs and other non-story types).\n * Returns undefined if the file cannot be read or parsed.\n */\nexport default async function getStorybookStoryCount(\n packageDir: string,\n): Promise<number | undefined> {\n const indexPath = path.join(packageDir, 'index.json');\n try {\n const content = await fs.promises.readFile(indexPath, 'utf8');\n const data = JSON.parse(content) as StorybookIndex;\n const entries = data.entries ?? data.stories ?? {};\n return Object.values(entries).filter((e) => e.type === 'story').length;\n } catch (error) {\n console.warn('Failed to get estimated snaps count from Storybook:', error);\n return undefined;\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\n\nexport default function getStorybookVersionFromPackageJson(\n packageJsonPath: string = path.join(process.cwd(), 'package.json'),\n): number {\n const data = fs.readFileSync(packageJsonPath, 'utf8');\n const packageJson = JSON.parse(data);\n\n const combinedDependencies = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n const storybookPackage = [\n 'storybook',\n '@storybook/react',\n '@storybook/angular',\n '@storybook/vue',\n ].find((pkg) => combinedDependencies[pkg]);\n\n if (storybookPackage) {\n const storybookVersion = combinedDependencies[storybookPackage];\n const majorVersion = Number.parseInt(storybookVersion.match(/\\d+/)[0], 10);\n return majorVersion;\n } else {\n throw new Error('Storybook is not listed as a dependency in package.json');\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["fs", "path", "fs", "path", "fs", "path", "HAPPO_DEBUG", "fs", "path"]
3
+ "sources": ["../../src/storybook/index.ts", "../../src/isomorphic/parseSkip.ts", "../../src/storybook/getStorybookBuildCommandParts.ts", "../../src/storybook/getStorybookVersionFromPackageJson.ts", "../../src/storybook/resolveStoryFileItems.ts"],
4
+ "sourcesContent": ["import { spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { StorybookIntegration } from '../config/index.ts';\nimport { isInSkipSet, toSkipSet } from '../isomorphic/parseSkip.ts';\nimport type { OnlyItem, SkipItem } from '../isomorphic/types.ts';\nimport getStorybookBuildCommandParts from './getStorybookBuildCommandParts.ts';\nimport getStorybookVersionFromPackageJson from './getStorybookVersionFromPackageJson.ts';\nimport resolveStoryFileItems, { type StorybookIndexEntry } from './resolveStoryFileItems.ts';\n\nconst { HAPPO_DEBUG } = process.env;\n\nfunction resolveBuildCommandParts() {\n const version = getStorybookVersionFromPackageJson();\n\n if (version < 9) {\n throw new Error(\n `Storybook v${version} is not supported. Please update storybook to v9 or later.`,\n );\n }\n\n return getStorybookBuildCommandParts();\n}\n\nasync function buildStorybook({\n configDir,\n staticDir,\n outputDir,\n}: {\n configDir: string;\n staticDir?: string | undefined;\n outputDir: string;\n}): Promise<void> {\n await fs.promises.rm(outputDir, { recursive: true, force: true });\n\n const buildCommandParts = resolveBuildCommandParts();\n\n if (!buildCommandParts[0]) {\n throw new Error('Failed to resolve build command parts');\n }\n\n const params = [\n ...buildCommandParts,\n '--output-dir',\n outputDir,\n '--config-dir',\n configDir,\n ];\n\n if (staticDir) {\n params.push('--static-dir', staticDir);\n }\n\n let binary = fs.existsSync('yarn.lock') ? 'yarn' : 'npx';\n\n if (buildCommandParts[0].includes('node_modules')) {\n binary = buildCommandParts[0];\n params.shift(); // remove binary from params\n }\n\n if (HAPPO_DEBUG) {\n console.log(`[happo] Using build command \\`${binary} ${params.join(' ')}\\``);\n }\n\n return new Promise((resolve, reject) => {\n const spawned = spawn(binary, params, {\n stdio: 'inherit',\n shell: process.platform == 'win32',\n });\n\n spawned.on('exit', (code) => {\n if (code === 0) {\n try {\n fs.unlinkSync(path.join(outputDir, 'project.json'));\n } catch (error) {\n console.warn(\n `Ignoring error when attempting to remove project.json: ${error}`,\n );\n }\n resolve();\n } else {\n reject(new Error('Failed to build static storybook package'));\n }\n });\n });\n}\n\nexport interface BuildStorybookPackageResult {\n packageDir: string;\n estimatedSnapsCount?: number;\n resolvedSkip?: Array<{ component: string; variant?: string }>;\n}\n\nexport default async function buildStorybookPackage({\n configDir = '.storybook',\n staticDir,\n outputDir = '.out',\n usePrebuiltPackage = false,\n skip,\n only,\n}: Omit<StorybookIntegration, 'type'> & {\n skip?: Array<SkipItem>;\n only?: Array<OnlyItem>;\n}): Promise<BuildStorybookPackageResult> {\n if (!usePrebuiltPackage) {\n await buildStorybook({ configDir, staticDir, outputDir });\n }\n\n const iframePath = path.join(outputDir, 'iframe.html');\n if (!fs.existsSync(iframePath)) {\n throw new Error(\n 'Failed to build static storybook package (missing iframe.html)',\n );\n }\n\n try {\n const iframeContent = await fs.promises.readFile(iframePath, 'utf8');\n\n // Read index.json once to compute story count and resolve storyFile items.\n let estimatedSnapsCount: number | undefined;\n let resolvedSkip: Array<{ component: string; variant?: string }> | undefined;\n let resolvedOnly: Array<{ component: string }> | undefined;\n\n const indexPath = path.join(outputDir, 'index.json');\n try {\n const indexContent = await fs.promises.readFile(indexPath, 'utf8');\n const indexData = JSON.parse(indexContent) as {\n entries?: Record<string, StorybookIndexEntry>;\n stories?: Record<string, StorybookIndexEntry>;\n };\n const entries = indexData.entries ?? indexData.stories ?? {};\n\n const storyEntries = Object.values(entries).filter((e) => e.type === 'story');\n estimatedSnapsCount = storyEntries.length;\n\n if (skip !== undefined) {\n resolvedSkip = resolveStoryFileItems(skip, entries);\n // Adjust the count so auto-chunking reflects only the stories that\n // will actually be rendered (skipped examples don't need a chunk slot).\n const skipSet = toSkipSet(resolvedSkip);\n estimatedSnapsCount = storyEntries.filter(\n (e) => !isInSkipSet(skipSet, e.title ?? '', e.name ?? ''),\n ).length;\n }\n\n if (only !== undefined) {\n resolvedOnly = resolveStoryFileItems(only as Array<SkipItem>, entries).map(\n ({ component }) => ({ component }),\n );\n if (resolvedOnly.length === 0) {\n console.warn(\n '[HAPPO] --only: no matching stories found in Storybook index. Generating a full report instead.',\n );\n resolvedOnly = undefined;\n } else {\n // Adjust the count so auto-chunking reflects only the stories that\n // will actually be rendered (only matching examples need a chunk slot).\n const onlyComponents = new Set(resolvedOnly.map((item) => item.component));\n estimatedSnapsCount = storyEntries.filter((e) =>\n onlyComponents.has(e.title ?? ''),\n ).length;\n\n // Compute the complement: all components NOT in the only list.\n // These will be borrowed from the baseline via an extends-report.\n const allComponents = new Set<string>();\n for (const e of storyEntries) {\n if (e.title) allComponents.add(e.title);\n }\n resolvedSkip = [...allComponents]\n .filter((c) => !onlyComponents.has(c))\n .map((component) => ({ component }));\n }\n }\n } catch (error) {\n console.warn('[HAPPO] Failed to read Storybook index.json:', error);\n if (skip !== undefined) {\n // Fall back to passing through only component-based items\n resolvedSkip = skip.filter(\n (item): item is { component: string; variant?: string } => 'component' in item,\n );\n }\n if (only !== undefined) {\n // Fall back to component-only items; if none remain, leave resolvedOnly\n // undefined so the browser-side filtering is disabled and a full report\n // is generated rather than an empty one.\n const componentOnly = only.filter(\n (item): item is { component: string } => 'component' in item,\n );\n resolvedOnly = componentOnly.length > 0 ? componentOnly : undefined;\n }\n }\n\n await fs.promises.writeFile(\n iframePath,\n iframeContent.replace(\n '<head>',\n `<head>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <script type=\"text/javascript\">window.__IS_HAPPO_RUN = true;</script>\n <script type=\"text/javascript\">window.happoSkipped = ${JSON.stringify(resolvedSkip ?? []).replaceAll(/<\\/script>/gi, String.raw`<\\/script>`)};</script>\n <script type=\"text/javascript\">window.happoOnly = ${JSON.stringify(resolvedOnly ?? null).replaceAll(/<\\/script>/gi, String.raw`<\\/script>`)};</script>\n `,\n ),\n );\n\n const result: BuildStorybookPackageResult = { packageDir: outputDir };\n if (estimatedSnapsCount != null) {\n result.estimatedSnapsCount = estimatedSnapsCount;\n }\n if (resolvedSkip !== undefined) {\n result.resolvedSkip = resolvedSkip;\n }\n return result;\n } catch (e) {\n console.error(e);\n throw e;\n }\n}\n", "import type { SkipItem } from './types.ts';\n\n/**\n * A pair of Sets used for O(1) skip lookups.\n * - [0]: component-only skips (match all variants of the component)\n * - [1]: component+variant skips (match a specific variant, keyed as \"component\\0variant\")\n */\nexport type SkipSet = readonly [componentOnly: Set<string>, componentVariant: Set<string>];\n\nfunction isSkipItem(item: unknown): item is SkipItem {\n if (typeof item !== 'object' || item === null) return false;\n const record = item as Record<string, unknown>;\n const hasComponent = typeof record['component'] === 'string';\n const hasStoryFile = typeof record['storyFile'] === 'string';\n if (hasComponent && hasStoryFile) return false;\n if (hasStoryFile) return record['variant'] === undefined;\n if (hasComponent) return record['variant'] === undefined || typeof record['variant'] === 'string';\n return false;\n}\n\n/**\n * Parses and validates a JSON string, returning an array of SkipItems.\n * Throws a TypeError if the JSON is invalid or not an array of SkipItems.\n */\nexport function validateSkip(json: string): Array<SkipItem> {\n const parsed: unknown = JSON.parse(json);\n if (!Array.isArray(parsed) || !parsed.every(isSkipItem)) {\n throw new TypeError(\n '--skip must be a JSON array of {component, variant?} or {storyFile} objects',\n );\n }\n return parsed;\n}\n\n/**\n * Parses a JSON string into an array of SkipItems. Returns an empty array on\n * any parse error or if the value is not a valid array of SkipItems.\n */\nexport function parseSkip(json?: string): Array<SkipItem> {\n if (!json) return [];\n try {\n return validateSkip(json);\n } catch {\n return [];\n }\n}\n\n/**\n * Converts an array of SkipItems into a SkipSet for efficient lookups.\n * Items with a `storyFile` key (unresolved) are silently ignored.\n */\nexport function toSkipSet(items: Array<SkipItem>): SkipSet {\n const componentOnly = new Set<string>();\n const componentVariant = new Set<string>();\n for (const item of items) {\n if (!('component' in item)) continue;\n const { component, variant } = item;\n if (variant === undefined) {\n componentOnly.add(component);\n } else {\n componentVariant.add(`${component}\\0${variant}`);\n }\n }\n return [componentOnly, componentVariant];\n}\n\n/**\n * Returns true if the given component+variant should be skipped according to\n * the SkipSet.\n */\nexport function isInSkipSet(\n [componentOnly, componentVariant]: SkipSet,\n component: string,\n variant: string,\n): boolean {\n return componentOnly.has(component) || componentVariant.has(`${component}\\0${variant}`);\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\n\nconst { HAPPO_DEBUG } = process.env;\n\nexport default function getStorybookBuildCommandParts(\n packageJsonPath: string = path.join(process.cwd(), 'package.json'),\n): [string, string] {\n try {\n const data = fs.readFileSync(packageJsonPath, 'utf8');\n const packageJson = JSON.parse(data);\n\n if (packageJson.scripts.storybook) {\n if (HAPPO_DEBUG) {\n console.log(\n '[happo] Found `storybook` script in package.json. Will attempt to use binary found at `node_modules/.bin/storybook` instead',\n );\n }\n\n const pathToStorybookCommand = path.join(\n process.cwd(),\n 'node_modules',\n '.bin',\n 'storybook',\n );\n\n if (fs.existsSync(pathToStorybookCommand)) {\n return [pathToStorybookCommand, 'build'];\n }\n }\n } catch (e) {\n if (HAPPO_DEBUG) {\n console.log(\n '[happo] Caught error when resolving Storybook build command parts. Will use default.',\n e,\n );\n }\n }\n\n return ['storybook', 'build'];\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\n\nexport default function getStorybookVersionFromPackageJson(\n packageJsonPath: string = path.join(process.cwd(), 'package.json'),\n): number {\n const data = fs.readFileSync(packageJsonPath, 'utf8');\n const packageJson = JSON.parse(data);\n\n const combinedDependencies = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n const storybookPackage = [\n 'storybook',\n '@storybook/react',\n '@storybook/angular',\n '@storybook/vue',\n ].find((pkg) => combinedDependencies[pkg]);\n\n if (storybookPackage) {\n const storybookVersion = combinedDependencies[storybookPackage];\n const majorVersion = Number.parseInt(storybookVersion.match(/\\d+/)[0], 10);\n return majorVersion;\n } else {\n throw new Error('Storybook is not listed as a dependency in package.json');\n }\n}\n", "import path from 'node:path';\n\nimport type { SkipItem } from '../isomorphic/types.ts';\n\nexport interface StorybookIndexEntry {\n type: string;\n importPath?: string;\n title?: string;\n name?: string;\n}\n\n/**\n * Resolves `storyFile` skip items to component-based skip items using the\n * Storybook `index.json` entries. Items that already have a `component` are\n * passed through unchanged.\n *\n * Path matching is done by normalising both the `importPath` from the index\n * and the user-supplied `storyFile` (stripping a leading `./`), with an\n * absolute-path fallback via `path.resolve`.\n */\nexport default function resolveStoryFileItems(\n skip: Array<SkipItem>,\n entries: Record<string, StorybookIndexEntry>,\n): Array<{ component: string; variant?: string }> {\n const fileToComponents = new Map<string, Set<string>>();\n for (const entry of Object.values(entries)) {\n if (!entry.importPath || !entry.title) continue;\n const normalized = normalizeImportPath(entry.importPath);\n let set = fileToComponents.get(normalized);\n if (!set) {\n set = new Set();\n fileToComponents.set(normalized, set);\n }\n set.add(entry.title);\n }\n\n const resolved: Array<{ component: string; variant?: string }> = [];\n\n for (const item of skip) {\n if ('component' in item) {\n resolved.push(item);\n continue;\n }\n\n const normalizedFile = normalizeImportPath(item.storyFile);\n let components = fileToComponents.get(normalizedFile);\n\n if (!components) {\n // Fall back to absolute path comparison\n const resolvedFile = path.resolve(item.storyFile);\n for (const [normalizedImport, titles] of fileToComponents) {\n if (path.resolve(normalizedImport) === resolvedFile) {\n components = titles;\n break;\n }\n }\n }\n\n if (components) {\n for (const component of components) {\n resolved.push({ component });\n }\n } else {\n console.warn(\n `[HAPPO] Could not find any stories for storyFile '${item.storyFile}' in the Storybook index`,\n );\n }\n }\n\n return resolved;\n}\n\nfunction normalizeImportPath(p: string): string {\n return p.startsWith('./') ? p.slice(2) : p;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["fs", "path", "fs", "path", "path", "HAPPO_DEBUG", "fs", "path"]
7
7
  }
@@ -3,5 +3,9 @@ interface SkipItem {
3
3
  variant: string;
4
4
  }
5
5
  export type SkipItems = Array<SkipItem>;
6
+ interface OnlyItem {
7
+ component: string;
8
+ }
9
+ export type OnlyItems = Array<OnlyItem>;
6
10
  export {};
7
11
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/storybook/isomorphic/types.ts"],"names":[],"mappings":"AAAA,UAAU,QAAQ;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/storybook/isomorphic/types.ts"],"names":[],"mappings":"AAAA,UAAU,QAAQ;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;AAExC,UAAU,QAAQ;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { SkipItem } from '../isomorphic/types.ts';
2
+ export interface StorybookIndexEntry {
3
+ type: string;
4
+ importPath?: string;
5
+ title?: string;
6
+ name?: string;
7
+ }
8
+ /**
9
+ * Resolves `storyFile` skip items to component-based skip items using the
10
+ * Storybook `index.json` entries. Items that already have a `component` are
11
+ * passed through unchanged.
12
+ *
13
+ * Path matching is done by normalising both the `importPath` from the index
14
+ * and the user-supplied `storyFile` (stripping a leading `./`), with an
15
+ * absolute-path fallback via `path.resolve`.
16
+ */
17
+ export default function resolveStoryFileItems(skip: Array<SkipItem>, entries: Record<string, StorybookIndexEntry>): Array<{
18
+ component: string;
19
+ variant?: string;
20
+ }>;
21
+ //# sourceMappingURL=resolveStoryFileItems.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveStoryFileItems.d.ts","sourceRoot":"","sources":["../../src/storybook/resolveStoryFileItems.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAC3C,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,EACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,GAC3C,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA+ChD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "happo",
3
- "version": "6.9.0",
3
+ "version": "6.10.1",
4
4
  "description": "Catch unexpected visual and accessibility changes and UI bugs",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -75,7 +75,10 @@
75
75
  "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",
76
76
  "test:playwright:nonce": "pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.playwright-nonce.config.ts --nonce $HAPPO_NONCE e2e -- playwright test && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.playwright-nonce.config.ts --nonce $HAPPO_NONCE finalize",
77
77
  "test:storybook": "pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.storybook.config.ts",
78
+ "test:storybook:skipped": "pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.storybook.config.ts --project storybook-skipped --skip \"$(node ./scripts/getSkip.ts)\"",
79
+ "test:storybook:only": "pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.storybook.config.ts --project storybook-only --only \"$(node ./scripts/getOnly.ts)\"",
78
80
  "test:pages": "pnpm build:dist && node --env-file-if-exists=.env.local dist/cli/main.js -c ./happoconfigs/happo.pages.config.ts",
81
+ "release": "set -a && source .env && set +a && release-with-ease",
79
82
  "tsc": "tsc --build tsconfig.json"
80
83
  },
81
84
  "browserslist": {
@@ -117,13 +120,13 @@
117
120
  "@types/react": "^19.2.0",
118
121
  "@types/react-dom": "^19.2.0",
119
122
  "cypress": "^15.5.0",
120
- "esbuild": "^0.27.0",
123
+ "esbuild": "^0.28.0",
121
124
  "eslint": "^10.0.2",
122
125
  "eslint-config-prettier": "^10.1.8",
123
126
  "eslint-plugin-compat": "^7.0.1",
124
127
  "eslint-plugin-depend": "^1.4.0",
125
128
  "eslint-plugin-simple-import-sort": "^12.1.1",
126
- "eslint-plugin-unicorn": "^63.0.0",
129
+ "eslint-plugin-unicorn": "^64.0.0",
127
130
  "jiti": "^2.6.1",
128
131
  "jsdom": "^29.0.0",
129
132
  "multiparty": "^4.2.3",
@@ -133,6 +136,7 @@
133
136
  "react-error-boundary": "^6.0.0",
134
137
  "storybook": "^10.0.1",
135
138
  "typescript": "^6.0.2",
139
+ "release-with-ease": "^2.1.0",
136
140
  "typescript-eslint": "^8.57.2"
137
141
  },
138
142
  "dependencies": {
@@ -1,10 +0,0 @@
1
- import {
2
- cancelJob
3
- } from "./chunk-BK32666K.js";
4
- import "./chunk-R6YURZXU.js";
5
- import "./chunk-BESQLM5F.js";
6
- import "./chunk-P4EXA4AX.js";
7
- export {
8
- cancelJob as default
9
- };
10
- //# sourceMappingURL=cancelJob-Y4WJCCU6.js.map