Vitest — это современный тест-раннер для проектов на основе Vite и SvelteKit. Его ключевое преимущество заключается в высокой скорости запуска, интеграции с Vite и поддержке современных возможностей JavaScript и TypeScript.
Для начала необходимо установить пакеты:
npm install -D vitest @testing-library/svelte @testing-library/jest-dom jsdom
vitest — основной тест-раннер.@testing-library/svelte — библиотека для тестирования
Svelte-компонентов через DOM.@testing-library/jest-dom — расширение для удобных
утверждений DOM.jsdom — эмуляция браузерного окружения для
Node.js.Далее создается конфигурация в файле
vitest.config.js:
import { defineConfig } from 'vitest/config';
import svelte from '@sveltejs/vite-plugin-svelte';
export default defineConfig({
plugins: [svelte()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: './vitest.setup.js',
},
});
Файл vitest.setup.js подключает дополнительные
возможности:
import '@testing-library/jest-dom';
Такое окружение позволяет писать тесты с использованием глобальных
функций describe, it, expect.
SvelteKit компоненты тестируются как обычные UI-компоненты. Основной
инструмент — render из
@testing-library/svelte.
Пример теста кнопки:
import { render, fireEvent } from '@testing-library/svelte';
import Button from '../src/lib/Button.svelte';
describe('Button Component', () => {
it('рендерит текст', () => {
const { getByText } = render(Button, { props: { label: 'Нажми меня' } });
expect(getByText('Нажми меня')).toBeInTheDocument();
});
it('вызывает callback при клике', async () => {
const handleClick = vi.fn();
const { getByText } = render(Button, { props: { label: 'Клик', onClick: handleClick } });
const button = getByText('Клик');
await fireEvent.click(button);
expect(handleClick).toHaveBeenCalledTimes(1);
});
});
Ключевые моменты:
render(Component, { props }) — рендерит компонент с
указанными свойствами.fireEvent — эмуляция пользовательских действий (клик,
ввод текста).vi.fn() — создание мок-функций для проверки
вызовов.Vitest предоставляет API для моков и заглушек, аналогичное Jest:
import { vi } from 'vitest';
import * as api from '../src/lib/api.js';
vi.mock('../src/lib/api.js', () => ({
fetchData: vi.fn(() => Promise.resolve({ data: [1, 2, 3] })),
}));
it('должен получить данные', async () => {
const result = await api.fetchData();
expect(result.data).toHaveLength(3);
});
Моки полезны для изоляции тестов от сетевых запросов или сторонних библиотек.
Svelte-компоненты имеют реактивные переменные, которые можно проверять через DOM или подписки:
import { render } from '@testing-library/svelte';
import Counter from '../src/lib/Counter.svelte';
it('увеличивает счетчик', async () => {
const { getByText } = render(Counter);
const incrementButton = getByText('Increment');
await fireEvent.click(incrementButton);
expect(getByText('Count: 1')).toBeInTheDocument();
await fireEvent.click(incrementButton);
expect(getByText('Count: 2')).toBeInTheDocument();
});
Тест проверяет правильное обновление значения счетчика через пользовательские действия.
Для реактивных выражений можно подписываться на store:
import { writable } from 'svelte/store';
it('store изменяется корректно', () => {
const count = writable(0);
let value;
count.subscribe(v => value = v);
count.set(5);
expect(value).toBe(5);
});
Для SvelteKit принято хранить тесты рядом с компонентами:
src/
└─ lib/
├─ Button.svelte
├─ Button.test.js
├─ Counter.svelte
└─ Counter.test.js
Или в отдельной папке tests:
tests/
├─ components/
│ ├─ Button.test.js
│ └─ Counter.test.js
└─ utils/
└─ api.test.js
Называние файлов с .test.js или .spec.js
позволяет Vitest автоматически их обнаруживать.
Для UI-компонентов критически важно проверять интерактивность:
fireEvent.click(element)fireEvent.input(element, { target: { value: 'text' } })fireEvent.change(element, { target: { value: 'new' } })Можно комбинировать события для сложных сценариев:
await fireEvent.input(inputElement, { target: { value: 'Svelte' } });
await fireEvent.click(submitButton);
expect(handleSubmit).toHaveBeenCalledWith('Svelte');
Асинхронные операции в компонентах обрабатываются через
async/await:
import AsyncComponent from '../src/lib/AsyncComponent.svelte';
it('отображает данные после загрузки', async () => {
const { findByText } = render(AsyncComponent);
const item = await findByText('Loaded Item');
expect(item).toBeInTheDocument();
});
findByText автоматически ждет появления элемента в
DOM.Vitest позволяет добавлять глобальные хелперы через
setupFiles:
import { render } from '@testing-library/svelte';
global.renderComponent = render;
Теперь renderComponent доступен во всех тестах без
импорта. Это ускоряет написание и поддержание тестов.
Vitest запускает тесты параллельно по файлам. Для изоляции состояния:
beforeEach для сброса mocks и store.afterEach для очистки DOM:import { cleanup } from '@testing-library/svelte';
afterEach(() => {
cleanup();
vi.clearAllMocks();
});
Vitest легко интегрируется с GitHub Actions, GitLab CI и другими сервисами:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 20
- run: npm install
- run: npm test
--coverage позволяет получать отчет о
покрытии тестами.lcov, что удобно для анализа
в CI.Эти возможности делают Vitest мощным инструментом для unit-тестирования SvelteKit UI-компонентов, обеспечивая надежность и предсказуемость поведения интерфейса.