-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Addon Vitest: Add component to test transformer #33479
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Addon Vitest: Add component to test transformer #33479
Conversation
|
View your CI Pipeline Execution ↗ for commit cf4298c
☁️ Nx Cloud last updated this comment at |
80898bc to
da79150
Compare
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughAdds a component-to-test transformer and integrates it into the Vitest Storybook addon via a conditional pre-transform plugin driven by STORYBOOK_COMPONENT_PATHS; extracts test-guard creation into a reusable helper; and re-exports the transformer from csf-tools. Changes
Sequence Diagram(s)sequenceDiagram
participant VitestPlugin as Vitest Addon Plugin
participant ComponentTransform as componentTransform
participant Parser as Code Parser/AST
participant Generator as Test Generator
VitestPlugin->>VitestPlugin: Read STORYBOOK_COMPONENT_PATHS
alt paths set
VitestPlugin->>ComponentTransform: transform(code, fileName, getComponentArgTypes)
ComponentTransform->>Parser: parse code, find JSX-bearing exports
Parser-->>ComponentTransform: export metadata (names, AST nodes)
ComponentTransform->>Generator: request argTypes (via getComponentArgTypes) and generate dummy props
Generator->>ComponentTransform: test wrappers, metadata, guard insertion
ComponentTransform-->>VitestPlugin: return transformed code + map
VitestPlugin->>VitestPlugin: inject pre-transform plugin into Vite/Vitest plugins
else no paths
VitestPlugin->>VitestPlugin: skip componentTransform injection
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
✨ Finishing touches
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
Comment |
There was a problem hiding this 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
🤖 Fix all issues with AI agents
In @code/core/src/csf-tools/vitest-plugin/component-transformer.ts:
- Around line 24-27: The sanitizeIdentifier function can return strings that
start with a digit (e.g., "123Component") which are invalid JS identifiers;
modify sanitizeIdentifier to, after stripping invalid chars and ensuring a
non-empty fallback, check whether the first character is a digit and if so
prefix the result with a safe character (e.g., '_' or 'C') so the returned value
is always a valid identifier; ensure this uses the existing sanitizeIdentifier
symbol and preserves the current fallback ('Component') behavior.
🧹 Nitpick comments (5)
code/core/src/csf-tools/vitest-plugin/component-transformer.test.ts (1)
5-13: Consider adding test coverage for thegetComponentArgTypescallback.The
transformhelper always callscomponentTransformwithout the optionalgetComponentArgTypesparameter. This means the args generation path (lines 314-317 in component-transformer.ts) is not exercised.💡 Example test case
it('generates args from getComponentArgTypes when provided', async () => { const code = ` export const Button = ({ label }: { label: string }) => <button>{label}</button>; `; const result = await componentTransform({ code, fileName: 'src/components/Button.tsx', getComponentArgTypes: async () => ({ label: { type: { name: 'string', required: true } }, }), }); expect(result.code).toContain('args: {'); expect(result.code).toContain('label:'); });code/addons/vitest/src/vitest-plugin/index.ts (2)
104-118: Consider clarifying or removing the TODO comment.The path normalization appears necessary to ensure consistent matching against resolved file IDs. If this is confirmed to work correctly during testing, consider removing the TODO or documenting why it's needed.
131-161: Returnundefinedinstead ofcodefor early exits to signal no transformation.When a Vite transform hook returns the original code as a string, it may cause unnecessary source map invalidation. Returning
undefinedornullexplicitly signals that no transformation occurred.Also, consider returning the source map from
componentTransformfor better debugging support.♻️ Proposed fix
async transform(code, id) { if (!optionalEnvToBoolean(process.env.VITEST) || storybookComponentTestPaths.length === 0) { - return code; + return; } const resolvedId = path.resolve(id); const matches = storybookComponentTestPaths.some( (testPath) => resolvedId === testPath || resolvedId.startsWith(testPath + path.sep) || resolvedId.endsWith(testPath) ); // We only transform paths included in STORYBOOK_COMPONENT_PATHS if (!matches) { - return code; + return; } const result = await componentTransform({ code, fileName: id, getComponentArgTypes: async ({ componentName, fileName }) => presets.apply('experimental_getArgTypesData', null, { componentFilePath: fileName, componentExportName: componentName, configDir, }), }); - return result.code; + return { + code: result.code, + map: result.map, + }; },code/core/src/csf-tools/vitest-plugin/component-transformer.ts (2)
180-209: Complex but correct hoisting logic for inline default exports.The approach of inserting a variable declaration before the export and then using
getPrevSibling()to get the init path is clever. Consider adding a brief comment explaining why this two-step approach is needed (to get a proper NodePath for JSX detection).
312-360: Consider parallelizinggetComponentArgTypescalls for performance.The current
for...ofloop withawaitprocesses components sequentially. IfgetComponentArgTypesinvolves I/O (like docgen), parallel processing could improve performance for files with many exports.💡 Parallel approach
// Build component data in parallel const componentData = await Promise.all( components.map(async (component) => { const argTypes = getComponentArgTypes ? await getComponentArgTypes({ componentName: component.exportedName, fileName }) : undefined; const generatedArgs = argTypes ? generateDummyPropsFromArgTypes(argTypes).required : undefined; return { component, generatedArgs }; }) ); // Generate test statements (synchronous) for (const { component, generatedArgs } of componentData) { // ... build testStoryArgs and testCall }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
code/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/transformer.ts
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,jsx,ts,tsx,json,md,html,css,scss}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Format code using Prettier with
yarn prettier --write <file>
Files:
code/core/src/csf-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.ts
**/*.{js,jsx,json,html,ts,tsx,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Run ESLint checks using
yarn lint:js:cmd <file>or the full commandcross-env NODE_ENV=production eslint --cache --cache-location=../.cache/eslint --ext .js,.jsx,.json,.html,.ts,.tsx,.mjs --report-unused-disable-directivesto fix linting errors before committing
Files:
code/core/src/csf-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Enable TypeScript strict mode across all packages
Files:
code/core/src/csf-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx,js,jsx}: Export functions from modules if they need to be tested
Do not useconsole.log,console.warn, orconsole.errordirectly unless in isolated files where importing loggers would significantly increase bundle size
Files:
code/core/src/csf-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.ts
code/{core,lib,addons,builders,frameworks,presets}/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
loggerfromstorybook/internal/node-loggerfor server-side logging in Node.js code
Files:
code/core/src/csf-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.ts
**/*.{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.mdcfor consistent mocking patterns with Vitest
Files:
code/core/src/csf-tools/vitest-plugin/component-transformer.test.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/spy-mocking.mdc)
**/*.test.{ts,tsx,js,jsx}: Usevi.mock()with thespy: trueoption for all package and file mocks in Vitest tests
Place all mocks at the top of the test file before any test cases
Usevi.mocked()to type and access the mocked functions in Vitest tests
Implement mock behaviors inbeforeEachblocks 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 withoutvi.mocked()in Vitest tests
Avoid mock implementations outside ofbeforeEachblocks in Vitest tests
Avoid mocking without thespy: trueoption 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 withvi.mocked()in Vitest tests
Document complex mock behaviors in Vitest tests
Group related mocks together in Vitest tests
Files:
code/core/src/csf-tools/vitest-plugin/component-transformer.test.ts
**/*.{test,spec}.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{test,spec}.{ts,tsx,js,jsx}: Write meaningful unit tests that actually import and call the functions being tested, not just verify syntax patterns
Achieve high test coverage of business logic, aiming for 75%+ coverage of statements/lines
Cover all branches, conditions, edge cases, error paths, and different input variations in unit tests
Usevi.mock()to mock file system, loggers, and other external dependencies in tests
Files:
code/core/src/csf-tools/vitest-plugin/component-transformer.test.ts
🧠 Learnings (25)
📓 Common learnings
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
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
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
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
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
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
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
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
📚 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-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.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-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.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-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.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-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.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-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.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 direct function mocking without `vi.mocked()` in Vitest tests
Applied to files:
code/core/src/csf-tools/vitest-plugin/transformer.tscode/addons/vitest/src/vitest-plugin/index.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 code/vitest.workspace.ts : Vitest configuration is centralized in `code/vitest.workspace.ts` for workspace setup
Applied to files:
code/core/src/csf-tools/vitest-plugin/transformer.tscode/addons/vitest/src/vitest-plugin/index.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-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.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 without the `spy: true` option in Vitest tests
Applied to files:
code/core/src/csf-tools/vitest-plugin/transformer.tscode/addons/vitest/src/vitest-plugin/index.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-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.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-tools/vitest-plugin/transformer.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-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.ts
📚 Learning: 2025-12-22T22:03:40.123Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Write meaningful unit tests that actually import and call the functions being tested, not just verify syntax patterns
Applied to files:
code/core/src/csf-tools/vitest-plugin/transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/core/src/csf-tools/index.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-tools/vitest-plugin/transformer.ts
📚 Learning: 2025-12-22T22:03:40.123Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Export functions from modules if they need to be tested
Applied to files:
code/core/src/csf-tools/vitest-plugin/component-transformer.tscode/core/src/csf-tools/vitest-plugin/component-transformer.test.tscode/core/src/csf-tools/index.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} : Each mock implementation should return a Promise for async functions in Vitest
Applied to files:
code/core/src/csf-tools/vitest-plugin/component-transformer.tscode/addons/vitest/src/vitest-plugin/index.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-tools/vitest-plugin/component-transformer.test.ts
📚 Learning: 2025-12-22T22:03:40.123Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to code/{core,lib,addons,builders,frameworks,presets}/**/*.{ts,tsx,js,jsx} : Use `logger` from `storybook/internal/node-logger` for server-side logging in Node.js code
Applied to files:
code/addons/vitest/src/vitest-plugin/index.tscode/core/src/csf-tools/index.ts
📚 Learning: 2025-12-22T22:03:40.123Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to code/{renderers}/**/*.{ts,tsx,js,jsx} : Use `logger` from `storybook/internal/client-logger` for client-side logging in browser code
Applied to files:
code/addons/vitest/src/vitest-plugin/index.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/addons/vitest/src/vitest-plugin/index.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/addons/vitest/src/vitest-plugin/index.ts
📚 Learning: 2025-11-05T09:37:25.920Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/tooltip/WithTooltip.tsx:54-96
Timestamp: 2025-11-05T09:37:25.920Z
Learning: Repo: storybookjs/storybook — In code/core/src/components/components/tooltip/WithTooltip.tsx, the legacy WithTooltip implementation is intentionally reintroduced for backward compatibility and is deprecated; maintainers (per Sidnioulz) do not want maintenance or improvements on it. Prefer WithTooltipNew/Popover; avoid suggesting changes to WithTooltip.* going forward.
Applied to files:
code/addons/vitest/src/vitest-plugin/index.ts
📚 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/addons/vitest/src/vitest-plugin/index.ts
📚 Learning: 2025-12-22T22:03:40.123Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Use `vi.mock()` to mock file system, loggers, and other external dependencies in tests
Applied to files:
code/core/src/csf-tools/index.ts
🧬 Code graph analysis (3)
code/core/src/csf-tools/vitest-plugin/component-transformer.ts (2)
code/core/src/core-server/utils/get-dummy-props-for-args.ts (1)
generateDummyPropsFromArgTypes(18-48)code/core/src/csf-tools/vitest-plugin/transformer.ts (1)
createTestGuardDeclaration(54-106)
code/core/src/csf-tools/vitest-plugin/component-transformer.test.ts (2)
code/core/src/csf-tools/index.ts (1)
componentTransform(7-7)code/core/src/csf-tools/vitest-plugin/component-transformer.ts (1)
componentTransform(264-373)
code/addons/vitest/src/vitest-plugin/index.ts (3)
code/core/src/common/utils/envs.ts (1)
optionalEnvToBoolean(59-70)code/core/src/csf-tools/index.ts (1)
componentTransform(7-7)code/core/src/csf-tools/vitest-plugin/component-transformer.ts (1)
componentTransform(264-373)
⏰ 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). (3)
- GitHub Check: normal
- GitHub Check: nx
- GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (8)
code/core/src/csf-tools/index.ts (1)
7-7: LGTM!The new export follows the established pattern and correctly exposes
componentTransformfrom the public API, consistent with the existingvitestTransformexport.code/core/src/csf-tools/vitest-plugin/component-transformer.test.ts (1)
206-214: LGTM!Good coverage of the early-return path when no JSX-containing components are found. This ensures non-component exports remain untouched.
code/core/src/csf-tools/vitest-plugin/transformer.ts (2)
46-106: Good refactor to extract reusable guard logic.The function is well-documented and properly typed. The TODO comments (lines 67-68, 78-79) correctly reference the upstream Vitest issue for future cleanup.
230-235: LGTM!Clean usage of the extracted helper. The guard declaration is properly integrated with the existing transform flow.
code/addons/vitest/src/vitest-plugin/index.ts (1)
504-506: LGTM!The conditional plugin insertion correctly gates the component transform plugin behind the environment variable, avoiding unnecessary plugin registration when not needed.
code/core/src/csf-tools/vitest-plugin/component-transformer.ts (3)
38-55: LGTM!The JSX detection is efficient with early exit on first match, and correctly handles both
JSXElementandJSXFragmentnodes.
69-90: LGTM!Good implementation of import deduplication that avoids duplicate specifiers while maintaining proper import ordering.
13-13: Verify cross-module import is intentional.This imports from
../../core-server/utils/get-dummy-props-for-args, crossing fromcsf-toolstocore-server. If this utility is meant to be shared, consider re-exporting it from a common location or moving it to a shared utils module.
Package BenchmarksCommit: The following packages have significant changes to their size or dependencies:
|
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 49 | 49 | 0 |
| Self size | 20.19 MB | 20.20 MB | 🚨 +10 KB 🚨 |
| Dependency size | 16.52 MB | 16.52 MB | 0 B |
| Bundle Size Analyzer | Link | Link |
@storybook/cli
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 183 | 183 | 0 |
| Self size | 775 KB | 775 KB | 🚨 +84 B 🚨 |
| Dependency size | 67.25 MB | 67.26 MB | 🚨 +11 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/codemod
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 176 | 176 | 0 |
| Self size | 30 KB | 30 KB | 0 B |
| Dependency size | 65.82 MB | 65.83 MB | 🚨 +10 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
create-storybook
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 50 | 50 | 0 |
| Self size | 999 KB | 999 KB | 🚨 +42 B 🚨 |
| Dependency size | 36.71 MB | 36.72 MB | 🚨 +10 KB 🚨 |
| Bundle Size Analyzer | node | node |
Closes #
What I did
This PR introduces a Vite transformer which transforms a component code directly to a test code, using portable stories. This is useful to quickly detect whether a component turned into a story would be successful. It also uses the
experimental_getArgTypesDatapreset to generate correct args for required props.This will only be used internally as there's no use case for user usage at the moment.
Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
codedirectorycode/core/src/components/components/Badge/Badge.tsxSTORYBOOK_COMPONENT_PATHS=core/src/components/components/Badge/Badge.tsx y test:watch Badge.tsxDocumentation
MIGRATION.MD
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal,ci:mergedorci:dailyGH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli-storybook/src/sandbox-templates.tsMake 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 PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the
@storybookjs/coreteam here.core team members can create a canary release here or locally with
gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>Summary by CodeRabbit
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.