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

Merge remote-tracking branch 'origin/OpenOLAT_15.1'

parents 03809711 0d30587d
No related branches found
No related tags found
No related merge requests found
Showing
with 474 additions and 15 deletions
......@@ -100,6 +100,7 @@
<test.env.instance.id>myolat</test.env.instance.id>
<test.env.jmx.rmi.port.0>3000</test.env.jmx.rmi.port.0>
<test.env.webdriver.browser>chrome</test.env.webdriver.browser>
<test.env.webdriver.chrome.version></test.env.webdriver.chrome.version>
<test.env.webdriver.chrome.arguments></test.env.webdriver.chrome.arguments>
<skipTests>true</skipTests>
<skipSeleniumTests>false</skipSeleniumTests>
......@@ -1326,6 +1327,7 @@
<test.env.jmx.rmi.port.0>${test.env.jmx.rmi.port.0}</test.env.jmx.rmi.port.0>
<arquillian.launch>tomcat-7-managed</arquillian.launch>
<webdriver.browser>${test.env.webdriver.browser}</webdriver.browser>
<webdriver.chrome.version>${test.env.webdriver.chrome.version}</webdriver.chrome.version>
<webdriver.chrome.arguments>${test.env.webdriver.chrome.arguments}</webdriver.chrome.arguments>
</systemPropertyVariables>
<testNGArtifactName>none:none</testNGArtifactName>
......
......@@ -23,7 +23,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.olat.core.CoreSpringFactory;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.form.flexible.FormItem;
......@@ -59,6 +58,7 @@ import org.olat.course.nodes.cl.model.CheckboxList;
import org.olat.course.nodes.cl.ui.CheckboxConfigDataModel.Cols;
import org.olat.course.run.environment.CourseEnvironment;
import org.olat.modules.ModuleConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Controller to manage a list of checks
......@@ -83,7 +83,8 @@ public class CheckListBoxListEditController extends FormBasicController {
private final CourseEnvironment courseEnv;
private final CheckListCourseNode courseNode;
private final CheckboxManager checkboxManager;
@Autowired
private CheckboxManager checkboxManager;
public CheckListBoxListEditController(UserRequest ureq, WindowControl wControl,
OLATResourceable courseOres, CheckListCourseNode courseNode, boolean inUse) {
......@@ -95,7 +96,6 @@ public class CheckListBoxListEditController extends FormBasicController {
ICourse course = CourseFactory.loadCourse(courseOres);
courseEnv = course.getCourseEnvironment();
config = courseNode.getModuleConfiguration();
checkboxManager = CoreSpringFactory.getImpl(CheckboxManager.class);
initForm(ureq);
}
......@@ -105,6 +105,7 @@ public class CheckListBoxListEditController extends FormBasicController {
setFormTitle("config.checkbox.title");
setFormDescription("config.checkbox.description");
setFormContextHelp("Assessment#_checklist_cb");
formLayout.setElementCssClass("o_sel_cl_edit_checklist");
if(inUse) {
setFormWarning("config.warning.inuse");
}
......@@ -114,6 +115,7 @@ public class CheckListBoxListEditController extends FormBasicController {
formLayout.add(tableCont);
addLink = uifactory.addFormLink("add.checkbox", tableCont, Link.BUTTON);
addLink.setElementCssClass("o_sel_cl_new_checkbox");
FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.title.i18nKey(), Cols.title.ordinal()));
......
......@@ -101,6 +101,7 @@ public class CheckListConfigurationController extends FormBasicController {
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
formLayout.setElementCssClass("o_sel_cl_edit_assessment");
if(wizard) {
titlePrefixEl = uifactory.addTextElement("titelprefix", "title.prefix", 64, "", formLayout);
titlePrefixEl.setMandatory(true);
......@@ -151,10 +152,12 @@ public class CheckListConfigurationController extends FormBasicController {
}
String minValStr = minVal == null ? "" : Float.toString(minVal.floatValue());
minPointsEl = uifactory.addTextElement("pointsmin", "config.points.min", 4, minValStr, formLayout);
minPointsEl.setElementCssClass("o_sel_cl_min_score");
minPointsEl.setMandatory(true);
minPointsEl.setDisplaySize(5);
String maxValStr = maxVal == null ? "" : Float.toString(maxVal.floatValue());
maxPointsEl = uifactory.addTextElement("pointsmax", "config.points.max", 4, maxValStr, formLayout);
maxPointsEl.setElementCssClass("o_sel_cl_max_score");
maxPointsEl.setMandatory(true);
maxPointsEl.setDisplaySize(5);
......@@ -180,6 +183,7 @@ public class CheckListConfigurationController extends FormBasicController {
String cutValStr = cutVal == null ? "" : Float.toString(cutVal.floatValue());
cutValueEl = uifactory.addTextElement("cutvalue", "config.cutvalue", 4, cutValStr, formLayout);
cutValueEl.setElementCssClass("o_sel_cl_cut_value");
cutValueEl.setDisplaySize(5);
cutValueEl.setMandatory(true);
......
......@@ -114,8 +114,10 @@ public class CheckboxEditController extends FormBasicController {
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
formLayout.setElementCssClass("o_sel_cl_edit_checkbox_form");
String title = checkbox.getTitle();
titleEl = uifactory.addTextElement("checkbox.title", "checkbox.title", 255, title, formLayout);
titleEl.setElementCssClass("o_sel_cl_checkbox_title");
String[] releaseKeys = new String[] {
CheckboxReleaseEnum.userAndCoach.name(), CheckboxReleaseEnum.coachOnly.name()
......@@ -142,6 +144,7 @@ public class CheckboxEditController extends FormBasicController {
String[] onKeys = new String[] { "on" };
String[] onValues = new String[] { translate("award.point.on") };
awardPointEl = uifactory.addCheckboxesHorizontal("points", formLayout, onKeys, onValues);
awardPointEl.setElementCssClass("o_sel_cl_checkbox_award_points");
awardPointEl.setVisible(withScore);
awardPointEl.addActionListener(FormEvent.ONCHANGE);
if(checkbox.getPoints() != null) {
......@@ -149,6 +152,7 @@ public class CheckboxEditController extends FormBasicController {
}
String points = checkbox.getPoints() == null ? null : Float.toString(checkbox.getPoints().floatValue());
pointsEl = uifactory.addTextElement("numofpoints", null, 10, points, formLayout);
pointsEl.setElementCssClass("o_sel_cl_checkbox_points");
pointsEl.setVisible(withScore && awardPointEl.isAtLeastSelected(1));
pointsEl.setDisplaySize(5);
......
......@@ -24,6 +24,6 @@ edit.moderator.coach=Betreuer
edit.poster=Beitr\u00E4ge erstellen
edit.poster.coach=Betreuer
edit.poster.guest=Gast
edit.poster.participant=Teilnehemer
edit.poster.participant=Teilnehmer
user.rights=Benutzerberechtigungen
......@@ -17,7 +17,7 @@ edit.moderator.coach=Betreuer
edit.poster=Forumsbeitr\u00E4ge erstellen
edit.poster.coach=Betreuer
edit.poster.guest=Gast
edit.poster.participant=Teilnehemer
edit.poster.participant=Teilnehmer
pane.tab.accessibility=Zugang
pane.tab.config=Konfiguration
peekview.allItemsLink= Alle Beitr\u00E4ge
......
......@@ -19,13 +19,18 @@
*/
package org.olat.ims.qti21.ui.editor;
import java.util.List;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.FormItem;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.elements.FormLink;
import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
import org.olat.core.gui.components.form.flexible.elements.TextElement;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
......@@ -34,8 +39,11 @@ import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
import org.olat.core.util.StringHelper;
import org.olat.core.util.Util;
import org.olat.ims.qti21.ui.AssessmentTestDisplayController;
import org.olat.ims.qti21.ui.editor.events.AssessmentTestEvent;
import uk.ac.ed.ph.jqtiplus.node.test.AbstractPart;
import uk.ac.ed.ph.jqtiplus.node.test.AssessmentItemRef;
import uk.ac.ed.ph.jqtiplus.node.test.AssessmentSection;
import uk.ac.ed.ph.jqtiplus.node.test.ItemSessionControl;
import uk.ac.ed.ph.jqtiplus.node.test.TestPart;
......@@ -56,7 +64,14 @@ public abstract class ItemSessionControlController extends FormBasicController {
private static final String[] yesNoInheritKeys = new String[] { YES, NO, INHERIT };
private TextElement maxAttemptsEl;
protected SingleSelection limitAttemptsEl, allowSkippingEl, allowCommentEl, allowReviewEl, showSolutionEl;
protected SingleSelection limitAttemptsEl;
private FormLink inheritMaxAttemptsButton;
private FormLayoutContainer maxAttemptsWarningLayout;
protected SingleSelection allowReviewEl;
protected SingleSelection showSolutionEl;
protected SingleSelection allowSkippingEl;
protected SingleSelection allowCommentEl;
private DialogBoxController attemptsWarningCtrl;
......@@ -108,6 +123,15 @@ public abstract class ItemSessionControlController extends FormBasicController {
maxAttemptsEl.setVisible(limitAttemptsEl.isSelected(0));
maxAttemptsEl.setEnabled(!restrictedEdit && editable);
String warningPage = velocity_root + "/max_attempts_warning.html";
maxAttemptsWarningLayout = FormLayoutContainer.createCustomFormLayout("maxAttemptsWarning", getTranslator(), warningPage);
formLayout.add(maxAttemptsWarningLayout);
inheritMaxAttemptsButton = uifactory.addFormLink("force.inherited.max.attempts", maxAttemptsWarningLayout, Link.BUTTON_XSMALL);
inheritMaxAttemptsButton.setForceOwnDirtyFormWarning(false);
inheritMaxAttemptsButton.setDomReplacementWrapperRequired(false);
maxAttemptsWarningLayout.add("force.inherited.max.attempts", inheritMaxAttemptsButton);
updateWarningMaxAttempts();
allowSkippingEl = uifactory.addRadiosHorizontal("item.session.control.allow.skipping", formLayout, aKeys, aValues);
allowSkippingEl.addActionListener(FormEvent.ONCHANGE);
allowSkippingEl.setEnabled(!restrictedEdit && editable);
......@@ -157,6 +181,39 @@ public abstract class ItemSessionControlController extends FormBasicController {
showSolutionEl.select(key, true);
}
}
private void updateWarningMaxAttempts() {
boolean needWarning = false;
MaxAttemptsStatistics statistics = MaxAttemptsStatistics.calculate(part);
if(statistics.getNumOfItems() != 0 && statistics.getNumOfItems() == statistics.getNumOfItemsWithoutInherited()) {
String itemMsg = translate("warning.item.session.control.attempts.all.items.defined");
maxAttemptsWarningLayout.contextPut("itemMsg", itemMsg);
needWarning = true;
} else if(statistics.getNumOfItemsWithoutInherited() > 0) {
String itemMsg = translate("warning.item.session.control.attempts.items.defined");
maxAttemptsWarningLayout.contextPut("itemMsg", itemMsg);
needWarning = true;
} else {
maxAttemptsWarningLayout.contextRemove("itemMsg");
}
if(statistics.getNumOfSubSections() != 0 && statistics.getNumOfSubSections() == statistics.getNumOfSectionsWithoutInherited()) {
String sectionMsg = translate("warning.item.session.control.attempts.all.sections.defined");
maxAttemptsWarningLayout.contextPut("sectionMsg", sectionMsg);
needWarning = true;
} else if(statistics.getNumOfSectionsWithoutInherited() > 0) {
String sectionMsg = translate("warning.item.session.control.attempts.sections.defined");
maxAttemptsWarningLayout.contextPut("sectionMsg", sectionMsg);
needWarning = true;
} else {
maxAttemptsWarningLayout.contextRemove("sectionMsg");
}
boolean warningVisible = limitAttemptsEl.isSelected(0) && needWarning;
inheritMaxAttemptsButton.setVisible(warningVisible);
maxAttemptsWarningLayout.setVisible(warningVisible);
}
@Override
protected void doDispose() {
......@@ -165,7 +222,7 @@ public abstract class ItemSessionControlController extends FormBasicController {
@Override
protected boolean validateFormLogic(UserRequest ureq) {
boolean allOk = true;
boolean allOk = super.validateFormLogic(ureq);
allOk &= validateSingleSelection(allowCommentEl);
allOk &= validateSingleSelection(allowReviewEl);
......@@ -187,7 +244,7 @@ public abstract class ItemSessionControlController extends FormBasicController {
}
}
return allOk & super.validateFormLogic(ureq);
return allOk;
}
private boolean validateSingleSelection(SingleSelection selectionEl) {
......@@ -200,8 +257,6 @@ public abstract class ItemSessionControlController extends FormBasicController {
return allOk;
}
@Override
protected void event(UserRequest ureq, Controller source, Event event) {
if(attemptsWarningCtrl == source) {
......@@ -210,6 +265,7 @@ public abstract class ItemSessionControlController extends FormBasicController {
limitAttemptsEl.getComponent().setDirty(true);
maxAttemptsEl.setVisible(false);
}
updateWarningMaxAttempts();
removeAsListenerAndDispose(attemptsWarningCtrl);
attemptsWarningCtrl = null;
}
......@@ -228,6 +284,10 @@ public abstract class ItemSessionControlController extends FormBasicController {
String text = translate("warning.item.session.control.attempts");
attemptsWarningCtrl = activateOkCancelDialog(ureq, null, text, attemptsWarningCtrl);
}
updateWarningMaxAttempts();
} else if(inheritMaxAttemptsButton == source) {
doInheritMaxAttempts(ureq);
updateWarningMaxAttempts();
}
super.formInnerEvent(ureq, source, event);
}
......@@ -280,7 +340,7 @@ public abstract class ItemSessionControlController extends FormBasicController {
if(limitAttemptsEl.isSelected(0) && maxAttemptsEl != null && maxAttemptsEl.isVisible()
&& StringHelper.isLong(maxAttemptsEl.getValue())) {
int maxAttempts = Integer.parseInt(maxAttemptsEl.getValue());
checkNotNull(itemSessionControl).setMaxAttempts(new Integer(maxAttempts));
checkNotNull(itemSessionControl).setMaxAttempts(Integer.valueOf(maxAttempts));
} else if(limitAttemptsEl.isSelected(1)) {
checkNotNull(itemSessionControl).setMaxAttempts(0);
} else if(itemSessionControl != null) {
......@@ -295,4 +355,92 @@ public abstract class ItemSessionControlController extends FormBasicController {
}
return itemSessionControl;
}
private void doInheritMaxAttempts(UserRequest ureq) {
doChildrenInheritMaxAttempts(part);
fireEvent(ureq, AssessmentTestEvent.ASSESSMENT_TEST_CHANGED_EVENT);
}
private void doChildrenInheritMaxAttempts(AbstractPart aPart) {
List<? extends AbstractPart> parts = aPart.getChildAbstractParts();
for(AbstractPart subPart:parts) {
ItemSessionControl itemSessionControl = subPart.getItemSessionControl();
if(itemSessionControl != null) {
itemSessionControl.setMaxAttempts(null);
}
if(subPart instanceof AssessmentSection) {
doChildrenInheritMaxAttempts(subPart);
}
}
}
private static class MaxAttemptsStatistics {
private int numOfSubSections = 0;
private int numOfItems = 0;
private int numOfSectionsWithoutInherited = 0;
private int numOfItemsWithoutInherited = 0;
public static final MaxAttemptsStatistics calculate(AbstractPart aPart) {
MaxAttemptsStatistics statistics = new MaxAttemptsStatistics();
warningMaxAttempts(aPart, statistics);
return statistics;
}
private static void warningMaxAttempts(AbstractPart aPart, MaxAttemptsStatistics statistics) {
List<? extends AbstractPart> parts = aPart.getChildAbstractParts();
for(AbstractPart subPart:parts) {
if(subPart instanceof AssessmentItemRef) {
statistics.incrementNumOfItems();
if(!statistics.isMaxAttemptsInherited(subPart)) {
statistics.incrementNumOfItemsWithoutInherited();
}
} else if(subPart instanceof AssessmentSection) {
statistics.incrementNumOfSubSections();
if(!statistics.isMaxAttemptsInherited(subPart)) {
statistics.incrementNumOfSectionsWithoutInherited();
}
warningMaxAttempts(subPart, statistics);
}
}
}
public int getNumOfSubSections() {
return numOfSubSections;
}
public void incrementNumOfSubSections() {
numOfSubSections++;
}
public int getNumOfItems() {
return numOfItems;
}
public void incrementNumOfItems() {
numOfItems++;
}
public int getNumOfSectionsWithoutInherited() {
return numOfSectionsWithoutInherited;
}
public void incrementNumOfSectionsWithoutInherited() {
numOfSectionsWithoutInherited++;
}
public int getNumOfItemsWithoutInherited() {
return numOfItemsWithoutInherited;
}
public void incrementNumOfItemsWithoutInherited() {
numOfItemsWithoutInherited++;
}
public boolean isMaxAttemptsInherited(AbstractPart aPart) {
ItemSessionControl itemSessionControl = aPart.getItemSessionControl();//can be null
return itemSessionControl == null || itemSessionControl.getMaxAttempts() == null;
}
}
}
<div class="o_qti_max_attempts o_warning">
#if($r.isNotEmpty($itemMsg))
<p>$itemMsg</p>
#end
#if($r.isNotEmpty($sectionMsg))
<p>$sectionMsg</p>
#end
#if($r.visible("force.inherited.max.attempts"))
$r.render("force.inherited.max.attempts")
#end
</div>
\ No newline at end of file
......@@ -90,6 +90,7 @@ fib.tolerance.mode.relative.example=Prozent, zum Beispiel 15 oder 99.0
fib.tolerance.mode.relative.help=Die Schranke stellt eine relative Zahl in Prozent dar.\u2028Beispiel\: L\u00F6sung 20, Untere Schranke 10, Obere Schranke 10 &rarr; Alle L\u00F6sungen zwischen 18 und 22 sind g\u00FCltig, denn die untere Schranke bedeutet minus 10% (20-2) und die obere Schranke plus 10% (20+2).
fib.tolerance.up=Obere Schranke
file=Datei
force.inherited.max.attempts=Setzt alle unter "L\u00F6sungsversuche" zu "Vererbt"
form.choice=Auswahl
form.drawing=Zeichnen
form.essay=Freitext
......@@ -300,6 +301,10 @@ warning.custom.operator=Es wurde eine her\u00ADstel\u00ADler\u00ADspe\u00ADzi\u0
warning.feedback.cutvalue=Feedback wird aktiviert, sobald bei "Notwendige Punktzahl f\u00FCr 'Bestanden'" eine Punktzahl eingegeben wurde.
warning.in.use=Die Ressource wird bereits f\u00FCr die Auswertung verwendet. Die Bearbeitung ist begrenzt.
warning.item.session.control.attempts=Diese Einschr\u00E4nkung kann Auswirkungen auf die Anzahl L\u00F6sungsversuche pro Frage haben.<br/>Bitte \u00FCberpr\u00FCfen Sie die Einstellung der Fragen.
warning.item.session.control.attempts.all.items.defined=Alle Fragen definieren schon die Anzahl L\u00F6sungsversuche und \u00FCberschreiben diesen Wert.
warning.item.session.control.attempts.all.sections.defined=Alle Sektionen definieren schon die Anzahl L\u00F6sungsversuche und \u00FCberschreiben diesen Wert.
warning.item.session.control.attempts.items.defined=Einige Fragen definieren schon die Anzahl L\u00F6sungsversuche und \u00FCberschreiben diesen Wert.
warning.item.session.control.attempts.sections.defined=Einige Sektionen definieren schon die Anzahl L\u00F6sungsversuche und \u00FCberschreiben diesen Wert.
warning.templates=Diese Frage benutzt Templates, die vom OpenOlat Editor nicht unterst\u00FCtzt werden.
warning.text.after.interaction=Diese Frage enth\u00E4lt Text nach dem interaktiven Element. Das ist von dem Editor nicht unterst\u00FCtzt. Der Text werden nach der Konvertierung nicht mehr vorhanden sein.
warning.unsupported.feedbacks=Diese Frage enth\u00E4tlt Feedbacks, die von dem Editor nicht unterst\u00FCtzt sind. Sie werden nach der Konvertierung nicht mehr vorhanden sein.
......@@ -90,6 +90,7 @@ fib.tolerance.mode.relative.example=Percentage, example 15 or 99.0
fib.tolerance.mode.relative.help=The solution is accepted until a lower and an upper bound. The bound is a relative number in percent. Example\: Solution 20, lower bound 10, upper bound 10 &rarr; all solutions between 18 and 22 are correct, as the lower bound means minus 10% (20-2) and the upper bound plus 10% (20+2).
fib.tolerance.up=Upper bound
file=File
force.inherited.max.attempts=Set all under "Number of attempts" to inherit
form.choice=Choice
form.drawing=Drawing
form.essay=Essay
......@@ -300,6 +301,10 @@ warning.custom.operator=This question contains creator specific extension which
warning.feedback.cutvalue=The feedback is based on the cut value. You need to define it first.
warning.in.use=The resource is already used for assessment purpose. Editing is limited.
warning.item.session.control.attempts=This limitation can have an impact on the number of attempts per questions.<br/>Please check the settings for the questions again.
warning.item.session.control.attempts.all.items.defined=All questions already defined the number of attempts and override this value.
warning.item.session.control.attempts.all.sections.defined=All sections already defined the number of attempts and override this value.
warning.item.session.control.attempts.items.defined=Certain questions defined the number of attempts and override this value.
warning.item.session.control.attempts.sections.defined=Certain sections defined the number of attempts and override this value.
warning.templates=This question contains some templates which are not compatible with the OpenOlat editor.
warning.text.after.interaction=This question has text after the interaction element. This is not compatible with the OpenOlat editor and the text will be lost after conversion.
warning.unsupported.feedbacks=This question contains feedbacks which are not compatible with the OpenOlat editor. They can be lost after conversion.
......@@ -116,6 +116,10 @@ ul.sessionControl {
}
}
.o_qti_max_attempts.o_warning {
margin: 0;
}
/* Hotspot */
#o_qti_hotspots_edit {
min-height: 100px;
......
This diff is collapsed.
source diff could not be displayed: it is too large. Options to address this: view the blob.
This diff is collapsed.
source diff could not be displayed: it is too large. Options to address this: view the blob.
......@@ -33,6 +33,7 @@ import org.jboss.arquillian.test.api.ArquillianResource;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.olat.course.learningpath.FullyAssessedTrigger;
import org.olat.repository.RepositoryEntryStatusEnum;
import org.olat.selenium.page.LoginPage;
import org.olat.selenium.page.NavigationPage;
......@@ -43,6 +44,8 @@ import org.olat.selenium.page.core.ContactPage;
import org.olat.selenium.page.core.FolderPage;
import org.olat.selenium.page.core.MenuTreePageFragment;
import org.olat.selenium.page.course.BigBlueButtonPage;
import org.olat.selenium.page.course.CheckListConfigPage;
import org.olat.selenium.page.course.CheckListPage;
import org.olat.selenium.page.course.ContactConfigPage;
import org.olat.selenium.page.course.CourseEditorPageFragment;
import org.olat.selenium.page.course.CoursePageFragment;
......@@ -2038,4 +2041,112 @@ public class CourseElementTest extends Deployments {
.assertOnMeeting(meetingName)
.assertOnJoin();
}
/**
* An author create a course with a course element
* with one check box. It add one participant. The
* participant log in, go to the course to check its
* box and see if it has done the course with 100%.
*
* @param loginPage The login page
* @throws IOException
* @throws URISyntaxException
*/
@Test
@RunAsClient
public void courseWithCheckboxWithScore()
throws IOException, URISyntaxException {
UserVO author = new UserRestClient(deploymentUrl).createAuthor();
UserVO participant = new UserRestClient(deploymentUrl).createRandomUser("ryomou");
LoginPage loginPage = LoginPage.load(browser, deploymentUrl);
loginPage.loginAs(author.getLogin(), author.getPassword());
//create a course
String courseTitle = "Check Course" + UUID.randomUUID();
NavigationPage navBar = NavigationPage.load(browser);
CoursePageFragment courseRuntime = navBar
.openAuthoringEnvironment()
.createCourse(courseTitle, true)
.clickToolbarBack();
//add participant
MembersPage members = courseRuntime
.members();
members
.importMembers()
.setMembers(participant)
.nextUsers()
.nextOverview()
.selectRepositoryEntryRole(false, false, true)
.nextPermissions()
.finish();
// back to course
members
.clickToolbarBack();
//create a course element of type Test with the test that we create above
String nodeTitle = "CheckNode";
CourseEditorPageFragment courseEditor = CoursePageFragment.getCourse(browser)
.edit();
courseEditor
.createNode("checklist")
.nodeTitle(nodeTitle);
String checkboxTitle = "Do some programming";
CheckListConfigPage checkConfig = new CheckListConfigPage(browser);
checkConfig
.selectListConfiguration()
.addCheckbox(checkboxTitle, 4)
.assertOnCheckboxInList(checkboxTitle);
checkConfig
.selectAssessmentConfiguration()
.setScoring(0, 4, 3)
.saveAssessmentConfiguration();
courseEditor
.selectTabLearnPath()
.setCompletionCriterion(FullyAssessedTrigger.passed)
.save();
courseEditor
.autoPublish()
.publish()
.settings()
.accessConfiguration()
.setUserAccess(UserAccess.membersOnly)
.save()
.clickToolbarBack();
//log out
new UserToolsPage(browser)
.logout();
// participant comes in
loginPage.loginAs(participant.getLogin(), participant.getPassword());
NavigationPage ryomouNavBar = NavigationPage.load(browser);
ryomouNavBar
.openMyCourses()
.select(courseTitle);
CoursePageFragment course = new CoursePageFragment(browser);
course
.clickTree()
.selectWithTitle(nodeTitle);
CheckListPage checkPage = new CheckListPage(browser);
checkPage
.assertOnCheckbox(checkboxTitle)
.check(checkboxTitle);
// student has done the course
course
.assertOnLearnPathNodeDone(nodeTitle)
.assertOnLearnPathPercent(100);
}
}
/**
* <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.course;
import org.olat.selenium.page.graphene.OOGraphene;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
/**
*
* Initial date: 3 juil. 2020<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class CheckListConfigPage {
private final WebDriver browser;
public CheckListConfigPage(WebDriver browser) {
this.browser = browser;
}
public CheckListConfigPage selectListConfiguration() {
OOGraphene.scrollTop(browser);
By configBy = By.className("o_sel_cl_edit_checklist");
OOGraphene.selectTab("o_node_config", configBy, browser);
return this;
}
public CheckListConfigPage addCheckbox(String title, int score) {
By addCheckboxBy = By.className("o_sel_cl_new_checkbox");
OOGraphene.waitElement(addCheckboxBy, browser);
browser.findElement(addCheckboxBy).click();
OOGraphene.waitBusy(browser);
OOGraphene.waitModalDialog(browser);
By titleBy = By.cssSelector("fieldset.o_sel_cl_edit_checkbox_form input.o_sel_cl_checkbox_title[type='text']");
OOGraphene.waitElement(titleBy, browser);
browser.findElement(titleBy).sendKeys(title);
if(score > 0) {
By awardPoints = By.cssSelector("fieldset.o_sel_cl_edit_checkbox_form div.o_sel_cl_checkbox_award_points input[type='checkbox']");
browser.findElement(awardPoints).click();
OOGraphene.waitBusy(browser);
By pointsBy = By.cssSelector("fieldset.o_sel_cl_edit_checkbox_form input.o_sel_cl_checkbox_points[type='text']");
OOGraphene.waitElement(pointsBy, browser);
browser.findElement(pointsBy).sendKeys(Integer.toString(score));
}
By saveBy = By.cssSelector("fieldset.o_sel_cl_edit_checkbox_form button.btn-primary");
browser.findElement(saveBy).click();
OOGraphene.waitBusy(browser);
OOGraphene.waitModalDialogDisappears(browser);
return this;
}
public CheckListConfigPage assertOnCheckboxInList(String title) {
By checkboxBy = By.xpath("//fieldset[contains(@class,'o_sel_cl_edit_checklist')]//div[contains(@class,'o_table_flexi')]/table//td[contains(text(),'" + title + "')]");
OOGraphene.waitElement(checkboxBy, browser);
return this;
}
public CheckListConfigPage selectAssessmentConfiguration() {
By configBy = By.className("o_sel_cl_edit_assessment");
OOGraphene.selectTab("o_node_config", configBy, browser);
return this;
}
public CheckListConfigPage setScoring(int minScore, int maxScore, int cutValue) {
By minScoreBy = By.cssSelector("fieldset.o_sel_cl_edit_assessment input.o_sel_cl_min_score[type='text']");
OOGraphene.waitElement(minScoreBy, browser);
browser.findElement(minScoreBy).sendKeys(Integer.toString(minScore));
By maxScoreBy = By.cssSelector("fieldset.o_sel_cl_edit_assessment input.o_sel_cl_max_score[type='text']");
browser.findElement(maxScoreBy).sendKeys(Integer.toString(maxScore));
By cutValueScoreBy = By.cssSelector("fieldset.o_sel_cl_edit_assessment input.o_sel_cl_cut_value[type='text']");
browser.findElement(cutValueScoreBy).sendKeys(Integer.toString(cutValue));
return this;
}
public CheckListConfigPage saveAssessmentConfiguration() {
By saveBy = By.cssSelector("fieldset.o_sel_cl_edit_assessment button.btn-primary");
browser.findElement(saveBy).click();
OOGraphene.waitBusy(browser);
OOGraphene.scrollTop(browser);
return this;
}
}
/**
* <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.course;
import org.olat.selenium.page.graphene.OOGraphene;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
/**
*
* Initial date: 9 juil. 2020<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class CheckListPage {
private final WebDriver browser;
public CheckListPage(WebDriver browser) {
this.browser = browser;
}
public CheckListPage assertOnCheckbox(String title) {
By titleBy = By.xpath("//h4[@class='o_cl_title'][contains(text(),'" + title + "')]");
OOGraphene.waitElement(titleBy, browser);
return this;
}
public CheckListPage check(String title) {
By checkBy = By.xpath("//div[contains(@class,'o_cl_line')][div/h4[@class='o_cl_title'][contains(text(),'" + title + "')]]//label/input[@type='checkbox']");
browser.findElement(checkBy).click();
OOGraphene.waitBusy(browser);
return this;
}
}
......@@ -29,6 +29,7 @@
<property name="firefoxDriverBinary">target/drone/ce03addb1fc8c24900011f90fc80f3c1/geckodriver</property>
-->
<property name="firefoxUserPreferences">src/test/profile/firefox/prefs.js</property>
<property name="chromeDriverVersion">${webdriver.chrome.version:84.0.4147.30}</property>
<property name="chromeArguments">${webdriver.chrome.arguments}</property>
<property name="chromeExperimentalOption">{
"prefs":{"credentials_enable_service": false, "profile.password_manager_enabled": false }
......
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