Skip to content

CSF-Factories: Handle meta.play and type errors#33353

Closed
jeevikar14 wants to merge 2 commits into
storybookjs:nextfrom
jeevikar14:fix/csf-factories-meta-play-error
Closed

CSF-Factories: Handle meta.play and type errors#33353
jeevikar14 wants to merge 2 commits into
storybookjs:nextfrom
jeevikar14:fix/csf-factories-meta-play-error

Conversation

@jeevikar14
Copy link
Copy Markdown
Contributor

@jeevikar14 jeevikar14 commented Dec 13, 2025

Fixes #33024

What was fixed

  • Ensured that meta.play is handled correctly and no longer throws at runtime
  • Updated typings and story usage to avoid TypeScript errors when using meta.input.play
  • Added/updated tests and stories to cover play inheritance behavior

How it was tested

  • Reproduced the issue locally using the reproduction link attached .
  • Verified the failure in the Interactions panel before the fix
  • Confirmed that after the fix:
    • Interaction tests pass for both Logged In and Logged Out stories
    • No runtime or TypeScript errors occur
  • Ran Storybook locally to validate behavior

Screenshots

Screenshots attached showing failing interactions before the fix and passing
interactions after the fix.
Screenshot 2025-12-13 133353
Screenshot 2025-12-13 161307
Screenshot 2025-12-13 161319

Summary by CodeRabbit

  • New Features

    • Added a new Page component with interactive stories (LoggedOut and LoggedIn states) demonstrating user authentication flows in Storybook.
  • Tests

    • Added test coverage for play function inheritance behavior.
  • Chores

    • Updated Storybook configuration to include example stories directory.
    • Added jsdom development dependencies.

✏️ Tip: You can customize this high-level summary in your review settings.

@kasperpeulen
Copy link
Copy Markdown
Member

I am fixing this here:
#33354

The solution there is based on using meta.input.play though.

@valentinpalkovic valentinpalkovic changed the title fix(csf-factories): handle meta.play and type errors CSF-Factories: Handle meta.play and type errors Dec 15, 2025
@valentinpalkovic valentinpalkovic added the ci:normal Run our default set of CI jobs (choose this for most PRs). label Dec 15, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 15, 2025

📝 Walkthrough

Walkthrough

This PR exports factory functions defineMeta and defineStory with play function inheritance from meta to stories, adds Storybook story directory configuration, removes the Globals interface in favor of Record<string, any>, introduces a new example Page component with stories, and adds jsdom as a dev dependency.

Changes

Cohort / File(s) Summary
Nx workspace cache files
code/.nx/workspace-data/lockfile-dependencies.hash, code/.nx/workspace-data/lockfile-nodes.hash, code/.nx/workspace-data/vite-1375197718504038785.hash
Added three cache/hash files containing numeric identifiers and empty JSON object for workspace build tracking.
Storybook configuration
code/.storybook/main.ts
Added a new story directory entry with path ../core/src/stories and titlePrefix 'example' to Storybook main configuration.
CSF factories implementation
code/core/src/csf/csf-factories.ts
Exported defineMeta and defineStory factory functions. Refactored defineStory to construct internal story object with play inheritance from meta; composed getter now inherits play from story or meta if not explicitly defined.
CSF factories tests
code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts, code/core/src/csf/csf-factories.play-inheritance.test.ts, code/core/src/csf/csf-factories.spec.ts, code/core/src/csf/csf-factories.test.ts
Added multiple test files verifying play inheritance from meta to story and composed story. Changed test environment from happy-dom to jsdom in primary test file.
Story type definitions
code/core/src/csf/story.ts
Removed exported Globals interface; replaced all Globals type references with Record<string, any> in StoryContextUpdate, ProjectAnnotations, ComponentAnnotations, and StoryAnnotations.
Example Page component and stories
code/src/stories/Page.tsx, code/src/stories/Page.stories.ts, code/core/src/stories/Page.tsx, code/core/src/stories/Page.stories.ts
Added new Page React component with optional user and callback props. Created corresponding Storybook stories with LoggedOut and LoggedIn states; LoggedIn story includes play function with DOM assertions for user interactions.
Dependencies
code/package.json
Added @types/jsdom@^27 and jsdom@^27.3.0 as dev dependencies.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • csf-factories.ts play inheritance logic: Review the refactored defineStory function to ensure play inheritance from meta is correctly implemented and composed object handles missing play gracefully.
  • Multiple test files: Verify whether the four test files (csf-factories.play-inheritance.test.ts, csf-factories.spec.ts, csf-factories.test.ts, and __tests__/csf-factories.play-inheritance.test.ts) are intentional duplicates or if consolidation is needed.
  • Globals interface removal: Confirm that removing the Globals export and replacing with Record<string, any> does not introduce breaking changes for consumers relying on the explicit type.
  • story.ts type changes: Ensure all lifecycle hook merges (afterEach, beforeEach, decorators, globals, loaders, parameters, tags) correctly use the new Record<string, any> pattern.

