Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Enhance CSF factories with extend method for React stories and add te…
…sts for extended stories
  • Loading branch information
yannbf committed Oct 17, 2025
commit bd00e44c5ae2400a7fc76ad49c886018591af823
10 changes: 9 additions & 1 deletion code/core/src/csf/csf-factories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ function defineStory<
return test as unknown as void;
},
extend<TInput extends StoryAnnotations<TRenderer, TRenderer['args']>>(input: TInput) {
return defineStory(
const extendedStory = defineStory(
{
...this.input,
...input,
Expand Down Expand Up @@ -252,6 +252,14 @@ function defineStory<
},
this.meta
);

// @ts-expect-error For React renderer, ensure Component property is properly set on extended story
if (this.Component) {
// @ts-expect-error same as above
extendedStory.Component = extendedStory.__compose();
}

return extendedStory;
},
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,15 @@ describe('CSF3', () => {
});
});

describe('Story extend', () => {
it('extended story should render with combined args', () => {
const ExtendedStory = CSF3Primary.extend({ args: { children: 'Hello world 2' } });
render(<ExtendedStory.Component />);
const buttonElement = screen.getByText(/Hello world 2/i);
expect(buttonElement).not.toBeNull();
});
});

const testCases = Object.entries({
CSF2StoryWithLocale,
CSF3Button,
Expand Down
6 changes: 6 additions & 0 deletions code/renderers/react/src/csf-factories.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ test('csf factories', () => {
});

expect(MyStory.input.args?.label).toBe('Hello world');

expect(MyStory.Component).toBeDefined();

const ExtendedMyStory = MyStory.extend({ args: { label: 'Hello world 2' } });
expect(ExtendedMyStory.input.args?.label).toBe('Hello world 2');
expect(ExtendedMyStory.Component).toBeDefined();
});

describe('Args can be provided in multiple ways', () => {
Expand Down
4 changes: 4 additions & 0 deletions code/renderers/react/src/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,8 @@ interface ReactMeta<T extends ReactTypes, MetaInput extends ComponentAnnotations
export interface ReactStory<T extends ReactTypes, TInput extends StoryAnnotations<T, T['args']>>
extends Story<T, TInput> {
Component: ComponentType<Partial<T['args']>>;

extend<TNewInput extends StoryAnnotations<T, T['args']>>(
input: TNewInput
): ReactStory<T, TNewInput>;
}
Loading