Мокирование роутера в библиотеке Page.js используется для имитации поведения навигации в приложении без реальной загрузки страниц или изменения URL в браузере. Это особенно полезно при тестировании компонентов, где важна логика маршрутизации, но нет необходимости в полноценном браузерном окружении.
Page.js — это небольшая клиентская библиотека для маршрутизации в одностраничных приложениях (SPA). Она работает по принципу сопоставления URL с обработчиками:
page('/', () => console.log('Главная страница'));
page('/about', () => console.log('Страница о нас'));
page.start();
При вызове page.start() библиотека начинает отслеживать
изменения URL и вызывает соответствующие функции-обработчики.
Для мокирования ключевым является понимание, что Page.js управляет двумя основными вещами:
pushState, replaceState.Мокирование позволяет перехватывать эти действия, чтобы контролировать тестируемое поведение без реальных переходов по URL.
page() и
page.start()import page from 'page';
jest.mock('page', () => {
const routes = {};
return {
__esModule: true,
default: (path, handler) => {
routes[path] = handler;
},
start: jest.fn(),
navigate: (path) => {
if (routes[path]) routes[path]();
},
};
});
В этом примере:
routes хранит сопоставление URL → обработчик.start заменён на мок-функцию.navigate имитирует переход по маршруту без
изменения URL браузера.Это позволяет тестировать вызовы обработчиков при переходах:
import page from 'page';
test('переход на главную страницу вызывает нужный обработчик', () => {
const handler = jest.fn();
page('/', handler);
page.navigate('/');
expect(handler).toHaveBeenCalled();
});
Для более низкоуровневого контроля можно заменить методы
window.history:
beforeEach(() => {
jest.spyOn(window.history, 'pushState').mockImplementation(() => {});
jest.spyOn(window.history, 'replaceState').mockImplementation(() => {});
});
afterEach(() => {
jest.restoreAllMocks();
});
Таким образом, любые вызовы page.redirect() или
page.show() не будут изменять URL, но сохранят логику
маршрутизации для проверки.
Page.js поддерживает динамические маршруты:
page('/user/:id', ctx => console.log(`Пользователь ${ctx.params.id}`));
При мокировании важно правильно формировать объект
ctx:
const ctx = { path: '/user/42', params: { id: '42' } };
routes['/user/:id'](ctx);
Такой подход позволяет проверять работу компонентов, использующих
ctx.params, без реальной навигации.
Пример с Sinon:
import sinon from 'sinon';
import page from 'page';
const startStub = sinon.stub(page, 'start');
const handlerSpy = sinon.spy();
page('/test', handlerSpy);
page.navigate('/test');
sinon.assert.calledOnce(handlerSpy);
startStub.restore();
ctx)
позволяет тестировать передачу параметров, query-параметров и
состояния.import page from 'page';
const routes = {};
const navigateMock = (path) => {
const routeKeys = Object.keys(routes);
const match = routeKeys.find(k => k.includes(':') || k === path);
if (match) {
const ctx = { path, params: { id: path.split('/')[2] } };
routes[match](ctx);
}
};
jest.mock('page', () => ({
__esModule: true,
default: (path, handler) => { routes[path] = handler; },
start: jest.fn(),
navigate: navigateMock,
}));
page('/user/:id', ctx => console.log(ctx.params.id));
page.navigate('/user/123'); // выведет 123
Такой подход обеспечивает полное мокирование роутера для тестирования SPA без реального DOM и URL, сохраняя всю функциональность Page.js для unit-тестов.