From d5ee1c41fa13723afcc3a5d888d5d8536eee1e57 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Wed, 3 May 2017 20:45:57 +0200
Subject: [PATCH] no-jira: start selenium tests for QTI 2.1 editor

---
 .../AssessmentItemEditorController.java       |  2 +
 .../AssessmentItemRefEditorController.java    |  1 +
 .../interactions/ChoiceScoreController.java   |  1 +
 .../interactions/DrawingEditorController.java |  1 +
 .../interactions/EssayEditorController.java   |  1 +
 .../interactions/FIBEditorController.java     |  1 +
 .../interactions/HotspotEditorController.java |  1 +
 .../interactions/HottextEditorController.java |  1 +
 .../interactions/KPrimEditorController.java   |  1 +
 .../interactions/MatchEditorController.java   |  1 +
 .../MultipleChoiceEditorController.java       |  1 +
 .../SingleChoiceEditorController.java         |  2 +
 .../interactions/UploadEditorController.java  |  1 +
 .../interactions/_content/simple_choices.html |  4 +-
 .../java/org/olat/selenium/ImsQTI21Test.java  | 48 ++++++++++++
 .../qti/QTI21AssessmentItemEditorPage.java    | 64 +++++++++++++++
 .../page/qti/QTI21ChoicesScoreEditorPage.java | 38 +++++++++
 .../selenium/page/qti/QTI21EditorPage.java    | 21 +++++
 .../qti/QTI21MultipleChoiceEditorPage.java    | 36 +++++++++
 .../org/olat/selenium/page/qti/QTI21Page.java |  4 +-
 .../page/qti/QTI21SingleChoiceEditorPage.java | 77 +++++++++++++++++++
 21 files changed, 304 insertions(+), 3 deletions(-)
 create mode 100644 src/test/java/org/olat/selenium/page/qti/QTI21AssessmentItemEditorPage.java
 create mode 100644 src/test/java/org/olat/selenium/page/qti/QTI21ChoicesScoreEditorPage.java
 create mode 100644 src/test/java/org/olat/selenium/page/qti/QTI21MultipleChoiceEditorPage.java
 create mode 100644 src/test/java/org/olat/selenium/page/qti/QTI21SingleChoiceEditorPage.java

diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java
index 2f7eb71329f..fd162e0392d 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java
@@ -127,6 +127,7 @@ public class AssessmentItemEditorController extends BasicController {
 			mainVC = createVelocityContainer("assessment_item_editor");
 			mainVC.contextPut("restrictedEdit", restrictedEdit);
 			tabbedPane = new TabbedPane("itemTabs", getLocale());
+			tabbedPane.setElementCssClass("o_sel_assessment_item_config");
 			tabbedPane.addListener(this);
 			mainVC.put("tabbedpane", tabbedPane);
 	
@@ -166,6 +167,7 @@ public class AssessmentItemEditorController extends BasicController {
 			mainVC = createVelocityContainer("assessment_item_editor");
 			mainVC.contextPut("restrictedEdit", restrictedEdit);
 			tabbedPane = new TabbedPane("itemTabs", getLocale());
+			tabbedPane.setElementCssClass("o_sel_assessment_item_config");
 			tabbedPane.addListener(this);
 			mainVC.put("tabbedpane", tabbedPane);
 	
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/AssessmentItemRefEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/AssessmentItemRefEditorController.java
index 177c8d3e529..10d4fbc9c21 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/AssessmentItemRefEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/AssessmentItemRefEditorController.java
@@ -58,6 +58,7 @@ public abstract class AssessmentItemRefEditorController extends FormBasicControl
 
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		formLayout.setElementCssClass("o_sel_assessment_item_options");
 		if(assessmentItemRef == null) return;
 		
 		Integer maxAttempts = null;
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/ChoiceScoreController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/ChoiceScoreController.java
index ec557e064ed..fb9b1d43e1e 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/ChoiceScoreController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/ChoiceScoreController.java
@@ -95,6 +95,7 @@ public class ChoiceScoreController extends AssessmentItemRefEditorController imp
 		ScoreBuilder maxScore = itemBuilder.getMaxScoreBuilder();
 		String maxValue = maxScore == null ? "" : (maxScore.getScore() == null ? "" : maxScore.getScore().toString());
 		maxScoreEl = uifactory.addTextElement("max.score", "max.score", 8, maxValue, formLayout);
+		maxScoreEl.setElementCssClass("o_sel_assessment_item_max_score");
 		maxScoreEl.setEnabled(!restrictedEdit);
 		
 		String[] modeValues = new String[]{
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/DrawingEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/DrawingEditorController.java
index 05f0d469622..32fc08457fa 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/DrawingEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/DrawingEditorController.java
@@ -103,6 +103,7 @@ public class DrawingEditorController extends FormBasicController {
 		setFormContextHelp("Test editor QTI 2.1 in detail#details_testeditor_fragetypen_drawing");
 		
 		titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), formLayout);
+		titleEl.setElementCssClass("o_sel_assessment_item_title");
 		titleEl.setMandatory(true);
 		
 		String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/EssayEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/EssayEditorController.java
index 931426962b2..55e8f4dc8f0 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/EssayEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/EssayEditorController.java
@@ -74,6 +74,7 @@ public class EssayEditorController extends FormBasicController {
 		setFormContextHelp("Test editor QTI 2.1 in detail#details_testeditor_fragetypen_freetext");
 		
 		titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), formLayout);
+		titleEl.setElementCssClass("o_sel_assessment_item_title");
 		titleEl.setMandatory(true);
 		
 		String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/FIBEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/FIBEditorController.java
index 94fe09aaee5..8be0c78c466 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/FIBEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/FIBEditorController.java
@@ -90,6 +90,7 @@ public class FIBEditorController extends FormBasicController {
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), formLayout);
+		titleEl.setElementCssClass("o_sel_assessment_item_title");
 		titleEl.setMandatory(true);
 		
 		String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HotspotEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HotspotEditorController.java
index a444608e5ad..dfd7cca3274 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HotspotEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HotspotEditorController.java
@@ -126,6 +126,7 @@ public class HotspotEditorController extends FormBasicController {
 		setFormContextHelp("Test editor QTI 2.1 in detail#details_testeditor_fragetypen_hotspot");
 		
 		titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), formLayout);
+		titleEl.setElementCssClass("o_sel_assessment_item_title");
 		titleEl.setMandatory(true);
 		
 		String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HottextEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HottextEditorController.java
index 0844ae4c532..cd0d1651978 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HottextEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HottextEditorController.java
@@ -79,6 +79,7 @@ public class HottextEditorController extends FormBasicController {
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		setFormContextHelp("Test editor QTI 2.1 in detail#details_testeditor_fragetypen_hot");
 		titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), formLayout);
+		titleEl.setElementCssClass("o_sel_assessment_item_title");
 		titleEl.setMandatory(true);
 		
 		String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/KPrimEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/KPrimEditorController.java
index f972dbb0612..c35cbc73cbd 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/KPrimEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/KPrimEditorController.java
@@ -95,6 +95,7 @@ public class KPrimEditorController extends FormBasicController {
 		formLayout.add("metadata", metadata);
 		
 		titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata);
+		titleEl.setElementCssClass("o_sel_assessment_item_title");
 		titleEl.setMandatory(true);
 
 		String description = itemBuilder.getQuestion();
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/MatchEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/MatchEditorController.java
index 677027b9e9e..3d09ec0b36d 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/MatchEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/MatchEditorController.java
@@ -100,6 +100,7 @@ public class MatchEditorController extends FormBasicController {
 		formLayout.add("metadata", metadata);
 		
 		titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata);
+		titleEl.setElementCssClass("o_sel_assessment_item_title");
 		titleEl.setMandatory(true);
 
 		String description = itemBuilder.getQuestion();
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/MultipleChoiceEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/MultipleChoiceEditorController.java
index 2954cf194d4..f7b0d8dee4c 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/MultipleChoiceEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/MultipleChoiceEditorController.java
@@ -100,6 +100,7 @@ public class MultipleChoiceEditorController extends FormBasicController {
 		formLayout.add("metadata", metadata);
 
 		titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata);
+		titleEl.setElementCssClass("o_sel_assessment_item_title");
 		titleEl.setMandatory(true);
 		
 		String description = itemBuilder.getQuestion();
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/SingleChoiceEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/SingleChoiceEditorController.java
index e558c32bb10..0679b526a19 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/SingleChoiceEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/SingleChoiceEditorController.java
@@ -97,6 +97,7 @@ public class SingleChoiceEditorController extends FormBasicController {
 		formLayout.add("metadata", metadata);
 
 		titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata);
+		titleEl.setElementCssClass("o_sel_assessment_item_title");
 		titleEl.setMandatory(true);
 
 		String description = itemBuilder.getQuestion();
@@ -154,6 +155,7 @@ public class SingleChoiceEditorController extends FormBasicController {
 		// Submit Button
 		FormLayoutContainer buttonsContainer = FormLayoutContainer.createDefaultFormLayout_2_10("buttons", getTranslator());
 		buttonsContainer.setRootForm(mainForm);
+		buttonsContainer.setElementCssClass("o_sel_choices_save");
 		formLayout.add(buttonsContainer);
 		formLayout.add("buttons", buttonsContainer);
 		uifactory.addFormSubmitButton("submit", buttonsContainer);
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/UploadEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/UploadEditorController.java
index b94385647ec..abe0cd12ac6 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/UploadEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/UploadEditorController.java
@@ -71,6 +71,7 @@ public class UploadEditorController extends FormBasicController {
 		setFormContextHelp("Test editor QTI 2.1 in detail#details_testeditor_fragetypen_fileupload");
 		
 		titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), formLayout);
+		titleEl.setElementCssClass("o_sel_qti_title");
 		titleEl.setMandatory(true);
 		
 		String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/_content/simple_choices.html b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/_content/simple_choices.html
index 38961fd6dc5..975341a7eb2 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/_content/simple_choices.html
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/_content/simple_choices.html
@@ -5,13 +5,13 @@
 </div>
 
 #foreach($choice in $choices)
-<div class="form-group #if($f.hasError($item)) has-feedback has-error #end clearfix">
+<div class="form-group #if($f.hasError($item)) has-feedback has-error #end clearfix o_sel_choice_${foreach.index}">
 	<div class="col-sm-1">
 		#if($r.available(${choice.getRemove().getComponent().getComponentName()}) && $r.visible(${choice.getRemove().getComponent().getComponentName()}))
 			<div>$r.render(${choice.getRemove().getComponent().getComponentName()})</div>
 		#end
 		#if($r.available(${choice.getAdd().getComponent().getComponentName()}) && $r.visible(${choice.getAdd().getComponent().getComponentName()}))
-			<div>$r.render(${choice.getAdd().getComponent().getComponentName()})</div>
+			<div class="o_sel_add_choice_${foreach.count}">$r.render(${choice.getAdd().getComponent().getComponentName()})</div>
 		#end
 		#if($r.available(${choice.getUp().getComponent().getComponentName()}) && $r.visible(${choice.getUp().getComponent().getComponentName()}))
 			<div>$r.render(${choice.getUp().getComponent().getComponentName()})</div>
diff --git a/src/test/java/org/olat/selenium/ImsQTI21Test.java b/src/test/java/org/olat/selenium/ImsQTI21Test.java
index 6028018d580..d891ae21664 100644
--- a/src/test/java/org/olat/selenium/ImsQTI21Test.java
+++ b/src/test/java/org/olat/selenium/ImsQTI21Test.java
@@ -42,9 +42,11 @@ import org.olat.selenium.page.NavigationPage;
 import org.olat.selenium.page.User;
 import org.olat.selenium.page.course.CourseEditorPageFragment;
 import org.olat.selenium.page.course.CoursePageFragment;
+import org.olat.selenium.page.qti.QTI21ChoicesScoreEditorPage;
 import org.olat.selenium.page.qti.QTI21ConfigurationCEPage;
 import org.olat.selenium.page.qti.QTI21EditorPage;
 import org.olat.selenium.page.qti.QTI21Page;
+import org.olat.selenium.page.qti.QTI21SingleChoiceEditorPage;
 import org.olat.selenium.page.repository.RepositoryAccessPage.UserAccess;
 import org.olat.selenium.page.user.UserToolsPage;
 import org.olat.test.ArquillianDeployments;
@@ -927,4 +929,50 @@ public class ImsQTI21Test {
 			.assertOnCourseAssessmentTestScore(4)
 			.assertOnCourseAttempts(1);
 	}