Possibly related PRs

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
code/core/src/csf/csf-factories.ts (1)

121-137: Story.composed returns a play field that the type doesn’t declare

Story['composed'] is declared as:

composed: Pick<ComposedStoryFn<TRenderer>, 'argTypes' | 'parameters' | 'id' | 'tags' | 'globals'> & {
  args: TRenderer['args'];
  name: string;
};

but the getter now returns { ..., play: composed.play } and tests access Story.composed.play. That means at runtime play exists, but TypeScript still thinks .play is not part of the type, which defeats the goal of avoiding type errors around meta.play / composed play.

Consider updating the type to include play, for example:

composed: Pick<
  ComposedStoryFn<TRenderer>,
  'argTypes' | 'parameters' | 'id' | 'tags' | 'globals' | 'play'
> & {
  args: TRenderer['args'];
  name: string;
};

(or a similar addition using ComposedStoryFn<TRenderer>['play']), so Story.composed.play is both valid at runtime and correctly typed.

Also applies to: 179-195

♻️ Duplicate comments (2)
code/core/src/csf/csf-factories.spec.ts (1)

1-15: This play-inheritance test duplicates coverage already added elsewhere

The spec here re-tests exactly the same scenario as the new CSF Next play inheritance tests in the other csf-factories test files (same meta definition, same assertions on Story.play and Story.composed.play).

To avoid redundant maintenance and slower test runs, I’d consolidate this into a single test module and remove the duplicates across the suite.

code/core/src/csf/csf-factories.play-inheritance.test.ts (1)

1-15: Another duplicate of the same play-inheritance scenario

This file repeats the same CSF Next play inheritance test already present in other csf-factories test modules. Keeping multiple identical copies makes it harder to evolve the behavior later.

Once you pick a canonical location for this scenario, consider removing the extras (including this file) to keep tests DRY.

🧹 Nitpick comments (6)
code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts (1)

1-15: Test covers the right behavior but duplicates other suites

This test correctly asserts that both Story.play and Story.composed.play inherit from meta.play. However, the exact same scenario is also tested in other files (csf-factories.spec.ts, csf-factories.play-inheritance.test.ts, and in csf-factories.test.ts), which is redundant and will run the same assertions multiple times.

Consider keeping this scenario in a single canonical place and removing the duplicates to keep the test suite lean and easier to maintain.

code/core/src/csf/csf-factories.test.ts (1)

7-20: New play-inheritance test is correct but adds yet another duplicate

The added CSF Next play inheritance test here is functionally identical to the tests introduced in:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts

It’s good coverage, but having four copies of the same assertions is overkill. I’d keep this scenario in one well-chosen place (e.g., this main .test.ts file) and delete the others.

code/src/stories/Page.tsx (1)

18-22: Add type="button" to prevent unintended form submission.

The buttons lack an explicit type attribute. If this component is ever nested within a form, these buttons could trigger form submission instead of invoking their handlers.

Apply this diff:

