-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Addon Docs: Skip !autodocs stories when computing primary story
#32712
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?
Changes from all commits
b80ec5b
e257102
de5ac0f
32407f9
1068768
293df88
796471b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| // @vitest-environment happy-dom | ||
| import { renderHook } from '@testing-library/react'; | ||
| import { describe, expect, it, vi } from 'vitest'; | ||
|
|
||
| import React from 'react'; | ||
| import type { FC, PropsWithChildren } from 'react'; | ||
|
|
||
| import type { PreparedStory } from 'storybook/internal/types'; | ||
|
|
||
| import type { DocsContextProps } from './DocsContext'; | ||
| import { DocsContext } from './DocsContext'; | ||
| import { usePrimaryStory } from './usePrimaryStory'; | ||
|
|
||
| const stories: Record<string, Partial<PreparedStory>> = { | ||
| story1: { name: 'Story One', tags: ['!autodocs'] }, | ||
| story2: { name: 'Story Two', tags: ['autodocs'] }, | ||
| story3: { name: 'Story Three', tags: ['autodocs'] }, | ||
| story4: { name: 'Story Four', tags: [] }, | ||
| }; | ||
|
|
||
| const createMockContext = (storyList: PreparedStory[]) => ({ | ||
| componentStories: vi.fn(() => storyList), | ||
| }); | ||
|
|
||
| const Wrapper: FC<PropsWithChildren<{ context: Partial<DocsContextProps> }>> = ({ | ||
| children, | ||
| context, | ||
| }) => <DocsContext.Provider value={context as DocsContextProps}>{children}</DocsContext.Provider>; | ||
|
|
||
| describe('usePrimaryStory', () => { | ||
| it('ignores !autodocs stories', () => { | ||
| const mockContext = createMockContext([ | ||
| stories.story1, | ||
| stories.story2, | ||
| stories.story3, | ||
| ] as PreparedStory[]); | ||
| const { result } = renderHook(() => usePrimaryStory(), { | ||
| wrapper: ({ children }) => <Wrapper context={mockContext}>{children}</Wrapper>, | ||
| }); | ||
| expect(result.current?.name).toBe('Story Two'); | ||
| }); | ||
|
|
||
| it('selects the first autodocs story', () => { | ||
| const mockContext = createMockContext([stories.story2, stories.story3] as PreparedStory[]); | ||
| const { result } = renderHook(() => usePrimaryStory(), { | ||
| wrapper: ({ children }) => <Wrapper context={mockContext}>{children}</Wrapper>, | ||
| }); | ||
| expect(result.current?.name).toBe('Story Two'); | ||
| }); | ||
|
|
||
| it('returns undefined if no story has "autodocs" tag', () => { | ||
| const mockContext = createMockContext([stories.story1, stories.story4] as PreparedStory[]); | ||
| const { result } = renderHook(() => usePrimaryStory(), { | ||
| wrapper: ({ children }) => <Wrapper context={mockContext}>{children}</Wrapper>, | ||
| }); | ||
| expect(result.current).toBeUndefined(); | ||
| }); | ||
|
|
||
| it('returns undefined for empty story list', () => { | ||
| const mockContext = createMockContext([]); | ||
| const { result } = renderHook(() => usePrimaryStory(), { | ||
| wrapper: ({ children }) => <Wrapper context={mockContext}>{children}</Wrapper>, | ||
| }); | ||
| expect(result.current).toBeUndefined(); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import { useContext } from 'react'; | ||
|
|
||
| import type { PreparedStory } from 'storybook/internal/types'; | ||
|
|
||
| import { DocsContext } from './DocsContext'; | ||
|
|
||
| /** | ||
| * A hook to get the primary story for the current component's doc page. It defines the primary | ||
| * story as the first story that includes the 'autodocs' tag | ||
| */ | ||
| export const usePrimaryStory = (): PreparedStory | undefined => { | ||
| const context = useContext(DocsContext); | ||
| const stories = context.componentStories(); | ||
| return stories.find((story) => story.tags.includes('autodocs')); | ||
| }; | ||
|
Comment on lines
+11
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major 🧩 Analysis chainLGTM! The hook logic correctly addresses the bug. The implementation correctly selects the first story with the 'autodocs' tag, which excludes stories marked with '!autodocs'. This should fix the issue where stories tagged with '!autodocs' were appearing as the primary preview when positioned first. Verify the fix resolves the reported issue by testing against the reproduction case: 🏁 Script executed: #!/bin/bash
# Description: Search for test files or stories that might cover the !autodocs tag behavior
# Look for existing tests related to autodocs tags
rg -n --type=ts --type=tsx -C3 '\!autodocs|autodocs.*tag'
# Find stories or test files that might need verification
fd -e story -e test.ts -e test.tsx | head -20Length of output: 1067 Add unit tests for '!autodocs' exclusion
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ia319 hooks usually have their own test file. You should be able to mock the DocsContext and build tests that show
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
Uh oh!
There was an error while loading. Please reload this page.