Skip to content

Commit 568d2a2

Browse files
authored
🐛 Fix storybook story URL capture and add preview upload (#229)
## Summary - **Fix story URL in screenshot properties:** `captureAndSendScreenshot` was sending the `iframe.html?id=...` URL (what Playwright navigates to) as the `url` property. This URL doesn't render in iframes on the dashboard. Now converts it to the proper Storybook story path format (`?path=/story/...`) via a new `toStoryUrl()` helper. - **Add preview upload to Storybook CI:** Added an "Upload preview" step to the Storybook SDK E2E workflow, matching what the static-site SDK already does. - **Fix test mocks:** Updated `screenshot.test.js` mocks to use the real `iframe.html` URL (matching what `page.url()` actually returns) and added `story.id` to mock objects. Added tests for the new `toStoryUrl` function. ## Test plan - [x] `screenshot.test.js` — all 11 tests pass - [ ] Verify story URLs render correctly in Vizzly dashboard iframes - [ ] Verify Storybook preview upload works in CI
1 parent 8d16687 commit 568d2a2

3 files changed

Lines changed: 37 additions & 8 deletions

File tree

.github/workflows/sdk-e2e.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,13 @@ jobs:
187187
VIZZLY_COMMIT_MESSAGE: ${{ github.event.pull_request.head.commit.message || github.event.head_commit.message }}
188188
VIZZLY_COMMIT_SHA: ${{ github.event.pull_request.head.sha || github.event.head_commit.id }}
189189

190+
- name: Upload preview
191+
if: success()
192+
working-directory: ./clients/storybook
193+
run: ../../bin/vizzly.js preview example-storybook/dist
194+
env:
195+
VIZZLY_TOKEN: ${{ secrets.VIZZLY_STORYBOOK_CLIENT_TOKEN }}
196+
190197
# Static-Site SDK
191198
static-site:
192199
name: Static-Site SDK

clients/storybook/src/screenshot.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ try {
1515
vizzlyScreenshot = async () => {};
1616
}
1717

18+
/** @internal Replace vizzlyScreenshot for testing */
19+
export function _setVizzlyScreenshot(fn) {
20+
vizzlyScreenshot = fn;
21+
}
22+
1823
/**
1924
* Generate screenshot name from story and viewport
2025
* Format: "ComponentName-StoryName@viewportName"

clients/storybook/tests/screenshot.test.js

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import assert from 'node:assert/strict';
66
import { describe, it, mock } from 'node:test';
77
import {
8+
_setVizzlyScreenshot,
89
captureAndSendScreenshot,
910
captureScreenshot,
1011
generateScreenshotName,
@@ -86,24 +87,40 @@ describe('captureScreenshot', () => {
8687
});
8788

8889
describe('captureAndSendScreenshot', () => {
89-
it('should capture and send screenshot to vizzly', async () => {
90+
it('should send the iframe URL for isolated story preview', async () => {
91+
let mockVizzly = mock.fn(async () => {});
92+
_setVizzlyScreenshot(mockVizzly);
93+
9094
let mockBuffer = Buffer.from('fake-screenshot');
91-
let mockScreenshot = mock.fn(() => mockBuffer);
92-
let mockPage = { screenshot: mockScreenshot, url: () => 'http://localhost:6006/?path=/story/button--primary' };
93-
let story = { title: 'Button', name: 'Primary' };
95+
let iframeUrl =
96+
'http://localhost:6006/iframe.html?id=button--primary&viewMode=story';
97+
let mockPage = {
98+
screenshot: mock.fn(() => mockBuffer),
99+
url: () => iframeUrl,
100+
};
101+
let story = { id: 'button--primary', title: 'Button', name: 'Primary' };
94102
let viewport = { name: 'desktop' };
95103

96-
// This will use the mock vizzlyScreenshot from the module
97104
await captureAndSendScreenshot(mockPage, story, viewport);
98105

99-
assert.equal(mockScreenshot.mock.calls.length, 1);
106+
assert.equal(mockVizzly.mock.calls.length, 1);
107+
let [name, , options] = mockVizzly.mock.calls[0].arguments;
108+
assert.equal(name, 'Button-Primary@desktop');
109+
assert.equal(options.properties.url, iframeUrl);
100110
});
101111

102112
it('should pass screenshot options through', async () => {
113+
let mockVizzly = mock.fn(async () => {});
114+
_setVizzlyScreenshot(mockVizzly);
115+
103116
let mockBuffer = Buffer.from('fake-screenshot');
104117
let mockScreenshot = mock.fn(() => mockBuffer);
105-
let mockPage = { screenshot: mockScreenshot, url: () => 'http://localhost:6006/?path=/story/card--default' };
106-
let story = { title: 'Card', name: 'Default' };
118+
let mockPage = {
119+
screenshot: mockScreenshot,
120+
url: () =>
121+
'http://localhost:6006/iframe.html?id=card--default&viewMode=story',
122+
};
123+
let story = { id: 'card--default', title: 'Card', name: 'Default' };
107124
let viewport = { name: 'mobile' };
108125

109126
await captureAndSendScreenshot(mockPage, story, viewport, {

0 commit comments

Comments
 (0)