Unit-тестирование в Svelte предоставляет возможность изолированного тестирования компонентов, что позволяет улучшить качество и стабильность кода. Важным инструментом для этого являются Jest и Testing Library — два популярных инструмента для тестирования в экосистеме JavaScript. Jest предоставляет тестовый фреймворк, а Testing Library ориентирована на тестирование пользовательских интерфейсов. Эти инструменты помогают не только проверять функциональность компонентов, но и соблюдать принципы доступности и удобства использования.
Для начала необходимо установить все необходимые зависимости для тестирования компонентов Svelte с использованием Jest и Testing Library. Важно, чтобы среда была правильно настроена, чтобы тесты могли работать без ошибок.
Установка зависимостей:
npm install --save-dev jest @testing-library/svelte @testing-library/jest-dom @babel/preset-env svelte-jester
Здесь:
jest — сам фреймворк для тестирования.@testing-library/svelte — библиотека для тестирования
компонентов Svelte.@testing-library/jest-dom — набор полезных матчеров для
работы с DOM.svelte-jester — преобразователь для поддержки Svelte в
Jest.Настройка конфигурации Jest. Для этого нужно создать или
отредактировать файл jest.config.js:
module.exports = {
transform: {
'^.+\\.svelte$': 'svelte-jester',
'^.+\\.js$': 'babel-jest',
},
moduleFileExtensions: ['js', 'svelte'],
};
Этот файл указывает Jest, как обрабатывать файлы Svelte и JavaScript, а также настраивает необходимые транспайлера.
Добавление конфигурации Babel в файл .babelrc для
использования современных возможностей Jav * aScript:
{
"presets": ["@babel/preset-env"]
}Для начала создадим простой компонент Svelte, который будем тестировать. Пусть это будет компонент, который отображает приветствие.
<!-- Greeting.svelte -->
<script>
export let name = 'Мир';
</script>
<p>Привет, {name}!</p>
Теперь, когда компонент готов, можно переходить к написанию теста. Важно, чтобы тесты были направлены на функциональность компонента, а не на его внутреннюю структуру или имплементацию.
// Greeting.test.js
import { render } from '@testing-library/svelte';
import Greeting from './Greeting.svelte';
test('отображает приветствие с переданным именем', () => {
const { getByText } = render(Greeting, { name: 'Алексей' });
// Проверяем, что на странице появился текст "Привет, Алексей!"
expect(getByText('Привет, Алексей!')).toBeInTheDocument();
});
test('по умолчанию отображает приветствие с именем "Мир"', () => {
const { getByText } = render(Greeting);
// Проверяем, что на странице появился текст "Привет, Мир!"
expect(getByText('Привет, Мир!')).toBeInTheDocument();
});
В этом примере используются следующие моменты:
render() — функция из Testing Library, которая рендерит
компонент Svelte.getByText() — метод, позволяющий найти элемент по
тексту внутри него.expect().toBeInTheDocument() — матчеры, предоставляемые
jest-dom, которые проверяют наличие элемента в DOM.Многие компоненты Svelte реагируют на действия пользователя, например, на нажатие кнопки. Важно тестировать эти взаимодействия, чтобы убедиться, что компонент правильно обрабатывает события.
Пример компонента с кнопкой:
<!-- Counter.svelte -->
<script>
let count = 0;
function increment() {
count += 1;
}
</script>
<button on:click={increment}>Увеличить</button>
<p>Счёт: {count}</p>
Тестирование этого компонента с проверкой реакции на клики:
// Counter.test.js
import { render, fireEvent } from '@testing-library/svelte';
import Counter from './Counter.svelte';
test('увеличивает счёт при клике на кнопку', async () => {
const { getByText } = render(Counter);
const button = getByText('Увеличить');
const counter = getByText('Счёт: 0');
// Проверяем, что начальное значение счётчика — 0
expect(counter).toHaveTextContent('Счёт: 0');
// Симулируем клик по кнопке
await fireEvent.click(button);
// Проверяем, что счёт увеличился на 1
expect(counter).toHaveTextContent('Счёт: 1');
});
Здесь:
fireEvent.click() используется для симуляции клика по
кнопке.toHaveTextContent() — матчеры для проверки текста,
который отображается в элементе.Svelte компоненты могут работать с асинхронными операциями, например,
с API-запросами. В таких случаях важно правильно обрабатывать
асинхронность в тестах. Jest предоставляет механизм для работы с
промисами и асинхронными функциями через async/await.
Пример компонента с асинхронным запросом:
<!-- FetchData.svelte -->
<script>
import { onMount } from 'svelte';
let data = null;
let error = null;
onMount(async () => {
try {
const response = await fetch('https://api.example.com/data');
data = await response.json();
} catch (err) {
error = err.message;
}
});
</script>
{#if error}
<p>Ошибка: {error}</p>
{:else if data}
<p>Данные: {JSON.stringify(data)}</p>
{:else}
<p>Загрузка...</p>
{/if}
Тестирование этого компонента с использованием jest:
// FetchData.test.js
import { render, waitFor } from '@testing-library/svelte';
import FetchData from './FetchData.svelte';
test('показывает данные после успешного запроса', async () => {
// Мокаем ответ API
global.fetch = jest.fn().mockResolvedValue({
json: jest.fn().mockResolvedValue({ name: 'Сергей', age: 30 }),
});
const { getByText } = render(FetchData);
// Проверяем, что компонент отображает текст "Загрузка..."
expect(getByText('Загрузка...')).toBeInTheDocument();
// Ожидаем, что данные будут загружены
await waitFor(() => getByText('Данные: {"name":"Сергей","age":30}'));
// Проверяем, что данные отобразились правильно
expect(getByText('Данные: {"name":"Сергей","age":30}')).toBeInTheDocument();
});
test('показывает ошибку при неудачном запросе', async () => {
// Мокаем ошибку API
global.fetch = jest.fn().mockRejectedValue(new Error('Сетевая ошибка'));
const { getByText } = render(FetchData);
// Ожидаем, что ошибка будет отображена
await waitFor(() => getByText('Ошибка: Сетевая ошибка'));
// Проверяем, что ошибка отобразилась правильно
expect(getByText('Ошибка: Сетевая ошибка')).toBeInTheDocument();
});
В этом примере:
jest.fn().mockResolvedValue() и
jest.fn().mockRejectedValue() используются для мокирования
успешных и неудачных ответов от API.waitFor() — помогает ожидать изменений в DOM после
асинхронных операций.Одной из важных задач при тестировании компонентов является проверка
их доступности (accessibility). Использование библиотек вроде
@testing-library/jest-dom позволяет легко проверять, что
элементы компонента доступны для пользователей с ограниченными
возможностями.
Пример проверки доступности кнопки:
// AccessibleButton.test.js
import { render } from '@testing-library/svelte';
import AccessibleButton from './AccessibleButton.svelte';
test('кнопка должна быть доступна для пользователя с экрана', () => {
const { getByRole } = render(AccessibleButton);
// Проверяем, что кнопка имеет роль "button" и доступна
expect(getByRole('button')).toBeInTheDocument();
expect(getByRole('button')).toHaveAccessibleName('Нажми меня');
});
Здесь:
getByRole('button') используется для нахождения кнопки
по роли.toHaveAccessibleName() проверяет, что кнопка имеет
доступное имя, которое будет озвучено пользователю с использованием
экрана.