Тестирование DOM-манипуляций
Тестирование DOM-манипуляций — проверка кода, взаимодействующего с DOM (добавление/удаление элементов, изменение классов, атрибутов, стилей), через jsdom-окружение Jest или реальный браузер в E2E тестах.
Зачем нужно
Ванильный JavaScript и jQuery-код активно работает с DOM. Unit-тесты для такого кода требуют jsdom-окружения — симуляции браузерного DOM в Node.js. Без тестов DOM-манипуляции проверяются только вручную в браузере.
Где используется
- Тестирование ванильных JS утилит (toggle, addClass, show/hide)
- Тестирование Web Components
- Проверка функций, работающих с
document,window,localStorage - Тестирование кастомных директив в Vue/Angular
Основной контент
Настройка jsdom в Jest
// jest.config.js
module.exports = {
testEnvironment: 'jsdom', // браузерное окружение
};
Тестирование простой DOM-функции
// toggleClass.js
export function toggleClass(element, className) {
if (element.classList.contains(className)) {
element.classList.remove(className);
} else {
element.classList.add(className);
}
}
// toggleClass.test.js
import { toggleClass } from './toggleClass';
test('добавляет класс если его нет', () => {
const el = document.createElement('div');
toggleClass(el, 'active');
expect(el.classList.contains('active')).toBe(true);
});
test('убирает класс если он есть', () => {
const el = document.createElement('div');
el.classList.add('active');
toggleClass(el, 'active');
expect(el.classList.contains('active')).toBe(false);
});
Тестирование с HTML-фиксатурой
// dropdown.test.js
import { initDropdown } from './dropdown';
beforeEach(() => {
document.body.innerHTML = `
<div class="dropdown">
<button class="dropdown-toggle">Меню</button>
<ul class="dropdown-menu hidden">
<li>Пункт 1</li>
</ul>
</div>
`;
initDropdown;
});
test('открывает меню при клике на кнопку', () => {
const button = document.querySelector('.dropdown-toggle');
const menu = document.querySelector('.dropdown-menu');
button.click();
expect(menu.classList.contains('hidden')).toBe(false);
});
test('закрывает меню при повторном клике', () => {
const button = document.querySelector('.dropdown-toggle');
const menu = document.querySelector('.dropdown-menu');
button.click();
button.click();
expect(menu.classList.contains('hidden')).toBe(true);
});
Тестирование localStorage
// storage.test.js
import { saveTheme, getTheme } from './storage';
beforeEach(() => {
localStorage.clear();
});
test('сохраняет тему в localStorage', () => {
saveTheme('dark');
expect(localStorage.getItem('theme')).toBe('dark');
});
test('возвращает null если тема не установлена', () => {
expect(getTheme).toBeNull();
});
Тестирование с Testing Library (для React)
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Accordion } from './Accordion';
test('раскрывает панель при клике', async () => {
render(<Accordion title="Секция 1" content="Содержимое" />);
const panel = screen.queryByText('Содержимое');
expect(panel).not.toBeVisible;
await userEvent.click(screen.getByText('Секция 1'));
expect(screen.getByText('Содержимое')).toBeVisible;
});
Частые ошибки
- Тест без
testEnvironment: 'jsdom'— в Node-окружении нетdocument; Jest выдастReferenceError: document is not defined - Нет
beforeEach(() => { document.body.innerHTML = '' })— DOM накапливается между тестами и ломает изоляцию - Тест проверяет стиль через
.style.display— лучше проверять через класс илиtoBeVisibleиз jest-dom
Связанные темы
- _MOC Тестирование
- Testing Library -- подход
- React Testing Library -- основы
- Jest -- конфигурация и плагины
- Тестирование пользовательских событий