Vex — это мощная библиотека для работы с UI-элементами, которая предоставляет удобные инструменты для создания различных интерфейсных компонентов, таких как модальные окна, уведомления и диалоги. Одной из важнейших частей разработки на JavaScript является тестирование, и Vex не исключение. В этой статье рассматриваются основы написания unit-тестов для кода, использующего библиотеку Vex.
Unit-тестирование представляет собой процесс проверки отдельных частей программы (модулей, функций) на корректность их работы. В контексте использования Vex это может включать тестирование логики отображения диалогов, правильности взаимодействия с пользователем, а также проверки всех возможных сценариев использования компонентов.
Unit-тесты позволяют:
Для того чтобы начать писать тесты для кода, использующего Vex, необходимо настроить окружение. В качестве тестового фреймворка можно использовать Jest, так как он предоставляет удобный API для написания тестов и интеграции с библиотеками, такими как Vex.
Для начала установим необходимые зависимости:
npm install jest @testing-library/react vex-js
Jest является популярным инструментом для тестирования кода на JavaScript, а @testing-library/react упрощает тестирование UI-компонентов, таких как модальные окна, с использованием подхода, ориентированного на пользователя.
Одной из задач при тестировании с использованием Vex является мокирование самой библиотеки, чтобы убедиться, что компоненты отображаются и работают корректно, не создавая при этом реальных модальных окон. Для этого используется jest.mock.
Пример мокирования вызова Vex:
jest.mock('vex-js', () => ({
vex: {
open: jest.fn(),
close: jest.fn(),
},
}));
В этом примере создается мок для функций open и
close, которые позволяют управлять отображением модальных
окон. Такие моки позволят проверять, были ли вызваны эти методы, и
работать с их результатами в тестах.
Одним из основных компонентов, с которым работает Vex, является создание и управление модальными окнами. Рассмотрим пример простого компонента, который открывает модальное окно при нажатии на кнопку.
import React, { useState } from 'react';
import { vex } from 'vex-js';
const ModalButton = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
const openModal = () => {
vex.open({ content: 'Это модальное окно!' });
setIsModalOpen(true);
};
return <button onCl ick={openModal}>Открыть модальное окно</button>;
};
export default ModalButton;
Для тестирования этого компонента можно использовать @testing-library/react,
чтобы имитировать нажатие кнопки и проверить, что вызов метода
open был сделан корректно.
Пример теста:
import { render, screen, fireEvent } from '@testing-library/react';
import ModalButton from './ModalButton';
import { vex } from 'vex-js';
jest.mock('vex-js', () => ({
vex: {
open: jest.fn(),
close: jest.fn(),
},
}));
test('открывает модальное окно при нажатии на кнопку', () => {
render(<ModalButton />);
const button = screen.getByText('Открыть модальное окно');
fireEvent.click(button);
expect(vex.open).toHaveBeenCalledTimes(1);
expect(vex.open).toHaveBeenCalledWith({
content: 'Это модальное окно!',
});
});
Этот тест:
ModalButton.vex.open был вызван с правильными
аргументами.Не менее важной задачей является проверка закрытия модальных окон. Рассмотрим следующий пример компонента, который закрывает модальное окно при нажатии на кнопку.
import React, { useState } from 'react';
import { vex } from 'vex-js';
const CloseModalButton = () => {
const closeModal = () => {
vex.close();
};
return <button onCl ick={closeModal}>Закрыть модальное окно</button>;
};
export default CloseModalButton;
Для тестирования этого компонента создадим тест, который проверит,
что метод close был вызван при нажатии на кнопку.
import { render, screen, fireEvent } from '@testing-library/react';
import CloseModalButton from './CloseModalButton';
import { vex } from 'vex-js';
jest.mock('vex-js', () => ({
vex: {
open: jest.fn(),
close: jest.fn(),
},
}));
test('закрывает модальное окно при нажатии на кнопку', () => {
render(<CloseModalButton />);
const button = screen.getByText('Закрыть модальное окно');
fireEvent.click(button);
expect(vex.close).toHaveBeenCalledTimes(1);
});
Здесь:
CloseModalButton.vex.close был вызван один
раз.В реальных приложениях часто встречаются случаи, когда отображение и скрытие модальных окон зависит от асинхронных операций, например, запросов к серверу. Рассмотрим пример, где окно открывается только после успешного ответа от сервера.
import React, { useState } from 'react';
import { vex } from 'vex-js';
const AsyncModalButton = () => {
const [loading, setLoading] = useState(false);
const openModalAsync = async () => {
setLoading(true);
const response = await fetch('/api/data');
if (response.ok) {
vex.open({ content: 'Данные загружены!' });
}
setLoading(false);
};
return <button onCl ick={openModalAsync} disabled={loading}>Открыть модальное окно</button>;
};
export default AsyncModalButton;
Для тестирования этого компонента можно использовать mocking для асинхронного запроса:
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import AsyncModalButton from './AsyncModalButton';
import { vex } from 'vex-js';
jest.mock('vex-js', () => ({
vex: {
open: jest.fn(),
close: jest.fn(),
},
}));
test('открывает модальное окно после успешного запроса', async () => {
global.fetch = jest.fn().mockResolvedValue({ ok: true });
render(<AsyncModalButton />);
const button = screen.getByText('Открыть модальное окно');
fireEvent.click(button);
await waitFor(() => expect(vex.open).toHaveBeenCalledTimes(1));
expect(vex.open).toHaveBeenCalledWith({ content: 'Данные загружены!' });
});
В этом тесте:
fetch, чтобы имитировать
успешный запрос.vex.open будет вызван только после
того, как запрос завершится успешно.Важно также тестировать сценарии, когда операция не удается. В случае с асинхронными запросами это может быть ошибка сети или ошибка сервера. Рассмотрим пример, где модальное окно не открывается, если запрос не удался.
import React, { useState } from 'react';
import { vex } from 'vex-js';
const ErrorModalButton = () => {
const [loading, setLoading] = useState(false);
const openModalError = async () => {
setLoading(true);
try {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error('Ошибка загрузки данных');
}
vex.open({ content: 'Данные загружены!' });
} catch (error) {
vex.open({ content: `Ошибка: ${error.message}` });
}
setLoading(false);
};
return <button onCl ick={openModalError} disabled={loading}>Открыть модальное окно</button>;
};
export default ErrorModalButton;
Тестируем обработку ошибки:
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import ErrorModalButton from './ErrorModalButton';
import { vex } from 'vex-js';
jest.mock('vex-js', () => ({
vex: {
open: jest.fn(),
close: jest.fn(),
},
}));
test('открывает модальное окно с ошибкой при неудачном запросе', async () => {
global.fetch