-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
CSF tests each
and matrix
#32556
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
base: next
Are you sure you want to change the base?
CSF tests each
and matrix
#32556
Conversation
WalkthroughAdds parameterized test support to CSF stories via new Story APIs: each and matrix. Updates csf-factories to generate multiple tests per parameter set, using fast-printf for label formatting. Extends CsfFile parsing to discover and expand A.each and A.matrix calls, including tag resolution from static values or inline functions, and validates/expands parameters (including cartesian product for matrix). Updates story indexer and multiple tests to cover discovery, naming, tagging, and execution. Adds new public types (EachTestParam, EachTestFunction, EachAnnotationsFunction) and re-exports them. Adds fast-printf as a dependency. Sequence Diagram(s)sequenceDiagram
autonumber
actor Author
participant Story as Story (CSF)
participant Factories as csf-factories
participant Runtime as Runtime/Test Runner
Author->>Story: define story
Author->>Story: Story.each(name, rows[, annotations], testFn)
Story->>Factories: create tests from rows
Factories->>Factories: format names (fast-printf)
Factories->>Runtime: register N tests with resolved annotations
Runtime-->>Author: execute each test with mapped params
sequenceDiagram
autonumber
actor Author
participant Story as Story (CSF)
participant Factories as csf-factories
participant CsfTools as CsfFile parser
participant Indexer as Story Indexer
Author->>Story: Story.matrix(name, matrix[, annotations], testFn)
Story->>Factories: expand cartesian product
Factories->>Factories: format names (fast-printf)
Note over Factories: Generate one test per combination
Factories->>Indexer: expose tests in story metadata
Indexer->>CsfTools: parse CallExpressions (matrix/each)
CsfTools->>CsfTools: validate params, resolve tags (incl. inline fns)
CsfTools-->>Indexer: discovered tests with names/tags
Possibly related PRs
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
Comment |
e93f6cc
to
a94138e
Compare
View your CI Pipeline Execution ↗ for commit a94138e
☁️ Nx Cloud last updated this comment at |
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: 2
🧹 Nitpick comments (1)
code/core/src/csf/csf-factories.ts (1)
29-31
: Allow readonly tuples for matrix inputs.Right now
MatrixParams
insists on mutable inner arrays, so a very common pattern such as
const matrix = [['A', 'B'], [1, 2]] as const; story.matrix(..., matrix, ...)
fails the constraint (readonly [...]
≠ mutable[...]
). Switching the inner type toReadonlyArray
keeps the runtime behavior identical while letting consumers useas const
/satisfies
without casts.-type MatrixParams<T extends EachTestParam[]> = { - [K in keyof T]: T[K][]; -}; +type MatrixParams<T extends EachTestParam[]> = { + [K in keyof T]: ReadonlyArray<T[K]>; +};
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
code/yarn.lock
is excluded by!**/yarn.lock
,!**/*.lock
📒 Files selected for processing (9)
code/core/package.json
(1 hunks)code/core/src/component-testing/components/test-fn.stories.tsx
(1 hunks)code/core/src/csf-tools/CsfFile.test.ts
(1 hunks)code/core/src/csf-tools/CsfFile.ts
(4 hunks)code/core/src/csf-tools/storyIndexer.test.ts
(2 hunks)code/core/src/csf/csf-factories.test.ts
(1 hunks)code/core/src/csf/csf-factories.ts
(4 hunks)code/core/src/csf/story.ts
(1 hunks)code/core/src/types/modules/csf.ts
(1 hunks)
👮 Files not reviewed due to content moderation or server errors (1)
- code/core/src/csf/story.ts
🧰 Additional context used
📓 Path-based instructions (2)
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/csf/csf-factories.test.ts
code/core/src/csf-tools/CsfFile.test.ts
code/core/src/csf-tools/storyIndexer.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/csf/csf-factories.test.ts
code/core/src/csf-tools/CsfFile.test.ts
code/core/src/csf-tools/storyIndexer.test.ts
🧬 Code graph analysis (3)
code/core/src/csf/csf-factories.test.ts (1)
code/core/src/csf/csf-factories.ts (3)
test
(232-260)meta
(64-67)getStoryChildren
(347-354)
code/core/src/csf-tools/CsfFile.test.ts (2)
code/core/src/csf-tools/CsfFile.ts (2)
loadCsf
(1109-1113)parse
(451-1014)code/core/src/csf/csf-factories.ts (2)
story
(123-127)test
(232-260)
code/core/src/csf/csf-factories.ts (1)
code/core/src/csf/story.ts (5)
EachTestParam
(291-291)EachTestFunction
(293-297)StoryAnnotations
(534-554)EachAnnotationsFunction
(299-303)TestFunction
(287-289)
⏰ 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 (5)
code/core/src/component-testing/components/test-fn.stories.tsx (1)
181-210
: Great smoke coverage for the new parameterized APIs.These stories hit both
.each
and.matrix
end-to-end (formatter + per-row args + assertions), so we get immediate signal that the plumbing works as intended.code/core/src/types/modules/csf.ts (1)
25-27
: Exports cover the new parameterized test typesGood call surfacing these through the public CSF types module so downstream factory consumers can stay strongly typed with the new
each
/matrix
APIs.code/core/src/csf-tools/storyIndexer.test.ts (1)
49-66
: Story index coverage foreach
/matrix
looks solidThe snapshot assertions exercise both the per-row and cartesian matrix expansions, so regressions in discovery or naming should be caught early.
code/core/src/csf-tools/CsfFile.test.ts (1)
2654-2963
: Great coverage on test tag propagation and expansionThese scenarios thoroughly validate that tag resolution, overrides, and generated names stay correct across
test
,each
, andmatrix
, which should keep the parser honest as the API evolves.code/core/src/csf/csf-factories.test.ts (1)
79-201
: Factory helpers verified end-to-endAppreciate the direct execution of the generated children—confirms both argument propagation and override behavior for
each
andmatrix
.
"execa": "^8.0.1", | ||
"exsolve": "^1.0.7", | ||
"fast-printf": "^1.6.10", | ||
"fetch-retry": "^6.0.0", | ||
"flush-promises": "^1.0.2", |
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.
Move fast-printf
to dependencies
.
fast-printf
is consumed at runtime by csf-factories.ts
, so bundling it as a dev dependency will leave downstream installs without the module and trigger Cannot find module 'fast-printf'
at execution time. Please publish it as a production dependency.
@@
- "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0",
- "recast": "^0.23.5",
+ "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0",
+ "fast-printf": "^1.6.10",
+ "recast": "^0.23.5",
@@
- "exsolve": "^1.0.7",
- "fast-printf": "^1.6.10",
+ "exsolve": "^1.0.7",
📝 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.
"execa": "^8.0.1", | |
"exsolve": "^1.0.7", | |
"fast-printf": "^1.6.10", | |
"fetch-retry": "^6.0.0", | |
"flush-promises": "^1.0.2", | |
"dependencies": { | |
"esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0", | |
"fast-printf": "^1.6.10", | |
"recast": "^0.23.5" | |
// … other dependencies … | |
}, | |
"devDependencies": { | |
"execa": "^8.0.1", | |
"exsolve": "^1.0.7", | |
"fetch-retry": "^6.0.0", | |
"flush-promises": "^1.0.2" | |
// … other devDependencies … | |
} |
🤖 Prompt for AI Agents
In code/core/package.json around lines 309 to 313, fast-printf is listed as a
devDependency but is required at runtime by csf-factories.ts; move
"fast-printf": "^1.6.10" from devDependencies into the top-level dependencies
section (same version), remove it from devDependencies, then update the lockfile
by running npm install or yarn install so the production install includes the
package.
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.
The dependency will be bundled by the build script.
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.
@mrginglymus Thank you for the clarification! You're absolutely right. I see from the retrieved learning that in Storybook's core package, dependencies 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.
I apologize for the confusion in my initial suggestion. The placement of fast-printf
in devDependencies is correct for Storybook's bundling approach.
✏️ Learnings added
Learnt from: mrginglymus
PR: storybookjs/storybook#32556
File: code/core/package.json:309-313
Timestamp: 2025-09-29T13:20:23.320Z
Learning: The `fast-printf` dependency in Storybook's core package is bundled into the final distribution during the build process, so it should remain in devDependencies rather than being moved to dependencies, following the same pattern as other bundled dependencies like `open`.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: ndelangen
PR: storybookjs/storybook#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.
t.isCallExpression(expression) && | ||
t.isMemberExpression(expression.callee) && | ||
expression.arguments.length >= 3 && | ||
t.isStringLiteral(expression.arguments[0]) && | ||
t.isArrayExpression(expression.arguments[1]) && | ||
t.isMemberExpression(expression.callee) && | ||
t.isIdentifier(expression.callee.object) && | ||
t.isIdentifier(expression.callee.property) && | ||
['each', 'matrix'].includes(expression.callee.property.name) | ||
) { | ||
const exportName = expression.callee.object.name; | ||
const testName = expression.arguments[0].value; | ||
const testFunction = | ||
expression.arguments.length === 3 ? expression.arguments[2] : expression.arguments[3]; | ||
const testArguments = | ||
expression.arguments.length === 3 ? null : expression.arguments[2]; | ||
const tags = parseTestTags(testArguments as t.Node | null, self._ast.program); | ||
|
||
const parameters = parseParameters(expression.arguments[1]); | ||
|
||
const combinate = (args: typeof parameters) => | ||
args.reduce<typeof args>( | ||
(acc, param) => acc.flatMap((acc2) => param.map((p) => [...acc2, p])), | ||
[[]] | ||
); | ||
|
||
(expression.callee.property.name === 'matrix' | ||
? combinate(parameters) | ||
: parameters | ||
).forEach((args) => { | ||
self._tests.push({ | ||
function: testFunction, | ||
name: format(testName, ...args), | ||
node: expression, | ||
// can't set id because meta title isn't available yet | ||
// so it's set later on | ||
id: 'FIXME', | ||
tags, | ||
parent: { node: self._storyStatements[exportName] }, | ||
}); | ||
// TODO: fix this when stories fail | ||
self._stories[exportName].__stats.tests = true; | ||
}); | ||
} |
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.
Handle .each
/.matrix
parameter arrays resolved from identifiers.
Right now we only enter this branch when the second argument is an inline array literal. In practice it’s common to write const cases = [...]
and then call A.each('case %s', cases, …)
. That’s perfectly valid at runtime, but with the current guard those tests disappear from the index because the parser never sees them. We should mirror the tag logic: resolve identifiers (and other simple indirections) to their initializer via findVarInitialization
before asserting t.isArrayExpression
, so hoisted/shared parameter lists are still discovered.
- t.isArrayExpression(expression.arguments[1]) &&
+ (t.isArrayExpression(expression.arguments[1]) ||
+ t.isIdentifier(expression.arguments[1])) &&
…
- const parameters = parseParameters(expression.arguments[1]);
+ const parametersNode = t.isIdentifier(expression.arguments[1])
+ ? findVarInitialization(expression.arguments[1].name, self._ast.program)
+ : expression.arguments[1];
+ if (!parametersNode || !t.isArrayExpression(parametersNode)) {
+ return;
+ }
+ const parameters = parseParameters(parametersNode);
Without this, parameterized tests defined through reusable constants (or simple re-exports) silently drop out of the story index. Let's make sure we cover that path before shipping.
📝 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.
t.isCallExpression(expression) && | |
t.isMemberExpression(expression.callee) && | |
expression.arguments.length >= 3 && | |
t.isStringLiteral(expression.arguments[0]) && | |
t.isArrayExpression(expression.arguments[1]) && | |
t.isMemberExpression(expression.callee) && | |
t.isIdentifier(expression.callee.object) && | |
t.isIdentifier(expression.callee.property) && | |
['each', 'matrix'].includes(expression.callee.property.name) | |
) { | |
const exportName = expression.callee.object.name; | |
const testName = expression.arguments[0].value; | |
const testFunction = | |
expression.arguments.length === 3 ? expression.arguments[2] : expression.arguments[3]; | |
const testArguments = | |
expression.arguments.length === 3 ? null : expression.arguments[2]; | |
const tags = parseTestTags(testArguments as t.Node | null, self._ast.program); | |
const parameters = parseParameters(expression.arguments[1]); | |
const combinate = (args: typeof parameters) => | |
args.reduce<typeof args>( | |
(acc, param) => acc.flatMap((acc2) => param.map((p) => [...acc2, p])), | |
[[]] | |
); | |
(expression.callee.property.name === 'matrix' | |
? combinate(parameters) | |
: parameters | |
).forEach((args) => { | |
self._tests.push({ | |
function: testFunction, | |
name: format(testName, ...args), | |
node: expression, | |
// can't set id because meta title isn't available yet | |
// so it's set later on | |
id: 'FIXME', | |
tags, | |
parent: { node: self._storyStatements[exportName] }, | |
}); | |
// TODO: fix this when stories fail | |
self._stories[exportName].__stats.tests = true; | |
}); | |
} | |
t.isCallExpression(expression) && | |
t.isMemberExpression(expression.callee) && | |
expression.arguments.length >= 3 && | |
t.isStringLiteral(expression.arguments[0]) && | |
(t.isArrayExpression(expression.arguments[1]) || | |
t.isIdentifier(expression.arguments[1])) && | |
t.isMemberExpression(expression.callee) && | |
t.isIdentifier(expression.callee.object) && | |
t.isIdentifier(expression.callee.property) && | |
['each', 'matrix'].includes(expression.callee.property.name) | |
) { | |
const exportName = expression.callee.object.name; | |
const testName = expression.arguments[0].value; | |
const testFunction = | |
expression.arguments.length === 3 ? expression.arguments[2] : expression.arguments[3]; | |
const testArguments = | |
expression.arguments.length === 3 ? null : expression.arguments[2]; | |
const tags = parseTestTags(testArguments as t.Node | null, self._ast.program); | |
const parametersNode = t.isIdentifier(expression.arguments[1]) | |
? findVarInitialization(expression.arguments[1].name, self._ast.program) | |
: expression.arguments[1]; | |
if (!parametersNode || !t.isArrayExpression(parametersNode)) { | |
return; | |
} | |
const parameters = parseParameters(parametersNode); | |
const combinate = (args: typeof parameters) => | |
args.reduce<typeof args>( | |
(acc, param) => acc.flatMap((acc2) => param.map((p) => [...acc2, p])), | |
[[]] | |
); | |
(expression.callee.property.name === 'matrix' | |
? combinate(parameters) | |
: parameters | |
).forEach((args) => { | |
self._tests.push({ | |
function: testFunction, | |
name: format(testName, ...args), | |
node: expression, | |
// can't set id because meta title isn't available yet | |
// so it's set later on | |
id: 'FIXME', | |
tags, | |
parent: { node: self._storyStatements[exportName] }, | |
}); | |
// TODO: fix this when stories fail | |
self._stories[exportName].__stats.tests = true; | |
}); | |
} |
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.
I hadn't noticed that utility - if the RFC gets over the line I will implement this.
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.
@mrginglymus That sounds like a great plan! The findVarInitialization
utility is indeed quite handy for resolving identifier references in AST parsing scenarios like this. It's already being used effectively in the codebase for parsing tags and other identifier-based configurations.
Once the RFC gets approved, implementing this enhancement will make the .each
and .matrix
functionality much more flexible for users who prefer to define their test parameters as reusable constants - which is a pretty common pattern. Good catch on deferring this until the RFC decision is made!
Package BenchmarksCommit: The following packages have significant changes to their size or dependencies:
|
Before | After | Difference | |
---|---|---|---|
Dependency count | 18 | 18 | 0 |
Self size | 2.07 MB | 2.06 MB | 🎉 -11 KB 🎉 |
Dependency size | 9.44 MB | 9.43 MB | 🎉 -10 KB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/addon-vitest
Before | After | Difference | |
---|---|---|---|
Dependency count | 6 | 6 | 0 |
Self size | 501 KB | 491 KB | 🎉 -11 KB 🎉 |
Dependency size | 1.53 MB | 1.53 MB | 0 B |
Bundle Size Analyzer | Link | Link |
@storybook/builder-vite
Before | After | Difference | |
---|---|---|---|
Dependency count | 11 | 11 | 0 |
Self size | 330 KB | 319 KB | 🎉 -10 KB 🎉 |
Dependency size | 1.30 MB | 1.30 MB | 0 B |
Bundle Size Analyzer | Link | Link |
storybook
Before | After | Difference | |
---|---|---|---|
Dependency count | 43 | 43 | 0 |
Self size | 30.16 MB | 30.19 MB | 🚨 +30 KB 🚨 |
Dependency size | 17.30 MB | 17.30 MB | 0 B |
Bundle Size Analyzer | Link | Link |
@storybook/html-vite
Before | After | Difference | |
---|---|---|---|
Dependency count | 14 | 14 | 0 |
Self size | 23 KB | 23 KB | 🚨 +18 B 🚨 |
Dependency size | 1.67 MB | 1.66 MB | 🎉 -10 KB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/nextjs
Before | After | Difference | |
---|---|---|---|
Dependency count | 531 | 531 | 0 |
Self size | 950 KB | 939 KB | 🎉 -11 KB 🎉 |
Dependency size | 58.43 MB | 58.41 MB | 🎉 -21 KB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/nextjs-vite
Before | After | Difference | |
---|---|---|---|
Dependency count | 124 | 124 | 0 |
Self size | 4.10 MB | 4.01 MB | 🎉 -81 KB 🎉 |
Dependency size | 21.62 MB | 21.59 MB | 🎉 -31 KB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/preact-vite
Before | After | Difference | |
---|---|---|---|
Dependency count | 14 | 14 | 0 |
Self size | 14 KB | 14 KB | 0 B |
Dependency size | 1.65 MB | 1.64 MB | 🎉 -10 KB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/react-native-web-vite
Before | After | Difference | |
---|---|---|---|
Dependency count | 157 | 157 | 0 |
Self size | 31 KB | 31 KB | 0 B |
Dependency size | 23.01 MB | 22.97 MB | 🎉 -31 KB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/react-vite
Before | After | Difference | |
---|---|---|---|
Dependency count | 114 | 114 | 0 |
Self size | 37 KB | 37 KB | 0 B |
Dependency size | 19.56 MB | 19.53 MB | 🎉 -31 KB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/react-webpack5
Before | After | Difference | |
---|---|---|---|
Dependency count | 272 | 272 | 0 |
Self size | 25 KB | 25 KB | 🚨 +18 B 🚨 |
Dependency size | 43.35 MB | 43.33 MB | 🎉 -21 KB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/svelte-vite
Before | After | Difference | |
---|---|---|---|
Dependency count | 19 | 19 | 0 |
Self size | 59 KB | 59 KB | 🎉 -52 B 🎉 |
Dependency size | 26.79 MB | 26.78 MB | 🎉 -10 KB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/sveltekit
Before | After | Difference | |
---|---|---|---|
Dependency count | 20 | 20 | 0 |
Self size | 58 KB | 58 KB | 🚨 +30 B 🚨 |
Dependency size | 26.85 MB | 26.84 MB | 🎉 -10 KB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/vue3-vite
Before | After | Difference | |
---|---|---|---|
Dependency count | 109 | 109 | 0 |
Self size | 38 KB | 38 KB | 0 B |
Dependency size | 43.78 MB | 43.77 MB | 🎉 -10 KB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/web-components-vite
Before | After | Difference | |
---|---|---|---|
Dependency count | 15 | 15 | 0 |
Self size | 20 KB | 20 KB | 0 B |
Dependency size | 1.70 MB | 1.68 MB | 🎉 -10 KB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/cli
Before | After | Difference | |
---|---|---|---|
Dependency count | 187 | 187 | 0 |
Self size | 905 KB | 890 KB | 🎉 -14 KB 🎉 |
Dependency size | 79.76 MB | 79.79 MB | 🚨 +30 KB 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/codemod
Before | After | Difference | |
---|---|---|---|
Dependency count | 169 | 169 | 0 |
Self size | 35 KB | 35 KB | 0 B |
Dependency size | 76.19 MB | 76.22 MB | 🚨 +30 KB 🚨 |
Bundle Size Analyzer | Link | Link |
create-storybook
Before | After | Difference | |
---|---|---|---|
Dependency count | 44 | 44 | 0 |
Self size | 1.55 MB | 1.55 MB | 🚨 +8 B 🚨 |
Dependency size | 47.46 MB | 47.49 MB | 🚨 +30 KB 🚨 |
Bundle Size Analyzer | node | node |
@storybook/react-dom-shim
Before | After | Difference | |
---|---|---|---|
Dependency count | 0 | 0 | 0 |
Self size | 22 KB | 12 KB | 🎉 -10 KB 🎉 |
Dependency size | 785 B | 785 B | 0 B |
Bundle Size Analyzer | Link | Link |
@storybook/preset-create-react-app
Before | After | Difference | |
---|---|---|---|
Dependency count | 68 | 68 | 0 |
Self size | 36 KB | 26 KB | 🎉 -10 KB 🎉 |
Dependency size | 5.97 MB | 5.97 MB | 0 B |
Bundle Size Analyzer | Link | Link |
@storybook/react
Before | After | Difference | |
---|---|---|---|
Dependency count | 2 | 2 | 0 |
Self size | 894 KB | 884 KB | 🎉 -10 KB 🎉 |
Dependency size | 28 KB | 18 KB | 🎉 -10 KB 🎉 |
Bundle Size Analyzer | Link | Link |
Re-opening #32396 as the target branch was deleted
What I did
Reasonably stable draft of an idea for a .each and .matrix function on csf4 factories to allow for efficient parametrization of tests.
Motivation is largely around chromatic usage - getting combinatorial coverage is currently a lot of C&P, even with things like extend and reusable play functions.
Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!
Documentation
MIGRATION.MD
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal
,ci:merged
orci:daily
GH 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.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 PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the
@storybookjs/core
team here.core team members can create a canary release here or locally with
gh workflow run --repo storybookjs/storybook canary-release-pr.yml --field pr=<PR_NUMBER>
Summary by CodeRabbit
New Features
Tests
Chores