From 9d7969c98d859df726e9bb181d5aa5332904f95b Mon Sep 17 00:00:00 2001
From: hg <none@none>
Date: Tue, 15 Nov 2016 20:10:45 +0100
Subject: [PATCH] OO-2019: selenium test base on feedback of sscheiwiler

---
 .../calendar/ui/CalendarEntryForm.java        |  2 +-
 .../calendar/ui/ConfirmDeleteController.java  |  1 +
 .../config/ui/CourseOptionsController.java    |  2 +
 .../org/olat/selenium/BusinessGroupTest.java  |  4 +-
 .../java/org/olat/selenium/CourseTest.java    | 91 +++++++++++++++++--
 .../olat/selenium/page/core/CalendarPage.java | 31 +++++--
 .../page/course/CourseOptionsPage.java        | 63 +++++++++++++
 .../page/course/CoursePageFragment.java       | 11 +++
 .../selenium/page/graphene/OOGraphene.java    | 12 +++
 9 files changed, 198 insertions(+), 19 deletions(-)
 create mode 100644 src/test/java/org/olat/selenium/page/course/CourseOptionsPage.java

diff --git a/src/main/java/org/olat/commons/calendar/ui/CalendarEntryForm.java b/src/main/java/org/olat/commons/calendar/ui/CalendarEntryForm.java
index 465722a2c30..b949d274962 100644
--- a/src/main/java/org/olat/commons/calendar/ui/CalendarEntryForm.java
+++ b/src/main/java/org/olat/commons/calendar/ui/CalendarEntryForm.java
@@ -381,7 +381,7 @@ public class CalendarEntryForm extends FormBasicController {
 		
 		classification = uifactory.addRadiosVertical("classification", "cal.form.class", formLayout, classKeys, classValues);
 		classification.setHelpUrlForManualPage("Calendar#_visibility");
-		classification.setHelpTextKey("cal.form.class.hover", null);
+		//classification.setHelpTextKey("cal.form.class.hover", null);
 		classification.setEnabled(!CalendarManagedFlag.isManaged(event, CalendarManagedFlag.classification));
 		switch (event.getClassification()) {
 			case KalendarEvent.CLASS_PRIVATE: classification.select("0", true); break;
diff --git a/src/main/java/org/olat/commons/calendar/ui/ConfirmDeleteController.java b/src/main/java/org/olat/commons/calendar/ui/ConfirmDeleteController.java
index 903047cf534..4696602d8b0 100644
--- a/src/main/java/org/olat/commons/calendar/ui/ConfirmDeleteController.java
+++ b/src/main/java/org/olat/commons/calendar/ui/ConfirmDeleteController.java
@@ -62,6 +62,7 @@ public class ConfirmDeleteController extends BasicController {
 					deleteAllButton.setElementCssClass("o_sel_cal_delete_all");
 				} else {
 					deleteFutureButton = LinkFactory.createButton("delete.future", mainVC, this);
+					deleteFutureButton.setElementCssClass("o_sel_cal_delete_future_events");
 				}
 				deleteOneButton = LinkFactory.createButton("delete.one", mainVC, this);
 				deleteOneButton.setElementCssClass("o_sel_cal_delete_one");
diff --git a/src/main/java/org/olat/course/config/ui/CourseOptionsController.java b/src/main/java/org/olat/course/config/ui/CourseOptionsController.java
index e8ed5f8a032..76ad1da8f71 100644
--- a/src/main/java/org/olat/course/config/ui/CourseOptionsController.java
+++ b/src/main/java/org/olat/course/config/ui/CourseOptionsController.java
@@ -201,6 +201,7 @@ public class CourseOptionsController extends FormBasicController {
 			boolean calendarEnabled = courseConfig.isCalendarEnabled();
 			boolean managedCal = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.calendar);
 			calendarEl = uifactory.addCheckboxesHorizontal("calIsOn", "chkbx.calendar.onoff", calendarCont, onKeys, onValues);
+			calendarEl.setElementCssClass("o_sel_course_options_calendar");
 			calendarEl.addActionListener(FormEvent.ONCHANGE);
 			calendarEl.select("xx", calendarEnabled);
 			calendarEl.setEnabled(editable && !managedCal);
@@ -280,6 +281,7 @@ public class CourseOptionsController extends FormBasicController {
 			saveCont.setRootForm(mainForm);
 			formLayout.add(saveCont);
 			saveButton = uifactory.addFormLink("save", saveCont, Link.BUTTON);
+			saveButton.setElementCssClass("o_sel_course_options_save");
 			saveButton.setPrimary(true);
 		}
 	}
diff --git a/src/test/java/org/olat/selenium/BusinessGroupTest.java b/src/test/java/org/olat/selenium/BusinessGroupTest.java
index d3066be42a8..bde32fff1b8 100644
--- a/src/test/java/org/olat/selenium/BusinessGroupTest.java
+++ b/src/test/java/org/olat/selenium/BusinessGroupTest.java
@@ -671,7 +671,7 @@ public class BusinessGroupTest {
 			.edit()
 			.setDescription("Special", null, null)
 			.save()
-			.configureModifyOneOccurence()
+			.confirmModifyOneOccurence()
 			.assertOnEvents("Special", 1)
 			.assertOnEvents("Recurring", 3);
 		
@@ -681,7 +681,7 @@ public class BusinessGroupTest {
 			.edit()
 			.setBeginEnd(11, 12).assertOnEvents("Special", 1)
 			.save()
-			.configureModifyAllOccurences()
+			.confirmModifyAllOccurences()
 			.assertOnEventsAt("Recurring", 3, 11);
 	}
 	
diff --git a/src/test/java/org/olat/selenium/CourseTest.java b/src/test/java/org/olat/selenium/CourseTest.java
index 0d287797958..f11e8b29dfe 100644
--- a/src/test/java/org/olat/selenium/CourseTest.java
+++ b/src/test/java/org/olat/selenium/CourseTest.java
@@ -1185,7 +1185,7 @@ public class CourseTest {
 		navBar.openCourse(courseTitle);
 		
 		String calendarNodeTitle = "iCal-1";
-		//create a course element of type CP with the CP that we create above
+		//create a course element of type calendar
 		CourseEditorPageFragment courseEditor = CoursePageFragment.getCourse(browser)
 			.edit();
 		courseEditor
@@ -1197,7 +1197,7 @@ public class CourseTest {
 			.publish()
 			.quickPublish();
 		
-		//open the course and see the CP
+		//open the course and see the calendar
 		CoursePageFragment course = courseEditor
 			.clickToolbarBack();
 		course
@@ -1218,7 +1218,7 @@ public class CourseTest {
 			.setAllDay(false)
 			.setBeginEnd(13, 15)
 			.save()
-			.configureModifyOneOccurence();
+			.confirmModifyOneOccurence();
 		
 		// check
 		calendar
@@ -1231,7 +1231,7 @@ public class CourseTest {
 			.edit()
 			.setDescription("Eventoki", null, null)
 			.save()
-			.configureModifyAllOccurences();
+			.confirmModifyAllOccurences();
 		// check
 		calendar
 			.assertOnEvents("Eventoki", 3)
@@ -1242,7 +1242,7 @@ public class CourseTest {
 			.openDetailsOccurence("Eventoki", 10)
 			.edit()
 			.delete()
-			.configureDeleteOneOccurence();
+			.confirmDeleteOneOccurence();
 		// check
 		calendar
 			.assertOnEvents("Eventoki", 2)
@@ -1253,13 +1253,90 @@ public class CourseTest {
 			.openDetailsOccurence("Eventoki", 3)
 			.edit()
 			.delete()
-			.configureDeleteAllOccurences();
+			.confirmDeleteAllOccurences();
 		
 		OOGraphene.waitingALittleBit();
 		calendar
 			.assertZeroEvent();
 	}
-
+	
+	/**
+	 * This is a variant of the test above based on the
+	 * feedback of our beta-testerin.
+	 * 
+	 * @param loginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void courseWithCalendar_alt(@InitialPage LoginPage loginPage)
+	throws IOException, URISyntaxException {
+		
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		loginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//create a course
+		String courseTitle = "Course-iCal-" + UUID.randomUUID();
+		navBar
+			.openAuthoringEnvironment()
+			.createCourse(courseTitle)
+			.clickToolbarBack();
+		
+		navBar.openCourse(courseTitle);
+		
+		// activate the calendar options
+		CoursePageFragment course = CoursePageFragment.getCourse(browser);
+		course
+			.options()
+			.calendar(Boolean.TRUE)
+			.save()
+			.clickToolbarBack();
+		
+		String calendarNodeTitle = "iCal-2";
+		//create a course element of type calendar
+		CourseEditorPageFragment courseEditor = CoursePageFragment.getCourse(browser)
+			.edit();
+		courseEditor
+			.createNode("cal")
+			.nodeTitle(calendarNodeTitle);
+		
+		//publish the course
+		course = courseEditor
+			.autoPublish();
+		//open the course and see the CP
+		course
+			.clickTree()
+			.selectWithTitle(calendarNodeTitle);
+		
+		// create a recurring event
+		CalendarPage calendar = new CalendarPage(browser);
+		calendar
+			.addEvent(2)
+			.setDescription("Repeat", "Loop", "Foreach")
+			.setAllDay(false)
+			.setBeginEnd(14, 18)
+			.setRecurringEvent(KalendarEvent.WEEKLY, 28)
+			.save()
+			.assertOnEvents("Repeat", 4);
+		
+		//pick an occurence which is not the first and modify it
+		calendar
+			.openDetailsOccurence("Repeat", 16)
+			.edit()
+			.setBeginEnd(15, 18)
+			.save()
+			.confirmModifyAllOccurences()
+			.assertOnEventsAt("Repeat", 4, 15);
+		
+		// delete futur event of the same event as above
+		calendar
+			.openDetailsOccurence("Repeat", 16)
+			.edit()
+			.delete()
+			.confirmDeleteFuturOccurences()
+			.assertOnEventsAt("Repeat", 2, 15);
+	}
 	
 	/**
 	 * An author creates a course, make it visible for
diff --git a/src/test/java/org/olat/selenium/page/core/CalendarPage.java b/src/test/java/org/olat/selenium/page/core/CalendarPage.java
index ece5f75066b..f2a6b9c90a0 100644
--- a/src/test/java/org/olat/selenium/page/core/CalendarPage.java
+++ b/src/test/java/org/olat/selenium/page/core/CalendarPage.java
@@ -146,11 +146,13 @@ public class CalendarPage {
 		By recurrenceBy = By.id("o_fiocal_form_recurrence_SELBOX");
 		WebElement recurrenceEl = browser.findElement(recurrenceBy);
 		new Select(recurrenceEl).selectByValue(recur);
+		OOGraphene.waitBusy(browser);
 		
-		//LocalDate date = LocalDate.now().withDayOfMonth(day);
-		By untilBy = By.cssSelector("fieldset.o_sel_cal_entry_form div.o_sel_cal_until input[type='text']");
-		OOGraphene.waitElement(untilBy, 5, browser);
-		browser.findElement(untilBy).click();
+		//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;
@@ -171,12 +173,15 @@ public class CalendarPage {
 	public CalendarPage save() {
 		By saveBy = By.cssSelector("fieldset.o_sel_cal_entry_form button.btn.btn-primary");
 		OOGraphene.waitElement(saveBy, 5, browser);
-		browser.findElement(saveBy).click();
+		
+		WebElement saveEl = browser.findElement(saveBy);
+		OOGraphene.moveTo(saveEl, browser)
+			.click();
 		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
-	public CalendarPage configureModifyOneOccurence() {
+	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();
@@ -184,7 +189,7 @@ public class CalendarPage {
 		return this;
 	}
 	
-	public CalendarPage configureModifyAllOccurences() {
+	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();
@@ -200,7 +205,7 @@ public class CalendarPage {
 		return this;
 	}
 	
-	public CalendarPage configureDeleteOneOccurence() {
+	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();
@@ -208,7 +213,15 @@ public class CalendarPage {
 		return this;
 	}
 	
-	public CalendarPage configureDeleteAllOccurences() {
+	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();
diff --git a/src/test/java/org/olat/selenium/page/course/CourseOptionsPage.java b/src/test/java/org/olat/selenium/page/course/CourseOptionsPage.java
new file mode 100644
index 00000000000..222fb307ee6
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/course/CourseOptionsPage.java
@@ -0,0 +1,63 @@
+/**
+ * <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.course;
+
+import org.olat.selenium.page.NavigationPage;
+import org.olat.selenium.page.graphene.OOGraphene;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+/**
+ * 
+ * Initial date: 15 nov. 2016<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class CourseOptionsPage {
+
+	private WebDriver browser;
+	
+	public CourseOptionsPage(WebDriver browser) {
+		this.browser = browser;
+	}
+	
+	public CourseOptionsPage calendar(Boolean enable) {
+		By calendarBy = By.cssSelector(".o_sel_course_options_calendar input[type='checkbox']");
+		WebElement calendarEl = browser.findElement(calendarBy);
+		OOGraphene.check(calendarEl, enable);
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	public CourseOptionsPage save() {
+		By saveBy = By.cssSelector("a.o_sel_course_options_save");
+		browser.findElement(saveBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	public CoursePageFragment clickToolbarBack() {
+		browser.findElement(NavigationPage.toolbarBackBy).click();
+		OOGraphene.waitBusy(browser);
+		return CoursePageFragment.getCourse(browser);
+	}
+
+}
diff --git a/src/test/java/org/olat/selenium/page/course/CoursePageFragment.java b/src/test/java/org/olat/selenium/page/course/CoursePageFragment.java
index 48f1a20b06c..6527837682a 100644
--- a/src/test/java/org/olat/selenium/page/course/CoursePageFragment.java
+++ b/src/test/java/org/olat/selenium/page/course/CoursePageFragment.java
@@ -171,6 +171,17 @@ public class CoursePageFragment {
 		return new RemindersPage(browser);
 	}
 	
+	public CourseOptionsPage options() {
+		if(!browser.findElement(settingsMenu).isDisplayed()) {
+			openSettingsMenu();
+		}
+		
+		By reminderBy = By.cssSelector("a.o_sel_course_options");
+		browser.findElement(reminderBy).click();
+		OOGraphene.waitBusy(browser);
+		return new CourseOptionsPage(browser);
+	}
+	
 	/**
 	 * Click the editor link in the tools drop-down
 	 * @return
diff --git a/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java b/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java
index a1925c4e60c..47343a3fee7 100644
--- a/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java
+++ b/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java
@@ -35,6 +35,7 @@ import org.openqa.selenium.JavascriptExecutor;
 import org.openqa.selenium.TimeoutException;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
 
 /**
  * 
@@ -87,6 +88,17 @@ public class OOGraphene {
 		Graphene.waitModel(browser).pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until().element(element).is().visible();
 	}
 	
+	public static void waitGui(WebDriver browser) {
+		Graphene.waitGui(browser);
+	}
+	
+	public static WebElement moveTo(WebElement element, WebDriver browser) {
+		Actions actions = new Actions(browser);
+		actions.moveToElement(element);
+		actions.perform();
+		return element;
+	}
+	
 	// top.tinymce.get('o_fi1000000416').setContent('<p>Hacked</p>');
 	// <div id="o_fi1000000416_diw" class="o_richtext_mce"> <iframe id="o_fi1000000416_ifr">
 	public static final void tinymce(String content, WebDriver browser) {
-- 
GitLab