diff --git a/.babelrc.js b/.babelrc.js index 8a5ab9a..91726ae 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -1,28 +1,28 @@ module.exports = { presets: [ [ - "@babel/preset-env", + '@babel/preset-env', { shippedProposals: true, - useBuiltIns: "usage", - corejs: "3", - targets: { node: "14" }, + useBuiltIns: 'usage', + corejs: '3', + targets: { node: '14' }, }, ], - "@babel/preset-typescript", - "@babel/preset-react", + '@babel/preset-typescript', + '@babel/preset-react', ], env: { esm: { presets: [ [ - "@babel/preset-env", + '@babel/preset-env', { shippedProposals: true, - useBuiltIns: "usage", - corejs: "3", + useBuiltIns: 'usage', + corejs: '3', modules: false, - targets: { chrome: "100" }, + targets: { chrome: '100' }, }, ], ], diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 94a973c..85acea9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,10 +8,10 @@ jobs: if: "!contains(github.event.head_commit.message, 'ci skip') && !contains(github.event.head_commit.message, 'skip ci')" steps: - uses: actions/checkout@v3 - + - name: Enable Corepack run: corepack enable - + - name: Prepare repository run: git fetch --unshallow --tags @@ -26,4 +26,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - yarn release \ No newline at end of file + yarn release diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 73a363b..ff610c6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,16 +7,18 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - + - name: Enable Corepack run: corepack enable - name: Setup Node.js uses: actions/setup-node@v4 + - name: Install dependencies + run: yarn install + - name: Build coverage addon - run: | - yarn install + run: | yarn build - name: Run tests in webpack example @@ -25,6 +27,8 @@ jobs: npx playwright install --with-deps yarn test-storybook:ci-coverage working-directory: examples/webpack5 + env: + YARN_ENABLE_IMMUTABLE_INSTALLS: false - name: Run tests in vite example run: | @@ -32,4 +36,5 @@ jobs: npx playwright install --with-deps yarn test-storybook:ci-coverage working-directory: examples/vite - + env: + YARN_ENABLE_IMMUTABLE_INSTALLS: false diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 1521c8b..0000000 --- a/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -dist diff --git a/.prettierrc b/.prettierrc index 0967ef4..c523e2f 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1 +1,6 @@ -{} +{ + "singleQuote": true, + "trailingComma": "es5", + "printWidth": 120, + "tabWidth": 2 +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..25fa621 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/README.md b/README.md index 8ff8cb6..548cf34 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,21 @@ Tools to support code coverage in Storybook and the [Storybook test runner](https://github.com/storybookjs/test-runner). It supports Storybook projects that use **Webpack5** or **Vite**. +> [!WARNING] +> If you're using Storybook in a Vite-based project, you might want to use [Storybook's Vitest integration](https://storybook.js.org/docs/writing-tests/integrations/vitest-addon?ref=test-runner-migration) instead. It's faster, provides code coverage out of the box (so you don't need this addon anymore), and integrates well with all Storybook's latest features. + +## Requirements + +- Storybook@>=10.0.0 + +### Version compatibility + +| Addon coverage version | Storybook version | +| ---------------------- | ----------------- | +| ^3.0.0 | ^10.0.0 | +| ^2.0.0 | ^9.0.0 | +| ^2.0.0 | ^8.0.0 | + ### Installation Install this addon by adding the `@storybook/addon-coverage` dependency: @@ -14,7 +29,7 @@ And by registering it in your `.storybook/main.js`: ```js export default { - addons: ["@storybook/addon-coverage"], + addons: ['@storybook/addon-coverage'], }; ``` @@ -26,10 +41,10 @@ This addon instruments your code by using a custom wrapper around [istanbul-lib- export default { addons: [ { - name: "@storybook/addon-coverage", + name: '@storybook/addon-coverage', options: { istanbul: { - include: ["**/stories/**"], + include: ['**/stories/**'], }, }, }, @@ -59,7 +74,7 @@ export default { > If you're using TypeScript, you can import the type for the options like so: > > ```ts -> import type { AddonOptionsWebpack } from "@storybook/addon-coverage"; +> import type { AddonOptionsWebpack } from '@storybook/addon-coverage'; > ``` **The available options if your project uses Vite are as follows:** @@ -80,10 +95,9 @@ export default { > If you're using TypeScript, you can import the type for the options like so: > > ```ts -> import type { AddonOptionsVite } from "@storybook/addon-coverage"; +> import type { AddonOptionsVite } from '@storybook/addon-coverage'; > ``` - ## Troubleshooting ### The coverage addon doesn't support optimized builds @@ -99,13 +113,10 @@ export default { // Your Storybook configuration goes here build: { test: { - disabledAddons: [ - '@storybook/addon-docs', - '@storybook/addon-essentials/docs', - ], + disabledAddons: ['@storybook/addon-docs', '@storybook/addon-essentials/docs'], }, }, -} +}; ``` ### Development scripts diff --git a/examples/vite/.storybook/main.ts b/examples/vite/.storybook/main.ts index 567faf0..2691d02 100644 --- a/examples/vite/.storybook/main.ts +++ b/examples/vite/.storybook/main.ts @@ -1,14 +1,10 @@ export default { - stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"], + stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'], - addons: [ - "@storybook/addon-essentials", - "@storybook/addon-interactions", - "@storybook/addon-coverage", - ], + addons: ['@storybook/addon-coverage'], framework: { - name: "@storybook/react-vite", + name: '@storybook/react-vite', options: {}, }, }; diff --git a/examples/vite/.storybook/preview.ts b/examples/vite/.storybook/preview.ts index 1f07351..4481fcf 100644 --- a/examples/vite/.storybook/preview.ts +++ b/examples/vite/.storybook/preview.ts @@ -1,7 +1,9 @@ -export const decorators = [(StoryFn) => { - console.log(globalThis.__coverage__) - return StoryFn() -}] +export const decorators = [ + (StoryFn) => { + console.log(globalThis.__coverage__); + return StoryFn(); + }, +]; export const parameters = { controls: { @@ -10,4 +12,4 @@ export const parameters = { date: /Date$/, }, }, -} \ No newline at end of file +}; diff --git a/examples/vite/index.html b/examples/vite/index.html index e0d1c84..e4b78ea 100644 --- a/examples/vite/index.html +++ b/examples/vite/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/vite/package.json b/examples/vite/package.json index ebf4cbf..2dae330 100644 --- a/examples/vite/package.json +++ b/examples/vite/package.json @@ -1,14 +1,14 @@ { "name": "vite", - "private": true, "version": "0.0.0", + "private": true, "type": "module", "scripts": { - "dev": "vite", "build": "tsc && vite build", + "build-storybook": "storybook build", + "dev": "vite", "preview": "vite preview", - "storybook": "npx storybook dev -p 6006", - "build-storybook": "npx storybook build", + "storybook": "storybook dev -p 6006", "test-storybook": "test-storybook --coverage", "test-storybook:ci-coverage": "concurrently -k -s first -n \"SB,TEST\" -c \"magenta,blue\" \"yarn build-storybook --quiet && npx serve storybook-static -l 6006\" \"wait-on tcp:6006 && yarn test-storybook --coverage\"" }, @@ -18,20 +18,17 @@ }, "devDependencies": { "@storybook/addon-coverage": "portal:../..", - "@storybook/addon-essentials": "^8.4.7", - "@storybook/addon-interactions": "^8.4.7", - "@storybook/react": "^8.4.7", - "@storybook/react-vite": "^8.4.7", - "@storybook/test": "^8.4.7", - "@storybook/test-runner": "^0.21.0", + "@storybook/react": "^10.0.0", + "@storybook/react-vite": "^10.0.0", + "@storybook/test-runner": "^0.24.1", "@types/react": "^18.0.17", "@types/react-dom": "^18.0.6", - "@vitejs/plugin-react": "^3.1.0", - "concurrently": "^9.1.0", - "storybook": "^8.4.7", - "typescript": "^4.6.4", - "vite": "^4.2.1", - "wait-on": "^8.0.1" + "@vitejs/plugin-react": "^5.1.0", + "concurrently": "^9.2.1", + "storybook": "^10.0.0", + "typescript": "^5.9.3", + "vite": "^7.2.2", + "wait-on": "^9.0.3" }, "packageManager": "yarn@4.5.3" } diff --git a/examples/vite/src/App.tsx b/examples/vite/src/App.tsx index cd20136..f1f87e6 100644 --- a/examples/vite/src/App.tsx +++ b/examples/vite/src/App.tsx @@ -1,9 +1,9 @@ -import { useState } from 'react' -import reactLogo from './assets/react.svg' -import './App.css' +import { useState } from 'react'; +import reactLogo from './assets/react.svg'; +import './App.css'; function App() { - const [count, setCount] = useState(0) + const [count, setCount] = useState(0); return (
@@ -17,18 +17,14 @@ function App() {

Vite + React

- +

Edit src/App.tsx and save to test HMR

-

- Click on the Vite and React logos to learn more -

+

Click on the Vite and React logos to learn more

- ) + ); } -export default App +export default App; diff --git a/examples/vite/src/main.tsx b/examples/vite/src/main.tsx index 611e848..a2bf01b 100644 --- a/examples/vite/src/main.tsx +++ b/examples/vite/src/main.tsx @@ -1,10 +1,10 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App' -import './index.css' +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; +import './index.css'; ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( -) +); diff --git a/examples/vite/src/stories/Button.stories.tsx b/examples/vite/src/stories/Button.stories.tsx index e0f7cc8..39337e6 100644 --- a/examples/vite/src/stories/Button.stories.tsx +++ b/examples/vite/src/stories/Button.stories.tsx @@ -1,15 +1,15 @@ -import type { StoryFn, Meta } from "@storybook/react"; +import type { StoryFn, Meta } from '@storybook/react'; -import { Button } from "./Button"; -import { expect } from "@storybook/test"; +import { Button } from './Button'; +import { expect } from 'storybook/test'; // More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export export default { - title: "Example/Button", + title: 'Example/Button', component: Button, // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: { - backgroundColor: { control: "color" }, + backgroundColor: { control: 'color' }, }, } as Meta; @@ -20,28 +20,26 @@ export const Primary = Template.bind({}); // More on args: https://storybook.js.org/docs/react/writing-stories/args Primary.args = { primary: true, - label: "Button", + label: 'Button', }; Primary.play = async () => { const coverage = (globalThis as any).__coverage__; - await expect( - Object.keys(coverage).find((cvg) => cvg.endsWith("Button.tsx")) - ).toBeTruthy(); + await expect(Object.keys(coverage).find((cvg) => cvg.endsWith('Button.tsx'))).toBeTruthy(); }; export const Secondary = Template.bind({}); Secondary.args = { - label: "Button", + label: 'Button', }; export const Large = Template.bind({}); Large.args = { - size: "large", - label: "Button", + size: 'large', + label: 'Button', }; export const Small = Template.bind({}); Small.args = { - size: "small", - label: "Button", + size: 'small', + label: 'Button', }; diff --git a/examples/vite/src/stories/Button.tsx b/examples/vite/src/stories/Button.tsx index c33be6e..66f8fd3 100644 --- a/examples/vite/src/stories/Button.tsx +++ b/examples/vite/src/stories/Button.tsx @@ -27,13 +27,7 @@ interface ButtonProps { /** * Primary UI component for user interaction */ -export const Button = ({ - primary = false, - size = 'medium', - backgroundColor, - label, - ...props -}: ButtonProps) => { +export const Button = ({ primary = false, size = 'medium', backgroundColor, label, ...props }: ButtonProps) => { const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary'; return (