В Riot.js события являются основным механизмом взаимодействия между
компонентами и пользователем. Они описываются декларативно в шаблонах и
обрабатываются методами тега. Тестирование событий направлено на
проверку корректности вызова обработчиков, изменения состояния
(state) и повторного рендеринга компонента.
Ключевая особенность Riot.js — тесная связка DOM, состояния и логики в рамках одного тега. Это влияет на стратегию тестирования: проверяется не только факт срабатывания события, но и итоговое состояние компонента и DOM.
Riot.js не навязывает конкретный инструмент тестирования. На практике используются:
.riot-файлов в тестах при необходимости.Тестирование событий обычно относится к уровню unit или component tests.
Компоненты Riot.js тестируются после монтирования в DOM. Минимальная подготовка включает:
div) в
document.body;riot.mount;Пример инициализации:
import { mount } from 'riot'
import MyComponent from './my-component.riot'
let el
beforeEach(() => {
el = document.createElement('div')
document.body.appendChild(el)
})
afterEach(() => {
document.body.removeChild(el)
})
Наиболее распространённый сценарий — проверка реакции на
click. В Riot.js обработчик описывается прямо в
шаблоне:
<button oncl ick={increment}>+</button>
Тестирование включает три этапа:
Пример теста:
test('увеличение счётчика по клику', () => {
const [component] = mount(el, MyComponent)
const button = el.querySelector('button')
button.click()
expect(component.state.count).toBe(1)
})
Важно учитывать, что обновление состояния в Riot.js происходит синхронно, но рендеринг может быть отложен до следующего тика.
input,
change)Для форм и полей ввода проверяется синхронизация значения DOM с состоянием:
<input type="text" onin put={onInput}>
Тест:
test('обновление состояния при вводе текста', () => {
const [component] = mount(el, MyComponent)
const input = el.querySelector('input')
input.value = 'test'
input.dispatchEvent(new Event('input'))
expect(component.state.value).toBe('test')
})
Здесь важно использовать dispatchEvent, так как простое
изменение value не инициирует событие.
Riot.js поддерживает пользовательские события через
this.trigger и this.on. Они применяются для
взаимодействия между компонентами или внутри логики.
Пример внутри компонента:
this.trigger('saved', data)
Тестирование таких событий строится на подписке:
test('эмит события saved', done => {
const [component] = mount(el, MyComponent)
component.on('saved', data => {
expect(data.id).toBe(1)
done()
})
component.save()
})
Использование done необходимо для асинхронных
сценариев.
При вложенных компонентах тестируется цепочка событий: действие → событие → реакция родителя.
Пример сценария:
Тест:
test('родитель реагирует на событие дочернего компонента', () => {
const [parent] = mount(el, ParentComponent)
const childButton = el.querySelector('.child button')
childButton.click()
expect(parent.state.childClicked).toBe(true)
})
Такой тест проверяет именно взаимодействие, а не внутреннюю реализацию компонентов.
Если обработчик события содержит асинхронную логику (fetch, setTimeout, promise), тестирование требует контроля времени и ожиданий.
Пример с таймером:
jest.useFakeTimers()
test('отложенное изменение состояния', () => {
const [component] = mount(el, MyComponent)
component.startTimer()
jest.runAllTimers()
expect(component.state.done).toBe(true)
})
Для async/await используется await или
возврат Promise из теста.
Событие в Riot.js почти всегда приводит к update().
Тестирование должно учитывать изменение DOM:
test('DOM обновляется после клика', () => {
mount(el, MyComponent)
const span = el.querySelector('span')
const button = el.querySelector('button')
button.click()
expect(span.textContent).toBe('1')
})
Проверяется результат, а не сам факт вызова update.
Для сложных компонентов рекомендуется:
Пример мока:
jest.mock('./api', () => ({
saveData: jest.fn(() => Promise.resolve({ ok: true }))
}))
Это позволяет сосредоточиться именно на реакции компонента на событие.
Отсутствие монтирования в DOM Без реального DOM события не срабатывают.
Ожидание синхронных обновлений там, где есть
асинхронность Неучтённые Promise приводят к ложным
падениям тестов.
Проверка внутренней реализации вместо поведения Тесты должны проверять результат взаимодействия, а не количество вызовов функций.
Эффективная стратегия включает:
Тестирование событий в Riot.js опирается на простоту фреймворка: минимальный API, прозрачное состояние и прямую связь DOM и логики. Это позволяет писать компактные, но надёжные тесты, полностью покрывающие поведение компонентов.