Есть отличная удаленная работа для php+codeception+jenkins+allure+docker спецов. 100% remote! Присоединиться к проекту

Как работать с нативным календарем Chrome или установить значение в <input type="date">

reactjs
webdriver
Теги: #<Tag:0x00007f7b642304d8> #<Tag:0x00007f7b64230398>

#1

На странице есть некий <input type="date">. При клике на него - открывается нативный календарь браузера. В Chrome это выглядит вот так: http://take.ms/u83TP
Задача - средствами Selenium установить туда значение. Как это можно сделать?

Календарь, который приведен на скрине никак не проявляется в коде страницы, поэтому найти какие-то его элементы и манипулировать ими не получается.

Я пробовал отправить в данное поле send_keys:

date = "20-02-2018"
date_field = driver.find_element(some_locator)
date_field.send_keys(date)

Причем приведенный в примере кода формат date соответствует тому, как эти поля у меня отображаются в Chrome. Но я так же перепробовал кучу других форматов для date (в т.ч. “yyyy-mm-dd”, “yyyymmdd” и многие другие.)
При выполнении этого кода в поле устанавливается дата, НО она каждый раз разная и можно сказать случайная. Причем даже если на вход подавались одни и те же данные - результат из раза в раз отличается. То станет что-то типа “20-01-0005”, то “01-02-2019” и т.п. Эпизодически проскакивают удачные разы, когда выставляется именно та дата, которую передавал, но это крайне редко.

После этого я пробовал установить дату средствами JavaScript:

driver.execute_script("arguments[0].value='2018-02-20'; ", date_field) 

И дата корректно выставляется.
НО, в моем приложении, когда устанавливается дата в это поле - она некоторым образом валидируется и всплывает некое сообщение.
Когда же я выставляю дату через JavaScript - валидация не происходит.
Это приложение сделано на React. И в реакте на это поле висит обработчик на событие Change (со слов разработчика, сам то я в этом увы не силен). Этот обработчик и делает нужную мне валидацию.

Тогда я попробовал сгенерировать событие change:

driver.execute_script("arguments[0].value='2018-02-20';  arguments[0].dispatchEvent(new Event('change')) ", date_field) 

Пробовал так же с new Event(‘change’, {bubbles: true, cancelable: false});
И на событие ‘input’ пробовал.

Но результат один - никакого. Значение меняется JavaScript -ом, но валидации не происходит. Реакт не видит моих изменений. И если я начинаю делать другие дальнейшие действия на странице (заполнять другие поля, с которыми все проще), то значение в моем поле даты перескакивает на исходное, которое было до моих изменений.

Буду очень благодарен за помощь в этом вопросе!

P.S. Windows 10, Selenium 3.9.0, Chrome 63, Chromedriver 2.35


(Ruslan Semerenko) #3

Попробуйте отправить дату в виде набора цифр без разделительных знаков “20022018”


#4

Уже пробовал. Результат такой же, как описан.


(Sergey Korol) #5

У всех подобных компонентов, как правило, есть вменяемый API. Узнайте, что за календарь используется, почитайте доки, и дергайте метод для установки даты напрямую при помощи JSExecutor.

Update: прочитал по диагонали. Только увидел, что речь о нативном. Тогда беда. :slight_smile:

P.S. Перечитал еще раз. Вижу, что используется React. Тогда самый надежный вариант - ReactTestUtils. Попросите девелоперов, чтобы пробрасывали соответствующий объект наружу на вашем окружении. При помощи него сможете достучаться до закрытых контролов. И следовательно - сгенерить change event.