Код, що працює з DOM (Alpine-компоненти, скрипти на сторінках Blade, веб-компоненти), потребує документа. У Node.js його немає - тому тест запускають у середовищі, що імітує браузер.
Середовища Vitest:
| Середовище | Що це | Особливості |
|---|---|---|
node |
без DOM (за замовчуванням) | для чистої логіки |
jsdom |
реалізація DOM на JavaScript | найповніша сумісність, повільніший |
happy-dom |
легша реалізація DOM | швидший, але деякі API відсутні чи поводяться інакше |
| Browser Mode | справжній браузер через Playwright | реальний рендеринг, макет, події |
// vitest.config.js
export default defineConfig({
test: { environment: 'jsdom' },
});
Чи лише для одного файлу - коментарем на початку: // @vitest-environment happy-dom.
Що jsdom і happy-dom не вміють: макет і розміри (getBoundingClientRect повертає нулі), прокрутку, IntersectionObserver, CSS-анімації, справжню навігацію. Тести, що від цього залежать, - для браузера.
DOM Testing Library - пошук елементів так, як їх бачить користувач:
import { screen, within } from '@testing-library/dom';
import userEvent from '@testing-library/user-event';
import { mountSubscribeForm } from './subscribe';
it('показує помилку для неправильної пошти', async () => {
document.body.innerHTML = '<div id="app"></div>';
mountSubscribeForm(document.getElementById('app'));
const user = userEvent.setup();
await user.type(screen.getByLabelText('Email'), 'not-an-email');
await user.click(screen.getByRole('button', { name: 'Підписатися' }));
expect(await screen.findByRole('alert')).toHaveTextContent('Неправильна адреса');
});
Пріоритет запитів:
getByRoleзname- як елемент бачать допоміжні технології;getByLabelText- поля форм;getByText- звичайний текст;getByTestId- останній варіант, коли нічого іншого немає.
Пошук за роллю водночас перевіряє доступність: якщо кнопку не знайти за роллю й назвою, її не знайде і програма читання з екрана.
getBy / queryBy / findBy: getBy кидає помилку, якщо елемента немає; queryBy повертає null (для перевірки відсутності); findBy - асинхронний, чекає появи елемента.
@testing-library/jest-dom додає зручні матчери: toBeVisible, toBeDisabled, toHaveValue, toHaveTextContent (працює і з Vitest).
Не тестуйте розмітку: перевірки на кшталт «третій div має клас error» ламаються від кожної зміни верстки, хоча поведінка не змінилася.