-          <button onClick={onLogout}>Log out</button>
+          <button type="button" onClick={onLogout}>Log out</button>
         ) : (
           <>
-            <button onClick={onLogin}>Log in</button>
-            <button onClick={onCreateAccount}>Sign up</button>
+            <button type="button" onClick={onLogin}>Log in</button>
+            <button type="button" onClick={onCreateAccount}>Sign up</button>
code/core/src/stories/Page.tsx (2)

1-37: Code duplication: identical Page component exists in two locations.

This file is identical to code/src/stories/Page.tsx. Consider consolidating to a single shared location and importing from both story files, or document if this duplication is intentional for demonstration purposes.


18-22: Add type="button" to prevent unintended form submission.

The buttons lack an explicit type attribute. If this component is ever nested within a form, these buttons could trigger form submission instead of invoking their handlers.

Apply this diff:

-          <button onClick={onLogout}>Log out</button>
+          <button type="button" onClick={onLogout}>Log out</button>
         ) : (
           <>
-            <button onClick={onLogin}>Log in</button>
-            <button onClick={onCreateAccount}>Sign up</button>
+            <button type="button" onClick={onLogin}>Log in</button>
+            <button type="button" onClick={onCreateAccount}>Sign up</button>
code/src/stories/Page.stories.ts (1)

18-18: Consider adding args to LoggedOut story for consistency.

While an empty story object works, explicitly setting args: { user: undefined } as in code/core/src/stories/Page.stories.ts (line 19) would make the intent clearer and match the pattern in the core stories file.

-export const LoggedOut: Story = {};
+export const LoggedOut: Story = {
+  args: {
+    user: undefined,
+  },
+  play: async ({ canvasElement }) => {
+    const canvas = within(canvasElement);
+    const loginButton = canvas.getByRole('button', { name: /Log in/i });
+    await expect(loginButton).toBeInTheDocument();
+  },
+};
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c4980c1 and 89f548c.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (15)
  • code/.nx/workspace-data/lockfile-dependencies.hash (1 hunks)
  • code/.nx/workspace-data/lockfile-nodes.hash (1 hunks)
  • code/.nx/workspace-data/vite-1375197718504038785.hash (1 hunks)
  • code/.storybook/main.ts (1 hunks)
  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts (1 hunks)
  • code/core/src/csf/csf-factories.play-inheritance.test.ts (1 hunks)
  • code/core/src/csf/csf-factories.spec.ts (1 hunks)
  • code/core/src/csf/csf-factories.test.ts (1 hunks)
  • code/core/src/csf/csf-factories.ts (6 hunks)
  • code/core/src/csf/story.ts (4 hunks)
  • code/core/src/stories/Page.stories.ts (1 hunks)
  • code/core/src/stories/Page.tsx (1 hunks)
  • code/package.json (1 hunks)
  • code/src/stories/Page.stories.ts (1 hunks)
  • code/src/stories/Page.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{test,spec}.{ts,tsx}: Test files should follow the naming pattern *.test.ts, *.test.tsx, *.spec.ts, or *.spec.tsx
Follow the spy mocking rules defined in .cursor/rules/spy-mocking.mdc for consistent mocking patterns with Vitest

Files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/core/src/csf/csf-factories.test.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/spy-mocking.mdc)

**/*.test.{ts,tsx,js,jsx}: Use vi.mock() with the spy: true option for all package and file mocks in Vitest tests
Place all mocks at the top of the test file before any test cases
Use vi.mocked() to type and access the mocked functions in Vitest tests
Implement mock behaviors in beforeEach blocks in Vitest tests
Mock all required dependencies that the test subject uses
Each mock implementation should return a Promise for async functions in Vitest
Mock implementations should match the expected return type of the original function
Mock all required properties and methods that the test subject uses in Vitest tests
Avoid direct function mocking without vi.mocked() in Vitest tests
Avoid mock implementations outside of beforeEach blocks in Vitest tests
Avoid mocking without the spy: true option in Vitest tests
Avoid inline mock implementations within test cases in Vitest tests
Avoid mocking only a subset of required dependencies in Vitest tests
Mock at the highest level of abstraction needed in Vitest tests
Keep mock implementations simple and focused in Vitest tests
Use type-safe mocking with vi.mocked() in Vitest tests
Document complex mock behaviors in Vitest tests
Group related mocks together in Vitest tests

Files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.test.ts
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use ESLint and Prettier configurations that are enforced in the codebase

Files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/story.ts
  • code/package.json
  • code/src/stories/Page.tsx
  • code/core/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/stories/Page.tsx
  • code/core/src/csf/csf-factories.spec.ts
  • code/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.ts
  • code/core/src/csf/csf-factories.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Enable TypeScript strict mode

Files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/story.ts
  • code/src/stories/Page.tsx
  • code/core/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/stories/Page.tsx
  • code/core/src/csf/csf-factories.spec.ts
  • code/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.ts
  • code/core/src/csf/csf-factories.test.ts
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

code/**/*.{ts,tsx,js,jsx,mjs}: Use server-side logger from 'storybook/internal/node-logger' for Node.js code
Use client-side logger from 'storybook/internal/client-logger' for browser code
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/story.ts
  • code/src/stories/Page.tsx
  • code/core/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/stories/Page.tsx
  • code/core/src/csf/csf-factories.spec.ts
  • code/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.ts
  • code/core/src/csf/csf-factories.test.ts
code/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions that need to be tested from their modules

