From 6452e287ff73288b82762ee161073ea979c16619 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Thu, 3 Jul 2014 21:57:54 +0200
Subject: [PATCH] OO-1068: 1 selenium test for business groups with 2 browsers

---
 .../group/ui/BusinessGroupFormController.java |   3 +
 .../ui/edit/DisplayMemberSwitchForm.java      |   2 +
 .../org/olat/course/FunctionalCourseTest.java |  80 --------
 .../org/olat/group/FunctionalGroupTest.java   | 190 ------------------
 .../org/olat/selenium/BusinessGroupTest.java  | 128 ++++++++++++
 .../org/olat/selenium/page/LoginPage.java     |  59 +++---
 .../olat/selenium/page/NavigationPage.java    |  34 +++-
 .../org/olat/selenium/page/Participant.java   |  40 ++++
 .../olat/selenium/page/group/GroupPage.java   | 119 +++++++++++
 .../olat/selenium/page/group/GroupsPage.java  |  90 +++++++++
 .../page/group/MembersWizardPage.java         |  97 +++++++++
 .../org/olat/test/rest/UserRestClient.java    |  22 +-
 src/test/resources/arquillian.xml             |   4 +
 13 files changed, 535 insertions(+), 333 deletions(-)
 delete mode 100644 src/test/java/org/olat/group/FunctionalGroupTest.java
 create mode 100644 src/test/java/org/olat/selenium/BusinessGroupTest.java
 create mode 100644 src/test/java/org/olat/selenium/page/Participant.java
 create mode 100644 src/test/java/org/olat/selenium/page/group/GroupPage.java
 create mode 100644 src/test/java/org/olat/selenium/page/group/GroupsPage.java
 create mode 100644 src/test/java/org/olat/selenium/page/group/MembersWizardPage.java

diff --git a/src/main/java/org/olat/group/ui/BusinessGroupFormController.java b/src/main/java/org/olat/group/ui/BusinessGroupFormController.java
index 70da70138fb..df58f6dc977 100644
--- a/src/main/java/org/olat/group/ui/BusinessGroupFormController.java
+++ b/src/main/java/org/olat/group/ui/BusinessGroupFormController.java
@@ -162,6 +162,7 @@ public class BusinessGroupFormController extends FormBasicController {
 			businessGroupName.setNotLongerThanCheck(BusinessGroup.MAX_GROUP_NAME_LENGTH, "create.form.error.nameTooLong");
 			businessGroupName.setRegexMatchCheck(BusinessGroup.VALID_GROUPNAME_REGEXP, "create.form.error.illegalName");
 		}
+		businessGroupName.setElementCssClass("o_sel_group_edit_title");
 		businessGroupName.setMandatory(true);
 		businessGroupName.setEnabled(!BusinessGroupManagedFlag.isManaged(businessGroup, BusinessGroupManagedFlag.title));
 		
