diff --git a/site/.storybook/main.ts b/site/.storybook/main.ts index 78ceb1d99b..b55302ae61 100644 --- a/site/.storybook/main.ts +++ b/site/.storybook/main.ts @@ -8,6 +8,7 @@ export default { "@storybook/addon-links", "@storybook/addon-themes", "storybook-addon-remix-react-router", + "@storybook/addon-vitest", ], staticDirs: ["../static"], diff --git a/site/.storybook/vitest.setup.ts b/site/.storybook/vitest.setup.ts new file mode 100644 index 0000000000..b2d3a795c3 --- /dev/null +++ b/site/.storybook/vitest.setup.ts @@ -0,0 +1,7 @@ +import { setProjectAnnotations } from "@storybook/react-vite"; +import { beforeAll } from "vitest"; +import * as previewAnnotations from "./preview"; + +const annotations = setProjectAnnotations([previewAnnotations]); + +beforeAll(annotations.beforeAll); diff --git a/site/AGENTS.md b/site/AGENTS.md index 31790fb136..0a355160d7 100644 --- a/site/AGENTS.md +++ b/site/AGENTS.md @@ -16,7 +16,9 @@ When investigating or editing TypeScript/React code, always use the TypeScript l ## Bash commands - `pnpm dev` - Start Vite development server -- `pnpm storybook --no-open` - Run storybook tests +- `pnpm storybook --no-open` - Start Storybook dev server +- `pnpm test:storybook` - Run storybook story tests (play functions) via Vitest + Playwright +- `pnpm test:storybook src/path/to/component.stories.tsx` - Run a single story file - `pnpm test` - Run jest unit tests - `pnpm test -- path/to/specific.test.ts` - Run a single test file - `pnpm lint` - Run complete linting suite (Biome + TypeScript + circular deps + knip) diff --git a/site/package.json b/site/package.json index 8f1f6742ec..392ecdf1f9 100644 --- a/site/package.json +++ b/site/package.json @@ -27,9 +27,10 @@ "storybook": "STORYBOOK=true storybook dev -p 6006", "storybook:build": "storybook build", "storybook:ci": "storybook build --test", - "test": "vitest run && jest", - "test:ci": "vitest run && jest --silent", - "test:watch": "vitest", + "test": "vitest run --project=unit && jest", + "test:storybook": "vitest --project=storybook", + "test:ci": "vitest run --project=unit && jest --silent", + "test:watch": "vitest --project=unit", "test:watch-jest": "jest --watch", "stats": "STATS=true pnpm build && npx http-server ./stats -p 8081 -c-1", "update-emojis": "cp -rf ./node_modules/emoji-datasource-apple/img/apple/64/* ./static/emojis && cp -f ./node_modules/emoji-datasource-apple/img/apple/sheets-256/64.png ./static/emojis/spritesheet.png" @@ -139,6 +140,7 @@ "@storybook/addon-docs": "10.2.10", "@storybook/addon-links": "10.2.10", "@storybook/addon-themes": "10.2.10", + "@storybook/addon-vitest": "10.2.10", "@storybook/react-vite": "10.2.10", "@swc/core": "1.3.38", "@swc/jest": "0.2.37", @@ -167,6 +169,7 @@ "@types/ua-parser-js": "0.7.36", "@types/uuid": "9.0.2", "@vitejs/plugin-react": "5.1.1", + "@vitest/browser-playwright": "4.0.14", "autoprefixer": "10.4.22", "chromatic": "11.29.0", "dpdm": "3.14.0", diff --git a/site/pnpm-lock.yaml b/site/pnpm-lock.yaml index 46150db386..f1047a26b7 100644 --- a/site/pnpm-lock.yaml +++ b/site/pnpm-lock.yaml @@ -326,6 +326,9 @@ importers: '@storybook/addon-themes': specifier: 10.2.10 version: 10.2.10(storybook@10.2.10(@testing-library/dom@10.4.0)(prettier@3.4.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)) + '@storybook/addon-vitest': + specifier: 10.2.10 + version: 10.2.10(@vitest/browser-playwright@4.0.14)(@vitest/browser@4.1.0(msw@2.4.8(typescript@5.6.3))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0))(vitest@4.0.14))(@vitest/runner@4.0.14)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)(storybook@10.2.10(@testing-library/dom@10.4.0)(prettier@3.4.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2))(vitest@4.0.14) '@storybook/react-vite': specifier: 10.2.10 version: 10.2.10(esbuild@0.25.12)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)(rollup@4.53.3)(storybook@10.2.10(@testing-library/dom@10.4.0)(prettier@3.4.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2))(typescript@5.6.3)(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0)) @@ -410,6 +413,9 @@ importers: '@vitejs/plugin-react': specifier: 5.1.1 version: 5.1.1(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0)) + '@vitest/browser-playwright': + specifier: 4.0.14 + version: 4.0.14(msw@2.4.8(typescript@5.6.3))(playwright@1.50.1)(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0))(vitest@4.0.14) autoprefixer: specifier: 10.4.22 version: 10.4.22(postcss@8.5.6) @@ -490,7 +496,7 @@ importers: version: 0.11.0(@biomejs/biome@2.2.4)(eslint@8.52.0)(optionator@0.9.3)(typescript@5.6.3)(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0)) vitest: specifier: 4.0.14 - version: 4.0.14(@types/node@20.19.25)(jiti@1.21.7)(jsdom@27.2.0)(msw@2.4.8(typescript@5.6.3))(yaml@2.7.0) + version: 4.0.14(@types/node@20.19.25)(@vitest/browser-playwright@4.0.14)(jiti@1.21.7)(jsdom@27.2.0)(msw@2.4.8(typescript@5.6.3))(yaml@2.7.0) packages: @@ -759,6 +765,9 @@ packages: cpu: [x64] os: [win32] + '@blazediff/core@1.9.1': + resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==, tarball: https://registry.npmjs.org/@blazediff/core/-/core-1.9.1.tgz} + '@bundled-es-modules/cookie@2.0.1': resolution: {integrity: sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==, tarball: https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz} @@ -1631,6 +1640,9 @@ packages: engines: {node: '>=18'} hasBin: true + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==, tarball: https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz} + '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==, tarball: https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz} @@ -2349,6 +2361,24 @@ packages: peerDependencies: storybook: ^10.2.10 + '@storybook/addon-vitest@10.2.10': + resolution: {integrity: sha512-U2oHw+Ar+Xd06wDTB74VlujhIIW89OHThpJjwgqgM6NWrOC/XLllJ53ILFDyREBkMwpBD7gJQIoQpLEcKBIEhw==, tarball: https://registry.npmjs.org/@storybook/addon-vitest/-/addon-vitest-10.2.10.tgz} + peerDependencies: + '@vitest/browser': ^3.0.0 || ^4.0.0 + '@vitest/browser-playwright': ^4.0.0 + '@vitest/runner': ^3.0.0 || ^4.0.0 + storybook: ^10.2.10 + vitest: ^3.0.0 || ^4.0.0 + peerDependenciesMeta: + '@vitest/browser': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/runner': + optional: true + vitest: + optional: true + '@storybook/builder-vite@10.2.10': resolution: {integrity: sha512-Wd6CYL7LvRRNiXMz977x9u/qMm7nmMw/7Dow2BybQo+Xbfy1KhVjIoZ/gOiG515zpojSozctNrJUbM0+jH1jwg==, tarball: https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-10.2.10.tgz} peerDependencies: @@ -2836,6 +2866,22 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@vitest/browser-playwright@4.0.14': + resolution: {integrity: sha512-rUvyz6wX6wDjcYzf/7fgXYfca2bAu0Axoq/v9LYdELzcBSS9UKjnZ7MaMY4UDP78HHHCdmdtceuSao1s51ON8A==, tarball: https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.0.14.tgz} + peerDependencies: + playwright: '*' + vitest: 4.0.14 + + '@vitest/browser@4.0.14': + resolution: {integrity: sha512-vO0uqR8SnPTd8ykp14yaIuUyMZ9HEBYuoZrVdUp7RrEp76VEnkrX9fDkGnK0NyBdfWXB6cqp7BmqVekd8yKHFQ==, tarball: https://registry.npmjs.org/@vitest/browser/-/browser-4.0.14.tgz} + peerDependencies: + vitest: 4.0.14 + + '@vitest/browser@4.1.0': + resolution: {integrity: sha512-tG/iOrgbiHQks0ew7CdelUyNEHkv8NLrt+CqdTivIuoSnXvO7scWMn4Kqo78/UGY1NJ6Hv+vp8BvRnED/bjFdQ==, tarball: https://registry.npmjs.org/@vitest/browser/-/browser-4.1.0.tgz} + peerDependencies: + vitest: 4.1.0 + '@vitest/expect@3.2.4': resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==, tarball: https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz} @@ -2853,12 +2899,26 @@ packages: vite: optional: true + '@vitest/mocker@4.1.0': + resolution: {integrity: sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==, tarball: https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.0.tgz} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + '@vitest/pretty-format@3.2.4': resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==, tarball: https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz} '@vitest/pretty-format@4.0.14': resolution: {integrity: sha512-SOYPgujB6TITcJxgd3wmsLl+wZv+fy3av2PpiPpsWPZ6J1ySUYfScfpIt2Yv56ShJXR2MOA6q2KjKHN4EpdyRQ==, tarball: https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.14.tgz} + '@vitest/pretty-format@4.1.0': + resolution: {integrity: sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==, tarball: https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.0.tgz} + '@vitest/runner@4.0.14': resolution: {integrity: sha512-BsAIk3FAqxICqREbX8SetIteT8PiaUL/tgJjmhxJhCsigmzzH8xeadtp7LRnTpCVzvf0ib9BgAfKJHuhNllKLw==, tarball: https://registry.npmjs.org/@vitest/runner/-/runner-4.0.14.tgz} @@ -2871,12 +2931,18 @@ packages: '@vitest/spy@4.0.14': resolution: {integrity: sha512-JmAZT1UtZooO0tpY3GRyiC/8W7dCs05UOq9rfsUUgEZEdq+DuHLmWhPsrTt0TiW7WYeL/hXpaE07AZ2RCk44hg==, tarball: https://registry.npmjs.org/@vitest/spy/-/spy-4.0.14.tgz} + '@vitest/spy@4.1.0': + resolution: {integrity: sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==, tarball: https://registry.npmjs.org/@vitest/spy/-/spy-4.1.0.tgz} + '@vitest/utils@3.2.4': resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==, tarball: https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz} '@vitest/utils@4.0.14': resolution: {integrity: sha512-hLqXZKAWNg8pI+SQXyXxWCTOpA3MvsqcbVeNgSi8x/CSN2wi26dSzn1wrOhmCmFjEvN9p8/kLFRHa6PI8jHazw==, tarball: https://registry.npmjs.org/@vitest/utils/-/utils-4.0.14.tgz} + '@vitest/utils@4.1.0': + resolution: {integrity: sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==, tarball: https://registry.npmjs.org/@vitest/utils/-/utils-4.1.0.tgz} + '@xterm/addon-canvas@0.7.0': resolution: {integrity: sha512-LF5LYcfvefJuJ7QotNRdRSPc9YASAVDeoT5uyXS/nZshZXjYplGXRECBGiznwvhNL2I8bq1Lf5MzRwstsYQ2Iw==, tarball: https://registry.npmjs.org/@xterm/addon-canvas/-/addon-canvas-0.7.0.tgz} peerDependencies: @@ -5066,6 +5132,10 @@ packages: react-dom: optional: true + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==, tarball: https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz} + engines: {node: '>=10'} + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==, tarball: https://registry.npmjs.org/ms/-/ms-2.0.0.tgz} @@ -5312,6 +5382,10 @@ packages: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==, tarball: https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz} engines: {node: '>= 6'} + pixelmatch@7.1.0: + resolution: {integrity: sha512-1wrVzJ2STrpmONHKBy228LM1b84msXDUoAzVEl0R8Mz4Ce6EPr+IVtxm8+yvrqLYMHswREkjYFaMxnyGnaY3Ng==, tarball: https://registry.npmjs.org/pixelmatch/-/pixelmatch-7.1.0.tgz} + hasBin: true + pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==, tarball: https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz} engines: {node: '>=8'} @@ -5326,6 +5400,10 @@ packages: engines: {node: '>=18'} hasBin: true + pngjs@7.0.0: + resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==, tarball: https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz} + engines: {node: '>=14.19.0'} + possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==, tarball: https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz} engines: {node: '>= 0.4'} @@ -5872,6 +5950,10 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, tarball: https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz} engines: {node: '>=14'} + sirv@3.0.2: + resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==, tarball: https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz} + engines: {node: '>=18'} + sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==, tarball: https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz} @@ -6150,6 +6232,10 @@ packages: toposort@2.0.2: resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==, tarball: https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==, tarball: https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz} + engines: {node: '>=6'} + tough-cookie@4.1.4: resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==, tarball: https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz} engines: {node: '>=6'} @@ -6630,6 +6716,18 @@ packages: utf-8-validate: optional: true + ws@8.19.0: + resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==, tarball: https://registry.npmjs.org/ws/-/ws-8.19.0.tgz} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + wsl-utils@0.1.0: resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==, tarball: https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz} engines: {node: '>=18'} @@ -6973,6 +7071,9 @@ snapshots: '@biomejs/cli-win32-x64@2.2.4': optional: true + '@blazediff/core@1.9.1': + optional: true + '@bundled-es-modules/cookie@2.0.1': dependencies: cookie: 0.7.2 @@ -8014,6 +8115,8 @@ snapshots: dependencies: playwright: 1.50.1 + '@polka/url@1.0.0-next.29': {} + '@popperjs/core@2.11.8': {} '@preact/signals-core@1.13.0': {} @@ -8714,6 +8817,20 @@ snapshots: storybook: 10.2.10(@testing-library/dom@10.4.0)(prettier@3.4.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) ts-dedent: 2.2.0 + '@storybook/addon-vitest@10.2.10(@vitest/browser-playwright@4.0.14)(@vitest/browser@4.1.0(msw@2.4.8(typescript@5.6.3))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0))(vitest@4.0.14))(@vitest/runner@4.0.14)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)(storybook@10.2.10(@testing-library/dom@10.4.0)(prettier@3.4.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2))(vitest@4.0.14)': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/icons': 2.0.1(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + storybook: 10.2.10(@testing-library/dom@10.4.0)(prettier@3.4.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + optionalDependencies: + '@vitest/browser': 4.1.0(msw@2.4.8(typescript@5.6.3))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0))(vitest@4.0.14) + '@vitest/browser-playwright': 4.0.14(msw@2.4.8(typescript@5.6.3))(playwright@1.50.1)(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0))(vitest@4.0.14) + '@vitest/runner': 4.0.14 + vitest: 4.0.14(@types/node@20.19.25)(@vitest/browser-playwright@4.0.14)(jiti@1.21.7)(jsdom@27.2.0)(msw@2.4.8(typescript@5.6.3))(yaml@2.7.0) + transitivePeerDependencies: + - react + - react-dom + '@storybook/builder-vite@10.2.10(esbuild@0.25.12)(rollup@4.53.3)(storybook@10.2.10(@testing-library/dom@10.4.0)(prettier@3.4.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0))': dependencies: '@storybook/csf-plugin': 10.2.10(esbuild@0.25.12)(rollup@4.53.3)(storybook@10.2.10(@testing-library/dom@10.4.0)(prettier@3.4.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0)) @@ -9226,6 +9343,54 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitest/browser-playwright@4.0.14(msw@2.4.8(typescript@5.6.3))(playwright@1.50.1)(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0))(vitest@4.0.14)': + dependencies: + '@vitest/browser': 4.0.14(msw@2.4.8(typescript@5.6.3))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0))(vitest@4.0.14) + '@vitest/mocker': 4.0.14(msw@2.4.8(typescript@5.6.3))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0)) + playwright: 1.50.1 + tinyrainbow: 3.0.3 + vitest: 4.0.14(@types/node@20.19.25)(@vitest/browser-playwright@4.0.14)(jiti@1.21.7)(jsdom@27.2.0)(msw@2.4.8(typescript@5.6.3))(yaml@2.7.0) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/browser@4.0.14(msw@2.4.8(typescript@5.6.3))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0))(vitest@4.0.14)': + dependencies: + '@vitest/mocker': 4.0.14(msw@2.4.8(typescript@5.6.3))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0)) + '@vitest/utils': 4.0.14 + magic-string: 0.30.21 + pixelmatch: 7.1.0 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.0.3 + vitest: 4.0.14(@types/node@20.19.25)(@vitest/browser-playwright@4.0.14)(jiti@1.21.7)(jsdom@27.2.0)(msw@2.4.8(typescript@5.6.3))(yaml@2.7.0) + ws: 8.19.0 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/browser@4.1.0(msw@2.4.8(typescript@5.6.3))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0))(vitest@4.0.14)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.0(msw@2.4.8(typescript@5.6.3))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0)) + '@vitest/utils': 4.1.0 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.0.3 + vitest: 4.0.14(@types/node@20.19.25)(@vitest/browser-playwright@4.0.14)(jiti@1.21.7)(jsdom@27.2.0)(msw@2.4.8(typescript@5.6.3))(yaml@2.7.0) + ws: 8.19.0 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + optional: true + '@vitest/expect@3.2.4': dependencies: '@types/chai': 5.2.3 @@ -9252,6 +9417,16 @@ snapshots: msw: 2.4.8(typescript@5.6.3) vite: 7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0) + '@vitest/mocker@4.1.0(msw@2.4.8(typescript@5.6.3))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0))': + dependencies: + '@vitest/spy': 4.1.0 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + msw: 2.4.8(typescript@5.6.3) + vite: 7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0) + optional: true + '@vitest/pretty-format@3.2.4': dependencies: tinyrainbow: 2.0.0 @@ -9260,6 +9435,11 @@ snapshots: dependencies: tinyrainbow: 3.0.3 + '@vitest/pretty-format@4.1.0': + dependencies: + tinyrainbow: 3.0.3 + optional: true + '@vitest/runner@4.0.14': dependencies: '@vitest/utils': 4.0.14 @@ -9277,6 +9457,9 @@ snapshots: '@vitest/spy@4.0.14': {} + '@vitest/spy@4.1.0': + optional: true + '@vitest/utils@3.2.4': dependencies: '@vitest/pretty-format': 3.2.4 @@ -9288,6 +9471,13 @@ snapshots: '@vitest/pretty-format': 4.0.14 tinyrainbow: 3.0.3 + '@vitest/utils@4.1.0': + dependencies: + '@vitest/pretty-format': 4.1.0 + convert-source-map: 2.0.0 + tinyrainbow: 3.0.3 + optional: true + '@xterm/addon-canvas@0.7.0(@xterm/xterm@5.5.0)': dependencies: '@xterm/xterm': 5.5.0 @@ -12036,6 +12226,8 @@ snapshots: react: 19.2.2 react-dom: 19.2.2(react@19.2.2) + mrmime@2.0.1: {} + ms@2.0.0: {} ms@2.1.3: {} @@ -12304,6 +12496,10 @@ snapshots: pirates@4.0.7: {} + pixelmatch@7.1.0: + dependencies: + pngjs: 7.0.0 + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 @@ -12316,6 +12512,8 @@ snapshots: optionalDependencies: fsevents: 2.3.2 + pngjs@7.0.0: {} + possible-typed-array-names@1.0.0: {} postcss-import@15.1.0(postcss@8.5.6): @@ -12971,6 +13169,12 @@ snapshots: signal-exit@4.1.0: {} + sirv@3.0.2: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + sisteransi@1.0.5: {} slash@3.0.0: {} @@ -13264,6 +13468,8 @@ snapshots: toposort@2.0.2: {} + totalist@3.0.1: {} + tough-cookie@4.1.4: dependencies: psl: 1.9.0 @@ -13557,7 +13763,7 @@ snapshots: jiti: 1.21.7 yaml: 2.7.0 - vitest@4.0.14(@types/node@20.19.25)(jiti@1.21.7)(jsdom@27.2.0)(msw@2.4.8(typescript@5.6.3))(yaml@2.7.0): + vitest@4.0.14(@types/node@20.19.25)(@vitest/browser-playwright@4.0.14)(jiti@1.21.7)(jsdom@27.2.0)(msw@2.4.8(typescript@5.6.3))(yaml@2.7.0): dependencies: '@vitest/expect': 4.0.14 '@vitest/mocker': 4.0.14(msw@2.4.8(typescript@5.6.3))(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0)) @@ -13581,6 +13787,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 20.19.25 + '@vitest/browser-playwright': 4.0.14(msw@2.4.8(typescript@5.6.3))(playwright@1.50.1)(vite@7.2.6(@types/node@20.19.25)(jiti@1.21.7)(yaml@2.7.0))(vitest@4.0.14) jsdom: 27.2.0 transitivePeerDependencies: - jiti @@ -13707,6 +13914,8 @@ snapshots: ws@8.18.3: {} + ws@8.19.0: {} + wsl-utils@0.1.0: dependencies: is-wsl: 3.1.1 diff --git a/site/vite.config.mts b/site/vite.config.mts index 98cd000002..f9893c3a87 100644 --- a/site/vite.config.mts +++ b/site/vite.config.mts @@ -1,5 +1,7 @@ import * as path from "node:path"; +import { storybookTest } from "@storybook/addon-vitest/vitest-plugin"; import react from "@vitejs/plugin-react"; +import { playwright } from "@vitest/browser-playwright"; import { visualizer } from "rollup-plugin-visualizer"; import type { PluginOption } from "vite"; import checker from "vite-plugin-checker"; @@ -210,10 +212,42 @@ export default defineConfig({ }, }, test: { - include: ["src/**/*.test.?(m)ts?(x)"], - globals: true, - environment: "jsdom", - setupFiles: ["@testing-library/jest-dom/vitest", "./test/vitestSetup.ts"], - silent: "passed-only", + projects: [ + { + extends: true, + test: { + name: "unit", + include: ["src/**/*.test.?(m)ts?(x)"], + globals: true, + environment: "jsdom", + setupFiles: [ + "@testing-library/jest-dom/vitest", + "./test/vitestSetup.ts", + ], + silent: "passed-only", + }, + }, + // Storybook story tests via Playwright browser mode. + // Discovery handled by the storybookTest plugin via + // .storybook/main.ts `stories` config. + { + extends: true, + plugins: [ + storybookTest({ + configDir: path.join(__dirname, ".storybook"), + }), + ], + test: { + name: "storybook", + browser: { + enabled: true, + headless: true, + provider: playwright(), + instances: [{ browser: "chromium" }], + }, + setupFiles: [".storybook/vitest.setup.ts"], + }, + }, + ], }, });