Skip to content
Vitest 3
Main Navigation Руководство & APIКонфигурацияРежим браузераРасширенный API
3.2.0
2.1.9
1.6.1
0.34.6

Русский

English
简体中文
繁體中文
Español
Français
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Русский

English
简体中文
繁體中文
Español
Français
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Внешний вид

Sidebar Navigation

Введение

Почему Vitest

Начало работы

Возможности

Настройка Vitest

API

Справочник по API тестирования

Мок-функции

Vi

expect

expectTypeOf

assert

assertType

Руководство

Интерфейс командной строки

Фильтрация тестов

Тестовые проекты

Средства отчётности

Покрытие кода

Снапшот-тестирование

Мокирование

Параллелизм

Тестирование типов

Vitest UI

Тестирование в исходном коде

Контекст теста

Аннотации тестов

Среда тестирования

Расширение матчеров

Интеграции с IDE

Отладка

Распространенные ошибки

Руководство по миграции

Миграция на Vitest 3.0

Миграция с Jest

Производительность

Профилирование производительности тестов

Улучшение производительности

Режим браузера

Расширенный API

Сравнение с другими тестовыми раннерами

Содержание страницы

expect ​

Следующие типы используются в приведенных ниже сигнатурах типов:

ts
type Awaitable<T> = T | PromiseLike<T>;

expect используется для создания утверждений. В этом контексте утверждения — это функции, которые можно вызывать для проверки истинности утверждения. Vitest по умолчанию предоставляет утверждения chai, а также совместимые с Jest утверждения, построенные на основе chai. В отличие от Jest, Vitest поддерживает сообщение об ошибке в качестве второго аргумента — если утверждение не выполняется, сообщение об ошибке будет содержать его.

ts
export interface ExpectStatic
  extends Chai.ExpectStatic,
    AsymmetricMatchersContaining {
  <T>(actual: T, message?: string): Assertion<T>;
  extend: (expects: MatchersObject) => void;
  anything: () => any;
  any: (constructor: unknown) => any;
  getState: () => MatcherState;
  setState: (state: Partial<MatcherState>) => void;
  not: AsymmetricMatchersContaining;
}

Например, этот код утверждает, что значение input равно 2. Если это не так, то будет выброшена ошибка, и тест завершится неудачей.

ts
import { expect } from 'vitest';

const input = Math.sqrt(4);

expect(input).to.equal(2); // chai API
expect(input).toBe(2); // jest API

Технически этот пример не использует функцию test, поэтому в консоли вы увидите ошибку Node.js вместо вывода от Vitest. Чтобы узнать больше о test, пожалуйста, прочитайте Справочник по Test API.

Также expect может использоваться статически для доступа к функциям сопоставления, описанным далее, и другим возможностям.

WARNING

expect не влияет на типы тестирования, если выражение не имеет ошибки типа. Если вы хотите использовать Vitest в качестве проверщика типов, используйте expectTypeOf или assertType.

soft ​

  • Тип: ExpectStatic & (actual: any) => Assertions

expect.soft функционирует аналогично expect, но вместо завершения теста при неудачном утверждении, он продолжает выполнение и помечает неудачу как сбой теста. Все ошибки, возникшие во время теста, будут отображены по завершении теста.

ts
import { expect, test } from 'vitest';

test('expect.soft test', () => {
  expect.soft(1 + 1).toBe(3); // отметить тест как проваленный и продолжить
  expect.soft(1 + 2).toBe(4); // отметить тест как проваленный и продолжить
});
// репортер сообщит об обеих ошибках в конце выполнения

Его также можно использовать с expect. Если утверждение expect не выполняется, тест будет прерван, и все ошибки будут выведены.

ts
import { expect, test } from 'vitest';

test('expect.soft test', () => {
  expect.soft(1 + 1).toBe(3); // отметить тест как проваленный и продолжить
  expect(1 + 2).toBe(4); // привел к сбою и прерыванию теста, все предыдущие ошибки будут выведены
  expect.soft(1 + 3).toBe(5); // не запускать
});

WARNING

expect.soft может использоваться только внутри функции test.

poll ​

ts
interface ExpectPoll extends ExpectStatic {
  (actual: () => T, options: { interval; timeout; message }): Promise<
    Assertions<T>
  >;
}

expect.poll повторно выполняет утверждение, пока оно не будет выполнено успешно. Вы можете настроить, сколько раз Vitest должен повторно запускать колбэк expect.poll, установив параметры interval и timeout.

Если внутри колбэка expect.poll выбрасывается ошибка, Vitest будет повторять попытки, пока не истечет время ожидания.

ts
import { expect, test } from 'vitest';

test('element exists', async () => {
  asyncInjectElement();

  await expect.poll(() => document.querySelector('.element')).toBeTruthy();
});

WARNING

expect.poll делает каждое утверждение асинхронным, поэтому вам нужно его ожидать. Начиная с Vitest 3, если вы забудете его ожидать, тест завершится с соответствующим предупреждением.

expect.poll не работает с несколькими сопоставителями:

  • Сопоставители снимков не поддерживаются, так как они всегда будут проходить успешно. Если ваше условие нестабильно, рассмотрите возможность использования vi.waitFor для его разрешения в первую очередь:
ts
import { expect, vi } from 'vitest';

const flakyValue = await vi.waitFor(() => getFlakyValue());
expect(flakyValue).toMatchSnapshot();
  • .resolves и .rejects не поддерживаются. expect.poll уже ожидает условие, если оно асинхронно.
  • toThrow и его псевдонимы не поддерживаются, потому что условие expect.poll всегда разрешается до того, как сопоставитель получит значение.

not ​

Использование not отрицает утверждение. Например, этот код утверждает, что значение input не равно 2. Если оно равно, утверждение выдаст ошибку, и тест завершится неудачей.

ts
import { expect, test } from 'vitest';

const input = Math.sqrt(16);

expect(input).not.to.equal(2); // chai API
expect(input).not.toBe(2); // jest API

toBe ​

  • Тип: (value: any) => Awaitable<void>

toBe можно использовать для утверждения равенства примитивов или того, что объекты имеют одну и ту же ссылку. Это эквивалентно вызову expect(Object.is(3, 3)).toBe(true). Если объекты не являются одним и тем же экземпляром, но вы хотите проверить идентичность их структур, вы можете использовать toEqual.

Например, приведенный ниже код проверяет, есть ли у торговца 13 яблок.

ts
import { expect, test } from 'vitest';

const stock = {
  type: 'apples',
  count: 13,
};

test('stock has 13 apples', () => {
  expect(stock.type).toBe('apples');
  expect(stock.count).toBe(13);
});

test('stocks are the same', () => {
  const refStock = stock; // та же ссылка

  expect(stock).toBe(refStock);
});

Старайтесь не использовать toBe с числами с плавающей запятой. Поскольку JavaScript округляет их, 0.1 + 0.2 не строго равно 0.3. Для надежного утверждения чисел с плавающей запятой используйте утверждение toBeCloseTo.

toBeCloseTo ​

  • Тип: (value: number, numDigits?: number) => Awaitable<void>

Используйте toBeCloseTo для сравнения чисел с плавающей запятой. Необязательный аргумент numDigits ограничивает количество цифр для проверки после десятичной точки. Например:

ts
import { expect, test } from 'vitest';

test.fails('decimals are not equal in javascript', () => {
  expect(0.2 + 0.1).toBe(0.3); // 0.2 + 0.1 равно 0.30000000000000004
});

test('decimals are rounded to 5 after the point', () => {
  // 0.2 + 0.1 равно 0.30000 | "000000000004" удалено
  expect(0.2 + 0.1).toBeCloseTo(0.3, 5);
  // ничего из 0.30000000000000004 не удалено
  expect(0.2 + 0.1).not.toBeCloseTo(0.3, 50);
});

toBeDefined ​

  • Тип: () => Awaitable<void>

toBeDefined утверждает, что значение не равно undefined. Полезный вариант использования — проверить, вернула ли функция какое-либо значение.

ts
import { expect, test } from 'vitest';

function getApples() {
  return 3;
}

test('function returned something', () => {
  expect(getApples()).toBeDefined();
});

toBeUndefined ​

  • Тип: () => Awaitable<void>

В отличие от toBeDefined, toBeUndefined утверждает, что значение равно undefined. Полезный вариант использования — проверить, что функция ничего не вернула.

ts
import { expect, test } from 'vitest';

function getApplesFromStock(stock: string) {
  if (stock === 'Bill') {
    return 13;
  }
}

test("mary doesn't have a stock", () => {
  expect(getApplesFromStock('Mary')).toBeUndefined();
});

toBeTruthy ​

  • Тип: () => Awaitable<void>

toBeTruthy утверждает, что значение истинно при преобразовании в логический тип. Полезно, если вам не важно конкретное значение, а лишь то, что оно может быть преобразовано в true.

Например, в данном коде вам не важно возвращаемое значение stocks.getInfo — это может быть сложный объект, строка или что-то иное. Код будет функционировать корректно.

ts
import { Stocks } from './stocks.js';

const stocks = new Stocks();
stocks.sync('Bill');
if (stocks.getInfo('Bill')) {
  stocks.sell('apples', 'Bill');
}

Итак, если вы хотите проверить, что stocks.getInfo является истинным, вы можете написать:

ts
import { expect, test } from 'vitest';
import { Stocks } from './stocks.js';

const stocks = new Stocks();

test('if we know Bill stock, sell apples to him', () => {
  stocks.sync('Bill');
  expect(stocks.getInfo('Bill')).toBeTruthy();
});

Все в JavaScript считается истинным, кроме false, null, undefined, NaN, 0, -0, 0n, "" и document.all.

toBeFalsy ​

  • Тип: () => Awaitable<void>

toBeFalsy утверждает, что значение ложно при преобразовании в логический тип. Полезно, если вам не важно само значение, а просто нужно знать, может ли оно быть преобразовано в false.

Например, имея этот код, вам не важно возвращаемое значение stocks.stockFailed — оно может вернуть любое ложное значение, но код все равно будет работать.

ts
import { Stocks } from './stocks.js';

const stocks = new Stocks();
stocks.sync('Bill');
if (!stocks.stockFailed('Bill')) {
  stocks.sell('apples', 'Bill');
}

Итак, если вы хотите проверить, что stocks.stockFailed будет ложным, вы можете написать:

ts
import { expect, test } from 'vitest';
import { Stocks } from './stocks.js';

const stocks = new Stocks();

test("if Bill stock hasn't failed, sell apples to him", () => {
  stocks.syncStocks('Bill');
  expect(stocks.stockFailed('Bill')).toBeFalsy();
});

Все в JavaScript считается истинным, кроме false, null, undefined, NaN, 0, -0, 0n, "" и document.all.

toBeNull ​

  • Тип: () => Awaitable<void>

toBeNull просто утверждает, что что-то равно null. Псевдоним для .toBe(null).

ts
import { expect, test } from 'vitest';

function apples() {
  return null;
}

test("we don't have apples", () => {
  expect(apples()).toBeNull();
});

toBeNaN ​

  • Тип: () => Awaitable<void>

toBeNaN просто утверждает, что что-то равно NaN. Псевдоним для .toBe(NaN).

ts
import { expect, test } from 'vitest';

let i = 0;

function getApplesCount() {
  i++;
  return i > 1 ? Number.NaN : i;
}

test('getApplesCount has some unusual side effects...', () => {
  expect(getApplesCount()).not.toBeNaN();
  expect(getApplesCount()).toBeNaN();
});

toBeOneOf ​

  • Тип: (sample: Array<any>) => any

toBeOneOf утверждает, что значение соответствует любому из значений в предоставленном массиве.

ts
import { expect, test } from 'vitest';

test('fruit is one of the allowed values', () => {
  expect(fruit).toBeOneOf(['apple', 'banana', 'orange']);
});

Асимметричный сопоставитель особенно полезен при тестировании необязательных свойств, которые могут быть либо null, либо undefined:

ts
test('optional properties can be null or undefined', () => {
  const user = {
    firstName: 'John',
    middleName: undefined,
    lastName: 'Doe',
  };

  expect(user).toEqual({
    firstName: expect.any(String),
    middleName: expect.toBeOneOf([expect.any(String), undefined]),
    lastName: expect.any(String),
  });
});

TIP

Вы можете использовать expect.not с этим сопоставителем, чтобы убедиться, что значение НЕ соответствует ни одному из предоставленных вариантов.

toBeTypeOf ​

  • Тип: (c: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined') => Awaitable<void>

toBeTypeOf утверждает, что фактическое значение имеет тип полученного типа.

ts
import { expect, test } from 'vitest';

const actual = 'stock';

test('stock is type of string', () => {
  expect(actual).toBeTypeOf('string');
});

toBeInstanceOf ​

  • Тип: (c: any) => Awaitable<void>

toBeInstanceOf утверждает, что фактическое значение является экземпляром полученного класса.

ts
import { expect, test } from 'vitest';
import { Stocks } from './stocks.js';

const stocks = new Stocks();

test('stocks are instance of Stocks', () => {
  expect(stocks).toBeInstanceOf(Stocks);
});

toBeGreaterThan ​

  • Тип: (n: number | bigint) => Awaitable<void>

toBeGreaterThan утверждает, что фактическое значение больше полученного. Равные значения приведут к ошибке теста.

ts
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';

test('have more then 10 apples', () => {
  expect(getApples()).toBeGreaterThan(10);
});

toBeGreaterThanOrEqual ​

  • Тип: (n: number | bigint) => Awaitable<void>

toBeGreaterThanOrEqual утверждает, что фактическое значение больше или равно полученному.

ts
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';

test('have 11 apples or more', () => {
  expect(getApples()).toBeGreaterThanOrEqual(11);
});

toBeLessThan ​

  • Тип: (n: number | bigint) => Awaitable<void>

toBeLessThan утверждает, что фактическое значение меньше полученного. Равные значения приведут к ошибке теста.

ts
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';

test('have less then 20 apples', () => {
  expect(getApples()).toBeLessThan(20);
});

toBeLessThanOrEqual ​

  • Тип: (n: number | bigint) => Awaitable<void>

toBeLessThanOrEqual утверждает, что фактическое значение меньше или равно полученному.

ts
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';

test('have 11 apples or less', () => {
  expect(getApples()).toBeLessThanOrEqual(11);
});

toEqual ​

  • Тип: (received: any) => Awaitable<void>

toEqual утверждает, что фактическое значение равно полученному или имеет ту же структуру, если это объект (сравнивает их рекурсивно). Вы можете увидеть разницу между toEqual и toBe в этом примере:

ts
import { expect, test } from 'vitest';

const stockBill = {
  type: 'apples',
  count: 13,
};

const stockMary = {
  type: 'apples',
  count: 13,
};

test('stocks have the same properties', () => {
  expect(stockBill).toEqual(stockMary);
});

test('stocks are not the same', () => {
  expect(stockBill).not.toBe(stockMary);
});

WARNING

Для объектов Error также сравниваются неперечисляемые свойства, такие как name, message, cause и AggregateError.errors. Для Error.cause сравнение выполняется асимметрично:

ts
// успех
expect(new Error('hi', { cause: 'x' })).toEqual(new Error('hi'));

// неудача
expect(new Error('hi')).toEqual(new Error('hi', { cause: 'x' }));

Чтобы проверить, было ли что-то выброшено, используйте утверждение toThrowError.

toStrictEqual ​

  • Тип: (received: any) => Awaitable<void>

toStrictEqual утверждает, что фактическое значение равно полученному или имеет ту же структуру, если это объект (сравнивает их рекурсивно), и того же типа.

Отличия от .toEqual:

  • Проверяются ключи со свойствами undefined. Например, {a: undefined, b: 2} не соответствует {b: 2} при использовании .toStrictEqual.
  • Проверяется разреженность массива. Например, [, 1] не соответствует [undefined, 1] при использовании .toStrictEqual.
  • Типы объектов проверяются на равенство. Например, экземпляр класса с полями a и b не будет равен литеральному объекту с полями a и b.
ts
import { expect, test } from 'vitest';

class Stock {
  constructor(type) {
    this.type = type;
  }
}

test('structurally the same, but semantically different', () => {
  expect(new Stock('apples')).toEqual({ type: 'apples' });
  expect(new Stock('apples')).not.toStrictEqual({ type: 'apples' });
});

toContain ​

  • Тип: (received: string) => Awaitable<void>

toContain утверждает, что фактическое значение находится в массиве. toContain также может проверять, является ли строка подстрокой другой строки. Если вы запускаете тесты в браузере, это утверждение также может проверять, содержится ли класс в classList или один элемент внутри другого.

ts
import { expect, test } from 'vitest';
import { getAllFruits } from './stocks.js';

test('the fruit list contains orange', () => {
  expect(getAllFruits()).toContain('orange');

  const element = document.querySelector('#el');
  // элемент содержит класс
  expect(element.classList).toContain('flex');
  // элемент является дочерним по отношению к другому
  expect(document.querySelector('#wrapper')).toContain(element);
});

toContainEqual ​

  • Тип: (received: any) => Awaitable<void>

toContainEqual утверждает, что элемент с определенной структурой и значениями содержится в массиве. Он работает аналогично toEqual для каждого элемента.

ts
import { expect, test } from 'vitest';
import { getFruitStock } from './stocks.js';

test('apple available', () => {
  expect(getFruitStock()).toContainEqual({ fruit: 'apple', count: 5 });
});

toHaveLength ​

  • Тип: (received: number) => Awaitable<void>

toHaveLength утверждает, что объект имеет свойство .length и оно установлено на определенное числовое значение.

ts
import { expect, test } from 'vitest';

test('toHaveLength', () => {
  expect('abc').toHaveLength(3);
  expect([1, 2, 3]).toHaveLength(3);

  expect('').not.toHaveLength(3); // длина не равна 3
  expect({ length: 3 }).toHaveLength(3);
});

toHaveProperty ​

  • Тип: (key: any, received?: any) => Awaitable<void>

toHaveProperty утверждает, что свойство по предоставленному ключу key существует для объекта.

Вы также можете предоставить необязательный аргумент значения, который используется для глубокого сравнения полученного значения свойства, аналогично сопоставителю toEqual.

ts
import { expect, test } from 'vitest';

const invoice = {
  isActive: true,
  'P.O': '12345',
  customer: {
    first_name: 'John',
    last_name: 'Doe',
    location: 'China',
  },
  total_amount: 5000,
  items: [
    {
      type: 'apples',
      quantity: 10,
    },
    {
      type: 'oranges',
      quantity: 5,
    },
  ],
};

test('John Doe Invoice', () => {
  expect(invoice).toHaveProperty('isActive'); // проверяет существование ключа
  expect(invoice).toHaveProperty('total_amount', 5000); // утверждает, что ключ существует и значение равно

  expect(invoice).not.toHaveProperty('account'); // проверяет отсутствие этого ключа

  // Доступ к вложенным свойствам с использованием точечной нотации
  expect(invoice).toHaveProperty('customer.first_name');
  expect(invoice).toHaveProperty('customer.last_name', 'Doe');
  expect(invoice).not.toHaveProperty('customer.location', 'India');

  // Глубокая ссылка с использованием массива, содержащего ключ
  expect(invoice).toHaveProperty('items[0].type', 'apples');
  expect(invoice).toHaveProperty('items.0.type', 'apples'); // точечная нотация также работает

  // Глубокая ссылка с использованием массива, содержащего keyPath
  expect(invoice).toHaveProperty(['items', 0, 'type'], 'apples');
  expect(invoice).toHaveProperty(['items', '0', 'type'], 'apples'); // строковая нотация также работает

  // Оберните ключ в массив, чтобы предотвратить его интерпретацию как глубокой ссылки
  expect(invoice).toHaveProperty(['P.O'], '12345');
});

toMatch ​

  • Тип: (received: string | regexp) => Awaitable<void>

toMatch утверждает, что строка соответствует регулярному выражению или строке.

ts
import { expect, test } from 'vitest';

test('top fruits', () => {
  expect('top fruits include apple, orange and grape').toMatch(/apple/);
  expect('applefruits').toMatch('fruit'); // toMatch также может принимать строку
});

toMatchObject ​

  • Тип: (received: object | array) => Awaitable<void>

toMatchObject утверждает, что объект соответствует подмножеству свойств объекта.

Вы также можете передать массив объектов. Это полезно, если вы хотите проверить точное совпадение двух массивов по количеству элементов, в отличие от arrayContaining, который допускает наличие дополнительных элементов в проверяемом массиве.

ts
import { expect, test } from 'vitest';

const johnInvoice = {
  isActive: true,
  customer: {
    first_name: 'John',
    last_name: 'Doe',
    location: 'China',
  },
  total_amount: 5000,
  items: [
    {
      type: 'apples',
      quantity: 10,
    },
    {
      type: 'oranges',
      quantity: 5,
    },
  ],
};

const johnDetails = {
  customer: {
    first_name: 'John',
    last_name: 'Doe',
    location: 'China',
  },
};

test('invoice has john personal details', () => {
  expect(johnInvoice).toMatchObject(johnDetails);
});

test('the number of elements must match exactly', () => {
  // Проверка соответствия массива объектов
  expect([{ foo: 'bar' }, { baz: 1 }]).toMatchObject([
    { foo: 'bar' },
    { baz: 1 },
  ]);
});

toThrowError ​

  • Тип: (received: any) => Awaitable<void>

  • Псевдоним: toThrow

toThrowError утверждает, что функция выбрасывает ошибку при вызове.

Вы можете предоставить необязательный аргумент для проверки того, что выбрасывается конкретная ошибка:

  • RegExp: сообщение об ошибке соответствует шаблону
  • string: сообщение об ошибке содержит подстроку
  • Error, AsymmetricMatcher: сравнение с полученным объектом аналогично toEqual(received)

TIP

Вы должны обернуть код в функцию, иначе ошибка не будет перехвачена, и тест провалится.

Это не относится к асинхронным вызовам, так как rejects корректно обрабатывает промисы:

ts
test('expect rejects toThrow', async ({ expect }) => {
  const promise = Promise.reject(new Error('Test'));
  await expect(promise).rejects.toThrowError();
});

Например, если мы хотим проверить, что getFruitStock('pineapples') выбрасывает ошибку, мы можем написать:

ts
import { expect, test } from 'vitest';

function getFruitStock(type: string) {
  if (type === 'pineapples') {
    throw new Error('Pineapples are not in stock');
  }

  // Выполнить другие действия
}

test('throws on pineapples', () => {
  // Проверить, что сообщение об ошибке содержит подстроку "stock": следующие утверждения эквивалентны
  expect(() => getFruitStock('pineapples')).toThrowError(/stock/);
  expect(() => getFruitStock('pineapples')).toThrowError('stock');

  // Проверить точное сообщение об ошибке
  expect(() => getFruitStock('pineapples')).toThrowError(
    /^Pineapples are not in stock$/
  );

  expect(() => getFruitStock('pineapples')).toThrowError(
    new Error('Pineapples are not in stock')
  );
  expect(() => getFruitStock('pineapples')).toThrowError(
    expect.objectContaining({
      message: 'Pineapples are not in stock',
    })
  );
});

TIP

Для тестирования асинхронных функций используйте в сочетании с rejects.

js
function getAsyncFruitStock() {
  return Promise.reject(new Error('empty'));
}

test('throws on pineapples', async () => {
  await expect(() => getAsyncFruitStock()).rejects.toThrowError('empty');
});

toMatchSnapshot ​

  • Тип: <T>(shape?: Partial<T> | string, hint?: string) => void

Это гарантирует, что значение соответствует актуальному снимку.

Вы можете предоставить необязательный строковый аргумент hint, который добавляется к имени теста. Хотя Vitest всегда добавляет число в конец имени снимка, короткие описательные подсказки могут быть более полезными, чем числа, для однозначной идентификации нескольких снимков в одном блоке it или test. Vitest сортирует снимки по имени в соответствующем файле .snap.

TIP

Когда снимок не совпадает и приводит к сбою теста, если несоответствие ожидаемо, вы можете нажать клавишу u для однократного обновления снимка. Или вы можете передать параметры CLI -u или --update, чтобы Vitest всегда обновлял тесты.

ts
import { expect, test } from 'vitest';

test('matches snapshot', () => {
  const data = { foo: new Set(['bar', 'snapshot']) };
  expect(data).toMatchSnapshot();
});

Вы также можете предоставить шаблон объекта, если вы тестируете только его структуру и не требуете 100% соответствия:

ts
import { expect, test } from 'vitest';

test('matches snapshot', () => {
  const data = { foo: new Set(['bar', 'snapshot']) };
  expect(data).toMatchSnapshot({ foo: expect.any(Set) });
});

toMatchInlineSnapshot ​

  • Тип: <T>(shape?: Partial<T> | string, snapshot?: string, hint?: string) => void

Это гарантирует, что значение соответствует актуальному снимку.

Vitest добавляет и обновляет строковый аргумент inlineSnapshot непосредственно в файле теста (вместо внешнего файла .snap).

ts
import { expect, test } from 'vitest';

test('matches inline snapshot', () => {
  const data = { foo: new Set(['bar', 'snapshot']) };
  // Vitest обновит следующее содержимое при обновлении снимка
  expect(data).toMatchInlineSnapshot(`
    {
      "foo": Set {
        "bar",
        "snapshot",
      },
    }
  `);
});

Вы также можете предоставить шаблон объекта, если вы тестируете только его структуру и не требуете 100% соответствия:

ts
import { expect, test } from 'vitest';

test('matches snapshot', () => {
  const data = { foo: new Set(['bar', 'snapshot']) };
  expect(data).toMatchInlineSnapshot(
    { foo: expect.any(Set) },
    `
    {
      "foo": Any<Set>,
    }
  `
  );
});

toMatchFileSnapshot ​

  • Тип: <T>(filepath: string, hint?: string) => Promise<void>

Сравнить или обновить снимок с содержимым явно указанного файла (вместо файла .snap).

ts
import { expect, it } from 'vitest';

it('render basic', async () => {
  const result = renderHTML(h('div', { class: 'foo' }));
  await expect(result).toMatchFileSnapshot('./test/basic.output.html');
});

Обратите внимание, что поскольку операция с файловой системой является асинхронной, вам нужно использовать await с toMatchFileSnapshot(). Если await не используется, Vitest обрабатывает это как expect.soft, то есть код после оператора продолжит выполняться, даже если снимок не совпадает. После завершения теста Vitest проверит снимок и завершится неудачей, если есть несоответствие.

toThrowErrorMatchingSnapshot ​

  • Тип: (hint?: string) => void

То же, что и toMatchSnapshot, но ожидает то же значение, что и toThrowError.

toThrowErrorMatchingInlineSnapshot ​

  • Тип: (snapshot?: string, hint?: string) => void

То же, что и toMatchInlineSnapshot, но ожидает то же значение, что и toThrowError.

toHaveBeenCalled ​

  • Тип: () => Awaitable<void>

Это утверждение полезно для проверки того, что функция была вызвана. Для использования этого утверждения необходимо передать функцию-шпион в expect.

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('spy function', () => {
  const buySpy = vi.spyOn(market, 'buy');

  expect(buySpy).not.toHaveBeenCalled();

  market.buy('apples', 10);

  expect(buySpy).toHaveBeenCalled();
});

toHaveBeenCalledTimes ​

  • Тип: (amount: number) => Awaitable<void>

Это утверждение проверяет, была ли функция вызвана указанное количество раз. Для использования этого утверждения необходимо передать функцию-шпион в expect.

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('spy function called two times', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);
  market.buy('apples', 20);

  expect(buySpy).toHaveBeenCalledTimes(2);
});

toHaveBeenCalledWith ​

  • Тип: (...args: any[]) => Awaitable<void>

Это утверждение проверяет, была ли функция вызвана хотя бы один раз с заданными параметрами. Для использования этого утверждения необходимо передать функцию-шпион в expect.

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('spy function', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);
  market.buy('apples', 20);

  expect(buySpy).toHaveBeenCalledWith('apples', 10);
  expect(buySpy).toHaveBeenCalledWith('apples', 20);
});

toHaveBeenCalledBefore 3.0.0+ ​

  • Тип: (mock: MockInstance, failIfNoFirstInvocation?: boolean) => Awaitable<void>

Это утверждение проверяет, был ли один Mock вызван раньше другого Mock.

ts
test('calls mock1 before mock2', () => {
  const mock1 = vi.fn();
  const mock2 = vi.fn();

  mock1();
  mock2();
  mock1();

  expect(mock1).toHaveBeenCalledBefore(mock2);
});

toHaveBeenCalledAfter 3.0.0+ ​

  • Тип: (mock: MockInstance, failIfNoFirstInvocation?: boolean) => Awaitable<void>

Это утверждение проверяет, был ли один Mock вызван после другого Mock.

ts
test('calls mock1 after mock2', () => {
  const mock1 = vi.fn();
  const mock2 = vi.fn();

  mock2();
  mock1();
  mock2();

  expect(mock1).toHaveBeenCalledAfter(mock2);
});

toHaveBeenCalledExactlyOnceWith 3.0.0+ ​

  • Тип: (...args: any[]) => Awaitable<void>

Это утверждение проверяет, была ли функция вызвана ровно один раз и именно с заданными параметрами. Для использования этого утверждения необходимо передать функцию-шпион в expect.

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('spy function', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);

  expect(buySpy).toHaveBeenCalledExactlyOnceWith('apples', 10);
});

toHaveBeenLastCalledWith ​

  • Тип: (...args: any[]) => Awaitable<void>

Это утверждение проверяет, была ли функция вызвана с определенными параметрами при ее последнем вызове. Для использования этого утверждения необходимо передать функцию-шпион в expect.

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('spy function', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);
  market.buy('apples', 20);

  expect(buySpy).not.toHaveBeenLastCalledWith('apples', 10);
  expect(buySpy).toHaveBeenLastCalledWith('apples', 20);
});

toHaveBeenNthCalledWith ​

  • Тип: (time: number, ...args: any[]) => Awaitable<void>

Это утверждение проверяет, была ли функция вызвана с определенными параметрами в определенное время. Отсчет начинается с 1. Таким образом, чтобы проверить второй вызов, вы должны написать .toHaveBeenNthCalledWith(2, ...).

Для использования этого утверждения необходимо передать функцию-шпион в expect.

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('first call of spy function called with right params', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);
  market.buy('apples', 20);

  expect(buySpy).toHaveBeenNthCalledWith(1, 'apples', 10);
});

toHaveReturned ​

  • Тип: () => Awaitable<void>

Это утверждение проверяет, успешно ли функция вернула значение хотя бы один раз (т.е. не вызвала ошибку). Для использования этого утверждения необходимо передать функцию-шпион в expect.

ts
import { expect, test, vi } from 'vitest';

function getApplesPrice(amount: number) {
  const PRICE = 10;
  return amount * PRICE;
}

test('spy function returned a value', () => {
  const getPriceSpy = vi.fn(getApplesPrice);

  const price = getPriceSpy(10);

  expect(price).toBe(100);
  expect(getPriceSpy).toHaveReturned();
});

toHaveReturnedTimes ​

  • Тип: (amount: number) => Awaitable<void>

Это утверждение проверяет, успешно ли функция вернула значение ровно указанное количество раз (т.е. не вызвала ошибку). Для использования этого утверждения необходимо передать функцию-шпион в expect.

ts
import { expect, test, vi } from 'vitest';

test('spy function returns a value two times', () => {
  const sell = vi.fn((product: string) => ({ product }));

  sell('apples');
  sell('bananas');

  expect(sell).toHaveReturnedTimes(2);
});

toHaveReturnedWith ​

  • Тип: (returnValue: any) => Awaitable<void>

Вы можете вызвать это утверждение, чтобы проверить, успешно ли функция вернула значение с заданными параметрами хотя бы один раз. Для использования этого утверждения необходимо передать функцию-шпион в expect.

ts
import { expect, test, vi } from 'vitest';

test('spy function returns a product', () => {
  const sell = vi.fn((product: string) => ({ product }));

  sell('apples');

  expect(sell).toHaveReturnedWith({ product: 'apples' });
});

toHaveLastReturnedWith ​

  • Тип: (returnValue: any) => Awaitable<void>

Вы можете вызвать это утверждение, чтобы проверить, успешно ли функция вернула заданное значение при последнем вызове. Для использования этого утверждения необходимо передать функцию-шпион в expect.

ts
import { expect, test, vi } from 'vitest';

test('spy function returns bananas on a last call', () => {
  const sell = vi.fn((product: string) => ({ product }));

  sell('apples');
  sell('bananas');

  expect(sell).toHaveLastReturnedWith({ product: 'bananas' });
});

toHaveNthReturnedWith ​

  • Тип: (time: number, returnValue: any) => Awaitable<void>

Вы можете вызвать это утверждение, чтобы проверить, успешно ли функция вернула значение с заданными параметрами при конкретном вызове. Для использования этого утверждения необходимо передать функцию-шпион в expect.

ts
import { expect, test, vi } from 'vitest';

test('spy function returns bananas on second call', () => {
  const sell = vi.fn((product: string) => ({ product }));

  sell('apples');
  sell('bananas');

  expect(sell).toHaveNthReturnedWith(2, { product: 'bananas' });
});

toHaveResolved ​

  • Тип: () => Awaitable<void>

Это утверждение проверяет, успешно ли функция разрешила значение хотя бы один раз (т.е. не была отклонена). Для использования этого утверждения необходимо передать функцию-шпион в expect.

Если функция вернула промис, но он еще не был разрешен, это вызовет ошибку.

ts
import { expect, test, vi } from 'vitest';
import db from './db/apples.js';

async function getApplesPrice(amount: number) {
  return amount * (await db.get('price'));
}

test('spy function resolved a value', async () => {
  const getPriceSpy = vi.fn(getApplesPrice);

  const price = await getPriceSpy(10);

  expect(price).toBe(100);
  expect(getPriceSpy).toHaveResolved();
});

toHaveResolvedTimes ​

  • Тип: (amount: number) => Awaitable<void>

Это утверждение проверяет, успешно ли функция разрешила значение ровно указанное количество раз (т.е. не была отклонена). Для использования этого утверждения необходимо передать функцию-шпион в expect.

Это будет считать только разрешенные промисы. Если функция вернула промис, но он еще не был разрешен, он не будет учтен.

ts
import { expect, test, vi } from 'vitest';

test('spy function resolved a value two times', async () => {
  const sell = vi.fn((product: string) => Promise.resolve({ product }));

  await sell('apples');
  await sell('bananas');

  expect(sell).toHaveResolvedTimes(2);
});

toHaveResolvedWith ​

  • Тип: (returnValue: any) => Awaitable<void>

Вы можете вызвать это утверждение, чтобы проверить, успешно ли функция разрешила заданное значение хотя бы один раз. Для использования этого утверждения необходимо передать функцию-шпион в expect.

Если функция вернула промис, но он еще не был разрешен, это вызовет ошибку.

ts
import { expect, test, vi } from 'vitest';

test('spy function resolved a product', async () => {
  const sell = vi.fn((product: string) => Promise.resolve({ product }));

  await sell('apples');

  expect(sell).toHaveResolvedWith({ product: 'apples' });
});

toHaveLastResolvedWith ​

  • Тип: (returnValue: any) => Awaitable<void>

Вы можете вызвать это утверждение, чтобы проверить, успешно ли функция разрешила заданное значение при последнем вызове. Для использования этого утверждения необходимо передать функцию-шпион в expect.

Если функция вернула промис, но он еще не был разрешен, это вызовет ошибку.

ts
import { expect, test, vi } from 'vitest';

test('spy function resolves bananas on a last call', async () => {
  const sell = vi.fn((product: string) => Promise.resolve({ product }));

  await sell('apples');
  await sell('bananas');

  expect(sell).toHaveLastResolvedWith({ product: 'bananas' });
});

toHaveNthResolvedWith ​

  • Тип: (time: number, returnValue: any) => Awaitable<void>

Вы можете вызвать это утверждение, чтобы проверить, успешно ли функция разрешила заданное значение при конкретном вызове. Для использования этого утверждения необходимо передать функцию-шпион в expect.

Если функция вернула промис, но он еще не был разрешен, это вызовет ошибку.

ts
import { expect, test, vi } from 'vitest';

test('spy function returns bananas on second call', async () => {
  const sell = vi.fn((product: string) => Promise.resolve({ product }));

  await sell('apples');
  await sell('bananas');

  expect(sell).toHaveNthResolvedWith(2, { product: 'bananas' });
});

toSatisfy ​

  • Тип: (predicate: (value: any) => boolean) => Awaitable<void>

Это утверждение проверяет, удовлетворяет ли значение определенному предикату.

ts
import { describe, expect, it } from 'vitest';

const isOdd = (value: number) => value % 2 !== 0;

describe('toSatisfy()', () => {
  it('pass with 0', () => {
    expect(1).toSatisfy(isOdd);
  });

  it('pass with negation', () => {
    expect(2).not.toSatisfy(isOdd);
  });
});

resolves ​

  • Тип: Promisify<Assertions>

resolves предназначен для удаления шаблонного кода при утверждении асинхронного кода. Используйте его для извлечения значения из ожидающего промиса и утверждения его значения с помощью обычных утверждений. Если промис отклоняется, утверждение завершится неудачей.

Он возвращает тот же объект Assertions, но все сопоставители теперь возвращают Promise, поэтому вам нужно будет его await. Также работает с утверждениями chai.

Например, если у вас есть функция, которая делает вызов API и возвращает некоторые данные, вы можете использовать этот код для утверждения ее возвращаемого значения:

ts
import { expect, test } from 'vitest';

async function buyApples() {
  return fetch('/buy/apples').then(r => r.json());
}

test('buyApples returns new stock id', async () => {
  // toEqual теперь возвращает промис, поэтому вы ОБЯЗАНЫ его ожидать
  await expect(buyApples()).resolves.toEqual({ id: 1 }); // jest API
  await expect(buyApples()).resolves.to.equal({ id: 1 }); // chai API
});

