Skip to content

Conversation

@kasperpeulen
Copy link
Contributor

@kasperpeulen kasperpeulen commented Oct 23, 2025

Closes #

What I did

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This pull request has been released as version 0.0.0-pr-32813-sha-13a2dbef. Try it out in a new sandbox by running npx [email protected] sandbox or in an existing project with npx [email protected] upgrade.

More information
Published version 0.0.0-pr-32813-sha-13a2dbef
Triggered by @kasperpeulen
Repository storybookjs/storybook
Branch kasper/source-code
Commit 13a2dbef
Datetime Fri Oct 24 14:28:22 UTC 2025 (1761316102)
Workflow run 18782830606

To request a new release of this pull request, mention the @storybookjs/core team.

core team members can create a new canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=32813

Summary by CodeRabbit

  • New Features

    • Experimental "code examples" feature flag to embed formatted story snippets.
    • Public experimental_enrichCsf hook exported for custom CSF post-processing.
  • Improvements

    • CSF enrichment path made asynchronous and awaits enrichment hooks.
    • React component manifests now include richer JSDoc tag details; decorators respect FEATURES.
  • Tests

    • Test setup initializes global FEATURES and restores mocks between tests.
  • Public API

    • Minor preset/type/signature and export refinements.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 23, 2025

📝 Walkthrough

Walkthrough

Makes CSF enrichment asynchronous, adds an experimentalCodeExamples feature and experimental_enrichCsf preset hook, implements React renderer code-snippet generation/injection into CSF, restructures JSDoc parsing to {description, tags}, and wires enrichment through Vite/Webpack/Rollup, presets, and tests.

Changes

Cohort / File(s) Summary
Feature flag & test globals
code/.storybook/main.ts, code/vitest-setup.ts, test-storybooks/portable-stories-kitchen-sink/react/globals.setup.ts, test-storybooks/portable-stories-kitchen-sink/react/jest.setup.ts
Enable experimentalCodeExamples feature and ensure global FEATURES exists for runtime/tests; minor string literal delimiter updates in a jest setup.
Types & config
code/core/src/types/modules/core-common.ts
Export new CsfEnricher type, add experimental_enrichCsf?: CsfEnricher and experimentalCodeExamples?: boolean to config, and add an overload for Presets.apply.
Presets & wiring
code/core/src/common/presets.ts, code/addons/docs/src/preset.ts, code/renderers/react/src/preset.ts
Propagate renderer experimental_enrichCsf via presets into docs/CSF plugin pipelines; expose React renderer enrich as experimental_enrichCsf and pass enrichCsf through CSF plugin options when present.
Core enrichment async surface
code/core/src/csf-tools/enrichCsf.ts, code/core/src/csf-tools/enrichCsf.test.ts
Make core enrichCsf async, accept optional async enrichCsf hook in options, and update tests/helpers to await enrichment.
Renderer enrich implementation
code/renderers/react/src/enrichCsf.ts, code/renderers/react/src/enrichCsf.test.ts, code/renderers/react/src/entry-preview-docs.ts, code/renderers/react/src/preset.ts
Add React enrichCsf that generates formatted story source and injects it into CSF when experimentalCodeExamples is enabled; re-export as preset, conditionally adjust decorators, and add tests and test setup.
JSDoc parsing & component manifest
code/renderers/react/src/componentManifest/jsdocTags.ts, code/renderers/react/src/componentManifest/jsdocTags.test.ts, code/renderers/react/src/componentManifest/generator.ts, code/renderers/react/src/componentManifest/generator.test.ts
Replace extractJSDocTags with extractJSDocInfo returning { description, tags }; include jsDocTags in manifests and update tests and mocks.
Build integrations (Vite/Webpack/Rollup)
code/builders/builder-vite/src/plugins/csf-plugin.ts, code/lib/csf-plugin/src/rollup-based-plugin.ts, code/lib/csf-plugin/src/webpack-loader.ts, code/addons/docs/src/preset.ts
Read experimental_enrichCsf from presets and pass enrichCsf into CSF plugins; await async enrichment in plugin flows.
Utilities & presets API
code/core/src/common/utils/formatter.ts, code/core/src/common/presets.ts
Export getPrettier; export InterPresetOptions; make preset apply config parameter optional.
Tests & test setup
code/renderers/react/vitest.config.ts, code/renderers/react/vitest.setup.ts, code/core/src/core-server/presets/favicon.test.ts, code/vitest-setup.ts
Add Vitest setup file to restore mocks after each test and register it in config; cast options as Presets in a favicon test; initialize global FEATURES in test setup.
Plugin loader/test adjustments
code/lib/csf-plugin/..., code/core/src/csf-tools/enrichCsf.test.ts
Update plugin loaders and tests to await the now-async enrichment step.
Misc test import fixes
code/renderers/react/src/componentManifest/generator.test.ts
Replace wildcard tsconfig-paths import with named loadConfig and update mocks accordingly.

Sequence Diagram(s)

sequenceDiagram
    participant Build as Build System (Vite/Webpack/Rollup)
    participant Presets as Preset Layer
    participant Core as core.enrichCsf
    participant Renderer as react.enrichCsf
    participant Codegen as Code Generator
    participant CSF as CSF AST

    Build->>Presets: load presets (may expose experimental_enrichCsf)
    Presets-->>Build: provide enrichCsf hook (if present)
    Build->>Core: await enrichCsf(csf, csfSource, { enrichCsf })
    Core->>Renderer: invoke optional renderer enrichCsf hook (async)
    alt experimentalCodeExamples enabled
        Renderer->>Codegen: generate formatted snippet per story (async)
        Codegen-->>Renderer: formatted snippet
        Renderer->>CSF: inject snippet into story.input.parameters.docs.source.code
    else feature disabled or no hook
        Renderer->>CSF: return CSF unchanged
    end
    Core-->>Build: return enriched CSF
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

  • Review focus: async boundary changes for enrichCsf across core and build plugins, React renderer enrichment logic and error handling, and updated tests that await async flows.
  • Pay attention to public API/type additions (CsfEnricher, experimental flags) and the added jsDocTags field in component manifests for consumer impact.

Possibly related PRs

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch kasper/source-code

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

Copy link
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

🧹 Nitpick comments (1)
code/renderers/react/src/enrichCsf.ts (1)

22-33: Track the TODO for user config support.

The TODO on Line 29 indicates that prettier formatting should respect user configuration. Consider creating an issue to track this enhancement.

Do you want me to open a new issue to track the user config support for code formatting?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af0645c and c165fc5.

📒 Files selected for processing (21)
  • code/.storybook/main.ts (1 hunks)
  • code/addons/docs/src/preset.ts (3 hunks)
  • code/builders/builder-vite/src/plugins/csf-plugin.ts (1 hunks)
  • code/core/src/common/presets.ts (2 hunks)
  • code/core/src/common/utils/formatter.ts (1 hunks)
  • code/core/src/csf-tools/enrichCsf.ts (2 hunks)
  • code/core/src/types/modules/core-common.ts (4 hunks)
  • code/lib/csf-plugin/src/rollup-based-plugin.ts (1 hunks)
  • code/lib/csf-plugin/src/webpack-loader.ts (1 hunks)
  • code/renderers/react/src/componentManifest/generator.test.ts (2 hunks)
  • code/renderers/react/src/componentManifest/generator.ts (2 hunks)
  • code/renderers/react/src/componentManifest/jsdocTags.test.ts (2 hunks)
  • code/renderers/react/src/componentManifest/jsdocTags.ts (1 hunks)
  • code/renderers/react/src/docs/jsxDecorator.tsx (2 hunks)
  • code/renderers/react/src/enrichCsf.test.ts (1 hunks)
  • code/renderers/react/src/enrichCsf.ts (1 hunks)
  • code/renderers/react/src/entry-preview-docs.ts (1 hunks)
  • code/renderers/react/src/preset.ts (1 hunks)
  • code/renderers/react/vitest.config.ts (1 hunks)
  • code/renderers/react/vitest.setup.ts (1 hunks)
  • code/vitest-setup.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,jsx,json,html,ts,tsx,mjs}

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

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/core/src/common/utils/formatter.ts
  • code/renderers/react/src/preset.ts
  • code/renderers/react/vitest.setup.ts
  • code/renderers/react/vitest.config.ts
  • code/renderers/react/src/componentManifest/jsdocTags.ts
  • code/vitest-setup.ts
  • code/addons/docs/src/preset.ts
  • code/renderers/react/src/enrichCsf.test.ts
  • code/core/src/csf-tools/enrichCsf.ts
  • code/renderers/react/src/entry-preview-docs.ts
  • code/lib/csf-plugin/src/webpack-loader.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/lib/csf-plugin/src/rollup-based-plugin.ts
  • code/renderers/react/src/enrichCsf.ts
  • code/renderers/react/src/componentManifest/jsdocTags.test.ts
  • code/builders/builder-vite/src/plugins/csf-plugin.ts
  • code/core/src/common/presets.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/types/modules/core-common.ts
  • code/renderers/react/src/docs/jsxDecorator.tsx
**/*.{ts,tsx,js,jsx,mjs}

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

Export functions from modules when they need to be unit-tested

Files:

  • code/core/src/common/utils/formatter.ts
  • code/renderers/react/src/preset.ts
  • code/renderers/react/vitest.setup.ts
  • code/renderers/react/vitest.config.ts
  • code/renderers/react/src/componentManifest/jsdocTags.ts
  • code/vitest-setup.ts
  • code/addons/docs/src/preset.ts
  • code/renderers/react/src/enrichCsf.test.ts
  • code/core/src/csf-tools/enrichCsf.ts
  • code/renderers/react/src/entry-preview-docs.ts
  • code/lib/csf-plugin/src/webpack-loader.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/lib/csf-plugin/src/rollup-based-plugin.ts
  • code/renderers/react/src/enrichCsf.ts
  • code/renderers/react/src/componentManifest/jsdocTags.test.ts
  • code/builders/builder-vite/src/plugins/csf-plugin.ts
  • code/core/src/common/presets.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/types/modules/core-common.ts
  • code/renderers/react/src/docs/jsxDecorator.tsx
code/**/*.{ts,tsx,js,jsx,mjs}

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

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/core/src/common/utils/formatter.ts
  • code/renderers/react/src/preset.ts
  • code/renderers/react/vitest.setup.ts
  • code/renderers/react/vitest.config.ts
  • code/renderers/react/src/componentManifest/jsdocTags.ts
  • code/vitest-setup.ts
  • code/addons/docs/src/preset.ts
  • code/renderers/react/src/enrichCsf.test.ts
  • code/core/src/csf-tools/enrichCsf.ts
  • code/renderers/react/src/entry-preview-docs.ts
  • code/lib/csf-plugin/src/webpack-loader.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/lib/csf-plugin/src/rollup-based-plugin.ts
  • code/renderers/react/src/enrichCsf.ts
  • code/renderers/react/src/componentManifest/jsdocTags.test.ts
  • code/builders/builder-vite/src/plugins/csf-plugin.ts
  • code/core/src/common/presets.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/types/modules/core-common.ts
  • code/renderers/react/src/docs/jsxDecorator.tsx
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

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

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/common/utils/formatter.ts
  • code/renderers/react/src/preset.ts
  • code/renderers/react/vitest.setup.ts
  • code/renderers/react/vitest.config.ts
  • code/renderers/react/src/componentManifest/jsdocTags.ts
  • code/vitest-setup.ts
  • code/addons/docs/src/preset.ts
  • code/renderers/react/src/enrichCsf.test.ts
  • code/core/src/csf-tools/enrichCsf.ts
  • code/renderers/react/src/entry-preview-docs.ts
  • code/lib/csf-plugin/src/webpack-loader.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/lib/csf-plugin/src/rollup-based-plugin.ts
  • code/renderers/react/src/enrichCsf.ts
  • code/renderers/react/src/componentManifest/jsdocTags.test.ts
  • code/builders/builder-vite/src/plugins/csf-plugin.ts
  • code/core/src/common/presets.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/types/modules/core-common.ts
  • code/renderers/react/src/docs/jsxDecorator.tsx
code/.storybook/**

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

Place internal UI Storybook configuration in code/.storybook/ and maintain it there

Files:

  • code/.storybook/main.ts
code/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

code/**/*.{test,spec}.{ts,tsx}: Place all test files under the code/ directory
Name test files as *.test.ts, *.test.tsx, *.spec.ts, or *.spec.tsx

Files:

  • code/renderers/react/src/enrichCsf.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/jsdocTags.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 mocked functions
Implement mock behaviors in beforeEach blocks
Mock all required dependencies that the test subject uses
Mock implementations should be placed in beforeEach blocks
Each mock implementation should return a Promise for async functions
Mock implementations should match the expected return type of the original function
Use vi.mocked() to access and implement mock behaviors
Mock all required properties and methods that the test subject uses
Avoid direct function mocking without vi.mocked()
Avoid mock implementations outside of beforeEach blocks
Avoid mocking without the spy: true option
Avoid inline mock implementations within test cases
Avoid mocking only a subset of required dependencies
Mock at the highest level of abstraction needed
Keep mock implementations simple and focused
Use type-safe mocking with vi.mocked()
Document complex mock behaviors
Group related mocks together

Files:

  • code/renderers/react/src/enrichCsf.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/jsdocTags.test.ts
**/*.@(test|spec).{ts,tsx,js,jsx}

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

**/*.@(test|spec).{ts,tsx,js,jsx}: Unit tests should import and execute the functions under test rather than only asserting on syntax patterns
Mock external dependencies in tests using vi.mock() (e.g., filesystem, loggers)

Files:

  • code/renderers/react/src/enrichCsf.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/jsdocTags.test.ts
🧠 Learnings (12)
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vi.mock() with the spy: true option for all package and file mocks in Vitest tests

Applied to files:

  • code/renderers/react/vitest.setup.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.@(test|spec).{ts,tsx,js,jsx} : Mock external dependencies in tests using `vi.mock()` (e.g., filesystem, loggers)

Applied to files:

  • code/renderers/react/vitest.setup.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vi.mocked() to access and implement mock behaviors

Applied to files:

  • code/renderers/react/vitest.setup.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Implement mock behaviors in beforeEach blocks

Applied to files:

  • code/renderers/react/vitest.setup.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vi.mocked() to type and access mocked functions

Applied to files:

  • code/renderers/react/vitest.setup.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock implementations should be placed in beforeEach blocks

Applied to files:

  • code/renderers/react/vitest.setup.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use type-safe mocking with vi.mocked()

Applied to files:

  • code/renderers/react/vitest.setup.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mock implementations outside of beforeEach blocks

Applied to files:

  • code/renderers/react/vitest.setup.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid direct function mocking without vi.mocked()

Applied to files:

  • code/renderers/react/vitest.setup.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:04.287Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursorrules:0-0
Timestamp: 2025-09-17T08:11:04.287Z
Learning: Applies to code/vitest.workspace.ts : Keep and use the Vitest workspace configuration at code/vitest.workspace.ts

Applied to files:

  • code/renderers/react/vitest.config.ts
📚 Learning: 2025-09-24T09:39:39.233Z
Learnt from: ndelangen
PR: storybookjs/storybook#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/renderers/react/src/entry-preview-docs.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to code/**/*.{ts,tsx,js,jsx,mjs} : In application code, use Storybook loggers instead of `console.*` (client code: `storybook/internal/client-logger`; server code: `storybook/internal/node-logger`)

Applied to files:

  • code/renderers/react/src/docs/jsxDecorator.tsx
🧬 Code graph analysis (14)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
code/renderers/react/src/componentManifest/utils.ts (1)
  • groupBy (2-12)
code/vitest-setup.ts (1)
code/renderers/web-components/template/components/Html.js (1)
  • globalThis (5-5)
code/addons/docs/src/preset.ts (3)
code/renderers/react/src/enrichCsf.ts (1)
  • enrichCsf (10-115)
code/core/src/csf-tools/enrichCsf.ts (1)
  • enrichCsf (144-150)
code/renderers/react/src/preset.ts (1)
  • enrichCsf (13-13)
code/renderers/react/src/enrichCsf.test.ts (3)
code/renderers/react/src/enrichCsf.ts (1)
  • enrichCsf (10-115)
code/core/src/common/presets.ts (2)
  • getPresets (317-327)
  • InterPresetOptions (23-28)
code/core/src/csf-tools/CsfFile.ts (1)
  • loadCsf (1032-1036)
code/core/src/csf-tools/enrichCsf.ts (3)
code/core/src/types/modules/core-common.ts (1)
  • CsfEnricher (365-365)
code/renderers/react/src/enrichCsf.ts (1)
  • enrichCsf (10-115)
code/renderers/react/src/preset.ts (1)
  • enrichCsf (13-13)
code/renderers/react/src/entry-preview-docs.ts (2)
code/core/src/types/modules/core-common.ts (1)
  • StorybookConfigRaw (367-526)
code/renderers/react/src/docs/jsxDecorator.tsx (1)
  • jsxDecorator (238-269)
code/lib/csf-plugin/src/webpack-loader.ts (3)
code/renderers/react/src/enrichCsf.ts (1)
  • enrichCsf (10-115)
code/core/src/csf-tools/enrichCsf.ts (1)
  • enrichCsf (144-150)
code/renderers/react/src/preset.ts (1)
  • enrichCsf (13-13)
code/lib/csf-plugin/src/rollup-based-plugin.ts (3)
code/renderers/react/src/enrichCsf.ts (1)
  • enrichCsf (10-115)
code/core/src/csf-tools/enrichCsf.ts (1)
  • enrichCsf (144-150)
code/renderers/react/src/preset.ts (1)
  • enrichCsf (13-13)
code/renderers/react/src/enrichCsf.ts (5)
code/core/src/csf-tools/enrichCsf.ts (1)
  • enrichCsf (144-150)
code/renderers/react/src/preset.ts (1)
  • enrichCsf (13-13)
code/core/src/csf-tools/CsfFile.ts (1)
  • CsfFile (277-1017)
code/core/src/common/utils/formatter.ts (1)
  • getPrettier (1-6)
code/renderers/react/src/componentManifest/generateCodeSnippet.ts (1)
  • getCodeSnippet (23-247)
code/renderers/react/src/componentManifest/jsdocTags.test.ts (1)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
  • extractJSDocInfo (5-21)
code/builders/builder-vite/src/plugins/csf-plugin.ts (3)
code/renderers/react/src/enrichCsf.ts (1)
  • enrichCsf (10-115)
code/core/src/csf-tools/enrichCsf.ts (1)
  • enrichCsf (144-150)
code/renderers/react/src/preset.ts (1)
  • enrichCsf (13-13)
code/renderers/react/src/componentManifest/generator.ts (1)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
  • extractJSDocInfo (5-21)
code/core/src/types/modules/core-common.ts (1)
code/core/src/csf-tools/CsfFile.ts (1)
  • CsfFile (277-1017)
code/renderers/react/src/docs/jsxDecorator.tsx (1)
code/core/src/types/modules/core-common.ts (1)
  • StorybookConfigRaw (367-526)
⏰ 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: Core Unit Tests, windows-latest
🔇 Additional comments (34)
code/core/src/common/utils/formatter.ts (3)

1-6: Export of getPrettier is well-suited for public API.

The function implements a robust pattern for handling optional dependencies: it dynamically imports prettier and returns a safe no-op fallback (resolveConfig: async () => null, format: (content) => content) if the import fails. This allows consumers to handle formatting failures gracefully without breaking the build.


13-31: Error handling strategy is sound for a formatter utility.

The broad catch-all at line 28–30 silently returns the original content on any error. This "fail gracefully" approach is appropriate for formatting utilities where a formatting failure should not break the pipeline. The function also correctly delegates to formatWithEditorConfig as a fallback when prettier config is missing or empty.


22-25: as any type assertions are acceptable given prettier's dynamic return type.

The type assertions when destructuring the prettier module return value are appropriate, since the dynamic import result varies depending on whether prettier is available or whether the fallback object is returned. While not ideal from a type-safety perspective, this is a pragmatic trade-off for handling optional dependencies.

Also applies to: 42-45

code/renderers/react/src/componentManifest/jsdocTags.ts (1)

5-21: Verify error handling for malformed JSDoc comments.

The function doesn't handle cases where parsed[0] might be undefined (e.g., if the comment-parser fails or returns an empty array). This could lead to runtime errors when processing malformed JSDoc comments.

