Добрый день коллеги. Возникла следующая заморочка. Есть календарь очень похожий на
календарик тыц
На входе есть дата вида 02/16/2014 в американском формате - первым идет месяц. Так вот суть проблемы, не получается с помощью WebDriver нормально кликнуть по нужной дате. Распарсить дату, выбрать месяц - это да это несложно и решаемо. А вот именно кликнуть по нужной дате и проверить, что появилось то количество выделенных дат - которое задано в Select How many nights? - не получается. Думаю, что задача может решиться с помощью JS. Но вот вопрос - насколько это валидно и увы, я практически не владею JS - поэтому и применять его бы не хотелось.
Задача очень простая. Не понимаю даже, где возникла сложность и зачем вам JS. Быстрый набросок кода:
final int selectedDays = 4;
driver.get("http://www.classicvacations.com/hotels/caribbean/turks-caicos/amanyara");
new Select(driver.findElement(By.id("num_nights"))).selectByIndex(selectedDays);
driver.findElement(By.id("day_25")).click();
Assert.assertEquals(
driver.findElements(By.xpath("//div[contains(@class, 'selected')]")).size(),
selectedDays);
Причем, у календаря все ячейки пронумерованы через id, т.е. вам не составит никакого труда формировать локатор динамически, подставляя соответствующий индекс.
Если вам нужно именно пролистать календарь до нужного года месяца - тоже не вижу в этом никакой проблемы, и надобности применять JS. Ну а как кликнуть выделить ячейки - сказано постом выше
Вот это мне и не совсем понятно. Как определить нужный id ячейки - ведь 25 ячейка, не всегда 25 число. Если только искать по присутствию текста. Но ведь у меня в одном календаре может быть несколько первых и вторых и третьих чисел.
Конкретно в этом календаре “кликабельные” дни имеет класс ‘vcell cursorstyle’ и вполне адекватный onclick с датой.
Но у них разные id, если посмотреть. То есть можно отделить предыдущий месяц от текущего.
Попробую для себя сформулировать как я понял советы. Разбирает дату на строку и месяц. С помощью какой нибудь Map - переводим цифру месяца в строку и ищем ее. Дальше, получается список элементов календаря с классом vcell cursorstyle (например) - и через for-each ищем соответствие атрибута ячейки - входной дате.
Получается так:
1)разбираем дату
2)выбираем месяц(ведь он тоже может быть не текущий)
3)ищем среди vcell cursorstyle нужную дату и жмем. Для каждого месяца выбрать можно только числа именно его месяца, так что тут и отсекать не придется возможно ничего.
4)проверяем, что следующие даты выделены.
Вообщем вы суть правильно уловили
А зачем переводить цифры месяца во что-либо? Как уже сказал выше @vmaximv, td.cursorstyle
содержит
onclick="checkInDateClicked('25', '12/24/2014', '12/26/2014');"
где первый параметр - индекс (который присутствует в id). Второй / третий - рендж (текущая дата ячейки + дата со смещением в кол-во дней, что вы выбрали в селекторе). Т.е. задав expected date в формате MM/dd/yyyy
, вы сможете кликать по элементу в зависимости от содержимого onclick
. Тут вам сразу будет и проверка на то, что нужная вам дата кликабельна. Как проверить кол-во выделенных ячеек - я написал выше. А конкретные даты опять-таки вытягиваются из onclick
+ сравнение с expected диапазоном. Хотя, если у вас будут неверные данные в onclick
, это отразиться на результатах. Т.е. в принципе можно и перестраховаться, анализируя отображаемое значение. Зависит от того, что вы тестируете - сам календарь, или функционал брони.
П.С. Манипуляции с датами лучше всего осуществлять при помощи библиотеки Joda Time.
А , и точно. Не обратил внимание на ответ от @vmaximv.
Тогда задача упрощается до нельзя
ПС: если нужно просто распарсить такую дату - есть стандартный класс DateFormat, там дата парсится в 2 строчки. А подключение JodaTime - это лишние зависимости в проекте. Хотя ничего против этой библиотеки не имею.
Много слышал про JodaTime, но случая не было попробовать. И судя по вышеприведенным ответам и не придется пока.
А вот здесь уже не совсем понятно. Как с помощью WebDriver вытащить данные из события OnClick
element.getAttribute(“onClick”)
Спасибо огромное.
Попробовал так.
@FindBy(id = "rate_calendar")
private WebElement calendarWidget;
private void setDateOnCalendar(String checkIn) {
List<WebElement> ActivecalendarCells = calendarWidget.findElements(By.cssSelector(".cursorstyle"));
List <String> sn = null;
for(WebElement e : ActivecalendarCells){
String s = e.getAttribute("onClick");
sn.add(s);
}
}
Выдает исключение:
org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
На строчке:
String s = e.getAttribute("onClick");
Во-первых, просто .cursorstyle
выдает чуть больше элементов, чем нужно. Я ведь не зря писал:
Во-вторых, ваш календарик очень тормознутый в принципе. Т.е. ему нужно некоторое время, чтобы понять, что вообще вокруг происходит. Вывод, я думаю, сможете сделать сами.
Я работаю не совсем ним) Но вообще ошибка была в другом. Сейчас метод выглядит так
assertThat(calendarWidget, should(isDisplayed()).whileWaitingUntil(timeoutHasExpired(TimeUnit.SECONDS.toMillis(30))));
int n = ActivecalendarCells.size();
String[] sn = new String[n];
for (int i = 0; i < n; i++) {
WebElement e = ActivecalendarCells.get(i);
String s = e.getAttribute("onclick");
sn[i] = s;
}
Вроде бы все отрабатывает корректно. Хотя первая строчка подхватывается неверно
getHotelRateCalendar('1')
Но это не великая беда. А вот как разобрать такое выражение
checkInDateClicked('27', '12/26/2014', '01/04/2015');
Но это уже я так понимаю, решается с помощью reg exp
Возможно, не совсем именно про такой календарик, но: