diff --git a/TESTING.README.LATEST b/TESTING.README.LATEST index 50a1f138902dc55bda5519499c280c96b389be8f..beca74ea368cfa1502261e0b33e811c01ea3df49 100644 --- a/TESTING.README.LATEST +++ b/TESTING.README.LATEST @@ -66,7 +66,7 @@ junit and integration tests in OpenOLAT 8 * Execute selenium functional integration tests ----------------------------------------- -- Selenium functional tests on GUI layer that load OpenOLAT with Arquillian in a Tomcat 7.0.27 managed by Arquillian +- Selenium functional tests on GUI layer that load OpenOLAT in a Tomcat 7.0.27 managed by Arquillian mvn package mvn -Parquillian surefire:test diff --git a/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java b/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java index 65784a75262ab2ef86e5c6bf48cf8972c974d0d2..7ce2824dbaf9935f03a1faf92b7ea5876cd2260b 100644 --- a/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java +++ b/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java @@ -274,6 +274,7 @@ public class FileUploadController extends FormBasicController { formLayout.add(buttons); FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttonGroupLayout", getTranslator()); buttons.add(buttonGroupLayout); + buttonGroupLayout.setElementCssClass("o_sel_upload_buttons"); uifactory.addFormSubmitButton("ul.upload", buttonGroupLayout); if (showCancel) { uifactory.addFormCancelButton("cancel", buttonGroupLayout, ureq, getWindowControl()); diff --git a/src/main/java/org/olat/core/gui/components/Component.java b/src/main/java/org/olat/core/gui/components/Component.java index d860be8075556a91a3645f42186b0b0086bc3bb4..2781a8c5ff784e579dc646efcbc2615ba078baa3 100644 --- a/src/main/java/org/olat/core/gui/components/Component.java +++ b/src/main/java/org/olat/core/gui/components/Component.java @@ -54,6 +54,7 @@ public abstract class Component { private String name; private String dispatchID; + private String elementCssClass; private long timestamp = 1l; private boolean staticCmp = true; @@ -158,6 +159,14 @@ public abstract class Component { return name; } + public String getElementCssClass() { + return elementCssClass; + } + + public void setElementCssClass(String elementCssClass) { + this.elementCssClass = elementCssClass; + } + /** * @return boolean */ diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/FormItem.java b/src/main/java/org/olat/core/gui/components/form/flexible/FormItem.java index 17342675e005475aec13442871b97c439f160bf1..37172c182776d188ca18f6e8568cb850993deac4 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/FormItem.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/FormItem.java @@ -173,6 +173,10 @@ public interface FormItem extends FormBaseComponentIdProvider { */ public boolean hasFocus(); + public String getElementCssClass(); + + public void setElementCssClass(String cssClass); + /** * called if this component is dispatched, e.g. was clicked (double clicked, * ...) diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormDecoratorImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormDecoratorImpl.java index 6935d0e59eea7956ff42085629a361f4e214120f..a04eaf597da38e0ae23234e8d9d968dc2f908e07 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormDecoratorImpl.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormDecoratorImpl.java @@ -31,6 +31,7 @@ import org.olat.core.gui.components.form.flexible.FormDecorator; 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.SpacerElement; +import org.olat.core.util.StringHelper; /** * Description:<br> @@ -43,7 +44,7 @@ import org.olat.core.gui.components.form.flexible.elements.SpacerElement; */ public class FormDecoratorImpl implements FormDecorator { - FormItemContainer container; + private final FormItemContainer container; public FormDecoratorImpl(FormItemContainer container) { this.container = container; @@ -115,6 +116,21 @@ public class FormDecoratorImpl implements FormDecorator { else return (item instanceof SpacerElement); } + + public String getContainerCssClass() { + if (container != null && StringHelper.containsNonWhitespace(container.getElementCssClass())) { + return " " + container.getElementCssClass(); + } + return ""; + } + + public String getElementCssClass(String formItemName) { + FormItem item = getFormItem(formItemName); + if (item != null && StringHelper.containsNonWhitespace(item.getElementCssClass())) { + return " " + item.getElementCssClass(); + } + return ""; + } /** * Internal helper to get a form item for the given name diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormItemImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormItemImpl.java index 0e43ef1d4fbc6ca3f2e34e6da4eb166ee2afc5da..2fa0284dd4a4727cd31f0e9795ebca6fffa7eb3d 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormItemImpl.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormItemImpl.java @@ -82,6 +82,7 @@ public abstract class FormItemImpl implements FormItem, InlineElement { private boolean isInlineEditingOn; private Component inlineEditingComponent; private String i18nKey4EmptyText="inline.empty.click.for.edit"; + private String elementCssClass; /** * @@ -115,6 +116,14 @@ public abstract class FormItemImpl implements FormItem, InlineElement { return name; } + public String getElementCssClass() { + return elementCssClass; + } + + public void setElementCssClass(String elementCssClass) { + this.elementCssClass = elementCssClass; + } + @Override public boolean isInlineEditingOn() { if(!isInlineEditingElement) throw new AssertException("isInlineEditingOn called although it is not a inlineEditingElement"); diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_buttongroup.html b/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_buttongroup.html index 99af8d8e6909a4dde7d53c0e641dcbea49d1b78e..43aa3581e9666be0384dd49e189f0c73103098fb 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_buttongroup.html +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_buttongroup.html @@ -1,4 +1,4 @@ -<div class="b_button_group"> +<div class="b_button_group $f.getContainerCssClass()"> #foreach ($item in $formitemnames) $r.render("$item") #end diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_default.html b/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_default.html index fcb0e5fd187323943b23b7c2245a54eb09305773..c4e82cd962f5fb49dac1e83fd4d345350df53999 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_default.html +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_default.html @@ -1,4 +1,4 @@ -<div class="b_form #if ($off_css_class) $off_css_class #end b_clearfix"> +<div class="b_form #if ($off_css_class) $off_css_class #end $f.getContainerCssClass() b_clearfix"> #if ($off_title) <fieldset><legend>$off_title</legend> #end #if ($off_chelp_package) $r.contextHelpWithWrapper("$off_chelp_package","$off_chelp_page","$off_chelp_hover") #end #if ($off_desc) <div class="b_form_desc">$off_desc</div> #end @@ -8,9 +8,9 @@ #foreach ($item in $formitemnames) #if ($f.isVisible($item)) #if($f.hasError($item)) - <div class="b_form_element_wrapper b_form_error b_clearfix"> + <div class="b_form_element_wrapper$f.getElementCssClass($item) b_form_error b_clearfix"> #else - <div class="b_form_element_wrapper b_clearfix"> + <div class="b_form_element_wrapper$f.getElementCssClass($item) b_clearfix"> #end #if ($f.hasLabel($item)) <div class="b_form_element_label"> diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_horizontal.html b/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_horizontal.html index be38bc12436352730183692a781f4815b807b31d..1e6f3a2994859fa4240fac591ea6d7a620147594 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_horizontal.html +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_horizontal.html @@ -1,4 +1,4 @@ -<div class="b_form b_form_horizontal #if ($off_css_class) $off_css_class #end b_clearfix"> +<div class="b_form b_form_horizontal #if ($off_css_class) $off_css_class #end $f.getContainerCssClass() b_clearfix"> #if ($off_title) <fieldset><legend>$off_title</legend> #end #if ($off_chelp_package) $r.contextHelpWithWrapper("$off_chelp_package","$off_chelp_page","$off_chelp_hover") #end #if ($off_desc) <div class="b_form_desc">$off_desc</div> #end @@ -8,9 +8,9 @@ #foreach ($item in $formitemnames) #if ($f.isVisible($item)) #if($f.hasError($item)) - <div class="b_form_element_wrapper b_form_horizontal b_form_error"> + <div class="b_form_element_wrapper$f.getElementCssClass($item) b_form_horizontal b_form_error"> #else - <div class="b_form_element_wrapper b_form_horizontal"> + <div class="b_form_element_wrapper$f.getElementCssClass($item) b_form_horizontal"> #end #if ($f.hasLabel($item)) <div class="b_form_element_label b_form_horizontal"> diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_vertical.html b/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_vertical.html index f332feb882495667893068bb348c2970df02ea0e..207f4ae88e594cb4c83e58724d088c0fddfbb6b4 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_vertical.html +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/_content/form_vertical.html @@ -1,4 +1,4 @@ -<div class="b_form b_form_vertical #if ($off_css_class) $off_css_class #end b_clearfix"> +<div class="b_form b_form_vertical #if ($off_css_class) $off_css_class #end $f.getContainerCssClass() b_clearfix"> #if ($off_title) <fieldset><legend>$off_title</legend> #end #if ($off_chelp_package) $r.contextHelpWithWrapper("$off_chelp_package","$off_chelp_page","$off_chelp_hover") #end #if ($off_desc) <div class="b_form_desc">$off_desc</div> #end @@ -8,9 +8,9 @@ #foreach ($item in $formitemnames) #if ($f.isVisible($item)) #if($f.hasError($item)) - <div class="b_form_element_wrapper b_form_vertical b_form_error b_clearfix"> + <div class="b_form_element_wrapper$f.getElementCssClass($item) b_form_vertical b_form_error b_clearfix"> #else - <div class="b_form_element_wrapper b_form_vertical b_clearfix"> + <div class="b_form_element_wrapper$f.getElementCssClass($item) b_form_vertical$f.getElementCssClass($item) b_clearfix"> #end #if ($f.hasLabel($item)) <div class="b_form_element_label b_form_vertical"> diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FormLinkImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FormLinkImpl.java index 93cdb4fa8167f6aeb527544e788db9fd7d072c97..c9d6dd144a310c091b73b2b57c4d10492f2eda1d 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FormLinkImpl.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FormLinkImpl.java @@ -162,6 +162,11 @@ public class FormLinkImpl extends FormItemImpl implements FormLink { return component; } + @Override + public void setElementCssClass(String elementCssClass) { + component.setElementCssClass(elementCssClass); + super.setElementCssClass(elementCssClass); + } /** * @see org.olat.core.gui.components.form.flexible.elements.FormLink#setCustomEnabledLinkCSS(java.lang.String) diff --git a/src/main/java/org/olat/core/gui/components/link/Link.java b/src/main/java/org/olat/core/gui/components/link/Link.java index ad293c9d6cefb54e4b41fcbb2fb1b5af88b05264..f913397bad13c2fb67a3b2e0cfbd728b44c1caa5 100644 --- a/src/main/java/org/olat/core/gui/components/link/Link.java +++ b/src/main/java/org/olat/core/gui/components/link/Link.java @@ -339,7 +339,6 @@ public class Link extends Component { setDirty(true); } - public void removeCSS(){ this.presentation = presentationBeforeCustomCSS; setDirty(true); diff --git a/src/main/java/org/olat/core/gui/components/link/LinkRenderer.java b/src/main/java/org/olat/core/gui/components/link/LinkRenderer.java index da4a92752856631f2b43cd53f49a06a4fcd2f73b..932dd62f051ccd950bbc41d7c2faeeeda8ece74b 100644 --- a/src/main/java/org/olat/core/gui/components/link/LinkRenderer.java +++ b/src/main/java/org/olat/core/gui/components/link/LinkRenderer.java @@ -43,6 +43,7 @@ import org.olat.core.gui.render.StringOutput; import org.olat.core.gui.render.URLBuilder; import org.olat.core.gui.translator.Translator; import org.olat.core.logging.AssertException; +import org.olat.core.util.StringHelper; /** * Description: Renders the link component depending of features and style. @@ -100,6 +101,9 @@ public class LinkRenderer implements ComponentRenderer { String customCss = ( link.isEnabled() ? link.getCustomEnabledLinkCSS() : link.getCustomDisabledLinkCSS() ); cssSb.append( customCss == null ? "" : customCss ); } + if(StringHelper.containsNonWhitespace(link.getElementCssClass())) { + cssSb.append(" ").append(link.getElementCssClass()); + } cssSb.append("\""); if (link.isEnabled()) { diff --git a/src/main/java/org/olat/core/gui/components/tree/SelectionTreeRenderer.java b/src/main/java/org/olat/core/gui/components/tree/SelectionTreeRenderer.java index 023eb275c748b21d60e6f305d30cd78601435976..9c1c113a51958e36d2447e2cd76a5caf14f1bac7 100644 --- a/src/main/java/org/olat/core/gui/components/tree/SelectionTreeRenderer.java +++ b/src/main/java/org/olat/core/gui/components/tree/SelectionTreeRenderer.java @@ -38,6 +38,7 @@ import org.olat.core.gui.render.RenderingState; import org.olat.core.gui.render.StringOutput; import org.olat.core.gui.render.URLBuilder; import org.olat.core.gui.translator.Translator; +import org.olat.core.util.StringHelper; import org.olat.core.util.tree.TreeHelper; /** @@ -112,7 +113,12 @@ public class SelectionTreeRenderer implements ComponentRenderer { target.append(tree.isMultiselect() ? SCRIPT_MULTI_PRE : SCRIPT_SINGLE_PRE); target.append(translator.translate("alert")); target.append(SCRIPT_POST); - target.append("<div class=\"b_selectiontree\"><form method=\"post\" name=\"seltree\" action=\""); + target.append("<div class=\"b_selectiontree"); + if(StringHelper.containsNonWhitespace(tree.getElementCssClass())) { + target.append(" ").append(tree.getElementCssClass()); + } + target.append("\"><form method=\"post\" name=\"seltree\" action=\""); + boolean iframePostEnabled = renderer.getGlobalSettings().getAjaxFlags().isIframePostEnabled(); ubu.buildURI(target, null, null, iframePostEnabled? AJAXFlags.MODE_TOBGIFRAME : AJAXFlags.MODE_NORMAL); target.append("\""); @@ -139,7 +145,7 @@ public class SelectionTreeRenderer implements ComponentRenderer { else target.append(internalTranslator.translate("selectiontree.noentries")); target.append("<br /><br />"); if (atLeastOneIsAccessible) { - target.append("<button type=\"submit\" class=\"b_button\" name=\"" + Form.SUBMIT_IDENTIFICATION + "\" value=\""); + target.append("<button type=\"submit\" class=\"b_button o_sel_submit_selection\" name=\"" + Form.SUBMIT_IDENTIFICATION + "\" value=\""); target.append(StringEscapeUtils.escapeHtml(translator.translate(tree.getFormButtonKey()))); if (!tree.isAllowEmptySelection()) { target.append("\" onclick=\"return seltree_check();\" onkeypress=\"return seltree_check();\">"); @@ -150,7 +156,7 @@ public class SelectionTreeRenderer implements ComponentRenderer { } if(tree.isShowCancelButton()){ - target.append("<button type=\"submit\" class=\"b_button\" name=\"" + Form.CANCEL_IDENTIFICATION + "\" value=\""); + target.append("<button type=\"submit\" class=\"b_button o_sel_cancel_selection\" name=\"" + Form.CANCEL_IDENTIFICATION + "\" value=\""); target.append(StringEscapeUtils.escapeHtml(translator.translate("cancel"))).append("\">"); target.append("<span>").append(translator.translate("cancel")).append("</span></button>"); } diff --git a/src/main/java/org/olat/core/gui/control/generic/layout/GenericMainController.java b/src/main/java/org/olat/core/gui/control/generic/layout/GenericMainController.java index 2e8ed3c9fc0ce36f9c3cf83112be71b4450d4895..8f9bb106f145714866db638003708662d2a41b9a 100644 --- a/src/main/java/org/olat/core/gui/control/generic/layout/GenericMainController.java +++ b/src/main/java/org/olat/core/gui/control/generic/layout/GenericMainController.java @@ -220,6 +220,10 @@ public abstract class GenericMainController extends MainLayoutBasicController { if(anExt.isEnabled()){ GenericActionExtension gAe = (GenericActionExtension) ae; gtnChild = gAe.createMenuNode(ureq); + + if(StringHelper.containsNonWhitespace(gAe.getNavigationKey())) { + gtnChild.setCssClass("o_sel_" + gAe.getNavigationKey()); + } if (gAe.getNodeIdentifierIfParent() != null) { // it's a parent-node, set identifier diff --git a/src/main/java/org/olat/core/gui/control/generic/portal/PortalImpl.java b/src/main/java/org/olat/core/gui/control/generic/portal/PortalImpl.java index db07fcf9510d25e71ad188809c0a4a018ad89f69..2977f1271049a773c4ff507c4422b3fa8df39017 100644 --- a/src/main/java/org/olat/core/gui/control/generic/portal/PortalImpl.java +++ b/src/main/java/org/olat/core/gui/control/generic/portal/PortalImpl.java @@ -105,9 +105,9 @@ public class PortalImpl extends DefaultController implements Portal, ControllerE // calculate the column css classes based on YAML schema int cols = portalColumns.size(); - List<String> columnCssClassWrapper = new ArrayList(cols); + List<String> columnCssClassWrapper = new ArrayList<String>(cols); columnCssClassWrapper.add(0, ""); // empty, in velocity things start with 1... - List<String> columnCssClassInner = new ArrayList(cols); + List<String> columnCssClassInner = new ArrayList<String>(cols); columnCssClassInner.add(0, ""); // empty, in velocity things start with 1... switch (cols) { case 0: @@ -120,29 +120,29 @@ public class PortalImpl extends DefaultController implements Portal, ControllerE break; case 2: // 50% each - columnCssClassWrapper.add(1, "b_c50l"); + columnCssClassWrapper.add(1, "b_c50l o_sel_portal_col_1"); columnCssClassInner.add(1, "b_subcl"); - columnCssClassWrapper.add(2, "b_c50r"); + columnCssClassWrapper.add(2, "b_c50r o_sel_portal_col_2"); columnCssClassInner.add(2, "b_subcr"); break; case 3: // 33% each - columnCssClassWrapper.add(1, "b_c33l"); + columnCssClassWrapper.add(1, "b_c33l o_sel_portal_col_1"); columnCssClassInner.add(1, "b_subcl"); - columnCssClassWrapper.add(2, "b_c33l"); + columnCssClassWrapper.add(2, "b_c33l o_sel_portal_col_2"); columnCssClassInner.add(2, "b_subcl"); - columnCssClassWrapper.add(3, "b_c33r"); + columnCssClassWrapper.add(3, "b_c33r o_sel_portal_col_3"); columnCssClassInner.add(3, "b_subcr"); break; case 4: // 25% each - columnCssClassWrapper.add(1, "b_c25l"); + columnCssClassWrapper.add(1, "b_c25l o_sel_portal_col_1"); columnCssClassInner.add(1, "b_subcl"); - columnCssClassWrapper.add(2, "b_c25l"); + columnCssClassWrapper.add(2, "b_c25l o_sel_portal_col_2"); columnCssClassInner.add(2, "b_subcl"); - columnCssClassWrapper.add(3, "b_c25l"); + columnCssClassWrapper.add(3, "b_c25l o_sel_portal_col_3"); columnCssClassInner.add(3, "b_subcl"); - columnCssClassWrapper.add(4, "b_c25r"); + columnCssClassWrapper.add(4, "b_c25r o_sel_portal_col_4"); columnCssClassInner.add(4, "b_subcr"); break; default: diff --git a/src/main/java/org/olat/core/gui/control/generic/tool/ToolController.java b/src/main/java/org/olat/core/gui/control/generic/tool/ToolController.java index 5cd861465cc86eff96cc0b277c20dda7ec4499d5..f05271aea588e78a6f59dc42e4a1ad6a0dbbb490 100644 --- a/src/main/java/org/olat/core/gui/control/generic/tool/ToolController.java +++ b/src/main/java/org/olat/core/gui/control/generic/tool/ToolController.java @@ -109,6 +109,17 @@ public interface ToolController extends Controller { */ public void addLink(String action, String text, String ident, String cssClass, boolean isDownloadLink); + /** + * + * @param action + * @param text + * @param ident + * @param cssClass + * @param elementCssClass + * @param markAsDownloadLink + */ + public void addLink(String action, String text, String ident, String cssClass, String elementCssClass, boolean markAsDownloadLink); + /** * a link (= a velocity $r.link(..)). in order to receive events, the code * creating the tool must use diff --git a/src/main/java/org/olat/core/gui/control/generic/tool/ToolControllerImpl.java b/src/main/java/org/olat/core/gui/control/generic/tool/ToolControllerImpl.java index 21ad9872720876fc1e74331c2c671e9fa4469103..7112ce0bc7a6494ad2673614380d9762b535d452 100644 --- a/src/main/java/org/olat/core/gui/control/generic/tool/ToolControllerImpl.java +++ b/src/main/java/org/olat/core/gui/control/generic/tool/ToolControllerImpl.java @@ -49,10 +49,10 @@ class ToolControllerImpl extends DefaultController implements ToolController { private static final String VELOCITY_ROOT = Util.getPackageVelocityRoot(ToolControllerImpl.class); - private List entries; - private List myLinks; + private List<ToolEntry> entries; + private List<Link> myLinks; private VelocityContainer content; - private boolean dragEnabled; + /** * to enumerate the names of the components so the caller has never to care * about possible name clashed if adding multiple components @@ -64,8 +64,8 @@ class ToolControllerImpl extends DefaultController implements ToolController { */ ToolControllerImpl(WindowControl wControl) { super(wControl); - entries = new ArrayList(); - myLinks = new ArrayList(); + entries = new ArrayList<ToolEntry>(); + myLinks = new ArrayList<Link>(); // init content; we do not need a translator here (null argument below) content = new VelocityContainer("toolcontent", VELOCITY_ROOT + "/index.html", null, this); content.contextPut("entries", entries); @@ -106,6 +106,10 @@ class ToolControllerImpl extends DefaultController implements ToolController { } public void addLink(String action, String text, String ident, String cssClass, boolean markAsDownloadLink) { + addLink(action, text, ident, cssClass, null, markAsDownloadLink); + } + + public void addLink(String action, String text, String ident, String cssClass, String elementCssClass, boolean markAsDownloadLink) { String linkCmpName = ident; if(ident==null){ //TODO:pb remove quickfix -> recorder is also removed @@ -117,6 +121,7 @@ class ToolControllerImpl extends DefaultController implements ToolController { if(markAsDownloadLink){ LinkFactory.markDownloadLink(linkCmp); } + linkCmp.setElementCssClass(elementCssClass); myLinks.add(linkCmp); addComponent(linkCmp, ident); } @@ -125,11 +130,12 @@ class ToolControllerImpl extends DefaultController implements ToolController { if(markAsDownloadLink){ LinkFactory.markDownloadLink(linkCmp); } + linkCmp.setElementCssClass(elementCssClass); myLinks.add(linkCmp); addComponent(linkCmp, ident); } else { - entries.add(new ToolEntry(ident, action, text, cssClass)); + entries.add(new ToolEntry(ident, action, text, cssClass, elementCssClass)); } } @@ -146,7 +152,7 @@ class ToolControllerImpl extends DefaultController implements ToolController { * @see org.olat.core.gui.control.generic.tool.ToolController#addPopUpLink(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, boolean) */ public void addPopUpLink(String action, String text, String ident, String cssClass, String width, String height, boolean browserMenubarEnabled) { - entries.add(new ToolEntry(ident, action, text, cssClass, width, height, browserMenubarEnabled)); + entries.add(new ToolEntry(ident, action, text, cssClass, null, width, height, browserMenubarEnabled)); } /** @@ -244,7 +250,6 @@ class ToolControllerImpl extends DefaultController implements ToolController { * @see org.olat.core.gui.control.generic.tool.ToolController#setDragEnabled(boolean) */ public void setDragEnabled(boolean dragEnabled) { - this.dragEnabled = dragEnabled; content.contextPut("offerdrag", Boolean.valueOf(dragEnabled)); } diff --git a/src/main/java/org/olat/core/gui/control/generic/tool/ToolEntry.java b/src/main/java/org/olat/core/gui/control/generic/tool/ToolEntry.java index dfef630457c2ceedc70f3b1086a47e711720c1fa..b8e42923dfe642d276d3229f2416ee2c25c16ea1 100644 --- a/src/main/java/org/olat/core/gui/control/generic/tool/ToolEntry.java +++ b/src/main/java/org/olat/core/gui/control/generic/tool/ToolEntry.java @@ -46,6 +46,7 @@ public class ToolEntry { private String componentName; private boolean enabled = true; private String cssClass = "b_toolbox_link"; // default + private String elementCssClass; private String width; private String height; private boolean browserMenubarEnabled; @@ -74,12 +75,13 @@ public class ToolEntry { * @param linkText * @param cssClass */ - public ToolEntry(String ident, String action, String linkText, String cssClass) { + public ToolEntry(String ident, String action, String linkText, String cssClass, String elementCssClass) { this.type = TYPE_LINK; this.ident = ident; this.action = action; this.linkText = linkText; if (cssClass != null) this.cssClass = cssClass; + this.elementCssClass = elementCssClass; } /** @@ -103,12 +105,13 @@ public class ToolEntry { * @param height * @param browserMenubarEnabled */ - public ToolEntry(String ident, String action, String linkText, String cssClass, String width, String height, boolean browserMenubarEnabled) { + public ToolEntry(String ident, String action, String linkText, String cssClass, String elementCssClass, String width, String height, boolean browserMenubarEnabled) { this.type = TYPE_POPUP_LINK; this.ident = ident; this.action = action; this.linkText = linkText; if (cssClass != null) this.cssClass = cssClass; + this.elementCssClass = elementCssClass; this.width = width; this.height = height; this.browserMenubarEnabled = browserMenubarEnabled; @@ -171,6 +174,13 @@ public class ToolEntry { return cssClass; } + /** + * @return The element CSS class used for Selenium tests. + */ + public String getElementCssClass() { + return elementCssClass; + } + /** * @return int */ diff --git a/src/main/java/org/olat/course/editor/InsertNodeController.java b/src/main/java/org/olat/course/editor/InsertNodeController.java index 31f840929ecf6cbc09f242bbe068e832d32524a0..31f7a30855516a93ba15da8ad074e184fff6bd51 100644 --- a/src/main/java/org/olat/course/editor/InsertNodeController.java +++ b/src/main/java/org/olat/course/editor/InsertNodeController.java @@ -64,6 +64,7 @@ public class InsertNodeController extends BasicController { this.type = type; insertTree = new SelectionTree("insert_new_node_selection", getTranslator()); + insertTree.setElementCssClass("o_sel_course_insert_node_popup"); insertTree.setFormButtonKey("insertAtSelectedTreepos"); insertTree.addListener(this); ICourse course = CourseFactory.getCourseEditSession(ores.getResourceableId()); diff --git a/src/main/java/org/olat/course/editor/PublishStep00.java b/src/main/java/org/olat/course/editor/PublishStep00.java index a1f110c0ef08bb2f849e519bad4c624b178f11cd..8b1ef15addc8c726a8d364c6ae0c992c26772393 100644 --- a/src/main/java/org/olat/course/editor/PublishStep00.java +++ b/src/main/java/org/olat/course/editor/PublishStep00.java @@ -292,8 +292,10 @@ class PublishStep00 extends BasicStep { //publish treemodel is tree model and INodeFilter at the same time multiSelectTree = uifactory.addTreeMultiselect("seltree", null, fic, publishManager2.getPublishTreeModel(), publishManager2.getPublishTreeModel()); selectAllLink = uifactory.addFormLink("checkall", fic); + selectAllLink.setElementCssClass("o_sel_course_publish_selectall_cbb"); selectAllLink.addActionListener(this, FormEvent.ONCLICK); uncheckallLink = uifactory.addFormLink("uncheckall", fic); + uncheckallLink.setElementCssClass("o_sel_course_publish_deselectall_cbb"); uncheckallLink.addActionListener(this, FormEvent.ONCLICK); } else { // set message container - telling nothing to publish. diff --git a/src/main/java/org/olat/course/editor/_content/insertNode.html b/src/main/java/org/olat/course/editor/_content/insertNode.html index 9b2d08864d01681ccacb0b976ac787ae80fcaa02..95a3a7c6653e21bf5ea872353a800cef75e59ddd 100644 --- a/src/main/java/org/olat/course/editor/_content/insertNode.html +++ b/src/main/java/org/olat/course/editor/_content/insertNode.html @@ -4,4 +4,4 @@ $r.render("nodelimitexceededwarning") <hr /> #end -$r.render("selection") +$r.render("selection") \ No newline at end of file diff --git a/src/main/java/org/olat/course/nodes/cp/CPEditController.java b/src/main/java/org/olat/course/nodes/cp/CPEditController.java index f419aaa0870d74cb9f608c3b4660bc33ced9072a..0e4a864c03b407f22b065e382f977fca7627c002 100644 --- a/src/main/java/org/olat/course/nodes/cp/CPEditController.java +++ b/src/main/java/org/olat/course/nodes/cp/CPEditController.java @@ -129,9 +129,11 @@ public class CPEditController extends ActivateableTabbableDefaultController impl main = new Panel("cpmain"); - cpConfigurationVc = this.createVelocityContainer("edit"); + cpConfigurationVc = createVelocityContainer("edit"); chooseCPButton = LinkFactory.createButtonSmall(NLS_COMMAND_CREATECP, cpConfigurationVc, this); + chooseCPButton.setElementCssClass("o_sel_cp_choose_repofile"); changeCPButton = LinkFactory.createButtonSmall(NLS_COMMAND_CHANGECP, cpConfigurationVc, this); + changeCPButton.setElementCssClass("o_sel_cp_change_repofile"); if (config.get(CONFIG_KEY_REPOSITORY_SOFTKEY) != null) { // fetch repository entry to display the repository entry title of the chosen cp diff --git a/src/main/java/org/olat/course/nodes/feed/FeedNodeEditController.java b/src/main/java/org/olat/course/nodes/feed/FeedNodeEditController.java index 96054ac3c812bcdfb7c009d7121b66b7ca6e4280..ea1f1ce84c85d0a2e9d54b1aef71b666d204866e 100644 --- a/src/main/java/org/olat/course/nodes/feed/FeedNodeEditController.java +++ b/src/main/java/org/olat/course/nodes/feed/FeedNodeEditController.java @@ -148,7 +148,9 @@ public abstract class FeedNodeEditController extends ActivateableTabbableDefault learningResource = new Panel("learning_resource_panel"); contentVC = new VelocityContainer("accessVC", FeedNodeEditController.class, "edit", getTranslator(), this); changeButton = LinkFactory.createButtonSmall(BUTTON_CHANGE_FEED, contentVC, this); + changeButton.setElementCssClass("o_sel_feed_change_repofile"); chooseButton = LinkFactory.createButtonSmall(BUTTON_CREATE_FEED, contentVC, this); + chooseButton.setElementCssClass("o_sel_feed_choose_repofile"); if (config.get(AbstractFeedCourseNode.CONFIG_KEY_REPOSITORY_SOFTKEY) != null) { // fetch repository entry to display the repository entry title of the diff --git a/src/main/java/org/olat/course/nodes/iq/IQEditController.java b/src/main/java/org/olat/course/nodes/iq/IQEditController.java index 6f68a1bcb4ebb2458555579b335c9ce494121916..6ed4e75941330f8a442cac726014ca39d259212d 100644 --- a/src/main/java/org/olat/course/nodes/iq/IQEditController.java +++ b/src/main/java/org/olat/course/nodes/iq/IQEditController.java @@ -296,7 +296,9 @@ public class IQEditController extends ActivateableTabbableDefaultController impl myContent = this.createVelocityContainer("edit"); chooseTestButton = LinkFactory.createButtonSmall("command.chooseRepFile", myContent, this); + chooseTestButton.setElementCssClass("o_sel_test_choose_repofile"); changeTestButton = LinkFactory.createButtonSmall("command.changeRepFile", myContent, this); + changeTestButton.setElementCssClass("o_sel_test_change_repofile"); modConfigForm = new IQEditForm(ureq, wControl, moduleConfiguration); listenTo(modConfigForm); myContent.put("iqeditform",modConfigForm.getInitialComponent()); diff --git a/src/main/java/org/olat/course/nodes/portfolio/PortfolioConfigForm.java b/src/main/java/org/olat/course/nodes/portfolio/PortfolioConfigForm.java index 0cdf092f7bf7bcf3477811537e910f065fa6adb6..e89809258c868072cb51312e47d81a7a381573a1 100644 --- a/src/main/java/org/olat/course/nodes/portfolio/PortfolioConfigForm.java +++ b/src/main/java/org/olat/course/nodes/portfolio/PortfolioConfigForm.java @@ -118,6 +118,7 @@ public class PortfolioConfigForm extends FormBasicController { previewMapLink.setCustomEnabledLinkCSS("b_preview"); ((Link)previewMapLink.getComponent()).setCustomDisplayText(name); previewMapLink.setVisible(map != null); + previewMapLink.setElementCssClass("o_sel_preview_map"); if(formLayout instanceof FormLayoutContainer) { FormLayoutContainer layoutContainer = (FormLayoutContainer)formLayout; @@ -126,8 +127,11 @@ public class PortfolioConfigForm extends FormBasicController { buttonGroupLayout.setRootForm(mainForm); layoutContainer.add(buttonGroupLayout); chooseMapLink = uifactory.addFormLink("select_or_import.map", buttonGroupLayout, Link.BUTTON); + chooseMapLink.setElementCssClass("o_sel_map_choose_repofile"); changeMapLink = uifactory.addFormLink("select.map", buttonGroupLayout, Link.BUTTON); + changeMapLink.setElementCssClass("o_sel_map_change_repofile"); editMapLink = uifactory.addFormLink("edit.map", buttonGroupLayout, Link.BUTTON); + editMapLink.setElementCssClass("o_sel_edit_map"); chooseMapLink.setVisible(map == null); chooseMapLink.setEnabled(!inUse); diff --git a/src/main/java/org/olat/course/nodes/wiki/WikiEditController.java b/src/main/java/org/olat/course/nodes/wiki/WikiEditController.java index 8a9f706280cff554249b8e0ff27a46cd262d8363..75e116492fc4257671a19b339deaa57119defec6 100644 --- a/src/main/java/org/olat/course/nodes/wiki/WikiEditController.java +++ b/src/main/java/org/olat/course/nodes/wiki/WikiEditController.java @@ -55,7 +55,6 @@ import org.olat.course.condition.Condition; import org.olat.course.condition.ConditionEditController; import org.olat.course.editor.NodeEditController; import org.olat.course.groupsandrights.CourseGroupManager; -import org.olat.course.nodes.CourseNodeFactory; import org.olat.course.nodes.WikiCourseNode; import org.olat.course.run.environment.CourseEnvironment; import org.olat.course.run.userview.UserCourseEnvironment; @@ -125,10 +124,11 @@ public class WikiEditController extends ActivateableTabbableDefaultController im main = new Panel("wikimain"); - content = this.createVelocityContainer("edit"); - /*previewButton = LinkFactory.createButtonSmall("command.preview", content, this);*/ + content = createVelocityContainer("edit"); chooseButton = LinkFactory.createButtonSmall("command.create", content, this); + chooseButton.setElementCssClass("o_sel_wiki_choose_repofile"); changeButton = LinkFactory.createButtonSmall("command.change", content, this); + changeButton.setElementCssClass("o_sel_wiki_choose_repofile"); editAccessVc = this.createVelocityContainer("edit_access"); CourseGroupManager groupMgr = course.getCourseEnvironment().getCourseGroupManager(); diff --git a/src/main/java/org/olat/course/run/RunMainController.java b/src/main/java/org/olat/course/run/RunMainController.java index d10701c9823481d799ae15b1f824dfec38ca5bf3..b1b91211ff176979032b83f1b65596a770e0c4c1 100644 --- a/src/main/java/org/olat/course/run/RunMainController.java +++ b/src/main/java/org/olat/course/run/RunMainController.java @@ -1095,11 +1095,11 @@ public class RunMainController extends MainLayoutBasicController implements Gene || hasCourseRight(CourseRights.RIGHT_ASSESSMENT)) { myTool.addHeader(translate("header.tools")); if (hasCourseRight(CourseRights.RIGHT_COURSEEDITOR) || isCourseAdmin) { - myTool.addLink(COMMAND_EDIT, translate("command.openeditor")); + myTool.addLink(COMMAND_EDIT, translate("command.openeditor"), null, null, "o_sel_course_open_editor", false); } if (hasCourseRight(CourseRights.RIGHT_GROUPMANAGEMENT) || isCourseAdmin) { //fxdiff VCRP-1,2: access control of resources - myTool.addLink("unifiedusermngt", translate("command.opensimplegroupmngt")); + myTool.addLink("unifiedusermngt", translate("command.opensimplegroupmngt"), null, null, "o_sel_course_open_membersmgmt", false); } if (hasCourseRight(CourseRights.RIGHT_ARCHIVING) || isCourseAdmin) { myTool.addLink("archiver", translate("command.openarchiver")); @@ -1300,74 +1300,6 @@ public class RunMainController extends MainLayoutBasicController implements Gene logAudit("Leaving course: [[["+courseTitle+"]]]", course.getResourceableId().toString()); } - /* - public void activate(UserRequest ureq, String viewIdentifier) { - if(isDisposed()) { - return; - } - // transform ACTIVATE_RUN to activate course root node - if (viewIdentifier.equals(RepositoryDetailsController.ACTIVATE_RUN)) { - // activating the run, means so far activating the root node - // viewIdentifier = course.getRunStructure().getRootNode().getIdent(); - return; - } - // - - if (viewIdentifier.equals(RepositoryDetailsController.ACTIVATE_EDITOR)) { - // activate editor - if (!isInEditor) { - if (currentToolCtr == null) { - // not already in the editor and also no other course tool running - isInEditor = true; - doHandleToolEvents(ureq, COMMAND_EDIT); - } else if (currentToolCtr != null) { - // not activateable as another tool is running, i.e. assessment tool - getWindowControl().setWarning(translate("warn.cannotactivatesinceintool")); - } - }// else it is already active - } else if (isInEditor || currentToolCtr != null) { - // do not activate anything if a course tool or the editor is active! - getWindowControl().setWarning(translate("warn.cannotactivatesinceintool")); - } else { - if (currentNodeController != null) { - currentNodeController.dispose(); - } - //fxdiff BAKS-7 Resume function - if (viewIdentifier.startsWith("CourseNode:")) { - viewIdentifier = viewIdentifier.substring("CourseNode:".length()); - } - - CourseNode cn = null; - cn = (viewIdentifier == null ? null : course.getRunStructure().getNode(viewIdentifier)); - String subsubId = null; - - // check for subsubIdent (jump into the third level) - if (viewIdentifier != null) { - if (viewIdentifier.indexOf(":") != -1) { - String[] vis = viewIdentifier.split(":"); - cn = course.getRunStructure().getNode(vis[0]); - subsubId = vis[1]; - } - } - // FIXME:fj:b is this needed in some cases?: currentCourseNode = cn; - getWindowControl().makeFlat(); - - //add loggin information for case course gets started via jumpin link/search - addLoggingResourceable(LoggingResourceable.wrap(course)); - if (cn!=null) { - addLoggingResourceable(LoggingResourceable.wrap(cn)); - } - updateTreeAndContent(ureq, cn, subsubId); - } - - // reset gloss toolC to get newly tabs - removeAsListenerAndDispose(glossaryToolCtr); - boolean hasGlossaryRights = hasCourseRight(CourseRights.RIGHT_GLOSSARY) || isCourseAdmin; - glossaryToolCtr = new CourseGlossaryToolLinkController(getWindowControl(), ureq, course, getTranslator(), hasGlossaryRights, - uce.getCourseEnvironment(), glossaryMarkerCtr); - listenTo(glossaryToolCtr); - }*/ - @Override //fxdiff BAKS-7 Resume function public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { diff --git a/src/main/java/org/olat/modules/fo/ForumController.java b/src/main/java/org/olat/modules/fo/ForumController.java index 8cda8d1685469f943cc4f6764cb70b4f355777f1..fc86caf451cce7447694054f1ef85cd4834b6483 100644 --- a/src/main/java/org/olat/modules/fo/ForumController.java +++ b/src/main/java/org/olat/modules/fo/ForumController.java @@ -220,8 +220,11 @@ public class ForumController extends BasicController implements GenericEventList vcListTitles = createVelocityContainer("list_titles"); msgCreateButton = LinkFactory.createButtonSmall("msg.create", vcListTitles, this); + msgCreateButton.setElementCssClass("o_sel_forum_thread_new"); archiveForumButton = LinkFactory.createButtonSmall("archive.forum", vcListTitles, this); + archiveForumButton.setElementCssClass("o_sel_forum_archive"); filterForUserButton = LinkFactory.createButtonSmall("filter", vcListTitles, this); + filterForUserButton.setElementCssClass("o_sel_forum_filter"); if(!this.isGuestOnly(ureq)) { SearchServiceUIFactory searchServiceUIFactory = (SearchServiceUIFactory)CoreSpringFactory.getBean(SearchServiceUIFactory.class); diff --git a/src/main/java/org/olat/modules/webFeed/ui/FeedMainController.java b/src/main/java/org/olat/modules/webFeed/ui/FeedMainController.java index 7a7a0236c901171e51df9d551c459011e96044b6..6f166230a51aebde259b882c175f8d397afc9828 100644 --- a/src/main/java/org/olat/modules/webFeed/ui/FeedMainController.java +++ b/src/main/java/org/olat/modules/webFeed/ui/FeedMainController.java @@ -135,6 +135,7 @@ public class FeedMainController extends BasicController implements Activateable2 // owner of the resource. if (callback.mayEditMetadata()) { editFeedButton = LinkFactory.createButtonSmall("feed.edit", vcInfo, this); + editFeedButton.setElementCssClass("o_sel_feed_edit"); } vcInfo.contextPut("callback", callback); diff --git a/src/main/java/org/olat/modules/webFeed/ui/ItemsController.java b/src/main/java/org/olat/modules/webFeed/ui/ItemsController.java index bf0bd0d0e42b36e246ad7c14fae8884b3f3362c7..20b37390a80782d90aa990dd887d94829b50aed4 100644 --- a/src/main/java/org/olat/modules/webFeed/ui/ItemsController.java +++ b/src/main/java/org/olat/modules/webFeed/ui/ItemsController.java @@ -222,6 +222,7 @@ public class ItemsController extends BasicController implements Activateable2 { artefactLinks = new HashMap<Item,Controller>(); if (feed.isInternal()) { addItemButton = LinkFactory.createButtonSmall("feed.add.item", vcItems, this); + addItemButton.setElementCssClass("o_sel_feed_item_new"); if (items != null) { for (Item item : items) { createButtonsForItem(ureq, item); @@ -339,7 +340,9 @@ public class ItemsController extends BasicController implements Activateable2 { String guid = item.getGuid(); Link editButton = LinkFactory.createCustomLink("feed.edit.item." + guid, "feed.edit.item." + guid, "feed.edit.item", Link.BUTTON_XSMALL, vcItems, this); + editButton.setElementCssClass("o_sel_feed_item_edit"); Link deleteButton = LinkFactory.createCustomLink("delete." + guid, "delete." + guid, "delete", Link.BUTTON_XSMALL, vcItems, this); + deleteButton.setElementCssClass("o_sel_feed_item_delete"); if(feedResource.isInternal() && getIdentity().getKey() != null && getIdentity().getKey().equals(item.getAuthorKey())) { String businessPath = BusinessControlFactory.getInstance().getAsString(getWindowControl().getBusinessControl()); @@ -420,6 +423,7 @@ public class ItemsController extends BasicController implements Activateable2 { } else if (source == makeInternalButton) { feedManager.updateFeedMode(Boolean.FALSE, feed); addItemButton = LinkFactory.createButton("feed.add.item", vcItems, this); + addItemButton.setElementCssClass("o_sel_feed_item_new"); currentItem = new Item(); currentItem.setDraft(true); currentItem.setAuthorKey(ureq.getIdentity().getKey()); diff --git a/src/main/java/org/olat/modules/webFeed/ui/blog/BlogPostFormController.java b/src/main/java/org/olat/modules/webFeed/ui/blog/BlogPostFormController.java index 0d90a415a1430bda723e18b0402e1d9dec4d490b..cf586538e42a9d6517004279563b5f19d2f4849a 100644 --- a/src/main/java/org/olat/modules/webFeed/ui/blog/BlogPostFormController.java +++ b/src/main/java/org/olat/modules/webFeed/ui/blog/BlogPostFormController.java @@ -174,8 +174,9 @@ public class BlogPostFormController extends FormBasicController { */ @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - this.setFormTitle("feed.edit.item"); - this.setFormContextHelp(this.getClass().getPackage().getName(), "post_form_help.html", "chelp.hover.form"); + setFormTitle("feed.edit.item"); + setFormContextHelp(this.getClass().getPackage().getName(), "post_form_help.html", "chelp.hover.form"); + formLayout.setElementCssClass("o_sel_blog_form"); title = uifactory.addTextElement("title", "feed.title.label", 256, post.getTitle(), this.flc); title.setMandatory(true); diff --git a/src/main/java/org/olat/modules/wiki/_content/articleSearch.html b/src/main/java/org/olat/modules/wiki/_content/articleSearch.html index d15edf108bb760e45652697fd0ba52607cd3acad..2f49be025ffacd925b3d4c5532ea404da63103cb 100644 --- a/src/main/java/org/olat/modules/wiki/_content/articleSearch.html +++ b/src/main/java/org/olat/modules/wiki/_content/articleSearch.html @@ -1,4 +1,4 @@ $r.render("search") -<div class="b_button_group"> +<div class="b_button_group o_sel_wiki_search"> $r.render("subm") </div> \ No newline at end of file diff --git a/src/main/java/org/olat/portfolio/ui/EPMapRunController.java b/src/main/java/org/olat/portfolio/ui/EPMapRunController.java index 4ea3d82efac2ac8e9e0297ea0d966df968f0ed40..e8b1d6a1779192402ea7b3df7b13a19de9bbad6f 100755 --- a/src/main/java/org/olat/portfolio/ui/EPMapRunController.java +++ b/src/main/java/org/olat/portfolio/ui/EPMapRunController.java @@ -113,6 +113,7 @@ public class EPMapRunController extends BasicController implements Activateable2 vC = createVelocityContainer("mymapsmain"); if(create) { createMapLink = LinkFactory.createButton("create.map", vC, this); + createMapLink.setElementCssClass("o_sel_create_map"); } String documentType = null; @@ -183,7 +184,9 @@ public class EPMapRunController extends BasicController implements Activateable2 if(option.equals(EPMapRunViewOption.MY_DEFAULTS_MAPS)) { VelocityContainer mapCreateVC = createVelocityContainer("createMapCallout"); createMapCalloutLink = LinkFactory.createLink("create.map.default", mapCreateVC, this); + createMapCalloutLink.setElementCssClass("o_sel_create_default_map"); createMapFromTemplateLink = LinkFactory.createLink("create.map.fromTemplate", mapCreateVC, this); + createMapFromTemplateLink.setElementCssClass("o_sel_create_template_map"); String title = translate("create.map"); removeAsListenerAndDispose(mapCreateCalloutCtrl); diff --git a/src/main/java/org/olat/portfolio/ui/artefacts/collect/EPAddArtefactController.java b/src/main/java/org/olat/portfolio/ui/artefacts/collect/EPAddArtefactController.java index 8bbe669802575508f30c03522ca8b814a4620547..b8d4c6d7808ddfe6c53f1c58af022115efe4ba74 100644 --- a/src/main/java/org/olat/portfolio/ui/artefacts/collect/EPAddArtefactController.java +++ b/src/main/java/org/olat/portfolio/ui/artefacts/collect/EPAddArtefactController.java @@ -77,6 +77,7 @@ public class EPAddArtefactController extends BasicController { portfolioModule = (PortfolioModule) CoreSpringFactory.getBean("portfolioModule"); addLinkVC = createVelocityContainer("addLink"); addBtn = LinkFactory.createButton("add.artefact", addLinkVC, this); + addBtn.setElementCssClass("o_sel_add_artfeact"); putInitialPanel(addLinkVC); } @@ -85,15 +86,18 @@ public class EPAddArtefactController extends BasicController { EPArtefactHandler<?> textHandler = portfolioModule.getArtefactHandler(EPTextArtefact.TEXT_ARTEFACT_TYPE); if (textHandler != null && textHandler.isEnabled()) { textBtn = LinkFactory.createLink("add.text.artefact", addPage, this); + textBtn.setElementCssClass("o_sel_add_text_artfeact"); } EPArtefactHandler<?> fileHandler = portfolioModule.getArtefactHandler(FileArtefact.FILE_ARTEFACT_TYPE); if (fileHandler != null && fileHandler.isEnabled()) { uploadBtn = LinkFactory.createLink("add.artefact.upload", addPage, this); + uploadBtn.setElementCssClass("o_sel_add_upload_artfeact"); } EPArtefactHandler<?> liveblogHandler = portfolioModule.getArtefactHandler(LiveBlogArtefact.TYPE); if (liveblogHandler != null && liveblogHandler.isEnabled()) { liveBlogBtn = LinkFactory.createLink("add.artefact.liveblog", addPage, this); liveBlogBtn.setCustomDisplayText(translate("add.artefact.blog")); + liveBlogBtn.setElementCssClass("o_sel_add_liveblog_artfeact"); } importBtn = LinkFactory.createLink("add.artefact.import", addPage, this); // not yet available, for v2 when import/export exists diff --git a/src/main/java/org/olat/portfolio/ui/artefacts/view/EPArtefactViewController.java b/src/main/java/org/olat/portfolio/ui/artefacts/view/EPArtefactViewController.java index d9a06b492f145189dbc03d2971b911ee717c3b07..893c8518c5f5f64623f55dd59c3eedd3ebe7b037 100644 --- a/src/main/java/org/olat/portfolio/ui/artefacts/view/EPArtefactViewController.java +++ b/src/main/java/org/olat/portfolio/ui/artefacts/view/EPArtefactViewController.java @@ -176,6 +176,7 @@ public class EPArtefactViewController extends FormBasicController { protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { if(detailsLinkEnabled && !artefactChooseMode) { detailsLink = uifactory.addFormLink("details.link", formLayout, Link.LINK); + detailsLink.setElementCssClass("o_sel_artefact_details"); } title = uifactory.addInlineTextElement("title", artefact.getTitle(), formLayout, this); diff --git a/src/main/java/org/olat/portfolio/ui/artefacts/view/EPArtefactViewReadOnlyController.java b/src/main/java/org/olat/portfolio/ui/artefacts/view/EPArtefactViewReadOnlyController.java index 215804a7ccce19dc145005b91609dea0f30cb7ed..fc5c93a07f7c48535fae534457f687f2dc612f88 100644 --- a/src/main/java/org/olat/portfolio/ui/artefacts/view/EPArtefactViewReadOnlyController.java +++ b/src/main/java/org/olat/portfolio/ui/artefacts/view/EPArtefactViewReadOnlyController.java @@ -74,6 +74,7 @@ public class EPArtefactViewReadOnlyController extends BasicController { vC.contextPut("authorName", fullName); if (secCallback.canView()){ detailsLink = LinkFactory.createCustomLink("small.details.link", "open", "small.details.link", Link.LINK, vC, this); + detailsLink.setElementCssClass("o_sel_artefact_details"); } ePFMgr = (EPFrontendManager) CoreSpringFactory.getBean("epFrontendManager"); diff --git a/src/main/java/org/olat/portfolio/ui/structel/_content/mapview.html b/src/main/java/org/olat/portfolio/ui/structel/_content/mapview.html index 69f6fb0858d246d228ca5d6c5a7de26bda54a846..c6b09a2fcb011214ffee569cb24ffb5e6881d7f1 100644 --- a/src/main/java/org/olat/portfolio/ui/structel/_content/mapview.html +++ b/src/main/java/org/olat/portfolio/ui/structel/_content/mapview.html @@ -1,6 +1,6 @@ <div class="b_clearfix"> #if($r.available("map.editButton")) - <div class="b_float_right"> + <div class="b_float_right b_eportfolio_edit_link"> $r.render("map.editButton") </div> #end diff --git a/src/main/java/org/olat/registration/DisclaimerFormController.java b/src/main/java/org/olat/registration/DisclaimerFormController.java index 9dadf17b42c5b05f1e2c9d57d1ab5e71493dbea1..dcaa5fed3d6ddb8784f5b7830ba720d1af829773 100644 --- a/src/main/java/org/olat/registration/DisclaimerFormController.java +++ b/src/main/java/org/olat/registration/DisclaimerFormController.java @@ -101,6 +101,7 @@ public class DisclaimerFormController extends FormBasicController { // Create submit and cancel buttons final FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("buttonLayout", getTranslator()); formLayout.add(buttonLayout); + buttonLayout.setElementCssClass("o_sel_disclaimer_buttons"); uifactory.addFormSubmitButton(DCL_ACCEPT, NLS_DISCLAIMER_OK, buttonLayout); uifactory.addFormCancelButton(NLS_DISCLAIMER_NOK, buttonLayout, ureq, getWindowControl()); } diff --git a/src/main/java/org/olat/repository/RepositoryEntryDetailsFormController.java b/src/main/java/org/olat/repository/RepositoryEntryDetailsFormController.java index d3221a6dd7cd4b6de757c4f67dd282012e0c2032..369ca584dc54ad7926962f0a497d78e7ae5f6a61 100644 --- a/src/main/java/org/olat/repository/RepositoryEntryDetailsFormController.java +++ b/src/main/java/org/olat/repository/RepositoryEntryDetailsFormController.java @@ -101,6 +101,7 @@ public class RepositoryEntryDetailsFormController extends FormBasicController { // FormLayoutContainer buttonContainer = FormLayoutContainer.createButtonLayout("buttonContainer", getTranslator()); formLayout.add("buttonContainer", buttonContainer); + buttonContainer.setElementCssClass("o_sel_repo_save_details"); uifactory.addFormSubmitButton("submit", buttonContainer); if (!isSubWorkflow) { diff --git a/src/main/java/org/olat/repository/SearchForm.java b/src/main/java/org/olat/repository/SearchForm.java index 645841579cc7abd428c2e6080983c42284e6117c..9cd40272c213f328416011411a928d4fd700dd49 100644 --- a/src/main/java/org/olat/repository/SearchForm.java +++ b/src/main/java/org/olat/repository/SearchForm.java @@ -225,25 +225,33 @@ public class SearchForm extends FormBasicController{ setFormTitle("search.generic"); displayName = uifactory.addTextElement("cif_displayname", "cif.displayname", 255, "", formLayout); + displayName.setElementCssClass("o_sel_repo_search_displayname"); displayName.setFocus(true); author = uifactory.addTextElement("cif_author", "cif.author", 255, "", formLayout); + author.setElementCssClass("o_sel_repo_search_author"); if (limitUsername != null) { author.setValue(limitUsername); author.setEnabled(false); } description = uifactory.addTextElement("cif_description", "cif.description", 255, "", formLayout); + description.setElementCssClass("o_sel_repo_search_description"); id = uifactory.addTextElement("cif_id", "cif.id", 12, "", formLayout); + id.setElementCssClass("o_sel_repo_search_id"); id.setVisible(isAdmin); id.setRegexMatchCheck("\\d*", "search.id.format"); typesSelection = uifactory.addCheckboxesVertical("search.limit.type", formLayout, new String[]{"xx"}, new String[]{""}, new String[]{null}, 1); typesSelection.addActionListener(listener, FormEvent.ONCLICK); + typesSelection.setElementCssClass("o_sel_repo_search_type_limit"); + + String[] typeKeys = getResources().toArray(new String[0]); + String[] typeCssClasess = getCssResources(getResources()); + types = uifactory.addCheckboxesVertical("cif_types", "cif.type", formLayout, typeKeys, getTranslatedResources(getResources()), typeCssClasess, 1); + types.setElementCssClass("o_sel_repo_search_types"); - types = uifactory.addCheckboxesVertical("cif_types", "cif.type", formLayout, getResources().toArray(new String[0]), getTranslatedResources(getResources()), null, 1); - FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("button_layout", getTranslator()); formLayout.add(buttonLayout); @@ -269,6 +277,15 @@ public class SearchForm extends FormBasicController{ return l.toArray(new String[0]); } + private String[] getCssResources(List<String> resources) { + String[] cssClasses= new String[resources.size()]; + int count = 0; + for(String key: resources){ + cssClasses[count++] = "o_sel_repo_search_" + key.toLowerCase().replace(".", "_"); + } + return cssClasses; + } + private List<String> getResources() { List<String> resources = new ArrayList<String>(); resources.add(CourseModule.getCourseTypeName()); diff --git a/src/main/java/org/olat/repository/_content/bgrep.html b/src/main/java/org/olat/repository/_content/bgrep.html index 01ba6e3745e5e911c0f2f376ee2dd1f122244d33..a589f441b7199531d803185f34173e79397607c6 100644 --- a/src/main/java/org/olat/repository/_content/bgrep.html +++ b/src/main/java/org/olat/repository/_content/bgrep.html @@ -1,3 +1,5 @@ +<div class="o_sel_edit_repositoryentry_popup"> <h4>$r.translate("properties.for", $title)</h4> <br /> -$r.render("descTB") \ No newline at end of file +$r.render("descTB") +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/repository/_content/referencableSearch.html b/src/main/java/org/olat/repository/_content/referencableSearch.html index 8b06b9292c5dea5e879bfbdc30ab158b6fa3c889..42b9cf09080e0d0a2e7dbbca405e86fe43b6b556 100644 --- a/src/main/java/org/olat/repository/_content/referencableSearch.html +++ b/src/main/java/org/olat/repository/_content/referencableSearch.html @@ -1,3 +1,4 @@ +<div class="o_sel_search_referenceable_entries"> <h3>$r.translate("referencableSearch.title")</h3> <p> | $r.render("allEntriesLink") | @@ -14,3 +15,4 @@ <h4>$subtitle</h4> $r.render("searchCtr") </p> +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/repository/controllers/ReferencableEntriesSearchController.java b/src/main/java/org/olat/repository/controllers/ReferencableEntriesSearchController.java index 055c3d1c6095a3bfef0090f19f51f34bb9a74f59..308cf92751b6e15c3e57e3a5998b8d06b6ef8f6f 100644 --- a/src/main/java/org/olat/repository/controllers/ReferencableEntriesSearchController.java +++ b/src/main/java/org/olat/repository/controllers/ReferencableEntriesSearchController.java @@ -125,11 +125,13 @@ public class ReferencableEntriesSearchController extends BasicController { boolean isVisible = isCreateButtonVisible(); if (isVisible) { createRessourceButton = LinkFactory.createButtonSmall("cmd.create.ressource", mainVC, this); + createRessourceButton.setElementCssClass("o_sel_repo_popup_create_resource"); } mainVC.contextPut("hasCreateRessourceButton", new Boolean(isVisible)); isVisible = isImportButtonVisible(); if (isVisible) { importRessourceButton = LinkFactory.createButtonSmall("cmd.import.ressource", mainVC, this); + importRessourceButton.setElementCssClass("o_sel_repo_popup_import_resource"); } mainVC.contextPut("hasImportRessourceButton", new Boolean(isVisible)); diff --git a/src/main/java/org/olat/repository/controllers/RepositoryAddChooseStepsController.java b/src/main/java/org/olat/repository/controllers/RepositoryAddChooseStepsController.java index 222381c1b9bb633bddb7a9814bdbd1e1ca98955d..8d70335bfb117e6ce9c681cbaef8ef29c462f3d0 100644 --- a/src/main/java/org/olat/repository/controllers/RepositoryAddChooseStepsController.java +++ b/src/main/java/org/olat/repository/controllers/RepositoryAddChooseStepsController.java @@ -81,6 +81,7 @@ public class RepositoryAddChooseStepsController extends BasicController { chooser = uifactory.addRadiosVertical("csc.label", formLayout, keys, labels); chooser.select(this.keys[0], true); uifactory.addFormSubmitButton("cmd.forward", formLayout); + formLayout.setElementCssClass("o_sel_repo_add_template_forward"); } @Override protected boolean validateFormLogic(UserRequest ureq) { return chooser.isOneSelected(); } diff --git a/src/main/java/org/olat/repository/controllers/RepositoryAddController.java b/src/main/java/org/olat/repository/controllers/RepositoryAddController.java index cb6022c0d80c368ec365e7ce70b2d01d17910b2b..5c6482976c0f2d114a3ea5d8740a8da4c1324685 100644 --- a/src/main/java/org/olat/repository/controllers/RepositoryAddController.java +++ b/src/main/java/org/olat/repository/controllers/RepositoryAddController.java @@ -141,7 +141,9 @@ public class RepositoryAddController extends BasicController { repositoryadd = createVelocityContainer("addDelegate"); cancelButton = LinkFactory.createButton("cmd.cancel", repositoryadd, this); + cancelButton.setElementCssClass("o_sel_repo_add_cancel"); forwardButton = LinkFactory.createButton("cmd.forward", repositoryadd, this); + forwardButton.setElementCssClass("o_sel_repo_add_forward"); String translatedTypeName = null; String typeIntro = null; diff --git a/src/main/java/org/olat/repository/controllers/RepositoryDetailsController.java b/src/main/java/org/olat/repository/controllers/RepositoryDetailsController.java index ae49ea76d1e05b4c85ba0a8e4e88c2581a096b49..a885d97a4fb2b3d8b0108ab2e0d66729d12ba17b 100644 --- a/src/main/java/org/olat/repository/controllers/RepositoryDetailsController.java +++ b/src/main/java/org/olat/repository/controllers/RepositoryDetailsController.java @@ -492,9 +492,9 @@ public class RepositoryDetailsController extends BasicController implements Gene if (isOwner) { if (isNewController) { if(isAuthor) { - detailsToolC.addLink(ACTION_EDIT, translate("details.openeditor"), TOOL_EDIT, null); - detailsToolC.addLink(ACTION_EDITDESC, translate("details.chdesc"), TOOL_CHDESC, null); - detailsToolC.addLink(ACTION_EDITPROP, translate("details.chprop"), TOOL_CHPROP, null); + detailsToolC.addLink(ACTION_EDIT, translate("details.openeditor"), TOOL_EDIT, null, "o_sel_repo_open_editor", false); + detailsToolC.addLink(ACTION_EDITDESC, translate("details.chdesc"), TOOL_CHDESC, null, "o_sel_repo_edit_descritpion", false); + detailsToolC.addLink(ACTION_EDITPROP, translate("details.chprop"), TOOL_CHPROP, null, "o_sel_repor_edit_properties", false); } detailsToolC.addLink(ACTION_ADD_CATALOG, translate("details.catadd"), TOOL_CATALOG, null); diff --git a/src/main/java/org/olat/repository/controllers/RepositoryMainController.java b/src/main/java/org/olat/repository/controllers/RepositoryMainController.java index b0f3ca650746e3191d135456ba42265f6daf08e2..50c2931c20e907e6ee644f841c1f84399954d38f 100644 --- a/src/main/java/org/olat/repository/controllers/RepositoryMainController.java +++ b/src/main/java/org/olat/repository/controllers/RepositoryMainController.java @@ -226,31 +226,31 @@ public class RepositoryMainController extends MainLayoutBasicController implemen //CP, SCORM, Wiki, Podcast, Blog, Test, Questionnaire, Glossary, other formats mainToolC.addHeader(translate("tools.add.header")); - mainToolC.addLink(RepositoryAddController.ACTION_ADD_COURSE, translate("tools.add.course"), RepositoryAddController.ACTION_ADD_COURSE, "o_toolbox_course"); - mainToolC.addLink(RepositoryAddController.ACTION_ADD_CP, translate("tools.add.cp"), RepositoryAddController.ACTION_ADD_CP, "o_toolbox_content"); - mainToolC.addLink(RepositoryAddController.ACTION_ADD_SCORM, translate("tools.add.scorm"), RepositoryAddController.ACTION_ADD_SCORM, "o_toolbox_scorm"); - mainToolC.addLink(RepositoryAddController.ACTION_ADD_WIKI, translate("tools.add.wiki"), RepositoryAddController.ACTION_ADD_WIKI, "o_toolbox_wiki"); - mainToolC.addLink(RepositoryAddController.ACTION_ADD_PODCAST, translate("tools.add.podcast"), RepositoryAddController.ACTION_ADD_PODCAST, "o_toolbox_podcast"); - mainToolC.addLink(RepositoryAddController.ACTION_ADD_BLOG, translate("tools.add.blog"), RepositoryAddController.ACTION_ADD_BLOG, "o_toolbox_blog"); - mainToolC.addLink(RepositoryAddController.ACTION_ADD_TEST, translate("tools.add.test"), RepositoryAddController.ACTION_ADD_TEST, "o_toolbox_test"); - mainToolC.addLink(RepositoryAddController.ACTION_ADD_SURVEY, translate("tools.add.survey"), RepositoryAddController.ACTION_ADD_SURVEY, "o_toolbox_questionnaire"); - mainToolC.addLink(RepositoryAddController.ACTION_ADD_GLOSSARY, translate("tools.add.glossary"), RepositoryAddController.ACTION_ADD_GLOSSARY, "o_toolbox_glossary"); - mainToolC.addLink(RepositoryAddController.ACTION_ADD_DOC, translate("tools.add.webdoc"), RepositoryAddController.ACTION_ADD_DOC, "b_toolbox_doc"); + mainToolC.addLink(RepositoryAddController.ACTION_ADD_COURSE, translate("tools.add.course"), RepositoryAddController.ACTION_ADD_COURSE, "o_toolbox_course o_sel_repo_import_course"); + mainToolC.addLink(RepositoryAddController.ACTION_ADD_CP, translate("tools.add.cp"), RepositoryAddController.ACTION_ADD_CP, "o_toolbox_content o_sel_repo_import_cp"); + mainToolC.addLink(RepositoryAddController.ACTION_ADD_SCORM, translate("tools.add.scorm"), RepositoryAddController.ACTION_ADD_SCORM, "o_toolbox_scorm o_sel_repo_import_scorm"); + mainToolC.addLink(RepositoryAddController.ACTION_ADD_WIKI, translate("tools.add.wiki"), RepositoryAddController.ACTION_ADD_WIKI, "o_toolbox_wiki o_sel_repo_import_wiki"); + mainToolC.addLink(RepositoryAddController.ACTION_ADD_PODCAST, translate("tools.add.podcast"), RepositoryAddController.ACTION_ADD_PODCAST, "o_toolbox_podcast o_sel_repo_import_podcast"); + mainToolC.addLink(RepositoryAddController.ACTION_ADD_BLOG, translate("tools.add.blog"), RepositoryAddController.ACTION_ADD_BLOG, "o_toolbox_blog o_sel_repo_import_blog"); + mainToolC.addLink(RepositoryAddController.ACTION_ADD_TEST, translate("tools.add.test"), RepositoryAddController.ACTION_ADD_TEST, "o_toolbox_test o_sel_repo_import_test"); + mainToolC.addLink(RepositoryAddController.ACTION_ADD_SURVEY, translate("tools.add.survey"), RepositoryAddController.ACTION_ADD_SURVEY, "o_toolbox_questionnaire o_sel_repo_import_questionnaire"); + mainToolC.addLink(RepositoryAddController.ACTION_ADD_GLOSSARY, translate("tools.add.glossary"), RepositoryAddController.ACTION_ADD_GLOSSARY, "o_toolbox_glossary o_sel_repo_import_glossary"); + mainToolC.addLink(RepositoryAddController.ACTION_ADD_DOC, translate("tools.add.webdoc"), RepositoryAddController.ACTION_ADD_DOC, "b_toolbox_doc o_sel_repo_import_doc"); mainToolC.addHeader(translate("tools.new.header")); - mainToolC.addLink(ACTION_NEW_CREATECOURSE, translate("tools.new.createcourse"), ACTION_NEW_CREATECOURSE, "o_toolbox_course"); - mainToolC.addLink(ACTION_NEW_CREATECP, translate("tools.new.createcp"), ACTION_NEW_CREATECP, "o_toolbox_content"); - mainToolC.addLink(ACTION_NEW_WIKI, translate("tools.new.wiki"), ACTION_NEW_WIKI, "o_toolbox_wiki"); - mainToolC.addLink(ACTION_NEW_PODCAST, translate("tools.new.podcast"), ACTION_NEW_PODCAST, "o_toolbox_podcast"); - mainToolC.addLink(ACTION_NEW_BLOG, translate("tools.new.blog"), ACTION_NEW_BLOG, "o_toolbox_blog"); + mainToolC.addLink(ACTION_NEW_CREATECOURSE, translate("tools.new.createcourse"), ACTION_NEW_CREATECOURSE, "o_toolbox_course o_sel_repo_new_course"); + mainToolC.addLink(ACTION_NEW_CREATECP, translate("tools.new.createcp"), ACTION_NEW_CREATECP, "o_toolbox_content o_sel_repo_new_cp"); + mainToolC.addLink(ACTION_NEW_WIKI, translate("tools.new.wiki"), ACTION_NEW_WIKI, "o_toolbox_wiki o_sel_repo_new_wiki"); + mainToolC.addLink(ACTION_NEW_PODCAST, translate("tools.new.podcast"), ACTION_NEW_PODCAST, "o_toolbox_podcast o_sel_repo_new_podcast"); + mainToolC.addLink(ACTION_NEW_BLOG, translate("tools.new.blog"), ACTION_NEW_BLOG, "o_toolbox_blog o_sel_repo_new_blog"); if (portfolioModule.isEnabled()){ - mainToolC.addLink(ACTION_NEW_PORTFOLIO, translate("tools.new.portfolio"), ACTION_NEW_PORTFOLIO, "o_toolbox_portfolio"); + mainToolC.addLink(ACTION_NEW_PORTFOLIO, translate("tools.new.portfolio"), ACTION_NEW_PORTFOLIO, "o_toolbox_portfolio o_sel_repo_new_portfolio"); } - mainToolC.addLink(ACTION_NEW_CREATETEST, translate("tools.new.createtest"), ACTION_NEW_CREATETEST, "o_toolbox_test"); - mainToolC.addLink(ACTION_NEW_CREATESURVEY, translate("tools.new.createsurvey"), ACTION_NEW_CREATESURVEY, "o_toolbox_questionnaire"); + mainToolC.addLink(ACTION_NEW_CREATETEST, translate("tools.new.createtest"), ACTION_NEW_CREATETEST, "o_toolbox_test o_sel_repo_new_test"); + mainToolC.addLink(ACTION_NEW_CREATESURVEY, translate("tools.new.createsurvey"), ACTION_NEW_CREATESURVEY, "o_toolbox_questionnaire o_sel_repo_new_questionnaire"); mainToolC.addLink(ACTION_NEW_CREATESHAREDFOLDER, translate("tools.new.createsharedfolder"), ACTION_NEW_CREATESHAREDFOLDER, - "o_toolbox_sharedfolder"); - mainToolC.addLink(ACTION_NEW_GLOSSARY, translate("tools.new.glossary"), ACTION_NEW_GLOSSARY, "o_toolbox_glossary"); + "o_toolbox_sharedfolder o_sel_repo_new_sharedfolder"); + mainToolC.addLink(ACTION_NEW_GLOSSARY, translate("tools.new.glossary"), ACTION_NEW_GLOSSARY, "o_toolbox_glossary o_sel_repo_new_glossary"); if (bIsAdmin || isAuthor) { mainToolC.addHeader(translate("tools.administration.header")); if (bIsAdmin) { @@ -266,44 +266,76 @@ public class RepositoryMainController extends MainLayoutBasicController implemen private TreeModel buildTreeModel(boolean bIsAuthor) { GenericTreeModel gtm = new GenericTreeModel(); GenericTreeNode rootNode = new GenericTreeNode(translate("search.home"), "search.home"); + rootNode.setCssClass("o_sel_repo_home"); gtm.setRootNode(rootNode); // TODO:catalog not yet finished : - rootNode.addChild(new GenericTreeNode(translate("search.catalog"), "search.catalog")); + GenericTreeNode node = new GenericTreeNode(translate("search.catalog"), "search.catalog"); + node.setCssClass("o_sel_repo_catalog"); + rootNode.addChild(node); // check if repository portlet is configured in olat_portals.xml boolean repoPortletOn = PortletFactory.containsPortlet("RepositoryPortletStudent"); // add default searches - rootNode.addChild(new GenericTreeNode(translate("search.generic"), "search.generic")); + node = new GenericTreeNode(translate("search.generic"), "search.generic"); + node.setCssClass("o_sel_repo_search_generic"); + rootNode.addChild(node); if (bIsAuthor) { GenericTreeNode myEntriesTn = new GenericTreeNode(translate("search.my"), "search.my"); + myEntriesTn.setCssClass("o_sel_repo_my"); myEntriesNodeId = myEntriesTn.getIdent(); rootNode.addChild(myEntriesTn); } // add repository search also used by portlets if (repoPortletOn) { - rootNode.addChild(new GenericTreeNode(translate("search.mycourses.student"), "search.mycourses.student")); + node = new GenericTreeNode(translate("search.mycourses.student"), "search.mycourses.student"); + node.setCssClass("o_sel_repo_my_student"); + rootNode.addChild(node); // for authors or users with group rights also show the teacher portlet SearchBusinessGroupParams rightParams = new SearchBusinessGroupParams(getIdentity(), true, false); if (bIsAuthor || businessGroupService.countBusinessGroups(rightParams, null) > 0) { - rootNode.addChild(new GenericTreeNode(translate("search.mycourses.teacher"), "search.mycourses.teacher")); + node = new GenericTreeNode(translate("search.mycourses.teacher"), "search.mycourses.teacher"); + node.setCssClass("o_sel_repo_my_teacher"); + rootNode.addChild(node); } } - rootNode.addChild(new GenericTreeNode(translate("search.course"), "search.course")); + node = new GenericTreeNode(translate("search.course"), "search.course"); + node.setCssClass("o_sel_repo_course"); + rootNode.addChild(node); if (bIsAuthor) { //cp, scorm, wiki, podcast, portfolie, test, questionn, resource folder, glossary - rootNode.addChild(new GenericTreeNode(translate("search.cp"), "search.cp")); - rootNode.addChild(new GenericTreeNode(translate("search.scorm"), "search.scorm")); - rootNode.addChild(new GenericTreeNode(translate("search.wiki"), "search.wiki")); - rootNode.addChild(new GenericTreeNode(translate("search.podcast"), "search.podcast" )); - rootNode.addChild(new GenericTreeNode(translate("search.blog"), "search.blog" )); + node = new GenericTreeNode(translate("search.cp"), "search.cp"); + node.setCssClass("o_sel_repo_cp"); + rootNode.addChild(node); + node = new GenericTreeNode(translate("search.scorm"), "search.scorm"); + node.setCssClass("o_sel_repo_scorm"); + rootNode.addChild(node); + node = new GenericTreeNode(translate("search.wiki"), "search.wiki"); + node.setCssClass("o_sel_repo_wiki"); + rootNode.addChild(node); + node = new GenericTreeNode(translate("search.podcast"), "search.podcast" ); + node.setCssClass("o_sel_repo_podcast"); + rootNode.addChild(node); + node = new GenericTreeNode(translate("search.blog"), "search.blog" ); + node.setCssClass("o_sel_repo_blog"); + rootNode.addChild(node); if (portfolioModule.isEnabled()){ - rootNode.addChild(new GenericTreeNode(translate("search.portfolio"), "search.portfolio")); + node = new GenericTreeNode(translate("search.portfolio"), "search.portfolio"); + node.setCssClass("o_sel_repo_portfolio"); + rootNode.addChild(node); } - rootNode.addChild(new GenericTreeNode(translate("search.test"), "search.test")); - rootNode.addChild(new GenericTreeNode(translate("search.survey"), "search.survey")); - rootNode.addChild(new GenericTreeNode(translate("search.sharedfolder"), "search.sharedfolder")); - rootNode.addChild(new GenericTreeNode(translate("search.glossary"), "search.glossary")); + node = new GenericTreeNode(translate("search.test"), "search.test"); + node.setCssClass("o_sel_repo_test"); + rootNode.addChild(node); + node = new GenericTreeNode(translate("search.survey"), "search.survey"); + node.setCssClass("o_sel_repo_survey"); + rootNode.addChild(node); + node = new GenericTreeNode(translate("search.sharedfolder"), "search.sharedfolder"); + node.setCssClass("o_sel_repo_sharefolder"); + rootNode.addChild(node); + node = new GenericTreeNode(translate("search.glossary"), "search.glossary"); + node.setCssClass("o_sel_repo_glossary"); + rootNode.addChild(node); } return gtm; diff --git a/src/main/java/org/olat/restapi/_spring/restApiContext.xml b/src/main/java/org/olat/restapi/_spring/restApiContext.xml index 74cb8213c2b90d0444eac1cc7cd39f07311a56df..838144caad621a6cac4c3cba3e62038e2d59a72a 100644 --- a/src/main/java/org/olat/restapi/_spring/restApiContext.xml +++ b/src/main/java/org/olat/restapi/_spring/restApiContext.xml @@ -5,7 +5,7 @@ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="restModule" class="org.olat.restapi.RestModule"> - <property name="defaultEnabled" value="false"/> + <property name="defaultEnabled" value="${restapi.enable}"/> <property name="coordinator" ref="coordinatorManager" /> <property name="persistedProperties"> <bean class="org.olat.core.configuration.PersistedProperties" scope="prototype" init-method="init" destroy-method="destroy" diff --git a/src/main/java/org/olat/restapi/repository/RepositoryEntriesResource.java b/src/main/java/org/olat/restapi/repository/RepositoryEntriesResource.java index d401ae52c2d128f436c31cbc9e59bfd26c01e4ed..7bab31e4834c7f0b111cd6e6614ef155b49f360d 100644 --- a/src/main/java/org/olat/restapi/repository/RepositoryEntriesResource.java +++ b/src/main/java/org/olat/restapi/repository/RepositoryEntriesResource.java @@ -30,7 +30,6 @@ import static org.olat.restapi.security.RestSecurityHelper.getRoles; import static org.olat.restapi.security.RestSecurityHelper.isAuthor; import java.io.File; -import java.io.InputStream; import java.net.URI; import java.util.ArrayList; import java.util.List; @@ -38,7 +37,6 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; -import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; @@ -62,10 +60,7 @@ import org.olat.core.id.OLATResourceable; import org.olat.core.id.Roles; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; -import org.olat.core.util.CodeHelper; -import org.olat.core.util.FileUtils; import org.olat.core.util.StringHelper; -import org.olat.core.util.WebappHelper; import org.olat.fileresource.FileResourceManager; import org.olat.fileresource.types.FileResource; import org.olat.repository.RepositoryEntry; @@ -75,6 +70,7 @@ import org.olat.resource.OLATResource; import org.olat.resource.OLATResourceManager; import org.olat.restapi.security.RestSecurityHelper; import org.olat.restapi.support.MediaTypeVariants; +import org.olat.restapi.support.MultipartReader; import org.olat.restapi.support.ObjectFactory; import org.olat.restapi.support.vo.RepositoryEntryVO; import org.olat.restapi.support.vo.RepositoryEntryVOes; @@ -280,9 +276,7 @@ public class RepositoryEntriesResource { @PUT @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Consumes({MediaType.MULTIPART_FORM_DATA}) - public Response putResource(@FormParam("filename") String filename, @FormParam("file") InputStream file, - @FormParam("resourcename") String resourcename, @FormParam("displayname") String displayname, - @FormParam("softkey") String softkey, @Context HttpServletRequest request) { + public Response putResource(@Context HttpServletRequest request) { if(!isAuthor(request)) { return Response.serverError().status(Status.UNAUTHORIZED).build(); } @@ -291,13 +285,17 @@ public class RepositoryEntriesResource { long length = 0; try { Identity identity = RestSecurityHelper.getUserRequest(request).getIdentity(); - tmpFile = getTmpFile(filename); - FileUtils.save(file, tmpFile); - FileUtils.closeSafely(file); + MultipartReader partsReader = new MultipartReader(request); + tmpFile = partsReader.getFile(); length = tmpFile.length(); if(length > 0) { - RepositoryEntry re = importFileResource(identity, tmpFile, resourcename, displayname, softkey); + Long accessRaw = partsReader.getLongValue("access"); + int access = accessRaw != null ? accessRaw.intValue() : RepositoryEntry.ACC_OWNERS; + String softkey = partsReader.getValue("softkey"); + String resourcename = partsReader.getValue("resourcename"); + String displayname = partsReader.getValue("displayname"); + RepositoryEntry re = importFileResource(identity, tmpFile, resourcename, displayname, softkey, access); RepositoryEntryVO vo = ObjectFactory.get(re); return Response.ok(vo).build(); } @@ -313,11 +311,11 @@ public class RepositoryEntriesResource { } private RepositoryEntry importFileResource(Identity identity, File fResource, String resourcename, String displayname, - String softkey) { + String softkey, int access) { try { FileResourceManager frm = FileResourceManager.getInstance(); FileResource newResource = frm.addFileResource(fResource, fResource.getName()); - return importResource(identity, newResource, resourcename, displayname, softkey); + return importResource(identity, newResource, resourcename, displayname, softkey, access); } catch(Exception e) { log.error("Fail to import a resource", e); throw new WebApplicationException(e); @@ -325,7 +323,7 @@ public class RepositoryEntriesResource { } public static RepositoryEntry importResource(Identity identity, OLATResourceable newResource, String resourcename, String displayname, - String softkey) { + String softkey, int access) { RepositoryEntry addedEntry = RepositoryManager.getInstance().createRepositoryEntryInstance(identity.getName()); addedEntry.setCanDownload(false); @@ -379,18 +377,15 @@ public class RepositoryEntriesResource { // Do set access for owner at the end, because unfinished course should be // invisible - addedEntry.setAccess(RepositoryEntry.ACC_OWNERS); + if(access < RepositoryEntry.ACC_OWNERS || access > RepositoryEntry.ACC_USERS_GUESTS) { + addedEntry.setAccess(RepositoryEntry.ACC_OWNERS); + } else { + addedEntry.setAccess(access); + } rm.saveRepositoryEntry(addedEntry); return addedEntry; } - private File getTmpFile(String suffix) { - suffix = (suffix == null ? "" : suffix); - File tmpFile = new File(WebappHelper.getUserDataRoot() + "/tmp/", CodeHelper.getGlobalForeverUniqueID() + "_" + suffix); - FileUtils.createEmptyFile(tmpFile); - return tmpFile; - } - @Path("{repoEntryKey}") public RepositoryEntryResource getRepositoryEntryResource() { return new RepositoryEntryResource(); diff --git a/src/main/java/org/olat/user/ChangePasswordForm.java b/src/main/java/org/olat/user/ChangePasswordForm.java index e86bf998a3f9c7e963f21987008fb7efd17a184b..913d9efd114c9597ab543c8f48a01f62873b4c71 100644 --- a/src/main/java/org/olat/user/ChangePasswordForm.java +++ b/src/main/java/org/olat/user/ChangePasswordForm.java @@ -110,13 +110,16 @@ public class ChangePasswordForm extends FormBasicController { @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - oldpass = uifactory.addPasswordElement("oldpass", "form.password.old", 128, "", formLayout); + oldpass.setElementCssClass("o_sel_home_pwd_old"); newpass1 = uifactory.addPasswordElement("newpass1", "form.password.new1", 128, "", formLayout); + newpass1.setElementCssClass("o_sel_home_pwd_new_1"); newpass2 = uifactory.addPasswordElement("newpass2", "form.password.new2", 128, "", formLayout); + newpass2.setElementCssClass("o_sel_home_pwd_new_2"); // Button layout FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("button_layout", getTranslator()); + buttonLayout.setElementCssClass("o_sel_home_pwd_buttons"); formLayout.add(buttonLayout); uifactory.addFormSubmitButton("submit", buttonLayout); uifactory.addFormCancelButton("cancel", buttonLayout, ureq, getWindowControl()); diff --git a/src/main/java/org/olat/user/ChangePrefsController.java b/src/main/java/org/olat/user/ChangePrefsController.java index ab7f1840770003cebafab5170609d4490b321f4a..5468bff64c5c99e0887054f7f0c3f1285081bde7 100644 --- a/src/main/java/org/olat/user/ChangePrefsController.java +++ b/src/main/java/org/olat/user/ChangePrefsController.java @@ -43,12 +43,12 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.media.RedirectMediaResource; import org.olat.core.id.Identity; -import org.olat.core.util.UserSession; import org.olat.core.util.WebappHelper; import org.olat.core.id.User; import org.olat.core.id.context.HistoryManager; import org.olat.core.id.context.HistoryModule; import org.olat.core.util.StringHelper; +import org.olat.core.util.UserSession; import org.olat.core.util.i18n.I18nManager; import org.olat.core.util.prefs.Preferences; import org.olat.core.util.prefs.PreferencesFactory; @@ -241,18 +241,22 @@ class SpecialPrefsForm extends FormBasicController { setFormContextHelp(this.getClass().getPackage().getName(), "home-prefs-special.html", "help.hover.home.prefs.special"); prefsElement = uifactory.addCheckboxesVertical("prefs", "title.prefs.accessibility", formLayout, keys, values, null, 1); + prefsElement.setElementCssClass("o_sel_home_settings_accessibility"); //fxdiff BAKS-7 Resume function HistoryModule historyModule = (HistoryModule)CoreSpringFactory.getBean("historyModule"); if(historyModule.isResumeEnabled()) { resumeElement = uifactory.addRadiosVertical("resume", "resume.label", formLayout, resumeKeys, resumeValues); + resumeElement.setElementCssClass("o_sel_home_settings_resume"); } if(historyModule.isBackEnabled()) { backElement = uifactory.addRadiosVertical("back-enabling", "back.label", formLayout, yesNoKeys, yesNoValues); + backElement.setElementCssClass("o_sel_home_settings_back_enabling"); } update(); final FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("button_layout", getTranslator()); formLayout.add(buttonLayout); + buttonLayout.setElementCssClass("o_sel_home_settings_gui_buttons"); uifactory.addFormSubmitButton("submit", buttonLayout); uifactory.addFormCancelButton("cancel", buttonLayout, ureq, getWindowControl()); } @@ -326,9 +330,11 @@ class UserPrefsResetForm extends FormBasicController { values = new String[] {translate("reset.elements.guiprefs"), translate("reset.elements.sysprefs"), translate("reset.elements.resume")}; resetElements = uifactory.addCheckboxesVertical("prefs", "reset.elements", formLayout, keys, values, null, 1); + resetElements.setElementCssClass("o_sel_home_settings_reset_sysprefs"); final FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("button_layout", getTranslator()); formLayout.add(buttonLayout); + buttonLayout.setElementCssClass("o_sel_home_settings_reset_sysprefs_buttons"); uifactory.addFormSubmitButton("reset.submit", buttonLayout); } diff --git a/src/main/java/org/olat/user/PreferencesFormController.java b/src/main/java/org/olat/user/PreferencesFormController.java index 0a95d921153378be95cb7d99b576017bbbf97d64..5be5c99e37a8353b289fb9e1a1668795f462fdb6 100644 --- a/src/main/java/org/olat/user/PreferencesFormController.java +++ b/src/main/java/org/olat/user/PreferencesFormController.java @@ -141,8 +141,10 @@ public class PreferencesFormController extends FormBasicController { // load preferences Preferences prefs = tobeChangedIdentity.getUser().getPreferences(); + // Username StaticTextElement username = uifactory.addStaticTextElement("form.username", tobeChangedIdentity.getName(), formLayout); + username.setElementCssClass("o_sel_home_settings_username"); username.setEnabled(false); // Language @@ -151,6 +153,7 @@ public class PreferencesFormController extends FormBasicController { String[] langValues = StringHelper.getMapValuesAsStringArray(languages); ArrayHelper.sort(langKeys, langValues, false, true, false); language = uifactory.addDropdownSingleselect("form.language", formLayout, langKeys, langValues, null); + language.setElementCssClass("o_sel_home_settings_language"); String langKey = prefs.getLanguage(); // Preselect the users language if available. Maye not anymore enabled on // this server @@ -170,6 +173,7 @@ public class PreferencesFormController extends FormBasicController { translate("form.fontsize.presentation") }; fontsize = uifactory.addDropdownSingleselect("form.fontsize", formLayout, cssFontsizeKeys, cssFontsizeValues, null); + fontsize.setElementCssClass("o_sel_home_settings_fontsize"); fontsize.select(prefs.getFontsize(), true); fontsize.addActionListener(this, FormEvent.ONCHANGE); @@ -185,6 +189,7 @@ public class PreferencesFormController extends FormBasicController { intervalValues[i] = translate(i18nPrefix + intervalKeys[i]); } notificationInterval = uifactory.addDropdownSingleselect("form.notification", formLayout, intervalKeys, intervalValues, null); + notificationInterval.setElementCssClass("o_sel_home_settings_notification_interval"); notificationInterval.select(prefs.getNotificationInterval(), true); } //fxdiff VCRP-16: intern mail system @@ -193,6 +198,7 @@ public class PreferencesFormController extends FormBasicController { String userEmail = tobeChangedIdentity.getUser().getProperty(UserConstants.EMAIL, getLocale()); String[] mailInternLabels = new String[] { translate("mail." + mailIntern[0], userEmail), translate("mail." + mailIntern[1], userEmail) }; mailSystem = uifactory.addRadiosVertical("mail-system", "mail.system", formLayout, mailIntern, mailInternLabels); + mailSystem.setElementCssClass("o_sel_home_settings_mail"); String mailPrefs = prefs.getReceiveRealMail(); if(StringHelper.containsNonWhitespace(mailPrefs)) { @@ -213,11 +219,13 @@ public class PreferencesFormController extends FormBasicController { String currentCharset = UserManager.getInstance().getUserCharset(tobeChangedIdentity); String[] csKeys = StringHelper.getMapKeysAsStringArray(charsets); charset = uifactory.addDropdownSingleselect("form.charset", formLayout, csKeys, csKeys, null); + charset.setElementCssClass("o_sel_home_settings_charset"); charset.select(currentCharset, true); // Submit and cancel buttons final FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("button_layout", getTranslator()); formLayout.add(buttonLayout); + buttonLayout.setElementCssClass("o_sel_home_settings_prefs_buttons"); uifactory.addFormSubmitButton("submit", buttonLayout); uifactory.addFormCancelButton("cancel", buttonLayout, ureq, getWindowControl()); } diff --git a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml index 6717f3cbc7547da5b97dbf716d215252c5edf24a..981a8413d4d9df89d33883749edf86c3e8c47f60 100644 --- a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml +++ b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml @@ -764,6 +764,7 @@ <!-- fxdiff: FXOLAT-227 user properties used for group-mail-function --> <entry key="org.olat.group.ui.run.BusinessGroupSendToChooserForm"> <bean class="org.olat.user.propertyhandlers.UserPropertyUsageContext"> + <property name="description" value=" " /> <property name="propertyHandlers"> <list> <ref bean="userPropertyLastName" /> diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index 2b0b98b721cd5165f6ec59d4548bcd05b3484376..6a4aa088bd3b76237f019431f685093a29d5027c 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -487,6 +487,14 @@ search.indexing.cronjob=disabled # Example '0 0 18 * * ?' start indexer at 18:00 ever day search.indexing.cronjob.expression=0 0 18 * * ? +######################################################################## +# REST API +######################################################################## + +#enable/disable the rest api +restapi.enable=false +restapi.enable.values=true,values + ######################################################################## # Security ######################################################################## diff --git a/src/test/java/org/olat/course/All_Elements_Course.zip b/src/test/java/org/olat/course/All_Elements_Course.zip new file mode 100644 index 0000000000000000000000000000000000000000..a6f72cfc20f987be4007d9b96390ca7037778453 Binary files /dev/null and b/src/test/java/org/olat/course/All_Elements_Course.zip differ diff --git a/src/test/java/org/olat/course/Empty_Course.zip b/src/test/java/org/olat/course/Empty_Course.zip new file mode 100644 index 0000000000000000000000000000000000000000..f2c9bcf1ac7454d126549302689acf35f7a42edc Binary files /dev/null and b/src/test/java/org/olat/course/Empty_Course.zip differ diff --git a/src/test/java/org/olat/course/FunctionalBackTest.java b/src/test/java/org/olat/course/FunctionalBackTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e2ae3871cab6899425a8ee127d85277650cc9076 --- /dev/null +++ b/src/test/java/org/olat/course/FunctionalBackTest.java @@ -0,0 +1,105 @@ +/** + * <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.course; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.List; + +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.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.olat.restapi.support.vo.CourseVO; +import org.olat.test.ArquillianDeployments; +import org.olat.user.restapi.UserVO; +import org.olat.util.FunctionalCourseUtil; +import org.olat.util.FunctionalHomeSiteUtil; +import org.olat.util.FunctionalRepositorySiteUtil; +import org.olat.util.FunctionalUtil; +import org.olat.util.FunctionalUtil.OlatSite; +import org.olat.util.FunctionalVOUtil; + +import com.thoughtworks.selenium.DefaultSelenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +@RunWith(Arquillian.class) +public class FunctionalBackTest { + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + DefaultSelenium browser; + + @ArquillianResource + URL deploymentUrl; + + FunctionalUtil functionalUtil; + FunctionalVOUtil functionalVOUtil; + FunctionalHomeSiteUtil functionalHomeSiteUtil; + FunctionalRepositorySiteUtil functionalRepositorySiteUtil; + FunctionalCourseUtil functionalCourseUtil; + + UserVO user; + + @Before + public void setup() throws IOException, URISyntaxException{ + functionalUtil = new FunctionalUtil(); + functionalUtil.setDeploymentUrl(deploymentUrl.toString()); + + functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword()); + functionalHomeSiteUtil = new FunctionalHomeSiteUtil(functionalUtil); + functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil); + functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil); + + /* create test user with REST */ + List<UserVO> userVO = functionalVOUtil.createTestUsers(deploymentUrl, 1); + + user = userVO.get(0); + } + + @Test + @RunAsClient + public void checkBack() throws URISyntaxException, IOException{ + /* deploy course with rest */ + CourseVO course0 = functionalVOUtil.importAllElementsCourse(deploymentUrl); + CourseVO course1 = functionalVOUtil.importAllElementsCourse(deploymentUrl); + + functionalUtil.login(browser, user.getLogin(), user.getPassword(), true); + + /* start - home site */ + functionalUtil.openSite(browser, OlatSite.HOME); + + //functionalUtil.openSite(browser,) + + //TODO:JK: implement me + } +} diff --git a/src/test/java/org/olat/course/FunctionalCourseTest.java b/src/test/java/org/olat/course/FunctionalCourseTest.java new file mode 100644 index 0000000000000000000000000000000000000000..bb538284e24c3675dc1eb72e9486125dbc07cac7 --- /dev/null +++ b/src/test/java/org/olat/course/FunctionalCourseTest.java @@ -0,0 +1,111 @@ +/** + * <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.course; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +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.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.olat.test.ArquillianDeployments; +import org.olat.util.FunctionalCourseUtil; +import org.olat.util.FunctionalRepositorySiteUtil; +import org.olat.util.FunctionalRepositorySiteUtil.CourseWizardAccess; +import org.olat.util.FunctionalRepositorySiteUtil.CourseWizardElement; +import org.olat.util.FunctionalUtil; +import org.olat.util.FunctionalUtil.OlatSite; + +import com.thoughtworks.selenium.DefaultSelenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +@RunWith(Arquillian.class) +public class FunctionalCourseTest { + + public final static String COURSE_TITLE = "wizard-course"; + public final static String COURSE_DESCRIPTION = "course created by wizard"; + + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + DefaultSelenium browser; + + @ArquillianResource + URL deploymentUrl; + + static FunctionalUtil functionalUtil; + static FunctionalRepositorySiteUtil functionalRepositorySiteUtil; + static FunctionalCourseUtil functionalCourseUtil; + + static boolean initialized = false; + + @Before + public void setup() throws IOException, URISyntaxException{ + if(!initialized){ + functionalUtil = new FunctionalUtil(); + functionalUtil.setDeploymentUrl(deploymentUrl.toString()); + + functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil); + functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil); + + initialized = true; + } + } + + @Test + @RunAsClient + public void checkCreateUsingWizard(){ + /* login */ + Assert.assertTrue(functionalUtil.login(browser, functionalUtil.getUsername(), functionalUtil.getPassword(), true)); + + /* open repository site */ + Assert.assertTrue(functionalUtil.openSite(browser, OlatSite.LEARNING_RESOURCES)); + + /* create course using wizard */ + CourseWizardElement[] elementArray = new CourseWizardElement[]{ + CourseWizardElement.INFO_PAGE, + CourseWizardElement.FORUM, + CourseWizardElement.ENROLLMENT, + CourseWizardElement.DOWNLOAD_FOLDER, + CourseWizardElement.EMAIL}; + + Assert.assertTrue(functionalRepositorySiteUtil.createCourseUsingWizard(browser, COURSE_TITLE, COURSE_DESCRIPTION, + elementArray, null, true, CourseWizardAccess.USERS)); + + /* click each node once */ + for(int i = 0; i < elementArray.length; i++){ + functionalCourseUtil.open(browser, i); + } + } +} diff --git a/src/test/java/org/olat/course/nodes/cp/FunctionalCPTest.java b/src/test/java/org/olat/course/nodes/cp/FunctionalCPTest.java new file mode 100644 index 0000000000000000000000000000000000000000..eaba37bbb98b12081cd82b165e2864f3888a1ae0 --- /dev/null +++ b/src/test/java/org/olat/course/nodes/cp/FunctionalCPTest.java @@ -0,0 +1,109 @@ +/** + * <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.course.nodes.cp; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +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.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.olat.restapi.support.vo.CourseVO; +import org.olat.test.ArquillianDeployments; +import org.olat.util.FunctionalCourseUtil; +import org.olat.util.FunctionalRepositorySiteUtil; +import org.olat.util.FunctionalUtil; +import org.olat.util.FunctionalVOUtil; +import org.olat.util.FunctionalCourseUtil.CourseNodeAlias; + +import com.thoughtworks.selenium.DefaultSelenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +@RunWith(Arquillian.class) +public class FunctionalCPTest { + public final static String CP_LEARNING_CONTENT_SHORT_TITLE = "cp learning content"; + public final static String CP_LEARNING_CONTENT_LONG_TITLE = "test cp learning content"; + public final static String CP_LEARNING_CONTENT_DESCRIPTION = "learning content"; + + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + DefaultSelenium browser; + + @ArquillianResource + URL deploymentUrl; + + static FunctionalUtil functionalUtil; + static FunctionalRepositorySiteUtil functionalRepositorySiteUtil; + static FunctionalCourseUtil functionalCourseUtil; + static FunctionalVOUtil functionalVOUtil; + + static boolean initialized = false; + + @Before + public void setup() throws IOException, URISyntaxException{ + if(!initialized){ + functionalUtil = new FunctionalUtil(); + functionalUtil.setDeploymentUrl(deploymentUrl.toString()); + + functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil); + functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil); + + functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword()); + + initialized = true; + } + } + + @Test + @RunAsClient + public void checkCreate() throws URISyntaxException, IOException{ + CourseVO course = functionalVOUtil.importEmptyCourse(deploymentUrl); + + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser, functionalUtil.getUsername(), functionalUtil.getPassword(), true)); + + /* */ + Assert.assertTrue(functionalRepositorySiteUtil.openCourse(browser, course.getRepoEntryKey())); + Assert.assertTrue(functionalCourseUtil.openCourseEditor(browser)); + + Assert.assertTrue(functionalCourseUtil.createCourseNode(browser, CourseNodeAlias.CP, CP_LEARNING_CONTENT_SHORT_TITLE, CP_LEARNING_CONTENT_LONG_TITLE, CP_LEARNING_CONTENT_DESCRIPTION, 0)); + Assert.assertTrue(functionalCourseUtil.createCPLearningContent(browser, CP_LEARNING_CONTENT_SHORT_TITLE, CP_LEARNING_CONTENT_DESCRIPTION)); + + Assert.assertTrue(functionalCourseUtil.publishEntireCourse(browser, null, null)); + + Assert.assertTrue(functionalCourseUtil.open(browser, course.getRepoEntryKey(), 0)); + } + +} diff --git a/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java b/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0451d3a1bfd0503e4dd5f329f3afb4d6db75b5c3 --- /dev/null +++ b/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java @@ -0,0 +1,113 @@ +/** + * <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.course.nodes.feed; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +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.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.olat.restapi.support.vo.CourseVO; +import org.olat.test.ArquillianDeployments; +import org.olat.util.FunctionalCourseUtil; +import org.olat.util.FunctionalRepositorySiteUtil; +import org.olat.util.FunctionalUtil; +import org.olat.util.FunctionalVOUtil; +import org.olat.util.FunctionalCourseUtil.CourseNodeAlias; + +import com.thoughtworks.selenium.DefaultSelenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +@RunWith(Arquillian.class) +public class FunctionalBlogTest { + + public final static String BLOG_SHORT_TITLE = "blog"; + public final static String BLOG_LONG_TITLE = "test blog"; + public final static String BLOG_DESCRIPTION = "blog"; + public final static String BLOG_FEED = "http://blogs.frentix.com/blogs/frentix/rss.xml"; + + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + DefaultSelenium browser; + + @ArquillianResource + URL deploymentUrl; + + static FunctionalUtil functionalUtil; + static FunctionalRepositorySiteUtil functionalRepositorySiteUtil; + static FunctionalCourseUtil functionalCourseUtil; + static FunctionalVOUtil functionalVOUtil; + + static boolean initialized = false; + + @Before + public void setup() throws IOException, URISyntaxException{ + if(!initialized){ + functionalUtil = new FunctionalUtil(); + functionalUtil.setDeploymentUrl(deploymentUrl.toString()); + + functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil); + functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil); + + functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword()); + + initialized = true; + } + } + + @Test + @RunAsClient + public void checkCreate() throws URISyntaxException, IOException{ + CourseVO course = functionalVOUtil.importEmptyCourse(deploymentUrl); + + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser, functionalUtil.getUsername(), functionalUtil.getPassword(), true)); + + /* */ + Assert.assertTrue(functionalRepositorySiteUtil.openCourse(browser, course.getRepoEntryKey())); + Assert.assertTrue(functionalCourseUtil.openCourseEditor(browser)); + + Assert.assertTrue(functionalCourseUtil.createCourseNode(browser, CourseNodeAlias.BLOG, BLOG_SHORT_TITLE, BLOG_LONG_TITLE, BLOG_DESCRIPTION, 0)); + Assert.assertTrue(functionalCourseUtil.createBlog(browser, BLOG_SHORT_TITLE, BLOG_DESCRIPTION)); + + Assert.assertTrue(functionalCourseUtil.publishEntireCourse(browser, null, null)); + + Assert.assertTrue(functionalCourseUtil.open(browser, course.getRepoEntryKey(), 0)); + Assert.assertTrue(functionalCourseUtil.importBlogFeed(browser, BLOG_FEED)); + + Assert.assertTrue(functionalCourseUtil.open(browser, course.getRepoEntryKey(), 0)); + } +} diff --git a/src/test/java/org/olat/course/nodes/feed/FunctionalPodcastTest.java b/src/test/java/org/olat/course/nodes/feed/FunctionalPodcastTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7ce914d918927dacd849154bf3310bcfcae9a25b --- /dev/null +++ b/src/test/java/org/olat/course/nodes/feed/FunctionalPodcastTest.java @@ -0,0 +1,113 @@ +/** + * <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.course.nodes.feed; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +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.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.olat.restapi.support.vo.CourseVO; +import org.olat.test.ArquillianDeployments; +import org.olat.util.FunctionalCourseUtil; +import org.olat.util.FunctionalRepositorySiteUtil; +import org.olat.util.FunctionalUtil; +import org.olat.util.FunctionalVOUtil; +import org.olat.util.FunctionalCourseUtil.CourseNodeAlias; + +import com.thoughtworks.selenium.DefaultSelenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +@RunWith(Arquillian.class) +public class FunctionalPodcastTest { + + public final static String PODCAST_SHORT_TITLE = "podcast"; + public final static String PODCAST_LONG_TITLE = "test podcast"; + public final static String PODCAST_DESCRIPTION = "podcast"; + public final static String PODCAST_FEED = "http://pod.drs.ch/rock_special_mpx.xml"; + + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + DefaultSelenium browser; + + @ArquillianResource + URL deploymentUrl; + + static FunctionalUtil functionalUtil; + static FunctionalRepositorySiteUtil functionalRepositorySiteUtil; + static FunctionalCourseUtil functionalCourseUtil; + static FunctionalVOUtil functionalVOUtil; + + static boolean initialized = false; + + @Before + public void setup() throws IOException, URISyntaxException{ + if(!initialized){ + functionalUtil = new FunctionalUtil(); + functionalUtil.setDeploymentUrl(deploymentUrl.toString()); + + functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil); + functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil); + + functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword()); + + initialized = true; + } + } + + @Test + @RunAsClient + public void checkCreate() throws URISyntaxException, IOException{ + CourseVO course = functionalVOUtil.importEmptyCourse(deploymentUrl); + + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser, functionalUtil.getUsername(), functionalUtil.getPassword(), true)); + + /* */ + Assert.assertTrue(functionalRepositorySiteUtil.openCourse(browser, course.getRepoEntryKey())); + Assert.assertTrue(functionalCourseUtil.openCourseEditor(browser)); + + Assert.assertTrue(functionalCourseUtil.createCourseNode(browser, CourseNodeAlias.PODCAST, PODCAST_SHORT_TITLE, PODCAST_LONG_TITLE, PODCAST_DESCRIPTION, 0)); + Assert.assertTrue(functionalCourseUtil.createPodcast(browser, PODCAST_SHORT_TITLE, PODCAST_DESCRIPTION)); + + Assert.assertTrue(functionalCourseUtil.publishEntireCourse(browser, null, null)); + + Assert.assertTrue(functionalCourseUtil.open(browser, course.getRepoEntryKey(), 0)); + Assert.assertTrue(functionalCourseUtil.importPodcastFeed(browser, PODCAST_FEED)); + + Assert.assertTrue(functionalCourseUtil.open(browser, course.getRepoEntryKey(), 0)); + } +} diff --git a/src/test/java/org/olat/course/nodes/iq/FunctionalIQTestTest.java b/src/test/java/org/olat/course/nodes/iq/FunctionalIQTestTest.java new file mode 100644 index 0000000000000000000000000000000000000000..39e513f6a9928bf0c5f7b669c8f77f6e8c79e17e --- /dev/null +++ b/src/test/java/org/olat/course/nodes/iq/FunctionalIQTestTest.java @@ -0,0 +1,109 @@ +/** + * <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.course.nodes.iq; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +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.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.olat.restapi.support.vo.CourseVO; +import org.olat.test.ArquillianDeployments; +import org.olat.util.FunctionalCourseUtil; +import org.olat.util.FunctionalCourseUtil.CourseNodeAlias; +import org.olat.util.FunctionalRepositorySiteUtil; +import org.olat.util.FunctionalUtil; +import org.olat.util.FunctionalVOUtil; + +import com.thoughtworks.selenium.DefaultSelenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +@RunWith(Arquillian.class) +public class FunctionalIQTestTest { + + public final static String IQ_TEST_SHORT_TITLE = "Test"; + public final static String IQ_TEST_LONG_TITLE = "Test"; + public final static String IQ_TEST_DESCRIPTION = "test"; + + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + DefaultSelenium browser; + + @ArquillianResource + URL deploymentUrl; + + static FunctionalUtil functionalUtil; + static FunctionalRepositorySiteUtil functionalRepositorySiteUtil; + static FunctionalCourseUtil functionalCourseUtil; + static FunctionalVOUtil functionalVOUtil; + + static boolean initialized = false; + + @Before + public void setup() throws IOException, URISyntaxException{ + if(!initialized){ + functionalUtil = new FunctionalUtil(); + functionalUtil.setDeploymentUrl(deploymentUrl.toString()); + + functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil); + functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil); + + functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword()); + + initialized = true; + } + } + + @Test + @RunAsClient + public void checkCreate() throws URISyntaxException, IOException{ + CourseVO course = functionalVOUtil.importEmptyCourse(deploymentUrl); + + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser, functionalUtil.getUsername(), functionalUtil.getPassword(), true)); + + /* */ + Assert.assertTrue(functionalRepositorySiteUtil.openCourse(browser, course.getRepoEntryKey())); + Assert.assertTrue(functionalCourseUtil.openCourseEditor(browser)); + + Assert.assertTrue(functionalCourseUtil.createCourseNode(browser, CourseNodeAlias.IQ_TEST, IQ_TEST_SHORT_TITLE, IQ_TEST_LONG_TITLE, IQ_TEST_DESCRIPTION, 0)); + Assert.assertTrue(functionalCourseUtil.createQTITest(browser, IQ_TEST_SHORT_TITLE, IQ_TEST_DESCRIPTION)); + + Assert.assertTrue(functionalCourseUtil.publishEntireCourse(browser, null, null)); + + Assert.assertTrue(functionalCourseUtil.open(browser, course.getRepoEntryKey(), 0)); + } +} diff --git a/src/test/java/org/olat/course/nodes/portfolio/FunctionalPortfolioTest.java b/src/test/java/org/olat/course/nodes/portfolio/FunctionalPortfolioTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e7438130058795647832ffc2531aed9e2bbc370c --- /dev/null +++ b/src/test/java/org/olat/course/nodes/portfolio/FunctionalPortfolioTest.java @@ -0,0 +1,130 @@ +/** + * <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.course.nodes.portfolio; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +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.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.olat.restapi.support.vo.CourseVO; +import org.olat.test.ArquillianDeployments; +import org.olat.util.FunctionalCourseUtil; +import org.olat.util.FunctionalEPortfolioUtil; +import org.olat.util.FunctionalHomeSiteUtil; +import org.olat.util.FunctionalRepositorySiteUtil; +import org.olat.util.FunctionalUtil; +import org.olat.util.FunctionalVOUtil; +import org.olat.util.FunctionalCourseUtil.CourseNodeAlias; + +import com.thoughtworks.selenium.DefaultSelenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +@RunWith(Arquillian.class) +public class FunctionalPortfolioTest { + + public final static String PORTFOLIO_TEMPLATE_SHORT_TITLE = "portfolio template"; + public final static String PORTFOLIO_TEMPLATE_LONG_TITLE = "test portfolio template"; + public final static String PORTFOLIO_TEMPLATE_DESCRIPTION = "portfolio template"; + + public final static String PORTFOLIO_BINDER = "portfolio template"; + public final static String PORTFOLIO_PAGE1_OLD_NAME = "New page"; + public final static String PORTFOLIO_PAGE1_NEW_NAME = "page 1"; + + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + DefaultSelenium browser; + + @ArquillianResource + URL deploymentUrl; + + static FunctionalUtil functionalUtil; + static FunctionalHomeSiteUtil functionalHomeSiteUtil; + static FunctionalRepositorySiteUtil functionalRepositorySiteUtil; + static FunctionalCourseUtil functionalCourseUtil; + static FunctionalEPortfolioUtil functionalEPortfolioUtil; + static FunctionalVOUtil functionalVOUtil; + + static boolean initialized = false; + + @Before + public void setup() throws IOException, URISyntaxException{ + if(!initialized){ + functionalUtil = new FunctionalUtil(); + functionalUtil.setDeploymentUrl(deploymentUrl.toString()); + + functionalHomeSiteUtil = new FunctionalHomeSiteUtil(functionalUtil); + functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil); + functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil); + functionalEPortfolioUtil = new FunctionalEPortfolioUtil(functionalUtil, functionalHomeSiteUtil); + + functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword()); + + initialized = true; + } + } + + @Test + @RunAsClient + public void checkCreate() throws URISyntaxException, IOException{ + CourseVO course = functionalVOUtil.importEmptyCourse(deploymentUrl); + + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser, functionalUtil.getUsername(), functionalUtil.getPassword(), true)); + functionalHomeSiteUtil.selectLanguage(browser, FunctionalHomeSiteUtil.ENGLISH_LANGUAGE_VALUE); + Assert.assertTrue(functionalUtil.logout(browser)); + Assert.assertTrue(functionalUtil.login(browser, functionalUtil.getUsername(), functionalUtil.getPassword(), true)); + + /* */ + Assert.assertTrue(functionalRepositorySiteUtil.openCourse(browser, course.getRepoEntryKey())); + Assert.assertTrue(functionalCourseUtil.openCourseEditor(browser)); + + Assert.assertTrue(functionalCourseUtil.createCourseNode(browser, CourseNodeAlias.PORTFOLIO_TASK, PORTFOLIO_TEMPLATE_SHORT_TITLE, PORTFOLIO_TEMPLATE_LONG_TITLE, PORTFOLIO_TEMPLATE_DESCRIPTION, 0)); + Assert.assertTrue(functionalCourseUtil.createPortfolioTask(browser, PORTFOLIO_TEMPLATE_SHORT_TITLE, PORTFOLIO_TEMPLATE_DESCRIPTION)); + + Assert.assertTrue(functionalCourseUtil.openPortfolioTemplateEditor(browser)); + Assert.assertTrue(functionalEPortfolioUtil.openEditor(browser)); + Assert.assertTrue(functionalEPortfolioUtil.renamePage(browser, PORTFOLIO_BINDER, PORTFOLIO_PAGE1_OLD_NAME, PORTFOLIO_PAGE1_NEW_NAME)); + Assert.assertTrue(functionalEPortfolioUtil.createPage(browser, PORTFOLIO_BINDER, null, null, null, false)); + Assert.assertTrue(functionalCourseUtil.closeTab(browser, PORTFOLIO_TEMPLATE_SHORT_TITLE)); + + Assert.assertTrue(functionalRepositorySiteUtil.openCourse(browser, course.getRepoEntryKey())); + Assert.assertTrue(functionalCourseUtil.openCourseEditor(browser)); + Assert.assertTrue(functionalCourseUtil.publishEntireCourse(browser, null, null)); + + Assert.assertTrue(functionalCourseUtil.open(browser, course.getRepoEntryKey(), 0)); + } +} diff --git a/src/test/java/org/olat/course/nodes/wiki/FunctionalWikiTest.java b/src/test/java/org/olat/course/nodes/wiki/FunctionalWikiTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cbdf0a8dd70106d4e084d898b586dbe7e34917ec --- /dev/null +++ b/src/test/java/org/olat/course/nodes/wiki/FunctionalWikiTest.java @@ -0,0 +1,109 @@ +/** + * <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.course.nodes.wiki; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +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.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.olat.restapi.support.vo.CourseVO; +import org.olat.test.ArquillianDeployments; +import org.olat.util.FunctionalCourseUtil; +import org.olat.util.FunctionalRepositorySiteUtil; +import org.olat.util.FunctionalUtil; +import org.olat.util.FunctionalVOUtil; +import org.olat.util.FunctionalCourseUtil.CourseNodeAlias; + +import com.thoughtworks.selenium.DefaultSelenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +@RunWith(Arquillian.class) +public class FunctionalWikiTest { + + public final static String WIKI_SHORT_TITLE = "wiki"; + public final static String WIKI_LONG_TITLE = "test wiki"; + public final static String WIKI_DESCRIPTION = "wiki"; + + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + DefaultSelenium browser; + + @ArquillianResource + URL deploymentUrl; + + static FunctionalUtil functionalUtil; + static FunctionalRepositorySiteUtil functionalRepositorySiteUtil; + static FunctionalCourseUtil functionalCourseUtil; + static FunctionalVOUtil functionalVOUtil; + + static boolean initialized = false; + + @Before + public void setup() throws IOException, URISyntaxException{ + if(!initialized){ + functionalUtil = new FunctionalUtil(); + functionalUtil.setDeploymentUrl(deploymentUrl.toString()); + + functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil); + functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil); + + functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword()); + + initialized = true; + } + } + + @Test + @RunAsClient + public void checkCreate() throws URISyntaxException, IOException{ + CourseVO course = functionalVOUtil.importEmptyCourse(deploymentUrl); + + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser, functionalUtil.getUsername(), functionalUtil.getPassword(), true)); + + /* */ + Assert.assertTrue(functionalRepositorySiteUtil.openCourse(browser, course.getRepoEntryKey())); + Assert.assertTrue(functionalCourseUtil.openCourseEditor(browser)); + + Assert.assertTrue(functionalCourseUtil.createCourseNode(browser, CourseNodeAlias.WIKI, WIKI_SHORT_TITLE, WIKI_LONG_TITLE, WIKI_DESCRIPTION, 0)); + Assert.assertTrue(functionalCourseUtil.createWiki(browser, WIKI_SHORT_TITLE, WIKI_DESCRIPTION)); + + Assert.assertTrue(functionalCourseUtil.publishEntireCourse(browser, null, null)); + + Assert.assertTrue(functionalCourseUtil.open(browser, course.getRepoEntryKey(), 0)); + } +} diff --git a/src/test/java/org/olat/login/FunctionalLoginTest.java b/src/test/java/org/olat/login/FunctionalLoginTest.java index 35e441f8ce9df9647607ba054e3563a5f65c17dc..3c67a8f3dba23b01460ba42f8667915536696708 100644 --- a/src/test/java/org/olat/login/FunctionalLoginTest.java +++ b/src/test/java/org/olat/login/FunctionalLoginTest.java @@ -19,8 +19,20 @@ */ package org.olat.login; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; +import java.util.UUID; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriBuilder; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPut; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.RunAsClient; import org.jboss.arquillian.drone.api.annotation.Drone; @@ -28,9 +40,13 @@ 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.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.olat.restapi.RestConnection; import org.olat.test.ArquillianDeployments; +import org.olat.user.restapi.UserVO; +import org.olat.util.FunctionalUtil; import com.thoughtworks.selenium.DefaultSelenium; @@ -42,18 +58,25 @@ import com.thoughtworks.selenium.DefaultSelenium; */ @RunWith(Arquillian.class) public class FunctionalLoginTest { - - @Deployment(testable = false) - public static WebArchive createDeployment() { - return ArquillianDeployments.createDeployment(); - } - - @Drone - DefaultSelenium browser; - - @ArquillianResource - URL deploymentUrl; - + + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + DefaultSelenium browser; + + @ArquillianResource + URL deploymentUrl; + + FunctionalUtil functionalUtil; + + @Before + public void setup(){ + functionalUtil = new FunctionalUtil(); + } + @Test @RunAsClient public void loadIndex() { @@ -62,7 +85,7 @@ public class FunctionalLoginTest { boolean isLoginFormPresent = browser.isElementPresent("xpath=//div[@class='o_login_form']"); Assert.assertTrue(isLoginFormPresent); } - + @Test @RunAsClient public void loadLogin() { @@ -70,19 +93,67 @@ public class FunctionalLoginTest { browser.waitForPageToLoad("5000"); boolean isLoginFormPresent = browser.isElementPresent("xpath=//div[@class='o_login_form']"); Assert.assertTrue(isLoginFormPresent); - + //type the password browser.type("id=o_fiooolat_login_name", "administrator"); - browser.type("id=o_fiooolat_login_pass", "openolat"); - browser.click("id=o_fiooolat_login_button"); - browser.waitForPageToLoad("15000"); - - //check if administrator appears in the footer - boolean loginAs = browser.isElementPresent("xpath=//div[@id='b_footer_user']//i[contains(text(), 'administrator')]"); - if(!loginAs) { - boolean acknowledge = browser.isElementPresent("xpath=//input[@name='acknowledge_checkbox']"); - Assert.assertTrue("Acknowledge first!", acknowledge); - browser.click("name=acknowledge_checkbox"); - } + browser.type("id=o_fiooolat_login_pass", "openolat"); + browser.click("id=o_fiooolat_login_button"); + functionalUtil.waitForPageToLoad(browser); + + //check if administrator appears in the footer + boolean loginAs = browser.isElementPresent("xpath=//div[@id='b_footer_user']//i[contains(text(), 'administrator')]"); + if(!loginAs) { + boolean acknowledge = browser.isElementPresent("xpath=//input[@name='acknowledge_checkbox']"); + Assert.assertTrue("Acknowledge first!", acknowledge); + browser.click("name=acknowledge_checkbox"); + } + } + + @Test + @RunAsClient + public void loginWithRandomUser() throws IOException, URISyntaxException{ + + RestConnection restConnection = new RestConnection(deploymentUrl); + + + Assert.assertTrue(restConnection.login(functionalUtil.getUsername(), functionalUtil.getPassword())); + + UserVO vo = new UserVO(); + String username = UUID.randomUUID().toString(); + vo.setLogin(username); + String password = UUID.randomUUID().toString(); + vo.setPassword(password); + vo.setFirstName("John"); + vo.setLastName("Smith"); + vo.setEmail(username + "@frentix.com"); + vo.putProperty("telOffice", "39847592"); + vo.putProperty("telPrivate", "39847592"); + vo.putProperty("telMobile", "39847592"); + vo.putProperty("gender", "Female");//male or female + vo.putProperty("birthDay", "12/12/2009"); + + + URI request = UriBuilder.fromUri(deploymentUrl.toURI()).path("restapi").path("users").build(); + HttpPut method = restConnection.createPut(request, MediaType.APPLICATION_JSON, true); + restConnection.addJsonEntity(method, vo); + method.addHeader("Accept-Language", "en"); + + HttpResponse response = restConnection.execute(method); + assertTrue(response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201); + InputStream body = response.getEntity().getContent(); + + functionalUtil.setDeploymentUrl(deploymentUrl.toString()); + Assert.assertTrue(functionalUtil.login(browser)); + + + //Identity savedIdent = BaseSecurityManager.getInstance().findIdentityByName(username); doesn't work + + // URI deleteRequest = UriBuilder.fromUri(deploymentUrl.toURI()).path("restapi").path("/users/" + savedIdent.getKey()).build(); + // HttpDelete deleteMethod = restConnection.createDelete(deleteRequest, MediaType.APPLICATION_XML, true); + // HttpResponse deleteResponse = restConnection.execute(deleteMethod); + // assertEquals(200, deleteResponse.getStatusLine().getStatusCode()); + + + restConnection.shutdown(); } } diff --git a/src/test/java/org/olat/login/FunctionalResumeTest.java b/src/test/java/org/olat/login/FunctionalResumeTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7f1a4e71995c5f1050e0fe252d77273ba2bee355 --- /dev/null +++ b/src/test/java/org/olat/login/FunctionalResumeTest.java @@ -0,0 +1,148 @@ +/** + * <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.login; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +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.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.olat.restapi.support.vo.CourseVO; +import org.olat.test.ArquillianDeployments; +import org.olat.util.FunctionalCourseUtil; +import org.olat.util.FunctionalHomeSiteUtil; +import org.olat.util.FunctionalRepositorySiteUtil; +import org.olat.util.FunctionalUtil; +import org.olat.util.FunctionalUtil.OlatSite; +import org.olat.util.FunctionalVOUtil; + +import com.thoughtworks.selenium.DefaultSelenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +@RunWith(Arquillian.class) +public class FunctionalResumeTest { + + + + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + DefaultSelenium browser; + + @ArquillianResource + URL deploymentUrl; + + FunctionalUtil functionalUtil; + FunctionalVOUtil functionalVOUtil; + FunctionalHomeSiteUtil functionalHomeSiteUtil; + FunctionalRepositorySiteUtil functionalRepositorySiteUtil; + FunctionalCourseUtil functionalCourseUtil; + + @Before + public void setup(){ + functionalUtil = new FunctionalUtil(); + functionalUtil.setDeploymentUrl(deploymentUrl.toString()); + + functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword()); + functionalHomeSiteUtil = new FunctionalHomeSiteUtil(functionalUtil); + functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil); + functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil); + } + + @Test + @RunAsClient + public void checkResume() throws IOException, URISyntaxException{ + /* deploy course with rest */ + CourseVO course = functionalVOUtil.importAllElementsCourse(deploymentUrl); + + /* create xpath to check if course is open */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//li[@class='b_nav_tab b_nav_active b_resource_CourseModule']") + .append("//a[@title='") + .append(functionalVOUtil.getAllElementsCourseFilename().substring(0, functionalVOUtil.getAllElementsCourseFilename().indexOf('.'))) + .append("']"); + + String courseXPath = selectorBuffer.toString(); + + /* login */ + Assert.assertTrue(functionalUtil.login(browser)); + + /* enable resume */ + functionalHomeSiteUtil.enableResume(browser); + + /* open course and check if it's open */ + Assert.assertTrue(functionalUtil.openSite(browser, OlatSite.LEARNING_RESOURCES)); + Assert.assertTrue(functionalRepositorySiteUtil.openCourse(browser, course.getRepoEntryKey())); + + /* + * There's a need to click something in the course because + * else it won't open up again after resume. + */ + functionalCourseUtil.openWithoutBusinessPath(browser, course.getRepoEntryKey(), 0); + + Assert.assertTrue(browser.isElementPresent(courseXPath)); + + /* logout */ + Assert.assertTrue(functionalUtil.logout(browser)); + + /* login */ + Assert.assertTrue(functionalUtil.login(browser, false)); + + /* check if we are on open course tab */ + Assert.assertTrue(browser.isElementPresent(courseXPath)); + + /* enable resume on request */ + functionalHomeSiteUtil.enableResumeOnRequest(browser); + + /* + * There's a need to click something in the course because + * else it won't open up again after resume. + */ + functionalCourseUtil.openWithoutBusinessPath(browser, course.getRepoEntryKey(), 4); + + Assert.assertTrue(functionalUtil.logout(browser)); + + /* login without clicking away dialogs */ + Assert.assertTrue(functionalUtil.login(browser, false)); + + /* Yes to resume last session */ + browser.click("xpath=//form//button"); + functionalUtil.waitForPageToLoad(browser); + + /* check if we are on open course tab */ + Assert.assertTrue(browser.isElementPresent(courseXPath)); + } +} diff --git a/src/test/java/org/olat/portal/FunctionalSettingsTest.java b/src/test/java/org/olat/portal/FunctionalSettingsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7f59e59878002917ffd220ff6058c3657bd8e912 --- /dev/null +++ b/src/test/java/org/olat/portal/FunctionalSettingsTest.java @@ -0,0 +1,385 @@ +/** + * <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.portal; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.LinkedHashMap; +import java.util.List; +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.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.olat.test.ArquillianDeployments; +import org.olat.user.restapi.UserVO; +import org.olat.util.FunctionalHomeSiteUtil; +import org.olat.util.FunctionalHomeSiteUtil.SettingsTab; +import org.olat.util.FunctionalLocatorPairsFactory; +import org.olat.util.FunctionalUtil; +import org.olat.util.FunctionalVOUtil; + +import com.thoughtworks.selenium.DefaultSelenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +@RunWith(Arquillian.class) +public class FunctionalSettingsTest { + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + DefaultSelenium browser; + + @ArquillianResource + URL deploymentUrl; + + FunctionalUtil functionalUtil; + FunctionalVOUtil functionalVOUtil; + FunctionalHomeSiteUtil functionalHomeSiteUtil; + + int portalColumnCount; + + @Before + public void setup(){ + functionalUtil = new FunctionalUtil(); + functionalUtil.setDeploymentUrl(deploymentUrl.toString()); + + functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword()); + functionalHomeSiteUtil = new FunctionalHomeSiteUtil(functionalUtil); + + portalColumnCount = 2; + } + + @Test + @RunAsClient + public void checkResetSettings(){ + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser)); + + /* reset settings */ + Assert.assertTrue(functionalHomeSiteUtil.resetSettings(browser)); + } + + @Test + @RunAsClient + public void checkLanguageSettings(){ + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser)); + + /* set language */ + functionalHomeSiteUtil.selectLanguage(browser, FunctionalHomeSiteUtil.GERMAN_LANGUAGE_VALUE); + } + + @Test + @RunAsClient + public void checkDisableResume(){ + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser)); + + /* resume off */ + functionalHomeSiteUtil.disableResume(browser); + } + + @Test + @RunAsClient + public void checkActivatePortlet(){ + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser)); + + /* click configure */ + functionalHomeSiteUtil.beginEditingPortal(browser); + + /* de-/activate portlets */ + if(functionalHomeSiteUtil.deactivatePortlet(browser, functionalHomeSiteUtil.getPortletEffCss())){ + Assert.assertFalse(functionalHomeSiteUtil.checkPortletActive(browser, functionalHomeSiteUtil.getPortletEffCss())); + } + + if(functionalHomeSiteUtil.activatePortlet(browser, functionalHomeSiteUtil.getPortletNotesCss())){ + Assert.assertTrue(functionalHomeSiteUtil.checkPortletActive(browser, functionalHomeSiteUtil.getPortletNotesCss())); + } + + /* end editing portal */ + functionalHomeSiteUtil.endEditingPortal(browser); + } + + @Test + @RunAsClient + public void checkMovePortlet(){ + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser)); + + /* click configure */ + functionalHomeSiteUtil.beginEditingPortal(browser); + + /* move portlets */ + int oldPositionDyk[] = functionalHomeSiteUtil.findPortletPosition(browser, functionalHomeSiteUtil.getPortletDykCss(), portalColumnCount); + + if(functionalHomeSiteUtil.movePortlet(browser, functionalHomeSiteUtil.getPortletDykCss(), FunctionalHomeSiteUtil.Direction.UP)){ + browser.refresh(); + int newPosition[] = functionalHomeSiteUtil.findPortletPosition(browser, functionalHomeSiteUtil.getPortletDykCss(), portalColumnCount); + + Assert.assertEquals(oldPositionDyk[1], newPosition[1] + 1); + } + + int oldPositionNoti[] = functionalHomeSiteUtil.findPortletPosition(browser, functionalHomeSiteUtil.getPortletNotiCss(), portalColumnCount); + + if(functionalHomeSiteUtil.movePortlet(browser, functionalHomeSiteUtil.getPortletNotiCss(), FunctionalHomeSiteUtil.Direction.LEFT)){ + int newPosition[] = functionalHomeSiteUtil.findPortletPosition(browser, functionalHomeSiteUtil.getPortletNotiCss(), portalColumnCount); + + Assert.assertEquals(oldPositionNoti[0] - 1, newPosition[0]); + } + + /* end editing portal */ + functionalHomeSiteUtil.endEditingPortal(browser); + } + + @Test + @RunAsClient + public void checkBrowserBack(){ + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser)); + + functionalHomeSiteUtil.enableBack(browser); + + /* check if settings were applied */ + Assert.assertTrue(functionalUtil.logout(browser)); + Assert.assertTrue(functionalUtil.login(browser)); + + LinkedHashMap<String,String> pages = new LinkedHashMap<String,String>(); + + /* locators as key to click and as value to test for */ + FunctionalLocatorPairsFactory pairsFactory = new FunctionalLocatorPairsFactory(functionalUtil); + pages.put(pairsFactory.getLocatorOfSite(functionalUtil.getOlatSiteHomeCss()), pairsFactory.getApprovalOfSite(functionalUtil.getOlatSiteHomeCss())); + pages.put(pairsFactory.getLocatorOfSite(functionalUtil.getOlatSiteAdministrationCss()), pairsFactory.getApprovalOfSite(functionalUtil.getOlatSiteAdministrationCss())); + pages.put(pairsFactory.getLocatorOfSite(functionalUtil.getOlatSiteGroupAdministrationCss()), pairsFactory.getApprovalOfSite(functionalUtil.getOlatSiteGroupAdministrationCss())); + pages.put(pairsFactory.getLocatorOfSite(functionalUtil.getOlatSiteGroupsCss()), pairsFactory.getApprovalOfSite(functionalUtil.getOlatSiteGroupsCss())); + pages.put(pairsFactory.getLocatorOfSite(functionalUtil.getOlatSiteLearningResourcesCss()), pairsFactory.getApprovalOfSite(functionalUtil.getOlatSiteLearningResourcesCss())); + pages.put(pairsFactory.getLocatorOfSite(functionalUtil.getOlatSiteUserManagementCss()), pairsFactory.getApprovalOfSite(functionalUtil.getOlatSiteUserManagementCss())); + + + /* visit specified pages */ + String[] keys = pages.keySet().toArray(new String[0]); + String[] values = (String[]) pages.values().toArray(new String[0]); + + int i; + + for(i = 0; i < pages.size(); i++){ + browser.click(keys[i]); + + functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToLoadElement(browser, values[i]); + } + + /* test for the appropriate pages */ + i = pages.size() -1; + + Assert.assertTrue(browser.isElementPresent(values[i])); + + i--; + + for(; i >= 0; i--){ + browser.goBack(); + + functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToLoadElement(browser, values[i]); + + Assert.assertTrue(browser.isElementPresent(values[i])); + } + } + + @Test + @RunAsClient + public void checkResetPassword() throws IOException, URISyntaxException{ + /* create test user via REST */ + List<UserVO> userVO = functionalVOUtil.createTestUsers(deploymentUrl, 1); + + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser)); + + /* password test */ + UserVO current = userVO.get(0); + + Assert.assertTrue(functionalUtil.logout(browser)); + Assert.assertTrue(functionalUtil.login(browser, current.getLogin(), current.getPassword(), true)); + + functionalUtil.openSite(browser, FunctionalUtil.OlatSite.HOME); + functionalHomeSiteUtil.openActionByMenuTree(browser, FunctionalHomeSiteUtil.HomeSiteAction.SETTINGS); + + String newPassword = ("passwd_" + 0 + "_" + UUID.randomUUID().toString()).substring(0, 24); + + functionalUtil.openContentTab(browser, SettingsTab.PASSWORD.ordinal()); + functionalUtil.typePassword(browser, functionalHomeSiteUtil.getOldPasswordCss(), current.getPassword()); + functionalUtil.typePassword(browser, functionalHomeSiteUtil.getNewPasswordCss(), newPassword); + functionalUtil.typePassword(browser, functionalHomeSiteUtil.getConfirmPasswordCss(), newPassword); + + functionalUtil.saveForm(browser, 0); + + Assert.assertTrue(functionalUtil.logout(browser)); + Assert.assertTrue(functionalUtil.login(browser, current.getLogin(), newPassword, true)); + } + + + @Test + @RunAsClient + public void checkSettings() throws IOException, URISyntaxException, InterruptedException{ + /* create test user via REST */ + List<UserVO> userVO = functionalVOUtil.createTestUsers(deploymentUrl, 1); + + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser)); + + /* reset settings */ + Assert.assertTrue(functionalHomeSiteUtil.resetSettings(browser)); + Assert.assertTrue(functionalUtil.login(browser)); + + /* set language */ + functionalHomeSiteUtil.selectLanguage(browser, FunctionalHomeSiteUtil.GERMAN_LANGUAGE_VALUE); + + /* resume off */ + functionalHomeSiteUtil.disableResume(browser); + + /* logout */ + Assert.assertTrue(functionalUtil.logout(browser)); + + /* login for test case */ + Assert.assertTrue(functionalUtil.login(browser)); + + /* click configure */ + functionalHomeSiteUtil.beginEditingPortal(browser); + + /* de-/activate portlets */ + if(functionalHomeSiteUtil.deactivatePortlet(browser, functionalHomeSiteUtil.getPortletEffCss())){ + Assert.assertFalse(functionalHomeSiteUtil.checkPortletActive(browser, functionalHomeSiteUtil.getPortletEffCss())); + } + + if(functionalHomeSiteUtil.activatePortlet(browser, functionalHomeSiteUtil.getPortletNotesCss())){ + Assert.assertTrue(functionalHomeSiteUtil.checkPortletActive(browser, functionalHomeSiteUtil.getPortletNotesCss())); + } + + /* move portlets */ + int oldPositionDyk[] = functionalHomeSiteUtil.findPortletPosition(browser, functionalHomeSiteUtil.getPortletDykCss(), portalColumnCount); + + if(functionalHomeSiteUtil.movePortlet(browser, functionalHomeSiteUtil.getPortletDykCss(), FunctionalHomeSiteUtil.Direction.UP)){ + browser.refresh(); + int newPosition[] = functionalHomeSiteUtil.findPortletPosition(browser, functionalHomeSiteUtil.getPortletDykCss(), portalColumnCount); + + Assert.assertEquals(oldPositionDyk[1], newPosition[1] + 1); + } + + int oldPositionNoti[] = functionalHomeSiteUtil.findPortletPosition(browser, functionalHomeSiteUtil.getPortletNotiCss(), portalColumnCount); + + if(functionalHomeSiteUtil.movePortlet(browser, functionalHomeSiteUtil.getPortletNotiCss(), FunctionalHomeSiteUtil.Direction.LEFT)){ + int newPosition[] = functionalHomeSiteUtil.findPortletPosition(browser, functionalHomeSiteUtil.getPortletNotiCss(), portalColumnCount); + + Assert.assertEquals(oldPositionNoti[0] - 1, newPosition[0]); + } + + /* end editing portal */ + functionalHomeSiteUtil.endEditingPortal(browser); + + /* edit settings */ + functionalHomeSiteUtil.openActionByMenuTree(browser, FunctionalHomeSiteUtil.HomeSiteAction.SETTINGS); + + functionalUtil.openContentTab(browser, SettingsTab.SYSTEM.ordinal()); + + functionalHomeSiteUtil.selectLanguage(browser, FunctionalHomeSiteUtil.ENGLISH_LANGUAGE_VALUE); + + functionalHomeSiteUtil.enableBack(browser); + + /* check if settings were applied */ + Assert.assertTrue(functionalUtil.logout(browser)); + Assert.assertTrue(functionalUtil.login(browser)); + + LinkedHashMap<String,String> pages = new LinkedHashMap<String,String>(); + + /* locators as key to click and as value to test for */ + FunctionalLocatorPairsFactory pairsFactory = new FunctionalLocatorPairsFactory(functionalUtil); + pages.put(pairsFactory.getLocatorOfSite(functionalUtil.getOlatSiteHomeCss()), pairsFactory.getApprovalOfSite(functionalUtil.getOlatSiteHomeCss())); + pages.put(pairsFactory.getLocatorOfSite(functionalUtil.getOlatSiteAdministrationCss()), pairsFactory.getApprovalOfSite(functionalUtil.getOlatSiteAdministrationCss())); + pages.put(pairsFactory.getLocatorOfSite(functionalUtil.getOlatSiteGroupAdministrationCss()), pairsFactory.getApprovalOfSite(functionalUtil.getOlatSiteGroupAdministrationCss())); + pages.put(pairsFactory.getLocatorOfSite(functionalUtil.getOlatSiteGroupsCss()), pairsFactory.getApprovalOfSite(functionalUtil.getOlatSiteGroupsCss())); + pages.put(pairsFactory.getLocatorOfSite(functionalUtil.getOlatSiteLearningResourcesCss()), pairsFactory.getApprovalOfSite(functionalUtil.getOlatSiteLearningResourcesCss())); + pages.put(pairsFactory.getLocatorOfSite(functionalUtil.getOlatSiteUserManagementCss()), pairsFactory.getApprovalOfSite(functionalUtil.getOlatSiteUserManagementCss())); + + + /* visit specified pages */ + String[] keys = pages.keySet().toArray(new String[0]); + String[] values = (String[]) pages.values().toArray(new String[0]); + + int i; + + for(i = 0; i < pages.size(); i++){ + browser.click(keys[i]); + + functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToLoadElement(browser, values[i]); + } + + /* test for the appropriate pages */ + i = pages.size() -1; + + Assert.assertTrue(browser.isElementPresent(values[i])); + + i--; + + for(; i >= 0; i--){ + browser.goBack(); + + functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToLoadElement(browser, values[i]); + + Assert.assertTrue(browser.isElementPresent(values[i])); + } + + /* password test */ + UserVO current = userVO.get(0); + + Assert.assertTrue(functionalUtil.logout(browser)); + Assert.assertTrue(functionalUtil.login(browser, current.getLogin(), current.getPassword(), true)); + + functionalUtil.openSite(browser, FunctionalUtil.OlatSite.HOME); + functionalHomeSiteUtil.openActionByMenuTree(browser, FunctionalHomeSiteUtil.HomeSiteAction.SETTINGS); + + String newPassword = ("passwd_" + 0 + "_" + UUID.randomUUID().toString()).substring(0, 24); + + functionalUtil.openContentTab(browser, SettingsTab.PASSWORD.ordinal()); + functionalUtil.typePassword(browser, functionalHomeSiteUtil.getOldPasswordCss(), current.getPassword()); + functionalUtil.typePassword(browser, functionalHomeSiteUtil.getNewPasswordCss(), newPassword); + functionalUtil.typePassword(browser, functionalHomeSiteUtil.getConfirmPasswordCss(), newPassword); + + functionalUtil.saveForm(browser, 0); + + Assert.assertTrue(functionalUtil.logout(browser)); + Assert.assertTrue(functionalUtil.login(browser, current.getLogin(), newPassword, true)); + } +} diff --git a/src/test/java/org/olat/portfolio/Course_including_Blog.zip b/src/test/java/org/olat/portfolio/Course_including_Blog.zip new file mode 100644 index 0000000000000000000000000000000000000000..62ec56d7e6f1321396de9cc7e58a1a2969ca585e Binary files /dev/null and b/src/test/java/org/olat/portfolio/Course_including_Blog.zip differ diff --git a/src/test/java/org/olat/portfolio/Course_including_Forum.zip b/src/test/java/org/olat/portfolio/Course_including_Forum.zip new file mode 100644 index 0000000000000000000000000000000000000000..9bf5602c46cbfe918cea1fb326886550aba49d3c Binary files /dev/null and b/src/test/java/org/olat/portfolio/Course_including_Forum.zip differ diff --git a/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java b/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java new file mode 100644 index 0000000000000000000000000000000000000000..358c0b6064c1febe3afa85fdc4bbb044540668b8 --- /dev/null +++ b/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java @@ -0,0 +1,468 @@ +/** + * <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.portfolio; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +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.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +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; +import org.olat.util.FunctionalCourseUtil; +import org.olat.util.FunctionalEPortfolioUtil; +import org.olat.util.FunctionalHomeSiteUtil; +import org.olat.util.FunctionalRepositorySiteUtil; +import org.olat.util.FunctionalUtil; +import org.olat.util.FunctionalVOUtil; + +import com.thoughtworks.selenium.DefaultSelenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +@RunWith(Arquillian.class) +public class FunctionalArtefactTest { + + /* content */ + public final static String BINDER_PROGRAMMING_THEORIE = "programming (theorie)"; + public final static String BINDER_PROGRAMMING_SAMPLES = "programming (code samples)"; + + public final static String FORUM_POST_TITLE = "question about multiplexing"; + public final static String FORUM_POST_MESSAGE = "What multiplexing exists in operating systems?"; + public final static String FORUM_ARTEFACT_TITLE = "multiplexing forum post"; + public final static String FORUM_ARTEFACT_DESCRIPTION = "Thread about multiplexing."; + public final static String[] FORUM_TAGS = {"networking", "multiplexing", "operating systems", "virtual machine", "forum", "post"}; + public final static String FORUM_BINDER = BINDER_PROGRAMMING_THEORIE; + public final static String FORUM_PAGE = "operating systems"; + public final static String FORUM_STRUCTURE = "issue 1"; + + public final static String WIKI_ARTICLE_PAGENAME = "Multiplexing"; + public final static String WIKI_ARTICLE_CONTENT = "==Time Multiplexing==\nscheduling a serially-reusable resource among several users\n\n==Space multiplexing==\ndividing a multiple-use resource up among several users"; + public final static String WIKI_ARTEFACT_TITLE = "multiplexing wiki"; + public final static String WIKI_ARTEFACT_DESCRIPTION = "wiki page about multiplexing"; + public final static String[] WIKI_TAGS = {"networking", "multiplexing", "operating systems", "virtual machine", "wiki"}; + public final static String WIKI_BINDER = BINDER_PROGRAMMING_THEORIE; + public final static String WIKI_PAGE = "operating systems"; + public final static String WIKI_STRUCTURE = "issue 2"; + + public final static String BLOG_TITLE = "My Blog"; + public final static String BLOG_DESCRIPTION = "Blog created with Selenium"; + public final static String BLOG_POST_TITLE = "Multiplexing articles"; + public final static String BLOG_POST_DESCRIPTION = "Where you may find useful information about multiplexing."; + public final static String BLOG_POST_CONTENT = "Operating Systems: Design & Implementation (by Andrew S. Tanenbaum)"; + public final static String BLOG_ARTEFACT_TITLE = "blog"; + public final static String BLOG_ARTEFACT_DESCRIPTION = "my personal blog"; + public final static String[] BLOG_TAGS = {"john smith", "blog"}; + public final static String BLOG_BINDER = BINDER_PROGRAMMING_THEORIE; + public final static String BLOG_PAGE = "operating systems"; + public final static String BLOG_STRUCTURE = "issue 3"; + + public final static String TEXT_ARTEFACT_CONTENT = "Bufferbloat is a phenomenon in a packet-switched computer network whereby excess buffering of packets inside the network causes high latency and jitter, as well as reducing the overall network throughput."; + public final static String TEXT_ARTEFACT_TITLE = "Definition bufferbloat"; + public final static String TEXT_ARTEFACT_DESCRIPTION = "Definition bufferbloat"; + public final static String[] TEXT_ARTEFACT_TAGS = {"bufferbloat", "network", "latency", "jitter"}; + public final static String TEXT_ARTEFACT_BINDER = BINDER_PROGRAMMING_THEORIE; + public final static String TEXT_ARTEFACT_PAGE = "networking"; + public final static String TEXT_ARTEFACT_STRUCTURE = "issue 1"; + + public final static String FILE_ARTEFACT_PATH = "/org/olat/portfolio/sfqcodel.cc"; + public final static String FILE_ARTEFACT_TITLE = "CoDel"; + public final static String FILE_ARTEFACT_DESCRIPTION = "CoDel Algorithm"; + public final static String[] FILE_ARTEFACT_TAGS = {"codel", "sample code"}; + public final static String FILE_ARTEFACT_BINDER = BINDER_PROGRAMMING_SAMPLES; + public final static String FILE_ARTEFACT_PAGE = "cpp"; + public final static String FILE_ARTEFACT_STRUCTURE = "issue 1"; + + public final static String LEARNING_JOURNAL_TITLE = "Programming Topics"; + public final static String LEARNING_JOURNAL_DESCRIPTION = "Some hot programming topics"; + public final static String[] LEARNING_JOURNAL_TAGS = {"programming", "c", "c++"}; + public final static String LEARNING_JOURNAL_BINDER = BINDER_PROGRAMMING_THEORIE; + public final static String LEARNING_JOURNAL_PAGE = "journal"; + public final static String LEARNING_JOURNAL_STRUCTURE = "2012/08/13"; + + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ArquillianDeployments.createDeployment(); + } + + @Drone + DefaultSelenium browser; + + @ArquillianResource + URL deploymentUrl; + + static FunctionalUtil functionalUtil; + static FunctionalHomeSiteUtil functionalHomeSiteUtil; + static FunctionalRepositorySiteUtil functionalRepositorySiteUtil; + static FunctionalCourseUtil functionalCourseUtil; + static FunctionalEPortfolioUtil functionalEportfolioUtil; + static FunctionalVOUtil functionalVOUtil; + + static UserVO user; + static List<Binder> map = new ArrayList<Binder>(); + + static boolean initialized = false; + + @Before + public void setup() throws IOException, URISyntaxException{ + if(!initialized){ + functionalUtil = new FunctionalUtil(); + functionalUtil.setDeploymentUrl(deploymentUrl.toString()); + functionalHomeSiteUtil = new FunctionalHomeSiteUtil(functionalUtil); + + functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil); + functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil); + functionalEportfolioUtil = new FunctionalEPortfolioUtil(functionalUtil, functionalHomeSiteUtil); + + functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword()); + + /* create test user with REST */ + List<UserVO> userVO = functionalVOUtil.createTestUsers(deploymentUrl, 1); + + user = userVO.get(0); + + initialized = true; + } + } + + Object[] prepareVerification(String binderName, String binderDescription, + String pageName, String pageDescription, + String structureName, String structureDescription, + String artefactName, String artefactDescription, String[] artefactTags, Object artefactContent){ + Binder binder = findBinderByName(this.map, binderName); + + if(binder == null){ + binder = new Binder(binderName, binderDescription); + this.map.add(binder); + } + + Binder.Page page = findPageByName(binder.page, pageName); + + if(page == null){ + page = binder.new Page(pageName, pageDescription); + binder.page.add(page); + } + + Binder.Page.Structure structure = findStructureByName(page.child, structureName); + + if(structure == null && structureName != null){ + structure = page.new Structure(structureName, structureDescription); + page.child.add(structure); + } + + Binder.Page.Artefact artefact = findArtefactByName(page.child, artefactName); + + if(artefact == null && structure != null){ + artefact = findArtefactByName(structure.child, artefactName); + } + + if(artefact == null){ + artefact = page.new Artefact(artefactName, artefactDescription, artefactTags, artefactContent); + + if(structure != null){ + structure.child.add(artefact); + }else{ + page.child.add(artefact); + } + } + + Object[] retval = new Object[]{binder, page, structure, artefact}; + + return(retval); + } + + Binder findBinderByName(List<Binder> binder, String name){ + if(name == null) + return(null); + + for(Binder current: binder){ + if(name.equals(current.name)){ + return(current); + } + } + + return(null); + } + + Binder.Page findPageByName(List<Binder.Page> page, String name){ + if(name == null) + return(null); + + for(Binder.Page current: page){ + if(name.equals(current.name)){ + return(current); + } + } + + return(null); + } + + Binder.Page.Artefact findArtefactByName(List<?> list, String name){ + if(name == null) + return(null); + + for(Object current: list){ + if(current instanceof Binder.Page.Artefact && name.equals(((Binder.Page.Artefact) current).name)){ + return((Binder.Page.Artefact) current); + } + } + + return(null); + } + + Binder.Page.Structure findStructureByName(List<?> list, String name){ + if(name == null) + return(null); + + for(Object current: list){ + if(current instanceof Binder.Page.Structure && name.equals(((Binder.Page.Structure) current).name)){ + return((Binder.Page.Structure) current); + } + } + + return(null); + } + + boolean checkArtefact(Binder.Page.Artefact artefact){ + + if(!functionalEportfolioUtil.openArtefactDetails(browser, user.getKey(), artefact.name)){ + return(false); + } + + //TODO:JK: implement me + return(true); + } + + boolean checkMap(Binder binder){ + //TODO:JK: implement me + return(true); + } + + @Test + @RunAsClient + public void checkCollectForumPost() throws IOException, URISyntaxException{ + /* + * Prepare for verification + */ + Object[] retval = prepareVerification(FORUM_BINDER, null, + FORUM_PAGE, null, + FORUM_STRUCTURE, null, + FORUM_ARTEFACT_TITLE, FORUM_ARTEFACT_DESCRIPTION, FORUM_TAGS, null); + + Binder binder = (Binder) retval[0]; + Binder.Page page = (Binder.Page) retval[1]; + Binder.Page.Structure structure = (Binder.Page.Structure) retval[2]; + Binder.Page.Artefact artefact = (Binder.Page.Artefact) retval[3]; + + /* + * test case + */ + /* deploy course with REST */ + CourseVO course = functionalVOUtil.importCourseIncludingForum(deploymentUrl); + + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser, user.getLogin(), user.getPassword(), true)); + + /* create binder, page or structure if necessary */ + Assert.assertTrue(functionalEportfolioUtil.createElements(browser, FORUM_BINDER, FORUM_PAGE, FORUM_STRUCTURE)); + + /* post message to forum */ + Assert.assertTrue(functionalCourseUtil.postForumMessage(browser, course.getRepoEntryKey(), 0, FORUM_POST_TITLE, FORUM_POST_MESSAGE)); + + /* add artefact */ + Assert.assertTrue(functionalCourseUtil.addToEportfolio(browser, FORUM_BINDER, FORUM_PAGE, FORUM_STRUCTURE, + FORUM_ARTEFACT_TITLE, FORUM_ARTEFACT_DESCRIPTION, FORUM_TAGS, + functionalEportfolioUtil)); + + /* + * Test for content and make assumptions if the changes were applied. + * Keep it simple use quick access with business paths. + */ + binder.ignore = false; + + page.ignore = false; + + structure.ignore = false; + + //TODO:JK: find a way to retrieve resourceable key + //artefact.content = new String(deploymentUrl.toString() + "/url/RepositoryEntry/" + course.getRepoEntryKey() + "/CourseNode/"); + artefact.ignore = false; + + /* verify */ + Assert.assertTrue(checkArtefact(artefact)); + Assert.assertTrue(checkMap(binder)); + } + + @Test + @RunAsClient + public void checkCollectWikiArticle() throws URISyntaxException, IOException{ + /* import wiki via rest */ + RepositoryEntryVO vo = functionalVOUtil.importWiki(deploymentUrl); + + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser, user.getLogin(), user.getPassword(), true)); + + /* create binder, page or structure if necessary */ + Assert.assertTrue(functionalEportfolioUtil.createElements(browser, WIKI_BINDER, WIKI_PAGE, WIKI_STRUCTURE)); + + /* create an article for the wiki */ + Assert.assertTrue(functionalCourseUtil.createWikiArticle(browser, vo.getKey(), WIKI_ARTICLE_PAGENAME, WIKI_ARTICLE_CONTENT)); + + /* add artefact */ + Assert.assertTrue(functionalCourseUtil.addToEportfolio(browser, WIKI_BINDER, WIKI_PAGE, WIKI_STRUCTURE, + WIKI_ARTEFACT_TITLE, WIKI_ARTEFACT_DESCRIPTION, WIKI_TAGS, + functionalEportfolioUtil)); + } + + @Test + @RunAsClient + public void checkCollectBlogPost() throws URISyntaxException, IOException{ + /* deploy course with REST */ + CourseVO course = functionalVOUtil.importCourseIncludingBlog(deploymentUrl); + + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser, user.getLogin(), user.getPassword(), true)); + + /* create binder, page or structure if necessary */ + Assert.assertTrue(functionalEportfolioUtil.createElements(browser, BLOG_BINDER, BLOG_PAGE, BLOG_STRUCTURE)); + + /* blog */ + Assert.assertTrue(functionalCourseUtil.createBlogEntry(browser, course.getRepoEntryKey(), 0, + BLOG_POST_TITLE, BLOG_POST_DESCRIPTION, BLOG_POST_CONTENT)); + + /* add artefact */ + Assert.assertTrue(functionalCourseUtil.addToEportfolio(browser, BLOG_BINDER, BLOG_PAGE, BLOG_STRUCTURE, + BLOG_ARTEFACT_TITLE, BLOG_ARTEFACT_DESCRIPTION, BLOG_TAGS, + functionalEportfolioUtil)); + } + + @Test + @RunAsClient + public void checkAddTextArtefact(){ + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser, user.getLogin(), user.getPassword(), true)); + + /* add text artefact */ + Assert.assertTrue(functionalEportfolioUtil.addTextArtefact(browser, TEXT_ARTEFACT_BINDER, TEXT_ARTEFACT_PAGE, TEXT_ARTEFACT_STRUCTURE, + TEXT_ARTEFACT_CONTENT, + TEXT_ARTEFACT_TITLE, TEXT_ARTEFACT_DESCRIPTION, + TEXT_ARTEFACT_TAGS)); + } + + @Test + @RunAsClient + public void checkUploadFileArtefact() throws URISyntaxException, MalformedURLException{ + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser, user.getLogin(), user.getPassword(), true)); + + /* upload file artefact */ + Assert.assertTrue(functionalEportfolioUtil.uploadFileArtefact(browser, FILE_ARTEFACT_BINDER, FILE_ARTEFACT_PAGE, FILE_ARTEFACT_STRUCTURE, + FunctionalArtefactTest.class.getResource(FILE_ARTEFACT_PATH).toURI(), + FILE_ARTEFACT_TITLE, FILE_ARTEFACT_DESCRIPTION, + FILE_ARTEFACT_TAGS)); + } + + @Test + @RunAsClient + public void checkCreateLearningJournal(){ + /* login for test setup */ + Assert.assertTrue(functionalUtil.login(browser, user.getLogin(), user.getPassword(), true)); + + /* create learning journal */ + Assert.assertTrue(functionalEportfolioUtil.createLearningJournal(browser, LEARNING_JOURNAL_BINDER, LEARNING_JOURNAL_PAGE, LEARNING_JOURNAL_STRUCTURE, + LEARNING_JOURNAL_TITLE, LEARNING_JOURNAL_DESCRIPTION, + LEARNING_JOURNAL_TAGS)); + + System.out.println(); + } + + /** + * Description:<br/> + * Helper classes to verify interactions with openolat. + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ + class Binder{ + String name; + String description; + List<Page> page = new ArrayList<Page>(); + boolean ignore = true; + + Binder(String name, String description){ + this.name = name; + this.description = description; + } + + class Page{ + String name; + String description; + List child = new ArrayList(); + boolean ignore = true; + + Page(String name, String description){ + this.name = name; + this.description = description; + } + + class Structure{ + String name; + String description; + List<Artefact> child = new ArrayList<Artefact>(); + boolean ignore = true; + + Structure(String name, String description){ + this.name = name; + this.description = description; + } + } + + class Artefact{ + String name; + String description; + String[] tags; + Object content; /* in general a URL but for text artefact a String */ + boolean ignore = true; + + Artefact(String name, String description, String[] tags, Object content){ + this.name = name; + this.description = description; + this.tags = tags; + this.content = content; + } + } + } + } +} diff --git a/src/test/java/org/olat/portfolio/blog.zip b/src/test/java/org/olat/portfolio/blog.zip new file mode 100644 index 0000000000000000000000000000000000000000..faac98707d2b2959672b11c56b4cd6f8f7c9134c Binary files /dev/null and b/src/test/java/org/olat/portfolio/blog.zip differ diff --git a/src/test/java/org/olat/portfolio/sfqcodel.cc b/src/test/java/org/olat/portfolio/sfqcodel.cc new file mode 100644 index 0000000000000000000000000000000000000000..a6d22b3f9f875f69e9ee19dcacb38af1140bd786 --- /dev/null +++ b/src/test/java/org/olat/portfolio/sfqcodel.cc @@ -0,0 +1,494 @@ +/* + * sfqCodel - Smart Flow Queuing, Controlled-Delay Active Queue Management + * with stochastic binning. Inspired by Eric Dumazaet's linux code, FQ_codel. + * This module was put together by Kathleen Nichols. + * For expediency, this originally combined codel.cc and some aspects of + * sfq.cc from the ns2 distribution, contributed by Curtis Villamizar, Feb, 1997. + * Notable differences from Eric's code: this uses packet-by-packet + * round-robining, which we believe to be more appropriate (more testing + * woud be useful), this simply tail drops if the buffer space is full and + * this should be changed to something that drops fullest bin first (as in + * Dumazaet's code), this code keeps an empty bin on the schedule for one + * cycle (effectively preventing a flow from getting to go "first" too + * quickly).. + * Van Jacobson contributed the hash to attempt to model linux kernel hash. + * This is experimental code, for implementation, see Dumazaet's code. + * + * Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com> + * + * Packets are hashed into 256 bins based on header + * Bins each have a separate CoDel manager + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, provided that this notice is retained in full, this + * software may be distributed under the terms of the GNU General + * Public License ("GPL") version 2, in which case the provisions of the + * GPL apply INSTEAD OF those given above. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <math.h> +#include <sys/types.h> +#include "config.h" +#include "template.h" +#include "random.h" +#include "flags.h" +#include "delay.h" +#include "sfqcodel.h" + +static class sfqCoDelClass : public TclClass { + public: + sfqCoDelClass() : TclClass("Queue/sfqCoDel") {} + TclObject* create(int, const char*const*) { + return (new sfqCoDelQueue); + } +} class_codel; + +sfqCoDelQueue::sfqCoDelQueue() : tchan_(0) +{ + bind("interval_", &interval_); + bind("target_", &target_); // target min delay in clock ticks + bind("curq_", &curq_); // current queue size in bytes + bind("d_exp_", &d_exp_); // current delay experienced in clock ticks + for(int i=0; i<MAXBINS; i++) { + bin_[i].q_ = new PacketQueue(); + bin_[i].first_above_time_ = -1; + bin_[i].dropping_ = 0; + bin_[i].count_ = 0; + bin_[i].newflag = 0; + bin_[i].index = i; + bin_[i].on_sched_ = 0; + } + pq_ = bin_[0].q_; //does ns need this? + reset(); +} + +void sfqCoDelQueue::reset() +{ + binsched_ = NULL; + curq_ = 0; + d_exp_ = 0.; + maxpacket_ = 256; + curlen_ = 0; + curq_ = 0; + Queue::reset(); +} + +// Add a new packet to the queue. The packet is dropped if the maximum queue +// size in pkts is exceeded. Otherwise just add a timestamp so dequeue can +// compute the sojourn time (all the work is done in the deque). +// More sophisticated approaches can prevent a single flow from taking over +// a limited buffer. + +void sfqCoDelQueue::enque(Packet* pkt) +{ + // check for tail drop on full buffer + if(curlen_ >= qlim_) { + drop(pkt); + } else { + HDR_CMN(pkt)->ts_ = Scheduler::instance().clock(); + curlen_++; + curq_ += HDR_CMN(pkt)->size(); + + // Determine which bin to enqueue the packet and add it to that bin. + // the bin's id comes from a hash of its header + unsigned int i = hash(pkt) % MAXBINS; + (bin_[i].q_)->enque(pkt); + + //if it's the only bin in use, set binsched_ + if(binsched_ == NULL) { + binsched_ = &(bin_[i]); + bin_[i].prev = &(bin_[i]); + bin_[i].next = bin_[i].prev; + bin_[i].newflag = 1; + bin_[i].on_sched_ = 1; + } else if( bin_[i].on_sched_ == 0) { + //if bin was not on the schedule, add to the list before continuing + // bins but after other new bins + bindesc* b = binsched_; + while(b->newflag == 1) { + if(b->next == binsched_) break; + b = b->next; + } + if(b->next == binsched_) { + //insert at end + b->next = &(bin_[i]); + bin_[i].prev = b; + bin_[i].next = binsched_; + binsched_->prev = &(bin_[i]); + } else { + //insert in front of b + bin_[i].next = b; + bin_[i].prev = b->prev; + (b->prev)->next = &(bin_[i]); + b->prev = &(bin_[i]); + if(b == binsched_) + binsched_ = &(bin_[i]); + } + bin_[i].newflag = 1; + bin_[i].on_sched_ = 1; + } + } +} + +extern "C" { +/* lookup3.c, by Bob Jenkins, May 2006, Public Domain. */ + +//#include <stdint.h> /* defines uint32_t etc */ +//#include <sys/param.h> /* attempt to define endianness */ +//#ifdef linux +//# include <endian.h> /* attempt to define endianness */ +//#endif + +/* + * My best guess at if you are big-endian or little-endian. This may + * need adjustment. + */ +#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ + __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(i386) || defined(__i386__) || defined(__i486__) || \ + defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) +# define HASH_LITTLE_ENDIAN 1 +# define HASH_BIG_ENDIAN 0 +#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ + __BYTE_ORDER == __BIG_ENDIAN) || \ + (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 1 +#else +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 0 +#endif + +#define hashsize(n) ((u_int32_t)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + +static inline u_int32_t jhash_3words( u_int32_t a, u_int32_t b, u_int32_t c, u_int32_t i) { + i += 0xdeadbeef + (3 << 2); + a += i; + b += i; + c += i; + mix(a, b, c); + final(a, b, c); + return c; +} + +#undef mix +#undef final + +} + +unsigned int sfqCoDelQueue::hash(Packet* pkt) +{ + hdr_ip* iph = hdr_ip::access(pkt); + return jhash_3words(iph->daddr(), iph->saddr(), + (iph->dport() << 16) | iph->sport(), 0); +} + +// return the time of the next drop relative to 't' +double sfqCoDelQueue::control_law(double t) +{ + return t + interval_ / sqrt(count_); +} + +// Internal routine to dequeue a packet. All the delay and min tracking +// is done here to make sure it's done consistently on every dequeue. +dodequeResult sfqCoDelQueue::dodeque(PacketQueue* q) +{ + double now = Scheduler::instance().clock(); + dodequeResult r = { NULL, 0 }; + + r.p = q->deque(); + if (r.p == NULL) { + return r; + } else { + // d_exp_ and curq_ are ns2 'traced variables' that allow the dynamic + // queue behavior that drives CoDel to be captured in a trace file for + // diagnostics and analysis. d_exp_ is the sojourn time and curq_ is + // the current total q size in bytes. + d_exp_ = now - HDR_CMN(r.p)->ts_; + curlen_--; + curq_ -= HDR_CMN(r.p)->size_; + if (maxpacket_ < HDR_CMN(r.p)->size_) + // keep track of the max packet size. + maxpacket_ = HDR_CMN(r.p)->size_; + + // To span a large range of bandwidths, CoDel essentially runs two + // different AQMs in parallel. One is sojourn-time-based and takes + // effect when target_ is larger than the time it takes to send a + // TCP MSS packet. The 1st term of the "if" does this. + // The other is backlog-based and takes effect when the time to send an + // MSS packet is >= target_. The goal here is to keep the output link + // utilization high by never allowing the queue to get smaller than + // the amount that arrives in a typical interarrival time (one MSS-sized + // packet arriving spaced by the amount of time it takes to send such + // a packet on the bottleneck). The 2nd term of the "if" does this. + // Note that we use the overall value of curq_, across all bins + if (d_exp_ < target_ || curq_ <= maxpacket_) { + // went below - stay below for at least interval + first_above_time_ = 0; + } else { + if (first_above_time_ == 0) { + //just went above from below. if still above at first_above_time + // will say it’s ok to drop + if ((now - drop_next_) < 8*interval_ && count_ > 1) + first_above_time_ = control_law(now); + else + first_above_time_ = now + interval_; + } else if (now >= first_above_time_) { + r.ok_to_drop = 1; + } + } + } + return r; +} + +// Get the next scheduled bin that has a non-empty queue and return its +// pointer. If it's not binsched_, update binsched_ to be this value. +// A null pointer means there is nothing to send on any bin. + +bindesc* sfqCoDelQueue::readybin() +{ + //get the next scheduled bin that has a non-empty queue, + // set the binsched_ to that bin, + // if none, return NULL + if(binsched_ == NULL) return NULL; + bindesc* b = binsched_; + + while((b->q_)->length() == 0) { + //clean up, remove bin from schedule + if(b->next == b) { + //means this was the only bin on the schedule, so empty the schedule + b->next = NULL; + b->prev = NULL; + b->on_sched_ = 0; + binsched_ = NULL; + return NULL; + } else { + b->on_sched_ = 0; + binsched_ = b->next; + binsched_->prev = b->prev; + (b->prev)->next = binsched_; + b->next = b->prev = NULL; + b = binsched_; + } + } + + return binsched_; +} + +void sfqCoDelQueue::removebin(bindesc* b) { + + while((b->q_)->length() == 0) { + //clean up, remove bin from schedule + if(b->next == b) { + //means this was the only bin on the schedule, so empty the schedule + b->next = NULL; + b->prev = NULL; + b->on_sched_ = 0; + binsched_ = NULL; + return; + } else { + b->on_sched_ = 0; + binsched_ = b->next; + binsched_->prev = b->prev; + (b->prev)->next = binsched_; + b->next = b->prev = NULL; + b = binsched_; + } + } +} + +// All of the work of CoDel is done here. There are two branches: In packet +// dropping state (meaning that the queue sojourn time has gone above target +// and hasn’t come down yet) check if it’s time to leave or if it’s time for +// the next drop(s). If not in dropping state, decide if it’s time to enter it +// and do the initial drop. + +Packet* sfqCoDelQueue::deque() +{ + double now = Scheduler::instance().clock();; + bindesc* b; + dodequeResult r; + + do { + //have to check all bins until find a packet (or there are none) + if( (b = readybin()) == NULL) return NULL; + b->newflag = 0; + first_above_time_ = b->first_above_time_; + drop_next_ = b->drop_next_; + count_ = b->count_; + dropping_ = b->dropping_; + + r = dodeque( b->q_ ); + if(r.p == NULL) printf("sfqCoDelQueue::deque(): error\n"); + + if (dropping_) { + if (! r.ok_to_drop) { + // sojourn time below target - leave dropping state + dropping_ = 0; + } + // It’s time for the next drop. Drop the current packet and dequeue + // the next. If the dequeue doesn't take us out of dropping state, + // schedule the next drop. A large backlog might result in drop + // rates so high that the next drop should happen now, hence the + // ‘while’ loop. + while (now >= drop_next_ && dropping_) { + drop(r.p); + r = dodeque(b->q_); +//in dropping state, drop elderly packets +//while (r.ok_to_drop && d_exp_ > 8*interval_) { +// drop(r.p); +// r = dodeque(b->q_); +//} + //if drop emptied queue, it gets to be new on next arrival + if(r.p == NULL) + removebin(b); + if (! r.ok_to_drop) { + // leave dropping state + dropping_ = 0; + } else { + // schedule the next drop. + ++(count_); + drop_next_ = control_law(drop_next_); + } + } + + // If we get here we’re not in dropping state. 'ok_to_drop' means that the + // sojourn time has been above target for interval so enter dropping state. + } else if (r.ok_to_drop) { + drop(r.p); + r = dodeque(b->q_); + b->newflag = 0; + //if drop emptied queue, it gets to be new on next arrival + if(r.p == NULL) + removebin(b); + dropping_ = 1; + + // If min went above target close to when it last went below, + // assume that the drop rate that controlled the queue on the + // last cycle is a good starting point to control it now. + // Note: didn't put count_ decay line in sfqcodel + count_ = (count_ > 2 && now - drop_next_ < 8*interval_)? count_ - 2 : 1; + drop_next_ = control_law(now); + } + b->count_ = count_; + b->first_above_time_ = first_above_time_; + b->drop_next_ = drop_next_; + b->dropping_ = dropping_; + } while (r.p == NULL) ; + + //if there's a packet to send need to advance bin schedule. If no packet to + // send, means this bin's queue is empty, so advance binsched_. + // so that binsched_ will be next one to send (or NULL) + if(binsched_ != NULL) binsched_ = binsched_->next; + + return (r.p); +} + +int sfqCoDelQueue::command(int argc, const char*const* argv) +{ + Tcl& tcl = Tcl::instance(); + if (argc == 2) { + if (strcmp(argv[1], "reset") == 0) { + reset(); + return (TCL_OK); + } + } else if (argc == 3) { + // attach a file for variable tracing + if (strcmp(argv[1], "attach") == 0) { + int mode; + const char* id = argv[2]; + tchan_ = Tcl_GetChannel(tcl.interp(), (char*)id, &mode); + if (tchan_ == 0) { + tcl.resultf("sfqCoDel trace: can't attach %s for writing", id); + return (TCL_ERROR); + } + return (TCL_OK); + } + // connect CoDel to the underlying queue + if (!strcmp(argv[1], "packetqueue-attach")) { +// delete q_; +// if (!(q_ = (PacketQueue*) TclObject::lookup(argv[2]))) +printf("error in command\n"); + return (TCL_ERROR); +// else { +// pq_ = q_; +// return (TCL_OK); +// } + } + } + return (Queue::command(argc, argv)); +} + +// Routine called by TracedVar facility when variables change values. +// Note that the tracing of each var must be enabled in tcl to work. +void +sfqCoDelQueue::trace(TracedVar* v) +{ + const char *p; + + if (((p = strstr(v->name(), "curq")) == NULL) && + ((p = strstr(v->name(), "d_exp")) == NULL) ) { + fprintf(stderr, "sfqCoDel: unknown trace var %s\n", v->name()); + return; + } + if (tchan_) { + char wrk[500]; + double t = Scheduler::instance().clock(); + if(*p == 'c') { + sprintf(wrk, "c %g %d", t, int(*((TracedInt*) v))); + } else if(*p == 'd') { + sprintf(wrk, "d %g %g %d %g", t, double(*((TracedDouble*) v)), count_, + count_? control_law(0.)*1000.:0.); + } + int n = strlen(wrk); + wrk[n] = '\n'; + wrk[n+1] = 0; + (void)Tcl_Write(tchan_, wrk, n+1); + } +} diff --git a/src/test/java/org/olat/portfolio/wiki.zip b/src/test/java/org/olat/portfolio/wiki.zip new file mode 100644 index 0000000000000000000000000000000000000000..8d750dcfe383b800de4165543656356d35f1f060 Binary files /dev/null and b/src/test/java/org/olat/portfolio/wiki.zip differ diff --git a/src/test/java/org/olat/restapi/RepositoryEntriesTest.java b/src/test/java/org/olat/restapi/RepositoryEntriesTest.java index 98ee5a2333fb940b6b5f3fcea9adb8da03d53a7c..30b5733dfa13f63b9f50b50648c9027a4ac7cbee 100644 --- a/src/test/java/org/olat/restapi/RepositoryEntriesTest.java +++ b/src/test/java/org/olat/restapi/RepositoryEntriesTest.java @@ -144,12 +144,12 @@ public class RepositoryEntriesTest extends OlatJerseyTestCase { URI request = UriBuilder.fromUri(getContextURI()).path("repo/entries").build(); HttpPut method = conn.createPut(request, MediaType.APPLICATION_JSON, true); - method.addHeader("Content-Type", MediaType.MULTIPART_FORM_DATA); MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); entity.addPart("file", new FileBody(cp)); entity.addPart("filename", new StringBody("cp-demo.zip")); entity.addPart("resourcename", new StringBody("CP demo")); entity.addPart("displayname", new StringBody("CP demo")); + entity.addPart("access", new StringBody("3")); method.setEntity(entity); HttpResponse response = conn.execute(method); @@ -163,6 +163,7 @@ public class RepositoryEntriesTest extends OlatJerseyTestCase { assertNotNull(re.getOwnerGroup()); assertNotNull(re.getOlatResource()); assertEquals("CP demo", re.getDisplayname()); + assertEquals(RepositoryEntry.ACC_USERS, re.getAccess()); } @Test @@ -176,7 +177,6 @@ public class RepositoryEntriesTest extends OlatJerseyTestCase { URI request = UriBuilder.fromUri(getContextURI()).path("repo/entries").build(); HttpPut method = conn.createPut(request, MediaType.APPLICATION_JSON, true); - method.addHeader("Content-Type", MediaType.MULTIPART_FORM_DATA); MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); entity.addPart("file", new FileBody(cp)); entity.addPart("filename", new StringBody("qti-demo.zip")); @@ -209,7 +209,6 @@ public class RepositoryEntriesTest extends OlatJerseyTestCase { URI request = UriBuilder.fromUri(getContextURI()).path("repo/entries").build(); HttpPut method = conn.createPut(request, MediaType.APPLICATION_JSON, true); - method.addHeader("Content-Type", MediaType.MULTIPART_FORM_DATA); MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); entity.addPart("file", new FileBody(cp)); entity.addPart("filename", new StringBody("questionnaire-demo.zip")); @@ -241,7 +240,6 @@ public class RepositoryEntriesTest extends OlatJerseyTestCase { assertTrue(conn.login("administrator", "openolat")); URI request = UriBuilder.fromUri(getContextURI()).path("repo/entries").build(); HttpPut method = conn.createPut(request, MediaType.APPLICATION_JSON, true); - method.addHeader("Content-Type", MediaType.MULTIPART_FORM_DATA); MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); entity.addPart("file", new FileBody(cp)); entity.addPart("filename", new StringBody("wiki-demo.zip")); @@ -274,7 +272,6 @@ public class RepositoryEntriesTest extends OlatJerseyTestCase { URI request = UriBuilder.fromUri(getContextURI()).path("repo/entries").build(); HttpPut method = conn.createPut(request, MediaType.APPLICATION_JSON, true); - method.addHeader("Content-Type", MediaType.MULTIPART_FORM_DATA); MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); entity.addPart("file", new FileBody(cp)); entity.addPart("filename", new StringBody("blog-demo.zip")); diff --git a/src/test/java/org/olat/restapi/RestConnection.java b/src/test/java/org/olat/restapi/RestConnection.java index 6fb7f1028ce3618edcb25b5e6c3a0f92ad2c4640..e993a9cb7ab3dc5171779a2084e6693941b1130b 100644 --- a/src/test/java/org/olat/restapi/RestConnection.java +++ b/src/test/java/org/olat/restapi/RestConnection.java @@ -26,6 +26,7 @@ import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import java.util.ArrayList; import java.util.List; @@ -82,7 +83,7 @@ public class RestConnection { private String HOST = "localhost"; private String PROTOCOL = "http"; private String CONTEXT_PATH = "olat"; - + private final DefaultHttpClient httpclient; private static final JsonFactory jsonFactory = new JsonFactory(); @@ -96,6 +97,17 @@ public class RestConnection { //httpclient.setCookieStore(cookieStore); } + + public RestConnection(URL url) { + PORT = url.getPort(); + HOST = url.getHost(); + PROTOCOL = url.getProtocol(); + CONTEXT_PATH = url.getPath(); + + httpclient = new DefaultHttpClient(); + HttpClientParams.setCookiePolicy(httpclient.getParams(), CookiePolicy.RFC_2109); + } + public CookieStore getCookieStore() { return httpclient.getCookieStore(); } @@ -241,8 +253,11 @@ public class RestConnection { * @return http://localhost:9998 */ public UriBuilder getBaseURI() throws URISyntaxException { - URI uri = new URI(PROTOCOL, null, HOST, PORT, null, null, null); - return UriBuilder.fromUri(uri); + URI uri; + + uri = new URI(PROTOCOL, null, HOST, PORT, null, null, null); + + return UriBuilder.fromUri(uri); } /** diff --git a/src/test/java/org/olat/test/Selenium2TestsJunit4.java b/src/test/java/org/olat/test/Selenium2TestsJunit4.java index 40ce87dd5ae6a0f9b5bad3244e29bb4fa0bde129..c7e0091778e8b585887f1f64df182274be1f650e 100644 --- a/src/test/java/org/olat/test/Selenium2TestsJunit4.java +++ b/src/test/java/org/olat/test/Selenium2TestsJunit4.java @@ -28,7 +28,9 @@ import org.junit.runners.Suite; */ @RunWith(Suite.class) @Suite.SuiteClasses({ - org.olat.login.FunctionalLoginTest.class + org.olat.login.FunctionalLoginTest.class, + org.olat.login.FunctionalResumeTest.class, + org.olat.portfolio.FunctionalArtefactTest.class }) public class Selenium2TestsJunit4 { // diff --git a/src/test/java/org/olat/util/EPortfolioTOCStructurePosition.vm b/src/test/java/org/olat/util/EPortfolioTOCStructurePosition.vm new file mode 100644 index 0000000000000000000000000000000000000000..ae980887f2a04c5309450c71b264391e0c69c0c7 --- /dev/null +++ b/src/test/java/org/olat/util/EPortfolioTOCStructurePosition.vm @@ -0,0 +1,38 @@ +position = -1; + +if(document.querySelector){ + var selector = "${tocSelector}"; + var level1 = "${level1}"; + var level2 = "${level2}"; + var page = "${page}"; + var structure = "${structure}"; + + var selection = window.document.evaluate(selector, window.document.body, null, XPathResult.ANY_TYPE, null); + + for(i = 0; i < selection.length; i++){ + var current = selection.item(i); + + if(current.className.indexOf(level1) >= 0){ + var currentPage = window.document.evaluate("//a//span[text()=\'" + page + "\']", current, null, XPathResult.ANY_TYPE, null); + + if(currentPage != null){ + current = selection.item(i + 1); + + for(j = 0; current.className.indexOf(level2) >= 0; j++){ + current = selection.item(i + 1 + j); + + var currentStructure = window.document.evaluate("//a//span[text()=\'" + structure + "\']", current, null, XPathResult.ANY_TYPE, null); + + if(currentStructure != null){ + position = i + 1 + j; + break; + } + } + + break; + } + } + } +} + +position; diff --git a/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java b/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..d6ba9f9776072a2ed77ed57f9e6be2ce0f7eaf3e --- /dev/null +++ b/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java @@ -0,0 +1,62 @@ +/** + * <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.util; + +import com.thoughtworks.selenium.Selenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +public class FunctionalAdministrationSiteUtil { + + public enum AdministrationSiteAction { + SYSTEM_ADMINISTRATION, + ADVANCED_PROPERTIES, + BOOKINGS + } + + private FunctionalUtil functionalUtil; + + public FunctionalAdministrationSiteUtil(FunctionalUtil functionalUtil){ + this.functionalUtil = functionalUtil; + } + + /** + * @param browser + * @param action + * @return true on success otherwise false + * + * Browse the administrations site's navigation. + */ + public boolean openActionByMenuTree(Selenium browser, Object action){ + //TODO:JK: implement me + + return(false); + } + + public FunctionalUtil getFunctionalUtil() { + return functionalUtil; + } + + public void setFunctionalUtil(FunctionalUtil functionalUtil) { + this.functionalUtil = functionalUtil; + } +} diff --git a/src/test/java/org/olat/util/FunctionalCourseUtil.java b/src/test/java/org/olat/util/FunctionalCourseUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..992516cd055af6bfd7c6e0762ae7ec090d9c9385 --- /dev/null +++ b/src/test/java/org/olat/util/FunctionalCourseUtil.java @@ -0,0 +1,1496 @@ +/** + * <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.util; + +import com.thoughtworks.selenium.Selenium; + +/** + * Description: <br> + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +public class FunctionalCourseUtil { + public final static String COURSE_RUN_CSS = "o_course_run"; + public final static String COURSE_OPEN_EDITOR_CSS = "o_sel_course_open_editor"; + + public final static String COURSE_TAB_ACTIVE_CSS = "b_nav_active"; + public final static String COURSE_TAB_CLOSE_CSS = "b_nav_tab_close"; + + public final static String COURSE_EDITOR_PUBLISH_CSS = "b_toolbox_publish"; + public final static String COURSE_EDITOR_PUBLISH_WIZARD_SELECT_ALL_CSS = "o_sel_course_publish_selectall_cbb"; + public final static String COURSE_EDITOR_PUBLISH_WIZARD_ACCESS_ID = "o_fioaccessBox_SELBOX"; + public final static String COURSE_EDITOR_PUBLISH_WIZARD_CATALOG_ID = "o_fiocatalogBox_SELBOX"; + public final static String ADD_TO_CATALOG_YES_VALUE = "yes"; + public final static String ADD_TO_CATALOG_NO_VALUE = "no"; + + public final static String COURSE_EDITOR_INSERT_CONTENT_CSS = "b_toolbox_content"; + public final static String CREATE_COURSE_NODE_TARGET_POSITION_ITEM_CSS = "b_selectiontree_item"; + + public final static String EPORTFOLIO_ADD_CSS = "b_eportfolio_add"; + + public final static String FORUM_ICON_CSS = "o_fo_icon"; + public final static String BLOG_ICON_CSS = "o_blog_icon"; + + public final static String FORUM_TOOLBAR_CSS = "o_forum_toolbar"; + public final static String FORUM_THREAD_NEW_CSS = "o_sel_forum_thread_new"; + public final static String FORUM_ARCHIVE_CSS = "o_sel_forum_archive"; + public final static String FORUM_FILTER_CSS = "o_sel_forum_filter"; + + public final static String WIKI_CREATE_ARTICLE_CSS = "o_sel_wiki_search"; + public final static String WIKI_ARTICLE_BOX_CSS = "o_wikimod-article-box"; + public final static String WIKI_EDIT_FORM_WRAPPER_CSS = "o_wikimod_editform_wrapper"; + + public final static String BLOG_CREATE_ENTRY_CSS = "o_sel_feed_item_new"; + public final static String BLOG_FORM_CSS = "o_sel_blog_form"; + + public final static String TEST_CHOOSE_REPOSITORY_FILE_CSS = "o_sel_test_choose_repofile"; + public final static String CP_CHOOSE_REPOSITORY_FILE_CSS = "o_sel_cp_choose_repofile"; + public final static String WIKI_CHOOSE_REPOSITORY_FILE_CSS = "o_sel_wiki_choose_repofile"; + public final static String FEED_CHOOSE_REPOSITORY_FILE_CSS = "o_sel_feed_choose_repofile"; + public final static String MAP_CHOOSE_REPOSITORY_FILE_CSS = "o_sel_map_choose_repofile"; + + public final static String REPOSITORY_POPUP_CREATE_RESOURCE_CSS = "o_sel_repo_popup_create_resource"; + public final static String REPOSITORY_POPUP_IMPORT_RESOURCE_CSS = "o_sel_repo_popup_import_resource"; + + public final static String MAP_EDIT_CSS = "o_sel_edit_map"; + + public final static String BLOG_NO_POSTS_CSS = "o_blog_no_posts"; + + public final static String PODCAST_NO_EPISODES_CSS = "o_podcast_no_episodes"; + + public enum CourseNodeTab { + TITLE_AND_DESCRIPTION, + VISIBILITY, + ACCESS, + CONTENT; + }; + + public enum VisibilityOption { + BLOCKED_FOR_LEARNERS, + DEPENDING_ON_DATE, + DEPENDING_ON_GROUP, + DEPENDING_ON_ASSESSMENT, + APPLY_TO_OWNERS_AND_TUTORS(DEPENDING_ON_ASSESSMENT); + + private VisibilityOption requires; + + VisibilityOption(){ + this(null); + } + + VisibilityOption(VisibilityOption requires){ + setRequires(requires); + } + + public VisibilityOption getRequires() { + return requires; + } + + public void setRequires(VisibilityOption requires) { + this.requires = requires; + } + }; + + public enum AccessOption { + BLOCKED_FOR_LEARNERS, + DEPENDING_ON_DATE, + DEPENDING_ON_GROUP, + DEPENDING_ON_ASSESSMENT, + APPLY_TO_OWNERS_AND_TUTORS(DEPENDING_ON_ASSESSMENT); + + private AccessOption requires; + + AccessOption(){ + this(null); + } + + AccessOption(AccessOption requires){ + setRequires(requires); + } + + public AccessOption getRequires() { + return requires; + } + + public void setRequires(AccessOption requires) { + this.requires = requires; + } + } + + public enum CourseNodeAlias { + CP("o_cp_icon"), + BLOG("o_blog_icon"), + PODCAST("o_podcast_icon"), + WIKI("o_wiki_icon"), + PORTFOLIO_TASK("o_ep_icon"), + IQ_TEST("o_iqtest_icon"), + IQ_SELFTEST("o_iqself_icon"), + IQ_QUESTIONAIRE("o_iqsurv_icon"); + + private String iconCss; + + CourseNodeAlias(String iconCss){ + setIconCss(iconCss); + } + + public String getIconCss() { + return iconCss; + } + + public void setIconCss(String iconCss) { + this.iconCss = iconCss; + } + } + + public enum AccessSettings { + OWNERS("1"), + OWNERS_AND_AUTHORS("2"), + ALL_REGISTERED_USERS("3"), + REGISTERED_USERS_AND_GUESTS("4"), + MEMBERS_ONLY("membersonly"); + + private String accessValue; + + AccessSettings(String accessValue){ + setAccessValue(accessValue); + } + + public String getAccessValue() { + return accessValue; + } + + public void setAccessValue(String accessValue) { + this.accessValue = accessValue; + } + } + + public enum CourseEditorIQTestTab { + TITLE_AND_DESCRIPTION, + VISIBILITY, + ACCESS, + TEST_CONFIGURATION; + } + + public enum CourseEditorCpTab { + TITLE_AND_DESCRIPTION, + VISIBILITY, + ACCESS, + LEARNING_CONTENT; + } + + public enum CourseEditorWikiTab { + TITLE_AND_DESCRIPTION, + VISIBILITY, + ACCESS, + LEARNING_CONTENT; + } + + public enum CourseEditorBlogTab { + TITLE_AND_DESCRIPTION, + VISIBILITY, + ACCESS, + LEARNING_CONTENT; + } + + public enum CourseEditorPodcastTab { + TITLE_AND_DESCRIPTION, + VISIBILITY, + ACCESS, + LEARNING_CONTENT; + } + + public enum CourseEditorPortfolioTaskTab { + TITLE_AND_DESCRIPTION, + VISIBILITY, + ACCESS, + LEARNING_CONTENT, + ASSESSMENT; + } + + private String courseRunCss; + private String courseOpenEditorCss; + + private String courseTabActiveCss; + private String courseTabCloseCss; + + private String courseEditorPublishCss; + private String courseEditorPublishWizardSelectAllCss; + private String courseEditorPublishWizardAccessId; + private String courseEditorPublishWizardCatalogId; + + private String courseEditorInsertContentCss; + private String createCourseNodeTargetPositionItemCss; + + private String eportfolioAddCss; + + private String forumIconCss; + private String blogIconCss; + + private String forumToolbarCss; + private String forumThreadNewCss; + private String forumArchiveCss; + private String forumFilterCss; + + private String wikiCreateArticleCss; + private String wikiArticleBoxCss; + private String wikiEditFormWrapperCss; + + private String blogCreateEntryCss; + private String blogFormCss; + + private String testChooseRepositoryFileCss; + private String cpChooseRepositoryFileCss; + private String wikiChooseRepositoryFileCss; + private String feedChooseRepositoryFileCss; + private String mapChooseRepositoryFileCss; + + private String repositoryPopupCreateResourceCss; + + private String mapEditCss; + + private String blogNoPostsCss; + private String podcastNoEpisodesCss; + + private FunctionalUtil functionalUtil; + private FunctionalRepositorySiteUtil functionalRepositorySiteUtil; + + public FunctionalCourseUtil(FunctionalUtil functionalUtil, FunctionalRepositorySiteUtil functionalRepositorySiteUtil){ + this.functionalUtil = functionalUtil; + this.functionalRepositorySiteUtil = functionalRepositorySiteUtil; + + setCourseRunCss(COURSE_RUN_CSS); + setCourseOpenEditorCss(COURSE_OPEN_EDITOR_CSS); + + setCourseTabActiveCss(COURSE_TAB_ACTIVE_CSS); + setCourseTabCloseCss(COURSE_TAB_CLOSE_CSS); + + setCourseEditorPublishCss(COURSE_EDITOR_PUBLISH_CSS); + setCourseEditorPublishWizardSelectAllCss(COURSE_EDITOR_PUBLISH_WIZARD_SELECT_ALL_CSS); + setCourseEditorPublishWizardAccessId(COURSE_EDITOR_PUBLISH_WIZARD_ACCESS_ID); + setCourseEditorPublishWizardCatalogId(COURSE_EDITOR_PUBLISH_WIZARD_CATALOG_ID); + + setCourseEditorInsertContentCss(COURSE_EDITOR_INSERT_CONTENT_CSS); + setCreateCourseNodeTargetPositionItemCss(CREATE_COURSE_NODE_TARGET_POSITION_ITEM_CSS); + + setEportfolioAddCss(EPORTFOLIO_ADD_CSS); + + setForumIconCss(FORUM_ICON_CSS); + setBlogIconCss(BLOG_ICON_CSS); + + setForumToolbarCss(FORUM_TOOLBAR_CSS); + setForumThreadNewCss(FORUM_THREAD_NEW_CSS); + setForumArchiveCss(FORUM_ARCHIVE_CSS); + setForumFilterCss(FORUM_FILTER_CSS); + + setWikiCreateArticleCss(WIKI_CREATE_ARTICLE_CSS); + setWikiArticleBoxCss(WIKI_ARTICLE_BOX_CSS); + setWikiEditFormWrapperCss(WIKI_EDIT_FORM_WRAPPER_CSS); + + setBlogCreateEntryCss(BLOG_CREATE_ENTRY_CSS); + setBlogFormCss(BLOG_FORM_CSS); + + setTestChooseRepositoryFileCss(TEST_CHOOSE_REPOSITORY_FILE_CSS); + setCpChooseRepositoryFileCss(CP_CHOOSE_REPOSITORY_FILE_CSS); + setWikiChooseRepositoryFileCss(WIKI_CHOOSE_REPOSITORY_FILE_CSS); + setFeedChooseRepositoryFileCss(FEED_CHOOSE_REPOSITORY_FILE_CSS); + setMapChooseRepositoryFileCss(MAP_CHOOSE_REPOSITORY_FILE_CSS); + + setRepositoryPopupCreateResourceCss(REPOSITORY_POPUP_CREATE_RESOURCE_CSS); + + setMapEditCss(MAP_EDIT_CSS); + + setBlogNoPostsCss(BLOG_NO_POSTS_CSS); + setPodcastNoEpisodesCss(PODCAST_NO_EPISODES_CSS); + } + + /** + * @param browser + * @param courseId + * @param nth + * @return true on success otherwise false + * + * Opens the nth course element within the specified course. + */ + public boolean open(Selenium browser, long courseId, int nth){ + if(!functionalRepositorySiteUtil.openCourse(browser, courseId)) + return(false); + + return(open(browser, nth)); + } + + /** + * @param browser + * @param nth + * @return true on success + * + * Opens the nth course element in the current course. + */ + public boolean open(Selenium browser, int nth){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//ul[contains(@class, 'b_tree_l1')]//li[") + .append(nth + 1) + .append("]//a"); + + browser.click(selectorBuffer.toString()); + + return(true); + } + + /** + * @param browser + * @param courseId + * @param nth + * @return true on success otherwise false + * + * Opens the nth course element within the specified course + * without using business paths. + */ + public boolean openWithoutBusinessPath(Selenium browser, long courseId, int nth){ + if(!functionalRepositorySiteUtil.openCourseWithoutBusinessPath(browser, courseId)) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//ul[contains(@class, 'b_tree_l1')]//li[") + .append(nth + 1) + .append("]//a"); + + browser.click(selectorBuffer.toString()); + + return(true); + } + + /** + * @param browser + * @param title + * @return + */ + public boolean closeTab(Selenium browser, String title){ + StringBuffer stringBuffer = new StringBuffer(); + + stringBuffer.append("xpath=//li//div//a[@title='") + .append(title) + .append("']/../..//a[contains(@class, '") + .append(getCourseTabCloseCss()) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, stringBuffer.toString()); + browser.click(stringBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @return + * + * Closes the active tab. + */ + public boolean closeActiveTab(Selenium browser){ + StringBuffer stringBuffer = new StringBuffer(); + + stringBuffer.append("xpath=//li[contains(@class, '") + .append(getCourseTabActiveCss()) + .append("')]//a[contains(@class, '") + .append(getCourseTabCloseCss()) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, stringBuffer.toString()); + browser.click(stringBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @return true on success + * + * Opens the course editor but the course must be opened. + */ + public boolean openCourseEditor(Selenium browser){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(getCourseOpenEditorCss()) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToUnloadElement(browser, selectorBuffer.toString()); + + return(true); + } + + /** + * @param browser + * @param option + * @param nthForm + * @return true on success + * + * Disables the specified access option, the course editor should be open. + */ + public boolean disableAccessOption(Selenium browser, AccessOption option, int nthForm){ + //TODO:JK: implement me + + return(false); + } + + /** + * @param browser + * @param option + * @param nthForm + * @return true on success + * + * Enables the specified access option, the course editor should be open. + */ + public boolean enableAccessOption(Selenium browser, AccessOption option, int nthForm){ + //TODO:JK: implement me + + return(false); + } + + private String[] createCatalogSelectors(String path){ + //TODO:JK: implement me + + return(null); + } + + public boolean publishEntireCourse(Selenium browser, AccessSettings access, String catalog){ + /* click publish */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(getCourseEditorPublishCss()) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + /* select all course nodes */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(getCourseEditorPublishWizardSelectAllCss()) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + functionalUtil.clickWizardNext(browser); + + /* access options */ + functionalUtil.waitForPageToLoadElement(browser, "id=" + getCourseEditorPublishWizardAccessId()); + + if(access != null){ + functionalUtil.selectOption(browser, getCourseEditorPublishWizardAccessId(), access.getAccessValue()); + } + + functionalUtil.clickWizardNext(browser); + + /* add to catalog or not */ + functionalUtil.waitForPageToLoadElement(browser, "id=" + getCourseEditorPublishWizardCatalogId()); + + if(catalog != null){ + functionalUtil.selectOption(browser, getCourseEditorPublishWizardCatalogId(), ADD_TO_CATALOG_YES_VALUE); + + String[] catalogSelectors = createCatalogSelectors(catalog); + + for(String catalogSelector: catalogSelectors){ + functionalUtil.waitForPageToLoadElement(browser, catalogSelector); + browser.click(catalogSelector); + } + }else{ + functionalUtil.selectOption(browser, getCourseEditorPublishWizardCatalogId(), ADD_TO_CATALOG_NO_VALUE); + } + + functionalUtil.clickWizardFinish(browser); + functionalUtil.waitForPageToUnloadElement(browser, "id=" + getCourseEditorPublishWizardCatalogId()); + + return(true); + } + + /** + * @param browser + * @param node + * @param title + * @param description + * @param position + * @return true on success otherwise false + * + * Creates the specified course node in a opened course editor. + */ + public boolean createCourseNode(Selenium browser, CourseNodeAlias node, String shortTitle, String longTitle, String description, int position){ + /* click on the appropriate link to create node */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getCourseEditorInsertContentCss()) + .append("')]") + .append("//a[contains(@class, '") + .append(node.getIconCss()) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + /* choose insertion point */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, 'b_window')]//form[@name='seltree']//div[contains(@class, '") + .append(getCreateCourseNodeTargetPositionItemCss()) + .append("')]//input[@type='radio'])[") + .append(position + 1) + .append("]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, 'b_window')]//form[@name='seltree']//button[contains(@class, 'b_button_dirty')])[1]"); + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToUnloadElement(browser, selectorBuffer.toString()); + + /* fill in short title */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, 'o_editor')]//form//input[@type='text'])[1]"); + + browser.type(selectorBuffer.toString(), shortTitle); + + /* fill in long title */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, 'o_editor')]//form//input[@type='text'])[2]"); + + browser.type(selectorBuffer.toString(), longTitle); + + /* fill in description */ + functionalUtil.typeMCE(browser, description); + + /* click save */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, 'o_editor')]//form//button)[1]"); + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @return true on success + * + * Adds an artefact to eportfolio by clicking the appropriate + * button. + */ + public boolean addToEportfolio(Selenium browser, String binder, String page, String structure, + String title, String description, String[] tags, + FunctionalEPortfolioUtil functionalEPortfolioUtil){ + + /* open wizard */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(getEportfolioAddCss()) + .append("')]"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + if(binder != null){ + /* fill in wizard - title & description */ + functionalEPortfolioUtil.fillInTitleAndDescription(browser, title, description); + + /* fill in wizard - tags */ + functionalEPortfolioUtil.fillInTags(browser, tags); + + /* fill in wizard - destination */ + String selector = functionalEPortfolioUtil.createSelector(binder, page, structure); + + functionalUtil.waitForPageToLoadElement(browser, selector); + + browser.click(selector); + + /* click finish */ + functionalUtil.clickWizardFinish(browser); + functionalUtil.waitForPageToUnloadElement(browser, selector); + } + + return(true); + } + + /** + * @param browser + * @param courseId + * @param nth forum in the course + * @return true on success, otherwise false + * + * Opens the course with courseId and nth forum within the specified + * course. + */ + public boolean openForum(Selenium browser, long courseId, int nth){ + if(!functionalRepositorySiteUtil.openCourse(browser, courseId)) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//ul//li//a[contains(@class, '") + .append(getForumIconCss()) + .append("')])[") + .append(nth + 1) + .append("]") + .append(""); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param courseId + * @param nthForum + * @param title + * @param message + * @return true on success, otherwise false + * + * Opens the specified forum in the course and posts a new topic. + */ + public boolean postForumMessage(Selenium browser, long courseId, int nthForum, String title, String message){ + if(!openForum(browser, courseId, nthForum)) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + /* click open new topic */ + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getForumToolbarCss()) + .append("')]//a[contains(@class, '") + .append(getForumThreadNewCss()) + .append("')]"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + + /* fill in form - title */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getCourseRunCss()) + .append("')]//form//input[@type='text']"); + + browser.type(selectorBuffer.toString(), title); + +// functionalUtil.waitForPageToLoad(browser); + + /* fill in form - post */ + functionalUtil.typeMCE(browser, message); + + /* save form */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getCourseRunCss()) + .append("')]//form//button[last()]"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param id + * @return + * + * Opens the wiki specified by id. + */ + public boolean openWiki(Selenium browser, long id){ + browser.open(functionalUtil.getDeploymentPath() + "/url/RepositoryEntry/" + id); + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param wikiId + * @param pagename + * @param content + * @return true on success, otherwise false + * + * Creates a new wiki article. + */ + public boolean createWikiArticle(Selenium browser, long wikiId, String pagename, String content){ + if(!openWiki(browser, wikiId)) + return(false); + + /* type pagename */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form//div[contains(@class, '") + .append(getWikiCreateArticleCss()) + .append("')]/..//input[@type='text']"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + + browser.type(selectorBuffer.toString(), pagename); + + /* click create */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form//div[contains(@class, '") + .append(getWikiCreateArticleCss()) + .append("')]//button"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + /* edit content */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getWikiArticleBoxCss()) + .append("')]//a"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + + /* fill in text area */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getWikiEditFormWrapperCss()) + .append("')]//textarea"); + + browser.type(selectorBuffer.toString(), content); + + /* click save */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getWikiEditFormWrapperCss()) + .append("')]//button[last()]"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param id + * @return true on success, otherwise false + * + * Opens the blog specified by id. + */ + public boolean openBlog(Selenium browser, long id){ + browser.open(functionalUtil.getDeploymentPath() + "/url/RepositoryEntry/" + id); + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param courseId + * @param nth + * @return + * + * Opens the course with courseId and nth blog within the specified + * course. + */ + public boolean openBlogWithoutBusinessPath(Selenium browser, long courseId, int nth){ + if(!functionalRepositorySiteUtil.openCourse(browser, courseId)) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//ul//li//a[contains(@class, '") + .append(getBlogIconCss()) + .append("')])[") + .append(nth + 1) + .append("]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param url + * @return true on success + * + * Imports an existing feed into blog. + */ + public boolean importBlogFeed(Selenium browser, String url){ + /* open popup to enter url */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, '") + .append(getBlogNoPostsCss()) + .append("')]//a[contains(@class, 'b_button')])[last()]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + /* enter url */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, 'b_window_content')]//form//input[@type='text'])[2]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.type(selectorBuffer.toString(), url); + + /* click save */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, 'b_window_content')]//form//button[contains(@class, 'b_button_dirty')])[last()]"); + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + return(true); + } + + /** + * @param browser + * @param blogId + * @param title + * @param description + * @param content + * @return true on success, otherwise false + * + * Create a new blog entry. + */ + public boolean createBlogEntry(Selenium browser, long courseId, int nth, + String title, String description, String content){ + if(!openBlogWithoutBusinessPath(browser, courseId, nth)) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(getBlogCreateEntryCss()) + .append("')]"); + + browser.click(selectorBuffer.toString()); + + /* fill in form - title */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//form//div[contains(@class, '") + .append(getBlogFormCss()) + .append("')]//input[@type='text'])[1]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + + browser.type(selectorBuffer.toString(), title); + + /* fill in form - description */ + functionalUtil.typeMCE(browser, getBlogFormCss(), description); + + /* fill in form - content */ + functionalUtil.typeMCE(browser, getBlogFormCss(), content); + + /* save form */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form//div[contains(@class, '") + .append(getBlogFormCss()) + .append("')]//button[last()]"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param url + * @return true on success + * + * Imports an existing feed into podcast. + */ + public boolean importPodcastFeed(Selenium browser, String url){ + /* open popup to enter url */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, '") + .append(getPodcastNoEpisodesCss()) + .append("')]//a[contains(@class, 'b_button')])[last()]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + /* enter url */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, 'b_window_content')]//form//input[@type='text'])[2]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.type(selectorBuffer.toString(), url); + + /* click save */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, 'b_window_content')]//form//button[contains(@class, 'b_button_dirty')])[last()]"); + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + return(true); + } + + /** + * @param browser + * @param tab + * @return true on success + * + * Opens the test configurations appropriate tab. + */ + public boolean openCourseEditorIQTestTab(Selenium browser, CourseEditorIQTestTab tab){ + return(functionalUtil.openContentTab(browser, tab.ordinal())); + } + + /** + * @param browser + * @param tab + * @return true on success + * + * Opens the content package configurations appropriate tab. + */ + public boolean openCourseEditorCpTab(Selenium browser, CourseEditorCpTab tab){ + return(functionalUtil.openContentTab(browser, tab.ordinal())); + } + + /** + * @param browser + * @param tab + * @return true on success + * + * Opens the wiki configurations appropriate tab. + */ + public boolean openCourseEditorWikiTab(Selenium browser, CourseEditorWikiTab tab){ + return(functionalUtil.openContentTab(browser, tab.ordinal())); + } + + /** + * @param browser + * @param tab + * @return true on success + * + * Opens the blog configurations appropriate tab. + */ + public boolean openCourseEditorBlogTab(Selenium browser, CourseEditorBlogTab tab){ + return(functionalUtil.openContentTab(browser, tab.ordinal())); + } + + /** + * @param browser + * @param tab + * @return true on success + * + * Opens the podcast configurations appropriate tab. + */ + public boolean openCourseEditorPodcastTab(Selenium browser, CourseEditorPodcastTab tab){ + return(functionalUtil.openContentTab(browser, tab.ordinal())); + } + + /** + * @param browser + * @param tab + * @return true on success + * + * Opens the portfolio task configurations appropriate tab. + */ + public boolean openCourseEditorPortfolioTaskTab(Selenium browser, CourseEditorPortfolioTaskTab tab){ + return(functionalUtil.openContentTab(browser, tab.ordinal())); + } + + /** + * @param browser + * @param chooseRepositoryCss + * @param title + * @param description + * @return true on success + * + * Opens and fills in the "create resource" popup. + */ + private boolean createRepositoryResource(Selenium browser, String chooseRepositoryCss, String title, String description){ + /* click on "choose, create or import file" button */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(chooseRepositoryCss) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + /* click create button */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(getRepositoryPopupCreateResourceCss()) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + /* */ + return(functionalRepositorySiteUtil.fillInRepositoryEntryPopup(browser, title, description)); + } + + /** + * @param browser + * @param title + * @param description + * @return true on success + * + * Creates a new test. + */ + public boolean createQTITest(Selenium browser, String title, String description){ + if(!openCourseEditorIQTestTab(browser, CourseEditorIQTestTab.TEST_CONFIGURATION)) + return(false); + + if(!createRepositoryResource(browser, getTestChooseRepositoryFileCss(), title, description)){ + return(false); + } + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param title + * @param description + * @return true on success + * + * Creates a new CP learning content. + */ + public boolean createCPLearningContent(Selenium browser, String title, String description){ + if(!openCourseEditorCpTab(browser, CourseEditorCpTab.LEARNING_CONTENT)) + return(false); + + if(!createRepositoryResource(browser, getCpChooseRepositoryFileCss(), title, description)){ + return(false); + } + + return(true); + } + + /** + * @param browser + * @param title + * @param description + * @return true on success + * + * Creates a new wiki. + */ + public boolean createWiki(Selenium browser, String title, String description){ + if(!openCourseEditorWikiTab(browser, CourseEditorWikiTab.LEARNING_CONTENT)) + return(false); + + if(!createRepositoryResource(browser, getWikiChooseRepositoryFileCss(), title, description)){ + return(false); + } + + return(true); + } + + /** + * @param browser + * @param title + * @param description + * @return true on success + * + * Creates a new blog. + */ + public boolean createBlog(Selenium browser, String title, String description){ + if(!openCourseEditorBlogTab(browser, CourseEditorBlogTab.LEARNING_CONTENT)) + return(false); + + if(!createRepositoryResource(browser, getFeedChooseRepositoryFileCss(), title, description)){ + return(false); + } + + return(true); + } + + /** + * @param browser + * @param title + * @param description + * @return true on success + * + * Creates a new podcast. + */ + public boolean createPodcast(Selenium browser, String title, String description){ + if(!openCourseEditorPodcastTab(browser, CourseEditorPodcastTab.LEARNING_CONTENT)) + return(false); + + if(!createRepositoryResource(browser, getFeedChooseRepositoryFileCss(), title, description)){ + return(false); + } + + return(true); + } + + /** + * @param browser + * @param title + * @param description + * @return true on success + * + * Creates a new podcast. + */ + public boolean createPortfolioTask(Selenium browser, String title, String description){ + if(!openCourseEditorPortfolioTaskTab(browser, CourseEditorPortfolioTaskTab.LEARNING_CONTENT)) + return(false); + + if(!createRepositoryResource(browser, getMapChooseRepositoryFileCss(), title, description)){ + return(false); + } + + return(true); + } + + /** + * @param browser + * @return true on success + * + * Opens the portfolio template editor in conjunction with this method the appropriate node and + * the appopriate tab should already be opened. + */ + public boolean openPortfolioTemplateEditor(Selenium browser){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(getMapEditCss()) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + return(true); + } + + public FunctionalUtil getFunctionalUtil() { + return functionalUtil; + } + + public void setFunctionalUtil(FunctionalUtil functionalUtil) { + this.functionalUtil = functionalUtil; + } + + public FunctionalRepositorySiteUtil getFunctionalRepositorySiteUtil() { + return functionalRepositorySiteUtil; + } + + public void setFunctionalRepositorySiteUtil( + FunctionalRepositorySiteUtil functionalRepositorySiteUtil) { + this.functionalRepositorySiteUtil = functionalRepositorySiteUtil; + } + + public String getCourseRunCss() { + return courseRunCss; + } + + public void setCourseRunCss(String courseRunCss) { + this.courseRunCss = courseRunCss; + } + + public String getCourseOpenEditorCss() { + return courseOpenEditorCss; + } + + public void setCourseOpenEditorCss(String courseOpenEditorCss) { + this.courseOpenEditorCss = courseOpenEditorCss; + } + + public String getCourseTabActiveCss() { + return courseTabActiveCss; + } + + public void setCourseTabActiveCss(String courseTabActiveCss) { + this.courseTabActiveCss = courseTabActiveCss; + } + + public String getCourseTabCloseCss() { + return courseTabCloseCss; + } + + public void setCourseTabCloseCss(String courseTabCloseCss) { + this.courseTabCloseCss = courseTabCloseCss; + } + + public String getCourseEditorPublishCss() { + return courseEditorPublishCss; + } + + public void setCourseEditorPublishCss(String courseEditorPublishCss) { + this.courseEditorPublishCss = courseEditorPublishCss; + } + + public String getCourseEditorPublishWizardSelectAllCss() { + return courseEditorPublishWizardSelectAllCss; + } + + public void setCourseEditorPublishWizardSelectAllCss( + String courseEditorPublishWizardSelectAllCss) { + this.courseEditorPublishWizardSelectAllCss = courseEditorPublishWizardSelectAllCss; + } + + public String getCourseEditorPublishWizardAccessId() { + return courseEditorPublishWizardAccessId; + } + + public void setCourseEditorPublishWizardAccessId( + String courseEditorPublishWizardAccessId) { + this.courseEditorPublishWizardAccessId = courseEditorPublishWizardAccessId; + } + + public String getCourseEditorPublishWizardCatalogId() { + return courseEditorPublishWizardCatalogId; + } + + public void setCourseEditorPublishWizardCatalogId( + String courseEditorPublishWizardCatalogId) { + this.courseEditorPublishWizardCatalogId = courseEditorPublishWizardCatalogId; + } + + public String getCourseEditorInsertContentCss() { + return courseEditorInsertContentCss; + } + + public void setCourseEditorInsertContentCss(String courseEditorInsertContentCss) { + this.courseEditorInsertContentCss = courseEditorInsertContentCss; + } + + public String getCreateCourseNodeTargetPositionItemCss() { + return createCourseNodeTargetPositionItemCss; + } + + public void setCreateCourseNodeTargetPositionItemCss( + String createCourseNodeTargetPositionItemCss) { + this.createCourseNodeTargetPositionItemCss = createCourseNodeTargetPositionItemCss; + } + + public String getEportfolioAddCss() { + return eportfolioAddCss; + } + + public void setEportfolioAddCss(String eportfolioAddCss) { + this.eportfolioAddCss = eportfolioAddCss; + } + + public String getForumIconCss() { + return forumIconCss; + } + + public void setForumIconCss(String forumIconCss) { + this.forumIconCss = forumIconCss; + } + + public String getBlogIconCss() { + return blogIconCss; + } + + public void setBlogIconCss(String blogIconCss) { + this.blogIconCss = blogIconCss; + } + + public String getForumToolbarCss() { + return forumToolbarCss; + } + + public void setForumToolbarCss(String forumToolbarCss) { + this.forumToolbarCss = forumToolbarCss; + } + + public String getForumThreadNewCss() { + return forumThreadNewCss; + } + + public void setForumThreadNewCss(String forumThreadNewCss) { + this.forumThreadNewCss = forumThreadNewCss; + } + + public String getForumArchiveCss() { + return forumArchiveCss; + } + + public void setForumArchiveCss(String forumArchiveCss) { + this.forumArchiveCss = forumArchiveCss; + } + + public String getForumFilterCss() { + return forumFilterCss; + } + + public void setForumFilterCss(String forumFilterCss) { + this.forumFilterCss = forumFilterCss; + } + + public String getWikiCreateArticleCss() { + return wikiCreateArticleCss; + } + + public void setWikiCreateArticleCss(String wikiCreateArticleCss) { + this.wikiCreateArticleCss = wikiCreateArticleCss; + } + + public String getWikiArticleBoxCss() { + return wikiArticleBoxCss; + } + + public void setWikiArticleBoxCss(String wikiArticleBoxCss) { + this.wikiArticleBoxCss = wikiArticleBoxCss; + } + + public String getWikiEditFormWrapperCss() { + return wikiEditFormWrapperCss; + } + + public void setWikiEditFormWrapperCss(String wikiEditFormWrapperCss) { + this.wikiEditFormWrapperCss = wikiEditFormWrapperCss; + } + + public String getBlogCreateEntryCss() { + return blogCreateEntryCss; + } + + public void setBlogCreateEntryCss(String blogCreateEntryCss) { + this.blogCreateEntryCss = blogCreateEntryCss; + } + + public String getBlogFormCss() { + return blogFormCss; + } + + public void setBlogFormCss(String blogFormCss) { + this.blogFormCss = blogFormCss; + } + + public String getTestChooseRepositoryFileCss() { + return testChooseRepositoryFileCss; + } + + public void setTestChooseRepositoryFileCss(String testChooseRepositoryFileCss) { + this.testChooseRepositoryFileCss = testChooseRepositoryFileCss; + } + + public String getCpChooseRepositoryFileCss() { + return cpChooseRepositoryFileCss; + } + + public void setCpChooseRepositoryFileCss(String cpChooseRepositoryFileCss) { + this.cpChooseRepositoryFileCss = cpChooseRepositoryFileCss; + } + + public String getWikiChooseRepositoryFileCss() { + return wikiChooseRepositoryFileCss; + } + + public void setWikiChooseRepositoryFileCss(String wikiChooseRepositoryFileCss) { + this.wikiChooseRepositoryFileCss = wikiChooseRepositoryFileCss; + } + + public String getFeedChooseRepositoryFileCss() { + return feedChooseRepositoryFileCss; + } + + public void setFeedChooseRepositoryFileCss(String feedChooseRepositoryFileCss) { + this.feedChooseRepositoryFileCss = feedChooseRepositoryFileCss; + } + + public String getMapChooseRepositoryFileCss() { + return mapChooseRepositoryFileCss; + } + + public void setMapChooseRepositoryFileCss(String mapChooseRepositoryFileCss) { + this.mapChooseRepositoryFileCss = mapChooseRepositoryFileCss; + } + + public String getRepositoryPopupCreateResourceCss() { + return repositoryPopupCreateResourceCss; + } + + public void setRepositoryPopupCreateResourceCss(String repositoryPopupCreateResourceCss) { + this.repositoryPopupCreateResourceCss = repositoryPopupCreateResourceCss; + } + + public String getMapEditCss() { + return mapEditCss; + } + + public void setMapEditCss(String mapEditCss) { + this.mapEditCss = mapEditCss; + } + + public String getBlogNoPostsCss() { + return blogNoPostsCss; + } + + public void setBlogNoPostsCss(String blogNoPostsCss) { + this.blogNoPostsCss = blogNoPostsCss; + } + + public String getPodcastNoEpisodesCss() { + return podcastNoEpisodesCss; + } + + public void setPodcastNoEpisodesCss(String podcastNoEpisodesCss) { + this.podcastNoEpisodesCss = podcastNoEpisodesCss; + } + +} diff --git a/src/test/java/org/olat/util/FunctionalEPortfolioUtil.java b/src/test/java/org/olat/util/FunctionalEPortfolioUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..f8461d6bec24ff1350849eb18a46c7cdf4aef3df --- /dev/null +++ b/src/test/java/org/olat/util/FunctionalEPortfolioUtil.java @@ -0,0 +1,1088 @@ +/** + * <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.util; + +import java.io.IOException; +import java.io.StringWriter; +import java.net.MalformedURLException; +import java.net.URI; + +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.exception.MethodInvocationException; +import org.apache.velocity.exception.ParseErrorException; +import org.apache.velocity.exception.ResourceNotFoundException; +import org.olat.util.FunctionalHomeSiteUtil.EPortfolioAction; +import org.olat.util.FunctionalUtil.OlatSite; + +import com.thoughtworks.selenium.Selenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +public class FunctionalEPortfolioUtil { + public final static String EP_ARTEFACTS_BUSINESS_PATH = "EPArtefacts"; + public final static String EP_MAPS_BUSINESS_PATH = "EPMaps"; + + + public final static String EPORTFOLIO_CSS = "b_eportfolio"; + public final static String EPORTFOLIO_MAP_CSS = "b_eportfolio_map"; + + public final static String HOME_PORTAL_EDIT_LINK_CSS = "o_sel_add_artfeact"; + public final static String ADD_TEXT_ARTEFACT_CSS = "o_sel_add_text_artfeact"; + public final static String UPLOAD_FILE_ARTEFACT_CSS = "o_sel_add_upload_artfeact"; + public final static String CREATE_LEARNING_JOURNAL_CSS = "o_sel_add_liveblog_artfeact"; + + public final static String ADD_BINDER_BOX_ID = "o_addMapBox"; + public final static String CREATE_BINDER_CSS = "o_sel_create_map"; + public final static String CREATE_DEFAULT_BINDER_CSS = "o_sel_create_default_map"; + public final static String CREATE_TEMPLATE_BINDER_CSS = "o_sel_create_template_map"; + public final static String OPEN_BINDER_ICON_CSS = "b_open_icon"; + + public final static String EDIT_LINK_CSS = "b_eportfolio_edit_link"; + + public final static String EPORTFOLIO_TABLE_OF_CONTENTS_CSS = "b_portfolio_toc"; + public final static String EPORTFOLIO_TOC_LEVEL1_CSS = "level1"; + public final static String EPORTFOLIO_TOC_LEVEL2_CSS = "level2"; + + public final static String ADD_LINK_CSS = "b_eportfolio_add_link"; + public final static String PAGE_TABS_CSS = "b_pagination"; + + public final static String PAGE_ICON_CSS = "b_eportfolio_link"; + public final static String STRUCT_ICON_CSS = "b_ep_struct_icon"; + + public enum ArtefactDisplay { + TABLE, + THUMBNAILS, + } + + private String eportfolioCss; + private String eportfolioMapCss; + + private String homePortalEditLinkCss; + private String addTextArtefactCss; + private String uploadFileArtefactCss; + private String createLearningJournalCss; + + private String addBinderBoxId; + private String createBinderCss; + private String createDefaultBinderCss; + private String createTemplateBinderCss; + private String openBinderCss; + + private String editLinkCss; + + private String eportfolioTableOfContentsCss; + private String eportfolioTOCLevel1Css; + private String eportfolioTOCLevel2Css; + + private String addLinkCss; + private String pageTabsCss; + + private String pageIconCss; + private String structIconCss; + + private FunctionalUtil functionalUtil; + private FunctionalHomeSiteUtil functionalHomeSiteUtil; + + public FunctionalEPortfolioUtil(FunctionalUtil functionalUtil, FunctionalHomeSiteUtil functionalHomeSiteUtil){ + this.functionalUtil = functionalUtil; + this.functionalHomeSiteUtil = functionalHomeSiteUtil; + + setEPortfolioCss(EPORTFOLIO_CSS); + setEPortfolioMapCss(EPORTFOLIO_MAP_CSS); + + setHomePortalEditLinkCss(HOME_PORTAL_EDIT_LINK_CSS); + setAddTextArtefactCss(ADD_TEXT_ARTEFACT_CSS); + setUploadFileArtefactCss(UPLOAD_FILE_ARTEFACT_CSS); + setCreateLearningJournalCss(CREATE_LEARNING_JOURNAL_CSS); + + setAddBinderBoxId(ADD_BINDER_BOX_ID); + setCreateBinderCss(CREATE_BINDER_CSS); + setCreateDefaultBinderCss(CREATE_DEFAULT_BINDER_CSS); + setCreateTemplateBinderCss(CREATE_TEMPLATE_BINDER_CSS); + setOpenBinderCss(OPEN_BINDER_ICON_CSS); + + setEditLinkCss(EDIT_LINK_CSS); + + setEPortfolioTableOfContentsCss(EPORTFOLIO_TABLE_OF_CONTENTS_CSS); + setEPortfolioTOCLevel1Css(EPORTFOLIO_TOC_LEVEL1_CSS); + setEPortfolioTOCLevel2Css(EPORTFOLIO_TOC_LEVEL2_CSS); + + setAddLinkCss(ADD_LINK_CSS); + setPageTabsCss(PAGE_TABS_CSS); + + setPageIconCss(PAGE_ICON_CSS); + setStructIconCss(STRUCT_ICON_CSS); + } + + /** + * @param browser + * @param key + * @param artefactTitle + * @return + * + * + */ + public boolean openArtefactDetails(Selenium browser, Long key, String artefactTitle){ + String epArtefactsBusinessPath = functionalUtil.getDeploymentUrl().toString() + "/url/HomeSite/" + key + "/" + EP_ARTEFACTS_BUSINESS_PATH; + +// do{ +// browser.open(epArtefactsBusinessPath); +// }while(); + + //TODO:JK: implement me + + return(false); + } + + public boolean openBinder(Selenium browser, Long key, String binderTitle){ + String epMapsBusinessPath = functionalUtil.getDeploymentUrl().toString() + "/url/HomeSite/" + key + "/" + EP_MAPS_BUSINESS_PATH; + + //TODO:JK: implement me + + return(true); + } + + /** + * @param binder + * @param page + * @param structure + * @return + * + * Creates an xpath selector of specified binder, page and structure. + */ + public String createSelector(String binder, String page, String structure){ + if(binder == null || binder.isEmpty() || page == null || page.isEmpty()) + return(null); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath="); + selectorBuffer.append("//ul//li//a//span[text()='") + .append(binder) + .append("']/../../..//ul//li//a//span[text()='") + .append(page) + .append("']"); + + if(structure != null && !structure.isEmpty()){ + selectorBuffer.append("/../../..//ul//li//a//span[text()='") + .append(structure) + .append("']"); + } + + selectorBuffer.append("/.."); + + return(selectorBuffer.toString()); + } + + /** + * @param browser + * @param binder + * @param page + * @param structure + * @return true on success + * + * Creates the specified elements (binder, page, structure) + */ + public boolean createElements(Selenium browser, String binder, String page, String structure){ + if(!binderExists(browser, binder)){ + createDefaultBinder(browser, binder, null); + + createPage(browser, binder, page, ArtefactDisplay.THUMBNAILS, null); + + createStructure(browser, binder, page, structure, null); + }else{ + if(!pageExists(browser, binder, page)){ + createPage(browser, binder, page, ArtefactDisplay.THUMBNAILS, null); + + createStructure(browser, binder, page, structure, null); + }else{ + if(!structureExists(browser, binder, page, structure) && structure != null){ + createStructure(browser, binder, page, structure, null); + } + } + } + + return(true); + } + + /** + * @param browser + * @param title + * @return true if binder containing title exists else false. + * + * Checks if binder containing title exists. + */ + public boolean binderExists(Selenium browser, String title){ + if(!functionalUtil.openSite(browser, OlatSite.HOME)) + return(false); + + if(!functionalHomeSiteUtil.openActionByMenuTree(browser, EPortfolioAction.MY_BINDERS)) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//h4[text()='") + .append(title) + .append("']/..//a[contains(@class, '") + .append(getOpenBinderCss()) + .append("')]"); + + if(browser.isElementPresent(selectorBuffer.toString())){ + return(true); + }else{ + return(false); + } + } + + /** + * @param browser + * @param title + * @return true on success + * + * Opens a specified binder. + */ + public boolean openBinder(Selenium browser, String title){ + if(!functionalUtil.openSite(browser, OlatSite.HOME)) + return(false); + + if(!functionalHomeSiteUtil.openActionByMenuTree(browser, EPortfolioAction.MY_BINDERS, false)) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//h4[text()='") + .append(title) + .append("']/..//a[contains(@class, '") + .append(getOpenBinderCss()) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @return true on success + * + * Opens the editor of open binder. + */ + public boolean openEditor(Selenium browser){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getEditLinkCss()) + .append("')]//a"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param title + * @param description + * @return true on success + * + * Creates a binder. + */ + public boolean createDefaultBinder(Selenium browser, String title, String description){ + if(!functionalUtil.openSite(browser, OlatSite.HOME)) + return(false); + + if(!functionalHomeSiteUtil.openActionByMenuTree(browser, EPortfolioAction.MY_BINDERS)) + return(false); + + /* open add binder dialog */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(getCreateBinderCss()) + .append("')]"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("//a[contains(@class, '") + .append(getCreateDefaultBinderCss()) + .append("')]"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + /* fill in dialog - title */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[@id='") + .append(getAddBinderBoxId()) + .append("']//form//input[@type='text']"); + + browser.type(selectorBuffer.toString(), title); + + /* fill in dialog - description */ + functionalUtil.typeMCE(browser, description); + + + /* fill in dialog - save */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[@id='") + .append(getAddBinderBoxId()) + .append("']//form//button[last()]"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + public boolean pageExists(Selenium browser, String binder, String title){ + if(!openBinder(browser, binder)) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getEPortfolioTableOfContentsCss()) + .append("')]//ul//li[contains(@class, '") + .append(getEPortfolioTOCLevel1Css()) + .append("')]//a//span[contains(text(), '") + .append(title) + .append("')]"); + + if(browser.isElementPresent(selectorBuffer.toString())){ + return(true); + }else{ + return(false); + } + } + + /** + * @param browser + * @param binder + * @param title + * @param display + * @param description + * @return true on success + * + * Create a page in the specified binder. + */ + public boolean createPage(Selenium browser, String binder, String title, ArtefactDisplay display, String description){ + return(createPage(browser, binder, title, display, description, true)); + } + + public boolean createPage(Selenium browser, String binder, String title, ArtefactDisplay display, String description, boolean reopenBinder){ + if(reopenBinder){ + if(!openBinder(browser, binder)) + return(false); + } + + /* click add */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(getAddLinkCss()) + .append("')]"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + /* fill in wizard - title */ + if(title != null){ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getEPortfolioMapCss()) + .append("')]//form//input[@type='text']"); + + browser.type(selectorBuffer.toString(), title); + } + + /* fill in wizard - display */ + if(display != null){ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, '") + .append(getEPortfolioMapCss()) + .append("')]//form//input[@type='radio'])[") + .append(display.ordinal() + 1) + .append("]"); + + browser.click(selectorBuffer.toString()); + } + + /* fill in wizard - description */ + functionalUtil.typeMCE(browser, description); + + /* fill in wizard - save */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getEPortfolioMapCss()) + .append("')]//form//button[last()]"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + public boolean renamePage(Selenium browser, String binder, String oldName, String newName){ + String selector = createSelector(binder, oldName, null); + + functionalUtil.waitForPageToLoadElement(browser, selector); + browser.click(selector); + + /* rename */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getEPortfolioMapCss()) + .append("')]//form//input[@type='text']"); + + browser.type(selectorBuffer.toString(), newName); + + /* save */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, '") + .append(getEPortfolioMapCss()) + .append("')]//form//button)[last()]"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param binder + * @param page + * @param title + * @return true if structural element exists otherwise false + * + * Checks if structural element exists. + */ + public boolean structureExists(Selenium browser, String binder, String page, String title){ + if(!openBinder(browser, binder)) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("//div[contains(@class, '") + .append(getEPortfolioTableOfContentsCss()) + .append("')]//ul//li"); + + VelocityContext context = new VelocityContext(); + + context.put("tocSelector", selectorBuffer.toString()); + context.put("level1", getEPortfolioTOCLevel1Css()); + context.put("level2", getEPortfolioTOCLevel2Css()); + context.put("page", page); + context.put("structure", title); + + VelocityEngine engine = null; + + engine = new VelocityEngine(); + + StringWriter sw = new StringWriter(); + + try { + engine.evaluate(context, sw, "eportfolioTOCStructurePosition", FunctionalHomeSiteUtil.class.getResourceAsStream("EPortfolioTOCStructurePosition.vm")); + + Integer i = new Integer(browser.getEval(sw.toString())); + + if(i.intValue() != -1){ + return(true); + }else{ + return(false); + } + + } catch (ParseErrorException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (MethodInvocationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ResourceNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return(false); + } + + /** + * @param browser + * @param binder + * @param page + * @param title + * @param description + * @return true on success + * + * Creates the specified structural element. + */ + public boolean createStructure(Selenium browser, String binder, String page, + String title, String description){ + if(!openBinder(browser, binder)) + return(false); + + /* open editor */ + openEditor(browser); + + /* select page and click create structure */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append("x-tree-node-anchor") + .append("')]/span[text()='") + .append(page) + .append("']/.."); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(getAddLinkCss()) + .append("') and contains(@class, '") + .append(getStructIconCss()) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + /* fill in wizard - title */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getEPortfolioMapCss()) + .append("')]//form//input[@type='text']"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.type(selectorBuffer.toString(), title); + + /* fill in wizard - description */ + functionalUtil.typeMCE(browser, description); + + /* fill in wizard - save */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getEPortfolioMapCss()) + .append("')]//form//button[last()]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoadElement(browser, createSelector(binder, page, title)); + + return(true); + } + + /** + * @param browser + * @return + * + * Clicks the edit link. + */ + private boolean openEditLink(Selenium browser){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(getHomePortalEditLinkCss()) + .append("')]"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param title + * @param description + * @return true on success + * + * Fills in the open wizard's title and description fields. + */ + protected boolean fillInTitleAndDescription(Selenium browser, String title, String description){ + StringBuffer locatorBuffer = new StringBuffer(); + + locatorBuffer.append("xpath=//form//div[contains(@class, '") + .append(functionalUtil.getWizardCss()) + .append("')]//input[@type='text']"); + + functionalUtil.waitForPageToLoadElement(browser, locatorBuffer.toString()); + + browser.type(locatorBuffer.toString(), title); + + functionalUtil.typeMCE(browser, description); + + functionalUtil.clickWizardNext(browser); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param tags + * @return + * + * Fills in the open wizard's tags. + */ + protected boolean fillInTags(Selenium browser, String[] tags){ + int i = 1; + + for(String tag: tags){ + StringBuffer locatorBuffer = new StringBuffer(); + + locatorBuffer.append("xpath=(//form//div[contains(@class, '") + .append(functionalUtil.getWizardCss()) + .append("')]//input[@type='text'])[" + i + "]"); + + functionalUtil.waitForPageToLoadElement(browser, locatorBuffer.toString()); + + browser.focus(locatorBuffer.toString()); + browser.type(locatorBuffer.toString(), tag); + + browser.focus(locatorBuffer.toString()); + browser.fireEvent(locatorBuffer.toString(), "changed"); + + browser.keyDown(locatorBuffer.toString(), ","); + browser.keyPress(locatorBuffer.toString(), ","); + browser.keyUp(locatorBuffer.toString(), ","); + browser.fireEvent(locatorBuffer.toString(), "changed"); + browser.fireEvent(locatorBuffer.toString(), "blur"); + + i++; + } + + functionalUtil.clickWizardNext(browser); + + return(true); + } + + /** + * @param browser + * @param content + * @param title + * @param description + * @param tags + * @return + * + * Add a text artefact to a e-portfolio. + */ + public boolean addTextArtefact(Selenium browser, String binder, String page, String structure, + String content, String title, String description, String[] tags){ + /* create binder, page or structure if necessary */ + if(!createElements(browser, binder, page, structure)) + return(false); + + /* navigate to the right place */ + if(!functionalUtil.openSite(browser, OlatSite.HOME)) + return(false); + + if(!functionalHomeSiteUtil.openActionByMenuTree(browser, EPortfolioAction.MY_ARTIFACTS)) + return(false); + + /* open wizard */ + openEditLink(browser); + functionalUtil.waitForPageToLoad(browser); + + StringBuffer locatorBuffer = new StringBuffer(); + + locatorBuffer.append("xpath=//a[contains(@class, '") + .append(getAddTextArtefactCss()) + .append("')]"); + + browser.click(locatorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + + /* fill in wizard - content */ + functionalUtil.typeMCE(browser, content); + + functionalUtil.clickWizardNext(browser); + + functionalUtil.waitForPageToLoad(browser); + + /* fill in wizard - title & description */ + fillInTitleAndDescription(browser, title, description); + + /* fill in wizard - tags */ + fillInTags(browser, tags); + + /* fill in wizard - select destination */ + String selector = createSelector(binder, page, structure); + + functionalUtil.waitForPageToLoadElement(browser, selector); + + browser.click(selector); + + /* click finish */ + functionalUtil.clickWizardFinish(browser); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param file + * @param title + * @param description + * @param tags + * @param binderPath + * @return + * @throws MalformedURLException + * + * Upload a file artefact to a e-portfolio. + */ + public boolean uploadFileArtefact(Selenium browser, String binder, String page, String structure, + URI file, String title, String description, String[] tags) throws MalformedURLException{ + if(!createElements(browser, binder, page, structure)) + return(false); + + if(!functionalUtil.openSite(browser, OlatSite.HOME)) + return(false); + + if(!functionalHomeSiteUtil.openActionByMenuTree(browser, EPortfolioAction.MY_ARTIFACTS)) + return(false); + + /* open wizard */ + openEditLink(browser); + functionalUtil.waitForPageToLoad(browser); + + StringBuffer locatorBuffer = new StringBuffer(); + + locatorBuffer.append("xpath=//a[contains(@class, '") + .append(getUploadFileArtefactCss()) + .append("')]"); + + browser.click(locatorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + + /* fill in wizard - file */ + locatorBuffer = new StringBuffer(); + + locatorBuffer.append("xpath=//form//div[contains(@class, '") + .append(functionalUtil.getWizardCss()) + .append("')]//input[@type='file']"); + + browser.focus(locatorBuffer.toString()); + browser.type(locatorBuffer.toString(), file.toURL().getPath()); + //browser.attachFile(locatorBuffer.toString(), file.toURL().toString()); + + //TODO:JK: find a solution for IE + /* IE may don't like the following script */ + //browser.runScript("$(\"form ." + functionalUtil.getWizardCss() + " input[type='file']\").trigger(\"change\")"); + +// functionalUtil.waitForPageToLoad(browser); + + functionalUtil.clickWizardNext(browser); + + functionalUtil.waitForPageToLoad(browser); + + /* fill in wizard - title & description */ + fillInTitleAndDescription(browser, title, description); + + /* fill in wizard - tags */ + fillInTags(browser, tags); + + /* fill in wizard - select binder path */ + String selector = createSelector(binder, page, structure); + + functionalUtil.waitForPageToLoadElement(browser, selector); + + browser.click(selector); + + /* click finish */ + functionalUtil.clickWizardFinish(browser); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param title + * @param description + * @param tags + * @param binderPath + * @param create + * @return + * + * Create a learnig journal for a e-portfolio. + */ + public boolean createLearningJournal(Selenium browser, String binder, String page, String structure, + String title, String description, String[] tags){ + if(!createElements(browser, binder, page, structure)) + return(false); + + if(!functionalUtil.openSite(browser, OlatSite.HOME)) + return(false); + + if(!functionalHomeSiteUtil.openActionByMenuTree(browser, EPortfolioAction.MY_ARTIFACTS)) + return(false); + + /* open wizard */ + openEditLink(browser); + functionalUtil.waitForPageToLoad(browser); + + StringBuffer locatorBuffer = new StringBuffer(); + + locatorBuffer.append("xpath=//a[contains(@class, '") + .append(getCreateLearningJournalCss()) + .append("')]"); + + browser.click(locatorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + /* fill in wizard - title & description */ + fillInTitleAndDescription(browser, title, description); + + /* fill in wizard - tags */ + fillInTags(browser, tags); + + /* fill in wizard - select binder path */ + String selector = createSelector(binder, page, structure); + + functionalUtil.waitForPageToLoadElement(browser, selector); + + browser.click(selector); + + /* click finish */ + functionalUtil.clickWizardFinish(browser); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + public FunctionalUtil getFunctionalUtil() { + return functionalUtil; + } + + public void setFunctionalUtil(FunctionalUtil functionalUtil) { + this.functionalUtil = functionalUtil; + } + + public FunctionalHomeSiteUtil getFunctionalHomeSiteUtil() { + return functionalHomeSiteUtil; + } + + public void setFunctionalHomeSiteUtil( + FunctionalHomeSiteUtil functionalHomeSiteUtil) { + this.functionalHomeSiteUtil = functionalHomeSiteUtil; + } + + public String getEPortfolioCss() { + return eportfolioCss; + } + + public void setEPortfolioCss(String eportfolioCss) { + this.eportfolioCss = eportfolioCss; + } + + public String getEPortfolioMapCss() { + return eportfolioMapCss; + } + + public void setEPortfolioMapCss(String eportfolioMapCss) { + this.eportfolioMapCss = eportfolioMapCss; + } + + public String getHomePortalEditLinkCss() { + return homePortalEditLinkCss; + } + + public void setHomePortalEditLinkCss(String homePortalEditLinkCss) { + this.homePortalEditLinkCss = homePortalEditLinkCss; + } + + public String getAddTextArtefactCss() { + return addTextArtefactCss; + } + + public void setAddTextArtefactCss(String addTextArtefactCss) { + this.addTextArtefactCss = addTextArtefactCss; + } + + public String getUploadFileArtefactCss() { + return uploadFileArtefactCss; + } + + public void setUploadFileArtefactCss(String uploadFileArtefactCss) { + this.uploadFileArtefactCss = uploadFileArtefactCss; + } + + public String getCreateLearningJournalCss() { + return createLearningJournalCss; + } + + public void setCreateLearningJournalCss(String createLearningJournalCss) { + this.createLearningJournalCss = createLearningJournalCss; + } + + public String getAddBinderBoxId() { + return addBinderBoxId; + } + + public void setAddBinderBoxId(String addBinderBoxId) { + this.addBinderBoxId = addBinderBoxId; + } + + public String getCreateBinderCss() { + return createBinderCss; + } + + public void setCreateBinderCss(String createBinderCss) { + this.createBinderCss = createBinderCss; + } + + public String getCreateDefaultBinderCss() { + return createDefaultBinderCss; + } + + public void setCreateDefaultBinderCss(String createDefaultBinderCss) { + this.createDefaultBinderCss = createDefaultBinderCss; + } + + public String getCreateTemplateBinderCss() { + return createTemplateBinderCss; + } + + public void setCreateTemplateBinderCss(String createTemplateBinderCss) { + this.createTemplateBinderCss = createTemplateBinderCss; + } + + public String getOpenBinderCss() { + return openBinderCss; + } + + public void setOpenBinderCss(String openBinderCss) { + this.openBinderCss = openBinderCss; + } + + public String getEditLinkCss() { + return editLinkCss; + } + + + public void setEditLinkCss(String editLinkCss) { + this.editLinkCss = editLinkCss; + } + + + public String getEPortfolioTableOfContentsCss() { + return eportfolioTableOfContentsCss; + } + + public void setEPortfolioTableOfContentsCss(String eportfolioTableOfContentsCss) { + this.eportfolioTableOfContentsCss = eportfolioTableOfContentsCss; + } + + public String getEPortfolioTOCLevel1Css() { + return eportfolioTOCLevel1Css; + } + + public void setEPortfolioTOCLevel1Css(String eportfolioTOCLevel1Css) { + this.eportfolioTOCLevel1Css = eportfolioTOCLevel1Css; + } + + public String getEPortfolioTOCLevel2Css() { + return eportfolioTOCLevel2Css; + } + + public void setEPortfolioTOCLevel2Css(String eportfolioTOCLevel2Css) { + this.eportfolioTOCLevel2Css = eportfolioTOCLevel2Css; + } + + public String getAddLinkCss() { + return addLinkCss; + } + + public void setAddLinkCss(String addLinkCss) { + this.addLinkCss = addLinkCss; + } + + public String getPageTabsCss() { + return pageTabsCss; + } + + public void setPageTabsCss(String pageTabsCss) { + this.pageTabsCss = pageTabsCss; + } + + + public String getPageIconCss() { + return pageIconCss; + } + + + public void setPageIconCss(String pageIconCss) { + this.pageIconCss = pageIconCss; + } + + + public String getStructIconCss() { + return structIconCss; + } + + + public void setStructIconCss(String structIconCss) { + this.structIconCss = structIconCss; + } +} diff --git a/src/test/java/org/olat/util/FunctionalGroupsSiteUtil.java b/src/test/java/org/olat/util/FunctionalGroupsSiteUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..0cacbe55269ef0b394583c65608897189e834744 --- /dev/null +++ b/src/test/java/org/olat/util/FunctionalGroupsSiteUtil.java @@ -0,0 +1,62 @@ +/** + * <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.util; + +import com.thoughtworks.selenium.Selenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +public class FunctionalGroupsSiteUtil { + + public enum GroupsSiteAction { + MY_GROUPS, + PUBLISHED_GROUPS, + GROUPS_ADMINISTRATION + } + + private FunctionalUtil functionalUtil; + + public FunctionalGroupsSiteUtil(FunctionalUtil functionalUtil){ + this.functionalUtil = functionalUtil; + } + + /** + * @param browser + * @param action + * @return true on success otherwise false + * + * Browse the groups site's navigation. + */ + public boolean openActionByMenuTree(Selenium browser, Object action){ + //TODO:JK: implement me + + return(false); + } + + public FunctionalUtil getFunctionalUtil() { + return functionalUtil; + } + + public void setFunctionalUtil(FunctionalUtil functionalUtil) { + this.functionalUtil = functionalUtil; + } +} diff --git a/src/test/java/org/olat/util/FunctionalHomeSiteUtil.java b/src/test/java/org/olat/util/FunctionalHomeSiteUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..115c2a1bbd97697f8f2c225a57cbb99925156786 --- /dev/null +++ b/src/test/java/org/olat/util/FunctionalHomeSiteUtil.java @@ -0,0 +1,1485 @@ +/** + * <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.util; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Calendar; + +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.exception.MethodInvocationException; +import org.apache.velocity.exception.ParseErrorException; +import org.apache.velocity.exception.ResourceNotFoundException; +import org.junit.Assert; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.util.FunctionalUtil.OlatSite; + +import com.thoughtworks.selenium.Selenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +public class FunctionalHomeSiteUtil { + private final static OLog log = Tracing.createLoggerFor(FunctionalHomeSiteUtil.class); + + public final static String HOME_SITE_MENU_TREE_SELECTED_CSS = "b_tree_selected"; + + public final static String FORM_ELEMENT_WRAPPER = "b_form_element_wrapper"; + + /* menu tree */ + public final static String HOME_ACTION_PORTAL_CSS = "o_sel_portal"; + public final static String HOME_ACTION_SETTINGS_CSS = "o_sel_mysettings"; + public final static String HOME_ACTION_CALENDAR_CSS = "o_sel_calendar"; + public final static String HOME_ACTION_SUBSCRIPTIONS_CSS = "o_sel_notifications"; + public final static String HOME_ACTION_BOOKMARKS_CSS = "o_sel_bookmarks"; + public final static String HOME_ACTION_PERSONAL_FOLDER_CSS = "o_sel_userfolder"; + public final static String HOME_ACTION_NOTES_CSS = "o_sel_notelist"; + public final static String HOME_ACTION_EVIDENCES_OF_ACHIEVEMENT_CSS = "o_sel_effstatements"; + + public final static String EPORTFOLIO_PARENT_ID = "ddportfolioParent"; + public final static String EPORTFOLIO_ACTION_MY_ARTIFACTS_CSS = "o_sel_EPArtefacts"; + public final static String EPORTFOLIO_ACTION_MY_BINDERS_CSS = "o_sel_EPMaps"; + public final static String EPORTFOLIO_ACTION_MY_PORTFOLIO_TASKS_CSS = "o_sel_EPStructuredMaps"; + public final static String EPORTFOLIO_ACTION_RELEASED_BINDERS_CSS = "o_sel_EPSharedMaps"; + + /* portal */ + public final static String PORTAL_EDIT_LINK_CSS = "o_home_portaleditlink"; + + public final static String PORTAL_WRAPPER_CSS = "b_portal_wrapper"; + public final static String PORTAL_CSS = "b_portal"; + public final static String PORTAL_COLUMN_CSS_PREFIX = "o_sel_portal_col_"; + public final static String PORTAL_SUBCOLUMNS_CSS = "b_subcolumns"; + public final static String PORTAL_INACTIVE_CSS = "b_portal_inactive"; + + public final static String PORTLET_CSS = "b_portlet"; + public final static String PORTLET_EDIT_CSS = "b_portlet_edit"; + public final static String PORTLET_INACTIVE_CSS = "b_portlet_incactive"; + + public final static String PORTLET_QUICKSTART_CSS = "o_portlet_quickstart"; + public final static String PORTLET_REPOSITORY_STUDENT_CSS = "o_portlet_repository_student"; + public final static String PORTLET_REPOSITORY_TEACHER_CSS = "o_portlet_repository_teacher"; + public final static String PORTLET_INFOMESSAGES_CSS = "o_portlet_infomessages"; + public final static String PORTLET_CALENDAR_CSS = "o_portlet_calendar"; + public final static String PORTLET_BOOKMARK_CSS = "o_portlet_bookmark"; + public final static String PORTLET_GROUPS_CSS = "o_portlet_groups"; + public final static String PORTLET_NOTI_CSS = "o_portlet_noti"; + public final static String PORTLET_EFF_CSS = "o_portlet_eff"; + public final static String PORTLET_NOTES_CSS = "o_portlet_notes"; + public final static String PORTLET_DYK_CSS = "b_portlet_dyk"; + + public final static String PORTLET_MOVE_LEFT_CSS = "b_portlet_edit_left"; + public final static String PORTLET_MOVE_RIGHT_CSS = "b_portlet_edit_right"; + public final static String PORTLET_MOVE_UPWARDS_CSS = "b_portlet_edit_up"; + public final static String PORTLET_MOVE_DOWNWARDS_CSS = "b_portlet_edit_down"; + public final static String PORTLET_EDIT_INACTIVATE_CSS = "b_portlet_edit_delete"; + public final static String PORTLET_EDIT_ACTIVATE_CSS = "b_portlet_add"; + + /* General System Settings */ + public final static String PREFS_BUTTONS_CSS = "o_sel_home_settings_prefs_buttons"; + + public final static String LANGUAGE_OPTIONS_ID = "o_fioform_language_SELBOX"; + + public final static String GERMAN_LANGUAGE_VALUE = "de"; + public final static String ENGLISH_LANGUAGE_VALUE = "en"; + public final static String FRENCH_LANGUAGE_VALUE = "fr"; + public final static String SPANISH_LANGUAGE_VALUE = "es"; + public final static String ITALIAN_LANGUAGE_VALUE = "it"; + + /* Specific System Settings */ + public final static String GUI_BUTTONS_CSS = "o_sel_home_settings_gui_buttons"; + + public final static String ACCESSIBILITY_CSS = "o_sel_home_settings_accessibility"; + public final static String RESUME_LAST_SESSION_CSS = "o_sel_home_settings_resume"; + public final static String SUPPORT_FOR_BROWSER_BACK_CSS = "o_sel_home_settings_back_enabling"; + + public final static String NO_VALUE = "none"; + public final static String YES_AUTOMATICALLY_VALUE = "auto"; + public final static String YES_ON_REQUEST_VALUE = "ondemand"; + + public final static String OFF_VALUE = "no"; + public final static String ON_VALUE = "yes"; + + /* Reset Configurations */ + public final static String SYSPREFS_BUTTONS_CSS = "o_sel_home_settings_reset_sysprefs_buttons"; + + public final static String CONFIGURATIONS_CSS = "o_sel_home_settings_reset_sysprefs"; + + public final static String GUI_PREFERENCES_VALUE = "guiprefs"; + public final static String SYS_PREFERENCES_VALUE = "sysprefs"; + public final static String RESUME_VALUE = "resume"; + + /* password tab */ + public final static String OLD_PASSWORD_CSS = "o_sel_home_pwd_old"; + public final static String NEW_PASSWORD_CSS = "o_sel_home_pwd_new_1"; + public final static String CONFIRM_PASSWORD_CSS = "o_sel_home_pwd_new_2"; + + public enum PortalSettingsForms { + GENERAL_SYSTEM_SETTINGS, + SPECIFIC_SYSTEM_SETTINGS, + RESET_CONFIGURATIONS; + + public enum SpecificSystemSettingsRadios { + ACCESSIBILITY(ACCESSIBILITY_CSS), + RESUME_LAST_SESSION(RESUME_LAST_SESSION_CSS), + SUPPORT_FOR_BROWSER_BACK(SUPPORT_FOR_BROWSER_BACK_CSS); + + private String groupCss; + + SpecificSystemSettingsRadios(String groupCss){ + setGroupCss(groupCss); + } + + public String getGroupCss() { + return groupCss; + } + + public void setGroupCss(String groupCss) { + this.groupCss = groupCss; + } + + public enum ResumeLastSession{ + NO(NO_VALUE), + YES_AUTOMATICALLY(YES_AUTOMATICALLY_VALUE), + YES_ON_REQUEST(YES_ON_REQUEST_VALUE); + + private String valueAttribute; + + ResumeLastSession(String valueAttribute){ + setValueAttribute(valueAttribute); + } + + public String getValueAttribute() { + return valueAttribute; + } + + public void setValueAttribute(String valueAttribute) { + this.valueAttribute = valueAttribute; + } + } + + public enum SupportForBrowserBack { + ON(ON_VALUE), + OFF(OFF_VALUE); + + private String valueAttribute; + + SupportForBrowserBack(String valueAttribute){ + setValueAttribute(valueAttribute); + } + + public String getValueAttribute() { + return valueAttribute; + } + + public void setValueAttribute(String valueAttribute) { + this.valueAttribute = valueAttribute; + } + } + } + + + public enum ResetConfigurations{ + Configurations(CONFIGURATIONS_CSS); + + private String groupCss; + + ResetConfigurations(String groupCss){ + setGroupCss(groupCss); + } + + public String getGroupCss() { + return groupCss; + } + + public void setGroupCss(String groupCss) { + this.groupCss = groupCss; + } + + public enum ConfigurationsCheckboxes { + GUI_PREFERENCES(GUI_PREFERENCES_VALUE), + SYS_PREFERENCES(SYS_PREFERENCES_VALUE), + RESUME(RESUME_VALUE); + + private String valueAttribute; + + ConfigurationsCheckboxes (String valueAttribute){ + setValueAttribute(valueAttribute); + } + + + public String getValueAttribute() { + return valueAttribute; + } + + public void setValueAttribute(String valueAttribute) { + this.valueAttribute = valueAttribute; + } + } + } + } + + public enum HomeSiteAction { + PORTAL, + SETTINGS, + CALENDAR, + SUBSCRIPTIONS, + BOOKMARKS, + PERSONAL_FOLDER, + NOTES, + EVIDENCES_OF_ACHIEVEMENT, + OTHER_USERS, /* no corresponding CSS class available */ + }; + + public enum EPortfolioAction { + MY_ARTIFACTS, + MY_BINDERS, + MY_PORTFOLIO_TASKS, + RELEASED_BINDERS, + }; + + public enum Direction { + UP, + DOWN, + LEFT, + RIGHT; + } + + public enum SettingsTab { + PROFILE, + SYSTEM, + PASSWORD, + WEB_DAV, + TERMS_OF_USE; + } + + private FunctionalUtil functionalUtil; + + private String homeActionNavigationSelectedCss; + + private String homeActionPortalCss; + private String homeActionSettingsCss; + private String homeActionCalendarCss; + private String homeActionSubscriptionsCss; + private String homeActionBookmarksCss; + private String homeActionPersonalFolderCss; + private String homeActionNotesCss; + private String homeActionEvidencesOfAchievementCss; + + private String ePortfolioParentId; + private String ePortfolioActionMyArtifactsCss; + private String ePortfolioActionMyBindersCss; + private String ePortfolioActionMyPortfolioTasksCss; + private String ePortfolioActionReleasedBindersCss; + + private String portalEditLinkCss; + private String portalWrapperCss; + private String portalCss; + private String portalColumnCssPrefix; + private String portalSubcolumnsCss; + private String portalInactiveCss; + + private String portletCss; + private String portletEditCss; + private String portletInactiveCss; + + private String portletQuickstartCss; + private String portletRepositoryStudentCss; + private String portletRepositoryTeacherCss; + private String portletInfomessagesCss; + private String portletCalendarCss; + private String portletBookmarkCss; + private String portletGroupsCss; + private String portletNotiCss; + private String portletEffCss; + private String portletNotesCss; + private String portletDykCss; + + private String portletActivateCss; + private String portletInactivateCss; + private String portletMoveLeftCss; + private String portletMoveRightCss; + private String portletMoveUpCss; + private String portletMoveDownCss; + + private String prefsButtonsCss; + private String guiButtonsCss; + private String sysprefsButtonsCss; + + private String oldPasswordCss; + private String newPasswordCss; + private String confirmPasswordCss; + + /** + * @param functionalUtil + * + * Constructor + */ + public FunctionalHomeSiteUtil(FunctionalUtil functionalUtil){ + setUtil(functionalUtil); + + setHomeActionNavigationSelectedCss(HOME_SITE_MENU_TREE_SELECTED_CSS); + + setHomeActionPortalCss(HOME_ACTION_PORTAL_CSS); + setHomeActionSettingsCss(HOME_ACTION_SETTINGS_CSS); + setHomeActionCalendarCss(HOME_ACTION_CALENDAR_CSS); + setHomeActionSubscriptionsCss(HOME_ACTION_SUBSCRIPTIONS_CSS); + setHomeActionBookmarksCss(HOME_ACTION_BOOKMARKS_CSS); + setHomeActionPersonalFolderCss(HOME_ACTION_PERSONAL_FOLDER_CSS); + setHomeActionNotesCss(HOME_ACTION_NOTES_CSS); + setHomeActionEvidencesOfAchievementCss(HOME_ACTION_EVIDENCES_OF_ACHIEVEMENT_CSS); + + setEPortfolioParentId(EPORTFOLIO_PARENT_ID); + setEPortfolioActionMyArtifactsCss(EPORTFOLIO_ACTION_MY_ARTIFACTS_CSS); + setEPortfolioActionMyBindersCss(EPORTFOLIO_ACTION_MY_BINDERS_CSS); + setEPortfolioActionMyPortfolioTasksCss(EPORTFOLIO_ACTION_MY_PORTFOLIO_TASKS_CSS); + setEPortfolioActionReleasedBindersCss(EPORTFOLIO_ACTION_RELEASED_BINDERS_CSS); + + setPortalEditLinkCss(PORTAL_EDIT_LINK_CSS); + setPortalWrapperCss(PORTAL_WRAPPER_CSS); + setPortalCss(PORTAL_CSS); + setPortalColumnCssPrefix(PORTAL_COLUMN_CSS_PREFIX); + setPortalSubcolumnsCss(PORTAL_SUBCOLUMNS_CSS); + + setPortletCss(PORTLET_CSS); + setPortletEditCss(PORTLET_EDIT_CSS); + setPortletInactiveCss(PORTLET_INACTIVE_CSS); + + setPortletQuickstartCss(PORTLET_QUICKSTART_CSS); + setPortletRepositoryStudentCss(PORTLET_REPOSITORY_STUDENT_CSS); + setPortletRepositoryTeacherCss(PORTLET_REPOSITORY_TEACHER_CSS); + setPortletInfomessagesCss(PORTLET_INFOMESSAGES_CSS); + setPortletCalendarCss(PORTLET_CALENDAR_CSS); + setPortletBookmarkCss(PORTLET_BOOKMARK_CSS); + setPortletGroupsCss(PORTLET_GROUPS_CSS); + setPortletNotiCss(PORTLET_NOTI_CSS); + setPortletEffCss(PORTLET_EFF_CSS); + setPortletNotesCss(PORTLET_NOTES_CSS); + setPortletDykCss(PORTLET_DYK_CSS); + + setPortletActivateCss(PORTLET_EDIT_ACTIVATE_CSS); + setPortletInactivateCss(PORTLET_EDIT_INACTIVATE_CSS); + setPortletMoveLeftCss(PORTLET_MOVE_LEFT_CSS); + setPortletMoveRightCss(PORTLET_MOVE_RIGHT_CSS); + setPortletMoveUpCss(PORTLET_MOVE_UPWARDS_CSS); + setPortletMoveDownCss(PORTLET_MOVE_DOWNWARDS_CSS); + + setPrefsButtonsCss(PREFS_BUTTONS_CSS); + setGuiButtonsCss(GUI_BUTTONS_CSS); + setSysprefsButtonsCss(SYSPREFS_BUTTONS_CSS); + + setOldPasswordCss(OLD_PASSWORD_CSS); + setNewPasswordCss(NEW_PASSWORD_CSS); + setConfirmPasswordCss(CONFIRM_PASSWORD_CSS); + } + + /** + * @param page + * @return the matching CSS class + * + * Find the corresponding CSS class for page. + */ + public String findCssClassOfAction(Object page){ + if(page == null) + return(null); + + String selectedCss = null; + + if(page instanceof HomeSiteAction){ + switch((HomeSiteAction) page){ + case PORTAL: + { + selectedCss = getHomeActionPortalCss(); + break; + } + case SETTINGS: + { + selectedCss = getHomeActionSettingsCss(); + break; + } + case CALENDAR: + { + selectedCss = getHomeActionCalendarCss(); + break; + } + case SUBSCRIPTIONS: + { + selectedCss = getHomeActionSubscriptionsCss(); + break; + } + case BOOKMARKS: + { + selectedCss = getHomeActionBookmarksCss(); + break; + } + case PERSONAL_FOLDER: + { + selectedCss = getHomeActionPersonalFolderCss(); + break; + } + case NOTES: + { + selectedCss = getHomeActionNotesCss(); + break; + } + case EVIDENCES_OF_ACHIEVEMENT: + selectedCss = getHomeActionEvidencesOfAchievementCss(); + break; + } + }else if(page instanceof EPortfolioAction){ + switch((EPortfolioAction) page){ + case MY_ARTIFACTS: + { + selectedCss = getEPortfolioActionMyArtifactsCss(); + break; + } + case MY_BINDERS: + { + selectedCss = getEPortfolioActionMyBindersCss(); + break; + } + case MY_PORTFOLIO_TASKS: + { + selectedCss = getEPortfolioActionMyPortfolioTasksCss(); + break; + } + case RELEASED_BINDERS: + { + selectedCss = getEPortfolioActionReleasedBindersCss(); + break; + } + } + } + + return(selectedCss); + } + + /** + * @param browser + * @param action + * @return true if match otherwise false + * + * Check if the correct page is open. + */ + public boolean checkCurrentAction(Selenium browser, Object action){ + return(checkCurrentAction(browser, action, -1)); + } + + public boolean checkCurrentAction(Selenium browser, Object action, long timeout){ + String selectedCss = findCssClassOfAction(action); + + if(selectedCss == null) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=ul li.") + .append(selectedCss) + .append('.') + .append(getHomeActionNavigationSelectedCss()) + .append(" * a"); + + long timeElapsed = 0; + long startTime = Calendar.getInstance().getTimeInMillis(); + + do{ + if(browser.isElementPresent(selectorBuffer.toString())){ + return(true); + } + + if(timeout != -1){ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + //TODO:JK: Auto-generated catch block + e.printStackTrace(); + } + } + + timeElapsed = Calendar.getInstance().getTimeInMillis() - startTime; + }while(timeElapsed <= timeout && timeout != -1); + + return(false); + } + + /** + * @param browser + * @param action + * @return true on success otherwise false + * + * Browse the home site's menu tree. + */ + public boolean openActionByMenuTree(Selenium browser, Object action){ + return(openActionByMenuTree(browser, action, true)); + } + + /** + * @param browser + * @param action + * @param checkCurrentAction + * @return true on success otherwise false + * + * Browse the home site's menu tree. + */ + public boolean openActionByMenuTree(Selenium browser, Object action, boolean checkCurrentAction){ + String selectedCss = findCssClassOfAction(action); + + if(selectedCss == null){ + return(false); + } + + if(!checkCurrentAction || !checkCurrentAction(browser, action, Long.parseLong(functionalUtil.getWaitLimit()))){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//ul//li[contains(@class, '") + .append(selectedCss) + .append("')]//a"); + + if(action instanceof EPortfolioAction && !browser.isElementPresent(selectorBuffer.toString())){ + StringBuffer actionSelectorBuffer = new StringBuffer(); + + actionSelectorBuffer.append("xpath=//ul//div[@id='") + .append(getEPortfolioParentId()) + .append("']//a"); + + browser.click(actionSelectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + } + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + } + + return(true); + } + + /** + * @param browser + * + * Open portal in configuration mode. + */ + public void beginEditingPortal(Selenium browser){ + if(!functionalUtil.checkCurrentSite(browser, OlatSite.HOME)){ + functionalUtil.openSite(browser, OlatSite.HOME); + } + + /* goto home site */ + Assert.assertTrue(openActionByMenuTree(browser, HomeSiteAction.PORTAL)); + Assert.assertTrue(checkCurrentAction(browser, HomeSiteAction.PORTAL)); + + /* begin editing */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=.") + .append(PORTAL_EDIT_LINK_CSS) + .append(" * a"); + + browser.click(selectorBuffer.toString()); + } + + /** + * @param browser + * + * Close portal configuration mode. + */ + public void endEditingPortal(Selenium browser){ + if(!functionalUtil.checkCurrentSite(browser, OlatSite.HOME)){ + functionalUtil.openSite(browser, OlatSite.HOME); + } + + /* goto home site */ + Assert.assertTrue(openActionByMenuTree(browser, HomeSiteAction.PORTAL)); + Assert.assertTrue(checkCurrentAction(browser, HomeSiteAction.PORTAL)); + + /* end editing */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=.") + .append(PORTAL_EDIT_LINK_CSS) + .append(" * a"); + + browser.click(selectorBuffer.toString()); + } + + /** + * @param browser + * @param portletCss + * @return true if portlet active otherwise false + * + * Check the state of a portlet. + */ + public boolean checkPortletActive(Selenium browser, String portletCss){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[@class='") + .append(getPortalCss()) + .append(' ') + .append(getPortalSubcolumnsCss()) + .append("']//div[@class='") + .append(getPortletCss()) + .append(' ') + .append(portletCss) + .append("']"); + + if(browser.isElementPresent(selectorBuffer.toString())){ + return(true); + }else{ + /* selector of editing portlets */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[@class='") + .append(getPortalCss()) + .append(' ') + .append(getPortalSubcolumnsCss()) + .append("']//div[@class='") + .append(getPortletCss()) + .append(' ') + .append(getPortletEditCss()) + .append(' ') + .append(portletCss) + .append("']"); + + if(browser.isElementPresent(selectorBuffer.toString())){ + return(true); + }else{ + return(false); + } + } + } + + /** + * @param browser + * @param portletCss + * @param columnCount the count of columns to scan for + * @return the x and y position of the portlet, the result may be null if + * the portlet is inactive or doesn't exists. + * + * Find the position of the portlet within the portal. + */ + public int[] findPortletPosition(Selenium browser, String portletCss, int columnCount){ + for(int i = 0; i < columnCount; i++){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=.") + .append(getPortalCss()) + .append('.') + .append(getPortalSubcolumnsCss()) + .append(" .") + .append(getPortalColumnCssPrefix()) + .append(i + 1) + .append(" .") + .append(getPortletCss()) + .append('.') + .append(getPortletEditCss()) + .append('.') + .append(portletCss); + + if(browser.isElementPresent(selectorBuffer.toString())){ + int position[] = new int[2]; + + position[0] = i; + + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=.") + .append(getPortalCss()) + .append(" .") + .append(getPortalColumnCssPrefix()) + .append(i + 1) + .append(" .") + .append(getPortletCss()); + + VelocityContext context = new VelocityContext(); + + context.put("portalCss", getPortalCss()); + context.put("portalSubcolumnsCss", getPortalSubcolumnsCss()); + context.put("portletCss", getPortletCss()); + context.put("portalColumnCssPrefix", getPortalColumnCssPrefix()); + + context.put("portlet", portletCss); + + context.put("column", i); + context.put("j_stop", browser.getCssCount(selectorBuffer.toString()).intValue()); + + VelocityEngine engine = null; + + engine = new VelocityEngine(); + + StringWriter sw = new StringWriter(); + + try { + engine.evaluate(context, sw, "portletPosition", FunctionalHomeSiteUtil.class.getResourceAsStream("PortletPosition.vm")); + + Integer j = new Integer(browser.getEval(sw.toString())); + position[1] = j.intValue(); + + return(position); + } catch (ParseErrorException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (MethodInvocationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ResourceNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + + return(null); + } + } + + return(null); + } + + /** + * @param browser + * @param portletCss + * @return true if portlet was inactive and successfully activated + * otherwise false. + * + * Add specified portlet by its CSS class. + */ + public boolean activatePortlet(Selenium browser, String portletCss){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=.") + .append(getPortletCss()) + .append('.') + .append(getPortletInactiveCss()) + .append('.') + .append(portletCss) + .append(" .") + .append(getPortletActivateCss()) + .append(" * a"); + + if(browser.isElementPresent(selectorBuffer.toString())){ + browser.click(selectorBuffer.toString()); + + return(true); + }else{ + return(false); + } + } + + /** + * @param browser + * @param portletCss + * @return true if portlet was active and successfully deactivated + * otherwise false. + * + * Remove a portlet from portal. + */ + public boolean deactivatePortlet(Selenium browser, String portletCss){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=.") + .append(getPortletCss()) + .append('.') + .append(getPortletEditCss()) + .append('.') + .append(portletCss) + .append(" * .") + .append(getPortletInactivateCss()); + + if(browser.isElementPresent(selectorBuffer.toString())){ + browser.click(selectorBuffer.toString()); + + return(true); + }else{ + return(false); + } + } + + /** + * @param browser + * @param portletCss + * @param direction + * @return true if portlet was moved otherwise false + * + * Move a portlet to the given direction. + */ + public boolean movePortlet(Selenium browser, String portletCss, Direction direction){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=.") + .append(getPortletCss()) + .append('.') + .append(getPortletEditCss()) + .append('.') + .append(portletCss) + .append(" * ."); + + switch(direction){ + case LEFT: + { + selectorBuffer.append(getPortletMoveLeftCss()); + + break; + } + case RIGHT: + { + selectorBuffer.append(getPortletMoveRightCss()); + + break; + } + case UP: + { + selectorBuffer.append(getPortletMoveUpCss()); + + break; + } + case DOWN: + { + selectorBuffer.append(getPortletMoveDownCss()); + + break; + } + } + + if(browser.isElementPresent(selectorBuffer.toString())){ + browser.click(selectorBuffer.toString()); + + return(true); + }else{ + return(false); + } + + } + + + /** + * @param browser + * @param language permitted values are: en, es, fr, de, it + * + * Selects the specified language. + */ + public void selectLanguage(Selenium browser, String language){ + functionalUtil.openSite(browser, OlatSite.HOME); + + /* goto home site */ + Assert.assertTrue(openActionByMenuTree(browser, HomeSiteAction.SETTINGS)); + + /* open System tab */ + Assert.assertTrue(functionalUtil.openContentTab(browser, SettingsTab.SYSTEM.ordinal())); + + /* select language */ + functionalUtil.selectOption(browser, LANGUAGE_OPTIONS_ID, language); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form//div[contains(@class, '"); + selectorBuffer.append(getPrefsButtonsCss()); + selectorBuffer.append("')]//"); + selectorBuffer.append("button[@type='button']"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + } + + /** + * @param browser + * + * Enables resume in olat but you must be logged in. + */ + public void enableResume(Selenium browser){ + functionalUtil.openSite(browser, OlatSite.HOME); + + /* goto home site */ + Assert.assertTrue(openActionByMenuTree(browser, HomeSiteAction.SETTINGS)); + Assert.assertTrue(checkCurrentAction(browser, HomeSiteAction.SETTINGS)); + + /* open System tab */ + Assert.assertTrue(functionalUtil.openContentTab(browser, SettingsTab.SYSTEM.ordinal())); + + /* enable resume */ + Assert.assertTrue(functionalUtil.clickRadio(browser, + FunctionalHomeSiteUtil.PortalSettingsForms.SpecificSystemSettingsRadios.RESUME_LAST_SESSION.getGroupCss(), + FunctionalHomeSiteUtil.PortalSettingsForms.SpecificSystemSettingsRadios.ResumeLastSession.YES_AUTOMATICALLY.getValueAttribute())); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form//div[contains(@class, '"); + selectorBuffer.append(getGuiButtonsCss()); + selectorBuffer.append("')]//"); + selectorBuffer.append("button[@type='button']"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + } + + /** + * @param browser + * + * Enables resume on request in olat but you must be logged in. + */ + public void enableResumeOnRequest(Selenium browser){ + functionalUtil.openSite(browser, OlatSite.HOME); + + /* goto home site */ + Assert.assertTrue(openActionByMenuTree(browser, HomeSiteAction.SETTINGS)); + Assert.assertTrue(checkCurrentAction(browser, HomeSiteAction.SETTINGS)); + + /* open system tab */ + Assert.assertTrue(functionalUtil.openContentTab(browser, SettingsTab.SYSTEM.ordinal())); + + /* enable resume */ + Assert.assertTrue(functionalUtil.clickRadio(browser, + FunctionalHomeSiteUtil.PortalSettingsForms.SpecificSystemSettingsRadios.RESUME_LAST_SESSION.getGroupCss(), + FunctionalHomeSiteUtil.PortalSettingsForms.SpecificSystemSettingsRadios.ResumeLastSession.YES_ON_REQUEST.getValueAttribute())); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form//div[contains(@class, '"); + selectorBuffer.append(getGuiButtonsCss()); + selectorBuffer.append("')]//"); + selectorBuffer.append("button[@type='button']"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + } + + /** + * @param browser + * + * Disable resume in olat but you must be logged in. + */ + public boolean disableResume(Selenium browser){ + functionalUtil.openSite(browser, OlatSite.HOME); + + /* goto home site */ + Assert.assertTrue(openActionByMenuTree(browser, HomeSiteAction.SETTINGS)); + //Assert.assertTrue(checkCurrentAction(browser, HomeSiteAction.SETTINGS)); + + /* open system tab */ + Assert.assertTrue(functionalUtil.openContentTab(browser, SettingsTab.SYSTEM.ordinal())); + + /* disable resume */ + Assert.assertTrue(functionalUtil.clickRadio(browser, + FunctionalHomeSiteUtil.PortalSettingsForms.SpecificSystemSettingsRadios.RESUME_LAST_SESSION.getGroupCss(), + FunctionalHomeSiteUtil.PortalSettingsForms.SpecificSystemSettingsRadios.ResumeLastSession.NO.getValueAttribute())); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form//div[contains(@class, '"); + selectorBuffer.append(getGuiButtonsCss()); + selectorBuffer.append("')]//"); + selectorBuffer.append("button[@type='button']"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + + return(true); + } + + public boolean enableBack(Selenium browser){ + functionalUtil.openSite(browser, OlatSite.HOME); + + /* goto home site */ + Assert.assertTrue(openActionByMenuTree(browser, HomeSiteAction.SETTINGS)); + Assert.assertTrue(checkCurrentAction(browser, HomeSiteAction.SETTINGS)); + + /* open system tab */ + Assert.assertTrue(functionalUtil.openContentTab(browser, SettingsTab.SYSTEM.ordinal())); + + /* enable resume */ + Assert.assertTrue(functionalUtil.clickRadio(browser, + FunctionalHomeSiteUtil.PortalSettingsForms.SpecificSystemSettingsRadios.SUPPORT_FOR_BROWSER_BACK.getGroupCss(), + FunctionalHomeSiteUtil.PortalSettingsForms.SpecificSystemSettingsRadios.SupportForBrowserBack.ON.getValueAttribute())); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form//div[contains(@class, '"); + selectorBuffer.append(getGuiButtonsCss()); + selectorBuffer.append("')]//"); + selectorBuffer.append("button[@type='button']"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + + return(true); + } + + public boolean disableBack(Selenium browser){ + functionalUtil.openSite(browser, OlatSite.HOME); + + /* goto home site */ + Assert.assertTrue(openActionByMenuTree(browser, HomeSiteAction.SETTINGS)); + Assert.assertTrue(checkCurrentAction(browser, HomeSiteAction.SETTINGS)); + + /* open system tab */ + Assert.assertTrue(functionalUtil.openContentTab(browser, SettingsTab.SYSTEM.ordinal())); + + /* enable resume */ + Assert.assertTrue(functionalUtil.clickRadio(browser, + FunctionalHomeSiteUtil.PortalSettingsForms.SpecificSystemSettingsRadios.SUPPORT_FOR_BROWSER_BACK.getGroupCss(), + FunctionalHomeSiteUtil.PortalSettingsForms.SpecificSystemSettingsRadios.SupportForBrowserBack.OFF.getValueAttribute())); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form//div[contains(@class, '"); + selectorBuffer.append(getGuiButtonsCss()); + selectorBuffer.append("')]//"); + selectorBuffer.append("button[@type='button']"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + + return(true); + } + + /** + * @param browser + * @return true on success + * + * Resets portal settings to default. + */ + public boolean resetSettings(Selenium browser){ + log.info("open portal"); + functionalUtil.openSite(browser, OlatSite.HOME); + + /* open settings page */ + log.info("open settings tab"); + if(!openActionByMenuTree(browser, HomeSiteAction.SETTINGS)){ + return(false); + } + + /* click system tab */ + log.info("open system settings tab"); + functionalUtil.openContentTab(browser, SettingsTab.SYSTEM.ordinal()); + + /* using reset configurations form */ + /* click all checkboxes */ + log.info("clicking all reset configurations checkboxes"); + functionalUtil.clickCheckbox(browser, CONFIGURATIONS_CSS, GUI_PREFERENCES_VALUE); + + functionalUtil.clickCheckbox(browser, CONFIGURATIONS_CSS, SYS_PREFERENCES_VALUE); + + functionalUtil.clickCheckbox(browser, CONFIGURATIONS_CSS, RESUME_VALUE); + + /* click Reset */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form//div[contains(@class, '"); + selectorBuffer.append(getSysprefsButtonsCss()); + selectorBuffer.append("')]//"); + selectorBuffer.append("button[@type='button']"); + + log.info("submitting changes"); + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + //functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + + return(true); + } + + public FunctionalUtil getUtil() { + return functionalUtil; + } + + public void setUtil(FunctionalUtil functionalUtil) { + this.functionalUtil = functionalUtil; + } + + public String getHomeActionNavigationSelectedCss() { + return homeActionNavigationSelectedCss; + } + + public void setHomeActionNavigationSelectedCss( + String homeActionNavigationSelectedCss) { + this.homeActionNavigationSelectedCss = homeActionNavigationSelectedCss; + } + + public String getHomeActionPortalCss() { + return homeActionPortalCss; + } + + public void setHomeActionPortalCss(String homeActionPortalCss) { + this.homeActionPortalCss = homeActionPortalCss; + } + + public String getHomeActionSettingsCss() { + return homeActionSettingsCss; + } + + public void setHomeActionSettingsCss(String homeActionSettingsCss) { + this.homeActionSettingsCss = homeActionSettingsCss; + } + + public String getHomeActionCalendarCss() { + return homeActionCalendarCss; + } + + public void setHomeActionCalendarCss(String homeActionCalendarCss) { + this.homeActionCalendarCss = homeActionCalendarCss; + } + + public String getHomeActionSubscriptionsCss() { + return homeActionSubscriptionsCss; + } + + public void setHomeActionSubscriptionsCss(String homeActionSubscriptionsCss) { + this.homeActionSubscriptionsCss = homeActionSubscriptionsCss; + } + + public String getHomeActionBookmarksCss() { + return homeActionBookmarksCss; + } + + public void setHomeActionBookmarksCss(String homeActionBookmarksCss) { + this.homeActionBookmarksCss = homeActionBookmarksCss; + } + + public String getHomeActionPersonalFolderCss() { + return homeActionPersonalFolderCss; + } + + public void setHomeActionPersonalFolderCss(String homeActionPersonalFolderCss) { + this.homeActionPersonalFolderCss = homeActionPersonalFolderCss; + } + + public String getHomeActionNotesCss() { + return homeActionNotesCss; + } + + public void setHomeActionNotesCss(String homeActionNotesCss) { + this.homeActionNotesCss = homeActionNotesCss; + } + + public String getHomeActionEvidencesOfAchievementCss() { + return homeActionEvidencesOfAchievementCss; + } + + public void setHomeActionEvidencesOfAchievementCss( + String homeActionEvidencesOfAchievementCss) { + this.homeActionEvidencesOfAchievementCss = homeActionEvidencesOfAchievementCss; + } + + public String getEPortfolioParentId() { + return ePortfolioParentId; + } + + public void setEPortfolioParentId(String ePortfolioParentId) { + this.ePortfolioParentId = ePortfolioParentId; + } + + public String getEPortfolioActionMyArtifactsCss() { + return ePortfolioActionMyArtifactsCss; + } + + public void setEPortfolioActionMyArtifactsCss(String ePortfolioActionMyArtifactsCss) { + this.ePortfolioActionMyArtifactsCss = ePortfolioActionMyArtifactsCss; + } + + public String getEPortfolioActionMyBindersCss() { + return ePortfolioActionMyBindersCss; + } + + public void setEPortfolioActionMyBindersCss(String ePortfolioActionMyBindersCss) { + this.ePortfolioActionMyBindersCss = ePortfolioActionMyBindersCss; + } + + public String getEPortfolioActionMyPortfolioTasksCss() { + return ePortfolioActionMyPortfolioTasksCss; + } + + public void setEPortfolioActionMyPortfolioTasksCss( + String ePortfolioActionMyPortfolioTasksCss) { + this.ePortfolioActionMyPortfolioTasksCss = ePortfolioActionMyPortfolioTasksCss; + } + + public String getEPortfolioActionReleasedBindersCss() { + return ePortfolioActionReleasedBindersCss; + } + + public void setEPortfolioActionReleasedBindersCss( + String ePortfolioActionReleasedBindersCss) { + this.ePortfolioActionReleasedBindersCss = ePortfolioActionReleasedBindersCss; + } + + public String getPortalEditLinkCss() { + return portalEditLinkCss; + } + + public void setPortalEditLinkCss(String portalEditLinkCss) { + this.portalEditLinkCss = portalEditLinkCss; + } + + public String getPortalWrapperCss() { + return portalWrapperCss; + } + + public void setPortalWrapperCss(String portalWrapperCss) { + this.portalWrapperCss = portalWrapperCss; + } + + public String getPortalCss() { + return portalCss; + } + + public void setPortalCss(String portalCss) { + this.portalCss = portalCss; + } + + public String getPortalColumnCssPrefix() { + return portalColumnCssPrefix; + } + + public void setPortalColumnCssPrefix(String portalColumnCssPrefix) { + this.portalColumnCssPrefix = portalColumnCssPrefix; + } + + public String getPortalSubcolumnsCss() { + return portalSubcolumnsCss; + } + + public void setPortalSubcolumnsCss(String portalSubcolumnsCss) { + this.portalSubcolumnsCss = portalSubcolumnsCss; + } + + public String getPortalInactiveCss() { + return portalInactiveCss; + } + + public void setPortalInactiveCss(String portalInactiveCss) { + this.portalInactiveCss = portalInactiveCss; + } + + public String getPortletCss() { + return portletCss; + } + + public void setPortletCss(String portletCss) { + this.portletCss = portletCss; + } + + public String getPortletEditCss() { + return portletEditCss; + } + + public void setPortletEditCss(String portletEditCss) { + this.portletEditCss = portletEditCss; + } + + public String getPortletInactiveCss() { + return portletInactiveCss; + } + + public void setPortletInactiveCss(String portletInactiveCss) { + this.portletInactiveCss = portletInactiveCss; + } + + public String getPortletQuickstartCss() { + return portletQuickstartCss; + } + + public void setPortletQuickstartCss(String portletQuickstartCss) { + this.portletQuickstartCss = portletQuickstartCss; + } + + public String getPortletRepositoryStudentCss() { + return portletRepositoryStudentCss; + } + + public void setPortletRepositoryStudentCss(String portletRepositoryStudentCss) { + this.portletRepositoryStudentCss = portletRepositoryStudentCss; + } + + public String getPortletRepositoryTeacherCss() { + return portletRepositoryTeacherCss; + } + + public void setPortletRepositoryTeacherCss(String portletRepositoryTeacherCss) { + this.portletRepositoryTeacherCss = portletRepositoryTeacherCss; + } + + public String getPortletInfomessagesCss() { + return portletInfomessagesCss; + } + + public void setPortletInfomessagesCss(String portletInfomessagesCss) { + this.portletInfomessagesCss = portletInfomessagesCss; + } + + public String getPortletCalendarCss() { + return portletCalendarCss; + } + + public void setPortletCalendarCss(String portletCalendarCss) { + this.portletCalendarCss = portletCalendarCss; + } + + public String getPortletBookmarkCss() { + return portletBookmarkCss; + } + + public void setPortletBookmarkCss(String portletBookmarkCss) { + this.portletBookmarkCss = portletBookmarkCss; + } + + public String getPortletGroupsCss() { + return portletGroupsCss; + } + + public void setPortletGroupsCss(String portletGroupsCss) { + this.portletGroupsCss = portletGroupsCss; + } + + public String getPortletNotiCss() { + return portletNotiCss; + } + + public void setPortletNotiCss(String portletNotiCss) { + this.portletNotiCss = portletNotiCss; + } + + public String getPortletEffCss() { + return portletEffCss; + } + + public void setPortletEffCss(String portletEffCss) { + this.portletEffCss = portletEffCss; + } + + public String getPortletNotesCss() { + return portletNotesCss; + } + + public void setPortletNotesCss(String portletNotesCss) { + this.portletNotesCss = portletNotesCss; + } + + public String getPortletDykCss() { + return portletDykCss; + } + + public void setPortletDykCss(String portletDykCss) { + this.portletDykCss = portletDykCss; + } + + public String getPortletActivateCss() { + return portletActivateCss; + } + + public void setPortletActivateCss(String portletActivateCss) { + this.portletActivateCss = portletActivateCss; + } + + public String getPortletInactivateCss() { + return portletInactivateCss; + } + + public void setPortletInactivateCss(String portletInactivateCss) { + this.portletInactivateCss = portletInactivateCss; + } + + public String getPortletMoveLeftCss() { + return portletMoveLeftCss; + } + + public void setPortletMoveLeftCss(String portletMoveLeftCss) { + this.portletMoveLeftCss = portletMoveLeftCss; + } + + public String getPortletMoveRightCss() { + return portletMoveRightCss; + } + + public void setPortletMoveRightCss(String portletMoveRightCss) { + this.portletMoveRightCss = portletMoveRightCss; + } + + public String getPortletMoveUpCss() { + return portletMoveUpCss; + } + + public void setPortletMoveUpCss(String portletMoveUpCss) { + this.portletMoveUpCss = portletMoveUpCss; + } + + public String getPortletMoveDownCss() { + return portletMoveDownCss; + } + + public void setPortletMoveDownCss(String portletMoveDownCss) { + this.portletMoveDownCss = portletMoveDownCss; + } + + public String getPrefsButtonsCss() { + return prefsButtonsCss; + } + + public void setPrefsButtonsCss(String prefsButtonsCss) { + this.prefsButtonsCss = prefsButtonsCss; + } + + public String getGuiButtonsCss() { + return guiButtonsCss; + } + + public void setGuiButtonsCss(String guiButtonsCss) { + this.guiButtonsCss = guiButtonsCss; + } + + public String getSysprefsButtonsCss() { + return sysprefsButtonsCss; + } + + public void setSysprefsButtonsCss(String sysprefsButtonsCss) { + this.sysprefsButtonsCss = sysprefsButtonsCss; + } + + public String getOldPasswordCss() { + return oldPasswordCss; + } + + public void setOldPasswordCss(String oldPasswordCss) { + this.oldPasswordCss = oldPasswordCss; + } + + public String getNewPasswordCss() { + return newPasswordCss; + } + + public void setNewPasswordCss(String newPasswordCss) { + this.newPasswordCss = newPasswordCss; + } + + public String getConfirmPasswordCss() { + return confirmPasswordCss; + } + + public void setConfirmPasswordCss(String confirmPasswordCss) { + this.confirmPasswordCss = confirmPasswordCss; + } +} diff --git a/src/test/java/org/olat/util/FunctionalLocatorPairsFactory.java b/src/test/java/org/olat/util/FunctionalLocatorPairsFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..00bf5a7c1d62bdba5c525db933ab08f57136e7b6 --- /dev/null +++ b/src/test/java/org/olat/util/FunctionalLocatorPairsFactory.java @@ -0,0 +1,66 @@ +/** + * <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.util; + +/** + * Description: <br> + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +public class FunctionalLocatorPairsFactory { + private FunctionalUtil functionalUtil; + + public FunctionalLocatorPairsFactory(FunctionalUtil functionalUtil){ + this.functionalUtil = functionalUtil; + } + + public String getLocatorOfSite(String site){ + StringBuffer locatorBuffer = new StringBuffer(); + + locatorBuffer.append("css=.") + .append(functionalUtil.getOlatNavigationSiteCss()) + .append(".") + .append(site) + .append(" a"); + + return(locatorBuffer.toString()); + } + + public String getApprovalOfSite(String site){ + StringBuffer approvalBuffer = new StringBuffer(); + + approvalBuffer.append("css=.") + .append(functionalUtil.getOlatNavigationSiteCss()) + .append(".") + .append(functionalUtil.getOlatActiveNavigationSiteCss()) + .append(".") + .append(site); + + return(approvalBuffer.toString()); + } + + public FunctionalUtil getFunctionalUtil() { + return functionalUtil; + } + + public void setFunctionalUtil(FunctionalUtil functionalUtil) { + this.functionalUtil = functionalUtil; + } +} diff --git a/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java b/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..a1d874dbe4db61de36e91ed6a48ceeb8e41e01d5 --- /dev/null +++ b/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java @@ -0,0 +1,1101 @@ +/** + * <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.util; + +import java.io.IOException; +import java.util.List; + +import org.olat.util.FunctionalUtil.OlatSite; + +import com.thoughtworks.selenium.Selenium; + +/** + * Description: <br> + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +public class FunctionalRepositorySiteUtil { + + public final static String REPOSITORY_POPUP_CSS = "o_sel_edit_repositoryentry_popup"; + public final static String REPOSITORY_SAVE_DETAILS_CSS = "o_sel_repo_save_details"; + public final static String REPOSITORY_ADD_FORWARD_CSS = "o_sel_repo_add_forward"; + + public final static String COURSE_WIZARD_PUBLISH_CHECKBOX = "publishCheckbox"; + public final static String COURSE_WIZARD_ACCESS_OPTION_ID = "o_fioaccessChooser_SELBOX"; + + public final static String REPOSITORY_SITE_MENU_TREE_SELECTED_CSS = "b_tree_selected"; + + public final static String REPOSITORY_SITE_CATALOG_CSS = "o_sel_repo_catalog"; + public final static String REPOSITORY_SITE_SEARCH_FORM_CSS = "o_sel_repo_search_generic"; + public final static String REPOSITORY_SITE_MY_ENTRIES_CSS = "o_sel_repo_my"; + public final static String REPOSITORY_SITE_MY_COURSES_CSS = "o_sel_repo_my_student"; + public final static String REPOSITORY_SITE_MY_SUPERVISED_COURSES_CSS = "o_sel_repo_my_teacher"; + public final static String REPOSITORY_SITE_COURSES_CSS = "o_sel_repo_course"; + public final static String REPOSITORY_SITE_CP_LEARNING_CONTENT_CSS = "o_sel_repo_cp"; + public final static String REPOSITORY_SITE_SCORM_LEARNING_CONTENT_CSS = "o_sel_repo_scorm"; + public final static String REPOSITORY_SITE_WIKIS_CSS = "o_sel_repo_wiki"; + public final static String REPOSITORY_SITE_PODCASTS_CSS = "o_sel_repo_podcast"; + public final static String REPOSITORY_SITE_BLOGS_CSS = "o_sel_repo_blog"; + public final static String REPOSITORY_SITE_PORTFOLIO_TEMPLATES_CSS = "o_sel_repo_portfolio"; + public final static String REPOSITORY_SITE_TESTS_CSS = "o_sel_repo_test"; + public final static String REPOSITORY_SITE_QUESTIONAIRES_CSS = "o_sel_repo_survey"; + public final static String REPOSITORY_SITE_RESOURCE_FOLDER_CSS = "o_sel_repo_sharefolder"; + public final static String REPOSITORY_SITE_GLOSSARY_CSS = "o_sel_repo_glossary"; + + public enum Column { + AC, + TYPE, + TITLE_OF_LEARNING_RESOURCE, + AUTHOR, + ACCESS, + CREATED, + LAST_ACCESS, + DETAILED_VIEW; + } + + public final static String CP_LEARNING_CONTENT_ALIAS = "cp"; + public final static String WIKI_ALIAS = "wiki"; + public final static String PODCAST_ALIAS = "podcast"; + public final static String BLOG_ALIAS = "blog"; + public final static String PORTFOLIO_ALIAS = "portfolio"; + public final static String IQTEST_ALIAS = "iqtest"; + public final static String QUESTIONAIRE_ALIAS = "iqsurv"; + public final static String RESOURCE_FOLDER_ALIAS = "bc"; + public final static String GLOSSARY_ALIAS = "glossary"; + + public final static String TITLE_OF_LEARNING_RESOURCE_CSS = "o_sel_repo_search_displayname"; + public final static String AUTHOR_CSS = "o_sel_repo_search_author"; + public final static String DESCRIPTION_CSS = "o_sel_repo_search_description"; + public final static String ID_CSS = "o_sel_repo_search_id"; + public final static String LIMIT_SEARCH_CSS = "o_sel_repo_search_type_limit"; + + public enum SearchField { + TITLE_OF_LEARNING_RESOURCE(TITLE_OF_LEARNING_RESOURCE_CSS), + AUTHOR(AUTHOR_CSS), + DESCRIPTION(DESCRIPTION_CSS), + ID(ID_CSS), + LIMIT_SEARCH(LIMIT_SEARCH_CSS); + + private String entryCss; + + SearchField(String entryCss){ + setEntryCss(entryCss); + } + + public String getEntryCss() { + return entryCss; + } + + public void setEntryCss(String entryCss) { + this.entryCss = entryCss; + } + } + + public enum RepositorySiteAction { + CATALOG, + SEARCH_FORM, + MY_ENTRIES, + MY_COURSES, + MY_SUPERVISED_COURSES, + COURSES, + CP_LEARNING_CONTENT, + SCORM_LEARNING_CONTENT, + WIKIS, + PODCASTS, + BLOGS, + PORTFOLIO_TEMPLATES, + TESTS, + QUESTIONAIRES, + RESOURCE_FOLDER, + GLOSSARY; + } + + public enum AccessSettings { + ONLY_OWNERS, + OWNERS_AND_AUTHORS, + USERS, + USERS_AND_GUESTS, + MEMBERS_ONLY; + } + + public enum NextSteps { + WIZARD("sw"), + COURSE_EDITOR("ce"), + DETAILED_VIEW("dv"); + + private String value; + + NextSteps(String value){ + setValue(value); + } + + public String getValue(){ + return(value); + } + + public void setValue(String value){ + this.value = value; + } + } + + public enum CourseWizardElement { + INFO_PAGE("sp"), + ENROLLMENT("en"), + DOWNLOAD_FOLDER("bc"), + FORUM("fo"), + EMAIL("co"); + + private String value; + + CourseWizardElement(String value){ + setValue(value); + } + + public String getValue(){ + return(value); + } + + public void setValue(String value){ + this.value = value; + } + } + + public enum CourseWizardAccess { + USERS("acl_olat"), + USERS_AND_GUESTS("acl_guest"); + + private String value; + + CourseWizardAccess(String value){ + setValue(value); + } + + public String getValue(){ + return(value); + } + + public void setValue(String value){ + this.value = value; + } + } + + public final static String TOOLBOX_CONTENT_CSS = "b_toolbox_content"; + public final static String TOOLBOX_COURSE_CSS = "o_toolbox_course"; + public final static String TOOLBOX_CONTENT_PACKAGE_CSS = "o_toolbox_content"; + public final static String TOOLBOX_WIKI_CSS = "o_toolbox_wiki"; + public final static String TOOLBOX_PODCAST_CSS = "o_toolbox_podcast"; + public final static String TOOLBOX_BLOG_CSS = "o_toolbox_blog"; + public final static String TOOLBOX_PORTFOLIO_CSS = "o_toolbox_portfolio"; + public final static String TOOLBOX_IQTEST_CSS = "o_toolbox_test"; + public final static String TOOLBOX_QUESTIONNAIRE_CSS = "o_toolbox_questionnaire"; + public final static String TOOLBOX_SHAREDFOLDER_CSS = "o_toolbox_sharedfolder"; + public final static String TOOLBOX_GLOSSARY_CSS = "o_toolbox_glossary"; + + private String repositoryPopupCss; + private String repositorySaveDetailsCss; + private String repositoryAddForwardCss; + + private String courseWizardPublishCheckbox; + private String courseWizardAccessOptionCss; + + private String repositorySiteMenuTreeSelectedCss; + + private String repositorySiteCatalogCss; + private String repositorySiteSearchFormCss; + private String repositorySiteMyEntriesCss; + private String repositorySiteMyCoursesCss; + private String repositorySiteMySupervisedCoursesCss; + private String repositorySiteCoursesCss; + private String repositorySiteCPLearningContentCss; + private String repositorySiteScormLearningContentCss; + private String repositorySiteWikisCss; + private String repositorySitePodcastsCss; + private String repositorySiteBlogsCss; + private String repositorySitePortfolioTemplatesCss; + private String repositorySiteTestsCss; + private String repositorySiteQuestionairesCss; + private String repositorySiteResourceFolderCss; + private String repositorySiteGlossaryCss; + + private String toolboxContentCss; + private String toolboxCourseCss; + private String toolboxContentPackageCss; + private String toolboxWikiCss; + private String toolboxPodcastCss; + private String toolboxBlogCss; + private String toolboxPortfolioCss; + private String toolboxIQTestCss; + private String toolboxQuestionnaireCss; + private String toolboxSharedfolderCss; + private String toolboxGlossaryCss; + + private FunctionalUtil functionalUtil; + + + public FunctionalRepositorySiteUtil(FunctionalUtil functionalUtil){ + setRepositoryPopupCss(REPOSITORY_POPUP_CSS); + setRepositorySaveDetailsCss(REPOSITORY_SAVE_DETAILS_CSS); + setRepositoryAddForwardCss(REPOSITORY_ADD_FORWARD_CSS); + + setCourseWizardPublishCheckbox(COURSE_WIZARD_PUBLISH_CHECKBOX); + setCourseWizardAccessOptionId(COURSE_WIZARD_ACCESS_OPTION_ID); + + setRepositorySiteMenuTreeSelectedCss(REPOSITORY_SITE_MENU_TREE_SELECTED_CSS); + + setRepositorySiteCatalogCss(REPOSITORY_SITE_CATALOG_CSS); + setRepositorySiteSearchFormCss(REPOSITORY_SITE_SEARCH_FORM_CSS); + setRepositorySiteMyEntriesCss(REPOSITORY_SITE_MY_ENTRIES_CSS); + setRepositorySiteMyCoursesCss(REPOSITORY_SITE_MY_COURSES_CSS); + setRepositorySiteMySupervisedCoursesCss(REPOSITORY_SITE_MY_SUPERVISED_COURSES_CSS); + setRepositorySiteCoursesCss(REPOSITORY_SITE_COURSES_CSS); + setRepositorySiteCPLearningContentCss(REPOSITORY_SITE_CP_LEARNING_CONTENT_CSS); + setRepositorySiteScormLearningContentCss(REPOSITORY_SITE_SCORM_LEARNING_CONTENT_CSS); + setRepositorySiteWikisCss(REPOSITORY_SITE_WIKIS_CSS); + setRepositorySitePodcastsCss(REPOSITORY_SITE_PODCASTS_CSS); + setRepositorySiteBlogsCss(REPOSITORY_SITE_BLOGS_CSS); + setRepositorySitePortfolioTemplatesCss(REPOSITORY_SITE_PORTFOLIO_TEMPLATES_CSS); + setRepositorySiteTestsCss(REPOSITORY_SITE_TESTS_CSS); + setRepositorySiteQuestionairesCss(REPOSITORY_SITE_QUESTIONAIRES_CSS); + setRepositorySiteResourceFolderCss(REPOSITORY_SITE_RESOURCE_FOLDER_CSS); + setRepositorySiteGlossaryCss(REPOSITORY_SITE_GLOSSARY_CSS); + + setToolboxContentCss(TOOLBOX_CONTENT_CSS); + setToolboxCourseCss(TOOLBOX_COURSE_CSS); + setToolboxContentPackageCss(TOOLBOX_CONTENT_PACKAGE_CSS); + setToolboxWikiCss(TOOLBOX_WIKI_CSS); + setToolboxPodcastCss(TOOLBOX_PODCAST_CSS); + setToolboxBlogCss(TOOLBOX_BLOG_CSS); + setToolboxPortfolioCss(TOOLBOX_PORTFOLIO_CSS); + setToolboxIQTestCss(TOOLBOX_IQTEST_CSS); + setToolboxQuestionnaireCss(TOOLBOX_QUESTIONNAIRE_CSS); + setToolboxSharedfolderCss(TOOLBOX_SHAREDFOLDER_CSS); + setToolboxGlossaryCss(TOOLBOX_GLOSSARY_CSS); + + setFunctionalUtil(functionalUtil); + } + + public boolean displayColumns(Selenium browser, List<Column> column){ + //TODO:JK: implement me + + return(false); + } + + /** + * @param action + * @return the matching CSS class + * + * Find the corresponding CSS class for page. + */ + public String findCssClassOfAction(Object action){ + if(action == null) + return(null); + + String selectedCss = null; + + switch((RepositorySiteAction) action){ + case CATALOG: + { + selectedCss = getRepositorySiteCatalogCss(); + break; + } + case SEARCH_FORM: + { + selectedCss = getRepositorySiteSearchFormCss(); + break; + } + case MY_ENTRIES: + { + selectedCss = getRepositorySiteMyEntriesCss(); + break; + } + case MY_COURSES: + { + selectedCss = getRepositorySiteMyCoursesCss(); + break; + } + case MY_SUPERVISED_COURSES: + { + selectedCss = getRepositorySiteMySupervisedCoursesCss(); + break; + } + case COURSES: + { + selectedCss = getRepositorySiteCoursesCss(); + break; + } + case CP_LEARNING_CONTENT: + { + selectedCss = getRepositorySiteCPLearningContentCss(); + break; + } + case SCORM_LEARNING_CONTENT: + { + selectedCss = getRepositorySiteScormLearningContentCss(); + break; + } + case WIKIS: + { + selectedCss = getRepositorySiteWikisCss(); + break; + } + case PODCASTS: + { + selectedCss = getRepositorySitePodcastsCss(); + break; + } + case BLOGS: + { + selectedCss = getRepositorySiteBlogsCss(); + break; + } + case PORTFOLIO_TEMPLATES: + { + selectedCss = getRepositorySitePortfolioTemplatesCss(); + break; + } + case TESTS: + { + selectedCss = getRepositorySiteTestsCss(); + break; + } + case QUESTIONAIRES: + { + selectedCss = getRepositorySiteQuestionairesCss(); + break; + } + case RESOURCE_FOLDER: + { + selectedCss = getRepositorySiteResourceFolderCss(); + break; + } + case GLOSSARY: + { + selectedCss = getRepositorySiteGlossaryCss(); + break; + } + } + + return(selectedCss); + } + + /** + * @param browser + * @param action + * @return true if match otherwise false + * + * Check if the correct page is open. + */ + public boolean checkCurrentPage(Selenium browser, Object action){ + String selectedCss = findCssClassOfAction(action); + + if(selectedCss == null) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=ul .") + .append(selectedCss) + .append('.') + .append(getRepositorySiteMenuTreeSelectedCss()) + .append(" * a"); + + if(browser.isElementPresent(selectorBuffer.toString())){ + return(true); + }else{ + return(false); + } + } + + /** + * @param browser + * @param action + * @return true on success otherwise false + * + * Browse the learning resources site's navigation. + */ + public boolean openActionByMenuTree(Selenium browser, Object action){ //activateMenuTreeAction(browser, action) + String selectedCss = findCssClassOfAction(action); + + if(selectedCss == null){ + return(false); + } + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=ul .") + .append(selectedCss) + .append(" * a"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param key + * @return true on success otherwise false + * + * Opens a course by using business path. + */ + public boolean openCourse(Selenium browser, long key){ + browser.open(functionalUtil.getDeploymentPath() + "/url/RepositoryEntry/" + key); + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param key + * @return true on success otherwise false + * + * Opens a course matching key by using the search form. + */ + public boolean openCourseWithoutBusinessPath(Selenium browser, Long key){ + if(!functionalUtil.openSite(browser, OlatSite.LEARNING_RESOURCES)) + return(false); + + if(!openActionByMenuTree(browser, RepositorySiteAction.SEARCH_FORM)) + return(false); + + //FIXME:JK: use CSS classes instead of ordinal + int searchFormIndex = 0; + + /* open search form */ + functionalUtil.typeText(browser, SearchField.ID.getEntryCss(), key.toString()); + + /* click search */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form[") + .append(searchFormIndex + 1) + .append("]") + .append("//div[@class='b_form_element']") + .append("//a[@class='b_button']"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + + /* click course */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("//form") + .append("//tr[contains(@class,'b_first_child') and contains(@class, 'b_last_child')]") + .append("//td[3]") //FIXME:JK: this isn't very safe + .append("//a"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param key + * @return + * + * Opens the appropriate detailed view. + */ + public boolean openDetailedView(Selenium browser, Long key){ + //TODO:JK: implement me + + return(false); + } + + /** + * @param browser + * @param settings + * @return + */ + public boolean modifySettings(Selenium browser, AccessSettings settings){ + //TODO:JK: implement me + + return(false); + } + + public String findCssClassOfCourseAlias(String descriptor){ + //TODO:JK: implement me + + return(null); + } + + public boolean createCourseNode(Selenium browser, String alias, String title, String description){ + //TODO:JK: implement me + + return(false); + } + + /** + * @param browser + * @param nodeCss + * @return + * + * Clicks create course node of given CSS class. + */ + private boolean clickCreate(Selenium browser, String nodeCss){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getToolboxContentCss()) + .append("')]//ul//li//a[contains(@class, '") + .append(nodeCss) + .append("')]"); + + browser.click(selectorBuffer.toString()); + + return(true); + } + + + /** + * @param browser + * @param title + * @param nth + * @return true on success + * + * Opens the detail view of a specified learning resource. + */ + public boolean openDetailView(Selenium browser, String title, int nth){ + if(!functionalUtil.openSite(browser, OlatSite.LEARNING_RESOURCES)) + return(false); + + //FIXME:JK: use CSS classes instead of ordinal + int searchFormIndex = 0; + + /* open search form */ + functionalUtil.typeText(browser, SearchField.ID.getEntryCss(), title); + + /* click search */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form[") + .append(searchFormIndex + 1) + .append("]") + .append("//div[@class='b_form_element']") + .append("//a[@class='b_button']"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + + /* click course */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("//form") + .append("//tr[") + .append(nth) + .append("]") + .append("//td[6]") //FIXME:JK: this isn't very safe + .append("//a"); + + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @return the id + */ + private long readIdFromDetailView(Selenium browser){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath="); + //TODO:JK: implement me + + long id = Long.parseLong(browser.getText(selectorBuffer.toString())); + + return(id); + } + /** + * @param browser + * @param title + * @param description + * @return true on success + */ + private boolean fillInTitleAndDescription(Selenium browser, String title, String description){ + /* fill in wizard - title */ + StringBuffer locatorBuffer = new StringBuffer(); + + locatorBuffer.append("xpath=//form//div[contains(@class, '") + .append(functionalUtil.getWizardCss()) + .append("')]//input[@type='text']"); + + browser.type(locatorBuffer.toString(), title); + + /* fill in wizard - description */ + functionalUtil.typeMCE(browser, description); + + /* fill in wizard - click save */ + functionalUtil.saveForm(browser, 0); + + return(true); + } + + /** + * @param browser + * @param title + * @param description + * @return the learning resource's id + * @throws IOException + * + * Creates a new blog in the repository. + */ + public long createBlog(Selenium browser, String title, String description) throws IOException{ + if(!functionalUtil.openSite(browser, OlatSite.LEARNING_RESOURCES)) + throw(new IOException("can't open olat site of learning resources")); + + /* open wizard */ + if(!clickCreate(browser, getToolboxBlogCss())) + throw(new IOException("can't open create wizard of blog")); + + if(!openDetailView(browser, title, 0)) + throw(new IOException("can't open detail view")); + + long id = readIdFromDetailView(browser); + + /* fill in wizard - title and description */ + if(!fillInTitleAndDescription(browser, title, description)) + throw(new IOException("failed to fill in title and description")); + + /* fill in wizard - click next */ + functionalUtil.clickWizardNext(browser); + + /* click no, we don't want to open the editor */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(functionalUtil.getWizardCss()) + .append("']//form//");//TODO:JK: implement me + + browser.click(selectorBuffer.toString()); + + return(id); + } + + /** + * @param browser + * @param title + * @param description + * @return + * + * + */ + public boolean fillInRepositoryEntryPopup(Selenium browser, String title, String description){ + /* fill in title */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(getRepositoryPopupCss()) + .append("')]//form//input[@type='text']"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.type(selectorBuffer.toString(), title); + + /* fill in description */ + functionalUtil.typeMCE(browser, getRepositoryPopupCss(), description); + + /* click save */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, '") + .append(getRepositoryPopupCss()) + .append("')]//form//div[contains(@class, '") + .append(getRepositorySaveDetailsCss()) + .append("')]//button)[1]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + + browser.click(selectorBuffer.toString()); + + /* click next */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, 'b_window')]//a[contains(@class, '") + .append(getRepositoryAddForwardCss()) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToUnloadElement(browser, selectorBuffer.toString()); + + return(true); + } + + /** + * @param browser + * @param title + * @param description + * @param element + * @param catalog + * @param publish + * @param access + * @return true on success + * + * Creates a course using the wizard whereas the specified settings + * will applied. + */ + public boolean createCourseUsingWizard(Selenium browser, String title, String description, + CourseWizardElement[] element, String catalog, boolean publish, CourseWizardAccess access){ + if(!clickCreate(browser, getToolboxCourseCss())){ + return(false); + } + + if(!fillInRepositoryEntryPopup(browser, title, description)){ + return(false); + } + + /* select wizard */ + functionalUtil.clickRadio(browser, null, NextSteps.WIZARD.getValue()); + + /* click next */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, '") + .append(getRepositoryAddForwardCss()) + .append("')]//button)[last()]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToUnloadElement(browser, selectorBuffer.toString()); + + /* select course element */ + for(CourseWizardElement current: element){ + functionalUtil.clickCheckbox(browser, null, current.getValue()); + } + + functionalUtil.clickWizardNext(browser); + + /* catalog */ + if(catalog != null){ + //TODO:JK: implement me + } + + functionalUtil.clickWizardNext(browser); + + /* publish */ + if(!publish){ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, 'b_wizard')]//input[@type='checkbox' and @name='") + .append(getCourseWizardPublishCheckbox()) + .append("']"); + + browser.click(selectorBuffer.toString()); + } + + if(access != null){ + functionalUtil.selectOption(browser, getCourseWizardAccessOptionId(), access.getValue()); + } + + functionalUtil.clickWizardFinish(browser); + + return(true); + } + + public String getRepositoryPopupCss() { + return repositoryPopupCss; + } + + public void setRepositoryPopupCss(String repositoryPopupCss) { + this.repositoryPopupCss = repositoryPopupCss; + } + + public String getRepositorySaveDetailsCss() { + return repositorySaveDetailsCss; + } + + public void setRepositorySaveDetailsCss(String repositorySaveDetailsCss) { + this.repositorySaveDetailsCss = repositorySaveDetailsCss; + } + + public String getRepositoryAddForwardCss() { + return repositoryAddForwardCss; + } + + public void setRepositoryAddForwardCss(String repositoryAddForwardCss) { + this.repositoryAddForwardCss = repositoryAddForwardCss; + } + + public String getCourseWizardPublishCheckbox() { + return courseWizardPublishCheckbox; + } + + public void setCourseWizardPublishCheckbox(String courseWizardPublishCheckbox) { + this.courseWizardPublishCheckbox = courseWizardPublishCheckbox; + } + + public String getCourseWizardAccessOptionId() { + return courseWizardAccessOptionCss; + } + + public void setCourseWizardAccessOptionId(String courseWizardAccessOptionCss) { + this.courseWizardAccessOptionCss = courseWizardAccessOptionCss; + } + + public String getRepositorySiteMenuTreeSelectedCss() { + return repositorySiteMenuTreeSelectedCss; + } + + public void setRepositorySiteMenuTreeSelectedCss( + String repositorySitePageNavigationSelectedCss) { + this.repositorySiteMenuTreeSelectedCss = repositorySitePageNavigationSelectedCss; + } + + public String getRepositorySiteCatalogCss() { + return repositorySiteCatalogCss; + } + + public void setRepositorySiteCatalogCss(String repositorySiteCatalogCss) { + this.repositorySiteCatalogCss = repositorySiteCatalogCss; + } + + public String getRepositorySiteSearchFormCss() { + return repositorySiteSearchFormCss; + } + + public void setRepositorySiteSearchFormCss( + String repositorySiteSearchFormCss) { + this.repositorySiteSearchFormCss = repositorySiteSearchFormCss; + } + + public String getRepositorySiteMyEntriesCss() { + return repositorySiteMyEntriesCss; + } + + public void setRepositorySiteMyEntriesCss( + String repositorySiteMyEntriesCss) { + this.repositorySiteMyEntriesCss = repositorySiteMyEntriesCss; + } + + public String getRepositorySiteMyCoursesCss() { + return repositorySiteMyCoursesCss; + } + + public void setRepositorySiteMyCoursesCss( + String repositorySiteMyCoursesCss) { + this.repositorySiteMyCoursesCss = repositorySiteMyCoursesCss; + } + + public String getRepositorySiteMySupervisedCoursesCss() { + return repositorySiteMySupervisedCoursesCss; + } + + public void setRepositorySiteMySupervisedCoursesCss( + String repositorySiteMySupervisedCoursesCss) { + this.repositorySiteMySupervisedCoursesCss = repositorySiteMySupervisedCoursesCss; + } + + public String getRepositorySiteCoursesCss() { + return repositorySiteCoursesCss; + } + + public void setRepositorySiteCoursesCss(String repositorySiteCoursesCss) { + this.repositorySiteCoursesCss = repositorySiteCoursesCss; + } + + public String getRepositorySiteCPLearningContentCss() { + return repositorySiteCPLearningContentCss; + } + + public void setRepositorySiteCPLearningContentCss( + String repositorySiteCPLearningContentCss) { + this.repositorySiteCPLearningContentCss = repositorySiteCPLearningContentCss; + } + + public String getRepositorySiteScormLearningContentCss() { + return repositorySiteScormLearningContentCss; + } + + public void setRepositorySiteScormLearningContentCss( + String repositorySiteScormLearningContentCss) { + this.repositorySiteScormLearningContentCss = repositorySiteScormLearningContentCss; + } + + public String getRepositorySiteWikisCss() { + return repositorySiteWikisCss; + } + + public void setRepositorySiteWikisCss(String repositorySiteWikisCss) { + this.repositorySiteWikisCss = repositorySiteWikisCss; + } + + public String getRepositorySitePodcastsCss() { + return repositorySitePodcastsCss; + } + + public void setRepositorySitePodcastsCss(String repositorySitePodcastsCss) { + this.repositorySitePodcastsCss = repositorySitePodcastsCss; + } + + public String getRepositorySiteBlogsCss() { + return repositorySiteBlogsCss; + } + + public void setRepositorySiteBlogsCss(String repositorySiteBlogsCss) { + this.repositorySiteBlogsCss = repositorySiteBlogsCss; + } + + public String getRepositorySitePortfolioTemplatesCss() { + return repositorySitePortfolioTemplatesCss; + } + + public void setRepositorySitePortfolioTemplatesCss( + String repositorySitePortfolioTemplatesCss) { + this.repositorySitePortfolioTemplatesCss = repositorySitePortfolioTemplatesCss; + } + + public String getRepositorySiteTestsCss() { + return repositorySiteTestsCss; + } + + public void setRepositorySiteTestsCss(String repositorySiteTestsCss) { + this.repositorySiteTestsCss = repositorySiteTestsCss; + } + + public String getRepositorySiteQuestionairesCss() { + return repositorySiteQuestionairesCss; + } + + public void setRepositorySiteQuestionairesCss( + String repositorySiteQuestionairesCss) { + this.repositorySiteQuestionairesCss = repositorySiteQuestionairesCss; + } + + public String getRepositorySiteResourceFolderCss() { + return repositorySiteResourceFolderCss; + } + + public void setRepositorySiteResourceFolderCss( + String repositorySiteResourceFolderCss) { + this.repositorySiteResourceFolderCss = repositorySiteResourceFolderCss; + } + + public String getRepositorySiteGlossaryCss() { + return repositorySiteGlossaryCss; + } + + public void setRepositorySiteGlossaryCss(String repositorySiteGlossaryCss) { + this.repositorySiteGlossaryCss = repositorySiteGlossaryCss; + } + + public String getToolboxContentCss() { + return toolboxContentCss; + } + + public void setToolboxContentCss(String toolboxContentCss) { + this.toolboxContentCss = toolboxContentCss; + } + + public String getToolboxCourseCss() { + return toolboxCourseCss; + } + + public void setToolboxCourseCss(String toolboxCourseCss) { + this.toolboxCourseCss = toolboxCourseCss; + } + + public String getToolboxContentPackageCss() { + return toolboxContentPackageCss; + } + + public void setToolboxContentPackageCss(String toolboxContentPackageCss) { + this.toolboxContentPackageCss = toolboxContentPackageCss; + } + + public String getToolboxWikiCss() { + return toolboxWikiCss; + } + + public void setToolboxWikiCss(String toolboxWikiCss) { + this.toolboxWikiCss = toolboxWikiCss; + } + + public String getToolboxPodcastCss() { + return toolboxPodcastCss; + } + + public void setToolboxPodcastCss(String toolboxPodcastCss) { + this.toolboxPodcastCss = toolboxPodcastCss; + } + + public String getToolboxBlogCss() { + return toolboxBlogCss; + } + + public void setToolboxBlogCss(String toolboxBlogCss) { + this.toolboxBlogCss = toolboxBlogCss; + } + + public String getToolboxPortfolioCss() { + return toolboxPortfolioCss; + } + + public void setToolboxPortfolioCss(String toolboxPortfolioCss) { + this.toolboxPortfolioCss = toolboxPortfolioCss; + } + + public String getToolboxIQTestCss() { + return toolboxIQTestCss; + } + + public void setToolboxIQTestCss(String toolboxIQTestCss) { + this.toolboxIQTestCss = toolboxIQTestCss; + } + + public String getToolboxQuestionnaireCss() { + return toolboxQuestionnaireCss; + } + + public void setToolboxQuestionnaireCss(String toolboxQuestionnaireCss) { + this.toolboxQuestionnaireCss = toolboxQuestionnaireCss; + } + + public String getToolboxSharedfolderCss() { + return toolboxSharedfolderCss; + } + + public void setToolboxSharedfolderCss(String toolboxSharedfolderCss) { + this.toolboxSharedfolderCss = toolboxSharedfolderCss; + } + + public String getToolboxGlossaryCss() { + return toolboxGlossaryCss; + } + + public void setToolboxGlossaryCss(String toolboxGlossaryCss) { + this.toolboxGlossaryCss = toolboxGlossaryCss; + } + + public FunctionalUtil getFunctionalUtil() { + return functionalUtil; + } + + public void setFunctionalUtil(FunctionalUtil functionalUtil) { + this.functionalUtil = functionalUtil; + } +} diff --git a/src/test/java/org/olat/util/FunctionalUserManagementSiteUtil.java b/src/test/java/org/olat/util/FunctionalUserManagementSiteUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..817278d04e8f7f94b07eb35fe4664233e3e5b9ee --- /dev/null +++ b/src/test/java/org/olat/util/FunctionalUserManagementSiteUtil.java @@ -0,0 +1,64 @@ +/** + * <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.util; + +import com.thoughtworks.selenium.Selenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +public class FunctionalUserManagementSiteUtil { + + public enum UserManagementSiteAction { + USER_SEARCH, + CREATE_USER, + IMPORT_USER, + DELETE_USER, + DELETE_USER_IMMEDIATELY + } + + private FunctionalUtil functionalUtil; + + public FunctionalUserManagementSiteUtil(FunctionalUtil functionalUtil){ + this.functionalUtil = functionalUtil; + } + + /** + * @param browser + * @param action + * @return true on success otherwise false + * + * Browse the learning resources site's navigation. + */ + public boolean openActionByMenuTree(Selenium browser, Object action){ + //TODO:JK: implement me + + return(false); + } + + public FunctionalUtil getFunctionalUtil() { + return functionalUtil; + } + + public void setFunctionalUtil(FunctionalUtil functionalUtil) { + this.functionalUtil = functionalUtil; + } +} diff --git a/src/test/java/org/olat/util/FunctionalUtil.java b/src/test/java/org/olat/util/FunctionalUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..f25c0db5fc2265a3c95e94bd2abfa5d2ad048952 --- /dev/null +++ b/src/test/java/org/olat/util/FunctionalUtil.java @@ -0,0 +1,1143 @@ +/** + * <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.util; + +import java.io.IOException; +import java.util.Calendar; +import java.util.Properties; + +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.util.FunctionalAdministrationSiteUtil.AdministrationSiteAction; +import org.olat.util.FunctionalGroupsSiteUtil.GroupsSiteAction; +import org.olat.util.FunctionalHomeSiteUtil.HomeSiteAction; +import org.olat.util.FunctionalRepositorySiteUtil.RepositorySiteAction; +import org.olat.util.FunctionalUserManagementSiteUtil.UserManagementSiteAction; + +import com.thoughtworks.selenium.Selenium; + +/** + * + * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com + */ +public class FunctionalUtil { + private final static OLog log = Tracing.createLoggerFor(FunctionalUtil.class); + + public final static String DEPLOYMENT_URL = "http://localhost:8080/openolat"; + public final static String DEPLOYMENT_PATH = "/openolat"; + public final static String WAIT_LIMIT = "5000"; + + public final static String LOGIN_PAGE = "dmz"; + public final static String ACKNOWLEDGE_CHECKBOX = "acknowledge_checkbox"; + + public final static String INFO_DIALOG = "o_interceptionPopup"; + + public enum WaitLimitAttribute { + NORMAL("0"), + EXTENDED("3000"), + SAVE("7000"), + VERY_SAVE("12000"); + + private String extend; + + WaitLimitAttribute(String extend){ + setExtend(extend); + } + + public String getExtend() { + return extend; + } + + public void setExtend(String extend) { + this.extend = extend; + } + } + + public enum OlatSite { + HOME, + GROUPS, + LEARNING_RESOURCES, + GROUP_ADMINISTRATION, + USER_MANAGEMENT, + ADMINISTRATION, + } + + public final static String OLAT_TOP_NAVIGATION_LOGOUT_CSS = "o_topnav_logout"; + + public final static String OLAT_NAVIGATION_SITE_CSS = "b_nav_site"; + public final static String OLAT_ACTIVE_NAVIGATION_SITE_CSS = "b_nav_active"; + + public final static String OLAT_SITE_HOME_CSS = "o_site_home"; + public final static String OLAT_SITE_GROUPS_CSS = "o_site_groups"; + public final static String OLAT_SITE_LEARNING_RESOURCES_CSS = "o_site_repository"; + public final static String OLAT_SITE_GROUP_ADMINISTRATION_CSS = "o_site_groupsmanagement"; + public final static String OLAT_SITE_USER_MANAGEMENT_CSS = "o_site_useradmin"; + public final static String OLAT_SITE_ADMINISTRATION_CSS = "o_site_admin"; + + public final static String CONTENT_CSS = "b_main"; + public final static String CONTENT_TAB_CSS = "b_item_"; + public final static String ACTIVE_CONTENT_TAB_CSS = "b_active"; + + public final static String FORM_SAVE_XPATH = "//button[@type='button' and last()]"; + + public final static String WIZARD_CSS = "b_wizard"; + public final static String WIZARD_NEXT_CSS = "b_wizard_button_next"; + public final static String WIZARD_FINISH_CSS = "b_wizard_button_finish"; + + public final static String MCE_CONTENT_BODY_CSS = "mceContentBody"; + + private String username; + private String password; + + private String deploymentUrl; + private String deploymentPath; + private String waitLimit; + + private String loginPage; + private String acknowledgeCheckbox; + + private String infoDialog; + + private String olatTopNavigationLogoutCss; + + private String olatNavigationSiteCss; + private String olatActiveNavigationSiteCss; + + private String olatSiteHomeCss; + private String olatSiteGroupsCss; + private String olatSiteLearningResourcesCss; + private String olatSiteGroupAdministrationCss; + private String olatSiteUserManagementCss; + private String olatSiteAdministrationCss; + + private String contentCss; + private String contentTabCss; + private String activeContentTabCss; + + private String formSaveXPath; + + private String wizardCss; + private String wizardNextCss; + private String wizardFinishCss; + + private String mceContentBodyCss; + + private FunctionalHomeSiteUtil functionalHomeSiteUtil; + private FunctionalGroupsSiteUtil functionalGroupsSiteUtil; + private FunctionalRepositorySiteUtil functionalRepositorySiteUtil; + private FunctionalUserManagementSiteUtil functionalUserManagementSiteUtil; + private FunctionalAdministrationSiteUtil functionalAdministrationSiteUtil; + + public FunctionalUtil(){ + Properties properties = new Properties(); + + try { + //TODO:JK: use default properties file + properties.load(FunctionalUtil.class.getResourceAsStream("credentials.properties")); + + username = properties.getProperty("admin.login"); + password = properties.getProperty("admin.password"); + } catch (IOException e) { + + username = "administrator"; + password = "openolat"; + + //TODO:JK: Auto-generated catch block + e.printStackTrace(); + } + + deploymentUrl = DEPLOYMENT_URL; + deploymentPath = DEPLOYMENT_PATH; + waitLimit = WAIT_LIMIT; + + loginPage = LOGIN_PAGE; + acknowledgeCheckbox = ACKNOWLEDGE_CHECKBOX; + + infoDialog = INFO_DIALOG; + + olatTopNavigationLogoutCss = OLAT_TOP_NAVIGATION_LOGOUT_CSS; + + olatNavigationSiteCss = OLAT_NAVIGATION_SITE_CSS; + olatActiveNavigationSiteCss = OLAT_ACTIVE_NAVIGATION_SITE_CSS; + + olatSiteHomeCss = OLAT_SITE_HOME_CSS; + olatSiteGroupsCss = OLAT_SITE_GROUPS_CSS; + olatSiteLearningResourcesCss = OLAT_SITE_LEARNING_RESOURCES_CSS; + olatSiteGroupAdministrationCss = OLAT_SITE_GROUP_ADMINISTRATION_CSS; + olatSiteUserManagementCss = OLAT_SITE_USER_MANAGEMENT_CSS; + olatSiteAdministrationCss = OLAT_SITE_ADMINISTRATION_CSS; + + contentCss = CONTENT_CSS; + contentTabCss = CONTENT_TAB_CSS; + activeContentTabCss = ACTIVE_CONTENT_TAB_CSS; + + formSaveXPath = FORM_SAVE_XPATH; + + wizardCss = WIZARD_CSS; + wizardNextCss = WIZARD_NEXT_CSS; + wizardFinishCss = WIZARD_FINISH_CSS; + + mceContentBodyCss = MCE_CONTENT_BODY_CSS; + + functionalHomeSiteUtil = new FunctionalHomeSiteUtil(this); + functionalGroupsSiteUtil = new FunctionalGroupsSiteUtil(this); + functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(this); + functionalUserManagementSiteUtil = new FunctionalUserManagementSiteUtil(this); + functionalAdministrationSiteUtil = new FunctionalAdministrationSiteUtil(this); + } + + /** + * @param browser + * @param page + * + * Loads the specified page with default deployment url. + */ + public void loadPage(Selenium browser, String page){ + /* create url */ + StringBuffer urlBuffer = new StringBuffer(); + + urlBuffer.append(deploymentUrl) + .append('/') + .append(page); + + String url = urlBuffer.toString(); + + /* open url and wait specified time */ + browser.open(url); + waitForPageToLoad(browser); + } + + public void waitForPageToLoad(Selenium browser){ + waitForPageToLoad(browser, WaitLimitAttribute.VERY_SAVE); + } + + public void waitForPageToLoad(Selenium browser, WaitLimitAttribute wait){ + String waitLimit = Long.toString(Long.parseLong(getWaitLimit()) + Long.parseLong(wait.getExtend())); + + browser.waitForPageToLoad(waitLimit); + } + + /** + * @param browser + * @param locator + * @return true on success otherwise false + * + * Waits at most (waitLimit + WaitLimitAttribute.VERY_SAVE) amount of time for element to load + * specified by locator. + */ + public boolean waitForPageToLoadElement(Selenium browser, String locator){ + return(waitForPageToLoadElement(browser, locator, WaitLimitAttribute.VERY_SAVE)); + } + + /** + * @param browser + * @param locator + * @param wait + * @return true on success otherwise false + * + * Waits at most (waitLimit + wait) amount of time for element to load + * specified by locator. + */ + public boolean waitForPageToLoadElement(Selenium browser, String locator, WaitLimitAttribute wait){ + long startTime = Calendar.getInstance().getTimeInMillis(); + long currentTime = startTime; + long waitLimit = Long.parseLong(getWaitLimit()) + Long.parseLong(wait.getExtend()); + + log.info("waiting for page to load element"); + + do{ + if(browser.isElementPresent(locator)){ + log.info("found element after " + (currentTime - startTime) + "ms"); + + return(true); + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + + currentTime = Calendar.getInstance().getTimeInMillis(); + }while(waitLimit > currentTime - startTime); + + log.warn("giving up after " + waitLimit + "ms"); + + return(false); + } + + + /** + * @param browser + * @param locator + * @return true on success otherwise false + * + * Waits at most (waitLimit + WaitLimitAttribute.VERY_SAVE) amount of time for element to load + * specified by locator. + */ + public boolean waitForPageToUnloadElement(Selenium browser, String locator){ + return(waitForPageToUnloadElement(browser, locator, WaitLimitAttribute.VERY_SAVE)); + } + + /** + * @param browser + * @param locator + * @param wait + * @return true on success otherwise false + * + * Waits at most (waitLimit + wait) amount of time for element to load + * specified by locator. + */ + public boolean waitForPageToUnloadElement(Selenium browser, String locator, WaitLimitAttribute wait){ + long startTime = Calendar.getInstance().getTimeInMillis(); + long currentTime = startTime; + long waitLimit = Long.parseLong(getWaitLimit()) + Long.parseLong(wait.getExtend()); + + log.info("waiting for page to unload element"); + + do{ + if(!browser.isElementPresent(locator)){ + log.info("found element after " + (currentTime - startTime) + "ms"); + + return(true); + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + + currentTime = Calendar.getInstance().getTimeInMillis(); + }while(waitLimit > currentTime - startTime); + + log.warn("giving up after " + waitLimit + "ms"); + + return(false); + } + + /** + * @param site + * @return the matching CSS class + * + * Find CSS mapping for specific olat site. + */ + public String findCssClassOfSite(OlatSite site){ + String selectedCss; + + selectedCss = null; + + switch(site){ + case HOME: + { + selectedCss = getOlatSiteHomeCss(); + break; + } + case GROUPS: + { + selectedCss = getOlatSiteGroupsCss(); + break; + } + case LEARNING_RESOURCES: + { + selectedCss = getOlatSiteLearningResourcesCss(); + break; + } + case GROUP_ADMINISTRATION: + { + selectedCss = getOlatSiteAdministrationCss(); + break; + } + case USER_MANAGEMENT: + { + selectedCss = getOlatSiteUserManagementCss(); + break; + } + case ADMINISTRATION: + { + selectedCss = getOlatSiteAdministrationCss(); + break; + } + } + + return(selectedCss); + } + + /** + * @param browser + * @param site + * @return true if match otherwise false + * + * Check if the correct olat site is open. + */ + public boolean checkCurrentSite(Selenium browser, OlatSite site){ + return(checkCurrentSite(browser, site, -1)); + } + + public boolean checkCurrentSite(Selenium browser, OlatSite site, long timeout){ + String selectedCss = findCssClassOfSite(site); + + if(selectedCss == null){ + return(false); + } + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=.") + .append(getOlatNavigationSiteCss()) + .append(".") + .append(getOlatActiveNavigationSiteCss()) + .append(".") + .append(selectedCss); + + long timeElapsed = 0; + long startTime = Calendar.getInstance().getTimeInMillis(); + + do{ + if(browser.isElementPresent(selectorBuffer.toString())){ + return(true); + } + + if(timeout != -1){ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + //TODO:JK: Auto-generated catch block + e.printStackTrace(); + } + } + + timeElapsed = Calendar.getInstance().getTimeInMillis() - startTime; + }while(timeElapsed <= timeout && timeout != -1); + + return(false); + } + + /** + * @param browser + * @param site + * @return true on success + * + * Clicks the appropriate action on a site that it would be + * on it's initial state i.e. it looks like the user wouldn't + * have visited site before. + */ + private boolean resetSite(Selenium browser, OlatSite site){ + boolean retval = false; + + switch(site){ + case HOME: + { + retval = functionalHomeSiteUtil.openActionByMenuTree(browser, HomeSiteAction.PORTAL); + } + break; + case GROUPS: + { + retval = functionalGroupsSiteUtil.openActionByMenuTree(browser, GroupsSiteAction.MY_GROUPS); + } + break; + case LEARNING_RESOURCES: + { + retval = functionalRepositorySiteUtil.openActionByMenuTree(browser, RepositorySiteAction.MY_ENTRIES); + } + break; + case USER_MANAGEMENT: + { + retval = functionalUserManagementSiteUtil.openActionByMenuTree(browser, UserManagementSiteAction.USER_SEARCH); + } + break; + case GROUP_ADMINISTRATION: + { + //FIXME:JK: need to be implemented + } + break; + case ADMINISTRATION: + { + retval = functionalAdministrationSiteUtil.openActionByMenuTree(browser, AdministrationSiteAction.SYSTEM_ADMINISTRATION); + } + break; + } + + return(retval); + } + + /** + * @param browser + * @param site + * @return true on success otherwise false + * + * Open a specific olat site. + */ + public boolean openSite(Selenium browser, OlatSite site){ + String selectedCss = findCssClassOfSite(site); + + if(selectedCss == null){ + return(false); + } + + if(checkCurrentSite(browser, site, Long.parseLong(getWaitLimit()))){ + if(resetSite(browser, site)){ + return(true); + }else{ + return(false); + } + } + + /* open the appropriate site */ + StringBuilder selectorBuffer = new StringBuilder(); + + selectorBuffer.append("css=.") + .append(getOlatNavigationSiteCss()) + .append(".") + .append(selectedCss) + .append(" a"); + + browser.click(selectorBuffer.toString()); + waitForPageToLoad(browser); + waitForPageToLoadElement(browser, selectorBuffer.toString(), WaitLimitAttribute.NORMAL); + + /* set it to it's initial state */ + resetSite(browser, site); + + return(true); + } + + /** + * @param browser + * @return true on success otherwise false + * + * Login to olat using selenium. + */ + public boolean login(Selenium browser){ + return login(browser, true); + } + + public boolean login(Selenium browser, boolean closeDialogs){ + return(login(browser, getUsername(), getPassword(), closeDialogs)); + } + + public boolean login(Selenium browser, String username, String password, boolean closeDialogs){ + loadPage(browser, getLoginPage()); + + /* fill in login form */ + browser.type("id=o_fiooolat_login_name", username); + browser.type("id=o_fiooolat_login_pass", password); + browser.click("id=o_fiooolat_login_button"); + waitForPageToLoad(browser); + + if(closeDialogs){ + /* check if it's our first login */ + if(browser.isElementPresent("name=" + getAcknowledgeCheckbox())){ + browser.click("name=" + getAcknowledgeCheckbox()); + + /* click accept button */ + browser.click("xpath=//div[contains(@class, 'b_window')]//button[last()]"); + waitForPageToLoad(browser); + } + + /* click away info dialogs eg. restore session */ + //TODO:JK: find a way to solve endless loop + //while(browser.isElementPresent("class="+ getInfoDialog())){ + /* click last button */ + if(browser.isElementPresent("id="+ getInfoDialog())){ + browser.click("xpath=//form//div//button[@type='button']/../../span/a[@class='b_button']"); + waitForPageToLoad(browser); + } + //} + } + + /* validate page */ + return(true); + } + + /** + * @param browser + * @return + * + * Logout from olat LMS. + */ + public boolean logout(Selenium browser){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=#") + .append(getOlatTopNavigationLogoutCss()) + .append(" a"); + + waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param tabIndex + * @return true on success otherwise false + * + * Opens a tab at the specific tabIndex. + */ + public boolean openContentTab(Selenium browser, int tabIndex){ + StringBuffer activeTabSelectorBuffer = new StringBuffer(); + + activeTabSelectorBuffer.append("css=#") + .append(getContentCss()) + .append(" ul .") + .append(getContentTabCss()) + .append(tabIndex + 1) + .append('.') + .append(getActiveContentTabCss()); + + if(!browser.isElementPresent(activeTabSelectorBuffer.toString())){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("css=#") + .append(getContentCss()) + .append(" ul .") + .append(getContentTabCss()) + .append(tabIndex + 1) + .append(" * a"); + + browser.click(selectorBuffer.toString()); + waitForPageToLoad(browser); + } + + return(true); + } + + /** + * @param browser + * @param formIndex + * @return true on success + * + * Save the form at the position formIndex within content element. + */ + public boolean saveForm(Selenium browser, int formIndex){ + saveForm(browser, formIndex, getWaitLimit()); + + return(true); + } + + public boolean saveForm(Selenium browser, int formIndex, String waitLimit){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form[") + .append(formIndex + 1) + .append("]") + .append(getFormSaveXPath()); + + browser.click(selectorBuffer.toString()); + browser.waitForPageToLoad(waitLimit); + + return(true); + } + + /** + * @param browser + * @param groupCss + * @param value + * @return true on success + * + * Clicks the radio button with specific value attribute in groupCss container. + */ + public boolean clickCheckbox(Selenium browser, String groupCss, String value){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form") + .append("//div[@class='b_form_selection_vertical' or @class='b_form_selection_horizontal']") + .append("//input[@type='checkbox' and @value='") + .append(value) + .append("']"); + + browser.click(selectorBuffer.toString()); + + return(true); + } + + /** + * @param browser + * @param formIndex + * @param radioGroupIndex + * @param radioIndex + * @return true on success + * + * Clicks the radio button at position radioIndex from the selection at position radioGroupIndex. + */ + @Deprecated + public boolean clickRadio(Selenium browser, int formIndex, int radioGroupIndex, int radioIndex){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form[") + .append(formIndex) + .append("]") + .append("//div[@class='b_form_selection_vertical' or @class='b_form_selection_horizontal'][") + .append(radioGroupIndex) + .append("]") + .append("//input[@type='radio'][") + .append(radioIndex) + .append("]"); + + browser.click(selectorBuffer.toString()); + + return(true); + } + + /** + * @param browser + * @param groupCss + * @param value + * @return true on success + * + * Clicks the radio button with specific value attribute in groupCss container. + */ + public boolean clickRadio(Selenium browser, String groupCss, String value){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("//form") + .append("//div[@class='b_form_selection_vertical' or @class='b_form_selection_horizontal']") + .append("//input[@type='radio' and @value='") + .append(value) + .append("']"); + + browser.click(selectorBuffer.toString()); + + return(true); + } + + /** + * @param browser + * @param formIndex + * @param textIndex + * @param text + * @return true on success + * + * Type text in the specified text entry at textIndex position within form at formIndex. + */ + @Deprecated + public boolean typeText(Selenium browser, int formIndex, int textIndex, String text){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form[") + .append(formIndex) + .append("]") + .append("//input[@type='text'][") + .append(textIndex) + .append("]"); + + browser.type(selectorBuffer.toString(), text); + + return(true); + } + + /** + * @param browser + * @param entryCss + * @param text + * @return true on success + * + * Types text to the with CSS class specified entry. + */ + public boolean typeText(Selenium browser, String entryCss, String text){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form") + .append("//div[contains(@class, '") + .append(entryCss) + .append("')]") + .append("//input[@type='text']"); + + browser.type(selectorBuffer.toString(), text); + + return(true); + } + + public boolean typeMCE(Selenium browser, String content){ + if(content == null) + return(true); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("dom=document.getElementsByClassName('") + .append("mceIframeContainer") + .append("')[0].getElementsByTagName('iframe')[0].contentDocument.body"); + + waitForPageToLoadElement(browser, selectorBuffer.toString()); + + browser.type(selectorBuffer.toString(), content); + + return(true); + } + + public boolean typeMCE(Selenium browser, String cssClass, String content){ + if(content == null) + return(true); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("dom=document.getElementsByClassName('") + .append(cssClass) + .append("')[0].getElementsByClassName('") + .append("mceIframeContainer") + .append("')[0].getElementsByTagName('iframe')[0].contentDocument.body"); + + waitForPageToLoadElement(browser, selectorBuffer.toString()); + + browser.type(selectorBuffer.toString(), content); + + return(true); + } + + /** + * @param browser + * @param entryCss + * @param text + * @return true on success + * + * Types text to the with CSS class specified password entry. + */ + public boolean typePassword(Selenium browser, String entryCss, String text){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//form") + .append("//div[contains(@class, '") + .append(entryCss) + .append("')]") + .append("//input[@type='password']"); + + browser.type(selectorBuffer.toString(), text); + + return(true); + } + + /** + * @param browser + * @param id + * @param value + * @return + * + * Select an item of an option box. + */ + public boolean selectOption(Selenium browser, String id, String value){ + StringBuffer selectLocatorBuffer = new StringBuffer(); + + selectLocatorBuffer.append("xpath=//form") + .append("//select[@id='") + .append(id) + .append("']"); + + StringBuffer optionLocatorBuffer = new StringBuffer(); + + optionLocatorBuffer.append("value=") + .append(value); + + waitForPageToLoadElement(browser, selectLocatorBuffer.toString()); + browser.select(selectLocatorBuffer.toString(), optionLocatorBuffer.toString()); + + return(true); + } + + /** + * @param browser + * @return + * + * Clicks the next button of a wizard. + */ + public boolean clickWizardNext(Selenium browser){ + StringBuffer locatorBuffer = new StringBuffer(); + + locatorBuffer.append("xpath=//form//a[contains(@class, '") + .append(getWizardNextCss()) + .append("')]"); + + waitForPageToLoadElement(browser, locatorBuffer.toString()); + browser.click(locatorBuffer.toString()); + + return(true); + } + + /** + * @param browser + * @return + * + * Clicks the finish button of a wizard. + */ + public boolean clickWizardFinish(Selenium browser){ + StringBuffer locatorBuffer = new StringBuffer(); + + locatorBuffer.append("xpath=//form//a[contains(@class, '") + .append(getWizardFinishCss()) + .append("')]"); + + waitForPageToLoadElement(browser, locatorBuffer.toString()); + + browser.focus(locatorBuffer.toString()); + browser.click(locatorBuffer.toString()); + + return(true); + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getDeploymentUrl() { + return deploymentUrl; + } + + public void setDeploymentUrl(String deploymentUrl) { + this.deploymentUrl = deploymentUrl; + } + + public String getDeploymentPath() { + return deploymentPath; + } + + public void setDeploymentPath(String deploymentPath) { + this.deploymentPath = deploymentPath; + } + + public String getWaitLimit() { + return waitLimit; + } + + public void setWaitLimit(String waitLimit) { + this.waitLimit = waitLimit; + } + + public String getLoginPage() { + return loginPage; + } + + public void setLoginPage(String loginPage) { + this.loginPage = loginPage; + } + + public String getAcknowledgeCheckbox() { + return acknowledgeCheckbox; + } + + public void setAcknowledgeCheckbox(String acknowledgeCheckbox) { + this.acknowledgeCheckbox = acknowledgeCheckbox; + } + + public String getInfoDialog() { + return infoDialog; + } + + public void setInfoDialog(String infoDialog) { + this.infoDialog = infoDialog; + } + + public String getOlatTopNavigationLogoutCss() { + return olatTopNavigationLogoutCss; + } + + public void setOlatTopNavigationLogoutCss(String olatTopNavigationLogoutCss) { + this.olatTopNavigationLogoutCss = olatTopNavigationLogoutCss; + } + + public String getOlatNavigationSiteCss() { + return olatNavigationSiteCss; + } + + public void setOlatNavigationSiteCss(String olatNavigationSiteCss) { + this.olatNavigationSiteCss = olatNavigationSiteCss; + } + + public String getOlatActiveNavigationSiteCss() { + return olatActiveNavigationSiteCss; + } + + public void setOlatActiveNavigationSiteCss(String olatActiveNavigationSiteCss) { + this.olatActiveNavigationSiteCss = olatActiveNavigationSiteCss; + } + + public String getOlatSiteHomeCss() { + return olatSiteHomeCss; + } + + public void setOlatSiteHomeCss(String olatSiteHomeCss) { + this.olatSiteHomeCss = olatSiteHomeCss; + } + + public String getOlatSiteGroupsCss() { + return olatSiteGroupsCss; + } + + public void setOlatSiteGroupsCss(String olatSiteGroupsCss) { + this.olatSiteGroupsCss = olatSiteGroupsCss; + } + + public String getOlatSiteLearningResourcesCss() { + return olatSiteLearningResourcesCss; + } + + public void setOlatSiteLearningResourcesCss(String olatSiteLearningResourcesCss) { + this.olatSiteLearningResourcesCss = olatSiteLearningResourcesCss; + } + + public String getOlatSiteGroupAdministrationCss() { + return olatSiteGroupAdministrationCss; + } + + public void setOlatSiteGroupAdministrationCss( + String olatSiteGroupAdministrationCss) { + this.olatSiteGroupAdministrationCss = olatSiteGroupAdministrationCss; + } + + public String getOlatSiteUserManagementCss() { + return olatSiteUserManagementCss; + } + + public void setOlatSiteUserManagementCss(String olatSiteUserManagementCss) { + this.olatSiteUserManagementCss = olatSiteUserManagementCss; + } + + public String getOlatSiteAdministrationCss() { + return olatSiteAdministrationCss; + } + + public void setOlatSiteAdministrationCss(String olatSiteAdministrationCss) { + this.olatSiteAdministrationCss = olatSiteAdministrationCss; + } + + public String getContentCss() { + return contentCss; + } + + public void setContentCss(String contentCss) { + this.contentCss = contentCss; + } + + public String getContentTabCss() { + return contentTabCss; + } + + public void setContentTabCss(String contentTabCss) { + this.contentTabCss = contentTabCss; + } + + public String getActiveContentTabCss() { + return activeContentTabCss; + } + + public void setActiveContentTabCss(String activeContentTabCss) { + this.activeContentTabCss = activeContentTabCss; + } + + public String getFormSaveXPath() { + return formSaveXPath; + } + + public void setFormSaveXPath(String formSaveXPath) { + this.formSaveXPath = formSaveXPath; + } + + public String getWizardCss() { + return wizardCss; + } + + public void setWizardCss(String wizardCss) { + this.wizardCss = wizardCss; + } + + public String getWizardNextCss() { + return wizardNextCss; + } + + public void setWizardNextCss(String wizardNextCss) { + this.wizardNextCss = wizardNextCss; + } + + public String getWizardFinishCss() { + return wizardFinishCss; + } + + public void setWizardFinishCss(String wizardFinishCss) { + this.wizardFinishCss = wizardFinishCss; + } + + public String getMceContentBodyCss() { + return mceContentBodyCss; + } + + public void setMceContentBodyCss(String mceContentBodyCss) { + this.mceContentBodyCss = mceContentBodyCss; + } + + public FunctionalHomeSiteUtil getFunctionalHomeSiteUtil() { + return functionalHomeSiteUtil; + } + + public void setFunctionalHomeSiteUtil( + FunctionalHomeSiteUtil functionalHomeSiteUtil) { + this.functionalHomeSiteUtil = functionalHomeSiteUtil; + } + + public FunctionalGroupsSiteUtil getFunctionalGroupsSiteUtil() { + return functionalGroupsSiteUtil; + } + + public void setFunctionalGroupsSiteUtil( + FunctionalGroupsSiteUtil functionalGroupsSiteUtil) { + this.functionalGroupsSiteUtil = functionalGroupsSiteUtil; + } + + public FunctionalRepositorySiteUtil getFunctionalRepositorySiteUtil() { + return functionalRepositorySiteUtil; + } + + public void setFunctionalRepositorySiteUtil( + FunctionalRepositorySiteUtil functionalRepositorySiteUtil) { + this.functionalRepositorySiteUtil = functionalRepositorySiteUtil; + } + + public FunctionalUserManagementSiteUtil getFunctionalUserManagementSiteUtil() { + return functionalUserManagementSiteUtil; + } + + public void setFunctionalUserManagementSiteUtil( + FunctionalUserManagementSiteUtil functionalUserManagementSiteUtil) { + this.functionalUserManagementSiteUtil = functionalUserManagementSiteUtil; + } + + public FunctionalAdministrationSiteUtil getFunctionalAdministrationSiteUtil() { + return functionalAdministrationSiteUtil; + } + + public void setFunctionalAdministrationSiteUtil( + FunctionalAdministrationSiteUtil functionalAdministrationSiteUtil) { + this.functionalAdministrationSiteUtil = functionalAdministrationSiteUtil; + } +} diff --git a/src/test/java/org/olat/util/FunctionalVOUtil.java b/src/test/java/org/olat/util/FunctionalVOUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..6c07de8779fcebd056d806859d0adf8a4e82b4e4 --- /dev/null +++ b/src/test/java/org/olat/util/FunctionalVOUtil.java @@ -0,0 +1,354 @@ +/** + * <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.util; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriBuilder; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntity; +import org.apache.http.entity.mime.content.FileBody; +import org.apache.http.entity.mime.content.StringBody; +import org.junit.Assert; +import org.olat.restapi.RestConnection; +import org.olat.restapi.support.vo.CourseVO; +import org.olat.restapi.support.vo.RepositoryEntryVO; +import org.olat.user.restapi.UserVO; + +public class FunctionalVOUtil { + + public final static String WAIT_LIMIT = "15000"; + + public final static String ALL_ELEMENTS_COURSE_DISPLAYNAME = "All Elements Course"; + public final static String ALL_ELEMENTS_COURSE_FILENAME = "All_Elements_Course.zip"; + + public enum SysGroups{ + USERMANAGERS, + GROUPMANAGERS, + AUTHORS, + ADMIN, + USERS, + ANONYMOUS, + INSTITUTIONAL_RESOURCE_MANAGER, + }; + + private String username; + private String password; + + private String allElementsCourseDisplayname; + private String allElementsCourseFilename; + + private HttpClient client; + private String waitLimit; + + public FunctionalVOUtil(String username, String password){ + setUsername(username); + setPassword(password); + + setAllElementsCourseDisplayname(ALL_ELEMENTS_COURSE_DISPLAYNAME); + setAllElementsCourseFilename(ALL_ELEMENTS_COURSE_FILENAME); + + client = new HttpClient(); + waitLimit = WAIT_LIMIT; + } + + /** + * @param deploymentUrl + * @param count + * @throws IOException + * @throws URISyntaxException + * + * Creates the selenium test users with random passwords and + * writes it to credentials.properties. + */ + public List<UserVO> createTestUsers(URL deploymentUrl, int count) throws IOException, URISyntaxException{ + RestConnection restConnection = new RestConnection(deploymentUrl); + + restConnection.login(getUsername(), getPassword()); + + List<UserVO> user = new ArrayList<UserVO>(); + + for(int i = 0; i < count; i++){ + UserVO vo = new UserVO(); + String username = ("selenium_" + i + "_" + UUID.randomUUID().toString()).substring(0, 24); + vo.setLogin(username); + String password = ("passwd_" + i + "_" + UUID.randomUUID().toString()).substring(0, 24); + vo.setPassword(password); + vo.setFirstName("John_" + i); + vo.setLastName("Smith"); + vo.setEmail(username + "@frentix.com"); + vo.putProperty("telOffice", "39847592"); + vo.putProperty("telPrivate", "39847592"); + vo.putProperty("telMobile", "39847592"); + vo.putProperty("gender", "Female");//male or female + vo.putProperty("birthDay", "12/12/2009"); + + URI request = UriBuilder.fromUri(deploymentUrl.toURI()).path("restapi").path("users").build(); + HttpPut method = restConnection.createPut(request, MediaType.APPLICATION_JSON, true); + restConnection.addJsonEntity(method, vo); + method.addHeader("Accept-Language", "en"); + + HttpResponse response = restConnection.execute(method); + assertTrue(response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201); + InputStream body = response.getEntity().getContent(); + + UserVO current = restConnection.parse(body, UserVO.class); + Assert.assertNotNull(current); + + user.add(vo); + } + + restConnection.shutdown(); + + return(user); + } + + public void addUserToSysGroup(UserVO user, SysGroups group){ + //TODO:JK: implement me + } + + /** + * @param deploymentUrl + * @param path + * @param filename + * @param resourcename + * @param displayname + * @return CourseVO + * @throws URISyntaxException + * @throws IOException + * + * Imports the specified course via REST. + */ + public CourseVO importCourse(URL deploymentUrl, String path, String filename, String resourcename, String displayname) throws URISyntaxException, IOException{ + URL cpUrl = FunctionalVOUtil.class.getResource(path); + assertNotNull(cpUrl); + File cp = new File(cpUrl.toURI()); + + RestConnection conn = new RestConnection(deploymentUrl); + assertTrue(conn.login(getUsername(), getPassword())); + + URI request = UriBuilder.fromUri(deploymentUrl.toURI()).path("restapi").path("repo/courses").build(); + HttpPost method = conn.createPost(request, MediaType.APPLICATION_JSON, true); + MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); + entity.addPart("file", new FileBody(cp)); + entity.addPart("filename", new StringBody(filename)); + entity.addPart("resourcename", new StringBody(resourcename)); + entity.addPart("displayname", new StringBody(displayname)); + entity.addPart("access", new StringBody("3")); + String softKey = UUID.randomUUID().toString().replace("-", "").substring(0, 30); + entity.addPart("softkey", new StringBody(softKey)); + method.setEntity(entity); + + HttpResponse response = conn.execute(method); + assertTrue(response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201); + + CourseVO vo = conn.parse(response, CourseVO.class); + assertNotNull(vo); + assertNotNull(vo.getRepoEntryKey()); + assertNotNull(vo.getKey()); + + return(vo); + } + + public CourseVO importEmptyCourse(URL deploymentUrl) throws URISyntaxException, IOException{ + return(importCourse(deploymentUrl, "/org/olat/course/Empty_Course.zip", "Empty_Course.zip", "Empty Course", "Empty Course")); + } + + /** + * @param deploymentUrl + * @return + * @throws URISyntaxException + * @throws IOException + * + * Imports the "All Elements Course" via REST. + */ + public CourseVO importAllElementsCourse(URL deploymentUrl) throws URISyntaxException, IOException{ + return(importCourse(deploymentUrl, "/org/olat/course/All_Elements_Course.zip", "All_Elements_Course.zip", "All Elements Course", "All Elements Course")); + } + + /** + * @param deploymentUrl + * @return + * @throws URISyntaxException + * @throws IOException + * + * Imports the "Course including Forum" via REST. + */ + public CourseVO importCourseIncludingForum(URL deploymentUrl) throws URISyntaxException, IOException{ + return(importCourse(deploymentUrl, "/org/olat/portfolio/Course_including_Forum.zip", "Course_including_Forum.zip", "Course including Forum", "Course including Forum")); + } + + /** + * @param deploymentUrl + * @return + * @throws URISyntaxException + * @throws IOException + * + * Imports the "Course including Blog" via REST. + */ + public CourseVO importCourseIncludingBlog(URL deploymentUrl) throws URISyntaxException, IOException{ + return(importCourse(deploymentUrl, "/org/olat/portfolio/Course_including_Blog.zip", "Course_including_Blog.zip", "Course including Blog", "Course including Blog")); + } + + /** + * @param deploymentUrl + * @return + * @throws URISyntaxException + * @throws IOException + * + * imports a wiki via REST. + */ + public RepositoryEntryVO importWiki(URL deploymentUrl) throws URISyntaxException, IOException{ + URL wikiUrl = FunctionalVOUtil.class.getResource("/org/olat/portfolio/wiki.zip"); + Assert.assertNotNull(wikiUrl); + + File wiki = new File(wikiUrl.toURI()); + + RestConnection restConnection = new RestConnection(deploymentUrl); + + assertTrue(restConnection.login(getUsername(), getPassword())); + + URI request = UriBuilder.fromUri(deploymentUrl.toURI()).path("restapi").path("repo/entries").build(); + HttpPut method = restConnection.createPut(request, MediaType.APPLICATION_JSON, true); + MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); + entity.addPart("file", new FileBody(wiki)); + entity.addPart("filename", new StringBody("wiki.zip")); + entity.addPart("resourcename", new StringBody("Wiki")); + entity.addPart("displayname", new StringBody("Wiki")); + entity.addPart("access", new StringBody("3")); + method.setEntity(entity); + + HttpResponse response = restConnection.execute(method); + assertTrue(response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201); + + InputStream body = response.getEntity().getContent(); + + RepositoryEntryVO vo = restConnection.parse(body, RepositoryEntryVO.class); + assertNotNull(vo); + + return(vo); + } + + /** + * @param deploymentUrl + * @param login + * @param password + * @return + * @throws URISyntaxException + * @throws IOException + * + * Imports a blog via REST. + */ + public RepositoryEntryVO importBlog(URL deploymentUrl) throws URISyntaxException, IOException{ + URL blogUrl = FunctionalVOUtil.class.getResource("/org/olat/portfolio/blog.zip"); + Assert.assertNotNull(blogUrl); + + File blog = new File(blogUrl.toURI()); + + RestConnection restConnection = new RestConnection(deploymentUrl); + + assertTrue(restConnection.login(getUsername(), getPassword())); + + URI request = UriBuilder.fromUri(deploymentUrl.toURI()).path("restapi").path("repo/entries").build(); + HttpPut method = restConnection.createPut(request, MediaType.APPLICATION_JSON, true); + MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); + entity.addPart("file", new FileBody(blog)); + entity.addPart("filename", new StringBody("blog.zip")); + entity.addPart("resourcename", new StringBody("Blog")); + entity.addPart("displayname", new StringBody("Blog")); + entity.addPart("access", new StringBody("3")); + method.setEntity(entity); + + HttpResponse response = restConnection.execute(method); + assertTrue(response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201); + + InputStream body = response.getEntity().getContent(); + + RepositoryEntryVO vo = restConnection.parse(body, RepositoryEntryVO.class); + assertNotNull(vo); + + return(vo); + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getAllElementsCourseDisplayname() { + return allElementsCourseDisplayname; + } + + public void setAllElementsCourseDisplayname(String allElementsCourseDisplayname) { + this.allElementsCourseDisplayname = allElementsCourseDisplayname; + } + + public String getAllElementsCourseFilename() { + return allElementsCourseFilename; + } + + public void setAllElementsCourseFilename(String allElementsCourseFilename) { + this.allElementsCourseFilename = allElementsCourseFilename; + } + + public HttpClient getClient() { + return client; + } + + public void setClient(HttpClient client) { + this.client = client; + } + + public String getWaitLimit() { + return waitLimit; + } + + public void setWaitLimit(String waitLimit) { + this.waitLimit = waitLimit; + } +} diff --git a/src/test/java/org/olat/util/PortletPosition.vm b/src/test/java/org/olat/util/PortletPosition.vm new file mode 100644 index 0000000000000000000000000000000000000000..1906254af5c8e36aeb490f1f92be056c4e3af03a --- /dev/null +++ b/src/test/java/org/olat/util/PortletPosition.vm @@ -0,0 +1,25 @@ +var position = -1; + +if (document.querySelector){ + var portalCss = "${portalCss}"; + var portalSubcolumnsCss = "${portalSubcolumnsCss}"; + var portletCss = "${portletCss}"; + var portalColumnCssPrefix = "${portalColumnCssPrefix}"; + + var portlet = "${portlet}"; + + var j_stop = ${j_stop}; + var column = ${column}; + + var selection = window.document.querySelectorAll('.' + portalCss + '.' + portalSubcolumnsCss + ' .' + portalColumnCssPrefix + (column + 1) + ' .' + portletCss); + + for(j=0; j < j_stop; j++){ + var current = selection.item(j); + + if(current.className.indexOf(portlet) >= 0){ + position = j; + } + } +} + +position; diff --git a/src/test/profile/mysql/olat.arquillian.properties b/src/test/profile/mysql/olat.arquillian.properties index a2f15b7e8c41d7b0f206476caf6faad2547ac08c..35398f0e0fb5077fcd04c468debc98fe57c5f23c 100644 --- a/src/test/profile/mysql/olat.arquillian.properties +++ b/src/test/profile/mysql/olat.arquillian.properties @@ -23,6 +23,8 @@ localization.cache=true is.translation.server=disabled deploy.course.exports=false +restapi.enable=true + # for UserTest keepUserEmailAfterDeletion=true keepUserLoginAfterDeletion=true diff --git a/src/test/profile/mysql/olat.eclipse.properties b/src/test/profile/mysql/olat.eclipse.properties index 088eadeffe8ab6a3f17477140f100f14a7d63138..e8410493bcbb2ce253b0158d3ab2941f8929601a 100644 --- a/src/test/profile/mysql/olat.eclipse.properties +++ b/src/test/profile/mysql/olat.eclipse.properties @@ -12,6 +12,7 @@ db.show_sql=true archive.dir= log.dir= folder.root= +restapi.enable=true instance.id=2 @@ -51,3 +52,6 @@ db.host.port=3306 db.database.dialect=org.hibernate.dialect.MySQL5InnoDBDialect db.hibernate.ddl.auto= auto.upgrade.database=false + +restapi.enable=true + diff --git a/src/test/profile/mysql/olat.local.properties b/src/test/profile/mysql/olat.local.properties index d2bcfb5388c38e7470efc24c599ddf0e0247337c..294504438377201b2b3f0c201204d8258ddbd54e 100644 --- a/src/test/profile/mysql/olat.local.properties +++ b/src/test/profile/mysql/olat.local.properties @@ -12,6 +12,7 @@ db.show_sql=false archive.dir= log.dir= folder.root= +restapi.enable=true instance.id=${test.env.instance.id} diff --git a/src/test/profile/postgresql/olat.eclipse.properties b/src/test/profile/postgresql/olat.eclipse.properties index e086e529e7e1c36b81941e36efd0001561169538..73dcd05a8bf5eebdd5eec44c3657c7d56e1be003 100644 --- a/src/test/profile/postgresql/olat.eclipse.properties +++ b/src/test/profile/postgresql/olat.eclipse.properties @@ -12,6 +12,7 @@ db.show_sql=false archive.dir= log.dir= folder.root= +restapi.enable=true instance.id=2 diff --git a/src/test/profile/postgresql/olat.local.properties b/src/test/profile/postgresql/olat.local.properties index 898388ad2bc3e2e7ccbecf0b3e21cf67da62dc6b..542389b5b2ef3c8902378a28f35c72e43742ef21 100644 --- a/src/test/profile/postgresql/olat.local.properties +++ b/src/test/profile/postgresql/olat.local.properties @@ -12,6 +12,7 @@ db.show_sql=false archive.dir= log.dir= folder.root= +restapi.enable=true instance.id=${test.env.instance.id} diff --git a/src/test/resources/arquillian.xml b/src/test/resources/arquillian.xml index 1db76175a8597eff9b4e57fa2f23e5b038c7ad03..81bad42f3f035bb8f5df5ed9d3b5262b2facdcf0 100644 --- a/src/test/resources/arquillian.xml +++ b/src/test/resources/arquillian.xml @@ -12,11 +12,14 @@ <configuration> <property name="workDir">target/arquillianDeployments</property> <property name="catalinaHome">target/arq-apache-tomcat-7.0.27</property> + <!-- <property name="javaVmArguments">-Xmx512m -XX:MaxPermSize=128m -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</property> --> </configuration> </container> <extension qualifier="selenium"> - <property name="browser">*googlechrome</property> + <property name="browserCapabilities">firefox</property> + <property name="capabilityWebdriverFirefoxBin">/Applications/Firefox.app/Contents/MacOS/firefox-bin</property> + <!-- <property name="browser">*googlechrome</property> --> </extension> </arquillian> \ No newline at end of file diff --git a/src/test/resources/org/olat/course/Small_course.zip b/src/test/resources/org/olat/course/Small_course.zip new file mode 100644 index 0000000000000000000000000000000000000000..04671a1a2611083138d78425f2a578c97c8320f1 Binary files /dev/null and b/src/test/resources/org/olat/course/Small_course.zip differ diff --git a/src/test/resources/org/olat/util/credentials.properties b/src/test/resources/org/olat/util/credentials.properties new file mode 100644 index 0000000000000000000000000000000000000000..ac12670b8b67c0594b2cff11587e8f958bfc88ff --- /dev/null +++ b/src/test/resources/org/olat/util/credentials.properties @@ -0,0 +1,2 @@ +admin.login=administrator +admin.password=openolat