Работа с date pickers

В веб-тестировании работа с элементами выбора даты (date pickers) требует особого подхода, так как эти компоненты часто реализуются нестандартно через JavaScript, CSS и динамические DOM-структуры. Protractor предоставляет инструменты для взаимодействия с такими элементами, позволяя управлять как простыми HTML <input type="date">, так и кастомными календарными виджетами.


Определение и выбор date picker

Date picker может быть реализован:

  • Нативным HTML через <input type="date">.
  • Кастомным виджетом с открывающимся календарём, где дни, месяцы и годы представлены отдельными элементами.

Для взаимодействия с ними важно корректно выбрать элемент:

const dateInput = element(by.css('input#date-of-birth'));

Для кастомных календарей выбор может включать отдельные элементы:

const calendarIcon = element(by.css('.calendar-icon'));
const calendarWidget = element(by.css('.calendar-widget'));
const dayCell = calendarWidget.element(by.cssContainingText('.day', '15'));

Взаимодействие с нативными <input type="date">

Нативные поля даты поддерживают прямое присваивание значения через sendKeys, но значение должно быть в формате yyyy-mm-dd:

await dateInput.sendKeys('2026-01-15');

Если необходимо очистить поле перед вводом новой даты:

await dateInput.clear();
await dateInput.sendKeys('2026-01-15');

Работа с кастомными календарями

Кастомные date pickers требуют симуляции кликов по элементам интерфейса, так как прямой ввод в input может быть недоступен.

  1. Открытие календаря:
await calendarIcon.click();
  1. Выбор месяца и года (если календарь имеет навигацию):
const monthSelect = calendarWidget.element(by.css('.month-select'));
await monthSelect.element(by.cssContainingText('option', 'Январь')).click();

const yearSelect = calendarWidget.element(by.css('.year-select'));
await yearSelect.element(by.cssContainingText('option', '2026')).click();
  1. Выбор конкретного дня:
const day = calendarWidget.element(by.cssContainingText('.day', '15'));
await day.click();
  1. Проверка выбранной даты:
const selectedDate = await dateInput.getAttribute('value');
expect(selectedDate).toEqual('2026-01-15');

Асинхронность и ожидания

Кастомные виджеты часто обновляют DOM динамически, поэтому важно использовать ожидания:

const EC = protractor.ExpectedConditions;

await browser.wait(EC.visibilityOf(calendarWidget), 5000, 'Календарь не появился');
await browser.wait(EC.elementToBeClickable(dayCell), 5000, 'День не кликабельный');

Использование ExpectedConditions предотвращает ошибки типа ElementNotInteractableError.


Работа с динамическими датами

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

const targetDate = new Date();
targetDate.setDate(targetDate.getDate() + 7);

const dayToSelect = targetDate.getDate().toString();
const monthToSelect = targetDate.toLocaleString('default', { month: 'long' });
const yearToSelect = targetDate.getFullYear().toString();

await calendarIcon.click();
await calendarWidget.element(by.cssContainingText('.month-select option', monthToSelect)).click();
await calendarWidget.element(by.cssContainingText('.year-select option', yearToSelect)).click();
await calendarWidget.element(by.cssContainingText('.day', dayToSelect)).click();

Особенности взаимодействия с различными библиотеками

Кастомные date pickers, созданные с использованием сторонних библиотек (jQuery UI Datepicker, Angular Material, Bootstrap Datepicker), имеют свои особенности:

  • jQuery UI Datepicker: дни представлены как <td> с классами ui-datepicker-day.
  • Angular Material: требуется клик по <mat-datepicker-toggle> и последующая работа с mat-calendar.
  • Bootstrap Datepicker: навигация через .datepicker-days и выбор дня по CSS-классу .day.

Для всех библиотек основной подход одинаков: открыть календарь → выбрать месяц/год → выбрать день → проверить результат.


Советы по надежной автоматизации date pickers

  • Использовать уникальные селекторы: id, data-test атрибуты предпочтительнее CSS-классов, так как классы часто меняются.
  • Минимизировать жесткие таймауты: использовать ExpectedConditions вместо browser.sleep().
  • Выносить логику выбора даты в вспомогательные функции для повторного использования:
async function selectDate(dateInput, day, month, year) {
    await dateInput.click();
    const widget = element(by.css('.calendar-widget'));
    await widget.element(by.cssContainingText('.month-select option', month)).click();
    await widget.element(by.cssContainingText('.year-select option', year)).click();
    await widget.element(by.cssContainingText('.day', day)).click();
}
  • Проверять введённое значение после выбора, чтобы убедиться, что дата установлена корректно.

Эффективная работа с date pickers в Protractor требует комбинирования правильного выбора элементов, учёта асинхронного поведения DOM и понимания структуры конкретного календарного виджета. Это позволяет создавать стабильные и воспроизводимые тесты для любых реализаций date picker на веб-страницах.