@argos-ci/storybook 6.0.17 → 6.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  </a>
8
8
  </p>
9
9
 
10
- <p align="center"><strong>The open source visual testing plaform for modern engineering teams.</strong></p>
10
+ <p align="center"><strong>The open source visual testing platform for AI-native engineering teams.</strong></p>
11
11
 
12
12
  # Official Argos Storybook integration
13
13
 
@@ -15,9 +15,52 @@
15
15
  [![npm dm](https://img.shields.io/npm/dm/@argos-ci/storybook.svg)](https://www.npmjs.com/package/@argos-ci/storybook)
16
16
  [![npm dt](https://img.shields.io/npm/dt/@argos-ci/storybook.svg)](https://www.npmjs.com/package/@argos-ci/storybook)
17
17
 
18
- Visit [argos-ci.com/docs/storybook](https://argos-ci.com/docs/storybook) for guides, API and more.
18
+ Capture and review visual changes of your [Storybook](https://storybook.js.org/) stories with Argos. It runs your stories in a real browser and uploads a screenshot of each one to Argos in your CI.
19
+
20
+ Visit the [Storybook SDK documentation](https://argos-ci.com/docs/sdks-reference/storybook) for guides, the API reference, and more.
21
+
22
+ ## Installation
23
+
24
+ ```sh
25
+ npm install --save-dev @argos-ci/storybook
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ The recommended way to run visual tests is with the [Storybook Vitest addon](https://storybook.js.org/docs/writing-tests/integrations/vitest-addon). Register the Argos plugin in your Vitest config:
31
+
32
+ ```ts
33
+ // vitest.config.ts
34
+ import { defineConfig } from "vitest/config";
35
+ import { argosVitestPlugin } from "@argos-ci/storybook/vitest-plugin";
36
+
37
+ export default defineConfig({
38
+ plugins: [
39
+ argosVitestPlugin({
40
+ // Upload the screenshots to Argos only on CI.
41
+ uploadToArgos: process.env.CI === "true",
42
+ }),
43
+ ],
44
+ });
45
+ ```
46
+
47
+ A screenshot is captured for every story automatically. To capture additional screenshots (for example, at different steps of an interaction), call `argosScreenshot` inside a story's `play` function:
48
+
49
+ ```ts
50
+ // Button.stories.tsx
51
+ import { argosScreenshot } from "@argos-ci/storybook/vitest";
52
+
53
+ export const Example: Story = {
54
+ play: async (ctx) => {
55
+ await argosScreenshot(ctx, "example");
56
+ },
57
+ };
58
+ ```
59
+
60
+ > Using the [Storybook Test Runner](https://storybook.js.org/docs/writing-tests/integrations/test-runner) instead? Import `argosScreenshot` from `@argos-ci/storybook/test-runner` and call it from the `postVisit` hook. See the [Test Runner quickstart](https://argos-ci.com/docs/quickstart/storybook-quickstart/storybook-test-runner-quickstart).
19
61
 
20
62
  ## Links
21
63
 
22
- - [Official SDK Docs](https://argos-ci.com/docs/)
64
+ - [Official SDK Docs](https://argos-ci.com/docs/sdks-reference/storybook)
65
+ - [Quickstart](https://argos-ci.com/docs/quickstart/storybook-quickstart)
23
66
  - [Discord](https://argos-ci.com/discord)
@@ -38,7 +38,7 @@ type ArgosScreenshotOptions = Omit<ArgosScreenshotOptions$1, "viewports">;
38
38
  * Stabilize the UI and takes a screenshot of the application under test.
39
39
  *
40
40
  * @example argosScreenshot(page, context, options)
41
- * @see https://argos-ci.com/docs/playwright#api-overview
41
+ * @see https://argos-ci.com/docs/sdks-reference/playwright
42
42
  */
43
43
  declare function argosScreenshot(
44
44
  /**
@@ -263,7 +263,7 @@ const DEFAULT_PLAYWRIGHT_VIEWPORT_SIZE = {
263
263
  * Stabilize the UI and takes a screenshot of the application under test.
264
264
  *
265
265
  * @example argosScreenshot(page, context, options)
266
- * @see https://argos-ci.com/docs/playwright#api-overview
266
+ * @see https://argos-ci.com/docs/sdks-reference/playwright
267
267
  */
268
268
  async function argosScreenshot(page, context, options) {
269
269
  const storyContext = await getStoryContext(page, context);
@@ -1,8 +1,9 @@
1
1
  import { ArgosScreenshotOptions as ArgosScreenshotOptions$1, MetadataConfig } from "@argos-ci/playwright";
2
- import { UploadParameters } from "@argos-ci/core";
2
+ import { ArgosReporterConfig } from "@argos-ci/vitest/plugin";
3
3
  import { Plugin } from "vitest/config";
4
4
  import { BrowserCommand } from "vitest/node";
5
5
  import { Frame, Page, ViewportSize } from "playwright";
6
+
6
7
  //#region src/utils/parameters.d.ts
7
8
  type StorybookGlobals = Record<string, any>;
8
9
  //#endregion
@@ -35,9 +36,6 @@ type StorybookScreenshotContext<Handler extends Page | Frame> = {
35
36
  };
36
37
  type ArgosScreenshotOptions = Omit<ArgosScreenshotOptions$1, "viewports">;
37
38
  //#endregion
38
- //#region src/vitest-reporter.d.ts
39
- type ArgosReporterConfig = UploadParameters;
40
- //#endregion
41
39
  //#region src/vitest-plugin.d.ts
42
40
  type ArgosScreenshotCommandArgs = [Pick<StorybookScreenshotContext<Frame>, "name" | "story" | "test" | "mode">];
43
41
  interface ArgosVitestPluginOptions extends ArgosReporterConfig, ArgosScreenshotOptions {
@@ -1,7 +1,8 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { DO_NOT_USE_setMetadataConfig, argosScreenshot } from "@argos-ci/playwright";
3
3
  import { readVersionFromPackage } from "@argos-ci/util";
4
- import { upload } from "@argos-ci/core";
4
+ import { ArgosReporter } from "@argos-ci/vitest/plugin";
5
+ import { fitIframeToContent, resetTesterScale, setIframeViewportSize } from "@argos-ci/vitest/internal";
5
6
  import { dirname, resolve } from "node:path";
6
7
  import { fileURLToPath } from "node:url";
7
8
  //#region src/utils/metadata.ts
@@ -240,26 +241,6 @@ function composeName(name, suffix) {
240
241
  return name + (suffix ?? "");
241
242
  }
242
243
  //#endregion
243
- //#region src/vitest-reporter.ts
244
- var ArgosReporter = class {
245
- vitest;
246
- config;
247
- constructor(config) {
248
- this.config = config;
249
- }
250
- onInit(vitest) {
251
- this.vitest = vitest;
252
- }
253
- async onFinished() {
254
- await this.onTestRunEnd();
255
- }
256
- async onTestRunEnd() {
257
- if (this.vitest.config.watch) return;
258
- const res = await upload(this.config);
259
- console.log(`✅ Argos build created: ${res.build.url}`);
260
- }
261
- };
262
- //#endregion
263
244
  //#region src/vitest-plugin.ts
264
245
  /**
265
246
  * Create a command for taking Argos screenshots in Vitest.
@@ -269,55 +250,21 @@ const createArgosScreenshotCommand = (pluginOptions) => {
269
250
  return async (ctx, testContext) => {
270
251
  const frame = await ctx.frame();
271
252
  const fitToContent = getFitToContentFromParameters(testContext.story.parameters);
272
- const after = await before(ctx);
253
+ const after = await resetTesterScale(ctx);
273
254
  const options = applyFitToContent(screenshotOptions, fitToContent);
274
255
  const userBeforeScreenshot = options?.beforeScreenshot;
275
256
  const optionsWithFit = {
276
257
  ...options,
277
258
  beforeScreenshot: async (api) => {
278
259
  await userBeforeScreenshot?.(api);
279
- await ctx.page.evaluate(() => {
280
- const iframe = document.querySelector("iframe[data-vitest=\"true\"]");
281
- if (!(iframe instanceof HTMLIFrameElement) || !iframe.contentDocument) return;
282
- const { body, documentElement } = iframe.contentDocument;
283
- const contentHeight = Math.max(body.scrollHeight, body.offsetHeight, documentElement.scrollHeight);
284
- if (contentHeight > iframe.clientHeight) iframe.style.height = `${contentHeight}px`;
285
- });
260
+ await fitIframeToContent(ctx, { fitWidth: Boolean(fitToContent) });
286
261
  }
287
262
  };
288
263
  const attachments = await storybookArgosScreenshot(frame, {
289
264
  ...testContext,
290
265
  playwrightLibraries: ["@storybook/addon-vitest"],
291
266
  setViewportSize: async (size) => {
292
- await ctx.page.evaluate(({ size, fullPage }) => {
293
- const iframe = document.querySelector("iframe[data-vitest=\"true\"]");
294
- if (!(iframe instanceof HTMLIFrameElement)) throw new Error("Vitest iframe not found");
295
- if (!iframe.contentDocument) throw new Error("Vitest iframe contentDocument not found");
296
- if (size === "initial") {
297
- if (iframe.dataset.initialWidth && iframe.dataset.initialHeight) {
298
- iframe.style.width = iframe.dataset.initialWidth;
299
- iframe.style.height = iframe.dataset.initialHeight;
300
- }
301
- return;
302
- }
303
- if (!iframe.dataset.initialWidth && !iframe.dataset.initialHeight) {
304
- iframe.dataset.initialWidth = iframe.style.width;
305
- iframe.dataset.initialHeight = iframe.style.height;
306
- }
307
- if (size !== "default") iframe.style.width = `${size.width}px`;
308
- if (fullPage) {
309
- if (!iframe.contentWindow) throw new Error(`Can't access iframe window`);
310
- const viewportHeight = size === "default" ? iframe.contentWindow.innerHeight : size.height;
311
- iframe.style.height = "auto";
312
- iframe.style.height = viewportHeight < iframe.contentDocument.body.offsetHeight ? `${iframe.contentDocument.body.offsetHeight}px` : "100%";
313
- } else if (size !== "default") {
314
- iframe.style.height = "auto";
315
- iframe.style.height = `${size.height}px`;
316
- }
317
- }, {
318
- size,
319
- fullPage: screenshotOptions.fullPage ?? !fitToContent
320
- });
267
+ await setIframeViewportSize(ctx, size, { fullPage: screenshotOptions.fullPage ?? !fitToContent });
321
268
  }
322
269
  }, optionsWithFit);
323
270
  await after();
@@ -325,28 +272,6 @@ const createArgosScreenshotCommand = (pluginOptions) => {
325
272
  };
326
273
  };
