Closed4
Vitestと格闘している様子を実況
環境
library | version |
---|---|
react | 18.2.0 |
react-redux | 8.1.2 |
react-router-dom | 6.16.0 |
typescript | 5.0.2 |
vite | 4.4.5 |
vitest | 0.34.5 |
設定
ルートディレクトリへvitest.config.ts
を設置し設定を記述する
/// <reference types="vitest" />
import { defineConfig } from 'vite'
export default defineConfig({
test: {
globals: true, // viなどのAPIをimportなしで使用できる
environment: 'happy-dom',
alias: {
components: '/src/components',
// vite.config.tsにaliasを設定している場合はvitest.config.tsにも書く
},
setupFiles: './vitest-setup', // テストの前処理として実行したいコードを設定できる
},
})
仮想のURLを設定したテスト
<Router>
へcreateMemoryHistory
のhistory
を設定すると噛み合った
import { Provider } from 'react-redux'
import { Routes, Router, Route } from 'react-router-dom'
import { render, screen } from '@testing-library/react'
import { createMemoryHistory } from 'history'
import { store } from 'store' // 環境にあわせてstoreへのパスを設定
import { App } from './App' // テスト対象のコンポーネント
const history = createMemoryHistory()
// 共通処理: render
const initial = (path: string) => {
history.push(path)
return render(
<Provider store={store}>
<Router location={history.location} navigator={history}>
<Routes>
<Route path={このコンポーネントを表示したいpath} element={<App />} />
</Routes>
</Router>
</Provider>
)
}
describe('メインナビのテスト', () => {
test('/hogeにアクセスすると、fuga', () => {
const path = '/hoge'
initial(path)
// URLが"/hoge"のときAppがどうなっていてほしいか
})
})
useLocationのモック 効いていなかった
1件だけならモックアップ成功させられるも、リセットに失敗している。
1件目のtestメニューを使用するlocationを含んでいる場合は表示
は成功するのに
2件目メニューを使用するlocationを含んでいない場合は非表示
は成功しない。
1件目と2件目を入れ替えると最初のtestが成功する。
import { renderHook } from '@testing-library/react'
import { useMainNavigation } from './useMainNavigation'
describe('メインナビのテスト', () => {
afterEach(() => {
vi.doUnmock('react-router-dom')
})
test('メニューを使用するlocationを含んでいる場合は表示', () => {
vi.mock('react-router-dom', async () => {
const actualRedux = await vi.importActual('react-router-dom')
return {
...(actualRedux as any),
useLocation: vi.fn(() => {
return { pathname: '/information' }
}),
}
})
const { result } = renderHook(() => useMainNavigation())
expect(result.current.isVisible).toBe(true)
})
test('メニューを使用するlocationを含んでいない場合は非表示', () => {
vi.mock('react-router-dom', async () => {
const actualRedux = await vi.importActual('react-router-dom')
return {
...(actualRedux as any),
useLocation: vi.fn(() => {
return { pathname: '/login' }
}),
}
})
const { result } = renderHook(() => useMainNavigation())
expect(result.current.isVisible).toBe(false)
})
})
共通関数化に失敗
vi.mock('react-router-dom'〜をこのような共通関数にすると
value
がundefined
というエラーでテストが実行できなくなる
import { renderHook } from '@testing-library/react'
import { useMainNavigation } from './useMainNavigation'
const setupLocationMock = (value: string) => {
console.log('Setting up mock with pathname:', pathname);
vi.mock('react-router-dom', async () => {
const actualRedux = await vi.importActual('react-router-dom');
console.log('Mocking useLocation with pathname:', pathname);
return {
...(actualRedux as any),
useLocation: vi.fn(() => {
console.log('useLocation mock called');
return { pathname: value };
}),
};
});
}
describe('メインナビのテスト', () => {
afterEach(() => {
vi.doUnmock('react-router-dom')
})
test('メニューを使用するlocationを含んでいる場合は表示', () => {
setupLocationMock('/information')
const { result } = renderHook(() => useMainNavigation())
expect(result.current.isVisible).toBe(true)
})
})
このスクラップは4ヶ月前にクローズされました