From cdd2b6c5b0b684402aeca0f9844f888d8d4671f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Kr=C3=A4hemann?= <joel.kraehemann@frentix.com>
Date: Tue, 9 Oct 2012 10:29:27 +0200
Subject: [PATCH] non-jira, OO-348: Updated tests to use instantiated site
 utility classes from FunctionalUtil. Fixed unsafe method clickRadio in
 FunctionalUtil.java.  Implementing checkCreateSubcategory test therefore I
 have written createCatalogSelector and createCatalogSubcategory method.

---
 .../org/olat/course/FunctionalBackTest.java   |   4 +-
 .../org/olat/course/FunctionalCourseTest.java |   2 +-
 .../course/nodes/cp/FunctionalCPTest.java     |   2 +-
 .../course/nodes/feed/FunctionalBlogTest.java |   2 +-
 .../nodes/feed/FunctionalPodcastTest.java     |   2 +-
 .../course/nodes/iq/FunctionalIQTestTest.java |   2 +-
 .../portfolio/FunctionalPortfolioTest.java    |   4 +-
 .../course/nodes/wiki/FunctionalWikiTest.java |   2 +-
 .../org/olat/login/FunctionalResumeTest.java  |   6 +-
 .../olat/portal/FunctionalSettingsTest.java   |   2 +-
 .../portfolio/FunctionalArtefactTest.java     |   4 +-
 .../repository/FunctionalCatalogTest.java     | 127 +++++++++++++
 .../FunctionalAdministrationSiteUtil.java     |   6 +-
 .../org/olat/util/FunctionalCourseUtil.java   |  18 +-
 .../olat/util/FunctionalEPortfolioUtil.java   |   4 +
 .../olat/util/FunctionalGroupsSiteUtil.java   |   6 +-
 .../org/olat/util/FunctionalHomeSiteUtil.java |   1 +
 .../org/olat/util/FunctionalHtmlUtil.java     |   5 +
 .../util/FunctionalRepositorySiteUtil.java    | 178 ++++++++++++++++++
 .../FunctionalUserManagementSiteUtil.java     |   6 +-
 .../java/org/olat/util/FunctionalUtil.java    |  20 ++
 .../java/org/olat/util/FunctionalVOUtil.java  |   5 +-
 22 files changed, 387 insertions(+), 21 deletions(-)
 create mode 100644 src/test/java/org/olat/repository/FunctionalCatalogTest.java

diff --git a/src/test/java/org/olat/course/FunctionalBackTest.java b/src/test/java/org/olat/course/FunctionalBackTest.java
index fd04875eea8..34f4387f72b 100644
--- a/src/test/java/org/olat/course/FunctionalBackTest.java
+++ b/src/test/java/org/olat/course/FunctionalBackTest.java
@@ -77,8 +77,8 @@ public class FunctionalBackTest {
 		functionalUtil.setDeploymentUrl(deploymentUrl.toString());
 		
 		functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
-		functionalHomeSiteUtil = new FunctionalHomeSiteUtil(functionalUtil);
-		functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil);
+		functionalHomeSiteUtil = functionalUtil.getFunctionalHomeSiteUtil();
+		functionalRepositorySiteUtil = functionalUtil.getFunctionalRepositorySiteUtil();
 		functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil);
 		
 		/* create test user with REST */
diff --git a/src/test/java/org/olat/course/FunctionalCourseTest.java b/src/test/java/org/olat/course/FunctionalCourseTest.java
index 1c65cc6b05d..61ee8e57532 100644
--- a/src/test/java/org/olat/course/FunctionalCourseTest.java
+++ b/src/test/java/org/olat/course/FunctionalCourseTest.java
@@ -93,7 +93,7 @@ public class FunctionalCourseTest {
 			functionalUtil.setDeploymentUrl(deploymentUrl.toString());
 			functionalHtmlUtil = new FunctionalHtmlUtil();
 
-			functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil);
+			functionalRepositorySiteUtil = functionalUtil.getFunctionalRepositorySiteUtil();
 			functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil);
 
 			initialized = true;
diff --git a/src/test/java/org/olat/course/nodes/cp/FunctionalCPTest.java b/src/test/java/org/olat/course/nodes/cp/FunctionalCPTest.java
index eaba37bbb98..1acc24a4692 100644
--- a/src/test/java/org/olat/course/nodes/cp/FunctionalCPTest.java
+++ b/src/test/java/org/olat/course/nodes/cp/FunctionalCPTest.java
@@ -77,7 +77,7 @@ public class FunctionalCPTest {
 			functionalUtil = new FunctionalUtil();
 			functionalUtil.setDeploymentUrl(deploymentUrl.toString());
 
-			functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil);
+			functionalRepositorySiteUtil = functionalUtil.getFunctionalRepositorySiteUtil();
 			functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil);
 
 			functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
diff --git a/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java b/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java
index 0451d3a1bfd..b8a34cdf455 100644
--- a/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java
+++ b/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java
@@ -79,7 +79,7 @@ public class FunctionalBlogTest {
 			functionalUtil = new FunctionalUtil();
 			functionalUtil.setDeploymentUrl(deploymentUrl.toString());
 
-			functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil);
+			functionalRepositorySiteUtil = functionalUtil.getFunctionalRepositorySiteUtil();
 			functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil);
 
 			functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
diff --git a/src/test/java/org/olat/course/nodes/feed/FunctionalPodcastTest.java b/src/test/java/org/olat/course/nodes/feed/FunctionalPodcastTest.java
index 7ce914d9189..dc182c4ec93 100644
--- a/src/test/java/org/olat/course/nodes/feed/FunctionalPodcastTest.java
+++ b/src/test/java/org/olat/course/nodes/feed/FunctionalPodcastTest.java
@@ -79,7 +79,7 @@ public class FunctionalPodcastTest {
 			functionalUtil = new FunctionalUtil();
 			functionalUtil.setDeploymentUrl(deploymentUrl.toString());
 
-			functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil);
+			functionalRepositorySiteUtil = functionalUtil.getFunctionalRepositorySiteUtil();
 			functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil);
 
 			functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
diff --git a/src/test/java/org/olat/course/nodes/iq/FunctionalIQTestTest.java b/src/test/java/org/olat/course/nodes/iq/FunctionalIQTestTest.java
index 2da6c3e788e..433cb344e23 100644
--- a/src/test/java/org/olat/course/nodes/iq/FunctionalIQTestTest.java
+++ b/src/test/java/org/olat/course/nodes/iq/FunctionalIQTestTest.java
@@ -78,7 +78,7 @@ public class FunctionalIQTestTest {
 			functionalUtil = new FunctionalUtil();
 			functionalUtil.setDeploymentUrl(deploymentUrl.toString());
 
-			functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil);
+			functionalRepositorySiteUtil = functionalUtil.getFunctionalRepositorySiteUtil();
 			functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil);
 
 			functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
diff --git a/src/test/java/org/olat/course/nodes/portfolio/FunctionalPortfolioTest.java b/src/test/java/org/olat/course/nodes/portfolio/FunctionalPortfolioTest.java
index e7438130058..649f7318278 100644
--- a/src/test/java/org/olat/course/nodes/portfolio/FunctionalPortfolioTest.java
+++ b/src/test/java/org/olat/course/nodes/portfolio/FunctionalPortfolioTest.java
@@ -86,8 +86,8 @@ public class FunctionalPortfolioTest {
 			functionalUtil = new FunctionalUtil();
 			functionalUtil.setDeploymentUrl(deploymentUrl.toString());
 
-			functionalHomeSiteUtil = new FunctionalHomeSiteUtil(functionalUtil);
-			functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil);
+			functionalHomeSiteUtil = functionalUtil.getFunctionalHomeSiteUtil();
+			functionalRepositorySiteUtil = functionalUtil.getFunctionalRepositorySiteUtil();
 			functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil);
 			functionalEPortfolioUtil = new FunctionalEPortfolioUtil(functionalUtil, functionalHomeSiteUtil);
 			
diff --git a/src/test/java/org/olat/course/nodes/wiki/FunctionalWikiTest.java b/src/test/java/org/olat/course/nodes/wiki/FunctionalWikiTest.java
index cbdf0a8dd70..732170882a8 100644
--- a/src/test/java/org/olat/course/nodes/wiki/FunctionalWikiTest.java
+++ b/src/test/java/org/olat/course/nodes/wiki/FunctionalWikiTest.java
@@ -78,7 +78,7 @@ public class FunctionalWikiTest {
 			functionalUtil = new FunctionalUtil();
 			functionalUtil.setDeploymentUrl(deploymentUrl.toString());
 
-			functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil);
+			functionalRepositorySiteUtil = functionalUtil.getFunctionalRepositorySiteUtil();
 			functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil);
 
 			functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
