From 7553e764851ae89c6ce2874fb2d96d5e27302a2a Mon Sep 17 00:00:00 2001 From: Pranay Kothapalli Date: Sun, 7 Sep 2025 09:20:27 +0530 Subject: [PATCH 1/5] ci: run storybook smoke tests --- .github/workflows/storybook.yml | 24 ++++++++++++++++++++++++ .storybook/test-runner.js | 11 +++++++++++ package.json | 1 + 3 files changed, 36 insertions(+) create mode 100644 .github/workflows/storybook.yml create mode 100644 .storybook/test-runner.js diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml new file mode 100644 index 000000000..5b94b879d --- /dev/null +++ b/.github/workflows/storybook.yml @@ -0,0 +1,24 @@ +name: Storybook Build and Test + +on: + pull_request: + push: + branches: [main] + +jobs: + storybook: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: '18' + cache: 'npm' + - name: Install dependencies + run: npm ci + - name: Install Playwright + run: npx playwright install --with-deps chromium + - name: Build Storybook + run: npm run build-storybook + - name: Storybook smoke tests + run: npx storybook test --index-json ./storybook-static/index.json diff --git a/.storybook/test-runner.js b/.storybook/test-runner.js new file mode 100644 index 000000000..0ee2c9a82 --- /dev/null +++ b/.storybook/test-runner.js @@ -0,0 +1,11 @@ +import { within, userEvent } from '@storybook/testing-library'; + +// Basic smoke test for each story. If a button exists, click it to ensure interactions +// don't trigger runtime errors. +export const run = async ({ canvasElement }) => { + const canvas = within(canvasElement); + const button = canvas.queryByRole('button'); + if (button) { + await userEvent.click(button); + } +}; diff --git a/package.json b/package.json index bc80bc919..2b482d059 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "sb": "storybook dev -p 6006", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", + "test-storybook": "storybook test --index-json ./storybook-static/index.json", "build-css": "rollup -c rollup-css.config.js", "generate-tokens": "tsx ./src/tokenGen/index.js", "bundle-tokens": "rollup --config rollup-tokens.config.js", From 8803f370a4e930d82bd88e252c0c3b3c9fa1ff47 Mon Sep 17 00:00:00 2001 From: Pranay Kothapalli Date: Wed, 10 Sep 2025 19:01:15 +0530 Subject: [PATCH 2/5] Handle multiple buttons in Storybook smoke tests --- .github/workflows/storybook.yml | 3 +++ .storybook/test-runner.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index 5b94b879d..0ae453166 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -5,6 +5,9 @@ on: push: branches: [main] +permissions: + contents: read + jobs: storybook: runs-on: ubuntu-latest diff --git a/.storybook/test-runner.js b/.storybook/test-runner.js index 0ee2c9a82..ee75058b6 100644 --- a/.storybook/test-runner.js +++ b/.storybook/test-runner.js @@ -4,7 +4,7 @@ import { within, userEvent } from '@storybook/testing-library'; // don't trigger runtime errors. export const run = async ({ canvasElement }) => { const canvas = within(canvasElement); - const button = canvas.queryByRole('button'); + const [button] = canvas.queryAllByRole('button'); if (button) { await userEvent.click(button); } From 85dce38540855042bb73e2af26652377436788d5 Mon Sep 17 00:00:00 2001 From: Pranay Kothapalli Date: Wed, 10 Sep 2025 19:09:46 +0530 Subject: [PATCH 3/5] docs: explain Storybook smoke test runner --- .storybook/test-runner.js | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/.storybook/test-runner.js b/.storybook/test-runner.js index ee75058b6..f8a3ceaa2 100644 --- a/.storybook/test-runner.js +++ b/.storybook/test-runner.js @@ -1,9 +1,30 @@ +/** + * Basic smoke tests for Storybook stories. + * + * This configuration runs in CI via the Storybook test runner. It renders each + * story and performs a minimal interaction to surface runtime errors that unit + * tests might miss. + * + * What it covers: + * - Verifies that stories render without throwing. + * - Clicks the first button (if present) to catch simple interaction bugs. + * + * What it doesn't cover: + * - Visual regressions or accessibility checks. + * - Complex workflows that require multiple interactions. + * - Stories that depend on network requests or auth; those may require mocks + * or can be excluded from CI if flaky. + * + * This smoke test is a lightweight safety net and does not replace dedicated + * unit, integration, or visual testing. + */ import { within, userEvent } from '@storybook/testing-library'; -// Basic smoke test for each story. If a button exists, click it to ensure interactions -// don't trigger runtime errors. +// If a button exists, click the first one to ensure the interaction doesn't trigger +// runtime errors. export const run = async ({ canvasElement }) => { const canvas = within(canvasElement); + // Use queryAllByRole so the test runner doesn't throw when multiple buttons are present. const [button] = canvas.queryAllByRole('button'); if (button) { await userEvent.click(button); From 5193b40439210da9a934398016af6f8f8df4893a Mon Sep 17 00:00:00 2001 From: Pranay Kothapalli Date: Wed, 10 Sep 2025 19:24:29 +0530 Subject: [PATCH 4/5] fix: use storybook test-runner CLI --- .github/workflows/storybook.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index 0ae453166..4590c897b 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -24,4 +24,4 @@ jobs: - name: Build Storybook run: npm run build-storybook - name: Storybook smoke tests - run: npx storybook test --index-json ./storybook-static/index.json + run: npm run test-storybook diff --git a/package.json b/package.json index 2b482d059..10ebd5523 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "sb": "storybook dev -p 6006", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", - "test-storybook": "storybook test --index-json ./storybook-static/index.json", + "test-storybook": "npx @storybook/test-runner --index-json ./storybook-static/index.json", "build-css": "rollup -c rollup-css.config.js", "generate-tokens": "tsx ./src/tokenGen/index.js", "bundle-tokens": "rollup --config rollup-tokens.config.js", From 9a09a888e88871f456e276e1fb7c0dad3912719a Mon Sep 17 00:00:00 2001 From: Pranay Kothapalli Date: Wed, 10 Sep 2025 21:14:49 +0530 Subject: [PATCH 5/5] fix: load Storybook testing utilities lazily --- .storybook/test-runner.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.storybook/test-runner.js b/.storybook/test-runner.js index f8a3ceaa2..7d874352b 100644 --- a/.storybook/test-runner.js +++ b/.storybook/test-runner.js @@ -18,13 +18,17 @@ * This smoke test is a lightweight safety net and does not replace dedicated * unit, integration, or visual testing. */ -import { within, userEvent } from '@storybook/testing-library'; - // If a button exists, click the first one to ensure the interaction doesn't trigger // runtime errors. export const run = async ({ canvasElement }) => { + // Import testing utilities inside the runner so that Storybook's jsdom + // environment is available. Importing at the module level throws because the + // package expects `location` to exist on the global object. + const { within, userEvent } = await import('@storybook/testing-library'); + const canvas = within(canvasElement); - // Use queryAllByRole so the test runner doesn't throw when multiple buttons are present. + // Use queryAllByRole so the test runner doesn't throw when multiple buttons + // are present. const [button] = canvas.queryAllByRole('button'); if (button) { await userEvent.click(button);