From 80ca8138dcd2edab9cf39452096ce19575b9f0ad Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Tue, 22 Aug 2017 09:04:41 +0200
Subject: [PATCH] no-jira: selenium test for lti without grading for the moment

---
 .../course/nodes/basiclti/LTIConfigForm.java  |  7 ++
 .../java/org/olat/selenium/CourseTest.java    | 92 +++++++++++++++++++
 .../page/course/LTIConfigurationPage.java     | 66 +++++++++++++
 .../olat/selenium/page/course/LTIPage.java    | 74 +++++++++++++++
 4 files changed, 239 insertions(+)
 create mode 100644 src/test/java/org/olat/selenium/page/course/LTIConfigurationPage.java
 create mode 100644 src/test/java/org/olat/selenium/page/course/LTIPage.java

diff --git a/src/main/java/org/olat/course/nodes/basiclti/LTIConfigForm.java b/src/main/java/org/olat/course/nodes/basiclti/LTIConfigForm.java
index 4924c2f4dbf..4b2c6894e9f 100644
--- a/src/main/java/org/olat/course/nodes/basiclti/LTIConfigForm.java
+++ b/src/main/java/org/olat/course/nodes/basiclti/LTIConfigForm.java
@@ -246,17 +246,21 @@ public class LTIConfigForm extends FormBasicController {
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		setFormTitle("form.title");
 		setFormContextHelp("Other#_lti_config");
+		formLayout.setElementCssClass("o_sel_lti_config_form");
 
 		thost = uifactory.addTextElement("host", "LTConfigForm.url", 255, fullURI, formLayout);
+		thost.setElementCssClass("o_sel_lti_config_title");
 		thost.setExampleKey("LTConfigForm.url.example", null);
 		thost.setDisplaySize(64);
 		thost.setMandatory(true);
 		
 		tkey  = uifactory.addTextElement ("key","LTConfigForm.key", 255, key, formLayout);
+		tkey.setElementCssClass("o_sel_lti_config_key");
 		tkey.setExampleKey ("LTConfigForm.key.example", null);
 		tkey.setMandatory(true);
 		
 		tpass = uifactory.addTextElement ("pass","LTConfigForm.pass", 255, pass, formLayout);
+		tpass.setElementCssClass("o_sel_lti_config_pass");
 		tpass.setExampleKey("LTConfigForm.pass.example", null);
 		tpass.setMandatory(true);
 
@@ -315,6 +319,7 @@ public class LTIConfigForm extends FormBasicController {
 		String[] assessableKeys = new String[]{ "on" };
 		String[] assessableValues = new String[]{ "" };
 		isAssessableEl = uifactory.addCheckboxesHorizontal("isassessable", "assessable.label", formLayout, assessableKeys, assessableValues);
+		isAssessableEl.setElementCssClass("o_sel_lti_config_assessable");
 		isAssessableEl.addActionListener(FormEvent.ONCHANGE);
 		if(isAssessable) {
 			isAssessableEl.select("on", true);
@@ -323,12 +328,14 @@ public class LTIConfigForm extends FormBasicController {
 		Float scaleValue = config.getFloatEntry(BasicLTICourseNode.CONFIG_KEY_SCALEVALUE);
 		String scaleFactor = scaleValue == null ? "1.0" : scaleValue.toString();
 		scaleFactorEl = uifactory.addTextElement("scale", "scaleFactor", 10, scaleFactor, formLayout);
+		scaleFactorEl.setElementCssClass("o_sel_lti_config_scale");
 		scaleFactorEl.setDisplaySize(3);
 		scaleFactorEl.setVisible(isAssessable);
 		
 		Float cutValue = config.getFloatEntry(BasicLTICourseNode.CONFIG_KEY_PASSED_CUT_VALUE);
 		String cut = cutValue == null ? "" : cutValue.toString();
 		cutValueEl = uifactory.addTextElement("cutvalue", "cutvalue.label", 10, cut, formLayout);
+		cutValueEl.setElementCssClass("o_sel_lti_config_cutval");
 		cutValueEl.setDisplaySize(3);
 		cutValueEl.setVisible(isAssessable);
 		
diff --git a/src/test/java/org/olat/selenium/CourseTest.java b/src/test/java/org/olat/selenium/CourseTest.java
index 40d46a5a16c..aab91a5afcd 100644
--- a/src/test/java/org/olat/selenium/CourseTest.java
+++ b/src/test/java/org/olat/selenium/CourseTest.java
@@ -62,6 +62,8 @@ import org.olat.selenium.page.course.DialogConfigurationPage;
 import org.olat.selenium.page.course.DialogPage;
 import org.olat.selenium.page.course.ForumCEPage;
 import org.olat.selenium.page.course.InfoMessageCEPage;
+import org.olat.selenium.page.course.LTIConfigurationPage;
+import org.olat.selenium.page.course.LTIPage;
 import org.olat.selenium.page.course.MemberListConfigurationPage;
 import org.olat.selenium.page.course.MemberListPage;
 import org.olat.selenium.page.course.MembersPage;
@@ -1028,6 +1030,96 @@ public class CourseTest {
 			.assertOnBlogPost(post2Title);
 	}
 	
+
+	/**
+	 * An author setup a course with a LTI course element with score enabled.
+	 * A participant take the course and see the LTI content. The back channel
+	 * need the url of the OpenOLAT instance which is currently difficult
+	 * for a selenium test. The grading is not tested until a LTI server
+	 * can be installed on localhost.
+	 * 
+	 * @param authorLoginPage
+	 * @param participantBrowser
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void createCourseWithLTI(@InitialPage LoginPage authorLoginPage,
+			@Drone @User WebDriver participantBrowser)
+	throws IOException, URISyntaxException {
+		
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		UserVO participant = new UserRestClient(deploymentUrl).createRandomUser("Ryomou");
+		
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//create a course
+		String courseTitle = "Course-LTI-" + UUID.randomUUID();
+		navBar
+			.openAuthoringEnvironment()
+			.createCourse(courseTitle)
+			.clickToolbarBack();
+
+		//create a course element of type Test with the test that we create above
+		String ltiTitle = "LTI";
+		CourseEditorPageFragment courseEditor = CoursePageFragment.getCourse(browser)
+			.edit()
+			.createNode("lti")
+			.nodeTitle(ltiTitle);
+		
+		//configure assessment
+		LTIConfigurationPage ltiConfig = new LTIConfigurationPage(browser);
+		ltiConfig
+			.selectConfiguration()
+			.setLtiPage("http://lti.frentix.com/tool.php", "123456", "secret")
+			.enableScore(10.0d, 5.0d)
+			.save();
+		//set the score / passed calculation in root node and publish
+		courseEditor
+			.selectRoot()
+			.selectTabScore()
+			.enableRootScoreByNodes()
+			.autoPublish()
+			.accessConfiguration()
+			.setUserAccess(UserAccess.registred);
+		
+		//go to members management
+		CoursePageFragment courseRuntime = courseEditor.clickToolbarBack();
+		MembersPage members = courseRuntime
+			.members();
+		members
+			.addMember()
+			.searchMember(participant, true)
+			.nextUsers()
+			.nextOverview()
+			.nextPermissions()
+			.finish();
+		
+		//Participant login
+		LoginPage participantLoginPage = LoginPage.getLoginPage(participantBrowser, deploymentUrl);
+		participantLoginPage
+			.loginAs(participant.getLogin(), participant.getPassword())
+			.resume();
+
+		NavigationPage participantNavBar = new NavigationPage(participantBrowser);
+		participantNavBar
+			.openMyCourses()
+			.openSearch()
+			.extendedSearch(courseTitle)
+			.select(courseTitle);
+		
+		CoursePageFragment participantCourse = new CoursePageFragment(participantBrowser);
+		participantCourse
+			.clickTree()
+			.selectWithTitle(ltiTitle);
+		LTIPage lti = new LTIPage(participantBrowser);
+		lti
+			.start()
+			.outcomeToolProvider();
+			//.sendGrade(0.8d);
+	}
+	
 	/**
 	 * 
 	 * Create a catalog, create a course, while publishing add the
diff --git a/src/test/java/org/olat/selenium/page/course/LTIConfigurationPage.java b/src/test/java/org/olat/selenium/page/course/LTIConfigurationPage.java
new file mode 100644
index 00000000000..557a54e4508
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/course/LTIConfigurationPage.java
@@ -0,0 +1,66 @@
+package org.olat.selenium.page.course;
+
+import org.olat.selenium.page.graphene.OOGraphene;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+/**
+ * 
+ * Initial date: 21 août 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class LTIConfigurationPage {
+	
+	private final WebDriver browser;
+	
+	public LTIConfigurationPage(WebDriver browser) {
+		this.browser = browser;
+	}
+	
+	public LTIConfigurationPage selectConfiguration() {
+		By configBy = By.cssSelector("fieldset.o_sel_lti_config_form");
+		OOGraphene.selectTab(CourseEditorPageFragment.navBarNodeConfiguration, configBy, browser);
+		return this;
+	}
+	
+	public LTIConfigurationPage setLtiPage(String url, String key, String password) {
+		By urlBy = By.cssSelector("div.o_sel_lti_config_title input[type=text]");
+		browser.findElement(urlBy).sendKeys(url);
+		
+		By keyBy = By.cssSelector("div.o_sel_lti_config_key input[type=text]");
+		browser.findElement(keyBy).sendKeys(key);
+		
+		By passwordBy = By.cssSelector("div.o_sel_lti_config_pass input[type=text]");
+		browser.findElement(passwordBy).sendKeys(password);
+		
+		return this;
+	}
+	
+	public LTIConfigurationPage enableScore(double scale, double cutValue) {
+		By assessableBy = By.xpath("//div[contains(@class,'o_sel_lti_config_assessable')]//input[@type='checkbox']");
+		By assessableLabelBy = By.xpath("//div[contains(@class,'o_sel_lti_config_assessable')]//label[input[@type='checkbox']]");
+		WebElement assessableEl = browser.findElement(assessableBy);
+		WebElement assessableLabelEl = browser.findElement(assessableLabelBy);
+		OOGraphene.check(assessableLabelEl, assessableEl, Boolean.TRUE);
+		
+		By scaleBy = By.cssSelector("div.o_sel_lti_config_scale input[type=text]");
+		OOGraphene.waitElement(scaleBy, browser);
+		WebElement scaleEl = browser.findElement(scaleBy);
+		scaleEl.clear();
+		scaleEl.sendKeys(Double.toString(scale));
+		
+		By cutValueBy = By.cssSelector("div.o_sel_lti_config_cutval input[type=text]");
+		browser.findElement(cutValueBy).sendKeys(Double.toString(cutValue));
+		return this;
+	}
+	
+	public LTIConfigurationPage save() {
+		By saveBy = By.cssSelector("fieldset.o_sel_lti_config_form button.btn-primary");
+		browser.findElement(saveBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+
+}
diff --git a/src/test/java/org/olat/selenium/page/course/LTIPage.java b/src/test/java/org/olat/selenium/page/course/LTIPage.java
new file mode 100644
index 00000000000..e9be9a5ae02
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/course/LTIPage.java
@@ -0,0 +1,74 @@
+package org.olat.selenium.page.course;
+
+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;
+
+/**
+ * Attention! The browser instance is dependent of the location. Jump
+ * to the iframe need a jump back to OpenOLAT.
+ * 
+ * 
+ * Initial date: 21 août 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class LTIPage {
+	
+	private WebDriver browser;
+	
+	public LTIPage(WebDriver browser) {
+		this.browser = browser;
+	}
+	
+	public LTIPage start() {
+		By startBy = By.xpath("//div[contains(@class,'o_button_group')]/a[contains(@onclick,'start')]");
+		OOGraphene.waitElement(startBy, browser);
+		browser.findElement(startBy).click();
+		
+		By iframeBy = By.cssSelector(".o_iframedisplay iframe");
+		OOGraphene.waitElement(iframeBy, browser);
+		
+		List<WebElement> iframes = browser.findElements(iframeBy);
+		browser = browser.switchTo().frame(iframes.get(0));
+		
+		By launchedBy = By.xpath("//p[contains(text(),'Launch Validated.')]");
+		OOGraphene.waitElement(launchedBy, browser);
+		
+		return this;
+	}
+	
+	public LTIPage outcomeToolProvider() {
+		By outcomeToolLinkBy = By.xpath("//a[contains(@href,'tool_provider_outcome.php')]");
+		OOGraphene.waitElement(outcomeToolLinkBy, browser);
+		browser.findElement(outcomeToolLinkBy).click();
+		return this;
+	}
+	
+	public LTIPage sendGrade(double grade) {
+		By gradeBy = By.cssSelector("input[type=text][name=grade]");
+		OOGraphene.waitElement(gradeBy, browser);
+		browser.findElement(gradeBy).sendKeys(Double.toString(grade));
+		
+		By sendGradeBy = By.cssSelector("input[type=submit][value='Send Grade']");
+		browser.findElement(sendGradeBy).click();
+		
+		By preBy = By.tagName("pre");
+		OOGraphene.waitElement(preBy, browser);
+		List<WebElement> preEls = browser.findElements(preBy);
+		boolean success = true;
+		for(WebElement preEl:preEls) {
+			String text = preEl.getText();
+			if(text.contains("<imsx_codeMajor>success</imsx_codeMajor>")) {
+				success |= true;
+			}
+		}
+		Assert.assertTrue(success);
+		return this;
+	}
+
+}
-- 
GitLab