Files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/story.ts
  • code/src/stories/Page.tsx
  • code/core/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/stories/Page.tsx
  • code/core/src/csf/csf-factories.spec.ts
  • code/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.ts
  • code/core/src/csf/csf-factories.test.ts
code/**/*.{test,spec}.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

code/**/*.{test,spec}.{ts,tsx,js,jsx}: Write meaningful unit tests that actually import and call the functions being tested
Mock external dependencies using vi.mock() for file system, loggers, and other external dependencies in tests
Aim for high test coverage of business logic (75%+ for statements/lines) using coverage reports

Files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/core/src/csf/csf-factories.test.ts
code/**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

code/**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier with --write flag to format code before committing
Run ESLint with yarn lint:js:cmd to check for linting issues and fix errors before committing

Files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/story.ts
  • code/package.json
  • code/src/stories/Page.tsx
  • code/core/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/stories/Page.tsx
  • code/core/src/csf/csf-factories.spec.ts
  • code/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.ts
  • code/core/src/csf/csf-factories.test.ts
🧠 Learnings (19)
📓 Common learnings
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T14:50:24.889Z
Learning: Follow existing patterns and conventions in the Storybook codebase
Learnt from: ndelangen
Repo: storybookjs/storybook PR: 32507
File: code/core/src/manager/globals/globals-module-info.ts:25-33
Timestamp: 2025-09-24T09:39:39.233Z
Learning: In Storybook, storybook/actions/decorator is a preview-only entrypoint and should not be included in manager globals configuration. The duplicatedKeys array in code/core/src/manager/globals/globals-module-info.ts is specifically for manager-side externalization, not preview entrypoints.
Learnt from: mrginglymus
Repo: storybookjs/storybook PR: 32556
File: code/core/package.json:309-313
Timestamp: 2025-09-29T13:20:23.346Z
Learning: The `fast-printf` dependency in Storybook's core package is bundled into the final distribution during the build process, so it should remain in devDependencies rather than being moved to dependencies, following the same pattern as other bundled dependencies like `open`.
Learnt from: ndelangen
Repo: storybookjs/storybook PR: 32484
File: code/core/package.json:326-326
Timestamp: 2025-09-17T07:31:04.432Z
Learning: In Storybook's core package, dependencies like `open` are bundled into the final distribution during the build process, so they should remain in devDependencies rather than being moved to dependencies. End users don't need these packages as separate runtime dependencies since they're included in the bundled code.
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/viewport/components/Tool.tsx:38-39
Timestamp: 2025-09-18T20:51:06.618Z
Learning: The useGlobals hook from storybook/manager-api returns a tuple where the third element (storyGlobals) is typed as Globals, not Globals | undefined. This means TypeScript guarantees it's always defined, making the `in` operator safe to use without additional null checks.
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.
📚 Learning: 2025-11-28T14:50:24.889Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T14:50:24.889Z
Learning: Applies to code/**/*.{test,spec}.{ts,tsx,js,jsx} : Write meaningful unit tests that actually import and call the functions being tested

Applied to files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/core/src/csf/csf-factories.test.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Document complex mock behaviors in Vitest tests

Applied to files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.ts
  • code/core/src/csf/csf-factories.test.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Implement mock behaviors in `beforeEach` blocks in Vitest tests

Applied to files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/core/src/csf/csf-factories.ts
  • code/core/src/csf/csf-factories.test.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required properties and methods that the test subject uses in Vitest tests

Applied to files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/core/src/csf/csf-factories.test.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Group related mocks together in Vitest tests

Applied to files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/core/src/csf/csf-factories.test.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock at the highest level of abstraction needed in Vitest tests

Applied to files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid inline mock implementations within test cases in Vitest tests

Applied to files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/core/src/csf/csf-factories.ts
  • code/core/src/csf/csf-factories.test.ts
📚 Learning: 2025-11-24T17:49:31.838Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-24T17:49:31.838Z
Learning: Applies to **/*.{test,spec}.{ts,tsx} : Follow the spy mocking rules defined in `.cursor/rules/spy-mocking.mdc` for consistent mocking patterns with Vitest

Applied to files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/core/src/csf/csf-factories.test.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mock implementations outside of `beforeEach` blocks in Vitest tests

Applied to files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/core/src/csf/csf-factories.ts
  • code/core/src/csf/csf-factories.test.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Keep mock implementations simple and focused in Vitest tests

Applied to files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/core/src/csf/csf-factories.test.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking only a subset of required dependencies in Vitest tests

Applied to files:

  • code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.play-inheritance.test.ts
  • code/core/src/csf/csf-factories.spec.ts
  • code/core/src/csf/csf-factories.test.ts
📚 Learning: 2025-09-18T20:51:06.618Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/viewport/components/Tool.tsx:38-39
Timestamp: 2025-09-18T20:51:06.618Z
Learning: The useGlobals hook from storybook/manager-api returns a tuple where the third element (storyGlobals) is typed as Globals, not Globals | undefined. This means TypeScript guarantees it's always defined, making the `in` operator safe to use without additional null checks.

Applied to files:

  • code/core/src/csf/story.ts
📚 Learning: 2025-09-18T20:51:06.618Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/viewport/components/Tool.tsx:38-39
Timestamp: 2025-09-18T20:51:06.618Z
Learning: In viewport tool code, when using the `useGlobals` hook from storybook/manager-api, the third returned value `storyGlobals` is guaranteed by TypeScript to be defined (not undefined/null), making the `in` operator safe to use without additional null checks.

Applied to files:

  • code/core/src/csf/story.ts
📚 Learning: 2025-09-24T09:39:39.233Z
Learnt from: ndelangen
Repo: storybookjs/storybook PR: 32507
File: code/core/src/manager/globals/globals-module-info.ts:25-33
Timestamp: 2025-09-24T09:39:39.233Z
Learning: In Storybook, storybook/actions/decorator is a preview-only entrypoint and should not be included in manager globals configuration. The duplicatedKeys array in code/core/src/manager/globals/globals-module-info.ts is specifically for manager-side externalization, not preview entrypoints.

Applied to files:

  • code/core/src/csf/story.ts
  • code/.storybook/main.ts
📚 Learning: 2025-09-17T07:31:04.432Z
Learnt from: ndelangen
Repo: storybookjs/storybook PR: 32484
File: code/core/package.json:326-326
Timestamp: 2025-09-17T07:31:04.432Z
Learning: In Storybook's core package, dependencies like `open` are bundled into the final distribution during the build process, so they should remain in devDependencies rather than being moved to dependencies. End users don't need these packages as separate runtime dependencies since they're included in the bundled code.

Applied to files:

  • code/package.json
📚 Learning: 2025-11-05T09:38:47.712Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.

Applied to files:

  • code/src/stories/Page.tsx
  • code/core/src/stories/Page.tsx
  • code/.storybook/main.ts
📚 Learning: 2025-11-28T14:50:24.889Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T14:50:24.889Z
Learning: Follow existing patterns and conventions in the Storybook codebase

Applied to files:

  • code/core/src/stories/Page.stories.ts
  • code/.storybook/main.ts
  • code/src/stories/Page.stories.ts
  • code/core/src/csf/csf-factories.test.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock implementations should match the expected return type of the original function

Applied to files:

  • code/core/src/csf/csf-factories.ts
🧬 Code graph analysis (5)
code/core/src/csf/__tests__/csf-factories.play-inheritance.test.ts (1)
code/core/src/csf/csf-factories.ts (4)
  • meta (55-58)
  • defineMeta (102-120)
  • Story (122-154)
  • defineStory (160-266)
code/core/src/stories/Page.stories.ts (4)
code/core/src/csf/csf-factories.ts (3)
  • meta (55-58)
  • Meta (77-96)
  • Story (122-154)
code/core/src/stories/Page.tsx (1)
  • Page (12-37)
code/src/stories/Page.tsx (1)
  • Page (12-37)
code/src/stories/Page.stories.ts (2)
  • LoggedOut (18-18)
  • LoggedIn (20-31)
code/core/src/csf/csf-factories.spec.ts (1)
code/core/src/csf/csf-factories.ts (4)
  • meta (55-58)
  • defineMeta (102-120)
  • Story (122-154)
  • defineStory (160-266)
code/src/stories/Page.stories.ts (3)
code/core/src/stories/Page.tsx (1)
  • Page (12-37)
code/src/stories/Page.tsx (1)
  • Page (12-37)
code/core/src/stories/Page.stories.ts (2)
  • LoggedOut (18-27)
  • LoggedIn (30-39)
code/core/src/csf/csf-factories.test.ts (1)
code/core/src/csf/csf-factories.ts (5)
  • test (201-229)
  • meta (55-58)
  • defineMeta (102-120)
  • Story (122-154)
  • defineStory (160-266)
⏰ 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). (1)
  • GitHub Check: normal
🔇 Additional comments (11)
code/.nx/workspace-data/vite-1375197718504038785.hash (1)

1-1: Auto-generated workspace metadata file.

This is an Nx workspace cache file and does not require functional review. These files are conventionally excluded from detailed code reviews as they are auto-generated during the build/dev process.

code/.nx/workspace-data/lockfile-dependencies.hash (1)

1-1: Auto-generated workspace metadata file.

This is an Nx workspace cache file and does not require functional review. These files are conventionally excluded from detailed code reviews as they are auto-generated during the build/dev process.

code/.nx/workspace-data/lockfile-nodes.hash (1)

1-1: Auto-generated workspace metadata file.

This is an Nx workspace cache file and does not require functional review. These files are conventionally excluded from detailed code reviews as they are auto-generated during the build/dev process.

code/package.json (1)

251-255: Adding jsdom as a dev dependency is appropriate

Using jsdom (plus @types/jsdom) as devDependencies matches the Vitest jsdom environment change and avoids shipping it at runtime. No issues here.

code/core/src/csf/story.ts (1)

219-221: Widening globals to Record<string, any> looks consistent

Switching various globals properties to Record<string, any> (in StoryContextUpdate, ProjectAnnotations.initialGlobals, ComponentAnnotations.globals, and StoryAnnotations.globals) is consistent and better matches real-world usage where globals are arbitrary bags. This should also reduce type-friction around meta/preview globals.

Also applies to: 419-420, 512-513, 531-532

code/core/src/csf/csf-factories.ts (3)

102-120: Public defineMeta shape looks good

Exposing defineMeta with a typed (input, preview) => Meta return value matches how Preview.meta() delegates and keeps the generics wired correctly. The internal story() helper forwarding to defineStory preserves existing behavior.


195-226: Play inheritance and test/extend wiring look correct

  • get play() now consistently prefers input.play, then meta.input?.play, then a noop, which ensures Story.play is always callable for tests and composed usage.
  • The test() helper wraps the provided testFunction so that story.play (including meta-level play) always runs before the test, and still respects mountDestructured when needed.
  • extend() now merges from story.input (not this), combining args, argTypes, lifecycle hooks, decorators, globals, loaders, parameters, and tags via combineParameters/combineTags and normalizeArrays, which is the right direction for inheritance.

No functional issues spotted here.

Also applies to: 231-256


262-264: Dead play inheritance check is misleading

This block:

// Inherit play from meta if not defined
if (!('play' in story) && meta.input?.play) {
  story.play = meta.input.play;
}

never runs, because story already has a play getter, so 'play' in story is always true. The actual inheritance is handled by the getter (input.play ?? meta.input?.play), so this check is redundant and potentially confusing.

Either remove this block or, if you intended to materialize input.play, change the condition/target accordingly (e.g., operate on input instead of story).

⛔ Skipped due to learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/viewport/components/Tool.tsx:38-39
Timestamp: 2025-09-18T20:51:06.618Z
Learning: In viewport tool code, when using the `useGlobals` hook from storybook/manager-api, the third returned value `storyGlobals` is guaranteed by TypeScript to be defined (not undefined/null), making the `in` operator safe to use without additional null checks.
code/.storybook/main.ts (1)

19-22: Including ../core/src/stories in stories config looks correct

Adding the directory: '../core/src/stories' with titlePrefix: 'example' follows existing patterns in this file and should surface the new example stories as intended.

code/core/src/csf/csf-factories.test.ts (1)

2-3: Remove jsdom environment; these tests are not DOM-centric

The test suite (CSF Next play inheritance, addon parameters, and test function registration) contains only pure JavaScript factory function tests with no DOM operations. Using // @vitest-environment jsdom adds unnecessary overhead. Change to the default node environment since there are no DOM interactions, event handling, focus management, or timers being tested.

Likely an incorrect or invalid review comment.

code/core/src/stories/Page.stories.ts (1)

1-39: LGTM! Correct story implementation with proper args and assertions.

Both stories correctly provide the necessary args to set component state and use play functions to assert the expected UI elements are rendered. This is the proper pattern for testing presentational components.

Comment thread code/src/stories/Page.stories.ts
@kasperpeulen
Copy link
Copy Markdown
Member

Thanks for the PR anway, will merge the other one today

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug ci:normal Run our default set of CI jobs (choose this for most PRs). csf factories

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: CSF-Factories: Type errors with meta.input.play and meta.play is undefined

3 participants