WARNING

Если утверждение не ожидается, то у вас будет ложноположительный тест, который будет проходить каждый раз. Чтобы убедиться, что утверждения действительно вызываются, вы можете использовать expect.assertions(number).

Начиная с Vitest 3, если метод не ожидается, Vitest покажет предупреждение в конце теста. В Vitest 4 тест будет помечен как "неудачный", если утверждение не ожидается.

rejects ​

  • Тип: Promisify<Assertions>

rejects предназначен для удаления шаблонного кода при утверждении асинхронного кода. Используйте его для извлечения причины отклонения промиса и утверждения его значения с помощью обычных утверждений. Если промис успешно разрешается, утверждение завершится неудачей.

Он возвращает тот же объект Assertions, но все сопоставители теперь возвращают Promise, поэтому вам нужно будет его await. Также работает с утверждениями chai.

Например, если у вас есть функция, которая завершается сбоем при вызове, вы можете использовать этот код для утверждения причины:

ts
import { expect, test } from 'vitest';

async function buyApples(id) {
  if (!id) {
    throw new Error('no id');
  }
}

test('buyApples throws an error when no id provided', async () => {
  // toThrow теперь возвращает промис, поэтому вы ОБЯЗАНЫ его ожидать
  await expect(buyApples()).rejects.toThrow('no id');
});

WARNING

Если утверждение не ожидается, то у вас будет ложноположительный тест, который будет проходить каждый раз. Чтобы убедиться, что утверждения действительно вызывались, вы можете использовать expect.assertions(number).

Начиная с Vitest 3, если метод не ожидается, Vitest покажет предупреждение в конце теста. В Vitest 4 тест будет помечен как "неудачный", если утверждение не ожидается.

expect.assertions ​

  • Тип: (count: number) => void

После завершения теста (успешного или неуспешного) проверьте, что во время теста было вызвано определенное количество утверждений. Это полезно для проверки вызова асинхронного кода.

Например, если у нас есть функция, которая асинхронно вызывает два сопоставителя, мы можем утверждать, что они действительно были вызваны.

ts
import { expect, test } from 'vitest';

async function doAsync(...cbs) {
  await Promise.all(cbs.map((cb, index) => cb({ index })));
}

test('all assertions are called', async () => {
  expect.assertions(2);
  function callback1(data) {
    expect(data).toBeTruthy();
  }
  function callback2(data) {
    expect(data).toBeTruthy();
  }

  await doAsync(callback1, callback2);
});

WARNING

При использовании assertions с асинхронными параллельными тестами, expect из локального Test Context должен использоваться для корректного определения соответствующего теста.

expect.hasAssertions ​

  • Тип: () => void

После завершения теста (успешного или неуспешного) проверьте, что во время теста было вызвано хотя бы одно утверждение. Это полезно для проверки вызова асинхронного кода.

Например, если у вас есть код, который вызывает колбэк, мы можем сделать утверждение внутри этого колбэка. Однако тест всегда будет проходить, если мы не проверим, было ли это утверждение фактически вызвано.

ts
import { expect, test } from 'vitest';
import { db } from './db.js';

const cbs = [];

function onSelect(cb) {
  cbs.push(cb);
}

// после выбора из db, мы вызываем все колбэки
function select(id) {
  return db.select({ id }).then(data => {
    return Promise.all(cbs.map(cb => cb(data)));
  });
}

test('callback was called', async () => {
  expect.hasAssertions();
  onSelect(data => {
    // должно быть вызвано при выборе
    expect(data).toBeTruthy();
  });
  // если не ожидается, тест завершится неудачей
  // если у вас нет expect.hasAssertions(), тест пройдет
  await select(3);
});

expect.unreachable ​

  • Тип: (message?: string) => never

Этот метод используется для утверждения, что данная строка кода никогда не должна быть достигнута.

Например, если мы хотим проверить, что build() выбрасывает ошибку из-за того, что в принимающих каталогах нет папки src, а также обрабатывать каждую ошибку отдельно, мы можем сделать это:

ts
import { expect, test } from 'vitest';

async function build(dir) {
  if (dir.includes('no-src')) {
    throw new Error(`${dir}/src does not exist`);
  }
}

const errorDirs = [
  'no-src-folder',
  // ...
];

test.each(errorDirs)('build fails with "%s"', async dir => {
  try {
    await build(dir);
    expect.unreachable('Should not pass build');
  } catch (err: any) {
    expect(err).toBeInstanceOf(Error);
    expect(err.stack).toContain('build');

    switch (dir) {
      case 'no-src-folder':
        expect(err.message).toBe(`${dir}/src does not exist`);
        break;
      default:
        // для обработки всех возможных ошибок
        expect.unreachable('All error test must be handled');
        break;
    }
  }
});

expect.anything ​

  • Тип: () => any

Этот асимметричный сопоставитель, при использовании с проверкой равенства, всегда будет возвращать true. Полезно, если вы хотите убедиться в существовании свойства.

ts
import { expect, test } from 'vitest';

test('object has "apples" key', () => {
  expect({ apples: 22 }).toEqual({ apples: expect.anything() });
});

expect.any ​

  • Тип: (constructor: unknown) => any

Этот асимметричный сопоставитель, при использовании с проверкой равенства, вернет true только в том случае, если значение является экземпляром указанного конструктора. Полезно, если у вас есть значение, которое генерируется каждый раз, и вы хотите лишь убедиться, что оно существует и имеет правильный тип.

ts
import { expect, test } from 'vitest';
import { generateId } from './generators.js';

test('"id" is a number', () => {
  expect({ id: generateId() }).toEqual({ id: expect.any(Number) });
});

expect.closeTo ​

  • Тип: (expected: any, precision?: number) => any

expect.closeTo полезен при сравнении чисел с плавающей запятой в свойствах объектов или элементах массивов. Если вам нужно сравнить число, используйте вместо этого .toBeCloseTo.

Необязательный аргумент precision ограничивает количество цифр для проверки после десятичной точки. Для значения по умолчанию 2 критерий проверки равенства равен Math.abs(expected - received) < 0.005 (то есть, 10 ** -2 / 2).

Например, этот тест проходит с точностью до 5 знаков:

js
test('compare float in object properties', () => {
  expect({
    title: '0.1 + 0.2',
    sum: 0.1 + 0.2,
  }).toEqual({
    title: '0.1 + 0.2',
    sum: expect.closeTo(0.3, 5),
  });
});

expect.arrayContaining ​

  • Тип: <T>(expected: T[]) => any

При использовании в проверке равенства этот асимметричный сопоставитель вернет true, если значение является массивом и содержит указанные элементы.

ts
import { expect, test } from 'vitest';

test('basket includes fuji', () => {
  const basket = {
    varieties: ['Empire', 'Fuji', 'Gala'],
    count: 3,
  };
  expect(basket).toEqual({
    count: 3,
    varieties: expect.arrayContaining(['Fuji']),
  });
});

TIP

Вы можете использовать expect.not с этим сопоставителем, чтобы отрицать ожидаемое значение.

expect.objectContaining ​

  • Тип: (expected: any) => any

При использовании в проверке равенства этот асимметричный сопоставитель вернет true, если значение имеет похожую структуру.

ts
import { expect, test } from 'vitest';

test('basket has empire apples', () => {
  const basket = {
    varieties: [
      {
        name: 'Empire',
        count: 1,
      },
    ],
  };
  expect(basket).toEqual({
    varieties: [expect.objectContaining({ name: 'Empire' })],
  });
});

TIP

Вы можете использовать expect.not с этим сопоставителем, чтобы отрицать ожидаемое значение.

expect.stringContaining ​

  • Тип: (expected: any) => any

При использовании в проверке равенства этот асимметричный сопоставитель вернет true, если значение является строкой и содержит указанную подстроку.

ts
import { expect, test } from 'vitest';

test('variety has "Emp" in its name', () => {
  const variety = {
    name: 'Empire',
    count: 1,
  };
  expect(variety).toEqual({
    name: expect.stringContaining('Emp'),
    count: 1,
  });
});

TIP

Вы можете использовать expect.not с этим сопоставителем, чтобы отрицать ожидаемое значение.

expect.stringMatching ​

  • Тип: (expected: any) => any

При использовании в проверке равенства этот асимметричный сопоставитель вернет true, если значение является строкой и содержит указанную подстроку или соответствует регулярному выражению.

ts
import { expect, test } from 'vitest';

test('variety ends with "re"', () => {
  const variety = {
    name: 'Empire',
    count: 1,
  };
  expect(variety).toEqual({
    name: expect.stringMatching(/re$/),
    count: 1,
  });
});

TIP

Вы можете использовать expect.not с этим сопоставителем, чтобы отрицать ожидаемое значение.

expect.addSnapshotSerializer ​

  • Тип: (plugin: PrettyFormatPlugin) => void

Этот метод добавляет пользовательские сериализаторы, используемые при создании снимка. Это расширенная возможность — если вы хотите узнать больше, пожалуйста, прочитайте руководство по пользовательским сериализаторам.

Если вы добавляете пользовательские сериализаторы, вы должны вызвать этот метод внутри setupFiles. Это затронет все снимки.

TIP

Если вы ранее использовали Vue CLI с Jest, вы можете установить jest-serializer-vue. В противном случае ваши снимки будут обернуты в строку, что приведет к экранированию символа " .

expect.extend ​

  • Тип: (matchers: MatchersObject) => void

Вы можете расширить стандартные сопоставители. Эта функция используется для расширения набора сопоставителей пользовательскими сопоставителями.

Таким образом, при определении сопоставителей вы также создаете асимметричные сопоставители, которые можно использовать, например, с expect.stringContaining.

ts
import { expect, test } from 'vitest';

test('custom matchers', () => {
  expect.extend({
    toBeFoo: (received, expected) => {
      if (received !== 'foo') {
        return {
          message: () => `expected ${received} to be foo`,
          pass: false,
        };
      }
    },
  });

  expect('foo').toBeFoo();
  expect({ foo: 'foo' }).toEqual({ foo: expect.toBeFoo() });
});

TIP

Если вы хотите, чтобы ваши сопоставители были доступны в каждом тесте, вы должны вызвать этот метод внутри setupFiles.

Эта функция совместима с expect.extend из Jest, поэтому любая библиотека, использующая ее для создания пользовательских сопоставителей, будет работать с Vitest.

Если вы используете TypeScript, начиная с Vitest 0.31.0 вы можете расширить стандартный интерфейс Assertion в файле объявлений типов (например, vitest.d.ts) с помощью следующего кода:

ts
interface CustomMatchers<R = unknown> {
  toBeFoo: () => R;
}

declare module 'vitest' {
  interface Assertion<T = any> extends CustomMatchers<T> {}
  interface AsymmetricMatchersContaining extends CustomMatchers {}
}

WARNING

Не забудьте включить файл объявлений типов в ваш tsconfig.json.

TIP

Если вы хотите узнать больше, ознакомьтесь с руководством по расширению сопоставителей.

expect.addEqualityTesters ​

  • Тип: (tester: Array<Tester>) => void

Вы можете использовать этот метод для определения пользовательских тестеров — методов, используемых сопоставителями для проверки равенства двух объектов. Он совместим с expect.addEqualityTesters из Jest.

ts
import { expect, test } from 'vitest';

class AnagramComparator {
  public word: string;

  constructor(word: string) {
    this.word = word;
  }

  equals(other: AnagramComparator): boolean {
    const cleanStr1 = this.word.replace(/ /g, '').toLowerCase();
    const cleanStr2 = other.word.replace(/ /g, '').toLowerCase();

    const sortedStr1 = cleanStr1.split('').sort().join('');
    const sortedStr2 = cleanStr2.split('').sort().join('');

    return sortedStr1 === sortedStr2;
  }
}

function isAnagramComparator(a: unknown): a is AnagramComparator {
  return a instanceof AnagramComparator;
}

function areAnagramsEqual(a: unknown, b: unknown): boolean | undefined {
  const isAAnagramComparator = isAnagramComparator(a);
  const isBAnagramComparator = isAnagramComparator(b);

  if (isAAnagramComparator && isBAnagramComparator) {
    return a.equals(b);
  } else if (isAAnagramComparator === isBAnagramComparator) {
    return undefined;
  } else {
    return false;
  }
}

expect.addEqualityTesters([areAnagramsEqual]);

test('custom equality tester', () => {
  expect(new AnagramComparator('listen')).toEqual(
    new AnagramComparator('silent')
  );
});
Pager
Предыдущая страницаVi
Следующая страницаexpectTypeOf

Выпущено на условиях лицензии MIT.

Авторские права (c) 2021-Present Vitest Team

https://vitest.dev/api/expect

Выпущено на условиях лицензии MIT.

Авторские права (c) 2021-Present Vitest Team