@@ -193,10 +194,12 @@ public class BusinessGroupFormController extends FormBasicController {
 		businessGroupMinimumMembers = uifactory.addTextElement("create.form.title.min", "create.form.title.min", 5, "", formLayout);
 		businessGroupMinimumMembers.setDisplaySize(6);
 		businessGroupMinimumMembers.setVisible(false); // currently the minimum feature is not enabled
+		businessGroupMinimumMembers.setElementCssClass("o_sel_group_edit_min_members");
 
 		// Maximum members input
 		businessGroupMaximumMembers = uifactory.addTextElement("create.form.title.max", "create.form.title.max", 5, "", formLayout);
 		businessGroupMaximumMembers.setDisplaySize(6);
+		businessGroupMaximumMembers.setElementCssClass("o_sel_group_edit_max_members");
 
 		// Checkboxes
 		enableWaitingList = uifactory.addCheckboxesHorizontal("create.form.enableWaitinglist", null, formLayout, waitingListKeys,
diff --git a/src/main/java/org/olat/group/ui/edit/DisplayMemberSwitchForm.java b/src/main/java/org/olat/group/ui/edit/DisplayMemberSwitchForm.java
index 38120c28a79..458b568f6ad 100644
--- a/src/main/java/org/olat/group/ui/edit/DisplayMemberSwitchForm.java
+++ b/src/main/java/org/olat/group/ui/edit/DisplayMemberSwitchForm.java
@@ -100,7 +100,9 @@ public class DisplayMemberSwitchForm extends FormBasicController {
 	
 	public void setDisplayMembers(BusinessGroup group) {
 		showOwners.select("show_owners", group.isOwnersVisibleIntern());
+		showOwners.setElementCssClass("o_sel_group_show_owners");
 		showPartips.select("show_participants", group.isParticipantsVisibleIntern());
+		showPartips.setElementCssClass("o_sel_group_show_participants");
 		showWaitingList.select("show_waiting_list", group.isWaitingListVisibleIntern());
 		openOwners.select("open_owners", group.isOwnersVisiblePublic());
 		openPartips.select("open_participants", group.isParticipantsVisiblePublic());
diff --git a/src/test/java/org/olat/course/FunctionalCourseTest.java b/src/test/java/org/olat/course/FunctionalCourseTest.java
index 07e24b33d95..49aad84c736 100644
--- a/src/test/java/org/olat/course/FunctionalCourseTest.java
+++ b/src/test/java/org/olat/course/FunctionalCourseTest.java
@@ -21,7 +21,6 @@ package org.olat.course;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -50,7 +49,6 @@ import org.olat.restapi.support.vo.GroupVO;
 import org.olat.restapi.support.vo.RepositoryEntryVO;
 import org.olat.test.ArquillianDeployments;
 import org.olat.util.FunctionalCourseUtil;
-import org.olat.util.FunctionalCourseUtil.CourseEditorCourseTab;
 import org.olat.util.FunctionalCourseUtil.CourseNodeAlias;
 import org.olat.util.FunctionalHtmlUtil;
 import org.olat.util.FunctionalRepositorySiteUtil;
@@ -153,84 +151,6 @@ public class FunctionalCourseTest {
 		
 		functionalUtil.logout(browser);
 	}
-
-	@Test
-	@RunAsClient
-	public void checkCreateUsingEditor() throws FileNotFoundException, IOException, URISyntaxException{
-		/* login */
-		Assert.assertTrue(functionalUtil.login(browser, functionalUtil.getUsername(), functionalUtil.getPassword(), true));
-		
-		/* open repository site */
-		Assert.assertTrue(functionalUtil.openSite(browser, OlatSite.LEARNING_RESOURCES));
-		
-		/* create course */
-		Assert.assertTrue(functionalRepositorySiteUtil.createCourseUsingEditor(browser, EDITOR_COURSE_TITLE, EDITOR_COURSE_DESCRIPTION));
-		
-		/* set single page as overview */
-		Assert.assertTrue(functionalCourseUtil.uploadOverviewPage(browser, FunctionalCourseTest.class.getResource(EDITOR_COURSE_OVERVIEW_FILE).toURI()));
-		
-		/* publish entire course */
-		Assert.assertTrue(functionalCourseUtil.publishEntireCourse(browser, null, null));
-		
-		/* change short title and save */
-		Assert.assertTrue(functionalCourseUtil.openCourseEditorCourseTab(browser, CourseEditorCourseTab.TITLE_AND_DESCRIPTION));
-		
-		StringBuffer selectorBuffer = new StringBuffer();
-		
-		selectorBuffer.append("xpath=(//div[contains(@class, 'o_editor')]//form//input[@type='text'])[1]");
-		
-		browser.type(selectorBuffer.toString(), EDITOR_COURSE_CHANGED_TITLE);
-		
-		selectorBuffer = new StringBuffer();
-		
-		selectorBuffer.append("xpath=(//div[contains(@class, 'o_editor')]//form//button[contains(@class, '")
-		.append(functionalUtil.getButtonDirtyCss())
-		.append("')])[last()]");
-		
-		functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
-		browser.click(selectorBuffer.toString());
-		functionalUtil.waitForPageToUnloadElement(browser, selectorBuffer.toString());
-		
-		/* publish entire course */
-		Assert.assertTrue(functionalCourseUtil.publishEntireCourse(browser, null, null));
-		
-		/*
-		 * Test for content i.e. approve if changes were applied.
-		 */
-		String courseLink = null;
-		
-		Assert.assertNotNull(courseLink = functionalCourseUtil.readExternalLink(browser));
-		Assert.assertTrue(functionalCourseUtil.closeActiveTab(browser));
-		
-		browser.open(courseLink);
-		functionalUtil.waitForPageToLoad(browser);
-
-		String originalText = functionalHtmlUtil.stripTags(IOUtils.toString(FunctionalCourseTest.class.getResourceAsStream(EDITOR_COURSE_OVERVIEW_FILE)), true);
-
-		//TODO:JK: probably you want to replace the following code with functionalUtil.waitForPageToLoadContent
-		String spIFrameSelector = "dom=document.getElementsByClassName('b_module_singlepage_wrapper')[0].getElementsByTagName('iframe')[0]";
-		functionalUtil.waitForPageToLoadElement(browser, spIFrameSelector);
-		browser.selectFrame(spIFrameSelector);
-		String source = browser.getHtmlSource();
-		String currentText = functionalHtmlUtil.stripTags(source, true);
-		browser.selectFrame("relative=up");
-		
-		
-		Assert.assertTrue(originalText.equals(currentText));
-		
-		selectorBuffer = new StringBuffer();
-		
-		selectorBuffer.append("xpath=//a[contains(@class, '")
-		.append(functionalCourseUtil.getStructureIconCss())
-		.append("')]")
-		.append("//span[contains(text(), '")
-		.append(EDITOR_COURSE_CHANGED_TITLE)
-		.append("')]");
-		
-		Assert.assertTrue(browser.isElementPresent(selectorBuffer.toString()));
-		
-		functionalUtil.logout(browser);
-	}
 	
 	@Test
 	@RunAsClient
diff --git a/src/test/java/org/olat/group/FunctionalGroupTest.java b/src/test/java/org/olat/group/FunctionalGroupTest.java
deleted file mode 100644
index 23cba3b2584..00000000000
--- a/src/test/java/org/olat/group/FunctionalGroupTest.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/**
- * <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.group;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-
-import org.jboss.arquillian.container.test.api.Deployment;
-import org.jboss.arquillian.container.test.api.RunAsClient;
-import org.jboss.arquillian.drone.api.annotation.Drone;
-import org.jboss.arquillian.junit.Arquillian;
-import org.jboss.arquillian.test.api.ArquillianResource;
-import org.jboss.shrinkwrap.api.spec.WebArchive;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.olat.collaboration.CollaborationTools;
-import org.olat.restapi.support.vo.GroupVO;
-import org.olat.test.ArquillianDeployments;
-import org.olat.user.restapi.UserVO;
-import org.olat.util.FunctionalGroupsSiteUtil;
-import org.olat.util.FunctionalGroupsSiteUtil.GroupTools;
-import org.olat.util.FunctionalGroupsSiteUtil.GroupsTabAction;
-import org.olat.util.FunctionalUtil;
-import org.olat.util.FunctionalVOUtil;
-import org.olat.util.browser.Student1;
-import org.olat.util.browser.Tutor1;
-
-import com.thoughtworks.selenium.DefaultSelenium;
-
-/**
- * 
- * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com
- */
-@RunWith(Arquillian.class)
-public class FunctionalGroupTest {
-	
-	public final static String CREATE_GROUP_NAME = "club of dead poets";
-	public final static String CREATE_GROUP_DESCRIPTION = "If you feel disappointed by the attitude and stance on free software of certain companies you're welcome.";
-	
-	public final static String CONFIGURE_TOOLS_INFORMATION = "group for testing";
-	
-	public final static String CONFIGURE_ACCESS_CONTROL_DESCRIPTION = "test access code";
-	public final static String CONFIGURE_ACCESS_CONTROL_ACCESS_CODE = "1234";
-
-	public final static String INVITATION_GROUP_NAME = "only members";
-	public final static String INVITATION_GROUP_DESCRIPTION = "You must be invited in order to see the group's content";
-	
-	@Deployment(testable = false)
-	public static WebArchive createDeployment() {
-		return ArquillianDeployments.createDeployment();
-	}
-	
-	@ArquillianResource
-	URL deploymentUrl;
-	
-	static FunctionalUtil functionalUtil;
-	static FunctionalGroupsSiteUtil functionalGroupsSiteUtil;
-	static FunctionalVOUtil functionalVOUtil;
-
-	static boolean initialized = false;
-	
-	@Before
-	public void setup() throws IOException, URISyntaxException{
-		if(!initialized){
-			functionalUtil = new FunctionalUtil();
-			functionalUtil.setDeploymentUrl(deploymentUrl.toString());
-			
-			functionalGroupsSiteUtil = functionalUtil.getFunctionalGroupsSiteUtil();
-
-			functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
-
-			initialized = true;
-		}
-	}
-
-	@Test
-	@RunAsClient
-	public void checkConfigureAccessControl(@Drone @Tutor1 DefaultSelenium tutor0,
-			@Drone @Student1 DefaultSelenium student0)
-					throws IOException, URISyntaxException{
-		/*
-		 * test setup
-		 */
-		/* create users */
-		int tutorCount = 1;
-			
-		final UserVO[] tutors = new UserVO[tutorCount];
-		functionalVOUtil.createTestAuthors(deploymentUrl, tutorCount).toArray(tutors);
-		
-		int studentCount = 1;
-		
-		final UserVO[] students = new UserVO[studentCount];
-		functionalVOUtil.createTestUsers(deploymentUrl, studentCount).toArray(students);
-		
-		/* create group via REST */
-		final GroupVO[] groups = new GroupVO[tutorCount];
-		functionalVOUtil.createTestCourseGroups(deploymentUrl, tutorCount).toArray(groups);
-		
-		functionalVOUtil.addOwnerToGroup(deploymentUrl, groups[0], tutors[0]);
-		
-		//TODO:JK: I wish there would be REST extension to configure waiting list
-		functionalVOUtil.setGroupConfiguration(deploymentUrl, groups[0],
-				new String[]{
-					CollaborationTools.TOOL_CALENDAR,
-					CollaborationTools.TOOL_CHAT,
-					CollaborationTools.TOOL_CONTACT,
-					CollaborationTools.TOOL_FOLDER,
-					CollaborationTools.TOOL_FORUM,
-					CollaborationTools.TOOL_NEWS,
-					CollaborationTools.TOOL_PORTFOLIO,
-					CollaborationTools.TOOL_WIKI,
-				},
-				false, false,
-				false, true,
-				true, true);
-		
-		/*
-		 * test case
-		 */
-		Assert.assertTrue(functionalUtil.login(tutor0, tutors[0].getLogin(), tutors[0].getPassword(), true));
-		
-		/* open group */
-		Assert.assertTrue(functionalGroupsSiteUtil.openMyGroup(tutor0, groups[0].getName()));
-		
-		/* apply booking method */
-		Assert.assertTrue(functionalGroupsSiteUtil.applyBookingAccessCode(tutor0,
-				CONFIGURE_ACCESS_CONTROL_DESCRIPTION, CONFIGURE_ACCESS_CONTROL_ACCESS_CODE));
-		
-		/* logout tutor */
-		functionalUtil.logout(tutor0);
-		
-		/*
-		 * verify
-		 */
-		Assert.assertTrue(functionalUtil.login(student0, students[0].getLogin(), students[0].getPassword(), true));
-		
-		/* book group */
-		Assert.assertTrue(functionalGroupsSiteUtil.bookWithAccessCode(student0,
-				groups[0].getName(), CONFIGURE_ACCESS_CONTROL_ACCESS_CODE));
-		
-		/* verify tools */
-		GroupTools[] tools = new GroupTools[]{
-				GroupTools.CALENDAR,
-				GroupTools.EMAIL,
-				GroupTools.EPORTFOLIO,
-				GroupTools.FOLDER,
-				GroupTools.FORUM,
-				GroupTools.INFORMATION,
-				GroupTools.WIKI,
-		};
-		
-		for(GroupTools currentTool: tools){
-			GroupsTabAction action = functionalGroupsSiteUtil.findGroupTabActionForTool(currentTool);
-			
-			StringBuffer selectorBuffer = new StringBuffer();
-			selectorBuffer.append("xpath=//ul[contains(@class, '")
-			.append(functionalUtil.getTreeLevel1Css())
-			.append("')]//li//a[contains(@class, '")
-			.append(action.getIconCss())
-			.append("')]");
-			
-			functionalUtil.waitForPageToLoadElement(student0, selectorBuffer.toString());
-		}
-		
-		/* logout student */
-		functionalUtil.logout(student0);
-	}
-
-
-}
diff --git a/src/test/java/org/olat/selenium/BusinessGroupTest.java b/src/test/java/org/olat/selenium/BusinessGroupTest.java
new file mode 100644
index 00000000000..e502f39e158
--- /dev/null
+++ b/src/test/java/org/olat/selenium/BusinessGroupTest.java
@@ -0,0 +1,128 @@
+/**
+ * <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;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.UUID;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.drone.api.annotation.Drone;
+import org.jboss.arquillian.graphene.page.InitialPage;
+import org.jboss.arquillian.graphene.page.Page;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.olat.selenium.page.LoginPage;
+import org.olat.selenium.page.NavigationPage;
+import org.olat.selenium.page.Participant;
+import org.olat.selenium.page.group.GroupPage;
+import org.olat.selenium.page.user.UserToolsPage;
+import org.olat.test.ArquillianDeployments;
+import org.olat.test.rest.UserRestClient;
+import org.olat.user.restapi.UserVO;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+/**
+ * 
+ * Initial date: 03.07.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@RunWith(Arquillian.class)
+public class BusinessGroupTest {
+	
+	@Deployment(testable = false)
+	public static WebArchive createDeployment() {
+		return ArquillianDeployments.createDeployment();
+	}
+
+	@Drone
+	private WebDriver browser;
+	@Drone @Participant
+	private WebDriver participantBrowser;
+	@ArquillianResource
+	private URL deploymentUrl;	
+
+	@Page
+	private UserToolsPage userTools;
+	@Page
+	private NavigationPage navBar;
+	
+
+	@Page @Participant
+	private NavigationPage participantNavBar;
+
+	/**
+	 * An author create a group, set the visibility to
+	 * show owners and participants. Add a member to the
+	 * group.
+	 * 
+	 * The participant log in, search the group and open it.
+	 * 
+	 * @param loginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void groupMembers(@InitialPage LoginPage loginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		UserVO participant = new UserRestClient(deploymentUrl).createRandomUser();
+		
+		loginPage
+			.loginAs(author.getLogin(), author.getPassword())
+			.resume();
+		
+		//go to groups
+		String groupName = "Group-1-" + UUID.randomUUID();
+		GroupPage group = navBar
+			.openGroups(browser)
+			.createGroup(groupName, "A very little group");
+		
+		group
+			.openAdministration()
+			.openAdminMembers()
+			.setVisibility(true, true)
+			.addMember(participant);
+		
+		LoginPage participantLoginPage = LoginPage.getLoginPage(participantBrowser, deploymentUrl);
+		//tools
+		participantLoginPage
+			.loginAs(participant.getLogin(), participant.getPassword())
+			.resume();
+		
+		participantNavBar
+				.openGroups(participantBrowser)
+				.selectGroup(groupName);
+		
+		WebElement contentEl = participantBrowser.findElement(By.id("o_main_center_content_inner"));
+		String content = contentEl.getText();
+		Assert.assertTrue(content.contains(groupName));
+	}
+}
diff --git a/src/test/java/org/olat/selenium/page/LoginPage.java b/src/test/java/org/olat/selenium/page/LoginPage.java
index 100afdf75bf..a78ca4c155c 100644
--- a/src/test/java/org/olat/selenium/page/LoginPage.java
+++ b/src/test/java/org/olat/selenium/page/LoginPage.java
@@ -20,6 +20,7 @@
 package org.olat.selenium.page;
 
 
+import java.net.URL;
 import java.util.List;
 
 import org.jboss.arquillian.drone.api.annotation.Drone;
@@ -31,7 +32,6 @@ import org.olat.user.restapi.UserVO;
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.FindBy;
 
 /**
  * The login page, annoted to be used as @InitialPage
@@ -44,46 +44,30 @@ import org.openqa.selenium.support.FindBy;
 @Location("dmz")
 public class LoginPage {
 	
-	public static final String loginFormClassName = "o_login_form";
-	public static final String loginFormXPath = "//div[contains(@class,'o_login_form')]";
-
-	public static final String usernameId = "o_fiooolat_login_name";
-	public static final String passwordId = "o_fiooolat_login_pass";
-	public static final String loginButtonId = "o_fiooolat_login_button";
-	public static final String footerUserDivXPath = "//div[@id='o_footer_user']";
-	public static final String acknowledgeCheckboxXPath = "//input[@name='acknowledge_checkbox']";
-	
-	public static final By authXPath = By.xpath(footerUserDivXPath);
-	public static final By loginFormBy = By.xpath(loginFormXPath);
-	public static final By authOrDisclaimerXPath = By.xpath(footerUserDivXPath + "|" + acknowledgeCheckboxXPath);
-	public static final By disclaimerXPath = By.xpath(acknowledgeCheckboxXPath);
-	public static final By disclaimerButtonXPath = By.xpath("//div[contains(@class,'o_sel_disclaimer_buttons')]/button"); 
+	private static final String footerUserDivXPath = "//div[@id='o_footer_user']";
+	private static final String acknowledgeCheckboxXPath = "//input[@name='acknowledge_checkbox']";
 	
-	public static final By resumeButton = By.className("o_sel_resume_yes");
+	private static final By authXPath = By.xpath(footerUserDivXPath);
+	public static final By loginFormBy = By.cssSelector("div.o_login_form");
+	private static final By authOrDisclaimerXPath = By.xpath(footerUserDivXPath + "|" + acknowledgeCheckboxXPath);
+	private static final By disclaimerXPath = By.xpath(acknowledgeCheckboxXPath);
+	private static final By disclaimerButtonXPath = By.xpath("//div[contains(@class,'o_sel_disclaimer_buttons')]/button"); 
 	
+	public static final By resumeButton = By.className("o_sel_resume_yes");	
 	public static final By usernameFooterBy = By.id("o_username");
-
-	@FindBy(className = loginFormClassName)
-	private WebElement loginDiv;
-	@FindBy(xpath = loginFormXPath)
-	private WebElement loginDivXPath;
-	
-	@FindBy(id = usernameId)
-	private WebElement usernameInput;
-	@FindBy(id = passwordId)
-	private WebElement passwordInput;
-	@FindBy(id = loginButtonId)
-	private WebElement loginButton;
 	
 	@Drone
 	private WebDriver browser;
+	
+	public static LoginPage getLoginPage(WebDriver browser, URL deployementUrl) {
+		LoginPage page = new LoginPage();
+		page.browser = browser;
+		page.browser.navigate().to(deployementUrl);
+		return page;
+	}
 
 	public LoginPage assertOnLoginPage() {
-		Assert.assertNotNull(loginDiv);
-		Assert.assertNotNull(loginDivXPath);
-
-		Assert.assertTrue(loginDiv.isDisplayed());
-		Assert.assertTrue(loginDivXPath.isDisplayed());
+		Assert.assertTrue(browser.findElement(loginFormBy).isDisplayed());
 		return this;
 	}
 	
@@ -102,9 +86,16 @@ public class LoginPage {
 	 * @param password
 	 */
 	public LoginPage loginAs(String username, String password) {
+		//fill login form
+		By usernameId = By.id("o_fiooolat_login_name");
+		WebElement usernameInput = browser.findElement(usernameId);
 		usernameInput.sendKeys(username);
+		By passwordId = By.id("o_fiooolat_login_pass");
+		WebElement passwordInput = browser.findElement(passwordId);
 		passwordInput.sendKeys(password);
-
+		
+		By loginBy = By.id("o_fiooolat_login_button");
+		WebElement loginButton = browser.findElement(loginBy);
 		Graphene.guardHttp(loginButton).click();
 		OOGraphene.waitElement(authOrDisclaimerXPath);
 		
diff --git a/src/test/java/org/olat/selenium/page/NavigationPage.java b/src/test/java/org/olat/selenium/page/NavigationPage.java
index 4ab69c25248..05785d9b083 100644
--- a/src/test/java/org/olat/selenium/page/NavigationPage.java
+++ b/src/test/java/org/olat/selenium/page/NavigationPage.java
@@ -25,11 +25,11 @@ 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.group.GroupsPage;
 import org.olat.selenium.page.repository.AuthoringEnvPage;
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.FindBy;
 
 /**
  * Page fragment which control the navigation bar with the static sites.
@@ -45,24 +45,19 @@ public class NavigationPage {
 	@Drone
 	private WebDriver browser;
 	
-	@FindBy(css="ul.o_navbar_sites")
-	private WebElement navigationSites;
-	
-	@FindBy(css = "li.o_site_author_env > a")
-	private WebElement authoringEnvTab;
-	@FindBy(css = "li.o_site_repository > a")
-	private WebElement myCourseTab;
+	private By navigationSitesBy = By.cssSelector("ul.o_navbar_sites");
+	private By authoringEnvTabBy = By.cssSelector("li.o_site_author_env > a");
 	
 	public NavigationPage assertOnNavigationPage() {
+		WebElement navigationSites = browser.findElement(navigationSitesBy);
 		Assert.assertTrue(navigationSites.isDisplayed());
 		return this;
 	}
 	
 	public AuthoringEnvPage openAuthoringEnvironment() {
-		if(!navigationSites.isDisplayed()) {
-			//too small, open the black panel
-		}
+		openNavigationSites();
 		//author?
+		WebElement authoringEnvTab = browser.findElement(authoringEnvTabBy);
 		Assert.assertTrue(authoringEnvTab.isDisplayed());
 		
 		authoringEnvTab.click();
@@ -75,6 +70,23 @@ public class NavigationPage {
 		return Graphene.createPageFragment(AuthoringEnvPage.class, main);
 	}
 	
+	public GroupsPage openGroups(WebDriver browser) {
+		By groupsBy = By.cssSelector("li.o_site_groups > a");
+		WebElement groups = browser.findElement(groupsBy);
+		Assert.assertTrue(groups.isDisplayed());
+		groups.click();
+		OOGraphene.waitBusy();
+		
+		return new GroupsPage(browser);
+	}
+	
+	private void openNavigationSites() {
+		List<WebElement> navigationSites = browser.findElements(navigationSitesBy);
+		if(navigationSites.isEmpty()) {
+			//too small, open the black panel
+		}
+	}
+	
 	public void openCourse(String title) {
 		By courseTab = By.xpath("//li/a[@title='" + title + "']");
 		WebElement courseLink = browser.findElement(courseTab);
diff --git a/src/test/java/org/olat/selenium/page/Participant.java b/src/test/java/org/olat/selenium/page/Participant.java
new file mode 100644
index 00000000000..f05b61043f3
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/Participant.java
@@ -0,0 +1,40 @@
+/**
+ * <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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+ 
+import org.jboss.arquillian.drone.api.annotation.Qualifier;
+
+/**
+ * 
+ * Initial date: 03.07.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.FIELD, ElementType.PARAMETER })
+@Qualifier
+public @interface Participant {
+
+}
diff --git a/src/test/java/org/olat/selenium/page/group/GroupPage.java b/src/test/java/org/olat/selenium/page/group/GroupPage.java
new file mode 100644
index 00000000000..fa88f684173
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/group/GroupPage.java
@@ -0,0 +1,119 @@
+/**
+ * <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.group;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.olat.selenium.page.graphene.OOGraphene;
+import org.olat.user.restapi.UserVO;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+/**
+ * Drive the group run page
+ * 
+ * Initial date: 03.07.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class GroupPage {
+	
+	private WebDriver browser;
+	
+	public GroupPage() {
+		//
+	}
+	
+	public GroupPage(WebDriver browser) {
+		this.browser = browser;
+	}
+	
+	public static GroupPage getGroup(WebDriver browser) {
+		return new GroupPage(browser);
+	}
+	
+	public GroupPage openAdministration() {
+		By adminBy = By.xpath("//div[contains(@class,'o_tree')]//a[contains(@href,'MENU_ADMINISTRATION')]");
+		WebElement adminLink = browser.findElement(adminBy);
+		adminLink.click();
+		OOGraphene.waitBusy();
+		return this;
+	}
+	
+	private static final By showOwners = By.className("o_sel_group_show_owners");
+	
+	public GroupPage openAdminMembers() {
+		openAdminTab(showOwners);
+		return this;
+	}
+	
+	public GroupPage setVisibility(boolean owners, boolean participants) {
+		By showOwnersBy = By.cssSelector(".o_sel_group_show_owners input[type='checkbox']");
+		WebElement showOwnersEl = browser.findElement(showOwnersBy);
+		if(owners) {
+			showOwnersEl.click();
+		}
+		
+		By showParticipants = By.cssSelector(".o_sel_group_show_participants input[type='checkbox']");
+		WebElement showParticipantsEl = browser.findElement(showParticipants);
+		if(participants) {
+			showParticipantsEl.click();
+		}
+		
+		return this;
+	}
+	
+	public GroupPage addMember(UserVO user) {
+		By addMemberBy = By.className("o_sel_group_add_member");
+		WebElement addMemberButton = browser.findElement(addMemberBy);
+		addMemberButton.click();
+		OOGraphene.waitBusy();
+		
+		new MembersWizardPage(browser)
+			.searchMember(user)
+			.next()
+			.next()
+			.next()
+			.finish();
+		
+		return this;
+	}
+	
+	private void openAdminTab(By marker) {
+		By navBarAdmin = By.cssSelector("div.o_tabbed_pane ul>li>a");
+		OOGraphene.waitElement(navBarAdmin);
+		List<WebElement> tabLinks = browser.findElements(navBarAdmin);
+		Assert.assertFalse(tabLinks.isEmpty());
+
+		boolean found = false;
+		for(WebElement tabLink:tabLinks) {
+			tabLink.click();
+			OOGraphene.waitBusy();
+			List<WebElement> markerEls = browser.findElements(marker);
+			if(markerEls.size() > 0) {
+				found = true;
+				break;
+			}
+		}
+		Assert.assertTrue(found);
+	}
+}
diff --git a/src/test/java/org/olat/selenium/page/group/GroupsPage.java b/src/test/java/org/olat/selenium/page/group/GroupsPage.java
new file mode 100644
index 00000000000..b365c506943
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/group/GroupsPage.java
@@ -0,0 +1,90 @@
+/**
+ * <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.group;
+
+import java.util.List;
+
+import org.jcodec.common.Assert;
+import org.olat.selenium.page.graphene.OOGraphene;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+/**
+ * Drive the groups site
+ * 
+ * Initial date: 03.07.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class GroupsPage {
+	
+	private WebDriver browser;
+	
+	public GroupsPage(WebDriver browser) {
+		this.browser = browser;
+	}
+	
+	public GroupPage createGroup(String name, String description) {
+		//click create button
+		By createBy = By.className("o_sel_group_create");
+		WebElement createButton = browser.findElement(createBy);
+		createButton.click();
+		OOGraphene.waitBusy();
+		
+		//fill the form
+		By nameBy = By.cssSelector(".o_sel_group_edit_title input[type='text']");
+		WebElement nameEl = browser.findElement(nameBy);
+		nameEl.sendKeys(name);
+		OOGraphene.tinymce(description, browser);
+		
+		//save
+		By submitBy = By.cssSelector(".o_sel_group_edit_group_form button.btn-primary");
+		WebElement submitButton = browser.findElement(submitBy);
+		submitButton.click();
+		OOGraphene.waitBusy();
+		
+		return new GroupPage(browser);
+	}
+	
+	/**
+	 * Select a group in the list by its name
+	 * @param name
+	 * @return
+	 */
+	public GroupPage selectGroup(String name) {
+		By linkBy = By.cssSelector("div.o_table_wrapper td a");
+		
+		WebElement groupLink = null;
+		List<WebElement> links = browser.findElements(linkBy);
+		for(WebElement link:links) {
+			if(link.getText().contains(name)) {
+				groupLink = link;
+			}
+		}
+		
+		Assert.assertNotNull(groupLink);
+		groupLink.click();
+		OOGraphene.waitBusy();
+		
+		return new GroupPage(browser);
+	}
+
+}
diff --git a/src/test/java/org/olat/selenium/page/group/MembersWizardPage.java b/src/test/java/org/olat/selenium/page/group/MembersWizardPage.java
new file mode 100644
index 00000000000..4e23856a345
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/group/MembersWizardPage.java
@@ -0,0 +1,97 @@
+/**
+ * <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.group;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.olat.selenium.page.graphene.OOGraphene;
+import org.olat.user.restapi.UserVO;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+/**
+ * Drive the wizard to add members
+ * 
+ * Initial date: 03.07.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class MembersWizardPage {
+
+	public static final By nextBy = By.className("o_wizard_button_next");
+	public static final By finishBy = By.className("o_wizard_button_finish");
+	
+	private WebDriver browser;
+	
+	public MembersWizardPage(WebDriver browser) {
+		this.browser = browser;
+	}
+	
+	public MembersWizardPage next() {
+		WebElement next = browser.findElement(nextBy);
+		Assert.assertTrue(next.isDisplayed());
+		Assert.assertTrue(next.isEnabled());
+		next.click();
+		OOGraphene.waitBusy();
+		OOGraphene.closeBlueMessageWindow(browser);
+		return this;
+	}
+	
+	public MembersWizardPage finish() {
+		WebElement finish = browser.findElement(finishBy);
+		Assert.assertTrue(finish.isDisplayed());
+		Assert.assertTrue(finish.isEnabled());
+		finish.click();
+		OOGraphene.waitBusy();
+		OOGraphene.closeBlueMessageWindow(browser);
+		return this;
+	}
+	
+	/**
+	 * Search member and select them
+	 * @param user
+	 * @return
+	 */
+	public MembersWizardPage searchMember(UserVO user) {
+		//Search by username
+		By usernameBy = By.cssSelector(".o_sel_usersearch_searchform input[type='text']");
+		OOGraphene.waitElement(usernameBy);
+		
+		List<WebElement> searchFields = browser.findElements(usernameBy);
+		Assert.assertFalse(searchFields.isEmpty());
+		searchFields.get(0).sendKeys(user.getLogin());
+
+		By searchBy = By.cssSelector(".o_sel_usersearch_searchform a.btn-default");
+		WebElement searchButton = browser.findElement(searchBy);
+		searchButton.click();
+		OOGraphene.waitBusy();
+		
+		//check
+		By checkAllBy = By.cssSelector("div.modal div.o_table_wrapper input[type='checkbox']");
+		List<WebElement> checkAll = browser.findElements(checkAllBy);
+		Assert.assertFalse(checkAll.isEmpty());
+		for(WebElement check:checkAll) {
+			check.click();
+		}
+		return this;
+	}
+}
diff --git a/src/test/java/org/olat/test/rest/UserRestClient.java b/src/test/java/org/olat/test/rest/UserRestClient.java
index eb6bf5fdc32..976cfeab61f 100644
--- a/src/test/java/org/olat/test/rest/UserRestClient.java
+++ b/src/test/java/org/olat/test/rest/UserRestClient.java
@@ -26,8 +26,6 @@ import java.io.InputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -68,25 +66,13 @@ public class UserRestClient {
 		this.username = username;
 		this.password = password;
 	}
-
-	public List<UserVO> createTestUsers(int count)
-	throws IOException, URISyntaxException {
-		RestConnection restConnection = new RestConnection(deploymentUrl);
-		assertTrue(restConnection.login(username, password));
-
-		List<UserVO> users = new ArrayList<UserVO>(count);
-		for(int i = 0; i < count; i++){
-			users.add(createUser(restConnection));
-		}
-		return users;
-	}
 	
 	public UserVO createRandomUser()
 	throws IOException, URISyntaxException {
 		RestConnection restConnection = new RestConnection(deploymentUrl);
 		assertTrue(restConnection.login(username, password));
 		
-		UserVO user = createUser(restConnection);
+		UserVO user = createUser(restConnection, "Rnd");
 
 		restConnection.shutdown();
 		return user;
@@ -97,7 +83,7 @@ public class UserRestClient {
 		RestConnection restConnection = new RestConnection(deploymentUrl);
 		assertTrue(restConnection.login(username, password));
 		
-		UserVO user = createUser(restConnection);
+		UserVO user = createUser(restConnection, "Auth");
 		
 		RolesVO roles = new RolesVO();
 		roles.setAuthor(true);
@@ -114,7 +100,7 @@ public class UserRestClient {
 		return user;
 	}
 	
-	private UserVO createUser(RestConnection restConnection)
+	private UserVO createUser(RestConnection restConnection, String role)
 	throws URISyntaxException, IOException {
 		String uuid = Integer.toString(counter.incrementAndGet()) + UUID.randomUUID().toString();
 		
@@ -123,7 +109,7 @@ public class UserRestClient {
 		vo.setLogin(username);
 		String password = ("passwd-" + uuid).substring(0, 24);
 		vo.setPassword(password);
-		vo.setFirstName("Selena-" + uuid);
+		vo.setFirstName("Selena-"+ role + "-" + uuid);
 		vo.setLastName("Smith");
 		vo.setEmail(username + "@frentix.com");
 		vo.putProperty("telOffice", "39847592");
diff --git a/src/test/resources/arquillian.xml b/src/test/resources/arquillian.xml
index e9f68c5bccf..1c6618a9d97 100644
--- a/src/test/resources/arquillian.xml
+++ b/src/test/resources/arquillian.xml
@@ -21,6 +21,10 @@
 		<property name="browser">safari</property>
 	</extension>
 	
+	<extension qualifier="graphene-participant">
+		<property name="browser">firefox</property>
+	</extension>
+	
 	<extension qualifier="safari">
 		<property name="browser">safari</property>
 	</extension>
-- 
GitLab