-
-
Notifications
You must be signed in to change notification settings - Fork 9.9k
Addon Vitest: Add experimental vitest integration #28768
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
Changes from 10 commits
6e24da4
dd5e342
5a60cf5
61a0223
04bd79a
ed560db
257f53d
1964c2d
67a6a60
8b309e4
eec554a
834647d
8623b92
d01d653
ac1a81d
f7f076c
ad09c0e
1cb605f
c5b2538
7a7944a
9b35a31
84f5b63
abe32f6
80b5481
b644b1f
3c6860b
c3ede6b
fb78fc5
fc6202e
39f688d
b82c13a
ac23ae6
fe5a978
edef177
1052856
f3433c6
bd1d751
ecf1c85
8caca19
503de44
8f2c88d
afd11a8
ca74d8a
81b6775
d2965c9
b672f53
5631f17
aa18abb
c6ebc2c
d57f328
c4dbf12
a076ef1
ab76bac
0841ad2
2996b7f
64a9fa3
8b59671
d06ab28
07babfe
2241c54
87c6223
c62e41d
e30bfcc
6289999
21112bc
31183db
257a945
df69ef5
89e4a1f
c98e196
81c6a13
072a951
76391dd
89f3a13
f90d77c
feccff5
e532994
3f96682
4300175
ef94fa3
0760555
8fde44d
43c0733
8f39a19
92deb47
6556d03
52aa6fd
385879e
7919ead
f7de2e2
c748186
632d0e4
58dde10
dee15b2
6fd386b
02d0789
17ba6e6
f66506e
a3652bb
b1e4f7c
1368aef
3e33d2e
1b89fe1
e9db42a
5f4ded2
0007c42
d62a856
433bbb5
12e0350
f4bf860
2e4b199
2ffd0d0
a5ff402
24e8a73
e4320b1
633f4b2
6d4caba
9b4d61c
d5995e3
42d630e
1c2888d
81281ec
e8364db
722e0d5
9dc93cc
2a83669
9728c77
72164de
f31323d
40dfa9f
bffb920
ee56cca
53232db
b617eb0
14e18d9
4d0744f
4c27387
d1cb751
1bf3c4c
527e8ea
49e7932
f747943
603ea16
898405e
be894e9
7798169
f82153b
e3f73c9
adc1cbb
8aa5680
6c6268c
c067329
b40b33e
d3dae46
b860bb5
e8805dd
7ebafe1
89b39a8
0f15aa1
567f11f
3930877
c00a80f
8d0a92a
934cefb
c066b8b
3861ac4
f2a90a9
af8c014
d2bc5fb
1dbf820
e2d63c5
f508cc4
8c580c7
a687a68
4af500e
4759c6a
f5f4f5a
4969596
8693eaf
da053e1
4bf0445
eb83b88
cb99e97
251d916
ba806c1
38a154e
b48ac41
a6df95a
1df2ab1
13c5361
45090b2
020b6c6
67f5678
fc07618
f773687
fddd3a5
c12e23e
6cade7d
659994d
5f24e86
bd51a23
1896a8c
f7ff019
416cd00
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 |
|---|---|---|
| @@ -1,5 +1,7 @@ | ||
| <h1>Migration</h1> | ||
|
|
||
| - [From version 8.2.x to 8.3.x](#from-version-82x-to-83x) | ||
| - [Removed `experimental_SIDEBAR_BOTTOM` and deprecated `experimental_SIDEBAR_TOP` addon types](#removed-experimental_sidebar_bottom-and-deprecated-experimental_sidebar_top-addon-types) | ||
| - [From version 8.1.x to 8.2.x](#from-version-81x-to-82x) | ||
| - [Failed to resolve import "@storybook/X" error](#failed-to-resolve-import-storybookx-error) | ||
| - [Preview.js globals renamed to initialGlobals](#previewjs-globals-renamed-to-initialglobals) | ||
|
|
@@ -414,6 +416,14 @@ | |
| - [Packages renaming](#packages-renaming) | ||
| - [Deprecated embedded addons](#deprecated-embedded-addons) | ||
|
|
||
| ## From version 8.2.x to 8.3.x | ||
|
|
||
| ### Removed `experimental_SIDEBAR_BOTTOM` and deprecated `experimental_SIDEBAR_TOP` addon types | ||
|
|
||
| The experimental SIDEBAR_BOTTOM addon type was removed in favor of a built-in filter UI. The enum type definition will remain available until Storybook 9.0 but will be ignored. Similarly the experimental SIDEBAR_TOP addon type is deprecated and will be removed in a future version. | ||
|
|
||
| These APIs allowed addons to render arbitrary content in the Storybook sidebar. Due to potential conflicts between addons and challenges regarding styling, these APIs are/will be removed. In the future, Storybook will provide declarative API hooks to allow addons to add content to the sidebar without risk of conflicts or UI inconsistencies. One such API is `experimental_updateStatus` which allow addons to set a status for stories. The SIDEBAR_BOTTOM slot is now used to allow filtering stories with a given status. | ||
|
Comment on lines
+423
to
+427
Contributor
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. check: Consider providing examples or more detailed guidance on how to migrate from the deprecated |
||
|
|
||
| ## From version 8.1.x to 8.2.x | ||
|
|
||
| ### Failed to resolve import "@storybook/X" error | ||
|
|
@@ -2324,8 +2334,8 @@ export default config; | |
|
|
||
| #### Vite builder uses Vite config automatically | ||
|
|
||
| When using a [Vite-based framework](#framework-field-mandatory), Storybook will automatically use your `vite.config.(ctm)js` config file starting in 7.0. | ||
| Some settings will be overridden by Storybook so that it can function properly, and the merged settings can be modified using `viteFinal` in `.storybook/main.js` (see the [Storybook Vite configuration docs](https://storybook.js.org/docs/react/builders/vite#configuration)). | ||
| When using a [Vite-based framework](#framework-field-mandatory), Storybook will automatically use your `vite.config.(ctm)js` config file starting in 7.0. | ||
| Some settings will be overridden by Storybook so that it can function properly, and the merged settings can be modified using `viteFinal` in `.storybook/main.js` (see the [Storybook Vite configuration docs](https://storybook.js.org/docs/react/builders/vite#configuration)). | ||
| If you were using `viteFinal` in 6.5 to simply merge in your project's standard Vite config, you can now remove it. | ||
|
|
||
| For Svelte projects this means that the `svelteOptions` property in the `main.js` config should be omitted, as it will be loaded automatically via the project's `vite.config.js`. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,6 +47,8 @@ enum events { | |
| STORY_ARGS_UPDATED = 'storyArgsUpdated', | ||
| // Reset either a single arg of a story all args of a story | ||
| RESET_STORY_ARGS = 'resetStoryArgs', | ||
| // Emitted after a filter is set | ||
| SET_FILTER = 'setFilter', | ||
|
Comment on lines
+50
to
+51
Contributor
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. style: Ensure that the |
||
| // Emitted by the preview at startup once it knows the initial set of globals+globalTypes | ||
| SET_GLOBALS = 'setGlobals', | ||
| // Tell the preview to update the value of a global | ||
|
|
@@ -114,6 +116,7 @@ export const { | |
| SELECT_STORY, | ||
| SET_CONFIG, | ||
| SET_CURRENT_STORY, | ||
| SET_FILTER, | ||
| SET_GLOBALS, | ||
| SET_INDEX, | ||
| SET_STORIES, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,6 +41,7 @@ import { | |
| DOCS_PREPARED, | ||
| SET_CURRENT_STORY, | ||
| SET_CONFIG, | ||
| SET_FILTER, | ||
|
||
| } from '@storybook/core/core-events'; | ||
| import { logger } from '@storybook/core/client-logger'; | ||
|
|
||
|
|
@@ -662,6 +663,8 @@ export const init: ModuleFn<SubAPI, SubState> = ({ | |
| Object.entries(refs).forEach(([refId, { internal_index, ...ref }]) => { | ||
|
Contributor
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. logic: Verify that emitting the |
||
| fullAPI.setRef(refId, { ...ref, storyIndex: internal_index }, true); | ||
| }); | ||
|
|
||
| provider.channel?.emit(SET_FILTER, { id }); | ||
| }, | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import { fn } from '@storybook/test'; | ||
|
Contributor
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. style: Consider using a more descriptive name for the imported |
||
| import { FilterToggle } from './FilterToggle'; | ||
|
|
||
| export default { | ||
| component: FilterToggle, | ||
| args: { | ||
| active: false, | ||
| onClick: fn(), | ||
|
Contributor
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. check: Ensure that the |
||
| }, | ||
| }; | ||
|
|
||
| export const Errors = { | ||
| args: { | ||
| count: 2, | ||
| label: 'Error', | ||
| status: 'critical', | ||
| }, | ||
| }; | ||
|
|
||
| export const ErrorsActive = { | ||
| args: { | ||
| ...Errors.args, | ||
|
Contributor
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. style: Verify that spreading |
||
| active: true, | ||
| }, | ||
| }; | ||
|
|
||
| export const Warning = { | ||
| args: { | ||
| count: 12, | ||
| label: 'Warning', | ||
| status: 'warning', | ||
| }, | ||
| }; | ||
|
|
||
| export const WarningActive = { | ||
| args: { | ||
| ...Warning.args, | ||
|
Contributor
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. style: Similar to |
||
| active: true, | ||
| }, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| import { Badge as BaseBadge, IconButton } from '@storybook/components'; | ||
| import { css, styled } from '@storybook/theming'; | ||
| import React, { type ComponentProps } from 'react'; | ||
|
||
|
|
||
| const Badge = styled(BaseBadge)(({ theme }) => ({ | ||
| padding: '4px 8px', | ||
| fontSize: theme.typography.size.s1, | ||
| })); | ||
|
|
||
| const Button = styled(IconButton)( | ||
|
Contributor
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. logic: The nested hover styles could be simplified by using a single hover selector with conditional logic for different statuses. |
||
| ({ theme }) => ({ | ||
| fontSize: theme.typography.size.s2, | ||
| '&:hover [data-badge][data-status=warning], [data-badge=true][data-status=warning]': { | ||
| background: '#E3F3FF', | ||
| borderColor: 'rgba(2, 113, 182, 0.1)', | ||
| color: '#0271B6', | ||
| }, | ||
| '&:hover [data-badge][data-status=critical], [data-badge=true][data-status=critical]': { | ||
| background: theme.background.negative, | ||
| boxShadow: `inset 0 0 0 1px rgba(182, 2, 2, 0.1)`, | ||
| color: theme.color.negativeText, | ||
| }, | ||
| }), | ||
| ({ active, theme }) => | ||
| !active && | ||
| css({ | ||
| '&:hover': { | ||
| color: theme.base === 'light' ? theme.color.defaultText : theme.color.light, | ||
| }, | ||
| }) | ||
| ); | ||
|
|
||
| const Label = styled.span(({ theme }) => ({ | ||
| color: theme.base === 'light' ? theme.color.defaultText : theme.color.light, | ||
| })); | ||
|
|
||
| interface FilterToggleProps { | ||
| active: boolean; | ||
| count: number; | ||
| label: string; | ||
| status: ComponentProps<typeof Badge>['status']; | ||
| } | ||
|
|
||
| export const FilterToggle = ({ | ||
|
Contributor
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. check: Ensure that the |
||
| active, | ||
| count, | ||
| label, | ||
| status, | ||
| ...props | ||
| }: FilterToggleProps & Omit<ComponentProps<typeof Button>, 'status'>) => { | ||
| return ( | ||
| <Button active={active} {...props}> | ||
| <Badge status={status} data-badge={active} data-status={status}> | ||
| {count} | ||
| </Badge> | ||
| <Label>{`${label}${count === 1 ? '' : 's'}`}</Label> | ||
| </Button> | ||
| ); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,7 @@ import type { IndexHash, State } from '@storybook/core/manager-api'; | |
| import { ManagerContext, types } from '@storybook/core/manager-api'; | ||
| import type { StoryObj, Meta } from '@storybook/react'; | ||
| import { within, userEvent, expect, fn } from '@storybook/test'; | ||
| import type { Addon_SidebarTopType } from '@storybook/core/types'; | ||
| import type { Addon_SidebarTopType, API_StatusState } from '@storybook/core/types'; | ||
| import { Button, IconButton } from '@storybook/core/components'; | ||
| import { FaceHappyIcon } from '@storybook/icons'; | ||
| import { Sidebar, DEFAULT_REF_ID } from './Sidebar'; | ||
|
|
@@ -26,6 +26,26 @@ const storyId = 'root-1-child-a2--grandchild-a1-1'; | |
| export const simpleData = { menu, index, storyId }; | ||
| export const loadingData = { menu }; | ||
|
|
||
| const managerContext: any = { | ||
|
Contributor
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. logic: Centralizing the manager context state and API mock functions is a good practice for maintainability. |
||
| state: { | ||
| docsOptions: { | ||
| defaultName: 'Docs', | ||
| autodocs: 'tag', | ||
| docsMode: false, | ||
| }, | ||
| }, | ||
| api: { | ||
| emit: fn().mockName('api::emit'), | ||
| on: fn().mockName('api::on'), | ||
| off: fn().mockName('api::off'), | ||
| getShortcutKeys: fn(() => ({ search: ['control', 'shift', 's'] })).mockName( | ||
| 'api::getShortcutKeys' | ||
| ), | ||
| selectStory: fn().mockName('api::selectStory'), | ||
| experimental_setFilter: fn().mockName('api::experimental_setFilter'), | ||
| }, | ||
| }; | ||
|
|
||
| const meta = { | ||
| component: Sidebar, | ||
| title: 'Sidebar/Sidebar', | ||
|
|
@@ -44,28 +64,7 @@ const meta = { | |
| }, | ||
| decorators: [ | ||
| (storyFn) => ( | ||
| <ManagerContext.Provider | ||
| value={ | ||
| { | ||
| state: { | ||
| docsOptions: { | ||
| defaultName: 'Docs', | ||
| autodocs: 'tag', | ||
| docsMode: false, | ||
| }, | ||
| }, | ||
| api: { | ||
| emit: fn().mockName('api::emit'), | ||
| on: fn().mockName('api::on'), | ||
| off: fn().mockName('api::off'), | ||
| getShortcutKeys: fn(() => ({ search: ['control', 'shift', 's'] })).mockName( | ||
| 'api::getShortcutKeys' | ||
| ), | ||
| selectStory: fn().mockName('api::selectStory'), | ||
| }, | ||
| } as any | ||
| } | ||
| > | ||
| <ManagerContext.Provider value={managerContext}> | ||
| <LayoutProvider> | ||
| <IconSymbols /> | ||
| {storyFn()} | ||
|
|
@@ -218,41 +217,29 @@ export const Searching: Story = { | |
| }; | ||
|
|
||
| export const Bottom: Story = { | ||
| args: { | ||
| bottom: [ | ||
| { | ||
| id: '1', | ||
| type: types.experimental_SIDEBAR_BOTTOM, | ||
| render: () => ( | ||
| <Button> | ||
| <FaceHappyIcon /> | ||
| Custom addon A | ||
| </Button> | ||
| ), | ||
| }, | ||
| { | ||
| id: '2', | ||
| type: types.experimental_SIDEBAR_BOTTOM, | ||
| render: () => ( | ||
| <Button> | ||
| {' '} | ||
| <FaceHappyIcon /> | ||
| Custom addon B | ||
| </Button> | ||
| ), | ||
| }, | ||
| { | ||
| id: '3', | ||
| type: types.experimental_SIDEBAR_BOTTOM, | ||
| render: () => ( | ||
| <IconButton> | ||
| {' '} | ||
| <FaceHappyIcon /> | ||
| </IconButton> | ||
| ), | ||
| }, | ||
| ], | ||
| }, | ||
| decorators: [ | ||
|
Contributor
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. check: Ensure the status states in the |
||
| (storyFn) => ( | ||
| <ManagerContext.Provider | ||
| value={{ | ||
| ...managerContext, | ||
| state: { | ||
| ...managerContext.state, | ||
| status: { | ||
| [storyId]: { | ||
| vitest: { status: 'warn', title: '', description: '' }, | ||
| vta: { status: 'error', title: '', description: '' }, | ||
| }, | ||
| 'root-1-child-a2--grandchild-a1-2': { | ||
| vitest: { status: 'warn', title: '', description: '' }, | ||
| }, | ||
| } satisfies API_StatusState, | ||
| }, | ||
| }} | ||
| > | ||
| {storyFn()} | ||
| </ManagerContext.Provider> | ||
| ), | ||
| ], | ||
| }; | ||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,7 @@ import { SearchResults } from './SearchResults'; | |
| import type { CombinedDataset, Selection } from './types'; | ||
| import { useLastViewed } from './useLastViewed'; | ||
| import { MEDIA_DESKTOP_BREAKPOINT } from '../../constants'; | ||
| import { SidebarBottom } from './SidebarBottom'; | ||
|
||
|
|
||
| export const DEFAULT_REF_ID = 'storybook_internal'; | ||
|
|
||
|
|
@@ -109,7 +110,6 @@ export interface SidebarProps extends API_LoadedRefData { | |
| status: State['status']; | ||
| menu: any[]; | ||
| extra: Addon_SidebarTopType[]; | ||
| bottom?: Addon_SidebarBottomType[]; | ||
| storyId?: string; | ||
| refId?: string; | ||
| menuHighlighted?: boolean; | ||
|
|
@@ -128,7 +128,6 @@ export const Sidebar = React.memo(function Sidebar({ | |
| previewInitialized, | ||
| menu, | ||
| extra, | ||
| bottom = [], | ||
| menuHighlighted = false, | ||
| enableShortcuts = true, | ||
| refs = {}, | ||
|
|
@@ -194,9 +193,7 @@ export const Sidebar = React.memo(function Sidebar({ | |
| </ScrollArea> | ||
| {isLoading ? null : ( | ||
| <Bottom className="sb-bar"> | ||
| {bottom.map(({ id, render: Render }) => ( | ||
| <Render key={id} /> | ||
| ))} | ||
| <SidebarBottom /> | ||
| </Bottom> | ||
|
Comment on lines
189
to
191
Contributor
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. style: Directly using SidebarBottom here assumes it covers all use cases previously handled by the bottom array. |
||
| )} | ||
| </Container> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import { fn } from '@storybook/test'; | ||
|
Contributor
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. style: Consider using a more descriptive name for the imported |
||
|
|
||
| import { SidebarBottomBase } from './SidebarBottom'; | ||
|
|
||
| export default { | ||
| component: SidebarBottomBase, | ||
| args: { | ||
| api: { | ||
| experimental_setFilter: fn(), | ||
| emit: fn(), | ||
| }, | ||
|
Comment on lines
+8
to
+11
Contributor
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. check: Ensure that the mocked |
||
| }, | ||
| }; | ||
|
|
||
| export const Errors = { | ||
| args: { | ||
| status: { | ||
| one: { 'sidebar-bottom-filter': { status: 'error' } }, | ||
| two: { 'sidebar-bottom-filter': { status: 'error' } }, | ||
|
Comment on lines
+17
to
+19
Contributor
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. check: Verify that the status keys ( |
||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| export const Warnings = { | ||
| args: { | ||
| status: { | ||
| one: { 'sidebar-bottom-filter': { status: 'warn' } }, | ||
| two: { 'sidebar-bottom-filter': { status: 'warn' } }, | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| export const Both = { | ||
| args: { | ||
| status: { | ||
| one: { 'sidebar-bottom-filter': { status: 'warn' } }, | ||
| two: { 'sidebar-bottom-filter': { status: 'warn' } }, | ||
| three: { 'sidebar-bottom-filter': { status: 'error' } }, | ||
| four: { 'sidebar-bottom-filter': { status: 'error' } }, | ||
|
Comment on lines
+35
to
+39
Contributor
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. style: Consider adding more diverse status scenarios to thoroughly test the component's behavior under different conditions. |
||
| }, | ||
| }, | ||
| }; | ||
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.
check: Ensure that the new section for version 8.2.x to 8.3.x is correctly linked in the table of contents.