From db0185f89e8e7e12189755e35ed63c400bea53b2 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Fri, 6 Mar 2015 21:32:41 +0100
Subject: [PATCH] OO-349: selenium test for certificate generated automatically
 after a test

---
 ...icateAndEfficiencyStatementController.java |  2 +
 .../st/EditScoreCalculationEasyForm.java      |  2 +
 .../course/nodes/st/_content/scoreedit.html   |  2 +-
 .../org/olat/selenium/AssessmentTest.java     | 98 +++++++++++++++++++
 .../page/course/CourseEditorPageFragment.java | 76 ++++++++++++++
 .../page/user/EfficiencyStatementPage.java    | 91 +++++++++++++++++
 .../olat/test/rest/RepositoryRestClient.java  | 38 +++++++
 .../org/olat/test/rest/UserRestClient.java    |  2 -
 8 files changed, 308 insertions(+), 3 deletions(-)

diff --git a/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementController.java b/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementController.java
index 784f7425cc6..262bfe2feb6 100644
--- a/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementController.java
+++ b/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementController.java
@@ -171,10 +171,12 @@ public class CertificateAndEfficiencyStatementController extends BasicController
 		if(efficiencyStatement != null && certificate != null) {
 			segmentView = SegmentViewFactory.createSegmentView("segments", mainVC, this);
 			certificateLink = LinkFactory.createLink("details.certificate", mainVC, this);
+			certificateLink.setElementCssClass("o_select_certificate_segement");
 			segmentView.addSegment(certificateLink, true);
 			selectCertificate(ureq);
 			
 			courseDetailsLink = LinkFactory.createLink("details.course.infos", mainVC, this);
+			courseDetailsLink.setElementCssClass("o_select_statement_segment");
 			segmentView.addSegment(courseDetailsLink, false);
 		} else if(efficiencyStatement != null) {
 			selectCourseInfos(ureq);
diff --git a/src/main/java/org/olat/course/nodes/st/EditScoreCalculationEasyForm.java b/src/main/java/org/olat/course/nodes/st/EditScoreCalculationEasyForm.java
index 1aa81717dc9..f1c2ba2f506 100644
--- a/src/main/java/org/olat/course/nodes/st/EditScoreCalculationEasyForm.java
+++ b/src/main/java/org/olat/course/nodes/st/EditScoreCalculationEasyForm.java
@@ -284,6 +284,7 @@ public class EditScoreCalculationEasyForm extends FormBasicController {
 		hasScore = uifactory.addCheckboxesHorizontal("scform.hasScore", formLayout, new String[]{"xx"}, new String[]{null});
 		hasScore.select("xx", sc != null && sc.getSumOfScoreNodes() != null && sc.getSumOfScoreNodes().size() > 0);
 		hasScore.addActionListener(FormEvent.ONCLICK); // Radios/Checkboxes need onclick because of IE bug OLAT-5753
+		hasScore.setElementCssClass("o_sel_has_score");
 		
 		scoreNodeIdents = initNodeSelectionElement(
 				formLayout, "scform.scoreNodeIndents", sc, (sc == null ? null : sc.getSumOfScoreNodes()), nodeIdentList
@@ -295,6 +296,7 @@ public class EditScoreCalculationEasyForm extends FormBasicController {
 		hasPassed = uifactory.addCheckboxesHorizontal("scform.passedtype", formLayout, new String[]{"xx"}, new String[]{null});
 		hasPassed.select("xx", sc != null && sc.getPassedType() != null && !sc.getPassedType().equals(ScoreCalculator.PASSED_TYPE_NONE));
 		hasPassed.addActionListener(FormEvent.ONCLICK); // Radios/Checkboxes need onclick because of IE bug OLAT-5753
+		hasPassed.setElementCssClass("o_sel_has_passed");
 		
 		String[] passedTypeKeys = new String[] {
 				ScoreCalculator.PASSED_TYPE_CUTVALUE,
diff --git a/src/main/java/org/olat/course/nodes/st/_content/scoreedit.html b/src/main/java/org/olat/course/nodes/st/_content/scoreedit.html
index 76d154c1cad..491953832d6 100644
--- a/src/main/java/org/olat/course/nodes/st/_content/scoreedit.html
+++ b/src/main/java/org/olat/course/nodes/st/_content/scoreedit.html
@@ -1,4 +1,4 @@
-<fieldset>
+<fieldset class="o_sel_structure_score">
 	<legend>$r.contextHelpWithWrapper("org.olat.course.nodes.st","ced-st-score.html","help.st")
 	$r.translate("score.fieldset.title")</legend>
 	
diff --git a/src/test/java/org/olat/selenium/AssessmentTest.java b/src/test/java/org/olat/selenium/AssessmentTest.java
index 7e574aeb721..402525721a5 100644
--- a/src/test/java/org/olat/selenium/AssessmentTest.java
+++ b/src/test/java/org/olat/selenium/AssessmentTest.java
@@ -57,6 +57,7 @@ import org.olat.selenium.page.repository.RepositoryAccessPage.UserAccess;
 import org.olat.selenium.page.user.UserToolsPage;
 import org.olat.test.ArquillianDeployments;
 import org.olat.test.JunitTestHelper;
+import org.olat.test.rest.RepositoryRestClient;
 import org.olat.test.rest.UserRestClient;
 import org.olat.user.restapi.UserVO;
 import org.openqa.selenium.By;
@@ -656,5 +657,102 @@ public class AssessmentTest {
 			.assertOnEfficiencyStatmentPage()
 			.assertOnCertificate(courseTitle);
 	}
+	
+	/**
+	 * An author create a course, set up the root node to make efficiency statement,
+	 * add a test, publish it and add a participant. It set the certificate.<br>
+	 * 
+	 * The participant logs in, make the test and look at its wonderful certificate
+	 * and the details of its performance.
+	 * 
+	 * @param authorLoginPage
+	 * @param reiBrowser
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void certificatesGeneratedByTest(@InitialPage LoginPage authorLoginPage,
+			@Drone @User WebDriver reiBrowser)
+	throws IOException, URISyntaxException {
+		//create an author and a participant
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		UserVO rei = new UserRestClient(deploymentUrl).createRandomUser("Rei");
+		//deploy the test
+		URL testUrl = ArquillianDeployments.class.getResource("file_resources/e4_test.zip");
+		String testTitle = "E4Test-" + UUID.randomUUID();
+		new RepositoryRestClient(deploymentUrl, author).deployResource(new File(testUrl.toURI()), "-", testTitle);
+		
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		//create a course
+		String courseTitle = "Certif-" + 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";
+		CoursePageFragment courseRuntime = CoursePageFragment.getCourse(browser);
+		courseRuntime
+			.edit()
+			.createNode("iqtest")
+			.nodeTitle(testNodeTitle)
+			.selectTabLearnContent()
+			.chooseTest(testTitle)
+			.selectRoot()
+			.selectTabScore()
+			.enableRootScoreByNodes()
+			.autoPublish()
+			.accessConfiguration()
+			.setUserAccess(UserAccess.registred)
+			.clickToolbarBack();
+		
+		//add a participant to the course
+		MembersPage members = courseRuntime
+			.members();
+		members
+			.addMember()
+			.searchMember(rei, true)
+			.next().next().next().finish();
+		// return to course
+		courseRuntime = members
+				.clickToolbarBack()
+				.efficiencyStatementConfiguration()
+				.enableCertificates(true)
+				.enableRecertification()
+				.save()
+				.clickToolbarBack();
+		
+		//Participant log in
+		LoginPage reiLoginPage = LoginPage.getLoginPage(reiBrowser, deploymentUrl);
+		reiLoginPage
+			.loginAs(rei.getLogin(), rei.getPassword())
+			.resume();
+		
+		//open the course
+		NavigationPage reiNavBar = new NavigationPage(reiBrowser);
+		reiNavBar
+			.openMyCourses()
+			.select(courseTitle);
+		
+		//go to the test
+		CoursePageFragment reiTestCourse = new CoursePageFragment(reiBrowser);
+		reiTestCourse
+			.clickTree()
+			.selectWithTitle(testNodeTitle);
+		//pass the test
+		QTI12Page.getQTI12Page(reiBrowser).passE4(rei);
+				
+		//open the efficiency statements
+		UserToolsPage reiUserTools = new UserToolsPage(reiBrowser);
+		reiUserTools
+			.openUserToolsMenu()
+			.openMyEfficiencyStatement()
+			.assertOnEfficiencyStatmentPage()
+			.assertOnCertificateAndStatements(courseTitle)
+			.selectStatement(courseTitle).selectStatementSegment()
+			.assertOnCourseDetails(testNodeTitle, true);
+	}
 
 }
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 ac42ca0ae1f..82ab18128ba 100644
--- a/src/test/java/org/olat/selenium/page/course/CourseEditorPageFragment.java
+++ b/src/test/java/org/olat/selenium/page/course/CourseEditorPageFragment.java
@@ -86,6 +86,82 @@ public class CourseEditorPageFragment {
 		return this;
 	}
 	
+	/**
+	 * Select the root course element.
+	 */
+	public CourseEditorPageFragment selectRoot() {
+		By rootNodeBy = By.cssSelector("span.o_tree_link.o_tree_l0>a");
+		browser.findElement(rootNodeBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	/**
+	 * Select the tab score in a structure node.
+	 * 
+	 */
+	public CourseEditorPageFragment selectTabScore() {
+		By scoreTabBy = By.cssSelector("fieldset.o_sel_structure_score");
+		return selectTab(scoreTabBy);
+	}
+	
+	private CourseEditorPageFragment selectTab(By tabBy) {
+		List<WebElement> tabLinks = browser.findElements(navBarNodeConfiguration);
+
+		boolean found = false;
+		a_a:
+		for(WebElement tabLink:tabLinks) {
+			tabLink.click();
+			OOGraphene.waitBusy(browser);
+			List<WebElement> chooseRepoEntry = browser.findElements(tabBy);
+			if(chooseRepoEntry.size() > 0) {
+				found = true;
+				break a_a;
+			}
+		}
+
+		Assert.assertTrue("Found the tab", found);
+		return this;
+	}
+	
+	/**
+	 * Enable passed and points by nodes
+	 * @return
+	 */
+	public CourseEditorPageFragment enableRootScoreByNodes() {
+		By enablePointBy = By.cssSelector("fieldset.o_sel_structure_score .o_sel_has_score input[type='checkbox']");
+		browser.findElement(enablePointBy).click();
+		OOGraphene.waitBusy(browser); //scform.scoreNodeIndents
+		
+		By enablePointNodesBy = By.cssSelector("fieldset.o_sel_structure_score input[type='checkbox'][name='scform.scoreNodeIndents']");
+		List<WebElement> pointNodeEls = browser.findElements(enablePointNodesBy);
+		for(WebElement pointNodeEl:pointNodeEls) {
+			pointNodeEl.click();
+			OOGraphene.waitBusy(browser);
+		}
+		
+		By enablePassedBy = By.cssSelector("fieldset.o_sel_structure_score .o_sel_has_passed input[type='checkbox']");
+		browser.findElement(enablePassedBy).click();
+		OOGraphene.waitBusy(browser);
+		
+		By passedInheritBy = By.cssSelector("fieldset.o_sel_structure_score input[type='radio'][name='passedType'][value='inherit']");
+		browser.findElement(passedInheritBy).click();
+		OOGraphene.waitBusy(browser);
+		
+		By enablePassedNodesBy = By.cssSelector("fieldset.o_sel_structure_score input[type='checkbox'][name='scform.passedNodeIndents']");
+		List<WebElement> enablePassedNodeEls = browser.findElements(enablePassedNodesBy);
+		for(WebElement enablePassedNodeEl:enablePassedNodeEls) {
+			enablePassedNodeEl.click();
+			OOGraphene.waitBusy(browser);
+		}
+		
+		//save
+		By submitBy = By.cssSelector("fieldset.o_sel_structure_score button.btn.btn-primary");
+		browser.findElement(submitBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
 	/**
 	 * Create a new course element
 	 * @param nodeAlias The type of the course element
diff --git a/src/test/java/org/olat/selenium/page/user/EfficiencyStatementPage.java b/src/test/java/org/olat/selenium/page/user/EfficiencyStatementPage.java
index b20a5a597ea..8a0004db54f 100644
--- a/src/test/java/org/olat/selenium/page/user/EfficiencyStatementPage.java
+++ b/src/test/java/org/olat/selenium/page/user/EfficiencyStatementPage.java
@@ -22,6 +22,7 @@ package org.olat.selenium.page.user;
 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;
@@ -59,5 +60,95 @@ public class EfficiencyStatementPage {
 		Assert.assertFalse(certificateDownloadEls.isEmpty());
 		return this;
 	}
+	
+	/**
+	 * 
+	 * Statement cut the title, be aware of it
+	 * 
+	 * @param courseTitle
+	 * @return
+	 */
+	public EfficiencyStatementPage assertOnCertificateAndStatements(String courseTitle) {
+		WebElement rowToAssert = getStatementRow(courseTitle);
+		boolean found = false;
+		for(int i=0; i<20; i++) {
+			By certificateDownloadBy = By.cssSelector("a i.o_icon.o_filetype_pdf");
+			List<WebElement> certificateDownloadEls = rowToAssert.findElements(certificateDownloadBy);
+			if(certificateDownloadEls.size() > 0) {
+				found = true;
+				break;
+			}
+			OOGraphene.waitingALittleLonger();
+		}
+		Assert.assertTrue(found);
+		return this;
+	}
+	
+	/**
+	 * In the efficiency statement page / course details, check that
+	 * the node is in the table and the node is passe / failed.
+	 * 
+	 * @param testNodeTitle
+	 * @param passed
+	 * @return
+	 */
+	public EfficiencyStatementPage assertOnCourseDetails(String testNodeTitle, boolean passed) {
+		By courseCertificateBy = By.xpath("//div[contains(@class,'o_efficiencystatement')]//table//tr[td[contains(text(),'" + testNodeTitle + "')]]");
+		List<WebElement> certifiatesTable = browser.findElements(courseCertificateBy);
+		Assert.assertFalse(certifiatesTable.isEmpty());
+		
+		By by;
+		if(passed) {
+			by = By.cssSelector("td.text-left span.o_state.o_passed");
+		} else {
+			by = By.cssSelector("td.text-left span.o_state.o_failed");
+		}
+		List<WebElement> passedEl = certifiatesTable.get(0).findElements(by);
+		Assert.assertFalse(passedEl.isEmpty());
+		Assert.assertTrue(passedEl.get(0).isDisplayed());
+		return this;
+	}
+	
+	/**
+	 * On the page with the certificate and the efficiency statement,
+	 * select the efficiency statement tab where there are the course
+	 * details.
+	 * 
+	 * @param courseTitle
+	 * @return
+	 */
+	public EfficiencyStatementPage selectStatement(String courseTitle) {
+		WebElement rowToAssert = getStatementRow(courseTitle);
+		By courseCertificateBy = By.xpath("//td//a[contains(@href,'cmd.show')]");
+		rowToAssert.findElement(courseCertificateBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
+	
+	private WebElement getStatementRow(String courseTitle) {
+		By courseCertificateBy = By.xpath("//div[contains(@class,'o_sel_certificates_table')]//table//tr");
+		
+		WebElement rowToAssert = null;
+		List<WebElement> rowsEl = browser.findElements(courseCertificateBy);
+		a_a:
+		for(WebElement rowEl:rowsEl) {
+			for(WebElement col:rowEl.findElements(By.tagName("td"))) {
+				String text = col.getText();
+				if(courseTitle.contains(text) || text.contains(courseTitle)) {
+					rowToAssert = rowEl;
+					break a_a;
+				}
+			}
+		}
+		
+		Assert.assertNotNull(rowToAssert);
+		return rowToAssert;
+	}
 
+	public EfficiencyStatementPage selectStatementSegment() {
+		By courseDetailsBy = By.className("o_select_statement_segment");
+		browser.findElement(courseDetailsBy).click();
+		OOGraphene.waitBusy(browser);
+		return this;
+	}
 }
diff --git a/src/test/java/org/olat/test/rest/RepositoryRestClient.java b/src/test/java/org/olat/test/rest/RepositoryRestClient.java
index 0a4c2b1f0b1..62283f1a261 100644
--- a/src/test/java/org/olat/test/rest/RepositoryRestClient.java
+++ b/src/test/java/org/olat/test/rest/RepositoryRestClient.java
@@ -35,12 +35,15 @@ import javax.ws.rs.core.UriBuilder;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
 import org.apache.http.entity.ContentType;
 import org.apache.http.entity.mime.HttpMultipartMode;
 import org.apache.http.entity.mime.MultipartEntityBuilder;
 import org.olat.restapi.RestConnection;
 import org.olat.restapi.support.vo.CourseVO;
+import org.olat.restapi.support.vo.RepositoryEntryVO;
 import org.olat.test.ArquillianDeployments;
+import org.olat.user.restapi.UserVO;
 
 /**
  * 
@@ -59,6 +62,12 @@ public class RepositoryRestClient {
 		this(deploymentUrl, "administrator", "openolat");
 	}
 	
+	public RepositoryRestClient(URL deploymentUrl, UserVO author) {
+		this.deploymentUrl = deploymentUrl;
+		this.username = author.getLogin();
+		this.password = author.getPassword();
+	}
+	
 	public RepositoryRestClient(URL deploymentUrl, String username, String password) {
 		this.deploymentUrl = deploymentUrl;
 		this.username = username;
@@ -74,6 +83,35 @@ public class RepositoryRestClient {
 		return deployCourse(archive, "-", displayname);
 	}
 	
+	public RepositoryEntryVO deployResource(File archive, String resourcename, String displayname)
+	throws URISyntaxException, IOException {
+		RestConnection conn = new RestConnection(deploymentUrl);
+		assertTrue(conn.login(username, password));
+		
+		URI request = UriBuilder.fromUri(deploymentUrl.toURI()).path("restapi").path("repo").path("entries").build();
+		HttpPut method = conn.createPut(request, MediaType.APPLICATION_JSON, true);
+		String softKey = UUID.randomUUID().toString();
+		HttpEntity entity = MultipartEntityBuilder.create()
+				.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
+				.addBinaryBody("file", archive, ContentType.APPLICATION_OCTET_STREAM, archive.getName())
+				.addTextBody("filename", archive.getName())
+				.addTextBody("resourcename", resourcename)
+				.addTextBody("displayname", displayname)
+				.addTextBody("access", "3")
+				.addTextBody("softkey", softKey)
+				.build();
+		method.setEntity(entity);
+		
+		HttpResponse response = conn.execute(method);
+		assertTrue(response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201);
+		
+		RepositoryEntryVO vo = conn.parse(response, RepositoryEntryVO.class);
+		assertNotNull(vo);
+		assertNotNull(vo.getDisplayname());
+		assertNotNull(vo.getKey());
+		return vo;
+	}
+	
 	public CourseVO deployCourse(File archive, String resourcename, String displayname)
 	throws URISyntaxException, IOException {
 		
diff --git a/src/test/java/org/olat/test/rest/UserRestClient.java b/src/test/java/org/olat/test/rest/UserRestClient.java
index 547a29cd2ff..6cd270ad104 100644
--- a/src/test/java/org/olat/test/rest/UserRestClient.java
+++ b/src/test/java/org/olat/test/rest/UserRestClient.java
@@ -67,8 +67,6 @@ public class UserRestClient {
 		this.password = password;
 	}
 	
-
-	
 	public UserVO createRandomUser()
 	throws IOException, URISyntaxException {
 		return createRandomUser("Selena");
-- 
GitLab