Skip to content

feat: set up MSW for Storybook API mocking#930

Merged
Aureliolo merged 3 commits intomainfrom
feat/msw-storybook
Mar 30, 2026
Merged

feat: set up MSW for Storybook API mocking#930
Aureliolo merged 3 commits intomainfrom
feat/msw-storybook

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

  • Install msw + msw-storybook-addon and wire initialize()/mswLoader into Storybook preview
  • Create shared handler infrastructure in web/src/mocks/handlers/ with typed ApiResponse<T> envelope helper and reusable handlers for setup status and auth endpoints
  • Migrate LoginPage.stories.tsx from ESM namespace mutation workaround to declarative parameters.msw.handlers, eliminating the AdminCreationGate component
  • Update CLAUDE.md (package structure, dependencies) and brand-and-ux.md (Storybook tooling) to reflect MSW integration

Test plan

  • npm --prefix web run type-check passes
  • npm --prefix web run lint passes (zero warnings)
  • npm --prefix web run test passes (2145 tests)
  • npm --prefix web run storybook:build succeeds with mockServiceWorker.js in output
  • Manual: npm --prefix web run storybook -- verify DefaultLogin shows "Sign In" and AdminCreation shows "Create Admin Account"

Review coverage

Pre-reviewed by 3 agents (docs-consistency, frontend-reviewer, issue-resolution-verifier). 3 findings addressed (all docs drift). Frontend code review: clean, no issues.

Closes #898

🤖 Generated with Claude Code

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8f3584d3-50b9-4a55-a96f-60186c985c2e

📥 Commits

Reviewing files that changed from the base of the PR and between 89bf8d0 and b1d8641.

⛔ Files ignored due to path filters (1)
  • web/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • CLAUDE.md
  • docs/design/brand-and-ux.md
  • web/.storybook/preview.tsx
  • web/package.json
  • web/public/mockServiceWorker.js
  • web/src/mocks/handlers/auth.ts
  • web/src/mocks/handlers/helpers.ts
  • web/src/mocks/handlers/index.ts
  • web/src/mocks/handlers/setup.ts
  • web/src/pages/LoginPage.stories.tsx
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Deploy Preview
  • GitHub Check: Build Web
  • GitHub Check: Build Backend
  • GitHub Check: Build Sandbox
  • GitHub Check: Dashboard Test
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (go)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: TypeScript: Use camelCase for variable and function names
TypeScript: Always use async/await for promises instead of .then() chains

Files:

  • web/src/mocks/handlers/helpers.ts
  • web/src/mocks/handlers/index.ts
  • web/src/mocks/handlers/auth.ts
  • web/src/mocks/handlers/setup.ts
  • web/src/pages/LoginPage.stories.tsx
web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

web/src/**/*.{ts,tsx}: Always reuse existing components from web/src/components/ui/ (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast/ToastContainer, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem, Drawer, form fields, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor) before creating new components
Web dashboard design tokens: use Tailwind semantic classes (text-foreground, bg-card, text-accent, text-success, bg-danger, etc.) or CSS variables (var(--so-accent)); never hardcode hex values in .tsx/.ts files
Web dashboard typography: use font-sans or font-mono (maps to Geist tokens); never set fontFamily directly in .tsx/.ts files
Web dashboard spacing: use density-aware tokens (p-card, gap-section-gap, gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Web dashboard shadows/borders: use token variables (var(--so-shadow-card-hover), border-border, border-bright); never hardcode shadow or border values
Do NOT recreate status dots inline—use StatusBadge component
Do NOT build card-with-header layouts from scratch—use SectionCard component
Do NOT create metric displays with text-metric font-bold—use MetricCard component
Do NOT render initials circles manually—use Avatar component
Do NOT create complex (>8 line) JSX inside .map()—extract to a shared component
Do NOT use rgba() with hardcoded values—use design token variables
Web dashboard ESLint: Zero warnings enforced; use npm run lint to check and npm run lint --fix for auto-fix

Files:

  • web/src/mocks/handlers/helpers.ts
  • web/src/mocks/handlers/index.ts
  • web/src/mocks/handlers/auth.ts
  • web/src/mocks/handlers/setup.ts
  • web/src/pages/LoginPage.stories.tsx
{web/.storybook/main.ts,web/.storybook/preview.tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Storybook 10: Use defineMain from @storybook/react-vite/node for main.ts and definePreview from @storybook/react-vite for preview.tsx; must include explicit framework field

Files:

  • web/.storybook/preview.tsx
web/**/*.stories.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

web/**/*.stories.{ts,tsx}: Storybook 10: Use storybook/test (not @storybook/test) and storybook/actions (not @storybook/addon-actions) import paths
Storybook 10: Use parameters.backgrounds.options (object keyed by name) + initialGlobals.backgrounds.value for background options (replaces old default + values array)
Storybook 10: Use parameters.a11y.test: 'error' | 'todo' | 'off' for a11y testing (replaces old .element and .manual); set globally in preview.tsx to enforce WCAG compliance on all stories

Files:

  • web/src/pages/LoginPage.stories.tsx
🧠 Learnings (21)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:09:41.160Z
Learning: Applies to web/**/*.stories.{ts,tsx} : Storybook 10: Use storybook/test (not storybook/test) and storybook/actions (not storybook/addon-actions) import paths
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:09:41.160Z
Learning: Applies to {web/.storybook/main.ts,web/.storybook/preview.tsx} : Storybook 10: Use defineMain from storybook/react-vite/node for main.ts and definePreview from storybook/react-vite for preview.tsx; must include explicit framework field
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to web/package.json : Web dashboard Node.js 20+; dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, ESLint, vue-tsc)

Applied to files:

  • web/package.json
  • CLAUDE.md
📚 Learning: 2026-03-30T10:09:41.160Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:09:41.160Z
Learning: Applies to web/**/*.stories.{ts,tsx} : Storybook 10: Use storybook/test (not storybook/test) and storybook/actions (not storybook/addon-actions) import paths

Applied to files:

  • web/package.json
  • docs/design/brand-and-ux.md
  • web/src/mocks/handlers/index.ts
  • CLAUDE.md
  • web/.storybook/preview.tsx
  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).

Applied to files:

  • web/package.json
  • CLAUDE.md
📚 Learning: 2026-03-30T10:09:41.160Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:09:41.160Z
Learning: Applies to {web/.storybook/main.ts,web/.storybook/preview.tsx} : Storybook 10: Use defineMain from storybook/react-vite/node for main.ts and definePreview from storybook/react-vite for preview.tsx; must include explicit framework field

Applied to files:

  • web/package.json
  • docs/design/brand-and-ux.md
  • web/.storybook/preview.tsx
  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-30T10:09:41.160Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:09:41.160Z
Learning: Applies to web/**/*.stories.{ts,tsx} : Storybook 10: Use parameters.a11y.test: 'error' | 'todo' | 'off' for a11y testing (replaces old .element and .manual); set globally in preview.tsx to enforce WCAG compliance on all stories

Applied to files:

  • docs/design/brand-and-ux.md
  • web/.storybook/preview.tsx
  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-30T10:09:41.160Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:09:41.160Z
Learning: Applies to web/**/*.stories.{ts,tsx} : Storybook 10: Use parameters.backgrounds.options (object keyed by name) + initialGlobals.backgrounds.value for background options (replaces old default + values array)

Applied to files:

  • docs/design/brand-and-ux.md
  • web/.storybook/preview.tsx
  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-30T10:09:41.160Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:09:41.160Z
Learning: Applies to web/src/components/ui/**/*.{ts,tsx} : When creating new shared web components, place in web/src/components/ui/ with kebab-case filename, create .stories.tsx alongside with all states (default, hover, loading, error, empty), export props as TypeScript interface, use design tokens exclusively with no hardcoded colors/fonts/spacing, and import cn from `@/lib/utils` for conditional class merging

Applied to files:

  • docs/design/brand-and-ux.md
  • web/src/mocks/handlers/index.ts
  • CLAUDE.md
  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-30T10:09:41.160Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:09:41.160Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from web/src/components/ui/ (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast/ToastContainer, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem, Drawer, form fields, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor) before creating new components

Applied to files:

  • docs/design/brand-and-ux.md
  • CLAUDE.md
  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to docs/** : Docs source in docs/ (Markdown, built with Zensical); design spec in docs/design/ (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Documentation source in `docs/` (Markdown, built with Zensical). Design spec in `docs/design/` (7 pages: index, agents, organization, communication, engine, memory, operations). Architecture in `docs/architecture/` (overview, tech-stack, decision log). Roadmap in `docs/roadmap/`. Security in `docs/security.md`. Licensing in `docs/licensing.md`. Reference in `docs/reference/`. REST API reference in `docs/rest-api.md`. Library reference in `docs/api/` (auto-generated from docstrings). Custom templates in `docs/overrides/`. Config in `mkdocs.yml`.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to pyproject.toml : Dependencies: all versions use == in pyproject.toml. Groups: test (pytest + plugins, hypothesis), dev (includes test + ruff, mypy, pre-commit, commitizen, pip-audit). Required: mem0ai (Mem0 memory backend — the default and currently only backend). Install: uv sync installs everything (dev group is default).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-21T12:54:22.557Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T12:54:22.557Z
Learning: Go 1.26+ required; CLI dependencies in `cli/go.mod` (Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: Applies to go.mod : Maintain Go 1.26+ requirement. Dependencies: Cobra (CLI framework), charmbracelet/huh and charmbracelet/lipgloss (UI), sigstore-go (code signing), go-containerregistry (container image verification), go-tuf (TUF client for Sigstore).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-30T10:09:41.160Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:09:41.160Z
Learning: Applies to pyproject.toml : All Python versions use pinned versions with == in pyproject.toml; organize into groups: test (pytest + plugins, hypothesis), dev (includes test + ruff, mypy, pre-commit, commitizen, pip-audit); install with uv sync

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-30T10:09:41.160Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:09:41.160Z
Learning: Web dashboard: npm --prefix web install to install frontend dependencies; npm --prefix web run dev for dev server; npm --prefix web run build for production build

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Applies to cli/go.mod : CLI uses Go 1.26+. Dependencies: Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to cli/**/*.go : Go CLI (Go 1.26+) uses Cobra for commands, charmbracelet/huh for interactive CLI, charmbracelet/lipgloss for styled output. Cross-platform builds (linux/darwin/windows × amd64/arm64). GoReleaser for releases with cosign keyless signing of checksums.txt. SLSA L3 provenance attestations via actions/attest-build-provenance.

Applied to files:

  • CLAUDE.md
🔇 Additional comments (12)
web/src/mocks/handlers/helpers.ts (1)

1-6: Looks good: shared success envelope helper is correctly typed.

The helper is concise and correctly constructs the success shape expected by ApiResponse<T>.

web/src/mocks/handlers/auth.ts (1)

1-23: Clean MSW auth handlers implementation.

The handlers are straightforward, typed correctly, and reuse the shared apiSuccess() envelope as intended.

web/package.json (2)

88-89: Dependency additions are aligned with the Storybook MSW migration.

Adding msw and msw-storybook-addon in devDependencies matches the implementation goal.


97-100: No changes needed. The workerDirectory configuration as an array is valid and explicitly supported by MSW v2.12.x for monorepos and multiple package directories.

			> Likely an incorrect or invalid review comment.
CLAUDE.md (1)

223-223: Docs sync is good.

The new mocks/ package-structure entry and dependency list updates accurately reflect the MSW Storybook integration.

Also applies to: 431-431

web/.storybook/preview.tsx (2)

2-2: MSW loader integration in preview is correctly wired.

Import + global loader registration are in the right place for story-level handler activation.

Also applies to: 21-21


5-7: ⚠️ Potential issue | 🟠 Major

Correct the print.warning syntax in the suggested approach.

The recommendation to warn on unmocked /api/* requests while bypassing static assets and HMR is sound, but the diff contains a syntax error. print.warning should be accessed as a property, not called as a function.

Corrected approach
-initialize({ onUnhandledRequest: 'bypass' })
+initialize({
+  onUnhandledRequest(request, print) {
+    const { pathname } = new URL(request.url)
+    if (pathname.startsWith('/api/')) {
+      print.warning
+    }
+  },
+})
			> Likely an incorrect or invalid review comment.
docs/design/brand-and-ux.md (1)

189-189: Good documentation update for Storybook API mocking.

The MSW usage note is clear and aligned with the implemented handler architecture.

web/src/mocks/handlers/index.ts (1)

1-21: Nice handler barrel entrypoint.

The re-exports and usage docs make story-level mock wiring straightforward and consistent.

web/src/mocks/handlers/setup.ts (1)

1-37: Setup-status mock scenarios are well structured.

Both variants are typed, reusable, and map cleanly to the intended login/setup flows.

web/src/pages/LoginPage.stories.tsx (1)

4-9: Clean refactor to declarative MSW handlers.

The migration from ESM namespace mutation to parameters.msw.handlers is well-executed. The handler combinations correctly match the API flows:

  • DefaultLogin: setup-complete status + login endpoint
  • AdminCreation: needs-admin status + setup endpoint

The handler paths (/api/v1/setup/status, /api/v1/auth/login, /api/v1/auth/setup) correctly align with the actual API endpoints from web/src/api/endpoints/.

Also applies to: 27-38

web/public/mockServiceWorker.js (1)

1-11: Standard MSW-generated service worker — do not modify manually.

This is the canonical MSW service worker output generated via npx msw init. The version (2.12.14) matches the installed MSW package. If the MSW dependency is upgraded, regenerate this file with:

npx msw init web/public --save

Walkthrough

Mock Service Worker (MSW) was integrated into the Storybook development environment by installing msw and msw-storybook-addon dependencies, generating a service worker in web/public/mockServiceWorker.js, and configuring the Storybook preview to initialize MSW with a request loader. A new web/src/mocks/handlers/ directory was created with reusable handler modules for authentication and setup endpoints, each using a standardized apiSuccess() response envelope. The LoginPage.stories.tsx file was refactored to use MSW handler parameters instead of direct ESM namespace mutation. Documentation in CLAUDE.md and docs/design/brand-and-ux.md was updated to reflect the new mocking architecture.

Suggested labels

autorelease: tagged

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: set up MSW for Storybook API mocking' clearly and specifically summarizes the primary change: installing and configuring MSW for use in Storybook.
Description check ✅ Passed The description is well-organized, includes summary, test plan, and review coverage, and clearly relates to MSW setup for Storybook API mocking across the changeset.
Linked Issues check ✅ Passed The PR fully implements issue #898 objectives: MSW and msw-storybook-addon installed, service worker generated, Storybook preview wired, shared handlers created, LoginPage stories migrated, and documentation updated.
Out of Scope Changes check ✅ Passed All changes are directly scoped to MSW setup for Storybook: dependencies, service worker, preview config, handlers, story migration, and documentation—no unrelated modifications present.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 40.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 30, 2026 10:10 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request integrates Mock Service Worker (MSW) into the Storybook environment to provide a standardized way of mocking API responses. Key changes include adding the necessary dependencies, configuring the Storybook preview to use the MSW loader, and refactoring the LoginPage stories to utilize these new handlers instead of manual module patching. Feedback suggests enhancing the mocking utility with an apiError helper for failure scenarios and centralizing API route strings into constants to improve maintainability.

Comment on lines +4 to +6
export function apiSuccess<T>(data: T): ApiResponse<T> {
return { data, error: null, error_detail: null, success: true }
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The apiSuccess helper is great for consistency. To make the mocking infrastructure more complete, consider adding a corresponding apiError helper. This would standardize error responses and make it easier to create stories for failure states.

For example:

/** Build a failed ApiResponse envelope for MSW handlers. */
export function apiError<T = never>(error: string, error_detail: string | null): ApiResponse<T> {
  return { data: null, error, error_detail, success: false };
}