327
274
  /**
328
- * Run before taking the screenshots.
329
- * Remove the scale from vitest "vitest-tester" div
330
- * to avoid ending up with small screenshots.
331
- * @returns A function to restore the scale after the test.
332
- */
333
- async function before(ctx) {
334
- await ctx.page.evaluate(() => {
335
- const tester = document.getElementById("vitest-tester");
336
- if (!(tester instanceof HTMLElement)) return;
337
- if (!tester.getAttribute("data-scale")) throw new Error("Vitest iframe data-scale attribute not found");
338
- tester.dataset.bckTransform = tester.style.transform;
339
- tester.style.transform = `scale(1)`;
340
- });
341
- return async () => {
342
- await ctx.page.evaluate(() => {
343
- const tester = document.getElementById("vitest-tester");
344
- if (!(tester instanceof HTMLElement)) return;
345
- tester.style.transform = tester.dataset.bckTransform ?? "";
346
- });
347
- };
348
- }
349
- /**
350
275
  * Apply fitToContent options to the screenshot options.
351
276
  */
352
277
  function applyFitToContent(options, fitToContent) {
@@ -375,7 +300,7 @@ function argosVitestPlugin(options) {
375
300
  config() {
376
301
  return {
377
302
  optimizeDeps: { include: ["@argos-ci/storybook/internal/vitest-setup-file"] },
378
- test: { browser: { commands: { argosScreenshot: createArgosScreenshotCommand({
303
+ test: { browser: { commands: { argosStorybookScreenshot: createArgosScreenshotCommand({
379
304
  ...otherOptions,
380
305
  root
381
306
  }) } } }
@@ -27,7 +27,7 @@ function setupArgos(api) {
27
27
  if (!story) throw new Error(`@argos-ci/storybook/vitest-plugin should be used with @storybook/addon-vitest/vitest-plugin`);
28
28
  const { server } = await import("vitest/browser");
29
29
  globalThis.__ARGOS_STORYBOOK_STORY = story;
30
- await server.commands.argosScreenshot({
30
+ await server.commands.argosStorybookScreenshot({
31
31
  mode: "automatic",
32
32
  name: story.id,
33
33
  story: {
package/dist/vitest.d.mts CHANGED
@@ -39,7 +39,7 @@ type ArgosScreenshotCommandArgs = [Pick<StorybookScreenshotContext<Frame>, "name
39
39
  //#region src/vitest.d.ts
40
40
  declare module "vitest/browser" {
41
41
  interface BrowserCommands {
42
- argosScreenshot: (...args: ArgosScreenshotCommandArgs) => Promise<ArgosAttachment[]>;
42
+ argosStorybookScreenshot: (...args: ArgosScreenshotCommandArgs) => Promise<ArgosAttachment[]>;
43
43
  }
44
44
  }
45
45
  /**
package/dist/vitest.mjs CHANGED
@@ -26,7 +26,7 @@ function setupArgos(api) {
26
26
  if (!story) throw new Error(`@argos-ci/storybook/vitest-plugin should be used with @storybook/addon-vitest/vitest-plugin`);
27
27
  const { server } = await import("vitest/browser");
28
28
  globalThis.__ARGOS_STORYBOOK_STORY = story;
29
- await server.commands.argosScreenshot({
29
+ await server.commands.argosStorybookScreenshot({
30
30
  mode: "automatic",
31
31
  name: story.id,
32
32
  story: {
@@ -55,7 +55,7 @@ function setupArgos(api) {
55
55
  async function argosScreenshot(story, name) {
56
56
  if (!await checkIsVitestEnv()) return;
57
57
  const { server } = await import("vitest/browser");
58
- await server.commands.argosScreenshot({
58
+ await server.commands.argosStorybookScreenshot({
59
59
  mode: "manual",
60
60
  name: `${story.id}/${name}`,
61
61
  story: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@argos-ci/storybook",
3
3
  "description": "Visual testing for Storybook test runner.",
4
- "version": "6.0.17",
4
+ "version": "6.1.3",
5
5
  "author": "Smooth Code",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -9,7 +9,7 @@
9
9
  "url": "https://github.com/argos-ci/argos-javascript.git",
10
10
  "directory": "packages/storybook"
11
11
  },
12
- "homepage": "https://argos-ci.com/docs/storybook",
12
+ "homepage": "https://argos-ci.com/docs/sdks-reference/storybook",
13
13
  "keywords": [
14
14
  "storybook",
15
15
  "storybook-addon",
@@ -49,12 +49,13 @@
49
49
  "node": ">=22.0.0"
50
50
  },
51
51
  "dependencies": {
52
- "@argos-ci/core": "6.4.0",
53
- "@argos-ci/playwright": "7.3.0",
54
- "@argos-ci/util": "4.0.0"
52
+ "@argos-ci/core": "6.5.3",
53
+ "@argos-ci/playwright": "7.3.4",
54
+ "@argos-ci/util": "4.0.4",
55
+ "@argos-ci/vitest": "0.2.3"
55
56
  },
56
57
  "devDependencies": {
57
- "@argos-ci/cli": "6.1.0",
58
+ "@argos-ci/cli": "6.1.4",
58
59
  "@argos-ci/util": "workspace:*",
59
60
  "@storybook/addon-docs": "^10.4.6",
60
61
  "@storybook/addon-links": "^10.4.6",
@@ -62,6 +63,7 @@
62
63
  "@storybook/addon-vitest": "^10.4.6",
63
64
  "@storybook/react-vite": "^10.4.6",
64
65
  "@storybook/test-runner": "^0.24.4",
66
+ "@types/node": "catalog:",
65
67
  "@types/react": "^19.2.17",
66
68
  "@types/react-dom": "^19.2.3",
67
69
  "@vitest/browser": "^4.1.9",
@@ -98,5 +100,5 @@
98
100
  "check-format": "prettier --check --ignore-unknown --ignore-path=./.gitignore --ignore-path=../../.gitignore --ignore-path=../../.prettierignore .",
99
101
  "lint": "eslint ."
100
102
  },
101
- "gitHead": "3502fe8f348376405f56703b351037150d2c9136"
103
+ "gitHead": "1b25b7c1109a3d032d627c5f9d2f2c3937731aea"
102
104
  }