+	
+	/**
+	 * Test different settings in the single choice editor.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void choicesEditor(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Choices QTI 2.1 " + UUID.randomUUID();
+		navBar
+			.openAuthoringEnvironment()
+			.createQTI21Test(qtiTestTitle)
+			.clickToolbarBack();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		QTI21EditorPage qtiEditor = qtiPage
+				.edit();
+		//start a blank test
+		qtiEditor
+			.selectNode("Single choice")
+			.deleteNode();
+		//add a single choice
+		QTI21SingleChoiceEditorPage scEditor = qtiEditor
+			.addSingleChoice();
+		scEditor
+			.setAnswer(0, "Wrong answer")
+			.addChoice(1)
+			.setCorrect(1)
+			.setAnswer(1, "Correct answer")
+			.addChoice(2)
+			.setAnswer(2, "Pas la bonne")
+			.addChoice(3)
+			.setAnswer(3, "Nicht richtig")
+			.save();
+		QTI21ChoicesScoreEditorPage scScoreEditor = scEditor
+			.selectScores();
+	}
 }
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21AssessmentItemEditorPage.java b/src/test/java/org/olat/selenium/page/qti/QTI21AssessmentItemEditorPage.java
new file mode 100644
index 00000000000..cdaa50c59c9
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21AssessmentItemEditorPage.java
@@ -0,0 +1,64 @@
+/**
+ * <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.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+/**
+ * 
+ * Initial date: 03 may 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public abstract class QTI21AssessmentItemEditorPage {
+	
+	public static final By tabBarBy = By.cssSelector("ul.o_sel_assessment_item_config>li>a");
+	
+	protected final WebDriver browser;
+	
+	protected QTI21AssessmentItemEditorPage(WebDriver browser) {
+		this.browser = browser;
+	}
+	
+	protected QTI21AssessmentItemEditorPage selectTab(By tabBy) {
+		List<WebElement> tabLinks = browser.findElements(tabBarBy);
+
+		boolean found = false;
+		a_a:
+		for(WebElement tabLink:tabLinks) {
+			tabLink.click();
+			OOGraphene.waitBusy(browser);
+			List<WebElement> tabEls = browser.findElements(tabBy);
+			if(tabEls.size() > 0) {
+				found = true;
+				break a_a;
+			}
+		}
+
+		Assert.assertTrue("Found the tab", found);
+		return this;
+	}
+}
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21ChoicesScoreEditorPage.java b/src/test/java/org/olat/selenium/page/qti/QTI21ChoicesScoreEditorPage.java
new file mode 100644
index 00000000000..a095ae4764c
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21ChoicesScoreEditorPage.java
@@ -0,0 +1,38 @@
+/**
+ * <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 org.openqa.selenium.WebDriver;
+
+/**
+ * 
+ * Initial date: 3 mai 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class QTI21ChoicesScoreEditorPage {
+	
+	private final WebDriver browser;
+	
+	public QTI21ChoicesScoreEditorPage(WebDriver browser) {
+		this.browser = browser;
+	}
+
+}
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21EditorPage.java b/src/test/java/org/olat/selenium/page/qti/QTI21EditorPage.java
index dce4a95ee56..438bf39c0d5 100644
--- a/src/test/java/org/olat/selenium/page/qti/QTI21EditorPage.java
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21EditorPage.java
@@ -19,6 +19,7 @@
  */
 package org.olat.selenium.page.qti;
 
+import org.olat.ims.qti21.model.QTI21QuestionType;
 import org.olat.selenium.page.core.MenuTreePageFragment;
 import org.olat.selenium.page.graphene.OOGraphene;
 import org.openqa.selenium.By;
@@ -82,6 +83,26 @@ public class QTI21EditorPage {
 		return this;
 	}
 	
