-
Notifications
You must be signed in to change notification settings - Fork 10
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
Upgrade Storybook to 8.x (next) #2373
base: main
Are you sure you want to change the base?
Changes from all commits
83cc551
d4991cf
f63d521
6d82915
91ed3aa
508d892
f111d08
e0a5132
c4fa248
6ad522e
93279fa
3f3d310
8875ff2
7060439
a136065
9d18c59
0393fdb
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,6 +1,3 @@ | ||
import {resolve, dirname, join} from "path"; | ||
import {mergeConfig} from "vite"; | ||
import turbosnap from "vite-plugin-turbosnap"; | ||
import type {StorybookConfig} from "@storybook/react-vite"; | ||
|
||
const config: StorybookConfig = { | ||
|
@@ -9,52 +6,17 @@ const config: StorybookConfig = { | |
"../__docs__/**/*.mdx", | ||
], | ||
addons: [ | ||
getAbsolutePath("@storybook/addon-essentials"), | ||
getAbsolutePath("@storybook/addon-a11y"), | ||
getAbsolutePath("@storybook/addon-designs"), | ||
getAbsolutePath("@storybook/addon-interactions"), | ||
getAbsolutePath("@storybook/addon-mdx-gfm"), | ||
getAbsolutePath("storybook-addon-pseudo-states"), | ||
"@storybook/addon-essentials", | ||
"@storybook/addon-a11y", | ||
"@storybook/addon-designs", | ||
"storybook-addon-pseudo-states", | ||
"@storybook/experimental-addon-test", | ||
], | ||
staticDirs: ["../static"], | ||
core: { | ||
disableTelemetry: true, | ||
}, | ||
framework: getAbsolutePath("@storybook/react-vite"), | ||
async viteFinal(config, {configType}) { | ||
// Merge custom configuration into the default config | ||
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. note: I'm moving this to a separate 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. y'all are switching to vitest? 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. I see, it's just for running storybook tests. 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. correct! I'm thinking that we should probably write an ADR if we want to adopt this more widely. Just curious.... I know this is a big change, but I wonder if you have any opinions about switching from Jest to vitest for unit tests? 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. Jest is definitely a more well-trodden path as it's been around for longer. But Vitest is a solid testing framework! I was able to do everything I needed with Vitest and Testing Library. It's supposedly faster and easier to configure than Jest, too. |
||
const mergedConfig = mergeConfig(config, { | ||
resolve: { | ||
// Allow us to detect changes from local wonder-blocks packages. | ||
alias: [ | ||
{ | ||
find: /^@khanacademy\/wonder-blocks(-.*)$/, | ||
replacement: resolve( | ||
__dirname, | ||
"../packages/wonder-blocks$1/src", | ||
), | ||
}, | ||
], | ||
}, | ||
}); | ||
|
||
// Add turbosnap to production builds so we can let Chromatic take | ||
// snapshots only to stories associated with the current PR. | ||
if (configType === "PRODUCTION") { | ||
config.plugins?.push( | ||
turbosnap({rootDir: config.root || process.cwd()}), | ||
); | ||
} | ||
|
||
Comment on lines
-43
to
-47
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. note: Dropping this as it is no longer needed as a separate package. SB 8 now includes it internally. |
||
return mergedConfig; | ||
}, | ||
docs: { | ||
autodocs: true, | ||
}, | ||
framework: "@storybook/react-vite", | ||
}; | ||
|
||
export default config; | ||
|
||
function getAbsolutePath(value: string): any { | ||
return dirname(require.resolve(join(value, "package.json"))); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
import * as React from "react"; | ||
import wonderBlocksTheme from "./wonder-blocks-theme"; | ||
|
||
import {Decorator} from "@storybook/react"; | ||
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. Totally out of the blue and unrelated to this PR, but it looks like you don't have https://github.com/Khan/perseus/blob/main/.eslintrc.js#L220..L236 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. Great point! I'll add this rule in a separate PR. I'll probably wait until WB is in a more "quiet" state to apply the changes :) |
||
import {color} from "@khanacademy/wonder-blocks-tokens"; | ||
import Link from "@khanacademy/wonder-blocks-link"; | ||
import {ThemeSwitcherContext} from "@khanacademy/wonder-blocks-theming"; | ||
|
@@ -95,32 +95,29 @@ const parameters = { | |
}, | ||
}; | ||
|
||
const decorators = [ | ||
(Story, context) => { | ||
const theme = context.globals.theme; | ||
const enableRenderStateRootDecorator = | ||
context.parameters.enableRenderStateRootDecorator; | ||
|
||
if (enableRenderStateRootDecorator) { | ||
return ( | ||
<RenderStateRoot> | ||
<ThemeSwitcherContext.Provider value={theme}> | ||
<Story /> | ||
</ThemeSwitcherContext.Provider> | ||
</RenderStateRoot> | ||
); | ||
} | ||
const withThemeSwitcher: Decorator = ( | ||
Story, | ||
{globals: {theme}, parameters: {enableRenderStateRootDecorator}}, | ||
) => { | ||
if (enableRenderStateRootDecorator) { | ||
return ( | ||
<ThemeSwitcherContext.Provider value={theme}> | ||
<Story /> | ||
</ThemeSwitcherContext.Provider> | ||
<RenderStateRoot> | ||
<ThemeSwitcherContext.Provider value={theme}> | ||
<Story /> | ||
</ThemeSwitcherContext.Provider> | ||
</RenderStateRoot> | ||
); | ||
}, | ||
]; | ||
} | ||
return ( | ||
<ThemeSwitcherContext.Provider value={theme}> | ||
<Story /> | ||
</ThemeSwitcherContext.Provider> | ||
); | ||
}; | ||
|
||
const preview: Preview = { | ||
parameters, | ||
decorators, | ||
decorators: [withThemeSwitcher], | ||
globalTypes: { | ||
// Allow the user to select a theme from the toolbar. | ||
theme: { | ||
|
@@ -147,6 +144,8 @@ const preview: Preview = { | |
}, | ||
}, | ||
}, | ||
|
||
tags: ["autodocs"], | ||
}; | ||
|
||
export default preview; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { beforeAll } from 'vitest'; | ||
import { setProjectAnnotations } from '@storybook/react'; | ||
import * as projectAnnotations from './preview'; | ||
|
||
// This is an important step to apply the right configuration when testing your stories. | ||
// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations | ||
const project = setProjectAnnotations([projectAnnotations]); | ||
|
||
beforeAll(project.beforeAll); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -332,7 +332,7 @@ export const ControlledMultilpleCombobox: Story = { | |
], | ||
|
||
play: async ({canvasElement}) => { | ||
const canvas = within(canvasElement); | ||
const canvas = within(canvasElement.ownerDocument.body); | ||
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. Interesting, this differs from the examples for these 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. Ahh yeah, this is useful for when we are using portals. I should add a comment here stating that. |
||
|
||
// Move to second option item | ||
await userEvent.keyboard("{ArrowDown}"); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,46 +82,50 @@ export const Default: StoryComponentType = { | |
* The `onChange` prop is optional in case the toggle will | ||
* be wrapped in a larger clickable component. | ||
*/ | ||
export const Controlled: StoryComponentType = () => { | ||
const [checkedOne, setCheckedOne] = React.useState(false); | ||
const [checkedTwo, setCheckedTwo] = React.useState(false); | ||
export const Controlled: StoryComponentType = { | ||
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. note: This component doesn't have any big changes, just moved the code around to support CSF3. |
||
render: function Render() { | ||
const [checkedOne, setCheckedOne] = React.useState(false); | ||
const [checkedTwo, setCheckedTwo] = React.useState(false); | ||
|
||
return ( | ||
<View style={styles.column}> | ||
<Switch checked={checkedOne} onChange={setCheckedOne} /> | ||
|
||
<Switch | ||
testId="test-switch" | ||
aria-label="test switch" | ||
checked={checkedTwo} | ||
onChange={setCheckedTwo} | ||
icon={<PhosphorIcon icon={magnifyingGlassIcon} />} | ||
/> | ||
</View> | ||
); | ||
}; | ||
|
||
Controlled.play = async ({canvasElement}) => { | ||
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. In previous versions of Storybook you had to manually navigate to each story and press "play" to run the tests, right? 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. Right! and that made it hard to determine when we introduced a regression with these interaction tests. I also added the CI step to ensure that we don't introduce issues in the future. NOTE: Storybook uses the test-runner for this, but it will be replaced by this new test addon. The previous runner used Jest + Playwright, and they wanted to switch to Vitest specially because they can run these tests in browsers as well as in headless mode. This is a new 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. More context here: https://storybook.js.org/blog/storybook-test-sneak-peek/ |
||
const canvas = within(canvasElement); | ||
return ( | ||
<View style={styles.column}> | ||
<Switch checked={checkedOne} onChange={setCheckedOne} /> | ||
<Switch | ||
testId="test-switch" | ||
aria-label="test switch" | ||
checked={checkedTwo} | ||
onChange={setCheckedTwo} | ||
icon={<PhosphorIcon icon={magnifyingGlassIcon} />} | ||
/> | ||
</View> | ||
); | ||
}, | ||
play: async ({canvasElement}) => { | ||
const canvas = within(canvasElement); | ||
|
||
const switchWithIcon = canvas.getByTestId("test-switch"); | ||
const switchInput = canvas.getByRole("switch", {name: "test switch"}); | ||
const switchWithIcon = canvas.getByTestId("test-switch"); | ||
const switchInput = canvas.getByRole("switch", {name: "test switch"}); | ||
|
||
await userEvent.tab(); | ||
await userEvent.tab(); | ||
await userEvent.tab(); | ||
await userEvent.tab(); | ||
|
||
expect(switchWithIcon).toHaveStyle( | ||
"background-color: rgba(33, 36, 44, 0.5)", | ||
); | ||
expect(switchWithIcon).toHaveStyle("outline: 2px solid rgb(24, 101, 242)"); | ||
expect(switchInput).toHaveProperty("checked", false); | ||
expect(switchWithIcon).toHaveStyle( | ||
"background-color: rgba(33, 36, 44, 0.5)", | ||
); | ||
expect(switchWithIcon).toHaveStyle( | ||
"outline: 2px solid rgb(24, 101, 242)", | ||
); | ||
expect(switchInput).toHaveProperty("checked", false); | ||
|
||
await userEvent.click(switchWithIcon); | ||
// Wait for animations to finish | ||
await new Promise((resolve) => setTimeout(resolve, 150)); | ||
await userEvent.click(switchWithIcon); | ||
// Wait for animations to finish | ||
await new Promise((resolve) => setTimeout(resolve, 150)); | ||
|
||
expect(switchInput).toHaveProperty("checked", true); | ||
expect(switchWithIcon).toHaveStyle("background-color: rgb(24, 101, 242)"); | ||
expect(switchInput).toHaveProperty("checked", true); | ||
expect(switchWithIcon).toHaveStyle( | ||
"background-color: rgb(24, 101, 242)", | ||
); | ||
}, | ||
}; | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -375,23 +375,6 @@ export const AutoUpdate: StoryComponentType = { | |
} | null>(null); | ||
return ( | ||
<View style={[styles.centered, styles.row, {position: "relative"}]}> | ||
<Tooltip | ||
content="This is a tooltip that auto-updates its position when the trigger element changes." | ||
opened={true} | ||
autoUpdate={true} | ||
> | ||
<View | ||
style={[ | ||
position && { | ||
position: "absolute", | ||
top: position.y, | ||
left: position.x, | ||
}, | ||
]} | ||
> | ||
Trigger element | ||
</View> | ||
</Tooltip> | ||
Comment on lines
-378
to
-394
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. Why was this removed? 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. It was moved to be included after the buttons. See my previous comment here: https://github.com/Khan/wonder-blocks/pull/2373/files#r1862635270 |
||
<Button | ||
onClick={() => { | ||
setPosition({ | ||
|
@@ -413,6 +396,23 @@ export const AutoUpdate: StoryComponentType = { | |
> | ||
Click to update trigger position (fixed) | ||
</Button> | ||
<Tooltip | ||
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. note: Moved this instance to the right so it can work more consistently in different environments (browser and JSDOM). The issue with the previous story was that the assertion in the This was causing that the Tooltip was not positioned horizontally, causing the test to fail in CI. With this change, we can now ensure that there will be a horizontal reposition. |
||
content="This is a tooltip that auto-updates its position when the trigger element changes." | ||
opened={true} | ||
autoUpdate={true} | ||
> | ||
<View | ||
style={[ | ||
position && { | ||
position: "absolute", | ||
top: position.y, | ||
left: position.x, | ||
}, | ||
]} | ||
> | ||
Trigger element | ||
</View> | ||
</Tooltip> | ||
</View> | ||
); | ||
}, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,7 @@ | |
"start:storybook": "storybook dev -p 6061", | ||
"test:common": "yarn run build && yarn run lint && yarn run typecheck && yarn run alex", | ||
"test:coverage": "yarn run test:common && yarn run jest --coverage", | ||
"test:storybook": "vitest --project=storybook", | ||
"test": "yarn run jest && yarn run test:common", | ||
"typecheck": "tsc", | ||
"typewatch": "tsc --noEmit --watch --incremental", | ||
|
@@ -52,17 +53,16 @@ | |
"@khanacademy/eslint-plugin": "^2.0.0", | ||
"@khanacademy/wonder-stuff-testing": "^3.0.1", | ||
"@rollup/plugin-node-resolve": "^15.0.2", | ||
"@storybook/addon-a11y": "^8.2.1", | ||
"@storybook/addon-actions": "^8.2.1", | ||
"@storybook/addon-designs": "^8.0.3", | ||
"@storybook/addon-docs": "^8.2.1", | ||
"@storybook/addon-essentials": "^8.2.1", | ||
"@storybook/addon-interactions": "^8.2.1", | ||
"@storybook/addon-mdx-gfm": "^8.2.1", | ||
"@storybook/preview-api": "^8.2.1", | ||
"@storybook/react": "^8.2.1", | ||
"@storybook/react-vite": "^8.2.1", | ||
"@storybook/test": "^8.2.1", | ||
"@storybook/addon-a11y": "^8.5.0-alpha.10", | ||
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.
Are you planning to wait till this is released before landing? 😁 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. hehe living on the edge! j/k I can totally wait until it is officially released :). I mainly wanted to start this PR to be able to unlock their upcoming Accessibility addon (that uses this new testing tooling), so @marcysutton can try it out and give us some feedback, and also give feedback to the Storybook team as well, which she's planning to do :). |
||
"@storybook/addon-actions": "^8.5.0-alpha.10", | ||
"@storybook/addon-designs": "^8.0.4", | ||
"@storybook/addon-docs": "^8.5.0-alpha.10", | ||
"@storybook/addon-essentials": "^8.5.0-alpha.10", | ||
"@storybook/experimental-addon-test": "^8.5.0-alpha.10", | ||
"@storybook/preview-api": "^8.5.0-alpha.10", | ||
"@storybook/react": "^8.5.0-alpha.10", | ||
"@storybook/react-vite": "^8.5.0-alpha.10", | ||
"@storybook/test": "^8.5.0-alpha.10", | ||
"@swc-node/register": "^1.6.5", | ||
"@swc/core": "^1.3.36", | ||
"@testing-library/jest-dom": "^6.5.0", | ||
|
@@ -80,6 +80,8 @@ | |
"@types/react-window": "^1.8.5", | ||
"@typescript-eslint/eslint-plugin": "^5.59.5", | ||
"@typescript-eslint/parser": "^5.59.5", | ||
"@vitejs/plugin-react": "^4.3.3", | ||
"@vitest/browser": "^2.1.5", | ||
"alex": "^11.0.0", | ||
"babel-jest": "^29.7.0", | ||
"babel-loader": "^8.2.3", | ||
|
@@ -109,17 +111,18 @@ | |
"jest-extended": "^4.0.2", | ||
"jscodeshift": "^0.15.1", | ||
"npm-package-json-lint": "^6.4.0", | ||
"playwright": "^1.49.0", | ||
"prettier": "^2.8.1", | ||
"react-refresh": "^0.14.0", | ||
"rollup": "^2.79.1", | ||
"rollup-plugin-babel": "^4.4.0", | ||
"rollup-plugin-node-externals": "^7.1.2", | ||
"storybook": "^8.2.1", | ||
"storybook": "^8.5.0-alpha.10", | ||
"storybook-addon-pseudo-states": "^3.1.1", | ||
"typescript": "^4.9.5", | ||
"typescript": "5.7.2", | ||
"typescript-coverage-report": "^0.7.0", | ||
"vite": "^4.4.8", | ||
"vite-plugin-turbosnap": "^1.0.2" | ||
"vitest": "^2.1.5" | ||
}, | ||
"dependencies": { | ||
"@babel/runtime": "^7.18.6", | ||
|
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.
Storybook upgrades always want to drop this back in. I finally searched when it's needed. Apparently in Yarn PnP situations module resolution can fail without this. Good to know we can remove this in Perseus too then.
https://storybook.js.org/docs/faq#how-do-i-fix-module-resolution-in-special-environments
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.
oh I see, thanks for the context.