From cea9595f919a7c63f7f6364afee7eef4e1e8dff8 Mon Sep 17 00:00:00 2001
From: jkraehemann <none@none>
Date: Tue, 11 Sep 2012 13:46:09 +0200
Subject: [PATCH] OO-306: Implemented test case. Moved some ressources.

---
 .../portfolio/FunctionalPortfolioTest.java    | 130 +++++++++++++
 .../olat/portfolio/Course_including_Blog.zip  | Bin
 .../olat/portfolio/Course_including_Forum.zip | Bin
 .../portfolio/FunctionalPortfolioTest.java    |  76 --------
 .../org/olat/portfolio/blog.zip               | Bin
 .../org/olat/portfolio/sfqcodel.cc            |   0
 .../org/olat/portfolio/wiki.zip               | Bin
 .../org/olat/util/FunctionalCourseUtil.java   | 181 +++++++++++++++++-
 .../olat/util/FunctionalEPortfolioUtil.java   |  80 ++++++--
 .../java/org/olat/util/FunctionalUtil.java    |   2 +
 10 files changed, 371 insertions(+), 98 deletions(-)
 create mode 100644 src/test/java/org/olat/course/nodes/portfolio/FunctionalPortfolioTest.java
 rename src/test/{resources => java}/org/olat/portfolio/Course_including_Blog.zip (100%)
 rename src/test/{resources => java}/org/olat/portfolio/Course_including_Forum.zip (100%)
 delete mode 100644 src/test/java/org/olat/portfolio/FunctionalPortfolioTest.java
 rename src/test/{resources => java}/org/olat/portfolio/blog.zip (100%)
 rename src/test/{resources => java}/org/olat/portfolio/sfqcodel.cc (100%)
 rename src/test/{resources => java}/org/olat/portfolio/wiki.zip (100%)

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 00000000000..e7438130058
--- /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/resources/org/olat/portfolio/Course_including_Blog.zip b/src/test/java/org/olat/portfolio/Course_including_Blog.zip
similarity index 100%
rename from src/test/resources/org/olat/portfolio/Course_including_Blog.zip
rename to src/test/java/org/olat/portfolio/Course_including_Blog.zip
diff --git a/src/test/resources/org/olat/portfolio/Course_including_Forum.zip b/src/test/java/org/olat/portfolio/Course_including_Forum.zip
similarity index 100%
rename from src/test/resources/org/olat/portfolio/Course_including_Forum.zip
rename to src/test/java/org/olat/portfolio/Course_including_Forum.zip
diff --git a/src/test/java/org/olat/portfolio/FunctionalPortfolioTest.java b/src/test/java/org/olat/portfolio/FunctionalPortfolioTest.java
deleted file mode 100644
index b19d8f022ac..00000000000
--- a/src/test/java/org/olat/portfolio/FunctionalPortfolioTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * <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.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.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.olat.test.ArquillianDeployments;
-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 FunctionalPortfolioTest {
-	@Deployment(testable = false)
-	public static WebArchive createDeployment() {
-		return ArquillianDeployments.createDeployment();
-	}
-
-	@Drone
-	DefaultSelenium browser;
-
-	@ArquillianResource
-	URL deploymentUrl;
-
-	FunctionalUtil functionalUtil;
-	FunctionalVOUtil functionalVOUtil;
-	FunctionalRepositorySiteUtil functionalRepositorySiteUtil;
-	
-	@Before
-	public void setup(){
-		functionalUtil = new FunctionalUtil();
-		functionalUtil.setDeploymentUrl(deploymentUrl.toString());
-		
-		functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
-		functionalRepositorySiteUtil = new FunctionalRepositorySiteUtil(functionalUtil);
-	}
-
-	@Test
-	@RunAsClient
-	public void checkCreate(){
-		//TODO:JK: implement me
-		
-	}
-}
diff --git a/src/test/resources/org/olat/portfolio/blog.zip b/src/test/java/org/olat/portfolio/blog.zip
similarity index 100%
rename from src/test/resources/org/olat/portfolio/blog.zip
rename to src/test/java/org/olat/portfolio/blog.zip
diff --git a/src/test/resources/org/olat/portfolio/sfqcodel.cc b/src/test/java/org/olat/portfolio/sfqcodel.cc
similarity index 100%
rename from src/test/resources/org/olat/portfolio/sfqcodel.cc
rename to src/test/java/org/olat/portfolio/sfqcodel.cc
diff --git a/src/test/resources/org/olat/portfolio/wiki.zip b/src/test/java/org/olat/portfolio/wiki.zip
similarity index 100%
rename from src/test/resources/org/olat/portfolio/wiki.zip
rename to src/test/java/org/olat/portfolio/wiki.zip
diff --git a/src/test/java/org/olat/util/FunctionalCourseUtil.java b/src/test/java/org/olat/util/FunctionalCourseUtil.java
index a0633fb1714..5af3df545cb 100644
--- a/src/test/java/org/olat/util/FunctionalCourseUtil.java
+++ b/src/test/java/org/olat/util/FunctionalCourseUtil.java
@@ -30,6 +30,9 @@ 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";
@@ -61,13 +64,17 @@ public class FunctionalCourseUtil {
 	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 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 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";
@@ -213,9 +220,20 @@ public class FunctionalCourseUtil {
 		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;
@@ -245,11 +263,15 @@ public class FunctionalCourseUtil {
 	private String cpChooseRepositoryFileCss;
 	private String wikiChooseRepositoryFileCss;
 	private String feedChooseRepositoryFileCss;
+	private String mapChooseRepositoryFileCss;
 	
+	private String repositoryPopupCss;
 	private String repositoryPopupCreateResourceCss;
 	private String repositorySaveDetailsCss;
 	private String repositoryAddForwardCss;
 	
+	private String mapEditCss;
+	
 	private String blogNoPostsCss;
 	private String podcastNoEpisodesCss;
 	
@@ -263,6 +285,9 @@ public class FunctionalCourseUtil {
 		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);
@@ -292,11 +317,15 @@ public class FunctionalCourseUtil {
 		setCpChooseRepositoryFileCss(CP_CHOOSE_REPOSITORY_FILE_CSS);
 		setWikiChooseRepositoryFileCss(WIKI_CHOOSE_REPOSITORY_FILE_CSS);
 		setFeedChooseRepositoryFileCss(FEED_CHOOSE_REPOSITORY_FILE_CSS);
+		setMapChooseRepositoryFileCss(MAP_CHOOSE_REPOSITORY_FILE_CSS);
 		
+		setRepositoryPopupCss(REPOSITORY_POPUP_CSS);
 		setRepositoryPopupCreateResourceCss(REPOSITORY_POPUP_CREATE_RESOURCE_CSS);
 		setRepositorySaveDetailsCss(REPOSITORY_SAVE_DETAILS_CSS);
 		setRepositoryAddForwardCss(REPOSITORY_ADD_FORWARD_CSS);
 		
+		setMapEditCss(MAP_EDIT_CSS);
+		
 		setBlogNoPostsCss(BLOG_NO_POSTS_CSS);
 		setPodcastNoEpisodesCss(PODCAST_NO_EPISODES_CSS);
 	}
@@ -348,6 +377,51 @@ public class FunctionalCourseUtil {
 		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
@@ -411,6 +485,7 @@ public class FunctionalCourseUtil {
 		.append(getCourseEditorPublishCss())
 		.append("')]");
 		
+		functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
 		browser.click(selectorBuffer.toString());
 		
 		/* select all course nodes */
@@ -963,6 +1038,17 @@ public class FunctionalCourseUtil {
 		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
@@ -972,6 +1058,7 @@ public class FunctionalCourseUtil {
 	 * 
 	 * Opens and fills in the "create resource" popup.
 	 */
+	//FIXME:JK: needs an additional class to find elements
 	private boolean createRepositoryResource(Selenium browser, String chooseRepositoryCss, String title, String description){
 		/* click on "choose, create or import file" button */
 		StringBuffer selectorBuffer = new StringBuffer();
@@ -983,6 +1070,8 @@ public class FunctionalCourseUtil {
 		functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
 		browser.click(selectorBuffer.toString());
 		
+		functionalUtil.waitForPageToLoad(browser);
+		
 		/* click create button */
 		selectorBuffer = new StringBuffer();
 		
@@ -998,17 +1087,22 @@ public class FunctionalCourseUtil {
 		/* fill in title */
 		selectorBuffer = new StringBuffer();
 		
-		selectorBuffer.append("xpath=//div[contains(@class, 'b_window')]//form//input[@type='text']");
+		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, description);
+		functionalUtil.typeMCE(browser, getRepositoryPopupCss(), description);
 		
 		/* click save */
 		selectorBuffer = new StringBuffer();
 		
-		selectorBuffer.append("xpath=(//div[contains(@class, 'b_window')]//form//div[contains(@class, '")
+		selectorBuffer.append("xpath=(//div[contains(@class, '")
+		.append(getRepositoryPopupCss())
+		.append("')]//form//div[contains(@class, '")
 		.append(getRepositorySaveDetailsCss())
 		.append("')]//button)[1]");
 		
@@ -1047,6 +1141,8 @@ public class FunctionalCourseUtil {
 		if(!createRepositoryResource(browser, getTestChooseRepositoryFileCss(), title, description)){
 			return(false);
 		}
+		
+		functionalUtil.waitForPageToLoad(browser);
 				
 		return(true);
 	}
@@ -1127,6 +1223,45 @@ public class FunctionalCourseUtil {
 		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;
 	}
@@ -1160,6 +1295,22 @@ public class FunctionalCourseUtil {
 		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;
 	}
@@ -1340,6 +1491,22 @@ public class FunctionalCourseUtil {
 		this.feedChooseRepositoryFileCss = feedChooseRepositoryFileCss;
 	}
 
+	public String getMapChooseRepositoryFileCss() {
+		return mapChooseRepositoryFileCss;
+	}
+
+	public void setMapChooseRepositoryFileCss(String mapChooseRepositoryFileCss) {
+		this.mapChooseRepositoryFileCss = mapChooseRepositoryFileCss;
+	}
+
+	public String getRepositoryPopupCss() {
+		return repositoryPopupCss;
+	}
+
+	public void setRepositoryPopupCss(String repositoryPopupCss) {
+		this.repositoryPopupCss = repositoryPopupCss;
+	}
+
 	public String getRepositoryPopupCreateResourceCss() {
 		return repositoryPopupCreateResourceCss;
 	}
@@ -1364,6 +1531,14 @@ public class FunctionalCourseUtil {
 		this.repositoryAddForwardCss = repositoryAddForwardCss;
 	}
 
+	public String getMapEditCss() {
+		return mapEditCss;
+	}
+
+	public void setMapEditCss(String mapEditCss) {
+		this.mapEditCss = mapEditCss;
+	}
+
 	public String getBlogNoPostsCss() {
 		return blogNoPostsCss;
 	}
diff --git a/src/test/java/org/olat/util/FunctionalEPortfolioUtil.java b/src/test/java/org/olat/util/FunctionalEPortfolioUtil.java
index 97dfc857569..53e743c292f 100644
--- a/src/test/java/org/olat/util/FunctionalEPortfolioUtil.java
+++ b/src/test/java/org/olat/util/FunctionalEPortfolioUtil.java
@@ -261,13 +261,14 @@ public class FunctionalEPortfolioUtil {
 	 * 
 	 * Opens the editor of open binder.
 	 */
-	private boolean openEditor(Selenium browser){
+	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);
@@ -370,8 +371,14 @@ public class FunctionalEPortfolioUtil {
 	 * Create a page in the specified binder.
 	 */
 	public boolean createPage(Selenium browser, String binder, String title, ArtefactDisplay display, String description){
-		if(!openBinder(browser, binder))
-			return(false);
+		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();
@@ -385,24 +392,28 @@ public class FunctionalEPortfolioUtil {
 		functionalUtil.waitForPageToLoad(browser);
 		
 		/* fill in wizard - title */
-		selectorBuffer = new StringBuffer();
-		
-		selectorBuffer.append("xpath=//div[contains(@class, '")
-		.append(getEPortfolioMapCss())
-		.append("')]//form//input[@type='text']");
-		
-		browser.type(selectorBuffer.toString(), 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 */
-		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());
+		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);
@@ -416,6 +427,37 @@ public class FunctionalEPortfolioUtil {
 		
 		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);
 	}
 	
diff --git a/src/test/java/org/olat/util/FunctionalUtil.java b/src/test/java/org/olat/util/FunctionalUtil.java
index 0e6424add4a..23cb31cb915 100644
--- a/src/test/java/org/olat/util/FunctionalUtil.java
+++ b/src/test/java/org/olat/util/FunctionalUtil.java
@@ -585,6 +585,7 @@ public class FunctionalUtil {
 		.append(getOlatTopNavigationLogoutCss())
 		.append(" a");
 		
+		waitForPageToLoadElement(browser, selectorBuffer.toString());
 		browser.click(selectorBuffer.toString());
 		waitForPageToLoad(browser);
 		
@@ -851,6 +852,7 @@ public class FunctionalUtil {
 		optionLocatorBuffer.append("value=")
 		.append(value);
 		
+		waitForPageToLoadElement(browser, selectLocatorBuffer.toString());
 		browser.select(selectLocatorBuffer.toString(), optionLocatorBuffer.toString());
 		
 		return(true);
-- 
GitLab