コンテンツへスキップ

Vi

Vitestは、そのviヘルパーを通じて支援するユーティリティ関数を提供します。グローバルにアクセスできます(globals設定が有効になっている場合)、またはvitestから直接インポートできます。

js
import { vi } from 'vitest'

モックモジュール

このセクションでは、モジュールのモックを行う際に使用できるAPIについて説明します。Vitestはrequire()を使用してインポートされたモジュールのモックをサポートしていないことに注意してください。

vi.mock

  • : (path: string, factory?: (importOriginal: () => unknown) => unknown) => void

指定されたpathからのすべてのインポートされたモジュールを別のモジュールで置き換えます。パス内では設定されたViteエイリアスを使用できます。vi.mockへの呼び出しはホイスティングされるため、呼び出す場所を気にする必要はありません。常にすべてのインポートの前に実行されます。そのスコープ外の変数を参照する必要がある場合は、vi.hoisted内で定義し、vi.mock内で参照できます。

警告

vi.mockは、importキーワードでインポートされたモジュールに対してのみ機能します。requireでは機能しません。

vi.mockをホイスティングするために、Vitestは静的にファイルを解析します。これは、vitestパッケージから直接インポートされていない(たとえば、一部のユーティリティファイルから)viは使用できないことを示しています。vitestからインポートされたvivi.mockを使用するか、globals設定オプションを有効にしてください。

Vitestは、セットアップファイル内でインポートされたモジュールをモックしません。テストファイルが実行されるまでにキャッシュされるためです。テストファイルを実行する前にすべてのモジュールキャッシュをクリアするには、vi.resetModules()vi.hoisted内で呼び出すことができます。

警告

ブラウザモードは現在、モジュールのモックをサポートしていません。GitHubのissueでこの機能を追跡できます。

factoryが定義されている場合、すべてのインポートはその結果を返します。vi.unmockまたはvi.doUnmockが呼び出されるまで、Vitestはfactoryを1回だけ呼び出し、後続のすべてのインポートの結果をキャッシュします。

jestとは異なり、factoryは非同期にすることができます。vi.importActualまたは、最初の引数として渡されたfactoryを持つヘルパーを使用し、内部で元のモジュールを取得できます。

js
// when using JavaScript

.('./path/to/module.js', async () => {
  const  = await ()
  return {
    ...,
    // replace some exports
    : .(),
  }
})
ts
// when using TypeScript

vi.mock('./path/to/module.js', async (importOriginal) => {
  const mod = await importOriginal<typeof import('./path/to/module.js')>()
  return {
    ...mod,
    // replace some exports
    namedExport: vi.fn(),
  }
})

警告

vi.mockはホイスティングされます(つまり、ファイルの先頭に移動されます)。つまり、どこ(beforeEach内やtest内など)に記述しても、実際にはそれよりも前に呼び出されるということです。

これはまた、factoryの外側で定義されている変数をfactory内で使用できないことを意味します。

factory内で変数を使用する必要がある場合は、vi.doMockを試してください。同じように機能しますが、ホイスティングされません。後続のインポートのみをモックすることに注意してください。

vi.mockの前に宣言されている場合、vi.hoistedメソッドによって定義された変数を参照することもできます。

ts
import { namedExport } from './path/to/module.js'

const mocks = vi.hoisted(() => {
  return {
    namedExport: vi.fn(),
  }
})

vi.mock('./path/to/module.js', () => {
  return {
    namedExport: mocks.namedExport,
  }
})

vi.mocked(namedExport).mockReturnValue(100)

expect(namedExport()).toBe(100)
expect(namedExport).toBe(mocks.namedExport)

警告

デフォルトエクスポートを持つモジュールをモックする場合は、返されたfactory関数オブジェクト内にdefaultキーを指定する必要があります。これはESモジュール固有の注意点です。そのため、jestはCommonJSモジュールを使用するため、jestのドキュメントとは異なる場合があります。例:

ts
vi.mock('./path/to/module.js', () => {
  return {
    default: { myDefaultKey: vi.fn() },
    namedExport: vi.fn(),
    // etc...
  }
})

