From afba6d6bfa58bb98221527665051e620d1ce3bcb Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Thu, 23 Jul 2015 21:18:04 +0200
Subject: [PATCH] no-jira: selenium test for concurrent use of the forum in a
 course

---
 .../org/olat/modules/fo/ForumController.java  |   2 +
 .../modules/fo/MessageEditController.java     |   3 +
 .../java/org/olat/selenium/CourseTest.java    | 129 ++++++++++++++++++
 .../olat/selenium/page/forum/ForumPage.java   |  62 +++++++--
 4 files changed, 186 insertions(+), 10 deletions(-)

diff --git a/src/main/java/org/olat/modules/fo/ForumController.java b/src/main/java/org/olat/modules/fo/ForumController.java
index b64cf4208e2..436719b2a18 100644
--- a/src/main/java/org/olat/modules/fo/ForumController.java
+++ b/src/main/java/org/olat/modules/fo/ForumController.java
@@ -1276,8 +1276,10 @@ public class ForumController extends BasicController implements GenericEventList
 		edLink.setIconLeftCSS("o_icon o_icon-fw o_icon_edit");
 
 		Link qtLink = LinkFactory.createCustomLink("qt_"+msgCount, "qt_"+msgCount, "msg.quote", Link.BUTTON_SMALL, vcThreadView, this);
+		qtLink.setElementCssClass("o_sel_forum_reply_quoted");
 		qtLink.setIconLeftCSS("o_icon o_icon-fw o_icon_reply_with_quote");
 		Link rpLink = LinkFactory.createCustomLink("rp_"+msgCount, "rp_"+msgCount, "msg.reply", Link.BUTTON_SMALL, vcThreadView, this);
+		rpLink.setElementCssClass("o_sel_forum_reply");
 		rpLink.setIconLeftCSS("o_icon o_icon-fw o_icon_reply");
 
 		Link splitLink = LinkFactory.createCustomLink("split_"+msgCount, "split_"+msgCount, "msg.split", Link.LINK, vcThreadView, this);
diff --git a/src/main/java/org/olat/modules/fo/MessageEditController.java b/src/main/java/org/olat/modules/fo/MessageEditController.java
index f87c9ab80c5..e057a0fe33e 100644
--- a/src/main/java/org/olat/modules/fo/MessageEditController.java
+++ b/src/main/java/org/olat/modules/fo/MessageEditController.java
@@ -146,7 +146,10 @@ public class MessageEditController extends FormBasicController {
 	 */
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		formLayout.setElementCssClass("o_sel_forum_message_form");
+		
 		msgTitle = uifactory.addTextElement("msgTitle", "msg.title", 100, message.getTitle(), formLayout);
+		msgTitle.setElementCssClass("o_sel_forum_message_title");
 		msgTitle.setMandatory(true);
 		msgTitle.setNotEmptyCheck("error.field.not.empty");
 		msgBody = uifactory.addRichTextElementForStringData("msgBody", "msg.body", message.getBody(), 15, -1, true, null, null,
diff --git a/src/test/java/org/olat/selenium/CourseTest.java b/src/test/java/org/olat/selenium/CourseTest.java
index 3f8d2719188..3e69beda06b 100644
--- a/src/test/java/org/olat/selenium/CourseTest.java
+++ b/src/test/java/org/olat/selenium/CourseTest.java
@@ -43,6 +43,7 @@ import org.olat.selenium.page.Administrator;
 import org.olat.selenium.page.LoginPage;
 import org.olat.selenium.page.NavigationPage;
 import org.olat.selenium.page.Participant;
+import org.olat.selenium.page.Student;
 import org.olat.selenium.page.User;
 import org.olat.selenium.page.core.BookingPage;
 import org.olat.selenium.page.core.MenuTreePageFragment;
@@ -53,6 +54,7 @@ import org.olat.selenium.page.course.InfoMessageCEPage;
 import org.olat.selenium.page.course.PublisherPageFragment;
 import org.olat.selenium.page.course.RemindersPage;
 import org.olat.selenium.page.course.PublisherPageFragment.Access;
+import org.olat.selenium.page.forum.ForumPage;
 import org.olat.selenium.page.graphene.OOGraphene;
 import org.olat.selenium.page.repository.AuthoringEnvPage;
 import org.olat.selenium.page.repository.FeedPage;
@@ -1128,4 +1130,131 @@ public class CourseTest {
 		ryomouCourse
 			.assertOnTitle(infoTitle);
 	}
+	
+	/**
+	 * An author creates a course with a forum, publish it, open a new thread.
+	 * A first user come to see the thread. A second come via the peekview.
+	 * The three make a reply at the same time. And they check that they see
+	 * the replies, and the ones of the others.
+	 * 
+	 * @param loginPage
+	 * @param kanuBrowser
+	 * @param reiBrowser
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void concurrentForum(@InitialPage LoginPage loginPage,
+			@Drone @Participant WebDriver kanuBrowser,
+			@Drone @Student WebDriver reiBrowser)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		UserVO kanu = new UserRestClient(deploymentUrl).createRandomUser("Kanu");
+		UserVO rei = new UserRestClient(deploymentUrl).createRandomUser("Rei");
+		loginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//create a course
+		String courseTitle = "Course FO " + UUID.randomUUID();
+		navBar
+			.openAuthoringEnvironment()
+			.createCourse(courseTitle)
+			.clickToolbarBack();
+	
+		//go the authoring environment to create a forum
+		String foTitle = "FO - " + UUID.randomUUID();
+		CourseEditorPageFragment courseEditor = CoursePageFragment.getCourse(browser)
+			.edit();
+		courseEditor
+			.createNode("fo")
+			.nodeTitle(foTitle)
+		//publish the course
+			.publish()
+			.quickPublish(Access.users);
+		
+		//go to the forum
+		courseEditor
+			.clickToolbarBack()
+			.clickTree()
+			.selectWithTitle(foTitle.substring(0, 20));
+		
+		ForumPage authorForum = ForumPage
+			.getCourseForumPage(browser);
+		authorForum
+			.createThread("The best anime ever", "What is the best anime ever?");
+		
+		//First user go to the course
+		LoginPage kanuLoginPage = LoginPage.getLoginPage(kanuBrowser, deploymentUrl);
+		kanuLoginPage
+			.loginAs(kanu.getLogin(), kanu.getPassword())
+			.resume();
+
+		NavigationPage kanuNavBar = new NavigationPage(kanuBrowser);
+		kanuNavBar
+			.openMyCourses()
+			.openSearch()
+			.extendedSearch(courseTitle)
+			.select(courseTitle)
+			.start();
+		
+		//go to the forum
+		new CoursePageFragment(kanuBrowser)
+			.clickTree()
+			.selectWithTitle(foTitle.substring(0, 20));
+		
+		ForumPage kanuForum = ForumPage
+			.getCourseForumPage(kanuBrowser)
+			.openThread("The best anime ever");
+
+		
+		//First user go to the course
+		LoginPage reiLoginPage = LoginPage.getLoginPage(reiBrowser, deploymentUrl);
+		reiLoginPage
+			.loginAs(rei)
+			.resume();
+
+		NavigationPage reiNavBar = new NavigationPage(reiBrowser);
+		reiNavBar
+			.openMyCourses()
+			.openSearch()
+			.extendedSearch(courseTitle)
+			.select(courseTitle)
+			.start();
+		//select the thread in peekview
+		ForumPage reiForum = new ForumPage(reiBrowser)
+			.openThreadInPeekview("The best anime ever");
+		
+		//concurrent reply
+		String kanuReply = "Ikki Touzen";
+		String reiReply = "Neon Genesis Evangelion";
+		String authorReply = "Lain, serial experiment";
+		
+		authorForum
+			.replyToMessageNoWait("The best anime ever", null, authorReply);
+		reiForum
+			.replyToMessageNoWait("The best anime ever", null, reiReply);
+		kanuForum
+			.replyToMessageNoWait("The best anime ever", null, kanuReply);
+	
+		//wait the responses
+		OOGraphene.waitBusy(browser);
+		OOGraphene.waitBusy(kanuBrowser);
+		OOGraphene.waitBusy(reiBrowser);
+		
+		//check own responses
+		authorForum.assertMessageBody(authorReply);
+		kanuForum.assertMessageBody(kanuReply);
+		reiForum.assertMessageBody(reiReply);
+
+		//check others responses
+		authorForum
+			.flatView()
+			.waitMessageBody(kanuReply);
+		reiForum
+			.flatView()
+			.waitMessageBody(kanuReply);
+		kanuForum
+			.flatView()
+			.waitMessageBody(reiReply);
+	}
 }
diff --git a/src/test/java/org/olat/selenium/page/forum/ForumPage.java b/src/test/java/org/olat/selenium/page/forum/ForumPage.java
index 19870733aa5..d99e830b9a7 100644
--- a/src/test/java/org/olat/selenium/page/forum/ForumPage.java
+++ b/src/test/java/org/olat/selenium/page/forum/ForumPage.java
@@ -21,8 +21,6 @@ package org.olat.selenium.page.forum;
 
 import java.util.List;
 
-import org.jboss.arquillian.drone.api.annotation.Drone;
-import org.jboss.arquillian.graphene.Graphene;
 import org.junit.Assert;
 import org.olat.selenium.page.graphene.OOGraphene;
 import org.olat.selenium.page.portfolio.ArtefactWizardPage;
@@ -39,14 +37,9 @@ import org.openqa.selenium.WebElement;
  *
  */
 public class ForumPage {
-	
-	@Drone
+
 	private WebDriver browser;
 	
-	public ForumPage() {
-		//
-	}
-	
 	public ForumPage(WebDriver browser) {
 		this.browser = browser;
 	}
@@ -64,14 +57,14 @@ public class ForumPage {
 	
 		By mainBy = By.cssSelector("div.o_course_run");
 		WebElement main = browser.findElement(mainBy);
-		return Graphene.createPageFragment(ForumPage.class, main);
+		Assert.assertTrue(main.isDisplayed());
+		return new ForumPage(browser);
 	}
 	
 	public static ForumPage getGroupForumPage(WebDriver browser) {
 		By forumBy = By.cssSelector("div.o_forum");
 		List<WebElement> forumEl = browser.findElements(forumBy);
 		Assert.assertFalse(forumEl.isEmpty());
-	
 		return new ForumPage(browser);
 	}
 	
@@ -103,6 +96,27 @@ public class ForumPage {
 		return this;
 	}
 	
+	public ForumPage openThread(String title) {
+		By threadBy = By.xpath("//table[contains(@class,'o_table')]//tr//a[span[text()='" + title + "']]");
+		browser.findElement(threadBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	public ForumPage openThreadInPeekview(String title) {
+		By threadBy = By.xpath("//div[contains(@class,'o_forum_peekview_message')]//a[span[text()='" + title + "']]");
+		browser.findElement(threadBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	public ForumPage flatView() {
+		By flatBy = By.cssSelector("input[value='flat'][type='radio']");
+		browser.findElement(flatBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
 	public ForumPage assertMessageBody(String text) {
 		By messageBodyBy = By.className("o_forum_message_body");
 		List<WebElement> messages = browser.findElements(messageBodyBy);
@@ -116,6 +130,34 @@ public class ForumPage {
 		return this;
 	}
 	
+	public ForumPage waitMessageBody(String text) {
+		By messageBy = By.xpath("//div[contains(@class,'o_forum_message_body')][//p[contains(text(),'" + text + "')]]");
+		OOGraphene.waitElement(messageBy, 10, browser);
+		return this;
+	}
+
+	public ForumPage replyToMessage(String reference, String title, String reply) {
+		replyToMessageNoWait(reference, title, reply);
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	public ForumPage replyToMessageNoWait(String reference, String title, String reply) {
+		By replyBy = By.xpath("//div[contains(@class,'o_forum_message')][//h4[contains(text(),'" + reference + "')]]//a[contains(@class,'o_sel_forum_reply')]");
+		browser.findElement(replyBy).click();
+		OOGraphene.waitBusy(browser);
+		
+		if(title != null) {
+			By titleBy = By.cssSelector(".o_sel_forum_message_title input[type='text']");
+			browser.findElement(titleBy).sendKeys(title);
+		}
+		OOGraphene.tinymce(reply, browser);
+		
+		By saveBy = By.cssSelector("fieldset.o_sel_forum_message_form button.btn-primary");
+		browser.findElement(saveBy).click();
+		return this;
+	}
+	
 	/**
 	 * Add the thread to my artefacts
 	 * 
-- 
GitLab