📚
[備忘録] vitest workspaceを利用してstorybook testを行ってハマった
構成
apps
├ storybook
├ web
...
モノレポの構成は次の2つの記事を参照
process.cwd
が異なる
ハマりポイント 各パッケージ配下で実行したときとworkspace rootで実行したときでworkspace rootでテストを実行すると
pnpm exec vitest run
process.cwd
はプロジェクトルートになる
各パッケージ配下で実行すると
pnpm --filter storybook test
process.cwd
はapps/storybook
となる
これが原因で、各パッケージ配下で動いたのに、あらためてworkspace rootでvitest runすると動かなくなる。
vitest-plugin
の設定
storybookのサンプルコードをみると次のように書かれてあるが、workspace rootから実行するとstorybookTest({ configDir: '.storybook' })
のパス解決がうまくいかない。
/// <reference types="@vitest/browser/providers/playwright" />
import { defineProject } from 'vitest/config';
import { storybookTest } from '@storybook/experimental-addon-test/vitest-plugin';
import { storybookNextJsPlugin } from '@storybook/experimental-nextjs-vite/vite-plugin';
export default defineProject({
plugins: [
// See options at: https://storybook.js.org/docs/writing-tests/vitest-plugin#storybooktest
storybookTest({ configDir: '.storybook' }),
// More info at: https://github.com/storybookjs/vite-plugin-storybook-nextjs
storybookNextJsPlugin(),
],
test: {
globals: false,
browser: {
enabled: true,
headless: true,
provider: 'playwright',
// エラーが発生するためそれまでは、deprecatedだがinstancesではなくname指定を行う
// エラー内容: Cannot define a nested project for a chromium browser. The project name "chromium" was already defined.
// issue: https://github.com/storybookjs/storybook/issues/30363
// instances: [{ browser: 'chromium', name: 'chromium' }],
name: 'chromium',
},
setupFiles: ['.storybook/vitest.setup.tsx'],
},
});
対策: vitest.configをローカル実行用とworkspace root実行用の2つに分ける
ローカル実行用
apps/storybook/vitest.config.local.mts
/// <reference types="@vitest/browser/providers/playwright" />
import { defineProject } from 'vitest/config';
import { storybookTest } from '@storybook/experimental-addon-test/vitest-plugin';
import { storybookNextJsPlugin } from '@storybook/experimental-nextjs-vite/vite-plugin';
export default defineProject({
plugins: [
// See options at: https://storybook.js.org/docs/writing-tests/vitest-plugin#storybooktest
storybookTest({ configDir: '.storybook' }),
// More info at: https://github.com/storybookjs/vite-plugin-storybook-nextjs
storybookNextJsPlugin(),
],
test: {
globals: false,
browser: {
enabled: true,
headless: true,
provider: 'playwright',
// エラーが発生するためそれまでは、deprecatedだがinstancesではなくname指定を行う
// エラー内容: Cannot define a nested project for a chromium browser. The project name "chromium" was already defined.
// issue: https://github.com/storybookjs/storybook/issues/30363
// instances: [{ browser: 'chromium', name: 'chromium' }],
name: 'chromium',
},
setupFiles: ['.storybook/vitest.setup.tsx'],
},
// エラー対策 https://zenn.dev/coji/articles/a8508bae1d8fa6
optimizeDeps: { exclude: ['@mapbox/node-pre-gyp'] },
});
apps/storybook/package.json
{
"name": "storybook",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "storybook dev -p 6006",
"build": "storybook build",
"lint": "eslint .",
"test:coverage": "vitest --coverage --config vitest.config.local.mts",
"test": "vitest --config vitest.config.local.mts"
}
}
workspace root実行用
vitest.config.mts
/// <reference types="@vitest/browser/providers/playwright" />
import { defineProject } from 'vitest/config';
import { storybookTest } from '@storybook/experimental-addon-test/vitest-plugin';
import { storybookNextJsPlugin } from '@storybook/experimental-nextjs-vite/vite-plugin';
export default defineProject({
plugins: [
// See options at: https://storybook.js.org/docs/writing-tests/vitest-plugin#storybooktest
storybookTest({ configDir: 'apps/storybook/.storybook' }),
// More info at: https://github.com/storybookjs/vite-plugin-storybook-nextjs
storybookNextJsPlugin(),
],
test: {
globals: false,
browser: {
enabled: true,
headless: true,
provider: 'playwright',
// エラーが発生するためそれまでは、deprecatedだがinstancesではなくname指定を行う
// エラー内容: Cannot define a nested project for a chromium browser. The project name "chromium" was already defined.
// issue: https://github.com/storybookjs/storybook/issues/30363
// instances: [{ browser: 'chromium', name: 'chromium' }],
name: 'chromium',
},
setupFiles: ['.storybook/vitest.setup.tsx'],
},
});
vitest workspaceの設定はこちらを参照する
vitest.config.mts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
workspace: [
'./apps/**/vitest.config.mts', // ここでworkspaceを設定
'./packages/**/vitest.config.mts',
],
include: ['apps/**/*.spec.{ts,tsx}', 'packages/**/*.spec.{ts,tsx}'],
exclude: ['node_modules', 'dist', '.next', 'coverage', '.turbo'],
coverage: {
provider: 'v8', // または 'istanbul'
reporter: ['text', 'html', 'lcov'], // 必要なカバレッジレポート形式
all: true, // 全てのファイルを対象
include: [
'**/src/**/*.{ts,tsx}',
'**/lib/**/*.{ts,tsx}',
'**/stories/**/*.{ts,tsx}',
'**/app/**/*.{ts,tsx}',
], // カバレッジ計測対象
exclude: [
'**/node_modules',
'**/dist',
'tests',
'**/.next',
'**/coverage',
'**/.turbo',
], // 除外対象
},
},
});
workspace rootから実行するとpandacssのpostcssでエラーがでる
エラー
headless: true
の場合:
FAIL storybook (chromium) ../xxx.stories.tsx [ xxx.stories.tsx ]
TypeError: Failed to fetch dynamically imported module: http://localhost:63315/xxx/apps/storybook/.storybook/vitest.setup.ts?import&browserv=xxx
headless: false
の場合:
[vite] Internal server error: [postcss] Cannot find config file `panda.config.{ts,js,mjs,mts}`. Did you forget to run `panda init`?
postcss.config.cjs
にcwd
オプションを渡す
対策
apps/storybook/postcss.config.cjs
module.exports = {
plugins: {
'@pandacss/dev/postcss': {
// vitest workspaceのルートから起動するとき、cwdが異なることでpanda.config.tsを検知できないため、cwdを指定する
cwd: __dirname,
},
},
};
Discussion