モックしているファイルと並んで__mocks__フォルダがあり、factoryが提供されていない場合、Vitestは__mocks__サブフォルダに同じ名前のファイルを探し、それを実際のモジュールとして使用しようとします。依存関係をモックしている場合、Vitestはプロジェクトのルート(デフォルトはprocess.cwd())に__mocks__フォルダを探します。依存関係の場所をdeps.moduleDirectories設定オプションを使用してVitestに指示できます。

たとえば、次のファイル構造があるとします。

- __mocks__
  - axios.js
- src
  __mocks__
    - increment.js
  - increment.js
- tests
  - increment.test.js

factoryが提供されずにテストファイルでvi.mockを呼び出すと、モジュールとして使用する__mocks__フォルダ内のファイルが検出されます。

ts
// increment.test.js
import { vi } from 'vitest'

// axios is a default export from `__mocks__/axios.js`
import axios from 'axios'

// increment is a named export from `src/__mocks__/increment.js`
import { increment } from '../increment.js'

vi.mock('axios')
vi.mock('../increment.js')

axios.get(`/apples/${increment(1)}`)

警告

vi.mockを呼び出さない場合、モジュールは自動的にモックされないことに注意してください。Jestの自動モック動作を複製するには、setupFiles内で必要な各モジュールに対してvi.mockを呼び出すことができます。

__mocks__フォルダまたは提供されたfactoryがない場合、Vitestは元のモジュールをインポートし、そのすべてのエクスポートを自動的にモックします。適用されるルールについては、アルゴリズムを参照してください。

vi.doMock

  • : (path: string, factory?: (importOriginal: () => unknown) => unknown) => void

vi.mockと同じですが、ファイルの先頭にホイスティングされないため、グローバルファイルスコープの変数を参照できます。モジュールの次の動的インポートがモックされます。

警告

これにより、これの前にインポートされたモジュールはモックされません。ESMのすべての静的インポートは常にホイスティングされるため、これを静的インポートの前に配置しても、インポートの前に呼び出されるようにはなりません。

ts
vi.doMock('./increment.js') // this will be called _after_ the import statement

import { increment } from './increment.js'
ts
// ./increment.js
export function increment(number) {
  return number + 1
}
ts
import { beforeEach, test } from 'vitest'
import { increment } from './increment.js'

// the module is not mocked, because vi.doMock is not called yet
increment(1) === 2

let mockedIncrement = 100

beforeEach(() => {
  // you can access variables inside a factory
  vi.doMock('./increment.js', () => ({ increment: () => ++mockedIncrement }))
})

test('importing the next module imports mocked one', async () => {
  // original import WAS NOT MOCKED, because vi.doMock is evaluated AFTER imports
  expect(increment(1)).toBe(2)
  const { increment: mockedIncrement } = await import('./increment.js')
  // new dynamic import returns mocked module
  expect(mockedIncrement(1)).toBe(101)
  expect(mockedIncrement(1)).toBe(102)
  expect(mockedIncrement(1)).toBe(103)
})

vi.mocked

  • : <T>(obj: T, deep?: boolean) => MaybeMockedDeep<T>
  • : <T>(obj: T, options?: { partial?: boolean; deep?: boolean }) => MaybePartiallyMockedDeep<T>

TypeScriptの型ヘルパー。渡されたオブジェクトをそのまま返します。

partialtrueの場合、Partial<T>を戻り値として期待します。デフォルトでは、TypeScriptは最上位レベルの値のみがモックされていると判断します。実際にはオブジェクト全体がモックされていることをTypeScriptに伝えるには、第2引数として{ deep: true }を渡すことができます。

ts
import example from './example.js'

vi.mock('./example.js')

test('1 + 1 equals 10', async () => {
  vi.mocked(example.calc).mockReturnValue(10)
  expect(example.calc(1, '+', 1)).toBe(10)
})

vi.importActual

  • : <T>(path: string) => Promise<T>

モックするかどうかすべてのチェックをバイパスして、モジュールをインポートします。モジュールを部分的にモックしたい場合に役立ちます。

ts
vi.mock('./example.js', async () => {
  const axios = await vi.importActual('./example.js')

  return { ...axios, get: vi.fn() }
})