Consider adding defensive checks:

 export function extractJSDocInfo(jsdocComment: string) {
   const lines = jsdocComment.split('\n');
   const jsDoc = ['/**', ...lines.map((line) => ` * ${line}`), ' */'].join('\n');
 
   const parsed = parse(jsDoc);
+  
+  if (!parsed[0]) {
+    return { description: '', tags: {} };
+  }
 
   return {
     description: parsed[0].description,
     tags: Object.fromEntries(
code/core/src/common/presets.ts (1)

23-28: LGTM on exporting InterPresetOptions.

Making this type public improves type safety for code that needs to reference preset options.

code/renderers/react/src/componentManifest/jsdocTags.test.ts (1)

5-40: LGTM on test updates.

The tests correctly reflect the renamed function and new return structure. Inline snapshots accurately capture the expected output format.

code/renderers/react/src/componentManifest/generator.ts (3)

12-12: LGTM on updated import.

The import correctly reflects the renamed function.


86-86: Good addition of jsDocTags to the manifest.

Exposing the structured JSDoc tags enriches the component manifest and enables downstream consumers to access granular documentation metadata.


75-82: Potential undefined error when trimming description.

On Line 82, manifestDescription?.trim() could fail if manifestDescription is undefined when neither tags.describe, tags.desc, nor description exist. The optional chaining on Line 77 doesn't prevent undefined from being passed to trim().

Apply this fix to safely handle undefined:

-        const manifestDescription = (tags?.describe?.[0] || tags?.desc?.[0]) ?? description;
+        const manifestDescription = tags?.describe?.[0] || tags?.desc?.[0] || description;
 
         return {
           id,
           name: componentName,
-          description: manifestDescription?.trim(),
+          description: manifestDescription?.trim() ?? undefined,

Likely an incorrect or invalid review comment.

code/.storybook/main.ts (1)

141-141: LGTM on enabling experimental feature.

Enabling experimentalCodeExamples allows testing the new code examples functionality in the internal Storybook.

code/vitest-setup.ts (1)

42-42: LGTM on global FEATURES initialization.

Initializing globalThis.FEATURES early in the test setup ensures the global object is available for feature flag checks throughout the test suite.

code/lib/csf-plugin/src/webpack-loader.ts (1)

23-23: LGTM on awaiting enrichCsf.

Correctly awaits the now-async enrichCsf function, ensuring enrichment completes before formatting. The existing try-catch block handles any enrichment errors appropriately.

code/builders/builder-vite/src/plugins/csf-plugin.ts (1)

15-21: LGTM on integrating enrichCsf into Vite plugin.

The code correctly retrieves the optional experimental_enrichCsf enricher from presets and passes it to the CSF plugin, enabling async enrichment when configured.

code/renderers/react/vitest.setup.ts (1)

1-6: LGTM!

The setup file correctly restores mocks after each test, and the comment helpfully explains why this must be in afterEach rather than beforeEach (to preserve spy: true mocks).

code/lib/csf-plugin/src/rollup-based-plugin.ts (1)

26-26: LGTM!

The addition of await correctly handles the async enrichCsf call, aligning with the broader changes to make CSF enrichment asynchronous throughout the pipeline.

code/renderers/react/src/docs/jsxDecorator.tsx (1)

7-8: LGTM!

The global FEATURES type declaration correctly mirrors the configuration surface from StorybookConfigRaw['features'], ensuring consistent typing for feature flags across runtime and tests.

Also applies to: 235-236

code/renderers/react/src/preset.ts (1)

13-13: LGTM!

The export alias follows the established pattern for experimental features (consistent with experimental_componentManifestGenerator on Line 11) and properly exposes the enrichment capability.

code/addons/docs/src/preset.ts (1)

6-6: LGTM!

The integration of enrichCsf into the webpack configuration is correctly implemented, deriving it from the presets via experimental_enrichCsf and passing it to the CSF plugin when present.

Also applies to: 45-45, 106-111

code/renderers/react/src/componentManifest/generator.test.ts (1)

7-7: LGTM!

The refactoring from wildcard import to named import, combined with the addition of spy: true to the mock, aligns with the coding guidelines for Vitest mocking patterns.

Based on learnings.

Also applies to: 13-13, 98-98

code/renderers/react/vitest.config.ts (1)

8-10: LGTM!

The setupFiles configuration correctly references the new setup file, ensuring mocks are properly restored after each test.

code/renderers/react/src/entry-preview-docs.ts (1)

7-12: Now let me search the codebase for how FEATURES is initialized in the preview context and how entry-preview-docs.ts is loaded:Now let me search the codebase directly for FEATURES initialization and usage:Based on my verification, I have sufficient information to generate the rewritten review comment. Let me analyze what I've found:

  1. vitest-setup.ts initializes globalThis.FEATURES = {} at line 42 - this is test setup only
  2. entry-preview-docs.ts is a preview entry file (loaded in Storybook's preview iframe)
  3. Web searches show StorybookConfigRaw['features'] is a real configuration option in Storybook's main.ts
  4. The code uses FEATURES.experimentalCodeExamples with a ternary operator that doesn't guard against undefined

The core issue is that the review comment identifies a real concern: the code conditionally accesses a property on FEATURES without verifying it exists first. The current approach works if FEATURES is always injected by Storybook's build system before this module loads, but there's no explicit evidence that this happens for preview entry files. The vitest initialization found is insufficient because it's test-only.

However, since this is part of Storybook's internal rendering system and FEATURES is declared with declare var, it indicates this variable is meant to be injected by the build system. The risk is primarily around ensuring FEATURES is always available at preview runtime.


The conditional logic at lines 9-12 safely accesses FEATURES.experimentalCodeExamples because it's evaluated within a simple ternary operator. While FEATURES is declared but not initialized in this file, it's intended to be injected by Storybook's build system before this preview entry executes. The initialization in vitest-setup.ts (line 42: globalThis.FEATURES = {}) confirms the injection pattern for test environments. The type declaration with NonNullable<StorybookConfigRaw['features']> ensures type safety. This code is working as designed within Storybook's preview initialization framework and requires no changes.

code/renderers/react/src/enrichCsf.ts (3)

10-14: LGTM! Clean feature flag guard.

The early return pattern when the feature is disabled is appropriate and efficient.


35-45: Verify type assertion safety.

Line 41 casts declarator.get('init') to NodePath<t.Expression> before checking isExpression() on Line 43. While the subsequent check provides a guard, the assertion assumes the type before verification.

Consider whether the type guard check on Line 43 is sufficient, or if additional validation is needed before the cast.


15-114: Well-structured enrichment implementation.

The async enrichment logic with parallel processing via Promise.all is efficient. The AST manipulation correctly injects code snippets into story parameters while preserving existing values through spread operators, as documented in the inline comments.

code/renderers/react/src/enrichCsf.test.ts (3)

13-22: LGTM! Mocking follows coding guidelines.

The mocks use spy: true and implementations are in beforeEach, aligning with the project's testing guidelines.

Based on coding guidelines.


24-78: Comprehensive test coverage with inline snapshots.

The test validates the enriched CSF output including the injected code snippets in story parameters. The inline snapshot approach clearly documents the expected transformation.


80-110: Good coverage of disabled feature state.

The test verifies that enrichment is skipped when experimentalCodeExamples is disabled. The @ts-expect-error on Line 81 is acceptable for testing mock property access.

code/core/src/types/modules/core-common.ts (4)

110-111: Improved type inference for presets.

The generic overload enables better type inference when calling presets.apply() with a specific StorybookConfigRaw key, improving the developer experience.


365-365: Well-defined enricher type.

The CsfEnricher type signature clearly defines the contract for CSF enrichment hooks, accepting both the modified and source CSF files and returning a Promise.


381-381: LGTM! Experimental enricher configuration option.

The experimental_enrichCsf option is properly typed using the CsfEnricher type and follows the naming convention for experimental features.


481-488: Feature flag properly documented as experimental.

The JSDoc clearly marks this as experimental and provides a useful description. The default of false is appropriate for an experimental feature.

code/core/src/csf-tools/enrichCsf.ts (3)

2-2: LGTM! Import added for new enricher type.

The CsfEnricher type import is necessary for the EnrichCsfOptions extension.


9-9: Clean extension of EnrichCsfOptions.

Adding the optional enrichCsf hook enables customization of the enrichment pipeline without breaking existing usage.


144-146: Well-integrated async enrichment hook.

The conversion to async and the placement of the enricher hook between meta and story enrichment allows for asynchronous transformations while maintaining the existing enrichment flow.

@nx-cloud
Copy link

nx-cloud bot commented Oct 23, 2025

View your CI Pipeline Execution ↗ for commit 8422167

Command Status Duration Result
nx run-many -t build --parallel=3 ✅ Succeeded 45s View ↗

☁️ Nx Cloud last updated this comment at 2025-10-27 10:45:22 UTC

Copy link
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: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c165fc5 and 308889e.

📒 Files selected for processing (4)
  • code/core/src/types/modules/core-common.ts (5 hunks)
  • code/renderers/react/src/componentManifest/generator.ts (2 hunks)
  • code/renderers/react/src/docs/jsxDecorator.tsx (1 hunks)
  • code/renderers/react/src/enrichCsf.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • code/core/src/types/modules/core-common.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,jsx,json,html,ts,tsx,mjs}

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

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/renderers/react/src/docs/jsxDecorator.tsx
  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/enrichCsf.test.ts
**/*.{ts,tsx,js,jsx,mjs}

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

Export functions from modules when they need to be unit-tested

Files:

  • code/renderers/react/src/docs/jsxDecorator.tsx
  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/enrichCsf.test.ts
code/**/*.{ts,tsx,js,jsx,mjs}

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

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/renderers/react/src/docs/jsxDecorator.tsx
  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/enrichCsf.test.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

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

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/renderers/react/src/docs/jsxDecorator.tsx
  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/enrichCsf.test.ts
code/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

code/**/*.{test,spec}.{ts,tsx}: Place all test files under the code/ directory
Name test files as *.test.ts, *.test.tsx, *.spec.ts, or *.spec.tsx

Files:

  • code/renderers/react/src/enrichCsf.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 mocked functions
Implement mock behaviors in beforeEach blocks
Mock all required dependencies that the test subject uses
Mock implementations should be placed in beforeEach blocks
Each mock implementation should return a Promise for async functions
Mock implementations should match the expected return type of the original function
Use vi.mocked() to access and implement mock behaviors
Mock all required properties and methods that the test subject uses
Avoid direct function mocking without vi.mocked()
Avoid mock implementations outside of beforeEach blocks
Avoid mocking without the spy: true option
Avoid inline mock implementations within test cases
Avoid mocking only a subset of required dependencies
Mock at the highest level of abstraction needed
Keep mock implementations simple and focused
Use type-safe mocking with vi.mocked()
Document complex mock behaviors
Group related mocks together

Files:

  • code/renderers/react/src/enrichCsf.test.ts
**/*.@(test|spec).{ts,tsx,js,jsx}

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

**/*.@(test|spec).{ts,tsx,js,jsx}: Unit tests should import and execute the functions under test rather than only asserting on syntax patterns
Mock external dependencies in tests using vi.mock() (e.g., filesystem, loggers)

Files:

  • code/renderers/react/src/enrichCsf.test.ts
🧠 Learnings (1)
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to code/**/*.{ts,tsx,js,jsx,mjs} : In application code, use Storybook loggers instead of `console.*` (client code: `storybook/internal/client-logger`; server code: `storybook/internal/node-logger`)

Applied to files:

  • code/renderers/react/src/docs/jsxDecorator.tsx
🧬 Code graph analysis (2)
code/renderers/react/src/componentManifest/generator.ts (1)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
  • extractJSDocInfo (5-21)
code/renderers/react/src/enrichCsf.test.ts (3)
code/renderers/react/src/enrichCsf.ts (1)
  • enrichCsf (10-115)
code/core/src/common/presets.ts (2)
  • getPresets (317-327)
  • InterPresetOptions (23-28)
code/core/src/csf-tools/CsfFile.ts (1)
  • loadCsf (1042-1046)
⏰ 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: Core Unit Tests, windows-latest
🔇 Additional comments (8)
code/renderers/react/src/enrichCsf.test.ts (3)

1-16: Mock setup follows guidelines.

The mocks are correctly placed at the top of the file, and node:module uses the required spy: true option. The virtual 'my-preset' module mock is appropriately structured for this test scenario.


18-20: beforeEach implementation follows best practices.

Mock behavior is correctly implemented in the beforeEach block using vi.mocked() for type-safe access.


22-76: Test coverage for enrichment is solid.

The test properly validates that enrichCsf injects code parameters into story exports when the feature flag is enabled. Async operations are correctly awaited, and the inline snapshot provides clear expectations.

code/renderers/react/src/componentManifest/generator.ts (5)

12-12: LGTM: Import updated to match refactored JSDoc extraction.

The import change from extractJSDocTags to extractJSDocInfo aligns with the refactoring that now returns both description and tags, providing more complete JSDoc information.


79-79: Good practice: Trimming whitespace from description.

Using optional chaining with trim() appropriately handles the case where manifestDescription is undefined, while ensuring any description value is cleaned of extraneous whitespace.


76-85: LGTM: Manifest structure enhanced with JSDoc tags.

The returned manifest now includes jsDocTags, providing access to all extracted JSDoc tags. The use of optional chaining for summary and import safely handles missing tag values, and the satisfies ReactComponentManifest constraint ensures type safety.


61-61: Correct handling: Early return includes empty jsDocTags.

When the component file is unavailable, returning jsDocTags: {} is appropriate since JSDoc extraction hasn't occurred yet. This maintains structural consistency with the main return path while still providing component examples.


72-74: The review comment flags a theoretical concern that does not apply to the actual codebase.

The code at lines 72-74 is correct. While extractJSDocInfo does format tag values to include type and name information (e.g., {Type} name description), the empirical evidence shows that @describe and @desc tags are not used anywhere in the componentManifest codebase. The optional chaining at line 74 safely handles the absence of these tags by returning undefined, which then falls back to the description value. The logic is sound and defensive—no changes needed.

Likely an incorrect or invalid review comment.

Comment on lines +80 to +82
vi.spyOn((await import('my-preset')).default, 'features', 'get').mockImplementation(() => ({
experimentalCodeExamples: false,
}));
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Refactor: Mock implementation within test case violates guidelines.

Lines 80-82 modify the mock behavior inside the test case, which violates the guideline: "Avoid inline mock implementations within test cases" and "Implement mock behaviors in beforeEach blocks." Additionally, there's no cleanup/restore after this test, which could affect test isolation.

Consider one of these approaches:

Option 1 (Recommended): Separate describe blocks with beforeEach

-test('should not enrich when experimentalCodeExamples is disabled', async () => {
-  // @ts-expect-error module does not exist
-  vi.spyOn((await import('my-preset')).default, 'features', 'get').mockImplementation(() => ({
-    experimentalCodeExamples: false,
-  }));
+describe('when experimentalCodeExamples is disabled', () => {
+  beforeEach(async () => {
+    // @ts-expect-error module does not exist
+    vi.spyOn((await import('my-preset')).default, 'features', 'get').mockImplementation(() => ({
+      experimentalCodeExamples: false,
+    }));
+  });
+
+  test('should not enrich csf', async () => {
   const presets = await getPresets(['my-preset'], { isCritical: true } as InterPresetOptions);
   const enrichCsf = await presets.apply('experimental_enrichCsf');
+    // ... rest of test
+  });
+});

Option 2: Add mock cleanup

 test('should not enrich when experimentalCodeExamples is disabled', async () => {
   // @ts-expect-error module does not exist
-  vi.spyOn((await import('my-preset')).default, 'features', 'get').mockImplementation(() => ({
+  const spy = vi.spyOn((await import('my-preset')).default, 'features', 'get').mockImplementation(() => ({
     experimentalCodeExamples: false,
   }));
+  
+  try {
     const presets = await getPresets(['my-preset'], { isCritical: true } as InterPresetOptions);
     // ... rest of test assertions
+  } finally {
+    spy.mockRestore();
+  }
 });

Based on learnings (if any previous feedback suggested this pattern).

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In code/renderers/react/src/enrichCsf.test.ts around lines 80 to 82, the test
sets a spy mock implementation inline which violates the guideline to avoid
inline mocks and lacks cleanup; move the vi.spyOn(...).mockImplementation(...)
into a beforeEach within an appropriate describe block (or create a new describe
block for this behavior) and pair it with an afterEach that restores the spy
(e.g., vi.restoreAllMocks or spy.mockRestore) to ensure test isolation and
proper cleanup.

Copy link
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: 0

🧹 Nitpick comments (1)
code/core/src/core-server/presets/favicon.test.ts (1)

32-46: Consider adding the optional args parameter for full interface compliance.

The mock apply signature currently has two parameters but the Presets interface generic overload includes a third optional parameter: apply<T>(extension: string, config?: T, args?: unknown): Promise<T>. While the current tests don't require it, adding the third parameter would make the mock fully compliant with the interface.

Apply this diff to add the optional parameter:

 const createOptions = (locations: string[]): Parameters<typeof m.favicon>[1] => ({
   configDir: '',
   presets: {
-    apply: async (extension: string, config: any) => {
+    apply: async (extension: string, config: any, args?: unknown) => {
       switch (extension) {
         case 'staticDirs': {
           return locations.map((location) => ({ from: location, to: '/' }));
         }
         default: {
           return config as any;
         }
       }
     },
   } as Presets,
 });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 308889e and 7d970f5.

📒 Files selected for processing (2)
  • code/core/src/core-server/presets/favicon.test.ts (2 hunks)
  • code/core/src/csf-tools/enrichCsf.test.ts (22 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
code/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

code/**/*.{test,spec}.{ts,tsx}: Place all test files under the code/ directory
Name test files as *.test.ts, *.test.tsx, *.spec.ts, or *.spec.tsx

Files:

  • code/core/src/core-server/presets/favicon.test.ts
  • code/core/src/csf-tools/enrichCsf.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 mocked functions
Implement mock behaviors in beforeEach blocks
Mock all required dependencies that the test subject uses
Mock implementations should be placed in beforeEach blocks
Each mock implementation should return a Promise for async functions
Mock implementations should match the expected return type of the original function
Use vi.mocked() to access and implement mock behaviors
Mock all required properties and methods that the test subject uses
Avoid direct function mocking without vi.mocked()
Avoid mock implementations outside of beforeEach blocks
Avoid mocking without the spy: true option
Avoid inline mock implementations within test cases
Avoid mocking only a subset of required dependencies
Mock at the highest level of abstraction needed
Keep mock implementations simple and focused
Use type-safe mocking with vi.mocked()
Document complex mock behaviors
Group related mocks together

Files:

  • code/core/src/core-server/presets/favicon.test.ts
  • code/core/src/csf-tools/enrichCsf.test.ts
**/*.{js,jsx,json,html,ts,tsx,mjs}

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

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/core/src/core-server/presets/favicon.test.ts
  • code/core/src/csf-tools/enrichCsf.test.ts
**/*.@(test|spec).{ts,tsx,js,jsx}

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

**/*.@(test|spec).{ts,tsx,js,jsx}: Unit tests should import and execute the functions under test rather than only asserting on syntax patterns
Mock external dependencies in tests using vi.mock() (e.g., filesystem, loggers)

Files:

  • code/core/src/core-server/presets/favicon.test.ts
  • code/core/src/csf-tools/enrichCsf.test.ts
**/*.{ts,tsx,js,jsx,mjs}

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

Export functions from modules when they need to be unit-tested

Files:

  • code/core/src/core-server/presets/favicon.test.ts
  • code/core/src/csf-tools/enrichCsf.test.ts
code/**/*.{ts,tsx,js,jsx,mjs}

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

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/core/src/core-server/presets/favicon.test.ts
  • code/core/src/csf-tools/enrichCsf.test.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

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

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/core-server/presets/favicon.test.ts
  • code/core/src/csf-tools/enrichCsf.test.ts
🧬 Code graph analysis (2)
code/core/src/core-server/presets/favicon.test.ts (1)
code/core/src/types/modules/core-common.ts (1)
  • Presets (66-114)
code/core/src/csf-tools/enrichCsf.test.ts (2)
code/core/src/csf-tools/enrichCsf.ts (1)
  • EnrichCsfOptions (6-10)
code/core/src/csf-tools/CsfFile.ts (1)
  • formatCsf (1048-1058)
⏰ 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: Core Unit Tests, windows-latest
🔇 Additional comments (3)
code/core/src/csf-tools/enrichCsf.test.ts (2)

14-25: LGTM! Async helper correctly implemented.

The enrich helper has been properly converted to async, correctly awaiting the enrichCsf call while maintaining the synchronous formatCsf return.


29-952: LGTM! Test cases correctly updated for async flow.

All test cases have been consistently updated to be async and properly await the enrich helper. The pattern is correct throughout, and the unchanged snapshots confirm that the enrichment behavior is preserved.

code/core/src/core-server/presets/favicon.test.ts (1)

7-7: LGTM!

The type-only import is a good practice and correctly imports the Presets interface needed for type casting the mock object.

Copy link
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: 2

🧹 Nitpick comments (1)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)

13-19: Simplify the complex tag transformation.

The nested Object.entries(groupBy(...)).map(...) wrapped in Object.fromEntries is difficult to read and maintain. Consider extracting this logic or adding intermediate variables.

Apply this diff to improve readability:

+  const groupedTags = groupBy(parsed[0].tags || [], (it) => it.tag);
+  const formattedTags = Object.entries(groupedTags).map(([key, tags]) => {
+    const tagStrings = tags.map((tag) => {
+      const typePrefix = tag.type ? `{${tag.type}} ` : '';
+      const name = tag.name || '';
+      const description = tag.description || '';
+      return `${typePrefix}${name} ${description}`.trim();
+    });
+    return [key, tagStrings];
+  });
+
  return {
    description: parsed[0].description,
-    tags: Object.fromEntries(
-      Object.entries(groupBy(parsed[0].tags, (it) => it.tag)).map(([key, tags]) => [
-        key,
-        tags?.map((tag) => (tag.type ? `{${tag.type}} ` : '') + `${tag.name} ${tag.description}`) ??
-          [],
-      ])
-    ),
+    tags: Object.fromEntries(formattedTags),
  };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d970f5 and d53734f.

📒 Files selected for processing (1)
  • code/renderers/react/src/componentManifest/jsdocTags.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,json,html,ts,tsx,mjs}

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

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/renderers/react/src/componentManifest/jsdocTags.ts
**/*.{ts,tsx,js,jsx,mjs}

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

Export functions from modules when they need to be unit-tested

Files:

  • code/renderers/react/src/componentManifest/jsdocTags.ts
code/**/*.{ts,tsx,js,jsx,mjs}

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

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/renderers/react/src/componentManifest/jsdocTags.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

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

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/renderers/react/src/componentManifest/jsdocTags.ts
🧬 Code graph analysis (1)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
code/renderers/react/src/componentManifest/utils.ts (1)
  • groupBy (2-12)
⏰ 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: Core Unit Tests, windows-latest

Comment on lines 9 to +12
const parsed = parse(jsDoc);

return Object.fromEntries(
Object.entries(groupBy(parsed[0].tags, (it) => it.tag)).map(([key, tags]) => [
key,
tags?.map((tag) => (tag.type ? `{${tag.type}} ` : '') + `${tag.name} ${tag.description}`) ??
[],
])
);
}

export function removeTags(jsdocComment: string) {
return jsdocComment
.split('\n')
.filter((line) => !line.trim().startsWith('@'))
.join('\n');
return {
description: parsed[0].description,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Add defensive checks for parse results.

The code assumes parse() always returns a non-empty array with a valid first element. If parsing fails or the input is malformed, accessing parsed[0].description and parsed[0].tags will throw a runtime error.

Apply this diff to add defensive checks:

  const parsed = parse(jsDoc);
+
+  if (!parsed || parsed.length === 0) {
+    return { description: '', tags: {} };
+  }

  return {
    description: parsed[0].description,
🤖 Prompt for AI Agents
In code/renderers/react/src/componentManifest/jsdocTags.ts around lines 9 to 12,
the code assumes parse(jsDoc) always returns a non-empty array and directly
accesses parsed[0].description and parsed[0].tags; add defensive checks so
parsing failures or empty results don't throw: after calling parse(jsDoc) verify
parsed is an array and has at least one element, set a const first =
Array.isArray(parsed) && parsed.length > 0 ? parsed[0] : {} and then read
description and tags from first using sensible defaults (e.g., description =
first.description || '' and tags = Array.isArray(first.tags) ? first.tags : []);
optionally wrap parse in try/catch to return safe defaults if parse throws.

Comment on lines +13 to +19
tags: Object.fromEntries(
Object.entries(groupBy(parsed[0].tags, (it) => it.tag)).map(([key, tags]) => [
key,
tags?.map((tag) => (tag.type ? `{${tag.type}} ` : '') + `${tag.name} ${tag.description}`) ??
[],
])
),
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard against undefined tag properties.

The string concatenation on line 16 may produce "undefined" text if tag.name or tag.description is undefined. This could result in malformed output strings like "{string} undefined undefined".

Apply this diff to safely handle undefined values:

      Object.entries(groupBy(parsed[0].tags, (it) => it.tag)).map(([key, tags]) => [
        key,
-        tags?.map((tag) => (tag.type ? `{${tag.type}} ` : '') + `${tag.name} ${tag.description}`) ??
+        tags?.map((tag) => {
+          const typePrefix = tag.type ? `{${tag.type}} ` : '';
+          const name = tag.name || '';
+          const description = tag.description || '';
+          return `${typePrefix}${name} ${description}`.trim();
+        }) ??
          [],
      ])
🤖 Prompt for AI Agents
In code/renderers/react/src/componentManifest/jsdocTags.ts around lines 13 to
19, the map builds strings using tag.type, tag.name and tag.description which
can be undefined and produce literal "undefined" in output; update the mapping
to coerce each value to an empty string when undefined (e.g. use tag.type ?
`{${tag.type}} ` : '' and `${tag.name ?? ''}` and `${tag.description ?? ''}`),
then trim the resulting string to remove extra spaces so malformed strings like
"{string} undefined undefined" cannot occur.

Copy link
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

🧹 Nitpick comments (3)
code/core/src/types/modules/core-common.ts (3)

110-112: Consider clarifying the comment.

The comment "The second and third parameter are not needed" could be more explicit about the purpose of this overload.

Apply this diff to improve clarity:

-  /** The second and third parameter are not needed. And make type inference easier. */
+  /** Convenience overload for retrieving preset values without providing config or args. Improves type inference. */
   apply<T extends keyof StorybookConfigRaw>(extension: T): Promise<StorybookConfigRaw[T]>;

367-367: Clarify parameter roles in the CsfEnricher type.

The two parameters csf and csfSource are both of type CsfFile, but their distinct roles aren't clear from the names alone. Consider either renaming them (e.g., target and source, or enriched and original) or adding JSDoc to explain their purpose.

Example with JSDoc:

+/**
+ * Function that enriches a CSF (Component Story Format) file with additional metadata.
+ * @param csf - The CSF file to be enriched (will be modified)
+ * @param csfSource - The original CSF file source (read-only)
+ */
 export type CsfEnricher = (csf: CsfFile, csfSource: CsfFile) => Promise<void>;

383-383: Add JSDoc documentation for experimental_enrichCsf.

The new experimental_enrichCsf field lacks documentation explaining its purpose and usage. Since this is a public API in StorybookConfigRaw, it should have JSDoc similar to other fields in this interface.

Example JSDoc:

   componentManifestGenerator?: ComponentManifestGenerator;
+  /**
+   * Experimental hook for enriching CSF (Component Story Format) files during processing.
+   * This enables asynchronous transformation of CSF files before they are loaded.
+   * 
+   * @experimental This feature is in early development and may change significantly in future releases.
+   */
   experimental_enrichCsf?: CsfEnricher;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d53734f and 46d43a6.

📒 Files selected for processing (3)
  • code/addons/docs/src/preset.ts (3 hunks)
  • code/core/src/types/modules/core-common.ts (5 hunks)
  • code/renderers/react/src/preset.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • code/renderers/react/src/preset.ts
  • code/addons/docs/src/preset.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,json,html,ts,tsx,mjs}

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

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/core/src/types/modules/core-common.ts
**/*.{ts,tsx,js,jsx,mjs}

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

Export functions from modules when they need to be unit-tested

Files:

  • code/core/src/types/modules/core-common.ts
code/**/*.{ts,tsx,js,jsx,mjs}

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

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/core/src/types/modules/core-common.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

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

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/types/modules/core-common.ts
🧬 Code graph analysis (1)
code/core/src/types/modules/core-common.ts (1)
code/core/src/csf-tools/CsfFile.ts (1)
  • CsfFile (281-1027)
⏰ 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). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (1)
code/core/src/types/modules/core-common.ts (1)

4-4: LGTM: Import properly supports new type definition.

The type-only import of CsfFile is correctly structured and necessary for the CsfEnricher type definition below.

Comment on lines +484 to +495
/**
* Enables the new code example generation for React components. You can see those examples when
* clicking on the "Show code" button in the Storybook UI.
*
* We refactored the code examples by reading the actual source file. This should make the code
* examples a lot faster, more readable and more accurate. They are not dynamic though, it won't
* change if you change when using the control panel.
*
* @default false
* @experimental This feature is in early development and may change significantly in future releases.
*/
experimentalCodeExamples?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Fix grammatical error in JSDoc and consider addressing past review feedback.

The JSDoc has a grammatical issue in the sentence "it won't change if you change when using the control panel."

Apply this diff to fix the grammar:

      * We refactored the code examples by reading the actual source file. This should make the code
      * examples a lot faster, more readable and more accurate. They are not dynamic though, it won't
-     * change if you change when using the control panel.
+     * change when you modify controls in the control panel.

Additionally, the past review comment mentions "better support for render functions." If this is a key improvement, consider adding it explicitly to the JSDoc:

      * Enables the new code example generation for React components. You can see those examples when
      * clicking on the "Show code" button in the Storybook UI.
      *
      * We refactored the code examples by reading the actual source file. This should make the code
-     * examples a lot faster, more readable and more accurate. They are not dynamic though, it won't
-     * change when you modify controls in the control panel.
+     * examples a lot faster, more readable and more accurate, with improved support for render
+     * functions. They are not dynamic though, meaning they won't change when you modify controls
+     * in the control panel.
🤖 Prompt for AI Agents
In code/core/src/types/modules/core-common.ts around lines 484 to 495, the JSDoc
contains a grammatical error ("it won't change if you change when using the
control panel"); update the sentence to a clear form such as "The examples are
static and will not update when you change controls in the control panel." Also,
if desired, add a brief note about improved support for render functions (e.g.,
"May include better support for render functions") to the JSDoc to address the
past review feedback, keeping the @default and @experimental tags unchanged.

Copy link
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: 0

🧹 Nitpick comments (1)
test-storybooks/portable-stories-kitchen-sink/react/jest.setup.ts (1)

5-6: LGTM! Consider adding TypeScript declaration for type safety.

The defensive initialization using nullish coalescing is correct and ensures the FEATURES namespace exists before project annotations are applied.

For better TypeScript type safety, consider adding a global type declaration. You can add this at the top of the file:

+declare global {
+  // eslint-disable-next-line no-var
+  var FEATURES: Record<string, unknown>;
+}
+
 import "@testing-library/jest-dom";
 import { setProjectAnnotations } from "@storybook/react-vite";
 import sbAnnotations from "./.storybook/preview";

Optionally, add a brief comment explaining the purpose:

+// Initialize global FEATURES namespace for experimental feature flags
 globalThis.FEATURES ??= {};
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fdcb204 and 7d3aa5d.

📒 Files selected for processing (1)
  • test-storybooks/portable-stories-kitchen-sink/react/jest.setup.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,json,html,ts,tsx,mjs}

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

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • test-storybooks/portable-stories-kitchen-sink/react/jest.setup.ts
**/*.{ts,tsx,js,jsx,mjs}

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

Export functions from modules when they need to be unit-tested

Files:

  • test-storybooks/portable-stories-kitchen-sink/react/jest.setup.ts
test-storybooks/**

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

Maintain test Storybook configurations under test-storybooks/ for E2E and visual testing scenarios

Files:

  • test-storybooks/portable-stories-kitchen-sink/react/jest.setup.ts
🧬 Code graph analysis (1)
test-storybooks/portable-stories-kitchen-sink/react/jest.setup.ts (1)
code/renderers/web-components/template/components/Html.js (1)
  • globalThis (5-5)
⏰ 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). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest

Copy link
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: 0

🧹 Nitpick comments (1)
test-storybooks/portable-stories-kitchen-sink/react/globals.setup.ts (1)

1-1: LGTM! Consider adding a brief comment.

The initialization is correct and follows the established pattern used elsewhere in the codebase (e.g., code/vitest-setup.ts).

Optionally, add a brief comment explaining the purpose:

+// Initialize global feature flags object for test environment
 globalThis.FEATURES = {};
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d3aa5d and a496f56.

📒 Files selected for processing (3)
  • test-storybooks/portable-stories-kitchen-sink/react/globals.setup.ts (1 hunks)
  • test-storybooks/portable-stories-kitchen-sink/react/jest.config.js (1 hunks)
  • test-storybooks/portable-stories-kitchen-sink/react/jest.setup.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test-storybooks/portable-stories-kitchen-sink/react/jest.setup.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,json,html,ts,tsx,mjs}

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

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • test-storybooks/portable-stories-kitchen-sink/react/globals.setup.ts
  • test-storybooks/portable-stories-kitchen-sink/react/jest.config.js
**/*.{ts,tsx,js,jsx,mjs}

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

Export functions from modules when they need to be unit-tested

Files:

  • test-storybooks/portable-stories-kitchen-sink/react/globals.setup.ts
  • test-storybooks/portable-stories-kitchen-sink/react/jest.config.js
test-storybooks/**

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

Maintain test Storybook configurations under test-storybooks/ for E2E and visual testing scenarios

Files:

  • test-storybooks/portable-stories-kitchen-sink/react/globals.setup.ts
  • test-storybooks/portable-stories-kitchen-sink/react/jest.config.js
🧠 Learnings (2)
📚 Learning: 2025-09-17T08:11:04.287Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursorrules:0-0
Timestamp: 2025-09-17T08:11:04.287Z
Learning: Applies to code/**/*.{test,spec}.{ts,tsx} : Name test files as *.test.ts, *.test.tsx, *.spec.ts, or *.spec.tsx

Applied to files:

  • test-storybooks/portable-stories-kitchen-sink/react/jest.config.js
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Group related mocks together

Applied to files:

  • test-storybooks/portable-stories-kitchen-sink/react/jest.config.js
🧬 Code graph analysis (1)
test-storybooks/portable-stories-kitchen-sink/react/globals.setup.ts (1)
code/renderers/web-components/template/components/Html.js (1)
  • globalThis (5-5)
⏰ 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). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (1)
test-storybooks/portable-stories-kitchen-sink/react/jest.config.js (1)

3-3: LGTM! Proper placement for global initialization.

The setupFiles configuration correctly loads the global setup before setupFilesAfterEnv, ensuring that the global FEATURES object is available before any test setup runs.

Copy link
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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a496f56 and 8422167.

📒 Files selected for processing (1)
  • code/renderers/react/src/entry-preview-docs.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,json,html,ts,tsx,mjs}

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

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/renderers/react/src/entry-preview-docs.ts
**/*.{ts,tsx,js,jsx,mjs}

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

Export functions from modules when they need to be unit-tested

Files:

  • code/renderers/react/src/entry-preview-docs.ts
code/**/*.{ts,tsx,js,jsx,mjs}

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

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/renderers/react/src/entry-preview-docs.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

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

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/renderers/react/src/entry-preview-docs.ts
🧬 Code graph analysis (1)
code/renderers/react/src/entry-preview-docs.ts (2)
code/renderers/web-components/template/components/Html.js (1)
  • globalThis (5-5)
code/renderers/react/src/docs/jsxDecorator.tsx (1)
  • jsxDecorator (234-265)
⏰ 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). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest

Comment on lines +6 to +7
export const decorators: DecoratorFunction<ReactRenderer>[] =
'FEATURES' in globalThis && globalThis?.FEATURES?.experimentalCodeExamples ? [] : [jsxDecorator];
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Verify the necessity of the 'in' operator check.

The condition combines the in operator with optional chaining. While this is defensively sound, the 'FEATURES' in globalThis check may be redundant since optional chaining already handles undefined/null cases.

Consider simplifying to:

-export const decorators: DecoratorFunction<ReactRenderer>[] =
-  'FEATURES' in globalThis && globalThis?.FEATURES?.experimentalCodeExamples ? [] : [jsxDecorator];
+export const decorators: DecoratorFunction<ReactRenderer>[] =
+  globalThis.FEATURES?.experimentalCodeExamples ? [] : [jsxDecorator];

Additionally, consider using explicit boolean comparison if experimentalCodeExamples should strictly be a boolean flag:

globalThis.FEATURES?.experimentalCodeExamples === true

Run the following script to check if there are TypeScript errors and whether the 'in' check pattern is used consistently elsewhere:


🏁 Script executed:

#!/bin/bash
# Check for similar feature flag patterns in the codebase
rg -n "FEATURES.*in.*globalThis|globalThis.*FEATURES" --type=ts --type=js -C2

# Check for TypeScript definitions of globalThis.FEATURES
rg -n "globalThis.*FEATURES|FEATURES.*globalThis" --type=ts -g "*.d.ts" -C2

Length of output: 5148


Remove unnecessary 'FEATURES' in globalThis check to match codebase patterns.

The 'FEATURES' in globalThis check is inconsistent with the rest of the codebase. Every other feature flag in the application uses optional chaining without the 'in' operator:

  • code/core/src/measure/preview.ts:7: globalThis.FEATURES?.measure
  • code/core/src/outline/preview.ts:7: globalThis.FEATURES?.outline
  • code/core/src/actions/manager.tsx:10: globalThis?.FEATURES?.actions
  • And 8+ additional instances throughout the codebase

Since globalThis.FEATURES is initialized in vitest-setup.ts before code execution, the 'in' check is redundant. Simplify to match the established pattern:

-export const decorators: DecoratorFunction<ReactRenderer>[] =
-  'FEATURES' in globalThis && globalThis?.FEATURES?.experimentalCodeExamples ? [] : [jsxDecorator];
+export const decorators: DecoratorFunction<ReactRenderer>[] =
+  globalThis.FEATURES?.experimentalCodeExamples ? [] : [jsxDecorator];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const decorators: DecoratorFunction<ReactRenderer>[] =
'FEATURES' in globalThis && globalThis?.FEATURES?.experimentalCodeExamples ? [] : [jsxDecorator];
export const decorators: DecoratorFunction<ReactRenderer>[] =
globalThis.FEATURES?.experimentalCodeExamples ? [] : [jsxDecorator];
🤖 Prompt for AI Agents
In code/renderers/react/src/entry-preview-docs.ts around lines 6 to 7, remove
the redundant "'FEATURES' in globalThis" check and replace it with the same
optional-chaining pattern used across the codebase (e.g.,
globalThis?.FEATURES?.experimentalCodeExamples) so the decorators assignment
becomes conditional solely on optional chaining; ensure the expression remains
logically equivalent (use globalThis?.FEATURES?.experimentalCodeExamples) and
update formatting to match surrounding files.

@kasperpeulen kasperpeulen merged commit 26d8df6 into 10.1-with-canary-release Oct 27, 2025
22 of 34 checks passed
@kasperpeulen kasperpeulen deleted the kasper/source-code branch October 27, 2025 10:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants