Для работы с Jest необходимо добавить его в проект как зависимость разработки. Используется следующая команда:
npm install --save-dev jest
Если проект предполагает тестирование кода, связанного с DOM
(например, взаимодействие с элементами страницы), необходимо подключить
jest-environment-jsdom:
npm install --save-dev jest-environment-jsdom
После установки в package.json можно добавить скрипт для
запуска тестов:
"scripts": {
"test": "jest"
}
В конфигурации Jest можно явно указать среду выполнения для тестов, где требуется DOM:
"jest": {
"testEnvironment": "jsdom"
}
jest-environment-jsdom предоставляет имитацию
браузерного окружения в Node.js. В среде jsdom доступны
глобальные объекты, такие как window,
document, navigator, что позволяет тестировать
взаимодействие с DOM без запуска реального браузера.
Для изменения настроек jsdom можно использовать отдельный файл
конфигурации. Например, создать jest.setup.js:
// Установка глобальных переменных
globalThis.window = window;
globalThis.document = document;
globalThis.navigator = {
userAgent: 'node.js'
};
В конфигурации Jest подключается этот файл через опцию
setupFiles:
"jest": {
"testEnvironment": "jsdom",
"setupFiles": ["<rootDir>/jest.setup.js"]
}
Тестирование функций, работающих с DOM, выглядит следующим образом:
describe('DOM манипуляции', () => {
beforeEach(() => {
document.body.innerHTML = `
<div id="container">
<button id="btn">Click</button>
</div>
`;
});
test('кнопка существует', () => {
const button = document.getElementById('btn');
expect(button).not.toBeNull();
});
test('нажатие кнопки изменяет текст', () => {
const button = document.getElementById('btn');
button.addEventListener('click', () => {
button.textContent = 'Clicked';
});
button.click();
expect(button.textContent).toBe('Clicked');
});
});
В этом примере используется метод beforeEach для
инициализации DOM перед каждым тестом. Такой подход гарантирует, что
тесты не будут зависеть друг от друга.
В некоторых случаях нужно замокировать методы браузера, которые не
реализованы в jsdom, например window.fetch:
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ data: 'test' })
})
);
test('fetch возвращает данные', async () => {
const response = await fetch('/api/data');
const data = await response.json();
expect(data).toEqual({ data: 'test' });
});
Также возможно мокирование свойств DOM, таких как
window.location:
delete window.location;
window.location = { href: 'http://localhost/' };
test('проверка изменения location', () => {
window.location.href = 'http://example.com/';
expect(window.location.href).toBe('http://example.com/');
});
jsdom поддерживает асинхронные события DOM, такие как
setTimeout и Promise. Для тестирования
асинхронного поведения удобно использовать async/await и
методы Jest waitFor или таймеры:
test('асинхронное изменение DOM', async () => {
const container = document.createElement('div');
document.body.appendChild(container);
setTimeout(() => {
container.textContent = 'Done';
}, 100);
await new Promise(resolve => setTimeout(resolve, 150));
expect(container.textContent).toBe('Done');
});
Такой подход позволяет эмулировать пользовательские действия и задержки, сохраняя тесты детерминированными.
Jest позволяет настраивать различные среды выполнения для отдельных
тестов через директиву @jest-environment:
/**
* @jest-environment jsdom
*/
test('тест с использованием jsdom', () => {
document.body.innerHTML = '<p id="msg">Hello</p>';
const msg = document.getElementById('msg');
expect(msg.textContent).toBe('Hello');
});
Это удобно, когда проект содержит как серверные, так и клиентские тесты, требующие разных окружений.
beforeEach и afterEach для
очистки DOM и глобальных моков, чтобы избежать побочных эффектов.@testing-library/dom, которые упрощают работу с элементами
и событиями.Такой подход обеспечивает стабильное тестирование фронтенд-кода в Node.js без необходимости запуска реального браузера.