Skip to content
Snippets Groups Projects
Commit 9e174f60 authored by srosse's avatar srosse
Browse files

no-jira: selenium tests for QTI 2.1 editor, 2 matches with different settings,...

no-jira: selenium tests for QTI 2.1 editor, 2 matches with different settings, scoring and with feedbacks
parent 205c936b
No related branches found
No related tags found
No related merge requests found
......@@ -88,12 +88,13 @@ public class MatchScoreController extends AssessmentItemRefEditorController impl
setFormContextHelp("Test editor QTI 2.1 in detail#details_testeditor_score");
minScoreEl = uifactory.addTextElement("min.score", "min.score", 8, "0.0", formLayout);
minScoreEl.setElementCssClass("o_sel_assessment_item_min_score");
minScoreEl.setEnabled(false);
minScoreEl.setEnabled(!restrictedEdit);
ScoreBuilder maxScore = itemBuilder.getMaxScoreBuilder();
String maxValue = maxScore == null ? "" : (maxScore.getScore() == null ? "" : maxScore.getScore().toString());
maxScoreEl = uifactory.addTextElement("max.score", "max.score", 8, maxValue, formLayout);
maxScoreEl.setElementCssClass("o_sel_assessment_item_max_score");
maxScoreEl.setEnabled(!restrictedEdit);
String[] modeValues = new String[]{
......
......@@ -53,7 +53,7 @@ jQuery(function() {
#end
#if($r.available("add.match.row") || $r.available("add.match.column") || $r.available("submit"))
<div class="o_button_group">
<div class="o_button_group o_sel_match_save">
#if($r.available("submit"))
$r.render("submit")
#end
......
......@@ -11,8 +11,9 @@
#foreach($sourceChoice in $sourceChoices)
<tr>
<th>${sourceChoice.getSummary()}</th>
#set($sourceIndex = ${foreach.index})
#foreach($targetChoice in $targetChoices)
<td>
<td class="o_sel_match_${sourceIndex}_${foreach.index}">
#set($scoreWrapper = $r.get("${sourceChoice.getChoiceIdentifier().toString()}-${targetChoice.getChoiceIdentifier().toString()}"))
$r.render("${sourceChoice.getChoiceIdentifier().toString()}-${targetChoice.getChoiceIdentifier().toString()}")
#if(${scoreWrapper.isCorrect()})
......
......@@ -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.QTI21MatchEditorPage;
import org.olat.selenium.page.qti.QTI21MultipleChoiceEditorPage;
import org.olat.selenium.page.qti.QTI21Page;
import org.olat.selenium.page.qti.QTI21SingleChoiceEditorPage;
......@@ -953,7 +954,6 @@ public class ImsQTI21Test {
UserVO ryomou = new UserRestClient(deploymentUrl).createRandomUser("Ryomou");
authorLoginPage.loginAs(author.getLogin(), author.getPassword());
//upload a test
String qtiTestTitle = "Choices QTI 2.1 " + UUID.randomUUID();
navBar
.openAuthoringEnvironment()
......@@ -1097,7 +1097,6 @@ public class ImsQTI21Test {
UserVO eric = new UserRestClient(deploymentUrl).createRandomUser("Eric");
authorLoginPage.loginAs(author.getLogin(), author.getPassword());
//upload a test
String qtiTestTitle = "Choices QTI 2.1 " + UUID.randomUUID();
navBar
.openAuthoringEnvironment()
......@@ -1250,7 +1249,6 @@ public class ImsQTI21Test {
.assertOnAssessmentResults()
.assertOnAssessmentTestScore(6);// 3 points from the first question, 3 from the second
}
/**
* An author make a test with 2 kprims.<br>
......@@ -1272,7 +1270,6 @@ public class ImsQTI21Test {
UserVO melissa = new UserRestClient(deploymentUrl).createRandomUser("Melissa");
authorLoginPage.loginAs(author.getLogin(), author.getPassword());
//upload a test
String qtiTestTitle = "Choices QTI 2.1 " + UUID.randomUUID();
navBar
.openAuthoringEnvironment()
......@@ -1421,4 +1418,196 @@ public class ImsQTI21Test {
.assertOnAssessmentResults()
.assertOnAssessmentTestScore(6);// 3 points from the first question, 3 from the second
}
/**
* An author make a test with 2 matches. A match with "multiple selection"
* and score "all answers", a second with "single selection" and score
* "per answers".<br>
* A first user make the test, but doesn't answer all questions
* correctly, log out and a second user make the perfect test.
*
* @param authorLoginPage
* @param participantBrowser
* @throws IOException
* @throws URISyntaxException
*/
@Test
@RunAsClient
public void qti21EditorMatch(@InitialPage LoginPage authorLoginPage,
@Drone @User WebDriver participantBrowser)
throws IOException, URISyntaxException {
UserVO author = new UserRestClient(deploymentUrl).createAuthor();
UserVO rei = new UserRestClient(deploymentUrl).createRandomUser("Rei");
UserVO melissa = new UserRestClient(deploymentUrl).createRandomUser("Melissa");
authorLoginPage.loginAs(author.getLogin(), author.getPassword());
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 a match, multiple selection
QTI21MatchEditorPage matchEditor = qtiEditor
.addMatch();
matchEditor
.setSource(0, "Eclipse")
.setSource(1, "vim")
.setTarget(0, "IDE")
.setTarget(1, "TextProcessor")
.addColumn()
.setTarget(2, "TextEditor")
.setMatch(0, 0, true)
.setMatch(1, 2, true)
.save();
// change max score
matchEditor
.selectScores()
.setMaxScore("4")
.save();
// set some feedbacks
matchEditor
.selectFeedbacks()
.setHint("Hint", "This is only an hint")
.setCorrectSolution("Correct solution", "This is the correct solution")
.setCorrectFeedback("Correct feedback", "This is correct")
.setIncorrectFeedback("Incorrect", "Your answer is not correct")
.save();
// second match
matchEditor = qtiEditor
.addMatch()
.setSingleChoices()
.setSource(0, "Java")
.setSource(1, "C")
.addRow()
.setSource(2, "PHP")
.setTarget(0, "CodeIgniter")
.setTarget(1, "VisualStudio")
.addColumn()
.setTarget(2, "Eclipse")
.setMatch(0, 2, true)
.setMatch(1, 1, true)
.setMatch(2, 0, true)
.save();
// select score "per answer" and set the scores
matchEditor
.selectScores()
.selectAssessmentMode(ScoreEvaluation.perAnswer)
.setMaxScore("6")
.setScore(0, 0, "0.0")
.setScore(0, 1, "0.0")
.setScore(0, 2, "2.0")
.setScore(1, 0, "0.0")
.setScore(1, 1, "3.0")
.setScore(1, 2, "0.0")
.setScore(2, 0, "1.0")
.setScore(2, 1, "0.0")
.setScore(2, 2, "0.0")
.save();
matchEditor
.selectFeedbacks()
.setHint("Hint", "The hint")
.setCorrectSolution("Correct solution", "This is the correct solution")
.setCorrectFeedback("Correct feedback", "This is correct")
.setIncorrectFeedback("Incorrect", "Your answer is not correct")
.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()
.answerMatch("Eclipse", "IDE", true)
.answerMatch("vim", "IDE", true)
.saveAnswer()
.assertFeedback("Incorrect")
.assertCorrectSolution("Correct solution")
.hint()
.assertFeedback("Hint")
.answerMatch("vim", "IDE", false)
.answerMatch("vim", "TextEditor", true)
.saveAnswer()
.assertFeedback("Correct feedback")
.nextAnswer()
.answerMatch("Java", "Eclipse", true)
.answerMatch("C", "CodeIgniter", true)
.answerMatch("PHP", "VisualStudio", true)
.saveAnswer()
.assertCorrectSolution("Correct solution")
.assertFeedback("Incorrect")
.endTest()
.assertOnAssessmentResults()
.assertOnAssessmentTestScore(6);// 4 points from the first question, 2 from the second
//a second user search the content package
LoginPage melLoginPage = LoginPage.getLoginPage(participantBrowser, deploymentUrl);
melLoginPage
.loginAs(melissa.getLogin(), melissa.getPassword())
.resume();
NavigationPage melNavBar = new NavigationPage(participantBrowser);
melNavBar
.openMyCourses()
.openSearch()
.extendedSearch(qtiTestTitle)
.select(qtiTestTitle)
.start();
// make the test
QTI21Page
.getQTI12Page(participantBrowser)
.assertOnAssessmentItem()
.answerMatch("Eclipse", "IDE", true)
.answerMatch("vim", "TextEditor", true)
.saveAnswer()
.assertFeedback("Correct feedback")
.nextAnswer()
.answerMatch("Java", "Eclipse", true)
.answerMatch("C", "CodeIgniter", true)
.answerMatch("PHP", "VisualStudio", true)
.saveAnswer()
.answerMatch("C", "CodeIgniter", false)
.answerMatch("PHP", "VisualStudio", false)
.answerMatch("C", "VisualStudio", true)
.answerMatch("PHP", "CodeIgniter", true)
.saveAnswer()
.endTest()
.assertOnAssessmentResults()
.assertOnAssessmentTestScore(10);// 4 points from the first question, 6 from the second
}
}
......@@ -22,6 +22,7 @@ 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;
/**
*
......@@ -35,6 +36,18 @@ public class QTI21MatchEditorPage extends QTI21AssessmentItemEditorPage {
super(browser);
}
public QTI21MatchEditorPage setSource(int position, String text) {
String containerCssSelector = "th.o_sel_match_source_" + position;
OOGraphene.tinymce(text, containerCssSelector, browser);
return this;
}
public QTI21MatchEditorPage setTarget(int position, String text) {
String containerCssSelector = "th.o_sel_match_target_" + position;
OOGraphene.tinymce(text, containerCssSelector, browser);
return this;
}
/**
* Set if the answer is correct or wrong.
*
......@@ -42,34 +55,45 @@ public class QTI21MatchEditorPage extends QTI21AssessmentItemEditorPage {
* @param correct
* @return Itself
*/
public QTI21MatchEditorPage setCorrect(int position, boolean correct) {
By answerBy;
if(correct) {
answerBy = By.xpath("//div[contains(@class,'o_sel_choice_" + position + "')]//input[contains(@id,'oo_correct-')]");
} else {
answerBy = By.xpath("//div[contains(@class,'o_sel_choice_" + position + "')]//input[contains(@id,'oo_wrong-')]");
}
browser.findElement(answerBy).click();
public QTI21MatchEditorPage setMatch(int source, int target, boolean correct) {
By answerBy = By.xpath("//td[contains(@class,'o_sel_match_" + source + "_" + target + "')]/input[contains(@id,'oo_')]");
WebElement matchEl = browser.findElement(answerBy);
OOGraphene.check(matchEl, correct);
OOGraphene.waitBusy(browser);
return this;
}
public QTI21MatchEditorPage setAnswer(int position, String answer) {
String containerCssSelector = "div.o_sel_choice_" + position;
OOGraphene.tinymce(answer, containerCssSelector, browser);
public QTI21MatchEditorPage addColumn() {
By saveBy = By.cssSelector("div.o_sel_match_save a.o_sel_match_add_column");
browser.findElement(saveBy).click();
OOGraphene.waitBusy(browser);
return this;
}
public QTI21MatchEditorPage addRow() {
By saveBy = By.cssSelector("div.o_sel_match_save a.o_sel_match_add_row");
browser.findElement(saveBy).click();
OOGraphene.waitBusy(browser);
return this;
}
public QTI21MatchEditorPage setSingleChoices() {
By singleBy = By.cssSelector("div.o_sel_match_single input[type='radio'][value='single']");
browser.findElement(singleBy).click();
OOGraphene.waitBusy(browser);
return this;
}
public QTI21MatchEditorPage save() {
By saveBy = By.cssSelector("fieldset.o_sel_choices_save button.btn.btn-primary");
By saveBy = By.cssSelector("div.o_sel_match_save button.btn.btn-primary");
browser.findElement(saveBy).click();
OOGraphene.waitBusy(browser);
return this;
}
public QTI21ChoicesScoreEditorPage selectScores() {
public QTI21MatchScoreEditorPage selectScores() {
selectTab(By.className("o_sel_assessment_item_options"));
return new QTI21ChoicesScoreEditorPage(browser);
return new QTI21MatchScoreEditorPage(browser);
}
public QTI21FeedbacksEditorPage selectFeedbacks() {
......
/**
* <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.ims.qti21.model.xml.interactions.SimpleChoiceAssessmentItemBuilder.ScoreEvaluation;
import org.olat.selenium.page.graphene.OOGraphene;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
/**
*
* Initial date: 10 mai 2017<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class QTI21MatchScoreEditorPage {
private static final By choiceScoreTable = By.cssSelector("table.matchInteraction.score");
private final WebDriver browser;
public QTI21MatchScoreEditorPage(WebDriver browser) {
this.browser = browser;
}
public QTI21MatchScoreEditorPage selectAssessmentMode(ScoreEvaluation mode) {
By modeBy = By.cssSelector("#o_coassessment_mode input[value='" + mode.name() + "']");
browser.findElement(modeBy).click();
OOGraphene.waitBusy(browser);
if(mode == ScoreEvaluation.allCorrectAnswers) {
OOGraphene.waitElementDisappears(choiceScoreTable, 5, browser);
} else if (mode == ScoreEvaluation.perAnswer) {
OOGraphene.waitElement(choiceScoreTable, 5, browser);
}
return this;
}
public QTI21MatchScoreEditorPage setScore(int source, int target, String score) {
By scoreBy = By.cssSelector("td.o_sel_match_" + source + "_" + target + " input[type='text']");
WebElement scoreEl = browser.findElement(scoreBy);
scoreEl.clear();
scoreEl.sendKeys(score);
return this;
}
public QTI21MatchScoreEditorPage 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 QTI21MatchScoreEditorPage save() {
By saveBy = By.cssSelector("fieldset.o_sel_assessment_item_options button.btn.btn-primary");
browser.findElement(saveBy).click();
OOGraphene.waitBusy(browser);
return this;
}
}
......@@ -166,6 +166,13 @@ public class QTI21Page {
return this;
}
public QTI21Page answerMatch(String source, String target, boolean match) {
By matchBy = By.xpath("//div[contains(@class,'matchInteraction')]/table//tr[th/p[contains(text(),'" + source + "')]]/td[count(//div[contains(@class,'matchInteraction')]/table//tr/th[p[contains(text(),'" + target + "')]]/preceding-sibling::th)]/input");
WebElement matchEl = browser.findElement(matchBy);
OOGraphene.check(matchEl, match);
return this;
}
public QTI21Page saveAnswer() {
By saveAnswerBy = By.cssSelector("button.o_sel_assessment_item_submit");
browser.findElement(saveAnswerBy).click();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment