From 8a50eb08427fa3a73e3f145ef6efd708fba47247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Kr=C3=A4hemann?= <joel.kraehemann@frentix.com> Date: Thu, 18 Oct 2012 17:38:48 +0200 Subject: [PATCH] OO-302: enhanced syncing threads and implemented new test. --- .../course/nodes/feed/FunctionalBlogTest.java | 220 ++++++++++++++++-- .../java/org/olat/course/nodes/feed/blog.zip | Bin 0 -> 511 bytes .../FunctionalAdministrationSiteUtil.java | 161 ++++++++++++- .../org/olat/util/FunctionalCourseUtil.java | 5 + .../java/org/olat/util/FunctionalUtil.java | 74 +++++- .../java/org/olat/util/FunctionalVOUtil.java | 81 +++++-- 6 files changed, 498 insertions(+), 43 deletions(-) create mode 100644 src/test/java/org/olat/course/nodes/feed/blog.zip 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 fd1239e214c..7f0a7c7292a 100644 --- a/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java +++ b/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java @@ -25,6 +25,8 @@ import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.lang.ArrayUtils; import org.jboss.arquillian.container.test.api.Deployment; @@ -39,12 +41,15 @@ import org.junit.Ignore; 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.FunctionalAdministrationSiteUtil; import org.olat.util.FunctionalCourseUtil; import org.olat.util.FunctionalCourseUtil.BlogEdit; import org.olat.util.FunctionalRepositorySiteUtil; import org.olat.util.FunctionalUtil; +import org.olat.util.FunctionalUtil.OlatSite; import org.olat.util.FunctionalUtil.WaitLimitAttribute; import org.olat.util.FunctionalVOUtil; import org.olat.util.FunctionalCourseUtil.CourseNodeAlias; @@ -52,6 +57,7 @@ import org.olat.util.browser.Browser1; import org.olat.util.browser.Browser2; import org.olat.util.browser.Student1; import org.olat.util.browser.Student2; +import org.olat.util.browser.Tutor1; import com.thoughtworks.selenium.DefaultSelenium; import com.thoughtworks.selenium.Selenium; @@ -73,6 +79,17 @@ public class FunctionalBlogTest { public final static String DELETE_BLOG_DESCRIPTION = "The first blog entry will be deleted"; public final static String DELETE_BLOG_CONTENT = "You should be able to choose to create or feed from existing blog."; + public final static String CONCURRENT_CLEAR_CACHE_BLOG = "/org/olat/course/nodes/feed/blog.zip"; + public final static String CONCURRENT_CLEAR_CACHE_BLOG_FILE_NAME = "blog.zip"; + public final static String CONCURRENT_CLEAR_CACHE_BLOG_RESOURCE_NAME = "Blog"; + public final static String CONCURRENT_CLEAR_CACHE_BLOG_DISPLAY_NAME = "Parallel Computing Blog"; + public final static String CONCURRENT_CLEAR_CACHE_BLOG_POST1_TITLE = "Conditional locks with Java"; + public final static String CONCURRENT_CLEAR_CACHE_BLOG_POST1_DESCRIPTION = "Advanced thread safety in Java."; + public final static String CONCURRENT_CLEAR_CACHE_BLOG_POST1_CONTENT = "Please take a look at ReentrantLock class in JavaSE package java.util.concurrent.locks for further information."; + public final static String CONCURRENT_CLEAR_CACHE_BLOG_POST2_TITLE = "Creating conditions"; + public final static String CONCURRENT_CLEAR_CACHE_BLOG_POST2_DESCRIPTION = "Wait until condition is fulfilled."; + public final static String CONCURRENT_CLEAR_CACHE_BLOG_POST2_CONTENT = "With the ReentrantLock class you may create new conditions like following:<br><code>final Lock lock = new ReentrantLock();<br>final Condition cond = lock.newCondition()<br></code>"; + public final static String CONCURRENT_RW_BLOG_SHORT_TITLE = "blog"; public final static String CONCURRENT_RW_BLOG_LONG_TITLE = "blog cleared cache"; public final static String CONCURRENT_RW_BLOG_DESCRIPTION = "During open blog cache will be cleared"; @@ -93,6 +110,7 @@ public class FunctionalBlogTest { static FunctionalUtil functionalUtil; static FunctionalRepositorySiteUtil functionalRepositorySiteUtil; static FunctionalCourseUtil functionalCourseUtil; + static FunctionalAdministrationSiteUtil functionalAdministrationSiteUtil; static FunctionalVOUtil functionalVOUtil; static boolean initialized = false; @@ -105,7 +123,9 @@ public class FunctionalBlogTest { functionalRepositorySiteUtil = functionalUtil.getFunctionalRepositorySiteUtil(); functionalCourseUtil = functionalRepositorySiteUtil.getFunctionalCourseUtil(); - + + functionalAdministrationSiteUtil = functionalUtil.getFunctionalAdministrationSiteUtil(); + functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword()); initialized = true; @@ -141,8 +161,139 @@ public class FunctionalBlogTest { @Ignore @Test @RunAsClient - public void checkConcurrentClearCache(){ + public void checkDelete(){ + //TODO:JK: implement me + } + + @Ignore + @Test + @RunAsClient + public void checkConcurrentClearCache(@Drone @Tutor1 DefaultSelenium tutor0, @Drone @Student1 DefaultSelenium student0) throws IOException, URISyntaxException{ + /* + * Setup + */ + /* create author */ + int tutorCount = 1; + + final UserVO[] tutors = new UserVO[tutorCount]; + functionalVOUtil.createTestUsers(deploymentUrl, tutorCount).toArray(tutors); + + /* create user */ + int userCount = 1; + + final UserVO[] students = new UserVO[userCount]; + functionalVOUtil.createTestUsers(deploymentUrl, userCount).toArray(students); + + /* create blog and set rights for tutor */ + RepositoryEntryVO repoEntry = functionalVOUtil.importBlog(deploymentUrl, + CONCURRENT_CLEAR_CACHE_BLOG, + CONCURRENT_CLEAR_CACHE_BLOG_FILE_NAME, CONCURRENT_CLEAR_CACHE_BLOG_RESOURCE_NAME, CONCURRENT_CLEAR_CACHE_BLOG_DISPLAY_NAME); + //FIXME:JK: set rights + + /* + * Create content and visit it. + */ + /* tutor creates a new post */ + Assert.assertTrue(functionalUtil.login(tutor0, tutors[0].getLogin(), tutors[0].getPassword(), true)); + Assert.assertTrue(functionalCourseUtil.openBlog(tutor0, repoEntry.getKey())); + Assert.assertTrue(functionalCourseUtil.editBlogEntry(tutor0, + CONCURRENT_CLEAR_CACHE_BLOG_POST1_TITLE, CONCURRENT_CLEAR_CACHE_BLOG_POST1_DESCRIPTION, CONCURRENT_CLEAR_CACHE_BLOG_POST1_CONTENT, + -1, null)); + + /* student visits content */ + Assert.assertTrue(functionalUtil.login(student0, students[0].getLogin(), students[0].getPassword(), true)); + Assert.assertTrue(functionalCourseUtil.openBlog(student0, repoEntry.getKey())); + + + /* + * Clear cache and verify content. + */ + /* admin clears cache */ + Assert.assertTrue(functionalUtil.login(browser, functionalUtil.getUsername(), functionalUtil.getPassword(), true)); + Assert.assertTrue(functionalAdministrationSiteUtil.clearCache(browser, + new String[]{ + "org.olat.core.util.cache.n.impl.svm.SingleVMCacher@org.olat.modules.webFeed.dispatching.Path_feed__0", + "org.olat.core.util.cache.n.impl.svm.SingleVMCacher@org.olat.modules.webFeed.managers.FeedManagerImpl_feed__0" + } + )); + + Assert.assertTrue(functionalUtil.logout(browser)); + + /* tutor adds a new post */ + //Assert.assertTrue(functionalCourseUtil.backBlogEntry(tutor0)); + Assert.assertTrue(functionalCourseUtil.editBlogEntry(tutor0, + CONCURRENT_CLEAR_CACHE_BLOG_POST2_TITLE, CONCURRENT_CLEAR_CACHE_BLOG_POST2_DESCRIPTION, CONCURRENT_CLEAR_CACHE_BLOG_POST2_CONTENT, + -1, null)); + + /* student verifies title - month */ + functionalUtil.idle(student0); + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//ul[contains(@class, '") + .append(functionalCourseUtil.getBlogMonthCss()) + .append("')]//li//a)"); + + int iStop = student0.getXpathCount(selectorBuffer.toString()).intValue(); + boolean foundTitleInMonth = false; + + for(int i = 0; i < iStop; i++){ + functionalUtil.idle(student0); + + StringBuffer currentBuffer = new StringBuffer(selectorBuffer); + + currentBuffer.append('[') + .append(i + 1) + .append(']'); + + student0.click(currentBuffer.toString()); + + functionalUtil.idle(student0); + + if(student0.isTextPresent(CONCURRENT_CLEAR_CACHE_BLOG_POST2_TITLE)){ + foundTitleInMonth = true; + break; + } + } + + Assert.assertTrue(foundTitleInMonth); + + /* student verifies title - year */ + functionalUtil.idle(student0); + + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div//a[contains(@class, '") + .append(functionalCourseUtil.getBlogYearCss()) + .append("')])"); + + iStop = student0.getXpathCount(selectorBuffer.toString()).intValue(); + boolean foundTitleInYear = false; + + for(int i = 0; i < iStop; i++){ + functionalUtil.idle(student0); + + StringBuffer currentBuffer = new StringBuffer(selectorBuffer); + + currentBuffer.append('[') + .append(i + 1) + .append(']'); + + student0.click(currentBuffer.toString()); + + functionalUtil.idle(student0); + + if(student0.isTextPresent(CONCURRENT_CLEAR_CACHE_BLOG_POST2_TITLE)){ + foundTitleInYear = true; + break; + } + } + + Assert.assertTrue(foundTitleInYear); + + /* logout */ + Assert.assertTrue(functionalUtil.logout(tutor0)); + Assert.assertTrue(functionalUtil.logout(student0)); } @Test @@ -183,10 +334,19 @@ public class FunctionalBlogTest { student[1] = (Selenium) student1; final boolean[] success = new boolean[userCount]; - Arrays.fill(success, false); + Arrays.fill(success, true); + + /* for syncing threads */ + final ReentrantLock lock = new ReentrantLock(); + final ReentrantLock subroutineLock = new ReentrantLock(); + final Condition cond = lock.newCondition(); + final boolean[] doSignal = new boolean[1]; + doSignal[0] = false; - List<Thread> threads = new ArrayList<Thread>(); + final boolean[] finished = new boolean[userCount]; + Arrays.fill(finished, false); + /* students log in an visit blog */ for(int i = 0; i < userCount; i++){ final int index = i; @@ -203,19 +363,33 @@ public class FunctionalBlogTest { functionalCourseUtil.openBlogWithoutBusinessPath(student[i], course.getRepoEntryKey(), 0); functionalCourseUtil.openBlogEntry(student[i], 0); }catch(Exception e){ - // success[i] = false; + success[i] = false; + }finally{ + finished[i] = true; + + lock.lock(); + if(doSignal[0]){ + cond.signal(); + } + lock.unlock(); } } }); thread.start(); - threads.add(thread); } /* wait for browsers to be ready */ - for(Thread currentThread: threads){ - currentThread.join(60000); + lock.lock(); + doSignal[0] = true; + + try{ + while(ArrayUtils.contains(finished, false)){ + cond.await(); + } + }finally{ + lock.unlock(); } /* edit blog as author */ @@ -223,7 +397,8 @@ public class FunctionalBlogTest { null, null, CONCURRENT_RW_BLOG_NEW_CONTENT, 0, new BlogEdit[]{BlogEdit.CONTENT})); /* open entry by users */ - threads = new ArrayList<Thread>(); + Arrays.fill(finished, false); + doSignal[0] = false; for(int i = 0; i < userCount; i++){ final int index = i; @@ -238,25 +413,40 @@ public class FunctionalBlogTest { public void run() { try{ functionalCourseUtil.backBlogEntry(student[i]); - functionalUtil.waitForPageToLoadContent(student[i], null, CONCURRENT_RW_BLOG_NEW_CONTENT, WaitLimitAttribute.VERY_SAVE, null, false); + functionalCourseUtil.openBlogEntry(student[i], 0); + functionalUtil.waitForPageToLoadContent(student[i], null, CONCURRENT_RW_BLOG_NEW_CONTENT, WaitLimitAttribute.VERY_SAVE, null, true); functionalUtil.logout(student[i]); - success[i] = true; }catch(Exception e){ - // empty + success[i] = false; + }finally{ + finished[i] = true; + + lock.lock(); + if(doSignal[0]){ + cond.signal(); + } + lock.unlock(); } } }); thread.start(); - threads.add(thread); } /* wait for browsers to be logged out */ - for(Thread currentThread: threads){ - currentThread.join(60000); + lock.lock(); + doSignal[0] = true; + + try{ + while(ArrayUtils.contains(finished, false)){ + cond.await(); + } + }finally{ + lock.unlock(); } + Assert.assertFalse(ArrayUtils.contains(success, false)); Assert.assertTrue(functionalUtil.logout(browser)); diff --git a/src/test/java/org/olat/course/nodes/feed/blog.zip b/src/test/java/org/olat/course/nodes/feed/blog.zip new file mode 100644 index 0000000000000000000000000000000000000000..3064933f8387d1e20e8ababb501af218cab5ed1d GIT binary patch literal 511 zcmWIWW@Zs#-~dADq98{GB)|b=r=_N*=vCzAFwSF0{BL6qWGR%T78Pga=h-S5>KQ00 zq~;~(r)1`(+bV^IxanFb+1qj1fHc{0DJa-vrr24SnHZZ|npv7!8XB6L+2{j>Kr$tj z1*vv!nK`LJsm1xFMaijpPCowbHu_+3kb>O&l+>Ish*fq*Hu@-hu-PT4xt=M-`at{i z!4?L1vvV9cFo$6=(Ao2VH~^=|*nqN`K<&l)j0_C_|ARCFMHpB?1Q6iYn46lCnTSgx zBa;XNA~2C%1GWKTK9qz7ZGbnbE|4_LDIk|3z)c_%;%?&g2m!qaadLn+E7&+@24-;h Jcmrh^7y!L}T$lg= literal 0 HcmV?d00001 diff --git a/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java b/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java index 655bd2d45b4..59cd38099ae 100644 --- a/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java +++ b/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java @@ -19,8 +19,10 @@ */ package org.olat.util; +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; @@ -124,6 +126,21 @@ public class FunctionalAdministrationSiteUtil { } } + public enum SystemInformationTabs { + SESSIONS, + INFOMSG, + ERRORS, + LOGLEVELS, + SYSINFO, + SNOOP, + REQUESTLOGLEVEL, + USERSESSIONS, + LOCKS, + HIBERNATE, + CACHES, + BUILDINFO; + } + private FunctionalUtil functionalUtil; public FunctionalAdministrationSiteUtil(FunctionalUtil functionalUtil){ @@ -138,9 +155,149 @@ public class FunctionalAdministrationSiteUtil { * @return true on success otherwise false */ public boolean openActionByMenuTree(Selenium browser, Object action){ - //TODO:JK: implement me + functionalUtil.idle(browser); + + StringBuffer selectorBuffer; + + if(action instanceof AdministrationSiteAction){ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//li[contains(@class, '") + .append(((AdministrationSiteAction) action).getActionCss()) + .append("')]//a[contains(@class, '") + .append(functionalUtil.getTreeLevel1Css()) + .append("')]"); + }else if(action instanceof SystemConfigurationAction){ + /* check if collapsed */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//li[contains(@class, '") + .append(AdministrationSiteAction.CONFIGURATION.getActionCss()) + .append("')]//a[contains(@class, '") + .append(functionalUtil.getTreeLevelOpenCss()) + .append("')]"); + + if(browser.isElementPresent(selectorBuffer.toString())){ + browser.click(selectorBuffer.toString()); + functionalUtil.idle(browser); + } + + /* click */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//li[contains(@class, '") + .append(((SystemConfigurationAction) action).getActionCss()) + .append("')]//a[contains(@class, '") + .append(functionalUtil.getTreeLevel2Css()) + .append("')]"); + }else if(action instanceof SystemMaintenanceAction){ + /* check if collapsed */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//li[contains(@class, '") + .append(AdministrationSiteAction.MAINTENANCE.getActionCss()) + .append("')]//a[contains(@class, '") + .append(functionalUtil.getTreeLevelOpenCss()) + .append("')]"); + + if(browser.isElementPresent(selectorBuffer.toString())){ + browser.click(selectorBuffer.toString()); + functionalUtil.idle(browser); + } + + /* click */ + selectorBuffer.append("xpath=//li[contains(@class, '") + .append(((SystemMaintenanceAction) action).getActionCss()) + .append("')]//a[contains(@class, '") + .append(functionalUtil.getTreeLevel2Css()) + .append("')]"); + }else if(action instanceof CustomizingAction){ + /* check if collapsed */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//li[contains(@class, '") + .append(AdministrationSiteAction.CUSTOMIZATION.getActionCss()) + .append("')]//a[contains(@class, '") + .append(functionalUtil.getTreeLevelOpenCss()) + .append("')]"); + + if(browser.isElementPresent(selectorBuffer.toString())){ + browser.click(selectorBuffer.toString()); + functionalUtil.idle(browser); + } + + /* click */ + selectorBuffer.append("xpath=//li[contains(@class, '") + .append(((CustomizingAction) action).getActionCss()) + .append("')]//a[contains(@class, '") + .append(functionalUtil.getTreeLevel2Css()) + .append("')]"); + }else{ + return(false); + } + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + return(true); + } + + /** + * Clears the specified cache which matches to keys. + * + * @param browser + * @param keys + * @return + */ + public boolean clearCache(Selenium browser, String[] keys){ + if(!functionalUtil.openSite(browser, OlatSite.ADMINISTRATION)){ + return(false); + } + + if(!openActionByMenuTree(browser, AdministrationSiteAction.INFORMATION)){ + return(false); + } + + if(!functionalUtil.openContentTab(browser, SystemInformationTabs.CACHES.ordinal())){ + return(false); + } + + functionalUtil.idle(browser); + + /* click show all*/ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(functionalUtil.getTableAllCss()) + .append("')]"); + + if(browser.isElementPresent(selectorBuffer.toString())){ + browser.click(selectorBuffer.toString()); + } + + boolean success = true; + + /* clear appropriate cache */ + for(String currentKey: keys){ + functionalUtil.idle(browser); + + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//table//tr//td[contains(@text, '") + .append(currentKey) + .append("\\n") + .append("')]"); + + if(browser.isElementPresent(selectorBuffer.toString())){ + selectorBuffer.append("/../td[last()]//a"); + + browser.click(selectorBuffer.toString()); + }else{ + success = false; + } + } - return(false); + return(success); } public FunctionalUtil getFunctionalUtil() { diff --git a/src/test/java/org/olat/util/FunctionalCourseUtil.java b/src/test/java/org/olat/util/FunctionalCourseUtil.java index 96f16b82d60..d7131575f8b 100644 --- a/src/test/java/org/olat/util/FunctionalCourseUtil.java +++ b/src/test/java/org/olat/util/FunctionalCourseUtil.java @@ -1326,6 +1326,11 @@ public class FunctionalCourseUtil { if(!openBlogWithoutBusinessPath(browser, courseId, nth)) return(false); + return(editBlogEntry(browser, title, description, content, entry, edit)); + } + + public boolean editBlogEntry(Selenium browser, + String title, String description, String content, int entry, BlogEdit[] edit){ StringBuffer selectorBuffer = new StringBuffer(); if(edit == null){ diff --git a/src/test/java/org/olat/util/FunctionalUtil.java b/src/test/java/org/olat/util/FunctionalUtil.java index 1da9a422b46..5aeb1193f07 100644 --- a/src/test/java/org/olat/util/FunctionalUtil.java +++ b/src/test/java/org/olat/util/FunctionalUtil.java @@ -126,11 +126,19 @@ public class FunctionalUtil { public final static String BUTTON_CSS = "b_button"; public final static String BUTTON_DIRTY_CSS = "b_button_dirty"; public final static String BACK_BUTTON_CSS = "b_link_back"; + public final static String TABLE_FIRST_CHILD_CSS = "b_first_child"; public final static String TABLE_LAST_CHILD_CSS = "b_last_child"; + public final static String TABLE_ALL_CSS = "b_table_page_all"; + public final static String TREE_NODE_ANCHOR_CSS = "x-tree-node-anchor"; public final static String TREE_NODE_CSS = "x-tree-node"; public final static String TREE_NODE_LOADING_CSS = "x-tree-node-loading"; + public final static String TREE_LEVEL1_CSS = "b_tree_l1"; + public final static String TREE_LEVEL2_CSS = "b_tree_l2"; + public final static String TREE_LEVEL_OPEN_CSS = "b_tree_level_open"; + public final static String TREE_LEVEL_CLOSE_CSS = "b_tree_level_close"; + public final static String WINDOW_CLOSE_LINK_CSS = "b_link_close"; public final static String FORM_SAVE_XPATH = "//button[@type='button' and last()]"; @@ -174,14 +182,22 @@ public class FunctionalUtil { private String mceContentBodyCss; private String windowCloseLinkCss; + private String buttonCss; private String buttonDirtyCss; private String backButtonCss; + private String tableFirstChildCss; private String tableLastChildCss; + private String tableAllCss; + private String treeNodeAnchorCss; private String treeNodeCss; private String treeNodeLoadingCss; + private String treeLevel1Css; + private String treeLevel2Css; + private String treeLevelOpenCss; + private String treeLevelCloseCss; private FunctionalHomeSiteUtil functionalHomeSiteUtil; private FunctionalGroupsSiteUtil functionalGroupsSiteUtil; @@ -242,15 +258,23 @@ public class FunctionalUtil { mceContentBodyCss = MCE_CONTENT_BODY_CSS; - windowCloseLinkCss = WINDOW_CLOSE_LINK_CSS; + windowCloseLinkCss = WINDOW_CLOSE_LINK_CSS; + buttonCss = BUTTON_CSS; buttonDirtyCss = BUTTON_DIRTY_CSS; backButtonCss = BACK_BUTTON_CSS; + tableFirstChildCss = TABLE_FIRST_CHILD_CSS; tableLastChildCss = TABLE_LAST_CHILD_CSS; + tableAllCss = TABLE_ALL_CSS; + treeNodeAnchorCss = TREE_NODE_ANCHOR_CSS; treeNodeCss = TREE_NODE_CSS; treeNodeLoadingCss = TREE_NODE_LOADING_CSS; + treeLevel1Css = TREE_LEVEL1_CSS; + treeLevel2Css = TREE_LEVEL2_CSS; + treeLevelOpenCss = TREE_LEVEL_OPEN_CSS; + treeLevelCloseCss = TREE_LEVEL_CLOSE_CSS; functionalHomeSiteUtil = new FunctionalHomeSiteUtil(this); functionalGroupsSiteUtil = new FunctionalGroupsSiteUtil(this); @@ -435,12 +459,14 @@ public class FunctionalUtil { } if((content == null && source == null) || - (flags != null && source != null && !ArrayUtils.contains(flags, WaitForContentFlag.EQUALS) && source.contains(content)) || - content.equals(source)){ + (flags != null && source != null && !ArrayUtils.contains(flags, WaitForContentFlag.EQUALS) && content.equals(source)) || + source.contains(content)){ log.info("found content after " + (currentTime - startTime) + "ms"); /* go back to toplevel */ - browser.selectFrame("relative=top"); + if(iframeSelectors != null){ + browser.selectFrame("relative=top"); + } return(true); } @@ -1599,6 +1625,14 @@ public class FunctionalUtil { this.tableLastChildCss = tableLastChildCss; } + public String getTableAllCss() { + return tableAllCss; + } + + public void setTableAllCss(String tableAllCss) { + this.tableAllCss = tableAllCss; + } + public String getTreeNodeAnchorCss() { return treeNodeAnchorCss; } @@ -1622,4 +1656,36 @@ public class FunctionalUtil { public void setTreeNodeLoadingCss(String treeNodeLoadingCss) { this.treeNodeLoadingCss = treeNodeLoadingCss; } + + public String getTreeLevel1Css() { + return treeLevel1Css; + } + + public void setTreeLevel1Css(String treeLevel1Css) { + this.treeLevel1Css = treeLevel1Css; + } + + public String getTreeLevel2Css() { + return treeLevel2Css; + } + + public void setTreeLevel2Css(String treeLevel2Css) { + this.treeLevel2Css = treeLevel2Css; + } + + public String getTreeLevelOpenCss() { + return treeLevelOpenCss; + } + + public void setTreeLevelOpenCss(String treeLevelOpenCss) { + this.treeLevelOpenCss = treeLevelOpenCss; + } + + public String getTreeLevelCloseCss() { + return treeLevelCloseCss; + } + + public void setTreeLevelCloseCss(String treeLevelCloseCss) { + this.treeLevelCloseCss = treeLevelCloseCss; + } } diff --git a/src/test/java/org/olat/util/FunctionalVOUtil.java b/src/test/java/org/olat/util/FunctionalVOUtil.java index 5b617c0ef7e..b142e409eec 100644 --- a/src/test/java/org/olat/util/FunctionalVOUtil.java +++ b/src/test/java/org/olat/util/FunctionalVOUtil.java @@ -19,6 +19,7 @@ */ package org.olat.util; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -37,6 +38,7 @@ import javax.ws.rs.core.UriBuilder; import org.apache.commons.httpclient.HttpClient; import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.mime.HttpMultipartMode; @@ -49,6 +51,7 @@ 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.RolesVO; import org.olat.user.restapi.UserVO; public class FunctionalVOUtil { @@ -90,13 +93,13 @@ public class FunctionalVOUtil { } /** + * Creates the selenium test users with random passwords and + * writes it to credentials.properties. + * * @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); @@ -140,11 +143,40 @@ public class FunctionalVOUtil { return(user); } - public void addUserToSysGroup(UserVO user, SysGroups group){ - //TODO:JK: implement me + public List<UserVO> createTestAuthors(URL deploymentUrl, int count) throws IOException, URISyntaxException{ + /* create ordinary users */ + List<UserVO> user = createTestUsers(deploymentUrl, count); + + /* make a tutor */ + RestConnection restConnection = new RestConnection(deploymentUrl); + + restConnection.login(getUsername(), getPassword()); + + for(UserVO currentUser: user){ + /* retrieve roles */ + URI request = UriBuilder.fromUri(deploymentUrl.toURI()).path("/users/" + currentUser.getKey() + "/roles").build(); + HttpGet getMethod = restConnection.createGet(request, MediaType.APPLICATION_JSON, true); + HttpResponse response = restConnection.execute(getMethod); + assertEquals(200, response.getStatusLine().getStatusCode()); + RolesVO roles = restConnection.parse(response, RolesVO.class); + + /* send appropriate role */ + roles.setAuthor(true); + roles.setUserManager(true); + + request = UriBuilder.fromUri(deploymentUrl.toURI()).path("/users/" + currentUser.getKey() + "/roles").build(); + HttpPost postMethod = restConnection.createPost(request, MediaType.APPLICATION_JSON, true); + restConnection.addJsonEntity(postMethod, roles); + response = restConnection.execute(postMethod); + assertEquals(200, response.getStatusLine().getStatusCode()); + } + + return(user); } /** + * Imports the specified course via REST. + * * @param deploymentUrl * @param path * @param filename @@ -153,8 +185,6 @@ public class FunctionalVOUtil { * @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{ //TODO:JK: may be replace this code because the course will just be deployed and not imported @@ -188,53 +218,60 @@ public class FunctionalVOUtil { return(vo); } + /** + * + * @param deploymentUrl + * @return + * @throws URISyntaxException + * @throws IOException + */ public CourseVO importEmptyCourse(URL deploymentUrl) throws URISyntaxException, IOException{ return(importCourse(deploymentUrl, "/org/olat/course/Empty_Course.zip", "Empty_Course.zip", "Empty Course", "Empty Course")); } /** + * Imports the "All Elements Course" via REST. + * * @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_Without_External_Content.zip", "All_Elements_Course_Without_External_Content.zip", "All Elements Course Without External Content", "All Elements Course Without External Content")); } /** + * Imports the "Course including Forum" via REST. + * * @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")); } /** + * Imports the "Course including Blog" via REST. + * * @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")); } /** + * imports a wiki via REST. + * * @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"); @@ -268,17 +305,17 @@ public class FunctionalVOUtil { } /** + * Imports a blog via REST. + * * @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"); + public RepositoryEntryVO importBlog(URL deploymentUrl, String path, String filename, String resourcename, String displayname) throws URISyntaxException, IOException{ + URL blogUrl = FunctionalVOUtil.class.getResource(path); Assert.assertNotNull(blogUrl); File blog = new File(blogUrl.toURI()); @@ -291,9 +328,9 @@ public class FunctionalVOUtil { 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("filename", new StringBody(filename)); + entity.addPart("resourcename", new StringBody(resourcename)); + entity.addPart("displayname", new StringBody(displayname)); entity.addPart("access", new StringBody("3")); method.setEntity(entity); -- GitLab