/** * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at the * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Initial code contributed and copyrighted by<br> * frentix GmbH, http://www.frentix.com * <p> */ package org.olat.selenium.page.core; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; import java.util.List; import org.jboss.arquillian.drone.api.annotation.Drone; import org.junit.Assert; import org.olat.core.util.StringHelper; import org.olat.selenium.page.graphene.OOGraphene; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.Select; /** * Drive the calendar * * Initial date: 27.02.2015<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class CalendarPage { public static final By calendarToolbatBy = By.className("o_cal_toptoolbar"); private final DateTimeFormatter formatter = new DateTimeFormatterBuilder() .appendValue(ChronoField.YEAR, 4) .appendLiteral('-') .appendValue(ChronoField.MONTH_OF_YEAR, 2) .appendLiteral('-') .appendValue(ChronoField.DAY_OF_MONTH, 2) .toFormatter(); private final DateTimeFormatter oocurenceIdFormatter = new DateTimeFormatterBuilder() .appendValue(ChronoField.YEAR, 4) .appendValue(ChronoField.MONTH_OF_YEAR, 2) .appendValue(ChronoField.DAY_OF_MONTH, 2) .toFormatter(); @Drone private WebDriver browser; public CalendarPage() { // } public CalendarPage(WebDriver browser) { this.browser = browser; } /** * Don't forget that the calendar is a javascript application. You need * to wait until scripts, css and data are loaded before asserting. * * @return The calendar page */ public CalendarPage assertOnCalendar() { List<WebElement> calendarToolbarsEl = browser.findElements(calendarToolbatBy); Assert.assertFalse(calendarToolbarsEl.isEmpty()); return this; } /** * Add an event but don't fill the form. * * @param day * @param subject * @return */ public CalendarPage addEvent(int day) { LocalDate date = LocalDate.now().withDayOfMonth(day); String dateString = date.format(formatter); By cellBy = By.xpath("//div[contains(@class,'o_cal')]//td[contains(@data-date,'" + dateString + "')]//div[contains(@class,'fc-day-content')]"); browser.findElement(cellBy).click(); OOGraphene.waitModalDialog(browser); return this; } public CalendarPage setDescription(String subject, String description, String location) { if(StringHelper.containsNonWhitespace(subject)) { By subjectBy = By.cssSelector("fieldset.o_sel_cal_entry_form div.o_sel_cal_subject input[type='text']"); WebElement subjectEl = browser.findElement(subjectBy); subjectEl.clear(); subjectEl.sendKeys(subject); } if(StringHelper.containsNonWhitespace(description)) { By descriptionBy = By.cssSelector("fieldset.o_sel_cal_entry_form div.o_sel_cal_description textarea"); browser.findElement(descriptionBy).sendKeys(description); } if(StringHelper.containsNonWhitespace(location)) { By locationBy = By.cssSelector("fieldset.o_sel_cal_entry_form div.o_sel_cal_location input[type='text']"); browser.findElement(locationBy).sendKeys(location); } return this; } public CalendarPage setAllDay(boolean allDay) { By locationBy = By.cssSelector("fieldset.o_sel_cal_entry_form div.o_sel_cal_all_day input[type='checkbox']"); WebElement allDayEl = browser.findElement(locationBy); OOGraphene.check(allDayEl, new Boolean(allDay)); if(!allDay) { By hourBy = By.xpath("//fieldset[contains(@class,'o_sel_cal_entry_form')]//div[contains(@class,'o_sel_cal_begin')]//input[contains(@id,'o_dch_')]"); OOGraphene.waitElement(hourBy, 5, browser); } return this; } public CalendarPage setBeginEnd(int beginHour, int endHour) { By beginHourBy = By.xpath("//fieldset[contains(@class,'o_sel_cal_entry_form')]//div[contains(@class,'o_sel_cal_begin')]//input[starts-with(@id,'o_dch_')]"); WebElement beginHourEl = browser.findElement(beginHourBy); beginHourEl.clear(); beginHourEl.sendKeys(Integer.toString(beginHour)); By endHourBy = By.xpath("//fieldset[contains(@class,'o_sel_cal_entry_form')]//div[contains(@class,'o_sel_cal_end')]//input[starts-with(@id,'o_dch_')]"); WebElement endHourEl = browser.findElement(endHourBy); endHourEl.clear(); endHourEl.sendKeys(Integer.toString(endHour)); return this; } public CalendarPage setRecurringEvent(String recur, int day) { By recurrenceBy = By.id("o_fiocal_form_recurrence_SELBOX"); WebElement recurrenceEl = browser.findElement(recurrenceBy); new Select(recurrenceEl).selectByValue(recur); OOGraphene.waitBusy(browser); //By untilBy = By.cssSelector("fieldset.o_sel_cal_entry_form div.o_sel_cal_until input[type='text']"); By untilAltBy = By.cssSelector("fieldset.o_sel_cal_entry_form div.o_sel_cal_until span.input-group-addon i"); OOGraphene.waitElement(untilAltBy, 5, browser); browser.findElement(untilAltBy).click(); OOGraphene.waitGui(browser); selectDayInDatePicker(day); return this; } private CalendarPage selectDayInDatePicker(int day) { By datePickerBy = By.id("ui-datepicker-div"); OOGraphene.waitElement(datePickerBy, 5, browser); By dayBy = By.xpath("//div[@id='ui-datepicker-div']//td//a[normalize-space(text())='" + day + "']"); OOGraphene.waitElement(dayBy, 5, browser); browser.findElement(dayBy).click(); OOGraphene.waitElementUntilNotVisible(datePickerBy, 5, browser); //OOGraphene.waitingALittleBit(); return this; } public CalendarPage save() { By saveBy = By.cssSelector("fieldset.o_sel_cal_entry_form button.btn.btn-primary span"); OOGraphene.waitElement(saveBy, 5, browser); WebElement saveEl = browser.findElement(saveBy); OOGraphene.moveTo(saveEl, browser) .click(); OOGraphene.waitBusy(browser); return this; } public CalendarPage confirmModifyOneOccurence() { By saveOneBy = By.cssSelector("div.modal-dialog a.o_sel_cal_update_one"); OOGraphene.waitElement(saveOneBy, 5, browser); browser.findElement(saveOneBy).click(); OOGraphene.waitBusy(browser); return this; } public CalendarPage confirmModifyAllOccurences() { By saveAllBy = By.cssSelector("div.modal-dialog a.o_sel_cal_update_all"); OOGraphene.waitElement(saveAllBy, 5, browser); browser.findElement(saveAllBy).click(); OOGraphene.waitBusy(browser); return this; } public CalendarPage delete() { By deleteBy = By.cssSelector("fieldset.o_sel_cal_entry_form a.btn.o_sel_cal_delete"); OOGraphene.waitElement(deleteBy, 5, browser); browser.findElement(deleteBy).click(); OOGraphene.waitBusy(browser); return this; } public CalendarPage confirmDeleteOneOccurence() { By deleteOneBy = By.cssSelector("div.modal-dialog a.o_sel_cal_delete_one"); OOGraphene.waitElement(deleteOneBy, 5, browser); browser.findElement(deleteOneBy).click(); OOGraphene.waitBusy(browser); return this; } public CalendarPage confirmDeleteFuturOccurences() { By deleteFutureBy = By.cssSelector("div.modal-dialog a.o_sel_cal_delete_future_events"); OOGraphene.waitElement(deleteFutureBy, 5, browser); browser.findElement(deleteFutureBy).click(); OOGraphene.waitBusy(browser); return this; } public CalendarPage confirmDeleteAllOccurences() { By deleteAllBy = By.cssSelector("div.modal-dialog a.o_sel_cal_delete_all"); OOGraphene.waitElement(deleteAllBy, 5, browser); browser.findElement(deleteAllBy).click(); OOGraphene.waitBusy(browser); return this; } public CalendarPage assertOnEvent(String subject) { By titleBy = By.xpath("//div[@class='o_cal']//span[contains(text(),'" + subject + "')]"); OOGraphene.waitElement(titleBy, 5, browser); Assert.assertNotNull(browser.findElement(titleBy)); return this; } public CalendarPage assertOnEvents(String subject, int numOfEvents) { By titleBy = By.xpath("//div[@class='o_cal']//span[contains(text(),'" + subject + "')]"); OOGraphene.waitElement(titleBy, 5, browser); List<WebElement> eventEls = browser.findElements(titleBy); Assert.assertEquals(numOfEvents, eventEls.size()); return this; } public CalendarPage assertOnEventsAt(String subject, int numOfEvents, int atHour) { By titleBy = By.xpath("//div[@class='o_cal']//div[contains(@class,'fc-event-inner')][span[contains(text(),'" + atHour + ".00')]]/span[contains(text(),'" + subject + "')]"); OOGraphene.waitElement(titleBy, 5, browser); List<WebElement> eventEls = browser.findElements(titleBy); Assert.assertEquals(numOfEvents, eventEls.size()); return this; } public CalendarPage assertZeroEvent() { By eventsBy = By.xpath("//div[@class='fc-event-container']/div"); List<WebElement> eventEls = browser.findElements(eventsBy); Assert.assertEquals(0, eventEls.size()); return this; } public CalendarPage openDetails(String subject) { By titleBy = By.xpath("//div[@class='o_cal']//span[contains(text(),'" + subject + "')]"); OOGraphene.waitElement(titleBy, 5, browser); browser.findElement(titleBy).click(); OOGraphene.waitCallout(browser); return this; } public CalendarPage openDetailsOccurence(String subject, int day) { LocalDate date = LocalDate.now().withDayOfMonth(day); String dateString = date.format(oocurenceIdFormatter); By titleBy = By.xpath("//div[@class='o_cal']//div[contains(@id,'xOccOOccOx_" + dateString + "')]//span[contains(text(),'" + subject + "')]"); OOGraphene.waitElement(titleBy, 5, browser); browser.findElement(titleBy).click(); OOGraphene.waitCallout(browser); return this; } /** * The details callout need to be open. * * @return Itself */ public CalendarPage edit() { By editBy = By.cssSelector("div.popover-content div.o_callout_content div.o_cal_tooltip_buttons a.btn.btn-default"); OOGraphene.waitElement(editBy, 5, browser); browser.findElement(editBy).click(); OOGraphene.waitModalDialog(browser); return this; } }