Unit-тестирование в Mithril.js позволяет изолированно проверять поведение компонентов, их рендеринг, обработку событий и взаимодействие с состоянием. Основной целью является подтверждение корректности работы логики и структуры компонентов без необходимости поднимать весь фронтенд-приложение.
Компонент в Mithril определяется объектом с методами
view и, опционально, oninit,
oncreate, onupdate и onremove.
Для unit-тестирования важно уметь:
Для тестирования чаще всего используют комбинацию Jest или Mocha с jsdom, который позволяет работать с DOM в Node.js.
Mithril предоставляет функцию m.mount и
m.render для работы с DOM. В тестах обычно используют
m.render, так как она позволяет рендерить в заданный
контейнер и не зависит от жизненного цикла всего приложения.
Пример рендеринга:
import m from "mithril";
const Button = {
view: ({attrs}) => m("button", {onclick: attrs.onclick}, attrs.label)
};
test("рендерит кнопку с правильным текстом", () => {
const container = document.createElement("div");
const handleClick = jest.fn();
m.render(container, m(Button, {label: "Click me", onclick: handleClick}));
const button = container.querySelector("button");
expect(button.textContent).toBe("Click me");
});
Ключевые моменты:
m.render вместо
m.mount упрощает проверку структуры.Для проверки методов жизненного цикла (oninit,
oncreate, onupdate, onremove) в
unit-тестах можно использовать шпионов и mock-функции:
const Component = {
oninit: jest.fn(),
oncreate: jest.fn(),
view: () => m("div", "Content")
};
test("вызывает oninit и oncreate", () => {
const container = document.createElement("div");
m.render(container, m(Component));
expect(Component.oninit).toHaveBeenCalled();
expect(Component.oncreate).toHaveBeenCalled();
});
Особенности:
oninit вызывается до первого рендера,
oncreate — после вставки в DOM.onupdate необходимо повторно вызывать
m.render с новыми данными.События в Mithril-приложениях легко эмулируются через стандартный API браузера:
test("клик вызывает обработчик", () => {
const handleClick = jest.fn();
const container = document.createElement("div");
const Button = {
view: ({attrs}) => m("button", {onclick: attrs.onclick}, "Click")
};
m.render(container, m(Button, {onclick: handleClick}));
const button = container.querySelector("button");
button.click();
expect(handleClick).toHaveBeenCalledTimes(1);
});
Важные моменты:
.click() эмулирует событие
клика.keydown, input)
используется new Event("eventType") с
dispatchEvent.Если компонент содержит локальное состояние через oninit
или через замыкания, важно проверять изменение состояния при рендере и
событиях:
const Counter = {
count: 0,
view: () => m("div",
[
m("span", `Count: ${Counter.count}`),
m("button", {onclick: () => Counter.count++}, "Increment")
]
)
};
test("увеличение счётчика", () => {
const container = document.createElement("div");
m.render(container, m(Counter));
const button = container.querySelector("button");
button.click();
m.render(container, m(Counter)); // повторный рендер
const span = container.querySelector("span");
expect(span.textContent).toBe("Count: 1");
});
Особенности:
Для компонентов, которые делают HTTP-запросы или используют сторонние сервисы, применяется мокирование:
jest.mock("./api", () => ({
fetchData: jest.fn().mockResolvedValue({name: "Mithril"})
}));
import {fetchData} from "./api";
const DataComponent = {
data: null,
oninit: async () => {
DataComponent.data = await fetchData();
},
view: () => m("div", DataComponent.data?.name || "Loading")
};
test("рендерит данные после fetch", async () => {
const container = document.createElement("div");
await DataComponent.oninit();
m.render(container, m(DataComponent));
expect(container.textContent).toBe("Mithril");
});
Преимущества:
fetchData для проверки разных
сценариев.Для полноценного тестирования компонентов Mithril рекомендуется использовать конфигурацию Jest с jsdom. Это позволяет:
Пример настройки:
{
"testEnvironment": "jsdom",
"transform": {
"^.+\\.js$": "babel-jest"
}
}
Такой подход обеспечивает полную совместимость с современными инструментами тестирования и позволяет писать модульные, изолированные, повторяемые тесты.
async/await.