@argos-ci/storybook 6.0.18 → 6.1.4
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 +46 -3
- package/dist/test-runner.d.mts +1 -1
- package/dist/test-runner.mjs +1 -1
- package/dist/vitest-plugin.d.mts +2 -4
- package/dist/vitest-plugin.mjs +6 -85
- package/dist/vitest-setup-file.mjs +1 -1
- package/dist/vitest.d.mts +1 -1
- package/dist/vitest.mjs +2 -2
- package/package.json +9 -7
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
|
|
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
|
[](https://www.npmjs.com/package/@argos-ci/storybook)
|
|
16
16
|
[](https://www.npmjs.com/package/@argos-ci/storybook)
|
|
17
17
|
|
|
18
|
-
|
|
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)
|
package/dist/test-runner.d.mts
CHANGED
|
@@ -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
|
|
41
|
+
* @see https://argos-ci.com/docs/sdks-reference/playwright
|
|
42
42
|
*/
|
|
43
43
|
declare function argosScreenshot(
|
|
44
44
|
/**
|
package/dist/test-runner.mjs
CHANGED
|
@@ -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
|
|
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);
|
package/dist/vitest-plugin.d.mts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ArgosScreenshotOptions as ArgosScreenshotOptions$1, MetadataConfig } from "@argos-ci/playwright";
|
|
2
|
-
import {
|
|
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 {
|
package/dist/vitest-plugin.mjs
CHANGED
|
@@ -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 {
|
|
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,59 +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
|
|
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
|
|
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
|
-
if (fitWidth) {
|
|
286
|
-
const contentWidth = Math.max(body.scrollWidth, body.offsetWidth, documentElement.scrollWidth);
|
|
287
|
-
if (contentWidth > iframe.clientWidth) iframe.style.width = `${contentWidth}px`;
|
|
288
|
-
}
|
|
289
|
-
}, { fitWidth: Boolean(fitToContent) });
|
|
260
|
+
await fitIframeToContent(ctx, { fitWidth: Boolean(fitToContent) });
|
|
290
261
|
}
|
|
291
262
|
};
|
|
292
263
|
const attachments = await storybookArgosScreenshot(frame, {
|
|
293
264
|
...testContext,
|
|
294
265
|
playwrightLibraries: ["@storybook/addon-vitest"],
|
|
295
266
|
setViewportSize: async (size) => {
|
|
296
|
-
await ctx
|
|
297
|
-
const iframe = document.querySelector("iframe[data-vitest=\"true\"]");
|
|
298
|
-
if (!(iframe instanceof HTMLIFrameElement)) throw new Error("Vitest iframe not found");
|
|
299
|
-
if (!iframe.contentDocument) throw new Error("Vitest iframe contentDocument not found");
|
|
300
|
-
if (size === "initial") {
|
|
301
|
-
if (iframe.dataset.initialWidth && iframe.dataset.initialHeight) {
|
|
302
|
-
iframe.style.width = iframe.dataset.initialWidth;
|
|
303
|
-
iframe.style.height = iframe.dataset.initialHeight;
|
|
304
|
-
}
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
if (!iframe.dataset.initialWidth && !iframe.dataset.initialHeight) {
|
|
308
|
-
iframe.dataset.initialWidth = iframe.style.width;
|
|
309
|
-
iframe.dataset.initialHeight = iframe.style.height;
|
|
310
|
-
}
|
|
311
|
-
if (size !== "default") iframe.style.width = `${size.width}px`;
|
|
312
|
-
if (fullPage) {
|
|
313
|
-
if (!iframe.contentWindow) throw new Error(`Can't access iframe window`);
|
|
314
|
-
const viewportHeight = size === "default" ? iframe.contentWindow.innerHeight : size.height;
|
|
315
|
-
iframe.style.height = "auto";
|
|
316
|
-
iframe.style.height = viewportHeight < iframe.contentDocument.body.offsetHeight ? `${iframe.contentDocument.body.offsetHeight}px` : "100%";
|
|
317
|
-
} else if (size !== "default") {
|
|
318
|
-
iframe.style.height = "auto";
|
|
319
|
-
iframe.style.height = `${size.height}px`;
|
|
320
|
-
}
|
|
321
|
-
}, {
|
|
322
|
-
size,
|
|
323
|
-
fullPage: screenshotOptions.fullPage ?? !fitToContent
|
|
324
|
-
});
|
|
267
|
+
await setIframeViewportSize(ctx, size, { fullPage: screenshotOptions.fullPage ?? !fitToContent });
|
|
325
268
|
}
|
|
326
269
|
}, optionsWithFit);
|
|
327
270
|
await after();
|
|
@@ -329,28 +272,6 @@ const createArgosScreenshotCommand = (pluginOptions) => {
|
|
|
329
272
|
};
|
|
330
273
|
};
|
|
331
274
|
/**
|
|
332
|
-
* Run before taking the screenshots.
|
|
333
|
-
* Remove the scale from vitest "vitest-tester" div
|
|
334
|
-
* to avoid ending up with small screenshots.
|
|
335
|
-
* @returns A function to restore the scale after the test.
|
|
336
|
-
*/
|
|
337
|
-
async function before(ctx) {
|
|
338
|
-
await ctx.page.evaluate(() => {
|
|
339
|
-
const tester = document.getElementById("vitest-tester");
|
|
340
|
-
if (!(tester instanceof HTMLElement)) return;
|
|
341
|
-
if (!tester.getAttribute("data-scale")) throw new Error("Vitest iframe data-scale attribute not found");
|
|
342
|
-
tester.dataset.bckTransform = tester.style.transform;
|
|
343
|
-
tester.style.transform = `scale(1)`;
|
|
344
|
-
});
|
|
345
|
-
return async () => {
|
|
346
|
-
await ctx.page.evaluate(() => {
|
|
347
|
-
const tester = document.getElementById("vitest-tester");
|
|
348
|
-
if (!(tester instanceof HTMLElement)) return;
|
|
349
|
-
tester.style.transform = tester.dataset.bckTransform ?? "";
|
|
350
|
-
});
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
275
|
* Apply fitToContent options to the screenshot options.
|
|
355
276
|
*/
|
|
356
277
|
function applyFitToContent(options, fitToContent) {
|
|
@@ -379,7 +300,7 @@ function argosVitestPlugin(options) {
|
|
|
379
300
|
config() {
|
|
380
301
|
return {
|
|
381
302
|
optimizeDeps: { include: ["@argos-ci/storybook/internal/vitest-setup-file"] },
|
|
382
|
-
test: { browser: { commands: {
|
|
303
|
+
test: { browser: { commands: { argosStorybookScreenshot: createArgosScreenshotCommand({
|
|
383
304
|
...otherOptions,
|
|
384
305
|
root
|
|
385
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
4
|
+
"version": "6.1.4",
|
|
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.
|
|
53
|
-
"@argos-ci/playwright": "7.3.
|
|
54
|
-
"@argos-ci/util": "4.0.
|
|
52
|
+
"@argos-ci/core": "6.6.0",
|
|
53
|
+
"@argos-ci/playwright": "7.3.5",
|
|
54
|
+
"@argos-ci/util": "4.0.4",
|
|
55
|
+
"@argos-ci/vitest": "0.2.4"
|
|
55
56
|
},
|
|
56
57
|
"devDependencies": {
|
|
57
|
-
"@argos-ci/cli": "6.
|
|
58
|
+
"@argos-ci/cli": "6.2.0",
|
|
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": "
|
|
103
|
+
"gitHead": "686b6fa8385ed77598ec86f66b073e9897cef176"
|
|
102
104
|
}
|