vi.importMock

  • : <T>(path: string) => Promise<MaybeMockedDeep<T>>

すべてのプロパティ(ネストされたプロパティを含む)がモックされたモジュールをインポートします。vi.mockと同じルールに従います。適用されるルールについては、アルゴリズムを参照してください。

vi.unmock

  • : (path: string) => void

モックレジストリからモジュールを削除します。インポートへのすべての呼び出しは、以前モックされていた場合でも、元のモジュールを返します。この呼び出しはファイルの先頭にホイスティングされるため、たとえばsetupFilesで定義されたモジュールのみがアンモックされます。

vi.doUnmock

  • : (path: string) => void

vi.unmockと同じですが、ファイルの先頭にホイスティングされません。モジュールの次のインポートは、モックではなく元のモジュールをインポートします。これにより、以前にインポートされたモジュールはアンモックされません。

ts
// ./increment.js
export function increment(number) {
  return number + 1
}
ts
import { increment } from './increment.js'

// increment is already mocked, because vi.mock is hoisted
increment(1) === 100

// this is hoisted, and factory is called before the import on line 1
vi.mock('./increment.js', () => ({ increment: () => 100 }))

// all calls are mocked, and `increment` always returns 100
increment(1) === 100
increment(30) === 100

// this is not hoisted, so other import will return unmocked module
vi.doUnmock('./increment.js')

// this STILL returns 100, because `vi.doUnmock` doesn't reevaluate a module
increment(1) === 100
increment(30) === 100

// the next import is unmocked, now `increment` is the original function that returns count + 1
const { increment: unmockedIncrement } = await import('./increment.js')

unmockedIncrement(1) === 2
unmockedIncrement(30) === 31

vi.resetModules

  • : () => Vitest

すべてのモジュールのキャッシュをクリアすることで、モジュールレジストリをリセットします。これにより、再インポート時にモジュールを再評価できます。トップレベルのインポートは再評価できません。テスト間のローカル状態の競合を分離する場合に役立つ場合があります。

ts
import { vi } from 'vitest'

import { data } from './data.js' // Will not get reevaluated beforeEach test

beforeEach(() => {
  vi.resetModules()
})

test('change state', async () => {
  const mod = await import('./some/path.js') // Will get reevaluated
  mod.changeLocalState('new value')
  expect(mod.getLocalState()).toBe('new value')
})

test('module has old state', async () => {
  const mod = await import('./some/path.js') // Will get reevaluated
  expect(mod.getLocalState()).toBe('old value')
})

警告

モックレジストリはリセットしません。モックレジストリをクリアするには、vi.unmockまたはvi.doUnmockを使用します。

vi.dynamicImportSettled

すべてのインポートの読み込みを待ちます。それ以外の方法では待てないモジュールのインポートを開始する同期呼び出しがある場合に役立ちます。

ts
import { expect, test } from 'vitest'

// cannot track import because Promise is not returned
function renderComponent() {
  import('./component.js').then(({ render }) => {
    render()
  })
}

test('operations are resolved', async () => {
  renderComponent()
  await vi.dynamicImportSettled()
  expect(document.querySelector('.component')).not.toBeNull()
})

ヒント

動的インポート中に別の動的インポートが開始された場合、このメソッドはすべてが解決されるまで待ちます。

このメソッドは、インポートが解決された後の次のsetTimeoutティックも待機するため、同期操作はすべて解決されるまでに完了している必要があります。

関数とオブジェクトのモック

このセクションでは、メソッドモックの使用方法と、環境変数およびグローバル変数の置き換えについて説明します。

vi.fn

  • 型: (fn?: Function) => Mock

関数に対するスパイを作成しますが、関数なしで開始することもできます。関数が呼び出されるたびに、その呼び出し引数、戻り値、インスタンスを格納します。また、メソッドを使用して動作を操作できます。関数が指定されていない場合、モックは呼び出されるとundefinedを返します。

ts
const  = .(() => 0)

()

().()
().(0)

.(5)

const  = ()
().(5)
().(2, 5)

vi.isMockFunction

  • 型: (fn: Function) => boolean

