How to use composedStory method in storybook-root

Best JavaScript code snippet using storybook-root

index.ts

Source:index.ts Github

copy

Full Screen

1import { defaultDecorateStory, combineParameters } from '@storybook/client-api';2import addons, { applyHooks, HooksContext, mockChannel } from '@storybook/addons';3import type { Meta, StoryContext, ReactFramework } from '@storybook/react';4import { isExportStory } from '@storybook/csf'5import type { GlobalConfig, StoriesWithPartialProps, StoryFile, TestingStory, TestingStoryPlayContext } from './types';6import { getStoryName, globalRender, isInvalidStory, objectEntries } from './utils';7// Some addons use the channel api to communicate between manager/preview, and this is a client only feature, therefore we must mock it.8addons.setChannel(mockChannel());9let globalStorybookConfig = {};10const decorateStory = applyHooks(defaultDecorateStory);11const isValidStoryExport = (storyName: string, nonStoryExportsConfig = {}) =>12 isExportStory(storyName, nonStoryExportsConfig) && storyName !== '__namedExportsOrder'13/** Function that sets the globalConfig of your storybook. The global config is the preview module of your .storybook folder.14 *15 * It should be run a single time, so that your global config (e.g. decorators) is applied to your stories when using `composeStories` or `composeStory`.16 *17 * Example:18 *```jsx19 * // setup.js (for jest)20 * import { setGlobalConfig } from '@storybook/testing-react';21 * import * as globalStorybookConfig from './.storybook/preview';22 *23 * setGlobalConfig(globalStorybookConfig);24 *```25 *26 * @param config - e.g. (import * as globalConfig from '../.storybook/preview')27 */28export function setGlobalConfig(config: GlobalConfig) {29 globalStorybookConfig = config;30}31/**32 * Function that will receive a story along with meta (e.g. a default export from a .stories file)33 * and optionally a globalConfig e.g. (import * from '../.storybook/preview)34 * and will return a composed component that has all args/parameters/decorators/etc combined and applied to it.35 *36 *37 * It's very useful for reusing a story in scenarios outside of Storybook like unit testing.38 *39 * Example:40 *```jsx41 * import { render } from '@testing-library/react';42 * import { composeStory } from '@storybook/testing-react';43 * import Meta, { Primary as PrimaryStory } from './Button.stories';44 *45 * const Primary = composeStory(PrimaryStory, Meta);46 *47 * test('renders primary button with Hello World', () => {48 * const { getByText } = render(<Primary>Hello world</Primary>);49 * expect(getByText(/Hello world/i)).not.toBeNull();50 * });51 *```52 *53 * @param story54 * @param meta - e.g. (import Meta from './Button.stories')55 * @param [globalConfig] - e.g. (import * as globalConfig from '../.storybook/preview') this can be applied automatically if you use `setGlobalConfig` in your setup files.56 */57export function composeStory<GenericArgs>(58 story: TestingStory<GenericArgs>,59 meta: Meta<GenericArgs | any>,60 globalConfig: GlobalConfig = globalStorybookConfig61) {62 if (isInvalidStory(story)) {63 throw new Error(64 `Cannot compose story due to invalid format. @storybook/testing-react expected a function/object but received ${typeof story} instead.`65 );66 }67 if (story.story !== undefined) {68 throw new Error(69 `StoryFn.story object-style annotation is not supported. @storybook/testing-react expects hoisted CSF stories.70 https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#hoisted-csf-annotations`71 );72 }73 const renderFn = typeof story === 'function' ? story : story.render ?? meta.render ?? globalRender;74 const finalStoryFn = (context: StoryContext<ReactFramework, GenericArgs>) => {75 const { passArgsFirst = true } = context.parameters;76 if (!passArgsFirst) {77 throw new Error(78 'composeStory does not support legacy style stories (with passArgsFirst = false).'79 );80 }81 return renderFn(context.args, context);82 };83 const combinedDecorators = [84 ...(story.decorators || []),85 ...(meta?.decorators || []),86 ...(globalConfig.decorators || []),87 ];88 const decorated = decorateStory<ReactFramework>(89 finalStoryFn as any,90 combinedDecorators as any91 );92 const defaultGlobals = Object.entries(93 (globalConfig.globalTypes || {}) as Record<string, { defaultValue: any }>94 ).reduce((acc, [arg, { defaultValue }]) => {95 if (defaultValue) {96 acc[arg] = defaultValue;97 }98 return acc;99 }, {} as Record<string, { defaultValue: any }>);100 const combinedParameters = combineParameters(101 globalConfig.parameters || {},102 meta?.parameters || {},103 story.parameters || {},104 { component: meta?.component }105 )106 const combinedArgs = {107 ...meta?.args,108 ...story.args109 } as GenericArgs110 const context = {111 componentId: '',112 kind: '',113 title: '',114 id: '',115 name: '',116 story: '',117 argTypes: globalConfig.argTypes || {},118 globals: defaultGlobals,119 parameters: combinedParameters,120 initialArgs: combinedArgs,121 args: combinedArgs,122 viewMode: 'story',123 originalStoryFn: renderFn,124 hooks: new HooksContext(),125 } as StoryContext<ReactFramework, GenericArgs>;126 const composedStory = (extraArgs: Partial<GenericArgs>) => {127 return decorated({128 ...context,129 args: {130 ...combinedArgs, ...extraArgs131 }132 })133 }134 const boundPlay = ({ ...extraContext }: TestingStoryPlayContext<GenericArgs>) => {135 return story.play?.({ ...context, ...extraContext });136 }137 composedStory.storyName = story.storyName || story.name138 composedStory.args = combinedArgs139 composedStory.play = boundPlay;140 composedStory.decorators = combinedDecorators141 composedStory.parameters = combinedParameters142 return composedStory143}144/**145 * Function that will receive a stories import (e.g. `import * as stories from './Button.stories'`)146 * and optionally a globalConfig (e.g. `import * from '../.storybook/preview`)147 * and will return an object containing all the stories passed, but now as a composed component that has all args/parameters/decorators/etc combined and applied to it.148 *149 *150 * It's very useful for reusing stories in scenarios outside of Storybook like unit testing.151 *152 * Example:153 *```jsx154 * import { render } from '@testing-library/react';155 * import { composeStories } from '@storybook/testing-react';156 * import * as stories from './Button.stories';157 *158 * const { Primary, Secondary } = composeStories(stories);159 *160 * test('renders primary button with Hello World', () => {161 * const { getByText } = render(<Primary>Hello world</Primary>);162 * expect(getByText(/Hello world/i)).not.toBeNull();163 * });164 *```165 *166 * @param storiesImport - e.g. (import * as stories from './Button.stories')167 * @param [globalConfig] - e.g. (import * as globalConfig from '../.storybook/preview') this can be applied automatically if you use `setGlobalConfig` in your setup files.168 */169export function composeStories<170 TModule extends StoryFile171>(storiesImport: TModule, globalConfig?: GlobalConfig) {172 const { default: meta, __esModule, ...stories } = storiesImport;173 // This function should take this as input: 174 // {175 // default: Meta,176 // Primary: Story<ButtonProps>, <-- Props extends Args177 // Secondary: Story<OtherProps>,178 // }179 // And strips out default, then return composed stories as output: 180 // {181 // Primary: ComposedStory<Partial<ButtonProps>>,182 // Secondary: ComposedStory<Partial<OtherProps>>,183 // }184 // Compose an object containing all processed stories passed as parameters185 const composedStories = objectEntries(stories).reduce<Partial<StoriesWithPartialProps<TModule>>>(186 (storiesMap, [key, _story]) => {187 const storyName = String(key)188 // filter out non-story exports189 if (!isValidStoryExport(storyName, meta)) {190 return storiesMap;191 }192 const story = _story as TestingStory193 story.storyName = getStoryName(story) || storyName194 const result = Object.assign(storiesMap, {195 [key]: composeStory(story, meta, globalConfig)196 });197 return result;198 },199 {}200 );201 // @TODO: the inferred type of composedStories is correct but Partial.202 // investigate whether we can return an unpartial type of that without this hack203 return composedStories as unknown as Omit<StoriesWithPartialProps<TModule>, keyof StoryFile>;...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1import React from 'react';2import { storiesOf } from '@storybook/react';3import { action } from '@storybook/addon-actions';4import { withKnobs, text } from '@storybook/addon-knobs';5import { composedStory } from 'storybook-root-decorator';6import Button from './Button';7storiesOf('Button', module)8 .addDecorator(withKnobs)9 .add('with text', () => (10 <Button onClick={action('clicked')}>11 {text('Label', 'Hello Button')}12 ));13import { configure } from '@storybook/react';14import { addDecorator } from '@storybook/react';15import { withRootDecorator } from 'storybook-root-decorator';16addDecorator(withRootDecorator);17import { withRootDecorator } from 'storybook-root-decorator';18configure(() => {19 require('../test.js');20}, module);21const path = require('path');22module.exports = ({ config }) => {23 config.module.rules.push({24 include: path.resolve(__dirname, '../'),25 });26 return config;27};28import '@storybook/addon-actions/register';29import

