Skip to content

Migrate Storybook & add CI validation — prep for theming#438

Open
bballdavis wants to merge 11 commits intodevfrom
feature/storybook-migration
Open

Migrate Storybook & add CI validation — prep for theming#438
bballdavis wants to merge 11 commits intodevfrom
feature/storybook-migration

Conversation

@bballdavis
Copy link
Collaborator

Short migration of Storybook setup, plus CI that builds/validates Storybook and a few script cleanups.

Updated Storybook config/deps and cleaned up related scripts
Added CI job to build/validate Storybook snapshots
No UI or theming changes in this PR — this is the preparatory step before the theming work

The Storybook is currently its own CI test, but we could always incorporate it into the frontend test.

- Created stories for ChannelManager, ChannelPage, Configuration, DatabaseErrorOverlay, DownloadManager, ErrorBoundary, HelpDialog, InitialSetup, LocalLogin, PlexAuthDialog, PlexLibrarySelector, StorageStatus, VideosPage, AddSubfolderDialog, DeleteVideosDialog, DownloadFormatIndicator, SubfolderAutocomplete, WebSocketProvider, and videoStatus utilities.
- Implemented mock API responses using MSW for testing component interactions and states.
- Added play functions to validate UI behavior and interactions in the stories.
Copilot AI review requested due to automatic review settings February 18, 2026 17:36
@github-actions
Copy link
Contributor

github-actions bot commented Feb 18, 2026

📊 Test Coverage Report

Backend Coverage

Type Coverage Status
Lines 79.58% 🟡
Statements 79.45% 🟡
Functions 80.70% 🟢
Branches 72.57% 🟡

Frontend Coverage

Type Coverage Status
Lines 87.40% 🟢
Statements 86.71% 🟢
Functions 80.45% 🟢
Branches 81.51% 🟢

Coverage Requirements

  • Minimum threshold: 70% line coverage
  • Backend: ✅ Passes
  • Frontend: ✅ Passes

Coverage report generated for commit 43f1220

@claude
Copy link

claude bot commented Feb 18, 2026

Code Review: Storybook Migration & CI Validation

Strengths

  1. Comprehensive Storybook Coverage: Excellent addition of 77+ story files covering components from simple chips to complex pages
  2. Well-Structured CI Integration: New test-storybook job properly integrated with 15min timeout and check-all gate
  3. Proper Configuration: Clean Storybook config with MSW, theme switching, and proper decorators
  4. Good Test Organization: storybookPlayAdapter.tsx provides clean Jest integration

Issues & Concerns

High Priority

  1. Missing Newlines: Files lack trailing newlines (client/.storybook/main.js, preview.js, test-runner.js, storybook_coverage.test.js) - violates POSIX standards
  2. MockServiceWorker.js: Generated MSW file (349 lines) tracked in git - consider gitignoring and documenting generation
  3. Type Definitions: Verify client/src/types/storybook-shims.d.ts is complete (appears truncated in diff)

Medium Priority

  1. Jest Config Impact: testMatch change means tests/ files need .test. or .spec. suffix - verify existing tests
  2. Test Runner Strategy: CI runs build-storybook + Jest but test-runner.js exists unused - clarify approach
  3. Hardcoded Mocks: defaultMswHandlers in preview.js has hardcoded values - extract to fixtures file
  4. Missing CI Caching: No caching for Playwright browsers or Storybook builds - add ~/.cache/ms-playwright
  5. Environment Variables: process.env set to {} may conflict with envPrefix - verify stories work

Low Priority

  1. Redundant gitignore: Both storybook-static/ and client/storybook-static/ listed
  2. Test Coverage: Only 3 example stories validated - consider automated coverage checks
  3. WebSocket Mocks: Empty subscribe/unsubscribe functions may need basic implementation

Security Assessment

  • No security vulnerabilities found
  • MSW properly scoped to devDependencies
  • No sensitive data in mocks
  • CI isolation proper

Recommendations

Before merge:

  • Add trailing newlines to all files
  • Verify storybook-shims.d.ts completeness
  • Document mockServiceWorker.js strategy

Follow-up:

  • Add Playwright browser caching
  • Extract fixtures
  • Clarify test-runner usage

Verdict

Approve with minor changes - Solid foundation for Storybook integration. Fix trailing newlines and verify type definitions, then ready to merge.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR modernizes the client Storybook setup and adds CI validation to keep Storybook builds healthy as groundwork for upcoming theming work.

Changes:

  • Adds/updates Storybook tooling in the client (Storybook + MSW integration + preview/main config).
  • Introduces a Jest “storybook parity coverage” test harness that runs selected stories’ play functions in CI.
  • Adds a dedicated CI job to build Storybook and run the Storybook parity Jest test.

