diff --git a/src/main/java/org/olat/repository/ui/author/AuthorListController.java b/src/main/java/org/olat/repository/ui/author/AuthorListController.java index 3ee8d9f2d081f4b41833a47764c0dc654f87f8cd..4b0dd252dbf30273d2793241b1b5e395d54f51ea 100644 --- a/src/main/java/org/olat/repository/ui/author/AuthorListController.java +++ b/src/main/java/org/olat/repository/ui/author/AuthorListController.java @@ -194,6 +194,7 @@ public class AuthorListController extends FormBasicController implements Activat importLink = LinkFactory.createLink("cmd.import.ressource", getTranslator(), this); importLink.setDomReplacementWrapperRequired(false); importLink.setIconLeftCSS("o_icon o_icon_import"); + importLink.setElementCssClass("o_sel_author_import"); stackPanel.addTool(importLink, Align.left); List<OrderedRepositoryHandler> handlers = repositoryHandlerFactory.getOrderRepositoryHandlers(); diff --git a/src/main/java/org/olat/repository/ui/author/ImportRepositoryEntryController.java b/src/main/java/org/olat/repository/ui/author/ImportRepositoryEntryController.java index d9454d951bcefc5dab5c7805527503b1f7bb1ffd..76ff6d1ec62368b81bc85ae97420bab0f93ade34 100644 --- a/src/main/java/org/olat/repository/ui/author/ImportRepositoryEntryController.java +++ b/src/main/java/org/olat/repository/ui/author/ImportRepositoryEntryController.java @@ -116,6 +116,7 @@ public class ImportRepositoryEntryController extends FormBasicController { displaynameEl.setDisplaySize(30); displaynameEl.setMandatory(true); displaynameEl.setVisible(false); + displaynameEl.setElementCssClass("o_sel_author_imported_name"); String[] refValues = new String[]{ translate("references.expl") }; referencesEl = uifactory.addCheckboxesHorizontal("references", "references", formLayout, refKeys, refValues); diff --git a/src/test/java/org/olat/selenium/AssessmentTest.java b/src/test/java/org/olat/selenium/AssessmentTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e193e87d6c9e1dcdeb43dd3aeeccb78b94f79644 --- /dev/null +++ b/src/test/java/org/olat/selenium/AssessmentTest.java @@ -0,0 +1,159 @@ +/** + * <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; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.UUID; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.drone.api.annotation.Drone; +import org.jboss.arquillian.graphene.page.InitialPage; +import org.jboss.arquillian.graphene.page.Page; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.olat.selenium.page.LoginPage; +import org.olat.selenium.page.NavigationPage; +import org.olat.selenium.page.course.CourseEditorPageFragment; +import org.olat.selenium.page.course.CoursePageFragment; +import org.olat.selenium.page.qti.QTI12Page; +import org.olat.test.ArquillianDeployments; +import org.olat.test.JunitTestHelper; +import org.olat.test.rest.UserRestClient; +import org.olat.user.restapi.UserVO; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +/** + * + * Initial date: 11.02.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@RunWith(Arquillian.class) +public class AssessmentTest { + + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + private WebDriver browser; + @ArquillianResource + private URL deploymentUrl; + + @Page + private NavigationPage navBar; + + /** + * An author upload a test, create a course with a test course + * element, publish the course and do and pass the test. + * + * @param authorLoginPage + * @throws IOException + * @throws URISyntaxException + */ + @Test + @RunAsClient + public void qti12Test(@InitialPage LoginPage authorLoginPage) + throws IOException, URISyntaxException { + UserVO author = new UserRestClient(deploymentUrl).createAuthor(); + authorLoginPage.loginAs(author.getLogin(), author.getPassword()); + + //upload a test + String qtiTestTitle = "QTI-Test-1.2-" + UUID.randomUUID(); + URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/e4_test.zip"); + File qtiTestFile = new File(qtiTestUrl.toURI()); + navBar + .openAuthoringEnvironment() + .uploadResource(qtiTestTitle, qtiTestFile); + + //create a course + String courseTitle = "Course-With-QTI-Test-1.2-" + 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"; + CourseEditorPageFragment courseEditor = CoursePageFragment.getCourse(browser) + .edit(); + courseEditor + .createNode("iqtest") + .nodeTitle(testNodeTitle) + .selectTabLearnContent() + .chooseTest(qtiTestTitle); + + //publish the course + courseEditor + .publish() + .quickPublish(); + + //open the course and see the test start page + courseEditor + .clickToolbarBack() + .clickTree() + .selectWithTitle(testNodeTitle); + + //check that the title of the start page of test is correct + WebElement testH2 = browser.findElement(By.cssSelector("div.o_titled_wrapper.o_course_run h2")); + Assert.assertEquals(testNodeTitle, testH2.getText().trim()); + + //start the test + QTI12Page testPage = QTI12Page.getQTI12Page(browser); + testPage + .start() + .selectItem(0) + .answerSingleChoice(0) + .saveAnswer() + .selectItem(1) + .answerMultipleChoice(0, 2) + .saveAnswer() + .selectItem(2) + .answerKPrim(true, false, true, false) + .saveAnswer() + .selectItem(3) + .answerFillin("not") + .saveAnswer(); + testPage + .endTest(); + + //check results page + WebElement resultsEl = browser.findElement(By.id("o_qti_results")); + Assert.assertTrue(resultsEl.getText().contains(author.getFirstName())); + //close the test + testPage + .closeTest(); + //all answers are correct -> passed + WebElement passedEl = browser.findElement(By.cssSelector("tr.o_state.o_passed")); + Assert.assertTrue(passedEl.isDisplayed()); + } + +} 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 cdb080c1353ddca80a2c4ff533d321725907e600..8ca5d0ce2bc90855a0d3d041b3968a9589a1a931 100644 --- a/src/test/java/org/olat/selenium/page/course/CourseEditorPageFragment.java +++ b/src/test/java/org/olat/selenium/page/course/CourseEditorPageFragment.java @@ -179,6 +179,15 @@ public class CourseEditorPageFragment { return chooseResource(chooseWikiButton, resourceTitle); } + /** + * @see chooseResource + * @param resourceTitle + * @return + */ + public CourseEditorPageFragment chooseTest(String resourceTitle) { + return chooseResource(chooseTestButton, resourceTitle); + } + /** * Click the choose button, which open the resource chooser. Select * the "My entries" segment, search the rows for the resource title, diff --git a/src/test/java/org/olat/selenium/page/qti/QTI12Page.java b/src/test/java/org/olat/selenium/page/qti/QTI12Page.java new file mode 100644 index 0000000000000000000000000000000000000000..6c8b9a5db4b9bb5886fa9f700223c26b964f2f48 --- /dev/null +++ b/src/test/java/org/olat/selenium/page/qti/QTI12Page.java @@ -0,0 +1,127 @@ +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.Alert; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +/** + * + * Drive the test QTI 1.2 from OpenOLAT + * + * Initial date: 11.02.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class QTI12Page { + + private WebDriver browser; + + private QTI12Page(WebDriver browser) { + this.browser = browser; + } + + public static QTI12Page getQTI12Page(WebDriver browser) { + WebElement main = browser.findElement(By.id("o_main_wrapper")); + Assert.assertTrue(main.isDisplayed()); + return new QTI12Page(browser); + } + + public QTI12Page start() { + By startBy = By.cssSelector("a.o_sel_start_qti12_test"); + WebElement startButton = browser.findElement(startBy); + startButton.click(); + OOGraphene.waitBusy(); + return this; + } + + public QTI12Page selectItem(int position) { + By itemsBy = By.cssSelector("a.o_sel_qti_menu_item"); + List<WebElement> itemList = browser.findElements(itemsBy); + Assert.assertTrue(itemList.size() > position); + WebElement itemEl = itemList.get(position); + itemEl.click(); + OOGraphene.waitBusy(); + return this; + } + + public QTI12Page answerSingleChoice(int selectPosition) { + By itemsBy = By.cssSelector("div.o_qti_item_choice_option input[type='radio']"); + List<WebElement> optionList = browser.findElements(itemsBy); + Assert.assertTrue(optionList.size() > selectPosition); + WebElement optionEl = optionList.get(selectPosition); + optionEl.click(); + OOGraphene.waitBusy(); + return this; + } + + public QTI12Page answerMultipleChoice(int... selectPositions) { + By itemsBy = By.cssSelector("div.o_qti_item_choice_option input[type='checkbox']"); + List<WebElement> optionList = browser.findElements(itemsBy); + for(int selectPosition:selectPositions) { + Assert.assertTrue(optionList.size() > selectPosition); + optionList.get(selectPosition).click(); + } + OOGraphene.waitBusy(); + return this; + } + + public QTI12Page answerKPrim(boolean... choices) { + By itemsBy = By.cssSelector("table.o_qti_item_kprim input[type='radio']"); + List<WebElement> optionList = browser.findElements(itemsBy); + Assert.assertEquals(choices.length * 2, optionList.size()); + for(int i=0; i<choices.length; i++) { + WebElement optionTrueEl = optionList.get(i * 2); + WebElement optionFalseEl = optionList.get((i * 2) + 1); + if(choices[i]) { + optionTrueEl.click(); + } else { + optionFalseEl.click(); + } + } + OOGraphene.waitBusy(); + return this; + } + + public QTI12Page answerFillin(String... texts) { + By holesBy = By.cssSelector("div.o_qti_item input[type='text']"); + List<WebElement> holesList = browser.findElements(holesBy); + Assert.assertEquals(texts.length, holesList.size()); + for(int i=0; i<texts.length; i++) { + holesList.get(i).sendKeys(texts[i]); + } + OOGraphene.waitBusy(); + return this; + } + + public QTI12Page saveAnswer() { + By saveAnswerBy = By.name("olat_fosm"); + WebElement saveAnswerButton = browser.findElement(saveAnswerBy); + saveAnswerButton.click(); + OOGraphene.waitBusy(); + return this; + } + + public QTI12Page endTest() { + By endBy = By.cssSelector("div.o_button_group.o_button_group_right a"); + WebElement endButton = browser.findElement(endBy); + endButton.click(); + //accept and go further + Alert alert = browser.switchTo().alert(); + alert.accept(); + OOGraphene.waitAndCloseBlueMessageWindow(browser); + return this; + } + + public QTI12Page closeTest() { + By endBy = By.cssSelector("div.o_button_group.o_button_group_right a"); + WebElement endButton = browser.findElement(endBy); + endButton.click(); + OOGraphene.waitBusy(); + return this; + } +} diff --git a/src/test/java/org/olat/selenium/page/repository/AuthoringEnvPage.java b/src/test/java/org/olat/selenium/page/repository/AuthoringEnvPage.java index 30f5d9a4f3e0a3c93d8edc48fa38beb645b9c2f7..60d040c58dc199a3a1244513137e2e57735314a9 100644 --- a/src/test/java/org/olat/selenium/page/repository/AuthoringEnvPage.java +++ b/src/test/java/org/olat/selenium/page/repository/AuthoringEnvPage.java @@ -19,6 +19,8 @@ */ package org.olat.selenium.page.repository; +import java.io.File; + import org.jboss.arquillian.drone.api.annotation.Drone; import org.jboss.arquillian.graphene.Graphene; import org.junit.Assert; @@ -146,6 +148,29 @@ public class AuthoringEnvPage { .clickToolbarBack(); } + public AuthoringEnvPage uploadResource(String title, File resource) { + WebElement importLink = browser.findElement(By.className("o_sel_author_import")); + Assert.assertTrue(importLink.isDisplayed()); + importLink.click(); + OOGraphene.waitBusy(); + + By inputBy = By.cssSelector(".o_fileinput input[type='file']"); + OOGraphene.uploadFile(inputBy, resource, browser); + OOGraphene.waitElement(By.className("o_sel_author_imported_name")); + + By titleBy = By.cssSelector(".o_sel_author_imported_name input"); + WebElement titleEl = browser.findElement(titleBy); + titleEl.sendKeys(title); + + //save + By saveBy = By.cssSelector("div.o_sel_repo_save_details button.btn-primary"); + WebElement saveButton = browser.findElement(saveBy); + saveButton.click(); + OOGraphene.waitBusy(); + + return this; + } + public enum ResourceType { course("CourseModule"), cp("FileResource.IMSCP"), diff --git a/src/test/java/org/olat/test/file_resources/e4_test.zip b/src/test/java/org/olat/test/file_resources/e4_test.zip new file mode 100644 index 0000000000000000000000000000000000000000..393578fb6d17c5e577edd81ee5c63eb30d497fdd Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/e4_test.zip differ