🌈
next.jsでフルスタック開発をしている場合のvitest.configについて
課題
元々実装でバックエンド中心に実装をしていた。react-testing-libraryを入れて簡単なテストを実行した。
index.test.tsx
import { render, screen } from '@testing-library/react'
import '@testing-library/jest-dom'
import { test } from 'vitest'
import { BottomNavigation } from '@/components/template/BottomNavigation'
test('loads and displays greeting', ({ expect }) => {
render(<BottomNavigation />)
expect(screen.getByRole('link')).toHaveTextContent('ムーブ')
})
すると下記のようなエラーが出た。
documentがないということで、vitest.config.tsを確認する。
environmentのvprismaがnode前提になっているからのようだ。
vitest.config.ts
/// <reference types="vitest" />
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
// biome-ignore lint/correctness/noNodejsModules: <explanation>
import { resolve } from 'node:path'
export default defineConfig({
plugins: [react()],
test: {
include: ['./src/**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
globals: true,
environment: 'vprisma',
setupFiles: ['vitest-environment-vprisma/setup', './src/test/vitest.setup.ts'],
env: {
POSTGRES_PRISMA_URL: 'postgresql://root:password@localhost:5436/database_name?schema=public',
},
},
resolve: {
alias: [{ find: '@', replacement: resolve(__dirname, './src') }],
},
})
テスト方針は下記のように考えて実装をしていた。
- 全体のユースケースのテストはplaywrightでe2eテストを行う
- フロントエンドのclient側はReact Testing Library とvitestを使ってテスト
- server actionsを使う場合にデータベースとの接続部分をモックしたりする必要が出てくるので使わない。
- バックエンドはprismaを使ったテストを行う想定。
解決方法
そこで一つのファイルでnode環境とjsdomを使ったテストの両方をするのはどうかな?と考えて下記のようにファイルを分けた。
vitest.client.config.ts
/// <reference types="vitest" />
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
// biome-ignore lint/correctness/noNodejsModules: <explanation>
import { resolve } from 'node:path'
export default defineConfig({
plugins: [react()],
test: {
include: ['./src/**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
exclude: ['./src/server/**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
/** @link https://zenn.dev/nyatinte/articles/9ee2926895b83f */
environment: 'jsdom',
globals: true,
},
resolve: {
alias: [{ find: '@', replacement: resolve(__dirname, './src') }],
},
})
vitest.server.config.ts
/// <reference types="vitest" />
import { defineConfig } from 'vitest/config'
// biome-ignore lint/correctness/noNodejsModules: <explanation>
import { resolve } from 'node:path'
export default defineConfig({
test: {
include: ['./src/server/**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], // サーバー側の実装だけを対象にする。
globals: true,
environment: 'vprisma',
setupFiles: ['vitest-environment-vprisma/setup', './src/test/vitest.setup.ts'],
env: {
POSTGRES_PRISMA_URL: 'postgresql://root:password@localhost:5432/?schema=public',
},
},
resolve: {
alias: [{ find: '@', replacement: resolve(__dirname, './src') }],
},
})
下記のようにしてpackage.jsonでscriptsを指定をして実行した。
package.json
"scripts": {
"test:unit": "vitest run -c vitest.server.config.ts && vitest run -c vitest.client.config.ts",
},
もしも一つのファイルで実行する場合、今回vprismaを扱っていることが原因であり、改めてgithubのコードを確認するとenvironmentOptions.vprisma.baseEnvで環境を指定できるようだった。
vitest.config.ts
/// <reference types="vitest" />
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
// biome-ignore lint/correctness/noNodejsModules: <explanation>
import { resolve } from 'node:path'
export default defineConfig({
plugins: [react()],
test: {
include: ['./src/**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
globals: true,
environment: 'vprisma',
setupFiles: ['vitest-environment-vprisma/setup', './src/test/vitest.setup.ts'],
environmentOptions: {
vprisma: {
baseEnv: 'jsdom', // ここで指定
},
},
env: {
POSTGRES_PRISMA_URL: 'postgresql://root:password@localhost:5436/database_name?schema=public',
},
},
resolve: {
alias: [{ find: '@', replacement: resolve(__dirname, './src') }],
},
})
これで成功をした。
最後に
最初は2つのファイルの分けた方がいいかな?と思いつつも、一つのファイルでserver側のコードとclient側のコードの両方が実行するようにしたが、Next.jsでフルスタック開発をする場合は、やはりファイルを分けて対応をした方がそれぞれでconfigを設定できるからいいかもしれない。
Discussion