This could then be used in handlers for failure scenarios, like an invalid login attempt.

Comment on lines +1 to +18
/**
* MSW request handlers for Storybook API mocking.
*
* Usage in stories:
* import { setupStatusComplete } from '@/mocks/handlers'
*
* export const MyStory: Story = {
* parameters: {
* msw: { handlers: [...setupStatusComplete] },
* },
* }
*
* Each export is an array of RequestHandler objects. Spread them into
* parameters.msw.handlers -- the mswLoader (configured in preview.tsx)
* activates them before the story renders and resets between stories.
*
* All responses use the ApiResponse<T> envelope via the apiSuccess() helper.
*/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve maintainability and prevent potential mismatches between your mocks and the actual API endpoints, it's a good practice to avoid hardcoding URL paths in your handlers (e.g., in auth.ts and setup.ts).

Consider defining API routes as constants in a shared file and importing them into your handlers. This ensures that if an API route changes, you only need to update it in one place, and both your application code and your mocks will stay in sync.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 30, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA 9eb88d7.
Ensure that dependencies are being submitted on PR branches. Re-running this action after a short time may resolve the issue. See the documentation for more information and troubleshooting advice.

OpenSSF Scorecard

PackageVersionScoreDetails
npm/msw-storybook-addon 2.0.6 UnknownUnknown
npm/msw ^2.12.14 UnknownUnknown

Scanned Files

  • web/package-lock.json
  • web/package.json

coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 30, 2026
Aureliolo and others added 3 commits March 30, 2026 12:26
Install msw + msw-storybook-addon and wire initialize()/mswLoader into
Storybook preview. Create shared handler infrastructure in
web/src/mocks/handlers/ with typed ApiResponse envelope helpers and
reusable handlers for setup status and auth endpoints.

Migrate LoginPage.stories.tsx from ESM namespace mutation workaround to
declarative parameters.msw.handlers, eliminating the AdminCreationGate
component and its non-standard module patching.

Closes #898

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pre-reviewed by 3 agents, 3 findings addressed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Exclude mockServiceWorker.js from production build via Vite plugin
- Add apiError() helper for failure scenario mocking
- Fix imprecise comment about MSW handler reset behavior
- Fix misleading comment about MSW bypass mode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Aureliolo Aureliolo force-pushed the feat/msw-storybook branch from b1d8641 to 9eb88d7 Compare March 30, 2026 10:27
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 30, 2026 10:28 — with GitHub Actions Inactive
@Aureliolo Aureliolo merged commit 214078c into main Mar 30, 2026
31 checks passed
@Aureliolo Aureliolo deleted the feat/msw-storybook branch March 30, 2026 10:38
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 30, 2026 10:38 — with GitHub Actions Inactive
Aureliolo added a commit that referenced this pull request Mar 30, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.5.1](v0.5.0...v0.5.1)
(2026-03-30)


### Features

* add linear variant to ProgressGauge component
([#927](#927))
([89bf8d0](89bf8d0))
* frontend security hardening -- ESLint XSS ban + MotionConfig CSP nonce
([#926](#926))
([6592ed0](6592ed0))
* set up MSW for Storybook API mocking
([#930](#930))
([214078c](214078c))


### Refactoring

* **web:** replace Sidebar tablet overlay with shared Drawer component
([#928](#928))
([ad5451d](ad5451d))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: set up MSW for Storybook API mocking across all pages

2 participants