Reviewed changes

Copilot reviewed 83 out of 86 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
package.json Adds a root storybook script to run the client Storybook command.
docs/DEVELOPMENT.md Documents how to run Storybook locally and references the Jest parity test.
client/src/utils/tests/videoStatus.story.tsx Adds a Storybook story for videoStatus utilities.
client/src/types/storybook-shims.d.ts Adds TS shims for Storybook modules used in stories/tests.
client/src/tests/storybook_coverage.test.js Adds a Jest suite that runs selected stories’ play functions for parity validation.
client/src/providers/tests/WebSocketProvider.story.tsx Adds a Storybook story validating WebSocket context provisioning.
client/src/components/shared/tests/VideoActionsDropdown.story.tsx Adds interactive stories for VideoActionsDropdown.
client/src/components/shared/tests/SubfolderAutocomplete.story.tsx Adds stories covering selection behavior for SubfolderAutocomplete.
client/src/components/shared/tests/RatingBadge.story.tsx Adds stories for RatingBadge variants and states.
client/src/components/shared/tests/DownloadFormatIndicator.story.tsx Adds stories for different download format indicator states.
client/src/components/shared/tests/DeleteVideosDialog.story.tsx Adds a story validating delete confirmation flow.
client/src/components/shared/tests/ChangeRatingDialog.story.tsx Adds stories covering dialog open/close, selection, loading, and actions.
client/src/components/shared/tests/AddSubfolderDialog.story.tsx Adds stories for validation and submission behavior.
client/src/components/tests/storybookPlayAdapter.tsx Adds a helper to render stories and execute their play functions inside Jest.
client/src/components/tests/VideosPage.story.tsx Adds Stories for VideosPage with MSW-backed states (default/empty/error).
client/src/components/tests/StorageStatus.story.tsx Adds a story for StorageStatus with MSW handlers and hover tooltip check.
client/src/components/tests/PlexLibrarySelector.story.tsx Adds a story for selecting/saving a Plex library using MSW handlers.
client/src/components/tests/PlexAuthDialog.story.tsx Adds stories for Plex auth dialog and cancel behavior.
client/src/components/tests/LocalLogin.story.tsx Adds a story validating invalid-credentials UI via MSW.
client/src/components/tests/InitialSetup.story.tsx Adds stories for setup success and password mismatch flows using MSW.
client/src/components/tests/HelpDialog.story.tsx Adds a story validating help dialog close behavior.
client/src/components/tests/ErrorBoundary.story.tsx Adds a story validating error boundary reset flow.
client/src/components/tests/DownloadManager.story.tsx Adds stories for DownloadManager empty and populated job states.
client/src/components/tests/DatabaseErrorOverlay.story.tsx Adds stories for database overlay + retry action.
client/src/components/tests/Configuration.story.tsx Adds a story that exercises Configuration page loading and key UI elements via MSW.
client/src/components/tests/ChannelPage.story.tsx Adds a story validating ChannelPage loads and key interactions with MSW responses.
client/src/components/tests/ChannelManager.story.tsx Adds a story validating channel manager UI presence and interactions with MSW.
client/src/components/tests/ChangelogPage.story.tsx Adds stories for changelog load/refresh/loading/error states with MSW.
client/src/components/VideosPage/tests/FilterMenu.story.tsx Adds a story exercising FilterMenu selection behavior.
client/src/components/DownloadManager/tests/TerminateJobDialog.story.tsx Adds a story validating terminate confirmation flow.
client/src/components/DownloadManager/tests/DownloadProgress.story.tsx Adds a story validating queued jobs UI for download progress.
client/src/components/DownloadManager/tests/DownloadNew.story.tsx Adds extensive stories for manual/channel download flows with MSW.
client/src/components/DownloadManager/tests/DownloadHistory.story.tsx Adds a story validating “show jobs without videos” toggle behavior.
client/src/components/DownloadManager/ManualDownload/tests/VideoChip.story.tsx Adds a story validating “previously downloaded” popover flow.
client/src/components/DownloadManager/ManualDownload/tests/UrlInput.story.tsx Adds a story validating Enter-submit behavior.
client/src/components/DownloadManager/ManualDownload/tests/ManualDownload.story.tsx Adds a story validating adding a URL to the download queue using MSW.
client/src/components/DownloadManager/ManualDownload/tests/DownloadSettingsDialog.story.tsx Adds a story validating confirm defaults callback behavior.
client/src/components/Configuration/sections/tests/SponsorBlockSection.story.tsx Adds a story exercising sponsor category toggle behavior.
client/src/components/Configuration/sections/tests/SaveBar.story.tsx Adds stories for SaveBar click and validation error state.
client/src/components/Configuration/sections/tests/PlexIntegrationSection.story.tsx Adds a story validating Plex auth dialog launch action.
client/src/components/Configuration/sections/tests/NotificationsSection.story.tsx Adds a story validating adding a notification service.
client/src/components/Configuration/sections/tests/KodiCompatibilitySection.story.tsx Adds a story validating toggling metadata settings.
client/src/components/Configuration/sections/tests/DownloadPerformanceSection.story.tsx Adds a story validating stall detection toggle behavior.
client/src/components/Configuration/sections/tests/CoreSettingsSection.story.tsx Adds stories for auto-download toggle behavior and theme switcher placeholder.
client/src/components/Configuration/sections/tests/CookieConfigSection.story.tsx Adds a story validating enabling cookies surfaces upload UI.
client/src/components/Configuration/sections/tests/AutoRemovalSection.story.tsx Adds a story validating expand + enable flow for auto-removal.
client/src/components/Configuration/sections/tests/ApiKeysSection.story.tsx Adds a story validating opening the create API key dialog.
client/src/components/Configuration/sections/tests/AdvancedSettingsSection.story.tsx Adds a story validating proxy URL validation messaging.
client/src/components/Configuration/sections/tests/AccountSecuritySection.story.tsx Adds a story validating password mismatch helper text wiring.
client/src/components/Configuration/common/tests/InfoTooltip.story.tsx Adds a story validating tooltip shows on hover.
client/src/components/Configuration/common/tests/ConfigurationSkeleton.story.tsx Adds a story validating skeleton loading message.
client/src/components/Configuration/common/tests/ConfigurationCard.story.tsx Adds a story validating card renders title/subtitle/body.
client/src/components/Configuration/common/tests/ConfigurationAccordion.story.tsx Adds a story validating expanded accordion renders content.
client/src/components/Configuration/tests/SubtitleLanguageSelector.story.tsx Adds a story validating multi-select change callback behavior.
client/src/components/ChannelPage/components/tests/MobileFilterDrawer.story.tsx Adds stories validating filter drawer interactions and hide-date message.
client/src/components/ChannelPage/components/tests/FilterChips.story.tsx Adds stories validating clearing duration/date chips and empty state.
client/src/components/ChannelPage/components/tests/DurationFilterInput.story.tsx Adds stories validating duration input changes and compact mode.
client/src/components/ChannelPage/components/tests/DateRangeFilterInput.story.tsx Adds stories validating date input changes and compact mode.
client/src/components/ChannelPage/components/tests/ChannelVideosFilters.story.tsx Adds stories validating clear-all interactions for desktop/mobile.
client/src/components/ChannelPage/tests/VideoTableView.story.tsx Adds a story validating row selection callback behavior.
client/src/components/ChannelPage/tests/VideoListItem.story.tsx Adds a story validating selectable click triggers callback.
client/src/components/ChannelPage/tests/VideoCard.story.tsx Adds multiple stories covering different VideoCard states and interactions.
client/src/components/ChannelPage/tests/StillLiveDot.story.tsx Adds a story validating tooltip content appears on interaction.
client/src/components/ChannelPage/tests/ChannelVideosHeader.story.tsx Adds stories validating header action interactions and danger intent styling.
client/src/components/ChannelPage/tests/ChannelVideosDialogs.story.tsx Adds a story validating “Start Download” confirm callback.
client/src/components/ChannelPage/tests/ChannelVideos.story.tsx Adds a story validating empty state and search input interaction.
client/src/components/ChannelPage/tests/ChannelSettingsDialog.story.tsx Adds a story validating loaded dialog interactions with MSW.
client/src/components/ChannelManager/components/chips/tests/TitleFilterChip.story.tsx Adds stories validating regex chip click callback shape.
client/src/components/ChannelManager/components/chips/tests/SubFolderChip.story.tsx Adds stories validating root/global-default/specific rendering behavior.
client/src/components/ChannelManager/components/chips/tests/QualityChip.story.tsx Adds stories validating override vs global default display attributes.
client/src/components/ChannelManager/components/chips/tests/DurationFilterChip.story.tsx Adds stories for min/max/range label rendering.
client/src/components/ChannelManager/components/chips/tests/DownloadFormatConfigIndicator.story.tsx Adds stories for video/audio icon combinations.
client/src/components/ChannelManager/components/chips/tests/AutoDownloadChips.story.tsx Adds a story validating tab chip state attributes.
client/src/components/ChannelManager/components/tests/PendingSaveBanner.story.tsx Adds a story validating banner visibility text.
client/src/components/ChannelManager/components/tests/ChannelListRow.story.tsx Adds a story validating row actions (remove/regex/navigate).
client/src/components/ChannelManager/components/tests/ChannelCard.story.tsx Adds stories validating card interactions and pending-addition disabled behavior.
client/src/tests/App.story.tsx Adds stories for App logged-in, db error overlay, and requires-setup routing.
client/public/mockServiceWorker.js Adds generated MSW service worker for Storybook/MSW integration.
client/package.json Adds Storybook scripts and dependencies (Storybook + MSW tooling).
client/jest.config.cjs Adjusts Jest test matching/ignores to avoid treating stories as tests.
client/.storybook/test-runner.js Adds optional debug logging hooks for Storybook test-runner runs.
client/.storybook/preview.js Initializes MSW, applies global decorators/providers, and merges default MSW handlers.
client/.storybook/main.js Configures Storybook (Vite + tsconfig paths, story globs, addons, env defines).
.gitignore Ignores Storybook build outputs/caches and Storybook test artifacts.
.github/workflows/ci.yml Adds a CI job to build Storybook and run Jest parity validation; wires into check-all.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@claude
Copy link

claude bot commented Feb 23, 2026

PR Review: Migrate Storybook & add CI validation

Overall this is a well-structured addition — the MSW integration is clean, the global providers in preview.js are sensible, and colocating stories in __tests__ directories is a reasonable convention. A few things worth addressing before merging:


High Priority

1. Trivial tests provide false confidence in storybook_coverage.test.js

Two of the five tests in the storybook router configuration validation describe block are effectively no-ops:

// Always passes — tests nothing
test('stories should not nest MemoryRouter...', () => {
  expect(true).toBe(true);
});

// Always passes — array length > 0 is trivially true
test('Key router-dependent components have story wrappers', () => {
  const routerDependentComponents = ['ChannelManager', ...];
  expect(routerDependentComponents.length).toBeGreaterThan(0);
});

The third test also has an inverted assertion that always passes because undefined \!== false:

// story.parameters?.skipRouter is undefined by default, and undefined \!== false, so this never fails
expect(story.parameters?.skipRouter).not.toBe(false);

Since test-storybook is now a required CI gate, these tests should either be removed or replaced with something that can actually catch regressions.

2. Changing testMatch may silently drop existing tests

-  testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],
+  testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],

Removing the __tests__/** glob means any test file inside a __tests__ folder that doesn't carry a .test. or .spec. suffix is now silently ignored. Worth auditing that no legitimate test files were dropped before landing this.


Medium Priority

3. Response.json() polyfill will fail when body is an object

In client/jest.setup.ts:

async json() {
  return JSON.parse(this.body); // throws if body is already a plain object
}

MSW constructs Response internally with object bodies in some paths. JSON.parse of a non-string throws a SyntaxError. A safer implementation:

async json() {
  return typeof this.body === 'string' ? JSON.parse(this.body) : this.body;
}

4. storybookPlayAdapter passes undefined for Storybook test utilities

// storybookPlayAdapter.tsx
await story.play({
  // ...
  mount: undefined,
  userEvent: undefined,
  within: undefined,
  expect: undefined,
} as any);

Play functions that destructure these from the context argument (e.g. play: async ({ canvasElement, userEvent }) => {...}) will get undefined instead of the real utilities, producing cryptic runtime errors. Since all current stories import these directly from storybook/test instead, this is safe for now — but it's a silent footgun for future story authors. Worth adding a comment documenting the limitation, or throwing a descriptive error if a play function attempts to use context-provided utilities.

5. GitHub Actions pinned to @v3@v4 is current

uses: actions/checkout@v3
uses: actions/setup-node@v3
uses: actions/cache@v3

v4 has been available for all three for over a year. v3 will continue to work but upgrading is advisable for future-proofing and to benefit from performance/security fixes.


Low Priority

6. Version spec in package.json doesn't match what's installed

package.json declares "@storybook/addon-a11y": "^10.1.11" (and similar for other Storybook packages), but the lock file resolves to 10.2.9. This is valid semver behaviour, but it means a fresh npm install on a different machine could install 10.1.11 instead of 10.2.9. If 10.2.9 is intentional, pin the spec to match.

7. Missing newline at end of storybook-shims.d.ts

The diff shows \ No newline at end of file. Minor but will cause unnecessary noise in future diffs.


Positive Notes

  • The mergeMswHandlersLoader approach in preview.js (default handlers appended after story-specific ones so stories can override) is exactly the right precedence order.
  • onUnhandledRequest: 'bypass' is a sensible default — avoids spurious failures from unrelated network calls.
  • The test-runner.js debug mode via STORYBOOK_TEST_RUNNER_DEBUG=1 is a thoughtful DX addition.
  • Adding data-testid and aria-label attributes to VideoCard and VideoChip as part of this PR is good practice.

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.

2 participants