Интеграционное тестирование

Интеграционное тестирование предназначено для проверки корректного взаимодействия нескольких компонентов приложения между собой. Если модульное тестирование сосредоточено на отдельных функциях и методах, то интеграционные тесты исследуют работу системы на уровне связей между элементами.

В случае использования Pikaday важность интеграционного тестирования особенно высока, поскольку библиотека редко существует изолированно. Обычно она взаимодействует с:

  • HTML-формами;
  • пользовательскими компонентами интерфейса;
  • библиотеками форматирования дат;
  • серверными API;
  • механизмами валидации;
  • фреймворками JavaScript;
  • системами хранения состояния.

Основная цель заключается в подтверждении того, что выбор даты в календаре приводит к правильным изменениям во всех связанных частях приложения.


Что следует проверять интеграционными тестами

Для Pikaday недостаточно убедиться, что календарь открывается и отображает даты. Необходимо проверить весь сценарий использования.

Типичный поток может выглядеть следующим образом:

  1. Пользователь открывает поле ввода.
  2. Появляется календарь Pikaday.
  3. Пользователь выбирает дату.
  4. Поле ввода получает новое значение.
  5. Срабатывает обработчик события.
  6. Выполняется форматирование даты.
  7. Обновляется состояние приложения.
  8. Отправляются данные на сервер.

Интеграционный тест должен охватывать всю эту последовательность.


Проверка взаимодействия Pikaday и HTML-форм

Одним из наиболее распространённых сценариев является работа календаря внутри формы.

Пример конфигурации:

const picker = new Pikaday({
    field: document.getElementById('birthDate')
});

HTML:

<form id="userForm">
    <input id="birthDate">
    <button type="submit">Сохранить</button>
</form>

Интеграционный тест должен подтвердить:

  • отображение выбранной даты в поле;
  • корректную отправку значения формы;
  • отсутствие потери данных после сериализации.

Пример теста:

test('дата попадает в форму после выбора', () => {
    document.body.innerHTML = `
        <form id="form">
            <input id="date">
        </form>
    `;

    const input = document.getElementById('date');

    const picker = new Pikaday({
        field: input
    });

    picker.setDate('2025-06-01');

    expect(input.value).toContain('2025');
});

Здесь тестируется не отдельный метод библиотеки, а её взаимодействие с элементом формы.


Интеграция с обработчиками событий

Практически в каждом проекте используется обработчик выбора даты.

Пример:

const picker = new Pikaday({
    field: input,
    onSelect(date) {
        updateStatistics(date);
    }
});

Интеграционный тест должен подтвердить вызов бизнес-логики.

Пример:

test('выбор даты вызывает обновление статистики', () => {
    const updateStatistics = jest.fn();

    const picker = new Pikaday({
        field: document.createElement('input'),
        onSelect(date) {
            updateStatistics(date);
        }
    });

    picker.setDate(new Date());

    expect(updateStatistics).toHaveBeenCalled();
});

Подобная проверка показывает корректность связи между календарём и пользовательским кодом.


Проверка интеграции с Moment.js

Во многих старых проектах Pikaday используется совместно с библиотекой Moment.

Пример:

const picker = new Pikaday({
    field: input,
    format: 'DD.MM.YYYY'
});

После выбора даты часто выполняется преобразование:

const value = moment(input.value, 'DD.MM.YYYY');

Интеграционный тест должен подтверждать совместимость обеих библиотек.

Пример:

test('moment корректно читает дату из Pikaday', () => {
    picker.setDate(new Date(2025, 5, 15));

    const parsed = moment(input.value, 'DD.MM.YYYY');

    expect(parsed.isValid()).toBe(true);
});

Такой тест позволяет обнаружить ошибки формата ещё до появления их в рабочем приложении.


Проверка интеграции с API

Часто после выбора даты выполняется запрос на сервер.

Пример:

onSelect(date) {
    fetch('/api/report', {
        method: 'POST',
        body: JSON.stringify({
            date
        })
    });
}

Интеграционный тест должен убедиться, что данные передаются корректно.

Пример:

global.fetch = jest.fn(() =>
    Promise.resolve({
        json: () => Promise.resolve({})
    })
);

test('дата отправляется на сервер', () => {
    const picker = new Pikaday({
        field: document.createElement('input'),
        onSelect(date) {
            fetch('/api/report', {
                method: 'POST',
                body: JSON.stringify({ date })
            });
        }
    });

    picker.setDate(new Date());

    expect(fetch).toHaveBeenCalled();
});

Проверяется не сетевое соединение, а корректность интеграции между компонентами.


Интеграция с системами валидации

Календарь часто участвует в проверке корректности данных.

Пример:

function validateDate(value) {
    return value.length > 0;
}

После выбора даты должно автоматически проходить успешное подтверждение.

Тест:

test('выбранная дата проходит валидацию', () => {
    picker.setDate(new Date());

    expect(
        validateDate(input.value)
    ).toBe(true);
});

Подобные проверки позволяют обнаружить несовместимость между форматом даты и валидатором.


Тестирование нескольких связанных календарей

Распространённая задача — выбор диапазона дат.

Например:

const startPicker = new Pikaday({
    field: startInput
});

const endPicker = new Pikaday({
    field: endInput
});

После выбора начальной даты конечная дата должна быть не меньше неё.

Бизнес-логика:

startPicker.config.onSel ect = function(date) {
    endPicker.setMinDate(date);
};

Интеграционный тест:

test('начальная дата ограничивает конечную', () => {
    const startDate = new Date(2025, 5, 10);

    startPicker.setDate(startDate);

    expect(
        endPicker._o.minDate.getTime()
    ).toBe(startDate.getTime());
});

Тест подтверждает взаимодействие двух независимых экземпляров Pikaday.


Проверка обновления состояния приложения

Современные интерфейсы используют централизованное состояние.

Упрощённый пример:

const state = {
    selectedDate: null
};

После выбора даты:

onSelect(date) {
    state.selectedDate = date;
}

Интеграционный тест:

test('состояние получает выбранную дату', () => {
    const state = {
        selectedDate: null
    };

    const picker = new Pikaday({
        field: document.createElement('input'),
        onSelect(date) {
            state.selectedDate = date;
        }
    });

    picker.setDate(new Date());

    expect(state.selectedDate)
        .not.toBeNull();
});

Подобный сценарий особенно важен для крупных SPA-приложений.


Проверка взаимодействия с пользовательскими компонентами

После выбора даты может происходить обновление интерфейса.

Например:

onSelect(date) {
    result.textContent =
        date.toLocaleDateString();
}

Интеграционный тест:

test('интерфейс обновляется после выбора даты', () => {
    const result = document.createElement('div');

    const picker = new Pikaday({
        field: document.createElement('input'),
        onSelect(date) {
            result.textContent =
                date.toLocaleDateString();
        }
    });

    picker.setDate(new Date());

    expect(result.textContent)
        .not.toBe('');
});

Здесь тестируется связь календаря с визуальным компонентом.


Использование jsdom в интеграционных тестах

Pikaday активно взаимодействует с DOM, поэтому интеграционные тесты обычно выполняются в среде jsdom.

Настройка Jest:

module.exports = {
    testEnvironment: 'jsdom'
};

Это позволяет:

  • создавать элементы страницы;
  • эмулировать пользовательские действия;
  • проверять изменение интерфейса;
  • тестировать работу календаря без браузера.

Проверка пользовательского сценария целиком

Наиболее ценными считаются тесты, моделирующие реальные действия пользователя.

Пример полного сценария:

test('полный процесс выбора даты', () => {
    document.body.innerHTML = `
        <input id="date">
        <div id="preview"></div>
    `;

    const input = document.getElementById('date');
    const preview = document.getElementById('preview');

    const picker = new Pikaday({
        field: input,
        onSelect(date) {
            preview.textContent =
                input.value;
        }
    });

    picker.setDate(new Date(2025, 5, 15));

    expect(input.value).not.toBe('');
    expect(preview.textContent).not.toBe('');
});

Такой тест охватывает сразу несколько уровней взаимодействия:

  • работу Pikaday;
  • обновление поля ввода;
  • вызов обработчика;
  • изменение DOM.

Изоляция внешних зависимостей

Интеграционный тест не должен превращаться в полноценный системный тест.

Поэтому обычно изолируются:

  • сетевые запросы;
  • сторонние API;
  • базы данных;
  • внешние сервисы.

Для этого используются заглушки и моки:

jest.fn();
jest.spyOn();
jest.mock();

Подобный подход позволяет сосредоточиться именно на взаимодействии компонентов приложения с Pikaday.


Типичные ошибки, выявляемые интеграционными тестами

Интеграционное тестирование часто обнаруживает проблемы, которые невозможно заметить на уровне модульных тестов:

  • неверный формат даты между компонентами;
  • отсутствие вызова обработчиков событий;
  • ошибки сериализации даты перед отправкой на сервер;
  • конфликты локализации;
  • нарушение логики диапазонов дат;
  • потерю данных при обновлении состояния;
  • несовместимость с валидаторами;
  • ошибки синхронизации пользовательского интерфейса;
  • неправильную работу после рефакторинга бизнес-логики;
  • несоответствие между отображаемой и фактически сохраняемой датой.

Именно поэтому интеграционные тесты занимают центральное место при сопровождении приложений, использующих Pikaday в составе форм, административных панелей, CRM-систем, систем бронирования, календарных сервисов и других интерфейсов, где корректная работа даты влияет на функционирование всей системы.