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>	
 	|&nbsp;$r.render("allEntriesLink")&nbsp;|
@@ -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