From 9141dcc02da23be3d20c7120c9c1eebbf5f8a0a4 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Sat, 14 Feb 2015 16:50:57 +0100
Subject: [PATCH] OO-1349: add more selenium for assessment especially one to
 test the assessment mode

---
 .../fullWebApp/BaseFullWebappController.java  |   2 +
 .../assessment/AssessmentMainController.java  |   3 +
 .../ui/AssessmentModeEditController.java      |   8 +
 .../ui/AssessmentModeGuardController.java     |   2 +
 .../ui/AssessmentModeListController.java      |   2 +
 .../assessment/ui/_content/mode_list.html     |   2 +-
 .../member/MembersOverviewController.java     |   2 +
 .../course/run/CourseRuntimeController.java   |   2 +
 .../org/olat/selenium/AssessmentTest.java     | 297 +++++++++++++++++-
 .../java/org/olat/selenium/CourseTest.java    |   2 +-
 .../org/olat/selenium/UserSettingsTest.java   |   2 +-
 .../org/olat/selenium/page/LoginPage.java     |   8 +-
 .../olat/selenium/page/NavigationPage.java    |  12 +-
 .../java/org/olat/selenium/page/Student.java  |  40 +++
 .../page/core/AdministrationPage.java         |   8 +-
 .../org/olat/selenium/page/core/IMPage.java   |   8 +-
 .../page/core/MenuTreePageFragment.java       |   4 +-
 .../page/course/AssessmentModePage.java       | 218 +++++++++++++
 .../page/course/AssessmentToolPage.java       |  96 ++++++
 .../page/course/CourseEditorPageFragment.java |  33 +-
 .../page/course/CoursePageFragment.java       |  63 +++-
 .../page/course/CourseWizardPage.java         |   6 +-
 .../selenium/page/course/MembersPage.java     |  63 ++++
 .../selenium/page/course/MyCoursesPage.java   |  14 +-
 .../page/course/PublisherPageFragment.java    |  17 +-
 .../olat/selenium/page/forum/ForumPage.java   |   9 +-
 .../selenium/page/graphene/OOGraphene.java    |  63 +++-
 .../olat/selenium/page/group/GroupPage.java   |  16 +-
 .../olat/selenium/page/group/GroupsPage.java  |   6 +-
 .../page/group/MembersWizardPage.java         |   8 +-
 .../page/portfolio/ArtefactWizardPage.java    |   6 +-
 .../page/portfolio/PortfolioPage.java         |  44 +--
 .../org/olat/selenium/page/qti/QTI12Page.java |  65 +++-
 .../page/repository/AuthoringEnvPage.java     |  27 +-
 .../page/repository/CatalogAdminPage.java     |   6 +-
 .../selenium/page/repository/FeedPage.java    |  16 +-
 .../repository/RepositoryDetailsPage.java     |   4 +-
 .../RepositoryEditDescriptionPage.java        |   2 +-
 .../olat/selenium/page/user/PortalPage.java   |   6 +-
 .../selenium/page/user/UserPasswordPage.java  |   4 +-
 .../user/UserPreferencesPageFragment.java     |   6 +-
 .../selenium/page/user/UserSettingsPage.java  |  23 +-
 .../selenium/page/user/UserToolsPage.java     |  28 +-
 .../org/olat/selenium/page/wiki/WikiPage.java |  10 +-
 44 files changed, 1075 insertions(+), 188 deletions(-)
 create mode 100644 src/test/java/org/olat/selenium/page/Student.java
 create mode 100644 src/test/java/org/olat/selenium/page/course/AssessmentModePage.java
 create mode 100644 src/test/java/org/olat/selenium/page/course/AssessmentToolPage.java
 create mode 100644 src/test/java/org/olat/selenium/page/course/MembersPage.java

diff --git a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java
index 3ecadd214ff..4cf7cea7cc0 100644
--- a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java
+++ b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java
@@ -663,6 +663,8 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 			initializeDefaultSite(ureq);
 		} else if(assessmentGuardCtrl == source) {
 			if(event instanceof ChooseAssessmentModeEvent) {
+				ChooseAssessmentModeEvent came = (ChooseAssessmentModeEvent)event;
+				lockMode = came.getAssessmentMode();
 				lockStatus = LockStatus.locked;
 				removeAsListenerAndDispose(assessmentGuardCtrl);
 				assessmentGuardCtrl = null;
diff --git a/src/main/java/org/olat/course/assessment/AssessmentMainController.java b/src/main/java/org/olat/course/assessment/AssessmentMainController.java
index f4616b42fe2..e8b2dc6e83e 100644
--- a/src/main/java/org/olat/course/assessment/AssessmentMainController.java
+++ b/src/main/java/org/olat/course/assessment/AssessmentMainController.java
@@ -1265,12 +1265,14 @@ public class AssessmentMainController extends MainLayoutBasicController implemen
 			gtn.setTitle(translate("menu.groupfocus"));
 			gtn.setUserObject(CMD_GROUPFOCUS);
 			gtn.setAltText(translate("menu.groupfocus.alt"));
+			gtn.setCssClass("o_sel_assessment_tool_groups");
 			root.addChild(gtn);
 	
 			gtn = new GenericTreeNode();
 			gtn.setTitle(translate("menu.nodefocus"));
 			gtn.setUserObject(CMD_NODEFOCUS);
 			gtn.setAltText(translate("menu.nodefocus.alt"));
+			gtn.setCssClass("o_sel_assessment_tool_nodes");
 			root.addChild(gtn);
 		}
 		
@@ -1279,6 +1281,7 @@ public class AssessmentMainController extends MainLayoutBasicController implemen
 			gtn.setTitle(translate("menu.userfocus"));
 			gtn.setUserObject(CMD_USERFOCUS);
 			gtn.setAltText(translate("menu.userfocus.alt"));
+			gtn.setCssClass("o_sel_assessment_tool_users");
 			root.addChild(gtn);
 		}
 
diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java b/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java
index f5fc2bc77e1..0eff7f64e68 100644
--- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java
+++ b/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java
@@ -138,6 +138,7 @@ public class AssessmentModeEditController extends FormBasicController {
 
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		formLayout.setElementCssClass("o_sel_assessment_mode_edit_form");
 		if(StringHelper.containsNonWhitespace(assessmentMode.getName())) {
 			setFormTitle("form.mode.title", new String[]{ assessmentMode.getName() });
 		} else {
@@ -148,6 +149,7 @@ public class AssessmentModeEditController extends FormBasicController {
 		Status status = assessmentMode.getStatus();
 		String name = assessmentMode.getName();
 		nameEl = uifactory.addTextElement("mode.name", "mode.name", 255, name, formLayout);
+		nameEl.setElementCssClass("o_sel_assessment_mode_name");
 		nameEl.setMandatory(true);
 		nameEl.setEnabled(status != Status.followup && status != Status.end);
 		
@@ -157,6 +159,7 @@ public class AssessmentModeEditController extends FormBasicController {
 		descriptionEl.setEnabled(status != Status.followup && status != Status.end);
 		
 		beginEl = uifactory.addDateChooser("mode.begin", assessmentMode.getBegin(), formLayout);
+		beginEl.setElementCssClass("o_sel_assessment_mode_begin");
 		beginEl.setDateChooserTimeEnabled(true);
 		beginEl.setMandatory(true);
 		beginEl.setEnabled(status == Status.none || status == Status.leadtime);
@@ -166,10 +169,12 @@ public class AssessmentModeEditController extends FormBasicController {
 			leadTime = 0;
 		}
 		leadTimeEl = uifactory.addIntegerElement("mode.leadTime", leadTime, formLayout);
+		leadTimeEl.setElementCssClass("o_sel_assessment_mode_leadtime");
 		leadTimeEl.setDisplaySize(3);
 		leadTimeEl.setEnabled(status == Status.none || status == Status.leadtime);
 		
 		endEl = uifactory.addDateChooser("mode.end", assessmentMode.getEnd(), formLayout);
+		endEl.setElementCssClass("o_sel_assessment_mode_end");
 		endEl.setDateChooserTimeEnabled(true);
 		endEl.setMandatory(true);
 		endEl.setEnabled(status != Status.end);
@@ -179,6 +184,7 @@ public class AssessmentModeEditController extends FormBasicController {
 			followupTime = 0;
 		}
 		followupTimeEl = uifactory.addIntegerElement("mode.followupTime", followupTime, formLayout);
+		followupTimeEl.setElementCssClass("o_sel_assessment_mode_followuptime");
 		followupTimeEl.setDisplaySize(3);
 		followupTimeEl.setEnabled(status != Status.end);
 		
@@ -186,6 +192,7 @@ public class AssessmentModeEditController extends FormBasicController {
 				translate("mode.beginend.automatic"), translate("mode.beginend.manual")
 		};
 		startModeEl = uifactory.addDropdownSingleselect("mode.beginend", formLayout, startModeKeys, startModeValues, null);
+		startModeEl.setElementCssClass("o_sel_assessment_mode_start_mode");
 		if(assessmentMode.isManualBeginEnd()) {
 			startModeEl.select(startModeKeys[1], true);
 		} else {
@@ -204,6 +211,7 @@ public class AssessmentModeEditController extends FormBasicController {
 			translate("target.groups")
 		};
 		targetEl = uifactory.addRadiosVertical("audience", "mode.target", formLayout, audienceKeys, audienceValues);
+		targetEl.setElementCssClass("o_sel_assessment_mode_audience");
 		targetEl.setEnabled(status != Status.end);
 		Target target = assessmentMode.getTargetAudience();
 		if(target != null) {
diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeGuardController.java b/src/main/java/org/olat/course/assessment/ui/AssessmentModeGuardController.java
index cba82ba651d..992f391b5f3 100644
--- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeGuardController.java
+++ b/src/main/java/org/olat/course/assessment/ui/AssessmentModeGuardController.java
@@ -90,6 +90,7 @@ public class AssessmentModeGuardController extends BasicController implements Ge
 		mainVC.contextPut("guards", guards);
 		
 		mainContinueButton = LinkFactory.createCustomLink("continue-main", "continue-main", "current.mode.continue", Link.BUTTON, mainVC, this);
+		mainContinueButton.setElementCssClass("o_sel_assessment_continue");
 		mainContinueButton.setCustomEnabledLinkCSS("btn btn-primary");
 		mainContinueButton.setCustomDisabledLinkCSS("o_disabled btn btn-default");
 		mainContinueButton.setVisible(false);
@@ -279,6 +280,7 @@ public class AssessmentModeGuardController extends BasicController implements Ge
 		String id = Long.toString(CodeHelper.getRAMUniqueID());
 
 		Link goButton = LinkFactory.createCustomLink("go-" + id, "go", "current.mode.start", Link.BUTTON, mainVC, this);
+		goButton.setElementCssClass("o_sel_assessment_start");
 		goButton.setCustomEnabledLinkCSS("btn btn-primary");
 		goButton.setCustomDisabledLinkCSS("o_disabled btn btn-default");
 		
diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java b/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java
index ca7c5f4b123..8bea3c884f1 100644
--- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java
+++ b/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java
@@ -107,8 +107,10 @@ public class AssessmentModeListController extends FormBasicController implements
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		addLink = uifactory.addFormLink("add", "add", "add.mode", null, formLayout, Link.BUTTON);
+		addLink.setElementCssClass("o_sel_assessment_mode_add");
 		addLink.setIconLeftCSS("o_icon o_icon_add");
 		
+		
 		deleteLink = uifactory.addFormLink("delete", "delete", "delete.mode", null, formLayout, Link.BUTTON);
 		deleteLink.setIconLeftCSS("o_icon o_icon_delete");
 		
diff --git a/src/main/java/org/olat/course/assessment/ui/_content/mode_list.html b/src/main/java/org/olat/course/assessment/ui/_content/mode_list.html
index df11b0be5fa..25e81e55c34 100644
--- a/src/main/java/org/olat/course/assessment/ui/_content/mode_list.html
+++ b/src/main/java/org/olat/course/assessment/ui/_content/mode_list.html
@@ -1,4 +1,4 @@
-<fieldset>
+<fieldset class="o_sel_assessment_mode_list">
 	<legend>$r.translate("modes.title")</legend>
 	<div class="o_info">$r.translate("modes.description")</div>
 	<div class="o_button_group o_button_group_right">$r.render("add")</div>
diff --git a/src/main/java/org/olat/course/member/MembersOverviewController.java b/src/main/java/org/olat/course/member/MembersOverviewController.java
index 81733df69f1..3e52d2e090d 100644
--- a/src/main/java/org/olat/course/member/MembersOverviewController.java
+++ b/src/main/java/org/olat/course/member/MembersOverviewController.java
@@ -129,10 +129,12 @@ public class MembersOverviewController extends BasicController implements Activa
 		boolean managed = RepositoryEntryManagedFlag.isManaged(repoEntry, RepositoryEntryManagedFlag.membersmanagement);
 		addMemberLink = LinkFactory.createButton("add.member", mainVC, this);
 		addMemberLink.setIconLeftCSS("o_icon o_icon-fw o_icon_add");
+		addMemberLink.setElementCssClass("o_sel_course_add_member");
 		addMemberLink.setVisible(!managed);
 		mainVC.put("addMembers", addMemberLink);
 		importMemberLink = LinkFactory.createButton("import.member", mainVC, this);
 		importMemberLink.setIconLeftCSS("o_icon o_icon-fw o_icon_import");
+		importMemberLink.setElementCssClass("o_sel_course_import_members");
 		importMemberLink.setVisible(!managed);
 		mainVC.put("importMembers", importMemberLink);
 		dedupLink = LinkFactory.createButton("dedup.members", mainVC, this);
diff --git a/src/main/java/org/olat/course/run/CourseRuntimeController.java b/src/main/java/org/olat/course/run/CourseRuntimeController.java
index 10eec654cd7..7d9ec0b9812 100644
--- a/src/main/java/org/olat/course/run/CourseRuntimeController.java
+++ b/src/main/java/org/olat/course/run/CourseRuntimeController.java
@@ -379,10 +379,12 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im
 			
 			if (reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_GROUPMANAGEMENT)) {
 				membersLink = LinkFactory.createToolLink("unifiedusermngt", translate("command.opensimplegroupmngt"), this, "o_icon_membersmanagement");
+				membersLink.setElementCssClass("o_sel_course_members");
 				tools.addComponent(membersLink);
 			}
 			if (reSecurity.isEntryAdmin() || reSecurity.isCourseCoach() || reSecurity.isGroupCoach() || hasCourseRight(CourseRights.RIGHT_ASSESSMENT)) {
 				assessmentLink = LinkFactory.createToolLink("assessment",translate("command.openassessment"), this, "o_icon_assessment_tool");
+				assessmentLink.setElementCssClass("o_sel_course_assessment_tool");
 				tools.addComponent(assessmentLink);
 			}
 			if (reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_ARCHIVING)) {
diff --git a/src/test/java/org/olat/selenium/AssessmentTest.java b/src/test/java/org/olat/selenium/AssessmentTest.java
index c03169c1ae2..cddead01fa7 100644
--- a/src/test/java/org/olat/selenium/AssessmentTest.java
+++ b/src/test/java/org/olat/selenium/AssessmentTest.java
@@ -23,6 +23,8 @@ import java.io.File;
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.util.Calendar;
+import java.util.Date;
 import java.util.UUID;
 
 import org.jboss.arquillian.container.test.api.Deployment;
@@ -38,10 +40,17 @@ 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.Student;
+import org.olat.selenium.page.User;
+import org.olat.selenium.page.course.AssessmentModePage;
+import org.olat.selenium.page.course.AssessmentToolPage;
 import org.olat.selenium.page.course.CourseEditorPageFragment;
 import org.olat.selenium.page.course.CoursePageFragment;
+import org.olat.selenium.page.course.PublisherPageFragment.Access;
 import org.olat.selenium.page.graphene.OOGraphene;
 import org.olat.selenium.page.qti.QTI12Page;
+import org.olat.selenium.page.user.UserToolsPage;
 import org.olat.test.ArquillianDeployments;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.rest.UserRestClient;
@@ -148,7 +157,7 @@ public class AssessmentTest {
 		
 		//check results page
 		By resultsBy = By.id("o_qti_results");
-		OOGraphene.waitElement(resultsBy);
+		OOGraphene.waitElement(resultsBy, browser);
 		WebElement resultsEl = browser.findElement(resultsBy);
 		Assert.assertTrue(resultsEl.getText().contains(author.getFirstName()));
 		//close the test
@@ -158,5 +167,291 @@ public class AssessmentTest {
 		WebElement passedEl = browser.findElement(By.cssSelector("tr.o_state.o_passed"));
 		Assert.assertTrue(passedEl.isDisplayed());
 	}
+	
+
+	/**
+	 * An author upload a test, create a course with a test course
+	 * element, publish the course, assign the course to a student.
+	 * The student come to pass the test, logout after passing it.
+	 * The author check if the test of the student is passed in the
+	 * assessment tool.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void testCourseWithAssessment_qti12(@InitialPage LoginPage authorLoginPage,
+			@Drone @User WebDriver ryomouBrowser)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		UserVO ryomou = new UserRestClient(deploymentUrl).createRandomUser("Ryomou");
+		
+		//upload a test
+		String qtiTestTitle = "QTI-Test-1.2-" + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/e4_test.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile);
+		
+		//create a course
+		String courseTitle = "Course-With-QTI-Test-1.2-" + UUID.randomUUID();
+		navBar
+			.openAuthoringEnvironment()
+			.createCourse(courseTitle)
+			.clickToolbarBack();
+
+		//create a course element of type CP with the CP that we create above
+		String testNodeTitle = "Test-QTI-1.2";
+		CourseEditorPageFragment courseEditor = CoursePageFragment.getCourse(browser)
+			.edit();
+		courseEditor
+			.createNode("iqtest")
+			.nodeTitle(testNodeTitle)
+			.selectTabLearnContent()
+			.chooseTest(qtiTestTitle);
+
+		//publish the course
+		courseEditor
+			.publish()
+			.quickPublish(Access.membersOnly);
+		
+		//open the course and see the test start page
+		CoursePageFragment courseRuntime = courseEditor
+			.clickToolbarBack();
+		courseRuntime
+			.clickTree()
+			.selectWithTitle(testNodeTitle);
+		
+		//check that the title of the start page of test is correct
+		WebElement testH2 = browser.findElement(By.cssSelector("div.o_titled_wrapper.o_course_run h2"));
+		Assert.assertEquals(testNodeTitle, testH2.getText().trim());
+		
+		//add Ryomou as a course member
+		courseRuntime
+			.members()
+			.addMember()
+			.searchMember(ryomou)
+			.next().next().next().finish();
+		
+		//Ryomou open the group
+		LoginPage ryomouLoginPage = LoginPage.getLoginPage(ryomouBrowser, deploymentUrl);
+		ryomouLoginPage
+			.loginAs(ryomou.getLogin(), ryomou.getPassword())
+			.resume();
+		
+		//open the course
+		NavigationPage ryomouNavBar = new NavigationPage(ryomouBrowser);
+		ryomouNavBar
+			.openMyCourses()
+			.select(courseTitle);
+		
+		//go to the test
+		CoursePageFragment ryomouTestCourse = new CoursePageFragment(ryomouBrowser);
+		ryomouTestCourse
+			.clickTree()
+			.selectWithTitle(testNodeTitle);
+		
+		//start the test
+		QTI12Page testPage = QTI12Page.getQTI12Page(ryomouBrowser);
+		testPage
+			.start()
+			.selectItem(0)
+			.answerSingleChoice(0)
+			.saveAnswer()
+			.selectItem(1)
+			.answerMultipleChoice(0, 2)
+			.saveAnswer()
+			.selectItem(2)
+			.answerKPrim(true, false, true, false)
+			.saveAnswer()
+			.selectItem(3)
+			.answerFillin("not")
+			.saveAnswer();
+		testPage
+			.endTest();
+		
+		//check results page
+		By resultsBy = By.id("o_qti_results");
+		OOGraphene.waitElement(resultsBy, ryomouBrowser);
+		WebElement resultsEl = ryomouBrowser.findElement(resultsBy);
+		Assert.assertTrue(resultsEl.getText().contains(ryomou.getFirstName()));
+		//close the test
+		testPage
+			.closeTest();
+		//all answers are correct -> passed
+		WebElement passedEl = ryomouBrowser.findElement(By.cssSelector("tr.o_state.o_passed"));
+		Assert.assertTrue(passedEl.isDisplayed());
+		
+		//log out
+		UserToolsPage roymouUserTools = new UserToolsPage(ryomouBrowser);
+		roymouUserTools.logout();
+		
+		//author take the lead and check the assessment tool
+		navBar
+			.openMyCourses()
+			.select(courseTitle);
+		
+		//open the assessment tool
+		AssessmentToolPage assessmentTool = new CoursePageFragment(browser)
+			.assessmentTool();
+		
+		assessmentTool
+			.users()
+		//check that ryomou has passed the test
+			.assertOnUsers(ryomou)
+			.selectUser(ryomou)
+			.assertPassed(ryomou);
+	}
+	
+	/**
+	 * An author upload a test, create a course with a test course
+	 * element, publish the course, add 2 students (Ryomou and Kanu)
+	 * to the course, configure an assessment.<br />
+	 * A first student log in before the assessment is started by the
+	 * author, the second log-in after the begin of the assessment.
+	 * Both pass the test. The Author ends the assessment. The two
+	 * students wait the end of the assessment and go back to normal
+	 * activities. The author checks the students pass the test in the
+	 * assessment tool.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void assessmentMode_manual(@InitialPage LoginPage authorLoginPage,
+			@Drone @Student WebDriver ryomouBrowser, @Drone @Participant WebDriver kanuBrowser)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		UserVO ryomou = new UserRestClient(deploymentUrl).createRandomUser("Ryomou");
+		UserVO kanu = new UserRestClient(deploymentUrl).createRandomUser("Kanu");
+		
+		//upload a test
+		String qtiTestTitle = "QTI-Test-1.2-" + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/e4_test.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile);
+		
+		//create a course
+		String courseTitle = "Course-With-QTI-Test-1.2-" + UUID.randomUUID();
+		navBar
+			.openAuthoringEnvironment()
+			.createCourse(courseTitle)
+			.clickToolbarBack();
+
+		//create a course element of type CP with the CP that we create above
+		String testNodeTitle = "Test-QTI-1.2";
+		CourseEditorPageFragment courseEditor = CoursePageFragment.getCourse(browser)
+			.edit();
+		courseEditor
+			.createNode("iqtest")
+			.nodeTitle(testNodeTitle)
+			.selectTabLearnContent()
+			.chooseTest(qtiTestTitle);
+
+		//publish the course
+		courseEditor
+			.publish()
+			.quickPublish();
+		
+		//open the course and see the test start page
+		CoursePageFragment courseRuntime = courseEditor
+			.clickToolbarBack();
+		courseRuntime
+			.clickTree()
+			.selectWithTitle(testNodeTitle);
+		OOGraphene.closeBlueMessageWindow(browser);
+		
+		//check that the title of the start page of test is correct
+		WebElement testH2 = browser.findElement(By.cssSelector("div.o_titled_wrapper.o_course_run h2"));
+		Assert.assertEquals(testNodeTitle, testH2.getText().trim());
+		
+		//add Ryomou and Kanu as a course member
+		courseRuntime.members().quickAdd(ryomou);
+		courseRuntime.members().quickAdd(kanu);
+		
+		//Kanu log in 
+		LoginPage kanuLoginPage = LoginPage.getLoginPage(kanuBrowser, deploymentUrl);
+		kanuLoginPage
+			.loginAs(kanu.getLogin(), kanu.getPassword())
+			.resume();
+		
+		// prepare and start an assessment
+		Calendar cal = Calendar.getInstance();
+		Date begin = cal.getTime();
+		cal.add(Calendar.MINUTE, 5);
+		Date end = cal.getTime();
+		String assessmentName = "Assessment-" + UUID.randomUUID();
+		courseRuntime
+			.assessmentConfiguration()
+			.createAssessmentMode()
+			.editAssessment(assessmentName, begin, end, true)
+			.save()
+			.start(assessmentName)
+			.confirmStart();
+
+		//Ryomou opens the course
+		LoginPage ryomouLoginPage = LoginPage.getLoginPage(ryomouBrowser, deploymentUrl);
+		ryomouLoginPage
+			.loginAs(ryomou.getLogin(), ryomou.getPassword());
+		//start the assessment
+		AssessmentModePage ryomouAssessment = new AssessmentModePage(ryomouBrowser)
+			.startAssessment(false);
+		//go to the test
+		CoursePageFragment ryomouTestCourse = new CoursePageFragment(ryomouBrowser);
+		ryomouTestCourse
+			.clickTree()
+			.selectWithTitle(testNodeTitle);
+		//pass the test
+		QTI12Page.getQTI12Page(ryomouBrowser).passE4(ryomou);
+
+		
+		//Kanu makes the test
+		AssessmentModePage kanuAssessment = new AssessmentModePage(kanuBrowser)
+			.startAssessment(true);
+		//go to the test
+		CoursePageFragment kanuTestCourse = new CoursePageFragment(kanuBrowser);
+		kanuTestCourse
+			.clickTree()
+			.selectWithTitle(testNodeTitle);
+		//pass the test
+		QTI12Page.getQTI12Page(kanuBrowser).passE4(kanu);
+
+		
+		//Author ends the test
+		courseRuntime
+			.assessmentConfiguration()
+			.stop(assessmentName)
+			.confirmStop();
+		
+		By continueBy = By.className("o_sel_assessment_continue");
+		OOGraphene.waitElement(continueBy, 10, ryomouBrowser);
+		OOGraphene.waitElement(continueBy, 10, kanuBrowser);
+		kanuAssessment.backToOpenOLAT();
+		ryomouAssessment.backToOpenOLAT();
+		
+		//Author check if they pass the test
+		navBar
+			.openMyCourses()
+			.select(courseTitle);	
+		//open the assessment tool
+		AssessmentToolPage assessmentTool = new CoursePageFragment(browser)
+			.assessmentTool();		
+		assessmentTool
+			.users()
+		//check that ryomou has passed the test
+			.assertOnUsers(ryomou)
+			.assertOnUsers(kanu)
+			.selectUser(ryomou)
+			.assertPassed(ryomou);
+	}
 
 }
diff --git a/src/test/java/org/olat/selenium/CourseTest.java b/src/test/java/org/olat/selenium/CourseTest.java
index a7e7057ca32..596f4b85e5a 100644
--- a/src/test/java/org/olat/selenium/CourseTest.java
+++ b/src/test/java/org/olat/selenium/CourseTest.java
@@ -202,7 +202,7 @@ public class CourseTest {
 		Assert.assertEquals(5, nodes.size());
 		for(WebElement node:nodes) {
 			node.click();
-			OOGraphene.waitBusy();
+			OOGraphene.waitBusy(browser);
 		}
 	}
 	
diff --git a/src/test/java/org/olat/selenium/UserSettingsTest.java b/src/test/java/org/olat/selenium/UserSettingsTest.java
index 12dc4e11e30..bac04ca255d 100644
--- a/src/test/java/org/olat/selenium/UserSettingsTest.java
+++ b/src/test/java/org/olat/selenium/UserSettingsTest.java
@@ -440,6 +440,6 @@ public class UserSettingsTest {
 		//we are in user management
 		browser.navigate().back();
 		//we are in "My courses", check
-		OOGraphene.waitElement(NavigationPage.myCoursesAssertBy);
+		OOGraphene.waitElement(NavigationPage.myCoursesAssertBy, browser);
 	}
 }
diff --git a/src/test/java/org/olat/selenium/page/LoginPage.java b/src/test/java/org/olat/selenium/page/LoginPage.java
index 6f8ab439ea5..90a52da3f1f 100644
--- a/src/test/java/org/olat/selenium/page/LoginPage.java
+++ b/src/test/java/org/olat/selenium/page/LoginPage.java
@@ -97,7 +97,7 @@ public class LoginPage {
 		By loginBy = By.id("o_fiooolat_login_button");
 		WebElement loginButton = browser.findElement(loginBy);
 		Graphene.guardHttp(loginButton).click();
-		OOGraphene.waitElement(authOrDisclaimerXPath);
+		OOGraphene.waitElement(authOrDisclaimerXPath, browser);
 		
 		//wipe out disclaimer
 		List<WebElement> disclaimer = browser.findElements(disclaimerXPath);
@@ -107,7 +107,7 @@ public class LoginPage {
 			
 			WebElement acknowledgeButton = browser.findElement(disclaimerButtonXPath);
 			Graphene.guardHttp(acknowledgeButton).click();
-			OOGraphene.waitElement(authXPath);
+			OOGraphene.waitElement(authXPath, browser);
 		}
 		return this;
 	}
@@ -121,7 +121,7 @@ public class LoginPage {
 		Assert.assertTrue(resume.isDisplayed());
 		
 		resume.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -130,7 +130,7 @@ public class LoginPage {
 		if(resumes.size() > 0 && resumes.get(0).isDisplayed()) {
 			WebElement resume = resumes.get(0);
 			resume.click();
-			OOGraphene.waitBusy();
+			OOGraphene.waitBusy(browser);
 		}
 		return this;
 	}
diff --git a/src/test/java/org/olat/selenium/page/NavigationPage.java b/src/test/java/org/olat/selenium/page/NavigationPage.java
index 291f3df68db..1536a98fc7c 100644
--- a/src/test/java/org/olat/selenium/page/NavigationPage.java
+++ b/src/test/java/org/olat/selenium/page/NavigationPage.java
@@ -93,7 +93,7 @@ public class NavigationPage {
 	
 	public MyCoursesPage openMyCourses() {
 		navigate(myCoursesBy);
-		OOGraphene.waitElement(myCoursesAssertBy);
+		OOGraphene.waitElement(myCoursesAssertBy, browser);
 		return new MyCoursesPage(browser);
 	}
 	
@@ -128,10 +128,10 @@ public class NavigationPage {
 
 		links = browser.findElements(linkBy);
 		Assert.assertFalse(links.isEmpty());
-		OOGraphene.waitElement(links.get(0));
+		OOGraphene.waitElement(links.get(0), browser);
 		links.get(0).click();
-		OOGraphene.waitBusy();
-		OOGraphene.waitingTransition();
+		OOGraphene.waitBusy(browser);
+		OOGraphene.waitingTransition(browser);
 	}
 	
 	public void openCourse(String title) {
@@ -144,7 +144,7 @@ public class NavigationPage {
 		Assert.assertFalse(courseLinks.isEmpty());
 		
 		courseLinks.get(0).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 	}
 	
@@ -161,7 +161,7 @@ public class NavigationPage {
 		int count = 0;
 		while(backList.size() > 0) {
 			backList.get(count).click();
-			OOGraphene.waitBusy();
+			OOGraphene.waitBusy(browser);
 			backList = browser.findElements(toolbarBackBy);
 			
 			Assert.assertTrue(count++ < 3);
diff --git a/src/test/java/org/olat/selenium/page/Student.java b/src/test/java/org/olat/selenium/page/Student.java
new file mode 100644
index 00000000000..3b41f7385f1
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/Student.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: 08.07.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.FIELD, ElementType.PARAMETER })
+@Qualifier
+public @interface Student {
+
+}
diff --git a/src/test/java/org/olat/selenium/page/core/AdministrationPage.java b/src/test/java/org/olat/selenium/page/core/AdministrationPage.java
index b753351a527..91ab42dde4e 100644
--- a/src/test/java/org/olat/selenium/page/core/AdministrationPage.java
+++ b/src/test/java/org/olat/selenium/page/core/AdministrationPage.java
@@ -54,11 +54,11 @@ public class AdministrationPage {
 		//system tree node
 		WebElement systemLink = browser.findElement(By.xpath("//div[contains(@class,'o_tree')]//a[contains(@href,'systemParent/')]"));
 		systemLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		//cache tree node
 		WebElement cacheLink = browser.findElement(By.cssSelector(".o_sel_caches span.o_tree_level_label_leaf>a"));
 		cacheLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		//table
 		WebElement emptyLink = null;
 		List<WebElement> rows = browser.findElements(By.cssSelector(".o_table_wrapper table>tbody>tr"));
@@ -70,11 +70,11 @@ public class AdministrationPage {
 		Assert.assertNotNull(emptyLink);
 		//click to empty
 		emptyLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		//confirm
 		WebElement yesLink = browser.findElement(By.xpath("//div[contains(@class,'modal-dialog')]//a[contains(@href,'link_0')]"));
 		yesLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 }
diff --git a/src/test/java/org/olat/selenium/page/core/IMPage.java b/src/test/java/org/olat/selenium/page/core/IMPage.java
index 3cf81d91430..3116596ac37 100644
--- a/src/test/java/org/olat/selenium/page/core/IMPage.java
+++ b/src/test/java/org/olat/selenium/page/core/IMPage.java
@@ -51,13 +51,13 @@ public class IMPage {
 	 */
 	public IMPage openGroupChat() {
 		By openBy = By.className("o_sel_im_open_tool_chat");
-		OOGraphene.waitElement(openBy);
+		OOGraphene.waitElement(openBy, browser);
 		WebElement openButton = browser.findElement(openBy);
 		openButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		By imModalBy = By.className("o_im_chat");
-		OOGraphene.waitElement(imModalBy);
+		OOGraphene.waitElement(imModalBy, browser);
 		return this;
 	}
 	
@@ -74,7 +74,7 @@ public class IMPage {
 		By sendMessageBy = By.cssSelector(".o_im_chat_form a.btn.btn-default");
 		WebElement sendMessageButton = browser.findElement(sendMessageBy);
 		sendMessageButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
diff --git a/src/test/java/org/olat/selenium/page/core/MenuTreePageFragment.java b/src/test/java/org/olat/selenium/page/core/MenuTreePageFragment.java
index 45cc624d3b5..3bd21b5aff4 100644
--- a/src/test/java/org/olat/selenium/page/core/MenuTreePageFragment.java
+++ b/src/test/java/org/olat/selenium/page/core/MenuTreePageFragment.java
@@ -63,7 +63,7 @@ public class MenuTreePageFragment {
 		Assert.assertFalse(rootLinks.isEmpty());
 		
 		rootLinks.get(0).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -75,7 +75,7 @@ public class MenuTreePageFragment {
 			String text = nodeLink.getText();
 			if(text.contains(title)) {
 				nodeLink.click();
-				OOGraphene.waitBusy();
+				OOGraphene.waitBusy(browser);
 				found = true;
 			}
 		}
diff --git a/src/test/java/org/olat/selenium/page/course/AssessmentModePage.java b/src/test/java/org/olat/selenium/page/course/AssessmentModePage.java
new file mode 100644
index 00000000000..6d4b31897aa
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/course/AssessmentModePage.java
@@ -0,0 +1,218 @@
+/**
+ * <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 java.util.Date;
+import java.util.List;
+
+import org.jboss.arquillian.drone.api.annotation.Drone;
+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;
+import org.openqa.selenium.support.ui.Select;
+
+/**
+ * 
+ * Drive the assessment settings
+ * 
+ * Initial date: 13.02.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessmentModePage {
+	
+	@Drone
+	private WebDriver browser;
+	
+	public AssessmentModePage() {
+		//
+	}
+	
+	public AssessmentModePage(WebDriver browser) {
+		this.browser = browser;
+	}
+	
+	/**
+	 * Create a new assessment mode settings in the list
+	 * of assessment.
+	 * 
+	 * @return
+	 */
+	public AssessmentModePage createAssessmentMode() {
+		By addBy = By.className("o_sel_assessment_mode_add");
+		browser.findElement(addBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	/**
+	 * 
+	 * Fill the settings for the assessment.
+	 * 
+	 * @param name
+	 * @param begin
+	 * @param end
+	 * @param manual
+	 * @return
+	 */
+	public AssessmentModePage editAssessment(String name, Date begin, Date end, boolean manual) {
+		OOGraphene.closeBlueMessageWindow(browser);
+		
+		By nameBy = By.cssSelector("div.o_sel_assessment_mode_name input[type='text']");
+		browser.findElement(nameBy).sendKeys(name);
+		//begin
+		OOGraphene.datetime(begin, "o_sel_assessment_mode_begin", browser);
+		//end
+		OOGraphene.datetime(end, "o_sel_assessment_mode_end", browser);
+		//start mode
+		By startBy = By.cssSelector("div.o_sel_assessment_mode_start_mode select");
+		WebElement startEl = browser.findElement(startBy);
+		new Select(startEl).selectByValue(manual ? "manual" : "automatic");
+		//audience course
+		
+		By audienceBy = By.xpath("//div[contains(@class,'o_sel_assessment_mode_audience')]//input[@value='course']");
+		WebElement audienceEl = browser.findElement(audienceBy);
+		audienceEl.click();
+		return this;
+	}
+	
+	/**
+	 * Save the assessment mode settings.
+	 * 
+	 * @return
+	 */
+	public AssessmentModePage save() {
+		By saveButtonBy = By.cssSelector(".o_sel_assessment_mode_edit_form button.btn-primary");
+		browser.findElement(saveButtonBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	/**
+	 * Start an assessment in the list by its name
+	 * 
+	 * @param name
+	 * @return
+	 */
+	public AssessmentModePage start(String name) {
+		WebElement startEl = null;
+		By rowBy = By.cssSelector("fieldset.o_sel_assessment_mode_list table.table>tbody>tr");
+		By linkBy = By.cssSelector("td a");
+		List<WebElement> rowList = browser.findElements(rowBy);
+		for(WebElement row:rowList) {
+			if(row.getText().contains(name)) {
+				List<WebElement> linksEl = row.findElements(linkBy);
+				for(WebElement linkEl:linksEl) {
+					String href = linkEl.getAttribute("href");
+					if(href != null && href.contains("','start','")) {
+						startEl = linkEl;
+					}
+				}
+			}
+		}
+		
+		Assert.assertNotNull(startEl);
+		startEl.click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	/**
+	 * Confirm the start of the assessment.
+	 * 
+	 * @return
+	 */
+	public AssessmentModePage confirmStart() {
+		return confirmDialog();
+	}
+	
+	/**
+	 * Confirm a standard yes/no dialog
+	 * @return
+	 */
+	private AssessmentModePage confirmDialog() {
+		By confirmButtonBy = By.cssSelector("div.modal-dialog div.modal-footer a");
+		List<WebElement> buttonsEl = browser.findElements(confirmButtonBy);
+		buttonsEl.get(0).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	/**
+	 * Stop an assessment in the list by its name
+	 * 
+	 * @param name
+	 * @return
+	 */
+	public AssessmentModePage stop(String name) {
+		WebElement startEl = null;
+		By rowBy = By.cssSelector("fieldset.o_sel_assessment_mode_list table.table>tbody>tr");
+		By linkBy = By.cssSelector("td a");
+		List<WebElement> rowList = browser.findElements(rowBy);
+		for(WebElement row:rowList) {
+			if(row.getText().contains(name)) {
+				List<WebElement> linksEl = row.findElements(linkBy);
+				for(WebElement linkEl:linksEl) {
+					String href = linkEl.getAttribute("href");
+					if(href != null && href.contains("','stop','")) {
+						startEl = linkEl;
+					}
+				}
+			}
+		}
+		
+		Assert.assertNotNull(startEl);
+		startEl.click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	public AssessmentModePage confirmStop() {
+		return confirmDialog();
+	}
+	
+	/**
+	 * A student can start its assessment
+	 * 
+	 * @return
+	 */
+	public AssessmentModePage startAssessment(boolean wait) {
+		By startBy = By.cssSelector("div.modal-dialog div.modal-body div.o_button_group a.o_sel_assessment_start");
+		if(wait) {
+			OOGraphene.waitElement(startBy, browser);
+		}
+		List<WebElement> buttonsEl = browser.findElements(startBy);
+		buttonsEl.get(0).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	/**
+	 * After an assessment, go back to OpenOLAT.
+	 */
+	public void backToOpenOLAT() {
+		By continueBy = By.cssSelector("div.modal-dialog div.modal-body div.o_button_group a.o_sel_assessment_continue");
+		WebElement continueEl = browser.findElement(continueBy);
+		continueEl.click();
+		OOGraphene.waitBusy(browser);
+	}
+}
diff --git a/src/test/java/org/olat/selenium/page/course/AssessmentToolPage.java b/src/test/java/org/olat/selenium/page/course/AssessmentToolPage.java
new file mode 100644
index 00000000000..6227e1e2b61
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/course/AssessmentToolPage.java
@@ -0,0 +1,96 @@
+/**
+ * <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 java.util.List;
+
+import org.jboss.arquillian.drone.api.annotation.Drone;
+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;
+
+/**
+ * 
+ * Initial date: 12.02.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessmentToolPage {
+	
+	@Drone
+	private WebDriver browser;
+	
+	public AssessmentToolPage() {
+		//
+	}
+	
+	public AssessmentToolPage(WebDriver browser) {
+		this.browser = browser;
+	}
+	
+	public AssessmentToolPage users() {
+		By usersBy = By.cssSelector("li.o_sel_assessment_tool_users a");
+		WebElement usersLink = browser.findElement(usersBy);
+		usersLink.click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	public AssessmentToolPage assertOnUsers(UserVO user) {
+		By usersCellsBy = By.cssSelector("div.o_table_layout table tr td.text-left");
+		List<WebElement> usersCellsList = browser.findElements(usersCellsBy);
+		Assert.assertFalse(usersCellsList.isEmpty());
+		
+		boolean found = false;
+		for(WebElement usersCell:usersCellsList) {
+			found |= usersCell.getText().contains(user.getFirstName());
+		}
+		Assert.assertTrue(found);
+		return this;
+	}
+	
+	public AssessmentToolPage selectUser(UserVO user) {
+		By userLinksBy = By.xpath("//div[contains(@class,'o_table_layout')]//table//tr//td//a[text()[contains(.,'" + user.getFirstName() + "')]]");
+		WebElement userLink = browser.findElement(userLinksBy);
+		userLink.click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	public AssessmentToolPage assertPassed(UserVO user) {
+		By userInfosBy = By.cssSelector("div.panel li.list-group-item");
+		List<WebElement> userInfoList = browser.findElements(userInfosBy);
+		Assert.assertFalse(userInfoList.isEmpty());
+		boolean foundFirstName = false;
+		for(WebElement userInfo:userInfoList) {
+			foundFirstName |= userInfo.getText().contains(user.getFirstName());
+		}
+		Assert.assertTrue(foundFirstName);
+		
+		By passedBy = By.cssSelector("div.o_table_layout table tr td.text-left span.o_state.o_passed");
+		List<WebElement> passedEl = browser.findElements(passedBy);
+		Assert.assertFalse(passedEl.isEmpty());
+		Assert.assertTrue(passedEl.get(0).isDisplayed());
+		return this;
+	}
+}
diff --git a/src/test/java/org/olat/selenium/page/course/CourseEditorPageFragment.java b/src/test/java/org/olat/selenium/page/course/CourseEditorPageFragment.java
index 8ca5d0ce2bc..6ff194009d0 100644
--- a/src/test/java/org/olat/selenium/page/course/CourseEditorPageFragment.java
+++ b/src/test/java/org/olat/selenium/page/course/CourseEditorPageFragment.java
@@ -70,14 +70,11 @@ public class CourseEditorPageFragment {
 	@Drone
 	private WebDriver browser;
 	
-	@FindBy(id="o_main_left_content")
-	private WebElement treeContainer;
-	
 	@FindBy(className="o_course_editor")
 	private WebElement editor;
 	
 	public static CourseEditorPageFragment getEditor(WebDriver browser) {
-		OOGraphene.waitElement(editorBy);
+		OOGraphene.waitElement(editorBy, browser);
 		WebElement main = browser.findElement(By.id("o_main"));
 		return Graphene.createPageFragment(CourseEditorPageFragment.class, main);
 	}
@@ -96,7 +93,7 @@ public class CourseEditorPageFragment {
 		WebElement createButton = browser.findElement(createNodeButton);
 		Assert.assertTrue(createButton.isDisplayed());
 		createButton.click();
-		OOGraphene.waitElement(createNodeModalBy);
+		OOGraphene.waitElement(createNodeModalBy, browser);
 		
 		//modal
 		WebElement createNodeModal = browser.findElement(createNodeModalBy);
@@ -106,7 +103,7 @@ public class CourseEditorPageFragment {
 		WebElement createNodeLink = createNodeModal.findElement(node);
 		Assert.assertTrue(createNodeLink.isDisplayed());
 		createNodeLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -129,7 +126,7 @@ public class CourseEditorPageFragment {
 		
 		By saveButton = By.cssSelector("button.o_sel_node_editor_submit");
 		browser.findElement(saveButton).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		return this;
 	}
@@ -147,7 +144,7 @@ public class CourseEditorPageFragment {
 		a_a:
 		for(WebElement tabLink:tabLinks) {
 			tabLink.click();
-			OOGraphene.waitBusy();
+			OOGraphene.waitBusy(browser);
 			for(By chooseRepoEntriesButton: chooseRepoEntriesButtonList) {
 				List<WebElement> chooseRepoEntry = browser.findElements(chooseRepoEntriesButton);
 				if(chooseRepoEntry.size() > 0) {
@@ -200,11 +197,11 @@ public class CourseEditorPageFragment {
 	 */
 	public CourseEditorPageFragment chooseResource(By chooseButton, String resourceTitle) {
 		browser.findElement(chooseButton).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		//popup
 		WebElement popup = browser.findElement(By.className("o_sel_search_referenceable_entries"));
 		popup.findElement(By.cssSelector("a.o_sel_repo_popup_my_resources")).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		//find the row
 		WebElement selectRow = null;
@@ -221,7 +218,7 @@ public class CourseEditorPageFragment {
 		//find the select in the row
 		WebElement selectLink = selectRow.findElement(By.xpath("//a[contains(@href,'rtbSelectLink')]"));
 		selectLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		//double check that the resource is selected (search the preview link)
 		By previewLink = By.xpath("//a/span[text()[contains(.,'" + resourceTitle + "')]]");
@@ -274,7 +271,7 @@ public class CourseEditorPageFragment {
 		By editBy = By.className("o_sel_edit_map");
 		WebElement editLink = browser.findElement(editBy);
 		editLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		WebElement main = browser.findElement(By.id("o_main_wrapper"));
 		return Graphene.createPageFragment(PortfolioPage.class, main);
@@ -284,15 +281,15 @@ public class CourseEditorPageFragment {
 		OOGraphene.closeBlueMessageWindow(browser);
 		
 		browser.findElement(chooseButton).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		//popup
 		WebElement popup = browser.findElement(By.className("o_sel_search_referenceable_entries"));
 		popup.findElement(By.cssSelector("a.o_sel_repo_popup_my_resources")).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		//click create
 		popup.findElement(By.className("o_sel_repo_popup_create_resource")).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 
 		//fill the create form
 		return fillCreateForm(resourceTitle);
@@ -302,7 +299,7 @@ public class CourseEditorPageFragment {
 		WebElement modal = browser.findElement(By.cssSelector("div.modal.o_sel_author_create_popup"));
 		modal.findElement(AuthoringEnvPage.displayNameInput).sendKeys(displayName);
 		modal.findElement(AuthoringEnvPage.createSubmit).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -317,7 +314,7 @@ public class CourseEditorPageFragment {
 		publishButton.click();
 		
 		By modalBy = By.className("modal");
-		OOGraphene.waitElement(modalBy);
+		OOGraphene.waitElement(modalBy, browser);
 		WebElement modal = browser.findElement(By.className("modal"));
 		return Graphene.createPageFragment(PublisherPageFragment.class, modal);
 	}
@@ -329,7 +326,7 @@ public class CourseEditorPageFragment {
 	 */
 	public CoursePageFragment clickToolbarBack() {
 		browser.findElement(toolbarBackBy).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 		
 		WebElement main = browser.findElement(By.id("o_main"));
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 28770981829..a01d5d7fcf8 100644
--- a/src/test/java/org/olat/selenium/page/course/CoursePageFragment.java
+++ b/src/test/java/org/olat/selenium/page/course/CoursePageFragment.java
@@ -43,7 +43,14 @@ public class CoursePageFragment {
 	public static final By courseRun = By.className("o_course_run");
 	public static final By toolsMenu = By.cssSelector("ul.o_sel_course_tools");
 	public static final By toolsMenuCaret = By.cssSelector("a.o_sel_course_tools");
+
+	public static final By settingsMenu = By.cssSelector("ul.o_sel_course_settings");
+	public static final By settingsMenuCaret = By.cssSelector("a.o_sel_course_settings");
+	
 	public static final By editCourseBy = By.className("o_sel_course_editor");
+	public static final By assessmentToolBy = By.className("o_sel_course_assessment_tool");
+	public static final By assessmentModeBy = By.className("o_sel_course_assessment_mode");
+	public static final By membersCourseBy = By.className("o_sel_course_members");
 	public static final By treeContainerBy = By.id("o_main_left_content");
 	
 	@Drone
@@ -60,12 +67,12 @@ public class CoursePageFragment {
 	
 	public static CoursePageFragment getCourse(WebDriver browser, URL deploymentUrl, CourseVO course) {
 		browser.navigate().to(deploymentUrl.toExternalForm() + "url/RepositoryEntry/" + course.getRepoEntryKey());
-		OOGraphene.waitElement(courseRun);
+		OOGraphene.waitElement(courseRun, browser);
 		return new CoursePageFragment(browser);
 	}
 	
 	public static CoursePageFragment getCourse(WebDriver browser) {
-		OOGraphene.waitElement(courseRun);
+		OOGraphene.waitElement(courseRun, browser);
 		return new CoursePageFragment(browser);
 	}
 	
@@ -102,7 +109,17 @@ public class CoursePageFragment {
 	 */
 	public CoursePageFragment openToolsMenu() {
 		browser.findElement(toolsMenuCaret).click();
-		OOGraphene.waitElement(toolsMenu);
+		OOGraphene.waitElement(toolsMenu, browser);
+		return this;
+	}
+	
+	/**
+	 * Open the settings drop-down
+	 * @return
+	 */
+	public CoursePageFragment openSettingsMenu() {
+		browser.findElement(settingsMenuCaret).click();
+		OOGraphene.waitElement(settingsMenu, browser);
 		return this;
 	}
 	
@@ -115,10 +132,48 @@ public class CoursePageFragment {
 			openToolsMenu();
 		}
 		browser.findElement(editCourseBy).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 
 		WebElement main = browser.findElement(By.id("o_main"));
 		return Graphene.createPageFragment(CourseEditorPageFragment.class, main);
 	}
+	
+	/**
+	 * Click the members link in the tools drop-down
+	 * @return
+	 */
+	public MembersPage members() {
+		if(!browser.findElement(toolsMenu).isDisplayed()) {
+			openToolsMenu();
+		}
+		browser.findElement(membersCourseBy).click();
+		OOGraphene.waitBusy(browser);
+
+		WebElement main = browser.findElement(By.id("o_main"));
+		return Graphene.createPageFragment(MembersPage.class, main);
+	}
+	
+	public AssessmentToolPage assessmentTool() {
+		if(!browser.findElement(toolsMenu).isDisplayed()) {
+			openToolsMenu();
+		}
+		browser.findElement(assessmentToolBy).click();
+		OOGraphene.waitBusy(browser);
+
+		WebElement main = browser.findElement(By.id("o_main"));
+		Assert.assertTrue(main.isDisplayed());
+		return new AssessmentToolPage(browser);
+	}
+	
+	public AssessmentModePage assessmentConfiguration() {
+		if(!browser.findElement(settingsMenu).isDisplayed()) {
+			openSettingsMenu();
+		}
+		browser.findElement(assessmentModeBy).click();
+		OOGraphene.waitBusy(browser);
+
+		WebElement main = browser.findElement(By.id("o_main_container"));
+		return Graphene.createPageFragment(AssessmentModePage.class, main);
+	}
 }
diff --git a/src/test/java/org/olat/selenium/page/course/CourseWizardPage.java b/src/test/java/org/olat/selenium/page/course/CourseWizardPage.java
index 5e6cde50c9c..7d393fc72f8 100644
--- a/src/test/java/org/olat/selenium/page/course/CourseWizardPage.java
+++ b/src/test/java/org/olat/selenium/page/course/CourseWizardPage.java
@@ -60,7 +60,7 @@ public class CourseWizardPage {
 		Assert.assertTrue(next.isDisplayed());
 		Assert.assertTrue(next.isEnabled());
 		next.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 		return this;
 	}
@@ -74,7 +74,7 @@ public class CourseWizardPage {
 		Assert.assertTrue(finish.isDisplayed());
 		Assert.assertTrue(finish.isEnabled());
 		finish.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 		return this;
 	}
@@ -85,7 +85,7 @@ public class CourseWizardPage {
 		Assert.assertFalse(checkAll.isEmpty());
 		for(WebElement check:checkAll) {
 			check.click();
-			OOGraphene.waitBusy();
+			OOGraphene.waitBusy(browser);
 		}
 		
 		return this;
diff --git a/src/test/java/org/olat/selenium/page/course/MembersPage.java b/src/test/java/org/olat/selenium/page/course/MembersPage.java
new file mode 100644
index 00000000000..f7cafa5b757
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/course/MembersPage.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.jboss.arquillian.drone.api.annotation.Drone;
+import org.olat.selenium.page.graphene.OOGraphene;
+import org.olat.selenium.page.group.MembersWizardPage;
+import org.olat.user.restapi.UserVO;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+/**
+ * 
+ * Drive the members management page in course
+ * 
+ * 
+ * Initial date: 12.02.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class MembersPage {
+
+	@Drone
+	private WebDriver browser;
+	
+	public MembersWizardPage addMember() {
+		By addMemberBy = By.className("o_sel_course_add_member");
+		WebElement addMemberButton = browser.findElement(addMemberBy);
+		addMemberButton.click();
+		OOGraphene.waitBusy(browser);
+		return new MembersWizardPage(browser);
+	}
+	
+	/**
+	 * Add a user by username as participant
+	 * 
+	 * @param user
+	 */
+	public void quickAdd(UserVO user) {
+		addMember()
+			.searchMember(user)
+			.next().next().next().finish();
+	}
+
+}
diff --git a/src/test/java/org/olat/selenium/page/course/MyCoursesPage.java b/src/test/java/org/olat/selenium/page/course/MyCoursesPage.java
index f69d273a50a..a30cfe27eb9 100644
--- a/src/test/java/org/olat/selenium/page/course/MyCoursesPage.java
+++ b/src/test/java/org/olat/selenium/page/course/MyCoursesPage.java
@@ -52,7 +52,7 @@ public class MyCoursesPage {
 		By searchBy = By.className("o_sel_mycourses_search");
 		WebElement searchLink = browser.findElement(searchBy);
 		searchLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -60,7 +60,7 @@ public class MyCoursesPage {
 		By catalogBy = By.className("o_sel_mycourses_catlog");
 		WebElement catalogLink = browser.findElement(catalogBy);
 		catalogLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -70,7 +70,7 @@ public class MyCoursesPage {
 		if(extendedSearchButtons.size() > 0 && extendedSearchButtons.get(0).isDisplayed()) {
 			WebElement extendedSearchButton = extendedSearchButtons.get(0);
 			extendedSearchButton.click();
-			OOGraphene.waitBusy();
+			OOGraphene.waitBusy(browser);
 		}
 
 		By titleBy = By.cssSelector(".o_sel_repo_search_displayname input[type='text']");
@@ -80,7 +80,7 @@ public class MyCoursesPage {
 		By searchButton = By.className("o_sel_repo_search_button");
 		WebElement searchEl = browser.findElement(searchButton);
 		searchEl.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -95,7 +95,7 @@ public class MyCoursesPage {
 		}
 		Assert.assertNotNull(linkToSelect);
 		linkToSelect.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -111,7 +111,7 @@ public class MyCoursesPage {
 		}
 		Assert.assertNotNull(selectCategory);
 		selectCategory.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -119,7 +119,7 @@ public class MyCoursesPage {
 		By startBy = By.className("o_start");
 		WebElement startLink = browser.findElement(startBy);
 		startLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 	}
 
 }
diff --git a/src/test/java/org/olat/selenium/page/course/PublisherPageFragment.java b/src/test/java/org/olat/selenium/page/course/PublisherPageFragment.java
index 77c0e563b14..7381a3ce3bf 100644
--- a/src/test/java/org/olat/selenium/page/course/PublisherPageFragment.java
+++ b/src/test/java/org/olat/selenium/page/course/PublisherPageFragment.java
@@ -57,10 +57,15 @@ public class PublisherPageFragment {
 		return this;
 	}
 	
+
 	public void quickPublish() {
+		quickPublish(Access.guests);
+	}
+	
+	public void quickPublish(Access access) {
 		assertOnPublisher()
 			.next()
-			.selectAccess(Access.guests)
+			.selectAccess(access)
 			.next()
 			.selectCatalog(false)
 			.next() // -> no problem found
@@ -72,7 +77,7 @@ public class PublisherPageFragment {
 		Assert.assertTrue(next.isDisplayed());
 		Assert.assertTrue(next.isEnabled());
 		next.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 		return this;
 	}
@@ -82,7 +87,7 @@ public class PublisherPageFragment {
 		Assert.assertTrue(finish.isDisplayed());
 		Assert.assertTrue(finish.isEnabled());
 		finish.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 		return this;
 	}
@@ -103,7 +108,7 @@ public class PublisherPageFragment {
 		By addToCatalogBy = By.className("o_sel_publish_add_to_catalog");
 		WebElement addToCatalogButton = browser.findElement(addToCatalogBy);
 		addToCatalogButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		if(parentNode != null) {
 			selectCatalogNode(parentNode);
@@ -113,7 +118,7 @@ public class PublisherPageFragment {
 		By selectBy = By.cssSelector(".o_sel_catalog_chooser_tree a.o_sel_catalog_add_select");
 		WebElement selectButton = browser.findElement(selectBy);
 		selectButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -129,7 +134,7 @@ public class PublisherPageFragment {
 		}
 		Assert.assertNotNull(namedNode);
 		namedNode.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 	}
 	
 	public enum Access {
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 2f66b7d0fea..b704ebde107 100644
--- a/src/test/java/org/olat/selenium/page/forum/ForumPage.java
+++ b/src/test/java/org/olat/selenium/page/forum/ForumPage.java
@@ -70,7 +70,7 @@ public class ForumPage {
 		By newThreadBy = By.className("o_sel_forum_thread_new");
 		WebElement newThreadButton = browser.findElement(newThreadBy);
 		newThreadButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		//fill the form
 		By titleBy = By.cssSelector("div.modal-content form input[type='text']");
@@ -83,7 +83,7 @@ public class ForumPage {
 		By saveBy = By.cssSelector("div.modal-content form button.btn-primary");
 		WebElement saveButton = browser.findElement(saveBy);
 		saveButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -95,8 +95,7 @@ public class ForumPage {
 		By addAsArtefactBy = By.className("o_eportfolio_add");
 		WebElement addAsArtefactButton = browser.findElement(addAsArtefactBy);
 		addAsArtefactButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return ArtefactWizardPage.getWizard(browser);
 	}
-
-}
+}
\ No newline at end of file
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 4eecd448543..442017e1215 100644
--- a/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java
+++ b/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java
@@ -20,10 +20,15 @@
 package org.olat.selenium.page.graphene;
 
 import java.io.File;
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Date;
 import java.util.List;
+import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
 import org.jboss.arquillian.graphene.Graphene;
+import org.junit.Assert;
 import org.openqa.selenium.By;
 import org.openqa.selenium.ElementNotVisibleException;
 import org.openqa.selenium.JavascriptExecutor;
@@ -41,16 +46,21 @@ public class OOGraphene {
 
 	private static final long poolingDuration = 25;
 	
-	public static void waitBusy() {
-		Graphene.waitModel().pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until(new BusyPredicate());
+	public static void waitBusy(WebDriver browser) {
+		Graphene.waitModel(browser).pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until(new BusyPredicate());
 	}
 	
-	public static void waitElement(By element) {
-		Graphene.waitModel().pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until().element(element).is().visible();
+	public static void waitElement(By element, WebDriver browser) {
+		Graphene.waitModel(browser).pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until().element(element).is().visible();
 	}
 	
-	public static void waitElement(WebElement element) {
-		Graphene.waitModel().pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until().element(element).is().visible();
+	public static void waitElement(By element, int timeoutInSeconds, WebDriver browser) {
+		Graphene.waitModel(browser).withTimeout(timeoutInSeconds, TimeUnit.SECONDS)
+			.pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until().element(element).is().visible();
+	}
+	
+	public static void waitElement(WebElement element, WebDriver browser) {
+		Graphene.waitModel(browser).pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until().element(element).is().visible();
 	}
 	
 	public static final void tinymce(String content, WebDriver browser) {
@@ -58,8 +68,45 @@ public class OOGraphene {
 		((JavascriptExecutor)browser).executeScript("top.tinymce.activeEditor.setContent('" + content + "')");
 	}
 	
-	public static final void waitingTransition() {
-		Graphene.waitModel().pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until(new TransitionPredicate());
+	public static final void date(Date date, String seleniumCssClass, WebDriver browser) {
+		Locale locale = getLocale(browser);
+		String dateText = DateFormat.getDateInstance(DateFormat.SHORT, locale).format(date);
+		By dateBy = By.cssSelector("div." + seleniumCssClass + " input.o_date_day");
+		browser.findElement(dateBy).sendKeys(dateText);
+	}
+	
+	public static final void datetime(Date date, String seleniumCssClass, WebDriver browser) {
+		Locale locale = getLocale(browser);
+		String dateText = DateFormat.getDateInstance(DateFormat.SHORT, locale).format(date);
+		By dateBy = By.cssSelector("div." + seleniumCssClass + " input.o_date_day");
+		browser.findElement(dateBy).sendKeys(dateText);
+		
+		By timeBy = By.cssSelector("div." + seleniumCssClass + " input.o_date_ms");
+		List<WebElement> timeEls = browser.findElements(timeBy);
+		Assert.assertNotNull(timeEls);
+		Assert.assertEquals(2, timeEls.size());
+		
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(date);
+		int hour = cal.get(Calendar.HOUR_OF_DAY);
+		int minute = cal.get(Calendar.MINUTE);
+		timeEls.get(0).click();
+		timeEls.get(0).clear();
+		timeEls.get(0).sendKeys(Integer.toString(hour));
+		timeEls.get(1).clear();
+		timeEls.get(1).sendKeys(Integer.toString(minute));
+	}
+	
+	public static final Locale getLocale(WebDriver browser) {
+		String cssLanguage = browser.findElement(By.id("o_body")).getAttribute("class");
+		if(cssLanguage.contains("o_lang_de")) {
+			return Locale.GERMAN;
+		}
+		return Locale.ENGLISH;
+	}
+	
+	public static final void waitingTransition(WebDriver browser) {
+		Graphene.waitModel(browser).pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until(new TransitionPredicate());
 		waitingALittleBit();
 	}
 	
diff --git a/src/test/java/org/olat/selenium/page/group/GroupPage.java b/src/test/java/org/olat/selenium/page/group/GroupPage.java
index 84d82785718..977eda956c0 100644
--- a/src/test/java/org/olat/selenium/page/group/GroupPage.java
+++ b/src/test/java/org/olat/selenium/page/group/GroupPage.java
@@ -59,7 +59,7 @@ public class GroupPage {
 		By adminBy = By.xpath("//div[contains(@class,'o_tree')]//a[contains(@href,'MENU_ADMINISTRATION')]");
 		WebElement adminLink = browser.findElement(adminBy);
 		adminLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -77,7 +77,7 @@ public class GroupPage {
 		By chatBy = By.cssSelector("li.o_sel_group_chat a");
 		WebElement chatNode = browser.findElement(chatBy);
 		chatNode.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return new IMPage(browser);
 	}
 	
@@ -87,7 +87,7 @@ public class GroupPage {
 		if(owners) {
 			showOwnersEl.click();
 		}
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		By showParticipants = By.cssSelector(".o_sel_group_show_participants input[type='checkbox']");
 		WebElement showParticipantsEl = browser.findElement(showParticipants);
@@ -95,7 +95,7 @@ public class GroupPage {
 			showParticipantsEl.click();
 		}
 		
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -105,7 +105,7 @@ public class GroupPage {
 		Assert.assertFalse(checkTools.isEmpty());
 		for(WebElement checkTool:checkTools) {
 			checkTool.click();
-			OOGraphene.waitBusy();
+			OOGraphene.waitBusy(browser);
 		}
 		return this;
 	}
@@ -114,20 +114,20 @@ public class GroupPage {
 		By addMemberBy = By.className("o_sel_group_add_member");
 		WebElement addMemberButton = browser.findElement(addMemberBy);
 		addMemberButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return new MembersWizardPage(browser);
 	}
 	
 	private void openAdminTab(By marker) {
 		By navBarAdmin = By.cssSelector("div.o_tabbed_pane ul>li>a");
-		OOGraphene.waitElement(navBarAdmin);
+		OOGraphene.waitElement(navBarAdmin, browser);
 		List<WebElement> tabLinks = browser.findElements(navBarAdmin);
 		Assert.assertFalse(tabLinks.isEmpty());
 
 		boolean found = false;
 		for(WebElement tabLink:tabLinks) {
 			tabLink.click();
-			OOGraphene.waitBusy();
+			OOGraphene.waitBusy(browser);
 			List<WebElement> markerEls = browser.findElements(marker);
 			if(markerEls.size() > 0) {
 				found = true;
diff --git a/src/test/java/org/olat/selenium/page/group/GroupsPage.java b/src/test/java/org/olat/selenium/page/group/GroupsPage.java
index a569707ecb0..d0bb09fb504 100644
--- a/src/test/java/org/olat/selenium/page/group/GroupsPage.java
+++ b/src/test/java/org/olat/selenium/page/group/GroupsPage.java
@@ -47,7 +47,7 @@ public class GroupsPage {
 		By createBy = By.className("o_sel_group_create");
 		WebElement createButton = browser.findElement(createBy);
 		createButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		//fill the form
 		By nameBy = By.cssSelector(".o_sel_group_edit_title input[type='text']");
@@ -59,7 +59,7 @@ public class GroupsPage {
 		By submitBy = By.cssSelector(".o_sel_group_edit_group_form button.btn-primary");
 		WebElement submitButton = browser.findElement(submitBy);
 		submitButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		return new GroupPage(browser);
 	}
@@ -84,7 +84,7 @@ public class GroupsPage {
 		groupLink.click();
 		
 		By rootTreeNodeBy = By.xpath("//div[contains(@class,'o_tree')]//a/span[contains(text(),'" + name+ "')]");
-		OOGraphene.waitElement(rootTreeNodeBy);
+		OOGraphene.waitElement(rootTreeNodeBy, browser);
 		
 		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
index 4e23856a345..8becdc8070c 100644
--- a/src/test/java/org/olat/selenium/page/group/MembersWizardPage.java
+++ b/src/test/java/org/olat/selenium/page/group/MembersWizardPage.java
@@ -51,7 +51,7 @@ public class MembersWizardPage {
 		Assert.assertTrue(next.isDisplayed());
 		Assert.assertTrue(next.isEnabled());
 		next.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 		return this;
 	}
@@ -61,7 +61,7 @@ public class MembersWizardPage {
 		Assert.assertTrue(finish.isDisplayed());
 		Assert.assertTrue(finish.isEnabled());
 		finish.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 		return this;
 	}
@@ -74,7 +74,7 @@ public class MembersWizardPage {
 	public MembersWizardPage searchMember(UserVO user) {
 		//Search by username
 		By usernameBy = By.cssSelector(".o_sel_usersearch_searchform input[type='text']");
-		OOGraphene.waitElement(usernameBy);
+		OOGraphene.waitElement(usernameBy, browser);
 		
 		List<WebElement> searchFields = browser.findElements(usernameBy);
 		Assert.assertFalse(searchFields.isEmpty());
@@ -83,7 +83,7 @@ public class MembersWizardPage {
 		By searchBy = By.cssSelector(".o_sel_usersearch_searchform a.btn-default");
 		WebElement searchButton = browser.findElement(searchBy);
 		searchButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		//check
 		By checkAllBy = By.cssSelector("div.modal div.o_table_wrapper input[type='checkbox']");
diff --git a/src/test/java/org/olat/selenium/page/portfolio/ArtefactWizardPage.java b/src/test/java/org/olat/selenium/page/portfolio/ArtefactWizardPage.java
index d86886255bd..63760039fa9 100644
--- a/src/test/java/org/olat/selenium/page/portfolio/ArtefactWizardPage.java
+++ b/src/test/java/org/olat/selenium/page/portfolio/ArtefactWizardPage.java
@@ -61,7 +61,7 @@ public class ArtefactWizardPage {
 		Assert.assertTrue(next.isDisplayed());
 		Assert.assertTrue(next.isEnabled());
 		next.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 		return this;
 	}
@@ -75,7 +75,7 @@ public class ArtefactWizardPage {
 		Assert.assertTrue(finish.isDisplayed());
 		Assert.assertTrue(finish.isEnabled());
 		finish.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 		return this;
 	}
@@ -140,6 +140,6 @@ public class ArtefactWizardPage {
 		}
 		Assert.assertNotNull(linkToClick);
 		linkToClick.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 	}
 }
\ No newline at end of file
diff --git a/src/test/java/org/olat/selenium/page/portfolio/PortfolioPage.java b/src/test/java/org/olat/selenium/page/portfolio/PortfolioPage.java
index a3e904081ef..ed25236610d 100644
--- a/src/test/java/org/olat/selenium/page/portfolio/PortfolioPage.java
+++ b/src/test/java/org/olat/selenium/page/portfolio/PortfolioPage.java
@@ -51,7 +51,7 @@ public class PortfolioPage {
 		WebElement myMapsLink = browser.findElement(myMapsBy);
 		Assert.assertTrue(myMapsLink.isDisplayed());
 		myMapsLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -64,7 +64,7 @@ public class PortfolioPage {
 		WebElement myMapsLink = browser.findElement(myMapsBy);
 		Assert.assertTrue(myMapsLink.isDisplayed());
 		myMapsLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -75,10 +75,10 @@ public class PortfolioPage {
 	 */
 	public ArtefactWizardPage createTextArtefact() {
 		By addTextArtefactBy = By.className("o_sel_add_text_artfeact");
-		OOGraphene.waitElement(addTextArtefactBy);
+		OOGraphene.waitElement(addTextArtefactBy, browser);
 		WebElement addTextArtefactLink = browser.findElement(addTextArtefactBy);
 		addTextArtefactLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		return ArtefactWizardPage.getWizard(browser);
 	}
@@ -89,20 +89,20 @@ public class PortfolioPage {
 	 */
 	public ArtefactWizardPage createLearningJournal() {
 		By addJournalArtefactBy = By.className("o_sel_add_liveblog_artfeact");
-		OOGraphene.waitElement(addJournalArtefactBy);
+		OOGraphene.waitElement(addJournalArtefactBy, browser);
 		WebElement addJournalArtefactLink = browser.findElement(addJournalArtefactBy);
 		addJournalArtefactLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		return ArtefactWizardPage.getWizard(browser);
 	}
 	
 	public ArtefactWizardPage createFileArtefact() {
 		By addJournalArtefactBy = By.className("o_sel_add_upload_artfeact");
-		OOGraphene.waitElement(addJournalArtefactBy);
+		OOGraphene.waitElement(addJournalArtefactBy, browser);
 		WebElement addJournalArtefactLink = browser.findElement(addJournalArtefactBy);
 		addJournalArtefactLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		return ArtefactWizardPage.getWizard(browser);
 	}
@@ -116,7 +116,7 @@ public class PortfolioPage {
 		By linkArtefactBy = By.cssSelector("a.o_eportfolio_add_link.o_eportfolio_link");
 		WebElement linkArtefactLink = browser.findElement(linkArtefactBy);
 		linkArtefactLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -128,7 +128,7 @@ public class PortfolioPage {
 		By addAsArtefactBy = By.className("o_sel_add_artfeact");
 		WebElement addAsArtefactButton = browser.findElement(addAsArtefactBy);
 		addAsArtefactButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -147,11 +147,11 @@ public class PortfolioPage {
 		
 		//create default map
 		By createDefaultMapBy = By.className("o_sel_create_default_map");
-		OOGraphene.waitElement(createDefaultMapBy);
+		OOGraphene.waitElement(createDefaultMapBy, browser);
 		WebElement createDefaultMapLink = browser.findElement(createDefaultMapBy);
 		Assert.assertTrue(createDefaultMapLink.isDisplayed());
 		createDefaultMapLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		//title
 		By titleBy = By.xpath("//div[contains(@class,'o_sel_add_map_window')]//form//input[@type='text']");
@@ -166,7 +166,7 @@ public class PortfolioPage {
 		WebElement saveButton = browser.findElement(saveBy);
 		Assert.assertTrue(saveButton.isDisplayed());
 		saveButton.click();
-		OOGraphene.waitElement(By.className("o_eportfolio_map"));
+		OOGraphene.waitElement(By.className("o_eportfolio_map"), browser);
 		return this;
 	}
 	
@@ -183,7 +183,7 @@ public class PortfolioPage {
 			WebElement editorButton = browser.findElement(editorBy);
 			Assert.assertTrue(editorButton.isDisplayed());
 			editorButton.click();
-			OOGraphene.waitBusy();
+			OOGraphene.waitBusy(browser);
 		}
 		return this;
 	}
@@ -199,7 +199,7 @@ public class PortfolioPage {
 		}
 		By editTemplateBy = By.className("o_sel_ep_edit_map");
 		browser.findElement(editTemplateBy).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -211,7 +211,7 @@ public class PortfolioPage {
 		By toolsMenuCaretBy = By.cssSelector("a.o_sel_repository_tools");
 		browser.findElement(toolsMenuCaretBy).click();
 		By toolsMenuBy = By.cssSelector("ul.o_sel_repository_tools");
-		OOGraphene.waitElement(toolsMenuBy);
+		OOGraphene.waitElement(toolsMenuBy, browser);
 		return this;
 	}
 	
@@ -231,7 +231,7 @@ public class PortfolioPage {
 		Assert.assertNotNull(mapEl);
 		WebElement openLink = mapEl.findElement(openBy);
 		openLink.click();
-		OOGraphene.waitBusy();	
+		OOGraphene.waitBusy(browser);	
 		return this;
 	}
 	
@@ -253,7 +253,7 @@ public class PortfolioPage {
 		}
 		Assert.assertNotNull(selectedNode);
 		selectedNode.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -268,7 +268,7 @@ public class PortfolioPage {
 		}
 		Assert.assertNotNull(selectedStructLink);
 		selectedStructLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -283,7 +283,7 @@ public class PortfolioPage {
 		List<WebElement> level2Nodes = browser.findElements(pageNodeBy);
 		Assert.assertFalse(level2Nodes.isEmpty());
 		level2Nodes.get(0).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -324,7 +324,7 @@ public class PortfolioPage {
 		By newStructureBy = By.cssSelector("div.o_ep_toc_editor a.o_eportfolio_add_link.o_ep_struct_icon");
 		WebElement newStructureButton = browser.findElement(newStructureBy);
 		newStructureButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		//fill the form
 		return fillElementForm(title, description);
@@ -350,7 +350,7 @@ public class PortfolioPage {
 		By saveBy = By.cssSelector("form div.o_ep_struct_editor button.btn-primary");
 		WebElement saveButton = browser.findElement(saveBy);
 		saveButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 }
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI12Page.java b/src/test/java/org/olat/selenium/page/qti/QTI12Page.java
index 6c8b9a5db4b..0f8cb96e8ca 100644
--- a/src/test/java/org/olat/selenium/page/qti/QTI12Page.java
+++ b/src/test/java/org/olat/selenium/page/qti/QTI12Page.java
@@ -1,9 +1,29 @@
+/**
+ * <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.qti;
 
 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.Alert;
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebDriver;
@@ -31,11 +51,40 @@ public class QTI12Page {
 		return new QTI12Page(browser);
 	}
 	
+	public QTI12Page passE4(UserVO user) {
+		start()
+			.selectItem(0)
+			.answerSingleChoice(0)
+			.saveAnswer()
+			.selectItem(1)
+			.answerMultipleChoice(0, 2)
+			.saveAnswer()
+			.selectItem(2)
+			.answerKPrim(true, false, true, false)
+			.saveAnswer()
+			.selectItem(3)
+			.answerFillin("not")
+			.saveAnswer()
+			.endTest();
+		
+		//check results page
+		By resultsBy = By.id("o_qti_results");
+		OOGraphene.waitElement(resultsBy, browser);
+		WebElement resultsEl = browser.findElement(resultsBy);
+		Assert.assertTrue(resultsEl.getText().contains(user.getFirstName()));
+		//close the test
+		closeTest();
+		//all answers are correct -> passed
+		WebElement passedEl = browser.findElement(By.cssSelector("tr.o_state.o_passed"));
+		Assert.assertTrue(passedEl.isDisplayed());
+		return this;
+	}
+	
 	public QTI12Page start() {
 		By startBy = By.cssSelector("a.o_sel_start_qti12_test");
 		WebElement startButton = browser.findElement(startBy);
 		startButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -45,7 +94,7 @@ public class QTI12Page {
 		Assert.assertTrue(itemList.size() > position);
 		WebElement itemEl = itemList.get(position);
 		itemEl.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -55,7 +104,7 @@ public class QTI12Page {
 		Assert.assertTrue(optionList.size() > selectPosition);
 		WebElement optionEl = optionList.get(selectPosition);
 		optionEl.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -66,7 +115,7 @@ public class QTI12Page {
 			Assert.assertTrue(optionList.size() > selectPosition);
 			optionList.get(selectPosition).click();
 		}
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -83,7 +132,7 @@ public class QTI12Page {
 				optionFalseEl.click();
 			}
 		}
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -94,7 +143,7 @@ public class QTI12Page {
 		for(int i=0; i<texts.length; i++) {
 			holesList.get(i).sendKeys(texts[i]);
 		}
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -102,7 +151,7 @@ public class QTI12Page {
 		By saveAnswerBy = By.name("olat_fosm");
 		WebElement saveAnswerButton = browser.findElement(saveAnswerBy);
 		saveAnswerButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -121,7 +170,7 @@ public class QTI12Page {
 		By endBy = By.cssSelector("div.o_button_group.o_button_group_right a");
 		WebElement endButton = browser.findElement(endBy);
 		endButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 }
diff --git a/src/test/java/org/olat/selenium/page/repository/AuthoringEnvPage.java b/src/test/java/org/olat/selenium/page/repository/AuthoringEnvPage.java
index 60d040c58dc..e013b43d8b3 100644
--- a/src/test/java/org/olat/selenium/page/repository/AuthoringEnvPage.java
+++ b/src/test/java/org/olat/selenium/page/repository/AuthoringEnvPage.java
@@ -29,7 +29,6 @@ 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.FindBy;
 
 /**
  * Page to control the author environnment.
@@ -45,15 +44,12 @@ public class AuthoringEnvPage {
 	public static final By displayNameInput = By.cssSelector("div.o_sel_author_displayname input");
 	public static final By createSubmit = By.className("o_sel_author_create_submit");
 	public static final By createWizard = By.className("o_sel_author_create_wizard");
+	public static final By createMenuCaretBy = By.cssSelector("a.o_sel_author_create");
+	public static final By createMenuBy = By.cssSelector("ul.o_sel_author_create");
 	
 	@Drone
 	private WebDriver browser;
 	
-	@FindBy(css="a.o_sel_author_create")
-	private WebElement createMenuCaret;
-	@FindBy(css="ul.o_sel_author_create")
-	private WebElement createMenu;
-	
 	public RepositoryEditDescriptionPage createCP(String title) {
 		return openCreateDropDown()
 			.clickCreate(ResourceType.cp)
@@ -80,9 +76,11 @@ public class AuthoringEnvPage {
 	 * @return
 	 */
 	public AuthoringEnvPage openCreateDropDown() {
+		WebElement createMenuCaret = browser.findElement(createMenuCaretBy);
+		
 		Assert.assertTrue(createMenuCaret.isDisplayed());
 		createMenuCaret.click();
-		OOGraphene.waitElement(createMenu);
+		OOGraphene.waitElement(createMenuBy, browser);
 		return this;
 	}
 
@@ -92,11 +90,12 @@ public class AuthoringEnvPage {
 	 * @return
 	 */
 	public AuthoringEnvPage clickCreate(ResourceType type) {
+		WebElement createMenu = browser.findElement(createMenuBy);
 		Assert.assertTrue(createMenu.isDisplayed());
 		WebElement createLink = createMenu.findElement(By.className("o_sel_author_create-" + type.type()));
 		Assert.assertTrue(createLink.isDisplayed());
 		createLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -111,8 +110,8 @@ public class AuthoringEnvPage {
 		input.sendKeys(displayName);
 		WebElement submit = modal.findElement(createSubmit);
 		submit.click();
-		OOGraphene.waitBusy();
-		OOGraphene.waitElement(RepositoryEditDescriptionPage.generaltabBy);
+		OOGraphene.waitBusy(browser);
+		OOGraphene.waitElement(RepositoryEditDescriptionPage.generaltabBy, browser);
 		
 		WebElement main = browser.findElement(By.id("o_main_wrapper"));
 		return Graphene.createPageFragment(RepositoryEditDescriptionPage.class, main);
@@ -128,7 +127,7 @@ public class AuthoringEnvPage {
 		WebElement input = modal.findElement(displayNameInput);
 		input.sendKeys(displayName);
 		modal.findElement(createWizard).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		return CourseWizardPage.getWizard(browser);
 	}
@@ -152,11 +151,11 @@ public class AuthoringEnvPage {
 		WebElement importLink = browser.findElement(By.className("o_sel_author_import"));
 		Assert.assertTrue(importLink.isDisplayed());
 		importLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		By inputBy = By.cssSelector(".o_fileinput input[type='file']");
 		OOGraphene.uploadFile(inputBy, resource, browser);
-		OOGraphene.waitElement(By.className("o_sel_author_imported_name"));
+		OOGraphene.waitElement(By.className("o_sel_author_imported_name"), browser);
 		
 		By titleBy = By.cssSelector(".o_sel_author_imported_name input");
 		WebElement titleEl = browser.findElement(titleBy);
@@ -166,7 +165,7 @@ public class AuthoringEnvPage {
 		By saveBy = By.cssSelector("div.o_sel_repo_save_details button.btn-primary");
 		WebElement saveButton = browser.findElement(saveBy);
 		saveButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 
 		return this;
 	}
diff --git a/src/test/java/org/olat/selenium/page/repository/CatalogAdminPage.java b/src/test/java/org/olat/selenium/page/repository/CatalogAdminPage.java
index 869bf20d73d..bd1f79c0ddd 100644
--- a/src/test/java/org/olat/selenium/page/repository/CatalogAdminPage.java
+++ b/src/test/java/org/olat/selenium/page/repository/CatalogAdminPage.java
@@ -64,7 +64,7 @@ public class CatalogAdminPage {
 		
 		//fill the form
 		By titleBy = By.cssSelector(".o_sel_catalog_add_category_popup input[type='text']");
-		OOGraphene.waitElement(titleBy);
+		OOGraphene.waitElement(titleBy, browser);
 		WebElement titleEl = browser.findElement(titleBy);
 		titleEl.sendKeys(title);
 		
@@ -74,7 +74,7 @@ public class CatalogAdminPage {
 		By saveBy = By.cssSelector(".o_sel_catalog_add_category_popup .o_sel_catalog_entry_form_buttons button.btn-primary");
 		WebElement saveButton = browser.findElement(saveBy);
 		saveButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -95,7 +95,7 @@ public class CatalogAdminPage {
 		}
 		Assert.assertNotNull(selectedNode);
 		selectedNode.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 }
\ No newline at end of file
diff --git a/src/test/java/org/olat/selenium/page/repository/FeedPage.java b/src/test/java/org/olat/selenium/page/repository/FeedPage.java
index d8026bef258..a0a110c79e9 100644
--- a/src/test/java/org/olat/selenium/page/repository/FeedPage.java
+++ b/src/test/java/org/olat/selenium/page/repository/FeedPage.java
@@ -50,7 +50,7 @@ public class FeedPage {
 	
 	
 	public static FeedPage getFeedPage(WebDriver browser) {
-		OOGraphene.waitElement(feedBy);
+		OOGraphene.waitElement(feedBy, browser);
 		return new FeedPage(browser);
 	}
 	
@@ -97,7 +97,7 @@ public class FeedPage {
 	
 	private FeedPage newExternalFeed(By configureExternalButton, String url) {
 		browser.findElement(configureExternalButton).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		//fill the URL input field
 		By urlField = By.xpath("(//div[contains(@class,'modal-body')]//form//input[@type='text'])[2]");
 		WebElement urlEl = browser.findElement(urlField);
@@ -109,7 +109,7 @@ public class FeedPage {
 		//save the settings
 		By saveButton = By.xpath("//div[contains(@class,'modal-body')]//form//button[contains(@class,'btn-primary')]");
 		browser.findElement(saveButton).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -117,14 +117,14 @@ public class FeedPage {
 		//click the button to create a feed
 		By feedButton = By.xpath("//div[contains(@class,'o_blog_no_posts')]//a[contains(@href,'feed.make.internal')]");
 		browser.findElement(feedButton).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
 	public FeedPage addPost() {
 		By newItemButton = By.className("o_sel_feed_item_new");
 		browser.findElement(newItemButton).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -142,7 +142,7 @@ public class FeedPage {
 	public FeedPage publishPost() {
 		By publishButton = By.cssSelector(".o_sel_blog_form button.btn-primary");
 		browser.findElement(publishButton).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -154,7 +154,7 @@ public class FeedPage {
 		By addAsArtefactBy = By.className("o_eportfolio_add");
 		WebElement addAsArtefactButton = browser.findElement(addAsArtefactBy);
 		addAsArtefactButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return ArtefactWizardPage.getWizard(browser);
 	}
 	
@@ -167,7 +167,7 @@ public class FeedPage {
 		List<WebElement> monthLinks = browser.findElements(monthBy);
 		Assert.assertFalse(monthLinks.isEmpty());
 		monthLinks.get(0).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 }
\ No newline at end of file
diff --git a/src/test/java/org/olat/selenium/page/repository/RepositoryDetailsPage.java b/src/test/java/org/olat/selenium/page/repository/RepositoryDetailsPage.java
index c7eb8fb1b28..92f683c2161 100644
--- a/src/test/java/org/olat/selenium/page/repository/RepositoryDetailsPage.java
+++ b/src/test/java/org/olat/selenium/page/repository/RepositoryDetailsPage.java
@@ -58,13 +58,13 @@ public class RepositoryDetailsPage {
 	
 	public void launch() {
 		browser.findElement(launchBy).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 	}
 	
 	public void edit() {
 		browser.findElement(editBy).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.closeBlueMessageWindow(browser);
 	}
 
diff --git a/src/test/java/org/olat/selenium/page/repository/RepositoryEditDescriptionPage.java b/src/test/java/org/olat/selenium/page/repository/RepositoryEditDescriptionPage.java
index 31e23890d5b..da9646e8c68 100644
--- a/src/test/java/org/olat/selenium/page/repository/RepositoryEditDescriptionPage.java
+++ b/src/test/java/org/olat/selenium/page/repository/RepositoryEditDescriptionPage.java
@@ -59,7 +59,7 @@ public class RepositoryEditDescriptionPage {
 	
 	public void clickToolbarBack() {
 		browser.findElement(NavigationPage.toolbarBackBy).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		WebElement main = browser.findElement(By.id("o_main_wrapper"));
 		Assert.assertTrue(main.isDisplayed());
diff --git a/src/test/java/org/olat/selenium/page/user/PortalPage.java b/src/test/java/org/olat/selenium/page/user/PortalPage.java
index 097fb6f90a2..16de31375b3 100644
--- a/src/test/java/org/olat/selenium/page/user/PortalPage.java
+++ b/src/test/java/org/olat/selenium/page/user/PortalPage.java
@@ -57,7 +57,7 @@ public class PortalPage {
 		By editBy = By.cssSelector(".o_home_portaleditlink a.btn-default");
 		WebElement editButton = browser.findElement(editBy);
 		editButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -65,7 +65,7 @@ public class PortalPage {
 		By editBy = By.cssSelector(".o_home_portaleditlink a.btn-primary");
 		WebElement editButton = browser.findElement(editBy);
 		editButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -113,7 +113,7 @@ public class PortalPage {
 		List<WebElement> buttons = panel.findElements(action);
 		Assert.assertEquals(1, buttons.size());
 		buttons.get(0).click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 }
diff --git a/src/test/java/org/olat/selenium/page/user/UserPasswordPage.java b/src/test/java/org/olat/selenium/page/user/UserPasswordPage.java
index 4bfb2618244..e0d2b86bd75 100644
--- a/src/test/java/org/olat/selenium/page/user/UserPasswordPage.java
+++ b/src/test/java/org/olat/selenium/page/user/UserPasswordPage.java
@@ -42,7 +42,7 @@ public class UserPasswordPage {
 	private WebDriver browser;
 	
 	public static UserPasswordPage getUserPasswordPage(WebDriver browser) {
-		OOGraphene.waitElement(oldPasswordBy);
+		OOGraphene.waitElement(oldPasswordBy, browser);
 		WebElement main = browser.findElement(By.id("o_main"));
 		return Graphene.createPageFragment(UserPasswordPage.class, main);
 	}
@@ -62,7 +62,7 @@ public class UserPasswordPage {
 		By saveButtonBy = By.cssSelector("div.form-inline.o_sel_home_pwd_buttons button");
 		WebElement saveButton = browser.findElement(saveButtonBy);
 		saveButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		OOGraphene.waitAndCloseBlueMessageWindow(browser);
 		return this;
 	}
diff --git a/src/test/java/org/olat/selenium/page/user/UserPreferencesPageFragment.java b/src/test/java/org/olat/selenium/page/user/UserPreferencesPageFragment.java
index 890063f0ec5..ba223bf285f 100644
--- a/src/test/java/org/olat/selenium/page/user/UserPreferencesPageFragment.java
+++ b/src/test/java/org/olat/selenium/page/user/UserPreferencesPageFragment.java
@@ -93,7 +93,7 @@ public class UserPreferencesPageFragment {
 		
 		WebElement saveButton = browser.findElement(saveSystemSettingsButton);
 		saveButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -104,7 +104,7 @@ public class UserPreferencesPageFragment {
 		
 		WebElement saveButton = browser.findElement(saveSystemPrefsButton);
 		saveButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return this;
 	}
 	
@@ -119,7 +119,7 @@ public class UserPreferencesPageFragment {
 		
 		WebElement saveButton = browser.findElement(resetPrefsButton);
 		saveButton.click();
-		OOGraphene.waitElement(LoginPage.loginFormBy);
+		OOGraphene.waitElement(LoginPage.loginFormBy, browser);
 		return this;
 	}
 	
diff --git a/src/test/java/org/olat/selenium/page/user/UserSettingsPage.java b/src/test/java/org/olat/selenium/page/user/UserSettingsPage.java
index 211ac71e645..d7be3340f81 100644
--- a/src/test/java/org/olat/selenium/page/user/UserSettingsPage.java
+++ b/src/test/java/org/olat/selenium/page/user/UserSettingsPage.java
@@ -26,7 +26,6 @@ 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.FindBy;
 
 /**
  * 
@@ -39,23 +38,21 @@ public class UserSettingsPage {
 	@Drone
 	private WebDriver browser;
 	
-	@FindBy(className = "o_segments")
-	private WebElement segmentView;
+	public UserSettingsPage() {
+		//
+	}
 	
-	@FindBy(className = "o_sel_user_settings_prefs")
-	private WebElement preferencesSegmentLink;
-	@FindBy(className = "o_sel_user_settings_webdav")
-	private WebElement webdavSegmentLink;
-	@FindBy(className = "o_sel_user_settings_im")
-	private WebElement imSegmentLink;
-	@FindBy(className = "o_sel_user_settings_disclaimer")
-	private WebElement disclaimerSegmentLink;
+	public UserSettingsPage(WebDriver browser) {
+		this.browser = browser;
+	}
 
 	/**
 	 * Check that the user settings is displayed.
 	 * @return
 	 */
 	public UserSettingsPage assertOnUserSettings() {
+		By segementViewBy = By.className("o_segments");
+		WebElement segmentView = browser.findElement(segementViewBy);
 		Assert.assertTrue(segmentView.isDisplayed());
 		return this;
 	}
@@ -65,8 +62,10 @@ public class UserSettingsPage {
 	 * @return
 	 */
 	public UserPreferencesPageFragment openPreferences() {
+		By preferencesSegmentBy = By.className("o_sel_user_settings_prefs");
+		WebElement preferencesSegmentLink = browser.findElement(preferencesSegmentBy);
 		preferencesSegmentLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 
 		WebElement main = browser.findElement(By.id("o_main"));
 		return Graphene.createPageFragment(UserPreferencesPageFragment.class, main);
diff --git a/src/test/java/org/olat/selenium/page/user/UserToolsPage.java b/src/test/java/org/olat/selenium/page/user/UserToolsPage.java
index baadc1c31e0..b3d64babdf1 100644
--- a/src/test/java/org/olat/selenium/page/user/UserToolsPage.java
+++ b/src/test/java/org/olat/selenium/page/user/UserToolsPage.java
@@ -23,7 +23,6 @@ import java.util.List;
 
 import org.jboss.arquillian.drone.api.annotation.Drone;
 import org.jboss.arquillian.graphene.Graphene;
-import org.jboss.arquillian.graphene.page.Page;
 import org.junit.Assert;
 import org.olat.selenium.page.LoginPage;
 import org.olat.selenium.page.graphene.OOGraphene;
@@ -44,9 +43,14 @@ public class UserToolsPage {
 
 	@Drone
 	private WebDriver browser;
-
-	@Page
-	private UserSettingsPage userSettings;
+	
+	public UserToolsPage() {
+		//
+	}
+	
+	public UserToolsPage(WebDriver browser) {
+		this.browser = browser;
+	}
 	
 	/**
 	 * Check if the user menu is displayed.
@@ -75,8 +79,8 @@ public class UserToolsPage {
 			WebElement toolbarCaretLink = toolbarCaretLinks.get(0);
 			Assert.assertNotNull(toolbarCaretLink);
 			toolbarCaretLink.click();
-			OOGraphene.waitingTransition();
-			OOGraphene.waitElement(mySettingsClassName);
+			OOGraphene.waitingTransition(browser);
+			OOGraphene.waitElement(mySettingsClassName, browser);
 		}
 		assertOnUserTools();
 		return this;
@@ -91,16 +95,16 @@ public class UserToolsPage {
 		WebElement mySettingsLink = browser.findElement(mySettingsClassName);
 		Assert.assertTrue(mySettingsLink.isDisplayed());
 		mySettingsLink.click();
-		OOGraphene.waitBusy();
-		return userSettings;
+		OOGraphene.waitBusy(browser);
+		return new UserSettingsPage(browser);
 	}
 	
 	public UserSettingsPage openPassword() {
 		WebElement passwordLink = browser.findElement(By.className("o_sel_user_tools-mypassword"));
 		Assert.assertTrue(passwordLink.isDisplayed());
 		passwordLink.click();
-		OOGraphene.waitBusy();
-		return userSettings;
+		OOGraphene.waitBusy(browser);
+		return new UserSettingsPage(browser);
 	}
 	
 	public PortfolioPage openPortfolio() {
@@ -108,7 +112,7 @@ public class UserToolsPage {
 		WebElement passwordLink = browser.findElement(linkBy);
 		Assert.assertTrue(passwordLink.isDisplayed());
 		passwordLink.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		WebElement main = browser.findElement(By.id("o_main"));
 		return Graphene.createPageFragment(PortfolioPage.class, main);
@@ -124,6 +128,6 @@ public class UserToolsPage {
 		By logoutBy = By.className("o_logout");
 		WebElement logoutLink = browser.findElement(logoutBy);
 		Graphene.guardHttp(logoutLink).click();
-		OOGraphene.waitElement(LoginPage.loginFormBy);
+		OOGraphene.waitElement(LoginPage.loginFormBy, browser);
 	}
 }
\ No newline at end of file
diff --git a/src/test/java/org/olat/selenium/page/wiki/WikiPage.java b/src/test/java/org/olat/selenium/page/wiki/WikiPage.java
index 165fce4cbd1..008e4ff5dd2 100644
--- a/src/test/java/org/olat/selenium/page/wiki/WikiPage.java
+++ b/src/test/java/org/olat/selenium/page/wiki/WikiPage.java
@@ -54,14 +54,14 @@ public class WikiPage {
 		
 		//fill the name of the new page
 		By pageNameBy = By.cssSelector("div.o_callout_content form input[type='text']");
-		OOGraphene.waitElement(pageNameBy);
+		OOGraphene.waitElement(pageNameBy, browser);
 		WebElement pageNameEl = browser.findElement(pageNameBy);
 		pageNameEl.sendKeys(name);
 		//search for it
 		By searchBy = By.cssSelector("div.popover-content form .o_sel_wiki_search button");
 		WebElement searchButton = browser.findElement(searchBy);
 		searchButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		//not exist -> click the link to create the page
 		By notExistingBy = By.xpath("//div[contains(@class,'o_wikimod-article-box')]//a[@title='" + name + "']");
@@ -70,14 +70,14 @@ public class WikiPage {
 		
 		//fill the form
 		By textBy = By.cssSelector("div.o_wikimod_editform_wrapper form textarea");
-		OOGraphene.waitElement(textBy);
+		OOGraphene.waitElement(textBy, browser);
 		WebElement textEl = browser.findElement(textBy);
 		textEl.sendKeys(content);
 		//save the page
 		By saveAndCloseBy = By.className("o_sel_wiki_save_and_close");
 		WebElement saveAndCloseButton = browser.findElement(saveAndCloseBy);
 		saveAndCloseButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		
 		//assert
 		By pageTitleBy = By.className("o_wikimod_heading");
@@ -99,7 +99,7 @@ public class WikiPage {
 		By addAsArtefactBy = By.className("o_eportfolio_add");
 		WebElement addAsArtefactButton = browser.findElement(addAsArtefactBy);
 		addAsArtefactButton.click();
-		OOGraphene.waitBusy();
+		OOGraphene.waitBusy(browser);
 		return ArtefactWizardPage.getWizard(browser);
 	}
 
-- 
GitLab