指定されたパラメータがモック関数であるかどうかを確認します。TypeScriptを使用している場合、その型も絞り込まれます。

vi.clearAllMocks

すべてのスパイに対して.mockClear()を呼び出します。これによりモック履歴がクリアされますが、実装はデフォルトのものにリセットされません。

vi.resetAllMocks

すべてのスパイに対して.mockReset()を呼び出します。これによりモック履歴がクリアされ、実装が空の関数(undefinedを返す)にリセットされます。

vi.restoreAllMocks

すべてのスパイに対して.mockRestore()を呼び出します。これによりモック履歴がクリアされ、実装が元の状態にリセットされます。

vi.spyOn

  • 型: <T, K extends keyof T>(object: T, method: K, accessType?: 'get' | 'set') => MockInstance

vi.fn()に似て、オブジェクトのメソッドまたはゲッター/セッターに対するスパイを作成します。モック関数を返します。

ts
let  = 0
const  = {
  : () => 42,
}

const  = .(, 'getApples').(() => )
 = 1

(.()).(1)

().()
().(1)

ヒント

afterEach内でvi.restoreAllMocksを呼び出す(またはtest.restoreMocksを有効にする)ことで、すべてのメソッドを元の状態に復元できます。これにより、元のオブジェクト記述子が復元されるため、メソッドの実装を変更できなくなります。

ts
const cart = {
  getApples: () => 42,
}

const spy = vi.spyOn(cart, 'getApples').mockReturnValue(10)

console.log(cart.getApples()) // 10
vi.restoreAllMocks()
console.log(cart.getApples()) // 42
spy.mockReturnValue(10)
console.log(cart.getApples()) // still 42!

vi.stubEnv 0.26.0+

  • 型: (name: string, value: string) => Vitest

process.envimport.meta.envの環境変数の値を変更します。vi.unstubAllEnvsを呼び出すことで、元の値に戻すことができます。

ts
import { vi } from 'vitest'

// `process.env.NODE_ENV` and `import.meta.env.NODE_ENV`
// are "development" before calling "vi.stubEnv"

vi.stubEnv('NODE_ENV', 'production')

process.env.NODE_ENV === 'production'
import.meta.env.NODE_ENV === 'production'
// doesn't change other envs
import.meta.env.MODE === 'development'

ヒント

単純に値を代入して変更することもできますが、その場合はvi.unstubAllEnvsを使用して以前の値を復元することはできません。

ts
import.meta.env.MODE = 'test'

vi.unstubAllEnvs 0.26.0+

  • 型: () => Vitest

vi.stubEnvで変更されたすべてのimport.meta.envprocess.envの値を復元します。最初に呼び出された際に、Vitestは元の値を記憶し、unstubAllEnvsが再び呼び出されるまで保存します。

ts
import { vi } from 'vitest'

// `process.env.NODE_ENV` and `import.meta.env.NODE_ENV`
// are "development" before calling stubEnv

vi.stubEnv('NODE_ENV', 'production')

process.env.NODE_ENV === 'production'
import.meta.env.NODE_ENV === 'production'

vi.stubEnv('NODE_ENV', 'staging')

process.env.NODE_ENV === 'staging'
import.meta.env.NODE_ENV === 'staging'

vi.unstubAllEnvs()

// restores to the value that were stored before the first "stubEnv" call
process.env.NODE_ENV === 'development'
import.meta.env.NODE_ENV === 'development'

vi.stubGlobal

  • 型: (name: string | number | symbol, value: unknown) => Vitest

グローバル変数の値を変更します。vi.unstubAllGlobalsを呼び出すことで、元の値に戻すことができます。

ts
import {  } from 'vitest'

// `innerWidth` is "0" before calling stubGlobal

.('innerWidth', 100)

 === 100
. === 100
// if you are using jsdom or happy-dom
. === 100

ヒント

globalThisまたはwindowjsdomまたはhappy-dom環境を使用している場合)に単純に値を代入して変更することもできますが、その場合はvi.unstubAllGlobalsを使用して元の値を復元することはできません。

ts
globalThis.innerWidth = 100
// if you are using jsdom or happy-dom
window.innerWidth = 100

vi.unstubAllGlobals 0.26.0+

  • 型: () => Vitest

vi.stubGlobalで変更されたすべてのグローバル値(globalThis/global、およびjsdomまたはhappy-dom環境を使用している場合はwindow/top/self/parent)を復元します。最初に呼び出された際に、Vitestは元の値を記憶し、unstubAllGlobalsが再び呼び出されるまで保存します。

ts
import { vi } from 'vitest'

const Mock = vi.fn()

// IntersectionObserver is "undefined" before calling "stubGlobal"

vi.stubGlobal('IntersectionObserver', Mock)

IntersectionObserver === Mock
global.IntersectionObserver === Mock
globalThis.IntersectionObserver === Mock
// if you are using jsdom or happy-dom
window.IntersectionObserver === Mock

vi.unstubAllGlobals()

globalThis.IntersectionObserver === undefined
'IntersectionObserver' in globalThis === false
// throws ReferenceError, because it's not defined
IntersectionObserver === undefined

疑似タイマー

このセクションでは、疑似タイマーの使用方法について説明します。

vi.advanceTimersByTime

  • 型: (ms: number) => Vitest

このメソッドは、指定されたミリ秒数が経過するか、キューが空になるまで(どちらか先に来るまで)、開始されたすべてのタイマーを呼び出します。

ts
let  = 0
(() => .(++), 50)

.(150)

// log: 1
// log: 2
// log: 3

vi.advanceTimersByTimeAsync

  • 型: (ms: number) => Promise<Vitest>

このメソッドは、指定されたミリ秒数が経過するか、キューが空になるまで(どちらか先に来るまで)、開始されたすべてのタイマーを呼び出します。非同期で設定されたタイマーも含まれます。

ts
let  = 0
(() => .().(() => .(++)), 50)

await .(150)

// log: 1
// log: 2
// log: 3

vi.advanceTimersToNextTimer

  • 型: () => Vitest

次に利用可能なタイマーを呼び出します。各タイマー呼び出し間のassertionに役立ちます。自身でタイマーを管理するために、チェーン呼び出しを行うことができます。

ts
let  = 0
(() => .(++), 50)

.() // log: 1
  .() // log: 2
  .() // log: 3

vi.advanceTimersToNextTimerAsync

  • 型: () => Promise<Vitest>

次に利用可能なタイマーを呼び出し、非同期で設定された場合は解決されるまで待機します。各タイマー呼び出し間のassertionに役立ちます。

ts
let  = 0
(() => .().(() => .(++)), 50)

await .() // log: 1
(.).(1)

await .() // log: 2
await .() // log: 3

vi.getTimerCount

  • 型: () => number

待機中のタイマーの数を取得します。

vi.clearAllTimers

実行される予定のすべてのタイマーを削除します。これらのタイマーは将来実行されることはありません。

vi.getMockedSystemTime

  • : () => Date | null

setSystemTimeを使用して設定された、モックされた現在の日時を返します。日時がモックされていない場合、このメソッドはnullを返します。

vi.getRealSystemTime

  • : () => number

vi.useFakeTimersを使用している場合、Date.nowの呼び出しはモックされます。ミリ秒単位の実時間を取得する必要がある場合は、この関数を使用できます。

vi.runAllTicks

  • 型: () => Vitest

process.nextTickによってキューに入れられたすべてのmicrotaskを呼び出します。これにより、それ自体によってスケジュールされたすべてのmicrotaskも実行されます。

vi.runAllTimers

  • 型: () => Vitest

このメソッドは、タイマーキューが空になるまで、開始されたすべてのタイマーを呼び出します。つまり、runAllTimers中に呼び出されたすべてのタイマーが発火します。無限のintervalがある場合、10000回の試行後にエラーをスローします(fakeTimers.loopLimitで設定できます)。

ts
let  = 0
(() => .(++))
const  = (() => {
  .(++)
  if ( === 3)
    ()
}, 50)

.()

// log: 1
// log: 2
// log: 3

vi.runAllTimersAsync

  • 型: () => Promise<Vitest>

このメソッドは、タイマーキューが空になるまで、開始されたすべてのタイマーを非同期的に呼び出します。つまり、runAllTimersAsync中に呼び出されたすべてのタイマー(非同期タイマーを含む)が発火します。無限のintervalがある場合、10000回の試行後にエラーをスローします(fakeTimers.loopLimitで設定できます)。

ts
(async () => {
  .(await .('result'))
}, 100)

await .()

// log: result

vi.runOnlyPendingTimers

  • 型: () => Vitest

このメソッドは、vi.useFakeTimers呼び出し後に開始されたすべてのタイマーを呼び出します。その呼び出し中に開始されたタイマーは発火しません。

ts
let  = 0
(() => .(++), 50)

.()

// log: 1

vi.runOnlyPendingTimersAsync

  • 型: () => Promise<Vitest>

このメソッドは、vi.useFakeTimers呼び出し後に開始されたすべてのタイマー(非同期タイマーを含む)を非同期的に呼び出します。その呼び出し中に開始されたタイマーは発火しません。

ts
(() => {
  .(1)
}, 100)
(() => {
  .().(() => {
    .(2)
    (() => {
      .(3)
    }, 40)
  })
}, 10)

await .()

// log: 2
// log: 3
// log: 3
// log: 1

vi.setSystemTime

  • : (date: string | number | Date) => void

疑似タイマーが有効になっている場合、このメソッドはユーザーがシステムクロックを変更したことをシミュレートします(hrtimeperformance.nownew Date()などの日付関連のAPIに影響します)。ただし、タイマーは発火しません。疑似タイマーが無効になっている場合、このメソッドはDate.*呼び出しのみをモックします。

現在の日時に依存するものをテストする必要がある場合(たとえば、コード内のLuxon呼び出し)に役立ちます。

ts
const  = new (1998, 11, 19)

.()
.()

(.()).(.())

.()

vi.useFakeTimers

  • 型: (config?: FakeTimerInstallOpts) => Vitest

タイマーのモックを有効にするには、このメソッドを呼び出す必要があります。vi.useRealTimers()が呼び出されるまで、すべてのタイマー呼び出し(setTimeoutsetIntervalclearTimeoutclearIntervalsetImmediateclearImmediateDateなど)をラップします。

--pool=forksを使用してnode:child_process内でVitestを実行している場合、nextTickのモックはサポートされていません。NodeJSはnode:child_process内で内部的にprocess.nextTickを使用しており、モックされるとハングします。--pool=threadsを使用してVitestを実行している場合、nextTickのモックはサポートされています。

実装は内部的に@sinonjs/fake-timersに基づいています。

ヒント

バージョン0.35.0以降、vi.useFakeTimers()process.nextTickを自動的にモックしなくなりました。toFake引数にオプションを指定することで、引き続きモックできます: vi.useFakeTimers({ toFake: ['nextTick'] })

vi.isFakeTimers 0.34.5+

  • 型: () => boolean

疑似タイマーが有効になっている場合はtrueを返します。

vi.useRealTimers

  • 型: () => Vitest

タイマーが実行された後、このメソッドを呼び出して、モックされたタイマーを元のimplementationに戻すことができます。それ以前にスケジュールされたすべてのタイマーは破棄されます。

その他

Vitestが提供する便利なヘルパー関数のセットです。

vi.waitFor 0.34.5+

  • 型: <T>(callback: WaitForCallback<T>, options?: number | WaitForOptions) => Promise<T>

コールバックが正常に実行されるまで待ちます。コールバックがエラーをスローするか、拒否されたPromiseを返す場合、成功するかタイムアウトするまで待ち続けます。

これは、非同期アクションが完了するのを待つ必要がある場合(たとえば、サーバーを起動して起動するのを待つ必要がある場合)に非常に便利です。

ts
import { expect, test, vi } from 'vitest'
import { createServer } from './server.js'

test('Server started successfully', async () => {
  const server = createServer()

  await vi.waitFor(
    () => {
      if (!server.isReady)
        throw new Error('Server not started')

      console.log('Server started')
    },
    {
      timeout: 500, // default is 1000
      interval: 20, // default is 50
    }
  )
  expect(server.isReady).toBe(true)
})

非同期コールバックにも対応しています。

ts
// @vitest-environment jsdom

import { expect, test, vi } from 'vitest'
import { getDOMElementAsync, populateDOMAsync } from './dom.js'

test('Element exists in a DOM', async () => {
  // start populating DOM
  populateDOMAsync()

  const element = await vi.waitFor(async () => {
    // try to get the element until it exists
    const element = await getDOMElementAsync() as HTMLElement | null
    expect(element).toBeTruthy()
    expect(element.dataset.initialized).toBeTruthy()
    return element
  }, {
    timeout: 500, // default is 1000
    interval: 20, // default is 50
  })
  expect(element).toBeInstanceOf(HTMLElement)
})

vi.useFakeTimersが使用されている場合、vi.waitForは各チェックコールバックで自動的にvi.advanceTimersByTime(interval)を呼び出します。

vi.waitUntil 0.34.5+

  • 型: <T>(callback: WaitUntilCallback<T>, options?: number | WaitUntilOptions) => Promise<T>

これはvi.waitForに似ていますが、コールバックがエラーをスローすると、実行はすぐに中断され、エラーメッセージが表示されます。コールバックがfalsyな値を返す場合、truthyな値が返されるまで次のチェックが継続されます。これは、次のステップに進む前に何かが存在するのを待つ必要がある場合に便利です。

下の例を参照してください。vi.waitUntilを使用してページに要素が表示されるのを待つことができ、その後、その要素に対して何かを実行できます。

ts
import { , ,  } from 'vitest'

('Element render correctly', async () => {
  const  = await .(
    () => .('.element'),
    {
      : 500, // default is 1000
      : 20, // default is 50
    }
  )

  // do something with the element
  (.('.element-child')).()
})

vi.hoisted 0.31.0+

  • : <T>(factory: () => T) => T

ESモジュールのすべてのstaticなimport文はファイルの先頭にhoistedされるため、importの前に定義されているコードは、実際にはimportが評価された後に実行されます。

ただし、モジュールをimportする前に、日付のモックなど、いくつかの副作用を呼び出すことが役立つ場合があります。

この制限を回避するために、staticなimportを次のようにdynamicなimportに書き換えることができます。

diff
callFunctionWithSideEffect()
- import { value } from './some/module.js'
+ const { value } = await import('./some/module.js')

vitest を実行する際、vi.hoisted メソッドを使用することでこれを自動的に行うことができます。

diff
- callFunctionWithSideEffect()
import { value } from './some/module.js'
+ vi.hoisted(() => callFunctionWithSideEffect())

このメソッドは、ファクトリから返された値を返します。ローカルで定義された変数に簡単にアクセスする必要がある場合、vi.mock ファクトリでその値を使用できます。

ts
import { expect, vi } from 'vitest'
import { originalMethod } from './path/to/module.js'

const { mockedMethod } = vi.hoisted(() => {
  return { mockedMethod: vi.fn() }
})

vi.mock('./path/to/module.js', () => {
  return { originalMethod: mockedMethod }
})

mockedMethod.mockReturnValue(100)
expect(originalMethod()).toBe(100)

このメソッドは、環境がトップレベルのawaitをサポートしていなくても、非同期的に呼び出すことができることに注意してください。

ts
const promised = await vi.hoisted(async () => {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts')
  return response.json()
})

vi.setConfig

  • : RuntimeConfig

現在のテストファイルのconfigを更新します。このメソッドは、現在のテストファイルに影響を与えるconfigオプションのみをサポートします。

ts
vi.setConfig({
  allowOnly: true,
  testTimeout: 10_000,
  hookTimeout: 10_000,
  clearMocks: true,
  restoreMocks: true,
  fakeTimers: {
    now: new Date(2021, 11, 19),
    // supports the whole object
  },
  maxConcurrency: 10,
  sequence: {
    hooks: 'stack'
    // supports only "sequence.hooks"
  }
})

vi.resetConfig

  • : RuntimeConfig

vi.setConfig が以前に呼び出された場合、これによりconfigが元の状態にリセットされます。

MITライセンスの下でリリースされています。