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