From 74bad92fc0d426cd72e132477d1f40a3a51423ae Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Fri, 12 May 2017 20:06:48 +0200
Subject: [PATCH] no-jira: selenium tests for QTI 2.1 editor, upload with
 specific feedbacks

---
 .../LobFeedbackEditorController.java          | 10 +-
 .../interactions/UploadEditorController.java  |  4 +-
 .../java/org/olat/selenium/ImsQTI21Test.java  | 99 +++++++++++++++++++
 .../selenium/page/qti/QTI21EditorPage.java    |  5 +
 .../selenium/page/qti/QTI21LobEditorPage.java | 60 +++++++++++
 .../page/qti/QTI21LobFeedbacksEditorPage.java | 77 +++++++++++++++
 .../page/qti/QTI21MinimalScoreEditorPage.java | 57 +++++++++++
 .../org/olat/selenium/page/qti/QTI21Page.java | 18 ++++
 8 files changed, 328 insertions(+), 2 deletions(-)
 create mode 100644 src/test/java/org/olat/selenium/page/qti/QTI21LobEditorPage.java
 create mode 100644 src/test/java/org/olat/selenium/page/qti/QTI21LobFeedbacksEditorPage.java
 create mode 100644 src/test/java/org/olat/selenium/page/qti/QTI21MinimalScoreEditorPage.java

diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/LobFeedbackEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/LobFeedbackEditorController.java
index a18235dda08..27800c8e87e 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/LobFeedbackEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/LobFeedbackEditorController.java
@@ -75,7 +75,7 @@ public class LobFeedbackEditorController extends FormBasicController {
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		setFormContextHelp("Test editor QTI 2.1 in detail#details_testeditor_feedback");
-		
+		formLayout.setElementCssClass("o_sel_assessment_item_feedbacks");
 
 		String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
 		VFSContainer itemContainer = (VFSContainer)rootContainer.resolve(relativePath);
@@ -84,11 +84,13 @@ public class LobFeedbackEditorController extends FormBasicController {
 			ModalFeedbackBuilder hint = itemBuilder.getHint();
 			String hintTitle = hint == null ? "" : hint.getTitle();
 			hintTitleEl = uifactory.addTextElement("hintTitle", "form.imd.hint.title", -1, hintTitle, formLayout);
+			hintTitleEl.setElementCssClass("o_sel_assessment_item_hint_title");
 			hintTitleEl.setUserObject(hint);
 			hintTitleEl.setEnabled(!restrictedEdit);
 			String hintText = hint == null ? "" : hint.getText();
 			hintTextEl = uifactory.addRichTextElementForQTI21("hintText", "form.imd.hint.text", hintText, 8, -1,
 					itemContainer, formLayout, ureq.getUserSession(), getWindowControl());
+			hintTextEl.setElementCssClass("o_sel_assessment_item_hint");
 			hintTextEl.setEnabled(!restrictedEdit);
 			hintTextEl.setHelpTextKey("feedback.hint.help", null);
 			hintTextEl.setHelpUrlForManualPage("Test editor QTI 2.1 in detail#details_testeditor_feedback");
@@ -102,12 +104,14 @@ public class LobFeedbackEditorController extends FormBasicController {
 			feedbackCorrectSolutionTitleEl = uifactory.addTextElement("correctSolutionTitle", "form.imd.correct.solution.title", -1, correctSolutionTitle, formLayout);
 			feedbackCorrectSolutionTitleEl.setUserObject(correctSolutionFeedback);
 			feedbackCorrectSolutionTitleEl.setEnabled(!restrictedEdit);
+			feedbackCorrectSolutionTitleEl.setElementCssClass("o_sel_assessment_item_correct_solution_title");
 			String correctSolutionText = correctSolutionFeedback == null ? "" : correctSolutionFeedback.getText();
 			feedbackCorrectSolutionTextEl = uifactory.addRichTextElementForQTI21("correctSolutionText", "form.imd.correct.solution.text.word", correctSolutionText, 8, -1,
 					itemContainer, formLayout, ureq.getUserSession(), getWindowControl());
 			feedbackCorrectSolutionTextEl.setEnabled(!restrictedEdit);
 			feedbackCorrectSolutionTextEl.setHelpTextKey("feedback.correctsolution.help", null);
 			feedbackCorrectSolutionTextEl.setHelpUrlForManualPage("Test editor QTI 2.1 in detail#details_testeditor_feedback");
+			feedbackCorrectSolutionTextEl.setElementCssClass("o_sel_assessment_item_correct_solution");
 			RichTextConfiguration richTextConfig2 = feedbackCorrectSolutionTextEl.getEditorConfiguration();
 			richTextConfig2.setFileBrowserUploadRelPath("media");// set upload dir to the media dir
 		}
@@ -118,10 +122,12 @@ public class LobFeedbackEditorController extends FormBasicController {
 			feedbackTitleEl = uifactory.addTextElement("answeredTitle", "form.imd.answered.title", -1, correctTitle, formLayout);
 			feedbackTitleEl.setUserObject(answeredFeedback);
 			feedbackTitleEl.setEnabled(!restrictedEdit);
+			feedbackTitleEl.setElementCssClass("o_sel_assessment_item_answered_feedback_title");
 			String correctText = answeredFeedback == null ? "" : answeredFeedback.getText();
 			feedbackTextEl = uifactory.addRichTextElementForQTI21("answeredText", "form.imd.answered.text", correctText, 8, -1,
 					itemContainer, formLayout, ureq.getUserSession(), getWindowControl());
 			feedbackTextEl.setEnabled(!restrictedEdit);
+			feedbackTextEl.setElementCssClass("o_sel_assessment_item_answered_feedback");
 			RichTextConfiguration richTextConfig = feedbackTextEl.getEditorConfiguration();
 			richTextConfig.setFileBrowserUploadRelPath("media");// set upload dir to the media dir
 		}
@@ -132,10 +138,12 @@ public class LobFeedbackEditorController extends FormBasicController {
 			feedbackEmptyTitleEl = uifactory.addTextElement("emptyTitle", "form.imd.empty.title", -1, emptyTitle, formLayout);
 			feedbackEmptyTitleEl.setUserObject(emptyFeedback);
 			feedbackEmptyTitleEl.setEnabled(!restrictedEdit);
+			feedbackEmptyTitleEl.setElementCssClass("o_sel_assessment_item_empty_feedback_title");
 			String emptyText = emptyFeedback == null ? "" : emptyFeedback.getText();
 			feedbackEmptyTextEl = uifactory.addRichTextElementForQTI21("emptyText", "form.imd.empty.text", emptyText, 8, -1,
 					itemContainer, formLayout, ureq.getUserSession(), getWindowControl());
 			feedbackEmptyTextEl.setEnabled(!restrictedEdit);
+			feedbackEmptyTextEl.setElementCssClass("o_sel_assessment_item_empty_feedback");
 			RichTextConfiguration emptyTextConfig = feedbackEmptyTextEl.getEditorConfiguration();
 			emptyTextConfig.setFileBrowserUploadRelPath("media");// set upload dir to the media dir
 		}
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 abe0cd12ac6..e3dbfd24311 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,7 +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.setElementCssClass("o_sel_assessment_item_title");
 		titleEl.setMandatory(true);
 		
 		String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
@@ -80,10 +80,12 @@ public class UploadEditorController extends FormBasicController {
 		String description = itemBuilder.getQuestion();
 		textEl = uifactory.addRichTextElementForQTI21("desc", "form.imd.descr", description, 16, -1, itemContainer,
 				formLayout, ureq.getUserSession(), getWindowControl());
+		textEl.setElementCssClass("o_sel_assessment_item_question");
 
 		// Submit Button
 		FormLayoutContainer buttonsContainer = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
 		buttonsContainer.setRootForm(mainForm);
+		buttonsContainer.setElementCssClass("o_sel_upload_save");
 		formLayout.add(buttonsContainer);
 		uifactory.addFormSubmitButton("submit", buttonsContainer);
 	}
diff --git a/src/test/java/org/olat/selenium/ImsQTI21Test.java b/src/test/java/org/olat/selenium/ImsQTI21Test.java
index 1c955a2e428..404ffd3b55c 100644
--- a/src/test/java/org/olat/selenium/ImsQTI21Test.java
+++ b/src/test/java/org/olat/selenium/ImsQTI21Test.java
@@ -46,6 +46,7 @@ import org.olat.selenium.page.course.CoursePageFragment;
 import org.olat.selenium.page.qti.QTI21ConfigurationCEPage;
 import org.olat.selenium.page.qti.QTI21EditorPage;
 import org.olat.selenium.page.qti.QTI21KprimEditorPage;
+import org.olat.selenium.page.qti.QTI21LobEditorPage;
 import org.olat.selenium.page.qti.QTI21MatchEditorPage;
 import org.olat.selenium.page.qti.QTI21MultipleChoiceEditorPage;
 import org.olat.selenium.page.qti.QTI21Page;
@@ -1610,4 +1611,102 @@ public class ImsQTI21Test {
 			.assertOnAssessmentResults()
 			.assertOnAssessmentTestScore(10);// 4 points from the first question, 6 from the second
 	}
+	
+	/**
+	 * An author make a test with 1 upload and feedbacks.<br>
+	 * A user make the test, test hint and upload the file.
+	 * 
+	 * @param authorLoginPage
+	 * @param participantBrowser
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21EditorUpload(@InitialPage LoginPage authorLoginPage,
+			@Drone @User WebDriver participantBrowser)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		UserVO rei = new UserRestClient(deploymentUrl).createRandomUser("Rei");
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//make 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 an upload interaction
+		QTI21LobEditorPage uploadEditor = qtiEditor
+			.addUpload();
+		uploadEditor
+			.setQuestion("Upload a file")
+			.save()
+			.selectScores()
+			.setMaxScore("2.0")
+			.save();
+		uploadEditor
+			.selectFeedbacks()
+			.setHint("Hint", "Need a little help.")
+			.setCorrectSolution("Correct solution", "Only for Word")
+			.setAnsweredFeedback("Full", "You upload something")
+			.setEmpytFeedback("Empty", "You do not upload anything")
+			.save();
+		
+		qtiPage
+			.clickToolbarBack();
+		// access to all
+		qtiPage
+			.accessConfiguration()
+			.setUserAccess(UserAccess.guest)
+			.clickToolbarBack();
+		// show results
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		
+		//a user search the content package
+		LoginPage reiLoginPage = LoginPage.getLoginPage(participantBrowser, deploymentUrl);
+		reiLoginPage
+			.loginAs(rei.getLogin(), rei.getPassword())
+			.resume();
+		NavigationPage reiNavBar = new NavigationPage(participantBrowser);
+		reiNavBar
+			.openMyCourses()
+			.openSearch()
+			.extendedSearch(qtiTestTitle)
+			.select(qtiTestTitle)
+			.start();
+		
+		// make the test
+		QTI21Page reiQtiPage = QTI21Page
+				.getQTI12Page(participantBrowser);
+		reiQtiPage
+			.assertOnAssessmentItem()
+			.saveAnswer()
+			.assertFeedback("Empty")
+			.hint()
+			.assertFeedback("Hint");
+		
+		URL imageUrl = JunitTestHelper.class.getResource("file_resources/IMG_1482.JPG");
+		File imageFile = new File(imageUrl.toURI());
+		reiQtiPage
+			.answerUpload(imageFile)
+			.saveAnswer()
+			.assertFeedback("Full")
+			.endTest()
+			.assertOnAssessmentResults()
+			.assertOnAssessmentResultUpload("IMG_1482");
+	}
 }
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 52327d46044..7b838d3d8f0 100644
--- a/src/test/java/org/olat/selenium/page/qti/QTI21EditorPage.java
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21EditorPage.java
@@ -103,6 +103,11 @@ public class QTI21EditorPage {
 		return new QTI21MatchEditorPage(browser);
 	}
 	
+	public QTI21LobEditorPage addUpload() {
+		addQuestion(QTI21QuestionType.upload);
+		return new QTI21LobEditorPage(browser);
+	}
+	
 	private QTI21EditorPage addQuestion(QTI21QuestionType type) {
 		openElementsMenu();
 		
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21LobEditorPage.java b/src/test/java/org/olat/selenium/page/qti/QTI21LobEditorPage.java
new file mode 100644
index 00000000000..3732c529769
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21LobEditorPage.java
@@ -0,0 +1,60 @@
+/**
+ * <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;
+
+/**
+ * Drive the upload, drawing editor.
+ * 
+ * Initial date: 12 mai 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class QTI21LobEditorPage extends QTI21AssessmentItemEditorPage {
+	
+	public QTI21LobEditorPage(WebDriver browser) {
+		super(browser);
+	}
+	
+	public QTI21LobEditorPage setQuestion(String question) {
+		OOGraphene.tinymce(question, "div.o_sel_assessment_item_question", browser);
+		return this;
+	}
+	
+	public QTI21LobEditorPage save() {
+		By saveBy = By.cssSelector("div.o_sel_upload_save button.btn.btn-primary");
+		browser.findElement(saveBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	public QTI21MinimalScoreEditorPage selectScores() {
+		selectTab(By.className("o_sel_assessment_item_options"));
+		return new QTI21MinimalScoreEditorPage(browser);
+	}
+	
+	public QTI21LobFeedbacksEditorPage selectFeedbacks() {
+		selectTab(By.className("o_sel_assessment_item_feedbacks"));
+		return new QTI21LobFeedbacksEditorPage(browser);
+	}
+}
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21LobFeedbacksEditorPage.java b/src/test/java/org/olat/selenium/page/qti/QTI21LobFeedbacksEditorPage.java
new file mode 100644
index 00000000000..85cdb06111f
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21LobFeedbacksEditorPage.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;
+
+/**
+ * 
+ * Drive the feedbackabck editor with the special empty / answered
+ * feedbacks.
+ * 
+ * Initial date: 12 mai 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class QTI21LobFeedbacksEditorPage {
+	
+	private final WebDriver browser;
+	
+	public QTI21LobFeedbacksEditorPage(WebDriver browser) {
+		this.browser = browser;
+	}
+	
+	public QTI21LobFeedbacksEditorPage setHint(String title, String hint) {
+		By titleBy = By.cssSelector("div.o_sel_assessment_item_hint_title input[type='text']");
+		browser.findElement(titleBy).sendKeys(title);
+		OOGraphene.tinymce(hint, "div.o_sel_assessment_item_hint", browser);
+		return this;
+	}
+	
+	public QTI21LobFeedbacksEditorPage setCorrectSolution(String title, String correctSolution) {
+		By titleBy = By.cssSelector("div.o_sel_assessment_item_correct_solution_title input[type='text']");
+		browser.findElement(titleBy).sendKeys(title);
+		OOGraphene.tinymce(correctSolution, "div.o_sel_assessment_item_correct_solution", browser);
+		return this;
+	}
+	
+	public QTI21LobFeedbacksEditorPage setAnsweredFeedback(String title, String feedback) {
+		By titleBy = By.cssSelector("div.o_sel_assessment_item_answered_feedback_title input[type='text']");
+		browser.findElement(titleBy).sendKeys(title);
+		OOGraphene.tinymce(feedback, "div.o_sel_assessment_item_answered_feedback", browser);
+		return this;
+	}
+	
+	public QTI21LobFeedbacksEditorPage setEmpytFeedback(String title, String feedback) {
+		By titleBy = By.cssSelector("div.o_sel_assessment_item_empty_feedback_title input[type='text']");
+		browser.findElement(titleBy).sendKeys(title);
+		OOGraphene.tinymce(feedback, "div.o_sel_assessment_item_empty_feedback", browser);
+		return this;
+	}
+
+	public QTI21LobFeedbacksEditorPage save() {
+		By saveBy = By.cssSelector("fieldset.o_sel_assessment_item_feedbacks button.btn.btn-primary");
+		browser.findElement(saveBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+}
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21MinimalScoreEditorPage.java b/src/test/java/org/olat/selenium/page/qti/QTI21MinimalScoreEditorPage.java
new file mode 100644
index 00000000000..ae6c960715a
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21MinimalScoreEditorPage.java
@@ -0,0 +1,57 @@
+/**
+ * <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;
+import org.openqa.selenium.WebElement;
+
+/**
+ * Drive the minimal score editor with only the max score.
+ * 
+ * Initial date: 12 mai 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class QTI21MinimalScoreEditorPage {
+
+	private final WebDriver browser;
+	
+	public QTI21MinimalScoreEditorPage(WebDriver browser) {
+		this.browser = browser;
+	}
+	
+	public QTI21MinimalScoreEditorPage setMaxScore(String maxScore) {
+		By maxScoreBy = By.cssSelector("div.o_sel_assessment_item_max_score input[type='text']");
+		WebElement maxScoreEl = browser.findElement(maxScoreBy);
+		maxScoreEl.clear();
+		maxScoreEl.sendKeys(maxScore);
+		return this;
+	}
+	
+	public QTI21MinimalScoreEditorPage save() {
+		By saveBy = By.cssSelector("fieldset.o_sel_assessment_item_options button.btn.btn-primary");
+		browser.findElement(saveBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+
+}
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 a80b149944b..5e03f62c251 100644
--- a/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
@@ -19,6 +19,7 @@
  */
 package org.olat.selenium.page.qti;
 
+import java.io.File;
 import java.util.List;
 
 import org.junit.Assert;
@@ -173,6 +174,12 @@ public class QTI21Page {
 		return this;
 	}
 	
+	public QTI21Page answerUpload(File file) {
+		By inputBy = By.cssSelector(".uploadInteraction input[type='file']");
+		OOGraphene.uploadFile(inputBy, file, browser);
+		return this;
+	}
+	
 	public QTI21Page saveAnswer() {
 		By saveAnswerBy = By.cssSelector("button.o_sel_assessment_item_submit");
 		browser.findElement(saveAnswerBy).click();
@@ -312,6 +319,17 @@ public class QTI21Page {
 		return this;
 	}
 	
+	/**
+	 * 
+	 * @param name The name of the file without extension
+	 * @return Itself
+	 */
+	public QTI21Page assertOnAssessmentResultUpload(String name) {
+		By uploadBy = By.xpath("//div[contains(@class,'o_assessment_test_results')]//div[contains(@class,'uploadInteraction')]/a[contains(@href,'" + name + "')]");
+		OOGraphene.waitElement(uploadBy, 5, browser);
+		return this;
+	}
+	
 	public QTI21Page assertOnAssessmentTestFeedback(String feedback) {
 		By feedbackBy = By.xpath("//div[contains(@class,'o_info')]/h3[contains(text(),'" + feedback + "')]");
 		OOGraphene.waitElement(feedbackBy, 5, browser);
-- 
GitLab