Unit-тестирование позволяет проверять корректность работы отдельных частей приложения независимо от остальных компонентов системы. При использовании Pikaday тестирование обычно сосредоточено не на внутреннем устройстве библиотеки, а на логике интеграции календаря с пользовательским интерфейсом, обработчиками событий, бизнес-правилами и механизмами работы с датами.
Основная цель таких тестов заключается в выявлении ошибок на ранних этапах разработки и предотвращении регрессий после внесения изменений.
Наиболее распространённые сценарии тестирования включают:
Pikaday активно взаимодействует с DOM-элементами браузера. Это создаёт дополнительные требования к тестовой среде.
Типичный экземпляр создаётся следующим образом:
const picker = new Pikaday({
field: document.getElementById('date')
});
В ходе выполнения создаются:
Поэтому для unit-тестов обычно используется среда, эмулирующая браузер.
Наиболее популярный вариант:
Jest + JSDOM
JSDOM предоставляет виртуальный DOM, позволяя выполнять тестирование без запуска реального браузера.
Перед каждым тестом желательно создавать новый DOM.
Пример:
beforeEach(() => {
document.body.innerHTML = `
<input id="date">
`;
});
После завершения тестов ресурсы рекомендуется освобождать:
let picker;
afterEach(() => {
picker.destroy();
});
Такой подход предотвращает влияние предыдущих тестов на последующие.
Первый уровень тестирования связан с успешной инициализацией объекта.
Пример:
test('создание экземпляра Pikaday', () => {
const picker = new Pikaday({
field: document.getElementById('date')
});
expect(picker).toBeDefined();
});
Тест подтверждает, что конструктор успешно создаёт объект календаря.
После инициализации важно убедиться, что календарь связан с нужным полем.
Пример:
test('привязка к input', () => {
const input = document.getElementById('date');
const picker = new Pikaday({
field: input
});
expect(picker._o.field).toBe(input);
});
Подобные проверки позволяют обнаружить ошибки конфигурации.
Метод setDate() является одним из наиболее
используемых.
Пример:
test('установка даты', () => {
const picker = new Pikaday({
field: document.getElementById('date')
});
const date = new Date(2025, 4, 10);
picker.setDate(date);
expect(
picker.getDate().getTime()
).toBe(date.getTime());
});
Проверяется корректность сохранения выбранной даты.
После выбора даты содержимое поля должно измениться.
Пример:
test('обновление значения input', () => {
const input = document.getElementById('date');
const picker = new Pikaday({
field: input,
format: 'YYYY-MM-DD'
});
picker.setDate(new Date(2025, 0, 15));
expect(input.value).not.toBe('');
});
В реальном проекте желательно проверять точное значение строки.
Метод должен возвращать выбранную дату.
Пример:
test('получение выбранной даты', () => {
const picker = new Pikaday({
field: document.getElementById('date')
});
picker.setDate(new Date(2025, 7, 20));
const result = picker.getDate();
expect(result instanceof Date).toBe(true);
});
Такой тест гарантирует корректность интерфейса объекта.
Во многих приложениях требуется удаление выбранного значения.
Пример:
test('очистка даты', () => {
const picker = new Pikaday({
field: document.getElementById('date')
});
picker.setDate(null);
expect(picker.getDate()).toBeNull();
});
Подобные сценарии особенно важны для форм с необязательными полями.
Событие onSelect используется практически во всех
проектах.
Пример:
test('вызов onSelect', () => {
const callback = jest.fn();
const picker = new Pikaday({
field: document.getElementById('date'),
onSelect: callback
});
picker.setDate(new Date());
expect(callback).toHaveBeenCalled();
});
Тест гарантирует вызов пользовательской логики после выбора даты.
Иногда важно контролировать число срабатываний события.
Пример:
test('обработчик вызывается один раз', () => {
const callback = jest.fn();
const picker = new Pikaday({
field: document.getElementById('date'),
onSelect: callback
});
picker.setDate(new Date());
expect(callback).toHaveBeenCalledTimes(1);
});
Это помогает выявлять дублирование событий.
Минимальная дата часто используется в формах бронирования и регистрации.
Пример:
test('установка minDate', () => {
const minDate = new Date(2025, 0, 1);
const picker = new Pikaday({
field: document.getElementById('date'),
minDate
});
expect(
picker._o.minDate.getTime()
).toBe(minDate.getTime());
});
Проверяется корректность сохранения ограничения.
Аналогичная проверка выполняется для верхней границы диапазона.
test('установка maxDate', () => {
const maxDate = new Date(2025, 11, 31);
const picker = new Pikaday({
field: document.getElementById('date'),
maxDate
});
expect(
picker._o.maxDate.getTime()
).toBe(maxDate.getTime());
});
Для интерфейсной логики важно тестировать показ календаря.
Пример:
test('открытие календаря', () => {
const picker = new Pikaday({
field: document.getElementById('date')
});
picker.show();
expect(picker.isVisible()).toBe(true);
});
Пример:
test('скрытие календаря', () => {
const picker = new Pikaday({
field: document.getElementById('date')
});
picker.show();
picker.hide();
expect(picker.isVisible()).toBe(false);
});
После вызова destroy() обработчики должны удаляться.
Пример:
test('уничтожение календаря', () => {
const picker = new Pikaday({
field: document.getElementById('date')
});
picker.destroy();
expect(picker._o).toBeNull();
});
Конкретная реализация проверки может отличаться в зависимости от версии библиотеки.
При тестировании интеграционной логики часто применяются моки.
Пример функции:
function initializeCalendar(callback) {
return new Pikaday({
field: document.getElementById('date'),
onSelect: callback
});
}
Тест:
test('callback вызывается после выбора даты', () => {
const callback = jest.fn();
const picker = initializeCalendar(callback);
picker.setDate(new Date());
expect(callback).toHaveBeenCalled();
});
Мок позволяет проверить факт взаимодействия без выполнения реальной бизнес-логики.
Чаще всего проверяется собственный код проекта.
Пример:
function getSelectedDate(picker) {
return picker.getDate();
}
Тест:
test('возвращается дата из календаря', () => {
const picker = new Pikaday({
field: document.getElementById('date')
});
const date = new Date();
picker.setDate(date);
expect(
getSelectedDate(picker)
).toEqual(date);
});
Такой подход соответствует классической концепции unit-тестирования.
Если вокруг Pikaday существует дополнительный сервис, его желательно подменять.
Пример:
const api = {
saveDate: jest.fn()
};
Код приложения:
function handleDateSelection(date) {
api.saveDate(date);
}
Тест:
test('дата отправляется в сервис', () => {
const date = new Date();
handleDateSelection(date);
expect(api.saveDate)
.toHaveBeenCalledWith(date);
});
В результате тестируется только собственная логика проекта.
Во многих системах используются поля начала и окончания периода.
Создание:
const startPicker = new Pikaday({
field: startInput
});
const endPicker = new Pikaday({
field: endInput
});
Тест:
test('создаются два независимых календаря', () => {
expect(startPicker).not.toBe(endPicker);
});
Подобные проверки помогают избежать конфликтов состояния.
Пример пользовательской функции:
function isRangeValid(start, end) {
return start <= end;
}
Тест:
test('корректный диапазон дат', () => {
const start = new Date(2025, 0, 1);
const end = new Date(2025, 0, 5);
expect(
isRangeValid(start, end)
).toBe(true);
});
Хотя функция напрямую не относится к Pikaday, именно такие проверки составляют большую часть реального тестового покрытия.
При использовании Moment.js или собственных форматтеров необходимо тестировать итоговую строку.
Пример:
function formatDate(date) {
return date.toISOString().split('T')[0];
}
Тест:
test('форматирование даты', () => {
const date = new Date('2025-01-10');
expect(
formatDate(date)
).toBe('2025-01-10');
});
Наиболее полезное покрытие обычно включает:
Основной акцент unit-тестирования рекомендуется делать на собственном коде приложения, рассматривая Pikaday как внешнюю зависимость с уже проверенной внутренней реализацией. Такой подход обеспечивает быстрые, стабильные и легко поддерживаемые тесты, позволяющие своевременно обнаруживать ошибки при работе с датами и пользовательскими интерфейсами.