diff --git a/src/test/java/org/olat/login/FunctionalResumeTest.java b/src/test/java/org/olat/login/FunctionalResumeTest.java
index 438f97715e1..d0e44b2b0e4 100644
--- a/src/test/java/org/olat/login/FunctionalResumeTest.java
+++ b/src/test/java/org/olat/login/FunctionalResumeTest.java
@@ -77,8 +77,8 @@ public class FunctionalResumeTest {
 		functionalUtil.setDeploymentUrl(deploymentUrl.toString());
 		
 		functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
-		functionalHomeSiteUtil = new FunctionalHomeSiteUtil(functionalUtil);
-		functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil);
+		functionalHomeSiteUtil = functionalUtil.getFunctionalHomeSiteUtil();
+		functionalRepositorySiteUtil = functionalUtil.getFunctionalRepositorySiteUtil();
 		functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil);
 	}
 	
@@ -90,7 +90,7 @@ public class FunctionalResumeTest {
 		
 		/* create xpath to check if course is open */
 		StringBuffer selectorBuffer = new StringBuffer();
-		
+
 		selectorBuffer.append("xpath=//li[contains(@class, 'b_resource_CourseModule')]")
 		.append("//a[@title='")
 		.append(functionalVOUtil.getAllElementsCourseDisplayname())
diff --git a/src/test/java/org/olat/portal/FunctionalSettingsTest.java b/src/test/java/org/olat/portal/FunctionalSettingsTest.java
index e8610ec6817..9f3bac87004 100644
--- a/src/test/java/org/olat/portal/FunctionalSettingsTest.java
+++ b/src/test/java/org/olat/portal/FunctionalSettingsTest.java
@@ -75,7 +75,7 @@ public class FunctionalSettingsTest {
 		functionalUtil.setDeploymentUrl(deploymentUrl.toString());
 		
 		functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
-		functionalHomeSiteUtil = new FunctionalHomeSiteUtil(functionalUtil);
+		functionalHomeSiteUtil = functionalUtil.getFunctionalHomeSiteUtil();
 		
 		portalColumnCount = 2;
 	}
diff --git a/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java b/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java
index 82542f786d6..afbf92f5bf4 100644
--- a/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java
+++ b/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java
@@ -150,9 +150,9 @@ public class FunctionalArtefactTest {
 		if(!initialized){
 			functionalUtil = new FunctionalUtil();
 			functionalUtil.setDeploymentUrl(deploymentUrl.toString());
-			functionalHomeSiteUtil = new FunctionalHomeSiteUtil(functionalUtil);
+			functionalHomeSiteUtil = functionalUtil.getFunctionalHomeSiteUtil();
 
-			functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil);
+			functionalRepositorySiteUtil = functionalUtil.getFunctionalRepositorySiteUtil();
 			functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil);
 			functionalEportfolioUtil = new FunctionalEPortfolioUtil(functionalUtil, functionalHomeSiteUtil);
 
diff --git a/src/test/java/org/olat/repository/FunctionalCatalogTest.java b/src/test/java/org/olat/repository/FunctionalCatalogTest.java
new file mode 100644
index 00000000000..2b6d555aa9e
--- /dev/null
+++ b/src/test/java/org/olat/repository/FunctionalCatalogTest.java
@@ -0,0 +1,127 @@
+/**
+ * <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.repository;
+
+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.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.olat.restapi.support.vo.CourseVO;
+import org.olat.restapi.support.vo.RepositoryEntryVO;
+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 com.thoughtworks.selenium.DefaultSelenium;
+
+/**
+ * 
+ * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com
+ */
+public class FunctionalCatalogTest {
+	
+	public final static String[] SUBCATEGORY_PATHS = {
+		"/programming",
+		"/programming/c",
+		"/programming/java"
+		};
+	public final static String[] SUBCATEGORY_DESCRIPTIONS = {
+		"here you may find courses and resources related to programming",
+		"about the C programming language",
+		"about the Java programming language"
+		};
+	
+	@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 = functionalUtil.getFunctionalRepositorySiteUtil();
+			functionalCourseUtil = new FunctionalCourseUtil(functionalUtil, functionalRepositorySiteUtil);
+
+			functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
+			
+			initialized = true;
+		}
+	}
+
+	@Ignore
+	@Test
+	@RunAsClient
+	public void checkCreateSubcategory() throws URISyntaxException, IOException{
+		/*
+		 * prerequisites for test created via REST
+		 */
+		/* import wiki */
+		RepositoryEntryVO[] wikiVO = new RepositoryEntryVO[2]; 
+		
+		wikiVO[0] = functionalVOUtil.importWiki(deploymentUrl);
+		wikiVO[1] = functionalVOUtil.importWiki(deploymentUrl);
+		
+		/* import course */
+		CourseVO[] courseVO = new CourseVO[2];
+		
+		courseVO[0] = functionalVOUtil.importEmptyCourse(deploymentUrl);
+		courseVO[1] = functionalVOUtil.importEmptyCourse(deploymentUrl);
+		
+		/*
+		 * create or configure content
+		 */
+		
+		//TODO:JK: implement me
+		
+		/*
+		 * verify content
+		 */
+		
+		//TODO:JK: implement me
+	}
+	
+}
diff --git a/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java b/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java
index d6ba9f97760..0067f368381 100644
--- a/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java
+++ b/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java
@@ -19,6 +19,9 @@
  */
 package org.olat.util;
 
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
+
 import com.thoughtworks.selenium.Selenium;
 
 /**
@@ -26,7 +29,8 @@ import com.thoughtworks.selenium.Selenium;
  * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com
  */
 public class FunctionalAdministrationSiteUtil {
-
+	private final static OLog log = Tracing.createLoggerFor(FunctionalAdministrationSiteUtil.class);
+	
 	public enum AdministrationSiteAction {
 		SYSTEM_ADMINISTRATION,
 		ADVANCED_PROPERTIES,
diff --git a/src/test/java/org/olat/util/FunctionalCourseUtil.java b/src/test/java/org/olat/util/FunctionalCourseUtil.java
index fc7b3d720b2..87752e9d50d 100644
--- a/src/test/java/org/olat/util/FunctionalCourseUtil.java
+++ b/src/test/java/org/olat/util/FunctionalCourseUtil.java
@@ -22,6 +22,9 @@ package org.olat.util;
 import java.net.MalformedURLException;
 import java.net.URI;
 
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
+
 import com.thoughtworks.selenium.Selenium;
 
 /**
@@ -30,6 +33,8 @@ import com.thoughtworks.selenium.Selenium;
  * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com
  */
 public class FunctionalCourseUtil {
+	private final static OLog log = Tracing.createLoggerFor(FunctionalCourseUtil.class);
+	
 	public final static String COURSE_RUN_CSS = "o_course_run";
 	public final static String COURSE_OPEN_EDITOR_CSS = "o_sel_course_open_editor";
 	
@@ -43,6 +48,7 @@ public class FunctionalCourseUtil {
 	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 CATALOG_SUBCATEGORY_ICON_CSS = "o_catalog_cat_icon";
 	
 	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";
@@ -273,6 +279,7 @@ public class FunctionalCourseUtil {
 	private String courseEditorPublishWizardSelectAllCss;
 	private String courseEditorPublishWizardAccessId;
 	private String courseEditorPublishWizardCatalogId;
+	private String catalogSubcategoryIconCss;
 	
 	private String courseEditorOverviewRadioGroupCss;
 	private String courseEditorInsertContentCss;
@@ -330,6 +337,7 @@ public class FunctionalCourseUtil {
 		setCourseEditorPublishWizardSelectAllCss(COURSE_EDITOR_PUBLISH_WIZARD_SELECT_ALL_CSS);
 		setCourseEditorPublishWizardAccessId(COURSE_EDITOR_PUBLISH_WIZARD_ACCESS_ID);
 		setCourseEditorPublishWizardCatalogId(COURSE_EDITOR_PUBLISH_WIZARD_CATALOG_ID);
+		setCatalogSubcategoryIconCss(CATALOG_SUBCATEGORY_ICON_CSS);
 		
 		setCourseEditorOverviewRadioGroupCss(COURSE_EDITOR_OVERVIEW_RADIO_GROUP_CSS);
 		setCourseEditorInsertContentCss(COURSE_EDITOR_INSERT_CONTENT_CSS);
@@ -623,7 +631,7 @@ public class FunctionalCourseUtil {
 	 * 
 	 * Creates xpath selectors to select catalog within the tree.
 	 */
-	private String[] createCatalogSelectors(String path){
+	public String[] createCatalogSelectors(String path){
 		//TODO:JK: implement me
 		
 		return(null);
@@ -1492,6 +1500,14 @@ public class FunctionalCourseUtil {
 		this.courseEditorPublishWizardCatalogId = courseEditorPublishWizardCatalogId;
 	}
 
+	public String getCatalogSubcategoryIconCss() {
+		return catalogSubcategoryIconCss;
+	}
+
+	public void setCatalogSubcategoryIconCss(String catalogSubcategoryIconCss) {
+		this.catalogSubcategoryIconCss = catalogSubcategoryIconCss;
+	}
+
 	public String getCourseEditorOverviewRadioGroupCss() {
 		return courseEditorOverviewRadioGroupCss;
 	}
diff --git a/src/test/java/org/olat/util/FunctionalEPortfolioUtil.java b/src/test/java/org/olat/util/FunctionalEPortfolioUtil.java
index 35d030bef44..12e23f4195b 100644
--- a/src/test/java/org/olat/util/FunctionalEPortfolioUtil.java
+++ b/src/test/java/org/olat/util/FunctionalEPortfolioUtil.java
@@ -29,6 +29,8 @@ 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.core.logging.OLog;
+import org.olat.core.logging.Tracing;
 import org.olat.util.FunctionalHomeSiteUtil.EPortfolioAction;
 import org.olat.util.FunctionalUtil.OlatSite;
 
@@ -39,6 +41,8 @@ import com.thoughtworks.selenium.Selenium;
  * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com
  */
 public class FunctionalEPortfolioUtil {
+	private final static OLog log = Tracing.createLoggerFor(FunctionalEPortfolioUtil.class);
+	
 	public final static String EP_ARTEFACTS_BUSINESS_PATH = "EPArtefacts";
 	public final static String EP_MAPS_BUSINESS_PATH = "EPMaps";
 	
diff --git a/src/test/java/org/olat/util/FunctionalGroupsSiteUtil.java b/src/test/java/org/olat/util/FunctionalGroupsSiteUtil.java
index 0cacbe55269..6c7942fa4d4 100644
--- a/src/test/java/org/olat/util/FunctionalGroupsSiteUtil.java
+++ b/src/test/java/org/olat/util/FunctionalGroupsSiteUtil.java
@@ -19,6 +19,9 @@
  */
 package org.olat.util;
 
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
+
 import com.thoughtworks.selenium.Selenium;
 
 /**
@@ -26,7 +29,8 @@ import com.thoughtworks.selenium.Selenium;
  * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com
  */
 public class FunctionalGroupsSiteUtil {
-
+	private final static OLog log = Tracing.createLoggerFor(FunctionalGroupsSiteUtil.class);
+	
 	public enum GroupsSiteAction {
 		MY_GROUPS,
 		PUBLISHED_GROUPS,
diff --git a/src/test/java/org/olat/util/FunctionalHomeSiteUtil.java b/src/test/java/org/olat/util/FunctionalHomeSiteUtil.java
index 115c2a1bbd9..e445c2d0619 100644
--- a/src/test/java/org/olat/util/FunctionalHomeSiteUtil.java
+++ b/src/test/java/org/olat/util/FunctionalHomeSiteUtil.java
@@ -547,6 +547,7 @@ public class FunctionalHomeSiteUtil {
 			return(false);
 		}
 
+		//FIXME:JK: this is a known bottleneck, but can't be set to -1 until notifications will be clicked away!
 		if(!checkCurrentAction || !checkCurrentAction(browser, action, Long.parseLong(functionalUtil.getWaitLimit()))){
 			StringBuffer selectorBuffer = new StringBuffer();
 
diff --git a/src/test/java/org/olat/util/FunctionalHtmlUtil.java b/src/test/java/org/olat/util/FunctionalHtmlUtil.java
index 02ce2408093..ac8daa0dd80 100644
--- a/src/test/java/org/olat/util/FunctionalHtmlUtil.java
+++ b/src/test/java/org/olat/util/FunctionalHtmlUtil.java
@@ -19,11 +19,16 @@
  */
 package org.olat.util;
 
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
+
 /**
  * 
  * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com
  */
 public class FunctionalHtmlUtil {
+	private final static OLog log = Tracing.createLoggerFor(FunctionalHtmlUtil.class);
+	
 	/**
 	 * @param html
 	 * @param insertNewlines
diff --git a/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java b/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java
index 9bf3b27a926..f6848077ab1 100644
--- a/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java
+++ b/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java
@@ -21,7 +21,11 @@ package org.olat.util;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
 import org.olat.util.FunctionalUtil.OlatSite;
 
 import com.thoughtworks.selenium.Selenium;
@@ -32,6 +36,9 @@ import com.thoughtworks.selenium.Selenium;
  * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com
  */
 public class FunctionalRepositorySiteUtil {	
+	private final static OLog log = Tracing.createLoggerFor(FunctionalRepositorySiteUtil.class);
+	
+	private final static Pattern categoryPattern = Pattern.compile("/([^/]+)");
 	
 	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";
@@ -60,6 +67,12 @@ public class FunctionalRepositorySiteUtil {
 	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 final static String CATALOG_ADD_SUBCATEGORY = "o_sel_catalog_add_category";
+	public final static String CATALOG_ADD_LEARNING_RESOURCE = "o_sel_catalog_add_link_to_resource";
+	public final static String CATALOG_ADD_SUBCATEGORY_POPUP_CSS = "o_sel_catalog_add_category_popup";
+	public final static String CATALOG_SUBCATEGORY_ICON_CSS = "o_catalog_sub_icon";
+	public final static String CATALOG_SUBCATEGORY_LIST_CSS = "o_catalog_itemlist";
+	
 	public enum Column {
 		AC,
 		TYPE,
@@ -258,6 +271,12 @@ public class FunctionalRepositorySiteUtil {
 	private String repositorySiteResourceFolderCss;
 	private String repositorySiteGlossaryCss;
 
+	private String catalogAddSubcategoryCss;
+	private String catalogAddLearningResourceCss;
+	private String catalogAddSubcategoryPopupCss;
+	private String catalogSubcategoryListCss;
+	private String catalogSubcategoryIconCss;
+	
 	private String importCourseCss;
 	private String importCPLearningContentCss;
 	private String importScormCss;
@@ -323,6 +342,12 @@ public class FunctionalRepositorySiteUtil {
 		setRepositorySiteResourceFolderCss(REPOSITORY_SITE_RESOURCE_FOLDER_CSS);
 		setRepositorySiteGlossaryCss(REPOSITORY_SITE_GLOSSARY_CSS);
 
+		setCatalogAddSubcategoryCss(CATALOG_ADD_SUBCATEGORY);
+		setCatalogAddLearningResourceCss(CATALOG_ADD_LEARNING_RESOURCE);
+		setCatalogAddSubcategoryPopupCss(CATALOG_ADD_SUBCATEGORY_POPUP_CSS);
+		setCatalogSubcategoryListCss(CATALOG_SUBCATEGORY_LIST_CSS);
+		setCatalogSubcategoryIconCss(CATALOG_SUBCATEGORY_ICON_CSS);
+		
 		setImportCourseCss(IMPORT_COURSE_CSS);
 		setImportCPLearningContentCss(IMPORT_CP_LEARNING_CONTENT_CSS);
 		setImportScormCss(IMPORT_SCORM_CSS);
@@ -360,6 +385,117 @@ public class FunctionalRepositorySiteUtil {
 		setFunctionalUtil(functionalUtil);
 	}
 	
+	/**
+	 * @param path
+	 * @return
+	 * 
+	 * Creates xpath selectors to select catalog within the tree.
+	 */
+	public String[] createCatalogSelectors(String path){
+		if(path == null ||
+				!path.startsWith("/")){
+			return(null);
+		}
+		
+		Matcher categoryMatcher = categoryPattern.matcher(path);
+		String[] selectors = new String[categoryMatcher.groupCount()];
+		
+		for(int i = 0; categoryMatcher.find(); i++){
+			StringBuffer selector = new StringBuffer();
+			
+			selector.append("xpath=//div[contains(@class, '")
+			.append(getCatalogSubcategoryListCss())
+			.append("')]//a//span[contains(@class, '")
+			.append(getCatalogSubcategoryIconCss())
+			.append("' and text()='")
+			.append(categoryMatcher.group(1))
+			.append("')]/..");
+			
+			selectors[i] = selector.toString();
+		}
+		
+		return(selectors);
+	}
+	
+	/**
+	 * @param browser
+	 * @param path
+	 * @param name
+	 * @param description
+	 * @return
+	 * 
+	 * Adds a subcategory to catalog on the specified path.
+	 */
+	public boolean createCatalogSubcategory(Selenium browser, String path, String name, String description){
+		if(!functionalUtil.openSite(browser, FunctionalUtil.OlatSite.LEARNING_RESOURCES)){
+			return(false);
+		}
+		
+		if(!openActionByMenuTree(browser, RepositorySiteAction.CATALOG)){
+			return(false);
+		}
+		
+		/* create selectors to open desired path within catalog and open it */
+		String[] selectors = createCatalogSelectors(path);
+		
+		for(String currentSelector: selectors){
+			functionalUtil.waitForPageToLoadElement(browser, currentSelector);
+			browser.click(currentSelector);
+		}
+		
+		functionalUtil.waitForPageToUnloadElement(browser, selectors[selectors.length - 1]);
+		
+		/* click create */
+		StringBuffer selectorBuffer = new StringBuffer();
+		
+		selectorBuffer.append("xpath=//a[contains(@class, '")
+		.append(getCatalogAddSubcategoryCss())
+		.append("')]");
+		
+		browser.click(selectorBuffer.toString());
+		
+		/* fill in name */
+		selectorBuffer = new StringBuffer();
+		
+		selectorBuffer.append("xpath=//form//div[contains(@class, '")
+		.append(getCatalogAddSubcategoryPopupCss())
+		.append("')]//input[@type='text']");
+		
+		functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
+		browser.type(selectorBuffer.toString(), name);
+		
+		/* fill in description */
+		selectorBuffer = new StringBuffer();
+		
+		selectorBuffer.append("xpath=//form//div[contains(@class, '")
+		.append(getCatalogAddSubcategoryPopupCss())
+		.append("')]//textarea");
+		
+		browser.type(selectorBuffer.toString(), description);
+		
+		/* click save */
+		selectorBuffer = new StringBuffer();
+		
+		selectorBuffer.append("xpath=(//form//div[contains(@class, '")
+		.append(getCatalogAddSubcategoryPopupCss())
+		.append("')]//button[contains(@class, '")
+		.append(functionalUtil.getButtonDirtyCss())
+		.append("')])[last()]");
+		
+		browser.click(selectorBuffer.toString());
+		
+		functionalUtil.waitForPageToUnloadElement(browser, selectorBuffer.toString());
+		
+		return(true);
+	}
+	
+	/**
+	 * @param browser
+	 * @param column
+	 * @return
+	 * 
+	 * Select displayed columns of repository table.
+	 */
 	public boolean displayColumns(Selenium browser, List<Column> column){
 		//TODO:JK: implement me
 		
@@ -1117,6 +1253,48 @@ public class FunctionalRepositorySiteUtil {
 		this.repositorySiteGlossaryCss = repositorySiteGlossaryCss;
 	}
 
+	public String getCatalogAddSubcategoryCss() {
+		return catalogAddSubcategoryCss;
+	}
+
+	public void setCatalogAddSubcategoryCss(String catalogAddSubcategoryCss) {
+		this.catalogAddSubcategoryCss = catalogAddSubcategoryCss;
+	}
+
+	public String getCatalogAddLearningResourceCss() {
+		return catalogAddLearningResourceCss;
+	}
+
+	public void setCatalogAddLearningResourceCss(
+			String catalogAddLearningResourceCss) {
+		this.catalogAddLearningResourceCss = catalogAddLearningResourceCss;
+	}
+
+	public String getCatalogAddSubcategoryPopupCss() {
+		return catalogAddSubcategoryPopupCss;
+	}
+
+	public void setCatalogAddSubcategoryPopupCss(
+			String catalogAddSubcategoryPopupCss) {
+		this.catalogAddSubcategoryPopupCss = catalogAddSubcategoryPopupCss;
+	}
+
+	public String getCatalogSubcategoryListCss() {
+		return catalogSubcategoryListCss;
+	}
+
+	public void setCatalogSubcategoryListCss(String catalogSubcategoryListCss) {
+		this.catalogSubcategoryListCss = catalogSubcategoryListCss;
+	}
+
+	public String getCatalogSubcategoryIconCss() {
+		return catalogSubcategoryIconCss;
+	}
+
+	public void setCatalogSubcategoryIconCss(String catalogSubcategoryIconCss) {
+		this.catalogSubcategoryIconCss = catalogSubcategoryIconCss;
+	}
+
 	public String getImportCourseCss() {
 		return importCourseCss;
 	}
diff --git a/src/test/java/org/olat/util/FunctionalUserManagementSiteUtil.java b/src/test/java/org/olat/util/FunctionalUserManagementSiteUtil.java
index 817278d04e8..587f7b5a664 100644
--- a/src/test/java/org/olat/util/FunctionalUserManagementSiteUtil.java
+++ b/src/test/java/org/olat/util/FunctionalUserManagementSiteUtil.java
@@ -19,6 +19,9 @@
  */
 package org.olat.util;
 
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
+
 import com.thoughtworks.selenium.Selenium;
 
 /**
@@ -26,7 +29,8 @@ import com.thoughtworks.selenium.Selenium;
  * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com
  */
 public class FunctionalUserManagementSiteUtil {
-
+	private final static OLog log = Tracing.createLoggerFor(FunctionalUserManagementSiteUtil.class);
+	
 	public enum UserManagementSiteAction {
 		USER_SEARCH,
 		CREATE_USER,
diff --git a/src/test/java/org/olat/util/FunctionalUtil.java b/src/test/java/org/olat/util/FunctionalUtil.java
index 375617aedcc..e9a07e7857a 100644
--- a/src/test/java/org/olat/util/FunctionalUtil.java
+++ b/src/test/java/org/olat/util/FunctionalUtil.java
@@ -106,6 +106,8 @@ public class FunctionalUtil {
 	
 	public final static String BUTTON_DIRTY_CSS = "b_button_dirty";
 	
+	public final static String NOTIFICATION_BOX_CSS = "o_sel_info_message";
+	
 	private String username;
 	private String password;
 	
@@ -406,6 +408,12 @@ public class FunctionalUtil {
 		return(checkCurrentSite(browser, site, -1));
 	}
 	
+	/**
+	 * @param browser
+	 * @param site
+	 * @param timeout
+	 * @return
+	 */
 	public boolean checkCurrentSite(Selenium browser, OlatSite site, long timeout){
 		String selectedCss = findCssClassOfSite(site);
 		
@@ -507,6 +515,7 @@ public class FunctionalUtil {
 			return(false);
 		}
 		
+		//FIXME:JK: this is a known bottleneck, but can't be set to -1 until notifications will be clicked away!
 		if(checkCurrentSite(browser, site, Long.parseLong(getWaitLimit()))){
 			if(resetSite(browser, site)){
 				return(true);
@@ -534,6 +543,13 @@ public class FunctionalUtil {
 		return(true);
 	}
 	
+	/**
+	 * @param browser
+	 */
+	public void clickAwayNotification(Selenium browser){
+		//TODO:JK: the impatients and fearless may want to implement this method but be aware there may be more than one notification at the same time
+	}
+	
 	/**
 	 * @param browser
 	 * @return true on success otherwise false
@@ -709,6 +725,8 @@ public class FunctionalUtil {
 		.append(radioIndex)
 		.append("]");
 		
+		waitForPageToLoadElement(browser, selectorBuffer.toString());
+		
 		browser.click(selectorBuffer.toString());
 		
 		return(true);
@@ -730,6 +748,8 @@ public class FunctionalUtil {
 		.append("//input[@type='radio' and @value='")
 		.append(value)
 		.append("']");
+
+		waitForPageToLoadElement(browser, selectorBuffer.toString());
 		
 		browser.click(selectorBuffer.toString());
 
diff --git a/src/test/java/org/olat/util/FunctionalVOUtil.java b/src/test/java/org/olat/util/FunctionalVOUtil.java
index 013813c83de..5b617c0ef7e 100644
--- a/src/test/java/org/olat/util/FunctionalVOUtil.java
+++ b/src/test/java/org/olat/util/FunctionalVOUtil.java
@@ -44,13 +44,16 @@ 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.core.logging.OLog;
+import org.olat.core.logging.Tracing;
 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 {
-
+	private final static OLog log = Tracing.createLoggerFor(FunctionalVOUtil.class);
+	
 	public final static String WAIT_LIMIT = "15000";
 	
 	public final static String ALL_ELEMENTS_COURSE_DISPLAYNAME = "All Elements Course Without External Content";
-- 
GitLab