+	public QTI21SingleChoiceEditorPage addSingleChoice() {
+		addQuestion(QTI21QuestionType.sc);
+		return new QTI21SingleChoiceEditorPage(browser);
+	}
+	
+	public QTI21MultipleChoiceEditorPage addMultipleChoice() {
+		addQuestion(QTI21QuestionType.mc);
+		return new QTI21MultipleChoiceEditorPage(browser);
+	}
+	
+	private QTI21EditorPage addQuestion(QTI21QuestionType type) {
+		openElementsMenu();
+		
+		By addBy = By.xpath("//ul[contains(@class,'o_sel_qti_elements')]//a[contains(@onclick,'new.')][i[contains(@class,'" + type.getCssClass() + "')]]");
+		browser.findElement(addBy).click();
+		OOGraphene.waitBusy(browser);
+		OOGraphene.waitElement(By.className("o_sel_assessment_item_title"), browser);
+		return this;
+	}
+	
 	public QTI21EditorPage openChangeMenu() {
 		By changeMenuCaret = By.cssSelector("a.o_sel_qti_change_node");
 		browser.findElement(changeMenuCaret).click();
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21MultipleChoiceEditorPage.java b/src/test/java/org/olat/selenium/page/qti/QTI21MultipleChoiceEditorPage.java
new file mode 100644
index 00000000000..77ea198c1cf
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21MultipleChoiceEditorPage.java
@@ -0,0 +1,36 @@
+/**
+ * <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 org.openqa.selenium.WebDriver;
+
+/**
+ * 
+ * Initial date: 03 may 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class QTI21MultipleChoiceEditorPage extends QTI21AssessmentItemEditorPage {
+	
+	public QTI21MultipleChoiceEditorPage(WebDriver browser) {
+		super(browser);
+	}
+
+}
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21Page.java b/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
index 35705df9128..0c23be3f3f6 100644
--- a/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
@@ -47,7 +47,9 @@ public class QTI21Page {
 	}
 	
 	public static QTI21Page getQTI12Page(WebDriver browser) {
-		WebElement main = browser.findElement(By.id("o_main_wrapper"));
+		By mainBy = By.id("o_main_wrapper");
+		OOGraphene.waitElement(mainBy, 5, browser);
+		WebElement main = browser.findElement(mainBy);
 		Assert.assertTrue(main.isDisplayed());
 		return new QTI21Page(browser);
 	}
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21SingleChoiceEditorPage.java b/src/test/java/org/olat/selenium/page/qti/QTI21SingleChoiceEditorPage.java
new file mode 100644
index 00000000000..4dc34383f75
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21SingleChoiceEditorPage.java
@@ -0,0 +1,77 @@
+/**
+ * <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 org.olat.selenium.page.graphene.OOGraphene;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+
+/**
+ * 
+ * Initial date: 03 may 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class QTI21SingleChoiceEditorPage extends QTI21AssessmentItemEditorPage {
+
+	public QTI21SingleChoiceEditorPage(WebDriver browser) {
+		super(browser);
+	}
+	
+	/**
+	 * Add a new choice.
+	 * 
+	 * @return Itself
+	 */
+	public QTI21SingleChoiceEditorPage addChoice(int position) {
+		By addBy = By.xpath("//div[contains(@class,'o_sel_add_choice_" + position + "')]/a");
+		browser.findElement(addBy).click();
+		OOGraphene.waitBusy(browser);
+		//wait the next element
+		By addedBy = By.xpath("//div[contains(@class,'o_sel_add_choice_" + (position + 1) + "')]/a");
+		OOGraphene.waitElement(addedBy, 5, browser);
+		return this;
+	}
+	
+	public QTI21SingleChoiceEditorPage setCorrect(int position) {
+		By correctBy = By.xpath("//div[contains(@class,'o_sel_choice_" + position + "')]//input[contains(@id,'oo_correct-')]");
+		browser.findElement(correctBy).click();
+		return this;
+	}
+	
+	public QTI21SingleChoiceEditorPage setAnswer(int position, String answer) {
+		String containerCssSelector = "div.o_sel_choice_" + position;
+		OOGraphene.tinymce(answer, containerCssSelector, browser);
+		return this;
+	}
+	
+	public QTI21SingleChoiceEditorPage save() {
+		By saveBy = By.cssSelector("fieldset.o_sel_choices_save button.btn.btn-primary");
+		browser.findElement(saveBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	public QTI21ChoicesScoreEditorPage selectScores() {
+		selectTab(By.className("o_sel_assessment_item_options"));
+		return new QTI21ChoicesScoreEditorPage(browser);
+	}
+
+}
-- 
GitLab