Full Screen

Using AI Code Generation

copy

Full Screen

1import { composeStory } from 'storybook-root-decorator';2import { MyComponent } from './MyComponent';3export default {4};5const Template = composeStory(MyComponent);6export const Default = Template.bind({});7Default.args = {8};9import { addDecorator } from '@storybook/react';10import { withRootDecorator } from 'storybook-root-decorator';11addDecorator(withRootDecorator);12import { addDecorator } from '@storybook/react';13import { withRootDecorator } from 'storybook-root-decorator';14import { BrowserRouter as Router } from 'react-router-dom';15addDecorator(withRootDecorator(Router));16import { addDecorator } from '@storybook/react';17import { withRootDecorator } from 'storybook-root-decorator';18import { BrowserRouter as Router } from 'react-router-dom';19addDecorator(withRootDecorator(Router, { initialEntries: ['/'] }));20import { addDecorator } from '@storybook/react';21import { withRootDecorator } from 'storybook-root-decorator';22import { BrowserRouter as Router } from 'react-router-dom';23addDecorator(withRootDecorator(Router, { initialEntries: ['/'] }, { theme: 'dark' }));24import { addDecorator } from '@storybook/react';25import { withRootDecorator } from 'storybook-root-decorator';26import { BrowserRouter as Router } from 'react-router-dom';27addDecorator(withRootDecorator(Router, { initialEntries: ['/'] }, { theme: 'dark' }, { locale: 'en' }));28import { addDecorator } from '@storybook/react';29import { withRootDecorator } from 'storybook-root-decorator';30import { BrowserRouter as Router } from 'react-router-dom';31addDecorator(32 withRootDecorator(33 { initialEntries: ['/'] },34 { theme: 'dark' },35 { locale: 'en' },36 { i18nProvider: i18nProvider }37);38import { addDecorator } from '@storybook/react';39import { withRootDecorator } from 'storybook-root-decorator';40import { BrowserRouter as Router } from '

Full Screen

Using AI Code Generation

copy

Full Screen

1import { composedStory } from 'storybook-root-decorator';2const composedStory = require('storybook-root-decorator').composedStory;3import { composedStory } from 'storybook-root-decorator';4import { withA11y } from '@storybook/addon-a11y';5import { withKnobs } from '@storybook/addon-knobs';6import { withInfo } from '@storybook/addon-info';7import { withTests } from '@storybook/addon-jest';8import { withConsole } from '@storybook/addon-console';9import { withPerformance } from 'storybook-addon-performance';10import { withViewport } from '@storybook/addon-viewport';11import { composedStory } from 'storybook-root-decorator';12import { withA11y } from '@storybook/addon-a11y';13import { withKnobs } from '@storybook/addon-knobs';14import { withInfo } from '@storybook/addon-info';15import { withTests } from '@storybook/addon-jest';16import { withConsole } from '@storybook/addon-console';17import { withPerformance } from 'storybook-addon-performance';18import { withViewport } from '@storybook/addon-viewport';19import { composedStory } from 'storybook-root-decorator';20import { withA11y } from '@storybook/addon-a11y';21import { withKnobs } from '@storybook/addon-knobs';22import { withInfo } from '@storybook/addon-info';23import { withTests } from '@storybook/addon-jest';24import { withConsole } from '@storybook/addon-console';25import { withPerformance } from 'storybook-addon-performance';26import { withViewport } from '@storybook/addon-viewport';27import { composedStory } from 'storybook-root-decorator';28import { withA11y } from '@storybook/addon-a11y';29import { withKnobs } from '@storybook/addon-knobs';30import { withInfo } from '@storybook/addon-info';31import { withTests } from '@storybook/addon-jest';32import { withConsole } from '@storybook/add

Full Screen

Using AI Code Generation

copy

Full Screen

1import {composedStory} from 'storybook-root-decorator';2import {composedStory} from 'storybook-root-decorator';3import {composedStory} from 'storybook-root-decorator';4import {composedStory} from 'storybook-root-decorator';5import {composedStory} from 'storybook-root-decorator';6import {composedStory} from 'storybook-root-decorator';7import {composedStory} from 'storybook-root-decorator';8import {composedStory} from 'storybook-root-decorator';9import {composedStory} from 'storybook-root-decorator';10import {composedStory} from 'storybook-root-decorator';11import {composedStory} from 'storybook-root-decorator';12import {composedStory} from 'storybook-root-decorator';13import {composedStory} from 'storybook-root-decorator';14import {composedStory} from 'storybook-root-decorator';15import {composedStory} from 'storybook-root-decorator';16import {composedStory} from 'storybook-root-decorator';

Full Screen

Using AI Code Generation

copy

Full Screen

1import { composedStory } from 'storybook-root';2import { Button } from './Button';3export default {4};5export const Primary = composedStory(Button, {6});7export const Secondary = composedStory(Button, {8});9export const Large = composedStory(Button, {10});11export const Small = composedStory(Button, {12});13import { Primary, Secondary, Large, Small } from './test';14export default {15};16export const Button = {17};18import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';19import { Button } from './Button';20import { Primary, Secondary, Large, Small } from './test';21<Meta title="Button" component={Button} />22<Props of={Button} />23 <Story name="Primary" story={Primary} />24 <Story name="Secondary" story={Secondary} />25 <Story name="Large" story={Large} />26 <Story name="Small" story={Small} />

Full Screen

Using AI Code Generation

copy

Full Screen

1import React from 'react';2import { storiesOf } from '@storybook/react';3import { composeStory } from 'storybook-root-decorator';4import MyComponent from './MyComponent';5const stories = storiesOf('MyComponent', module);6stories.add('default', () => {7 const story = composeStory(MyComponent, { /* props */ });8 return story;9});10import { configure, addDecorator } from '@storybook/react';11import { withRootDecorator } from 'storybook-root-decorator';12addDecorator(withRootDecorator);13configure(require.context('../src', true, /\.stories\.js$/), module);14import { addDecorator } from '@storybook/react';15import { withRootDecorator } from 'storybook-root-decorator';16addDecorator(withRootDecorator);17import React from 'react';18import { ThemeProvider } from 'styled-components';19import theme from '../src/theme';20const rootDecorator = story => (21 <ThemeProvider theme={theme}>22 {story()}23);24export default rootDecorator;25const path = require('path');26module.exports = (storybookBaseConfig, configType) => {27 storybookBaseConfig.module.rules.push({28 include: path.resolve(__dirname, '../src'),29 {30 options: {31 },32 },33 });34 return storybookBaseConfig;35};36import 'storybook-root-decorator/register';37{38 "scripts": {39 },40 "devDependencies": {

Full Screen

Using AI Code Generation

copy

Full Screen

1export default {2};3export const Primary = () => <Button>Primary</Button>;4export const Secondary = () => <Button>Secondary</Button>;5export const Primary = () => <Button>Primary</Button>;6Primary.parameters = {7 composedStory: {8 parameters: {9 backgrounds: {10 },11 },12 },13};14export const Primary = () => <Button>Primary</Button>;15Primary.parameters = {16 composedStory: {17 parameters: {18 backgrounds: {19 { name: 'dark', value: '#000' },20 { name: 'light', value: '#fff' },21 },22 },23 },24};25export const Primary = () => <Button>Primary</Button>;26Primary.parameters = {27 composedStory: {28 parameters: {29 backgrounds: {30 { name: 'dark', value: '#000' },31 { name: 'light', value: '#fff' },32 },33 },34 (Story) => (35 <div style={{ backgroundColor: 'red' }}>36 },37};38export const Primary = () => <Button>Primary</Button>;39Primary.parameters = {40 composedStory: {41 parameters: {42 backgrounds: {43 { name: 'dark', value: '#000' },44 { name: 'light', value: '#fff' },45 },46 },47 (Story) => (48 <div style={{ backgroundColor: 'red' }}>49 args: {50 },

Full Screen

Using AI Code Generation

copy

Full Screen

1import { composeStory } from "storybook-root-decorator";2import { Button } from "storybook-root-decorator/dist/components/Button";3const ButtonStory = composeStory(Button, {4});5export default ButtonStory;6import ButtonStory from "../test";7export default {8};9export const Button = (args) => ButtonStory(args);10import { composeStory } from "storybook-root-decorator";11import { Heading } from "storybook-root-decorator/dist/components/Heading";12export default {13 component: composeStory(Heading, {14 }),15};16export const Heading = (args) => Heading(args);17import { Button } from "storybook-root-decorator/dist/components/Button";18 onClick={() => console.log("button clicked")}19import { composeStory } from "storybook-root-decorator";20import { Button } from "storybook-root-decorator/dist/components/Button";21const ButtonStory = composeStory(Button, {22});23export default ButtonStory;24import ButtonStory from "./test";25export default {26};27export const Button = (args) => ButtonStory(args);28import ButtonStory from "./test";29export default {30};31export const Button = (args) => ButtonStory(args);32import ButtonStory from "./test";33export default {34};35export const Button = (args) => ButtonStory(args);

Full Screen

Using AI Code Generation

copy

Full Screen

1import { composedStory } from 'storybook-root';2import React from 'react';3import { ThemeProvider } from 'styled-components';4import theme from 'theme';5const customWrapper = storyFn => (6 <ThemeProvider theme={theme}>{storyFn()}</ThemeProvider>7);8const composed = composedStory(customWrapper);9export default composed;

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run storybook-root automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful