Comments (7)
Hey @luciob what you are trying to achieve is not possible.
Storybook does not hold the JSX source in the parameters. The Storybook docs addon uses react-element-to-jsx-string
internally to rebuild the JSX and that happens dynamically as you access the docs view in Storybook.
If you want, the test-runner can generate DOM snapshots instead. I am not sure what you are trying to achieve though, would be nice to understand your use case better.
from test-runner.
I see! So the examples you are looking for are of the JSX, right? e.g.
<Checkbox onChange={...} />
I'm honestly not sure how you could achieve that with the test-runner and how difficult it might be, or even if it's possible. You could take some inspiration from how it's done in Storybook docs:
https://github.com/storybookjs/storybook/blob/3a1e61cefec8dfd350d42db5598b2d0d9159a878/code/renderers/react/src/docs/jsxDecorator.tsx#L78
Just keep in mind that the test-runner hook runs in node, so if you need to run things in the browser, you need to use page.evaluate
.
The only way to get this easily would be to manually add the source as a parameter, and then access it, but then it will be quite some effort for you to keep things up to date.
from test-runner.
Alright I found a solution to your use case. Please be advised that this is not a recommendation at all, this is more like a hacky workaround that happens to work well! However this code is brittle as it depends on internal things that might change.
Storybook already does the job for you, and addon-docs emits the story source after it's computed. So here's an example of how to:
- listen to that event before the story is rendered (preVisit hook)
- store the data
- use it to do whatever you want (postVisit hook)
import { getStoryContext, TestRunnerConfig } from '@storybook/test-runner'
declare global {
// this is defined internally in the test-runner
// and can be used for logging from the browser to node, helpful for debugging
var logToPage: (message: string) => Promise<void>;
}
type SourceData = { source: string; args: Record<string, any>; id: string}
let extractedData: SourceData
const waitFor = async <T>(condition: () => T): Promise<T> => {
let result = condition();
let timeout = 2000;
const interval = 100;
while (!result && timeout > 0) {
await new Promise(resolve => setTimeout(resolve, interval));
result = condition();
timeout -= interval;
}
if (!result) {
throw new Error('Timeout exceeded');
}
return result;
};
const config: TestRunnerConfig = {
async preVisit(page) {
const extractData = page.evaluate<SourceData>(() => {
return new Promise((resolve, reject) => {
const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__;
// use this helper if you want to debug
// window.logToPage('listening to the storybook channel')
// event emitted by the addon-docs when a snippet is rendered
channel.on('@storybook/core/docs/snippet-rendered', (data) => {
resolve(data)
})
})
})
// we can't await this because it will block the test from continuing
// so we store its value and get it in the next hook
extractData.then(data => {
extractedData = data
})
},
async postVisit(_page, context) {
// waitFor is probably not needed so feel free to remove it. It's here to ensure that the data will be there
// there could be cases where timing isn't right and the event takes a bit longer to be emitted (e.g. complex components that take longer to compute)
const data = await waitFor<typeof extractedData>(() => extractedData)
console.log('Story data', {
id: context.id,
title: context.title,
name: context.name,
source: data.source,
props: data.args
})
}
}
export default config
This results in what you're looking for:
{
id: 'components-iconbutton--default',
title: 'Components/IconButton',
name: 'Default',
source: '<IconButton\n aria-label="forward"\n name="arrow-right"\n/>',
props: { name: 'arrow-right', small: false, 'aria-label': 'forward' }
}
There are things you can change in this snippet. Some things are there for debugging purposes, some things might not be needed, I just wanted to give you a baseline to start with!
from test-runner.
Thanks @yannbf that worked. I was able to solve the issue and generate the components DB.
Just one side note: addon-docs
must be explicitly installed as dev dependency.
from test-runner.
Great to hear @luciob! I'd really love to see what you are able to achieve with this. Seems like you're experimenting with AI?
from test-runner.
Great to hear @luciob! I'd really love to see what you are able to achieve with this. Seems like you're experimenting with AI?
That is the idea. Build a JSON components DB to have all possible documentation for our MUI wrapper library @melfore/mosaic. Once that is done, create something very similar to projects like openV0
to let GPT generate UIs sourcing from our own library. Let's see where this will bring us..
Thanks again for your precious support!
from test-runner.
Hi @yannbf, thanks for your reply.
I'm already doing snapshots in the postVisit
hook, following the tutorial available on SB documentation.
What I'm trying to achieve is to build a JSON database of all components in my library, using StoryBook stories as source of truth.
For each component I want to have a record with:
- name
- description
- props (array of structured data)
- examples (array of source code examples, 1 for each component story)
The first three were quite easy using the postVisit
hook to access story parameters.
The last one is the missing one I'm trying to achieve.
Maybe I could use the react-element-to-jsx-string
somehow, but that's not clear to me how to dynamically import the components.
from test-runner.
Related Issues (20)
- [Bug]: Code coverage for components dropped after upgrading to storybook 8 HOT 4
- [Bug]: Include/Exclude tags dont behave as expected HOT 4
- [Feature request]: Test stoybook behind basic auth
- [Bug]: Storybook 8.1.4 updated stories index to v5, which is unsupported
- [Bug]: Globals variable not properly defined
- [Bug]: How do I get chrome browser logs working?
- [Feature request]: Add `logLevel` to cli options
- [Bug]: Ejecting adds `require` of file that does not exist HOT 2
- [Bug]: how to debug test runner network issues HOT 1
- [Feature request]: Respect dangerouslyIgnoreUnhandledErrors HOT 3
- [Bug]: --includeTags missing some tests HOT 2
- [Bug]: combineTags not available in @storybook/[email protected] HOT 1
- [Feature request]: `defaultPrepare` should be exported
- [Bug]: command test-storybook fails with yarn-berry HOT 10
- Test-runner tests files with no .stories file HOT 2
- [Bug]: A worker process has failed to exit gracefully and has been force exited.
- [Feature request]: is there a way to fail tests in console when coverage threshold is not met HOT 1
- [Bug]: Not able to achieve 100% interaction tests coverage for specific components
- [Feature request]: Run coverage report for interaction tests only
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from test-runner.