diff --git a/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java b/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java index e15b60ee8ec778e87abc9eee3e95b24faa376242..fe4b826ddd1e9f341d252174a1171a43695a2173 100644 --- a/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java +++ b/src/test/java/org/olat/portfolio/FunctionalArtefactTest.java @@ -40,6 +40,7 @@ import org.olat.restapi.support.vo.RepositoryEntryVO; import org.olat.test.ArquillianDeployments; import org.olat.user.restapi.UserVO; import org.olat.util.FunctionalCourseUtil; +import org.olat.util.FunctionalCourseUtil.AccessOption; import org.olat.util.FunctionalEPortfolioUtil; import org.olat.util.FunctionalHomeSiteUtil; import org.olat.util.FunctionalRepositorySiteUtil; @@ -165,7 +166,7 @@ public class FunctionalArtefactTest { /* create binder, page or structure if necessary */ Assert.assertTrue(functionalEportfolioUtil.createElements(browser, FORUM_BINDER, FORUM_PAGE, FORUM_STRUCTURE)); - + //FIXME:JK: really ugly try { Thread.sleep(500); @@ -194,7 +195,7 @@ public class FunctionalArtefactTest { /* create binder, page or structure if necessary */ Assert.assertTrue(functionalEportfolioUtil.createElements(browser, WIKI_BINDER, WIKI_PAGE, WIKI_STRUCTURE)); - + //FIXME:JK: really ugly try { Thread.sleep(500); @@ -202,7 +203,7 @@ public class FunctionalArtefactTest { // TODO Auto-generated catch block e.printStackTrace(); } - + /* create an article for the wiki */ Assert.assertTrue(functionalCourseUtil.createWikiArticle(browser, vo.getKey(), WIKI_ARTICLE_PAGENAME, WIKI_ARTICLE_CONTENT)); @@ -215,18 +216,35 @@ public class FunctionalArtefactTest { @Test @RunAsClient public void checkCollectBlogPost() throws URISyntaxException, IOException{ - /* import blog via rest */ - long repoKey = functionalRepositorySiteUtil.createBlog(browser, BLOG_TITLE, BLOG_DESCRIPTION); + /* deploy course with REST */ + CourseVO course = functionalVOUtil.importCourseIncludingBlog(deploymentUrl); + +// long repoKey = functionalRepositorySiteUtil.createBlog(browser, BLOG_TITLE, BLOG_DESCRIPTION); + + /* */ +// Assert.assertTrue(functionalUtil.login(browser, user.getLogin(), user.getPassword(), true)); +// Assert.assertTrue(functionalCourseUtil.openBlog(browser, repoKey)); +// Assert.assertTrue(functionalCourseUtil.openCourseEditor(browser)); +// Assert.assertTrue(functionalCourseUtil.disableAccessOption(browser, AccessOption.BLOCKED_FOR_LEARNERS, 1)); //TODO:JK: don't use hard coded form index + /* login for test setup */ Assert.assertTrue(functionalUtil.login(browser, user.getLogin(), user.getPassword(), true)); - /* create binder, page or structure if necessary */ Assert.assertTrue(functionalEportfolioUtil.createElements(browser, BLOG_BINDER, BLOG_PAGE, BLOG_STRUCTURE)); + //FIXME:JK: really ugly + try { + Thread.sleep(500); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + /* blog */ - Assert.assertTrue(functionalCourseUtil.createBlogEntry(browser, repoKey, BLOG_POST_TITLE, BLOG_POST_DESCRIPTION, BLOG_POST_CONTENT)); + Assert.assertTrue(functionalCourseUtil.createBlogEntry(browser, course.getRepoEntryKey(), 0, + BLOG_POST_TITLE, BLOG_POST_DESCRIPTION, BLOG_POST_CONTENT)); /* add artefact */ Assert.assertTrue(functionalCourseUtil.addToEportfolio(browser, BLOG_BINDER, BLOG_PAGE, BLOG_STRUCTURE, @@ -270,5 +288,7 @@ public class FunctionalArtefactTest { Assert.assertTrue(functionalEportfolioUtil.createLearningJournal(browser, LEARNING_JOURNAL_BINDER, LEARNING_JOURNAL_PAGE, LEARNING_JOURNAL_STRUCTURE, LEARNING_JOURNAL_TITLE, LEARNING_JOURNAL_DESCRIPTION, LEARNING_JOURNAL_TAGS)); + + System.out.println(); } } diff --git a/src/test/java/org/olat/util/FunctionalCourseUtil.java b/src/test/java/org/olat/util/FunctionalCourseUtil.java index d2220f4c7d6869dc2d5732e25a01490a12c9f343..b3fde027458c61e7bb3ee2c0dfa2f97fc6ccd992 100644 --- a/src/test/java/org/olat/util/FunctionalCourseUtil.java +++ b/src/test/java/org/olat/util/FunctionalCourseUtil.java @@ -34,6 +34,7 @@ public class FunctionalCourseUtil { public final static String EPORTFOLIO_ADD_CSS = "b_eportfolio_add"; public final static String FORUM_ICON_CSS = "o_fo_icon"; + public final static String BLOG_ICON_CSS = "o_blog_icon"; public final static String FORUM_TOOLBAR_CSS = "o_forum_toolbar"; public final static String FORUM_THREAD_NEW_CSS = "o_sel_forum_thread_new"; @@ -45,12 +46,73 @@ public class FunctionalCourseUtil { public final static String WIKI_EDIT_FORM_WRAPPER_CSS = "o_wikimod_editform_wrapper"; public final static String BLOG_CREATE_ENTRY_CSS = "o_sel_feed_item_new"; + public final static String BLOG_FORM_CSS = "o_sel_blog_form"; + + public enum CourseNodeTab { + TITLE_AND_DESCRIPTION, + VISIBILITY, + ACCESS, + CONTENT; + }; + + public enum VisibilityOption { + BLOCKED_FOR_LEARNERS, + DEPENDING_ON_DATE, + DEPENDING_ON_GROUP, + DEPENDING_ON_ASSESSMENT, + APPLY_TO_OWNERS_AND_TUTORS(DEPENDING_ON_ASSESSMENT); + + private VisibilityOption requires; + + VisibilityOption(){ + this(null); + } + + VisibilityOption(VisibilityOption requires){ + setRequires(requires); + } + + public VisibilityOption getRequires() { + return requires; + } + + public void setRequires(VisibilityOption requires) { + this.requires = requires; + } + }; + + public enum AccessOption { + BLOCKED_FOR_LEARNERS, + DEPENDING_ON_DATE, + DEPENDING_ON_GROUP, + DEPENDING_ON_ASSESSMENT, + APPLY_TO_OWNERS_AND_TUTORS(DEPENDING_ON_ASSESSMENT); + + private AccessOption requires; + + AccessOption(){ + this(null); + } + + AccessOption(AccessOption requires){ + setRequires(requires); + } + + public AccessOption getRequires() { + return requires; + } + + public void setRequires(AccessOption requires) { + this.requires = requires; + } + } private String courseRunCss; private String eportfolioAddCss; private String forumIconCss; + private String blogIconCss; private String forumToolbarCss; private String forumThreadNewCss; @@ -62,6 +124,7 @@ public class FunctionalCourseUtil { private String wikiEditFormWrapperCss; private String blogCreateEntryCss; + private String blogFormCss; private FunctionalUtil functionalUtil; private FunctionalRepositorySiteUtil functionalRepositorySiteUtil; @@ -75,6 +138,7 @@ public class FunctionalCourseUtil { setEportfolioAddCss(EPORTFOLIO_ADD_CSS); setForumIconCss(FORUM_ICON_CSS); + setBlogIconCss(BLOG_ICON_CSS); setForumToolbarCss(FORUM_TOOLBAR_CSS); setForumThreadNewCss(FORUM_THREAD_NEW_CSS); @@ -86,6 +150,7 @@ public class FunctionalCourseUtil { setWikiEditFormWrapperCss(WIKI_EDIT_FORM_WRAPPER_CSS); setBlogCreateEntryCss(BLOG_CREATE_ENTRY_CSS); + setBlogFormCss(BLOG_FORM_CSS); } /** @@ -135,6 +200,45 @@ public class FunctionalCourseUtil { return(true); } + /** + * @param browser + * @return true on success + * + * Opens the course editor but the course must be open. + */ + public boolean openCourseEditor(Selenium browser){ + //TODO:JK: implement me + return(false); + } + + /** + * @param browser + * @param option + * @param nthForm + * @return true on success + * + * Disables the specified access option, the course editor should be open. + */ + public boolean disableAccessOption(Selenium browser, AccessOption option, int nthForm){ + //TODO:JK: implement me + + return(false); + } + + /** + * @param browser + * @param option + * @param nthForm + * @return true on success + * + * Enables the specified access option, the course editor should be open. + */ + public boolean enableAccessOption(Selenium browser, AccessOption option, int nthForm){ + //TODO:JK: implement me + + return(false); + } + /** * @param browser * @return true on success @@ -173,8 +277,7 @@ public class FunctionalCourseUtil { /* click finish */ functionalUtil.clickWizardFinish(browser); - - functionalUtil.waitForPageToLoad(browser); + functionalUtil.waitForPageToUnloadElement(browser, selector); } return(true); @@ -272,7 +375,7 @@ public class FunctionalCourseUtil { * Opens the wiki specified by id. */ public boolean openWiki(Selenium browser, long id){ - browser.open(functionalUtil.getDeploymentUrl() + "url/RepositoryEntry/" + id); + browser.open(functionalUtil.getDeploymentPath() + "/url/RepositoryEntry/" + id); functionalUtil.waitForPageToLoad(browser); return(true); @@ -356,7 +459,36 @@ public class FunctionalCourseUtil { * Opens the blog specified by id. */ public boolean openBlog(Selenium browser, long id){ - browser.open(functionalUtil.getDeploymentUrl() + "url/RepositoryEntry/" + id); + browser.open(functionalUtil.getDeploymentPath() + "/url/RepositoryEntry/" + id); + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + + /** + * @param browser + * @param courseId + * @param nth + * @return + * + * Opens the course with courseId and nth blog within the specified + * course. + */ + public boolean openBlogWithoutBusinessPath(Selenium browser, long courseId, int nth){ + if(!functionalRepositorySiteUtil.openCourse(browser, courseId)) + return(false); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//ul//li//a[contains(@class, '") + .append(getBlogIconCss()) + .append("')])[") + .append(nth + 1) + .append("]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); return(true); @@ -372,8 +504,9 @@ public class FunctionalCourseUtil { * * Create a new blog entry. */ - public boolean createBlogEntry(Selenium browser, long blogId, String title, String description, String content){ - if(!openBlog(browser, blogId)) + public boolean createBlogEntry(Selenium browser, long courseId, int nth, + String title, String description, String content){ + if(!openBlogWithoutBusinessPath(browser, courseId, nth)) return(false); StringBuffer selectorBuffer = new StringBuffer(); @@ -387,40 +520,31 @@ public class FunctionalCourseUtil { /* fill in form - title */ selectorBuffer = new StringBuffer(); - selectorBuffer.append("xpath=//form//div[contains(@class, '") - .append(functionalUtil.getWizardCss()) - .append("')]//input[@type='text' and position = 1]"); + selectorBuffer.append("xpath=(//form//div[contains(@class, '") + .append(getBlogFormCss()) + .append("')]//input[@type='text'])[1]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); browser.type(selectorBuffer.toString(), title); /* fill in form - description */ - selectorBuffer = new StringBuffer(); - - selectorBuffer.append("xpath=//form//div[contains(@class, '") - .append(functionalUtil.getWizardCss()) - .append("')]//textarea[0]"); - - browser.type(selectorBuffer.toString(), description); + functionalUtil.typeMCE(browser, getBlogFormCss(), description); /* fill in form - content */ - selectorBuffer = new StringBuffer(); - - selectorBuffer.append("xpath=//form//div[contains(@class, '") - .append(functionalUtil.getWizardCss()) - .append("')]//textarea[1]"); - - browser.type(selectorBuffer.toString(), content); + functionalUtil.typeMCE(browser, getBlogFormCss(), content); /* save form */ selectorBuffer = new StringBuffer(); selectorBuffer.append("xpath=//form//div[contains(@class, '") - .append(functionalUtil.getWizardCss()) + .append(getBlogFormCss()) .append("')]//button[last()]"); browser.click(selectorBuffer.toString()); + functionalUtil.waitForPageToLoad(browser); - return(false); + return(true); } public FunctionalUtil getFunctionalUtil() { @@ -464,6 +588,14 @@ public class FunctionalCourseUtil { this.forumIconCss = forumIconCss; } + public String getBlogIconCss() { + return blogIconCss; + } + + public void setBlogIconCss(String blogIconCss) { + this.blogIconCss = blogIconCss; + } + public String getForumToolbarCss() { return forumToolbarCss; } @@ -527,5 +659,13 @@ public class FunctionalCourseUtil { public void setBlogCreateEntryCss(String blogCreateEntryCss) { this.blogCreateEntryCss = blogCreateEntryCss; } + + public String getBlogFormCss() { + return blogFormCss; + } + + public void setBlogFormCss(String blogFormCss) { + this.blogFormCss = blogFormCss; + } } diff --git a/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java b/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java index 886204a462737ae55e99e855d3966f271fc8fcaf..5d72b25dbf4ea7e2247f83bc025d13b7d7991866 100644 --- a/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java +++ b/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java @@ -126,6 +126,14 @@ public class FunctionalRepositorySiteUtil { GLOSSARY; } + public enum AccessSettings { + ONLY_OWNERS, + OWNERS_AND_AUTHORS, + USERS, + USERS_AND_GUESTS, + MEMBERS_ONLY; + } + public final static String TOOLBOX_CONTENT_CSS = "b_toolbox_content"; public final static String TOOLBOX_COURSE_CSS = "o_toolbox_course"; public final static String TOOLBOX_CONTENT_PACKAGE_CSS = "o_toolbox_content"; @@ -373,7 +381,7 @@ public class FunctionalRepositorySiteUtil { * Opens a course by using business path. */ public boolean openCourse(Selenium browser, long key){ - browser.open(functionalUtil.getDeploymentUrl() + "url/RepositoryEntry/" + key); + browser.open(functionalUtil.getDeploymentPath() + "/url/RepositoryEntry/" + key); functionalUtil.waitForPageToLoad(browser); return(true); @@ -425,6 +433,30 @@ public class FunctionalRepositorySiteUtil { return(true); } + /** + * @param browser + * @param key + * @return + * + * Opens the appropriate detailed view. + */ + public boolean openDetailedView(Selenium browser, Long key){ + //TODO:JK: implement me + + return(false); + } + + /** + * @param browser + * @param settings + * @return + */ + public boolean modifySettings(Selenium browser, AccessSettings settings){ + //TODO:JK: implement me + + return(false); + } + public String findCssClassOfCourseAlias(String descriptor){ //TODO:JK: implement me diff --git a/src/test/java/org/olat/util/FunctionalUtil.java b/src/test/java/org/olat/util/FunctionalUtil.java index 8e84818f57baa3163890017f113953e8e82b37d0..749a4dcefaa27af572b2327f5b3cafd426593b93 100644 --- a/src/test/java/org/olat/util/FunctionalUtil.java +++ b/src/test/java/org/olat/util/FunctionalUtil.java @@ -43,7 +43,8 @@ import com.thoughtworks.selenium.Selenium; public class FunctionalUtil { private final static OLog log = Tracing.createLoggerFor(FunctionalUtil.class); - public final static String DEPLOYMENT_URL = "http://localhost:8080/olat"; + public final static String DEPLOYMENT_URL = "http://localhost:8080/openolat"; + public final static String DEPLOYMENT_PATH = "/openolat"; public final static String WAIT_LIMIT = "5000"; public final static String LOGIN_PAGE = "dmz"; @@ -109,6 +110,7 @@ public class FunctionalUtil { private String password; private String deploymentUrl; + private String deploymentPath; private String waitLimit; private String loginPage; @@ -165,6 +167,7 @@ public class FunctionalUtil { } deploymentUrl = DEPLOYMENT_URL; + deploymentPath = DEPLOYMENT_PATH; waitLimit = WAIT_LIMIT; loginPage = LOGIN_PAGE; @@ -284,6 +287,57 @@ public class FunctionalUtil { return(false); } + + /** + * @param browser + * @param locator + * @return true on success otherwise false + * + * Waits at most (waitLimit + WaitLimitAttribute.VERY_SAVE) amount of time for element to load + * specified by locator. + */ + public boolean waitForPageToUnloadElement(Selenium browser, String locator){ + return(waitForPageToUnloadElement(browser, locator, WaitLimitAttribute.VERY_SAVE)); + } + + /** + * @param browser + * @param locator + * @param wait + * @return true on success otherwise false + * + * Waits at most (waitLimit + wait) amount of time for element to load + * specified by locator. + */ + public boolean waitForPageToUnloadElement(Selenium browser, String locator, WaitLimitAttribute wait){ + long startTime = Calendar.getInstance().getTimeInMillis(); + long currentTime = startTime; + long waitLimit = Long.parseLong(getWaitLimit()) + Long.parseLong(wait.getExtend()); + + log.info("waiting for page to unload element"); + + do{ + if(!browser.isElementPresent(locator)){ + log.info("found element after " + (currentTime - startTime) + "ms"); + + return(true); + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + + currentTime = Calendar.getInstance().getTimeInMillis(); + }while(waitLimit > currentTime - startTime); + + log.warn("giving up after " + waitLimit + "ms"); + + return(false); + } + /** * @param site * @return the matching CSS class @@ -735,6 +789,25 @@ public class FunctionalUtil { return(true); } + public boolean typeMCE(Selenium browser, String cssClass, String content){ + if(content == null) + return(true); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("dom=document.getElementsByClassName('") + .append(cssClass) + .append("')[0].getElementsByClassName('") + .append("mceIframeContainer") + .append("')[0].getElementsByTagName('iframe')[0].contentDocument.body"); + + waitForPageToLoadElement(browser, selectorBuffer.toString()); + + browser.type(selectorBuffer.toString(), content); + + return(true); + } + /** * @param browser * @param entryCss @@ -814,6 +887,9 @@ public class FunctionalUtil { .append(getWizardFinishCss()) .append("')]"); + waitForPageToLoadElement(browser, locatorBuffer.toString()); + + browser.focus(locatorBuffer.toString()); browser.click(locatorBuffer.toString()); return(true); @@ -843,6 +919,14 @@ public class FunctionalUtil { this.deploymentUrl = deploymentUrl; } + public String getDeploymentPath() { + return deploymentPath; + } + + public void setDeploymentPath(String deploymentPath) { + this.deploymentPath = deploymentPath; + } + public String getWaitLimit() { return waitLimit; } diff --git a/src/test/java/org/olat/util/FunctionalVOUtil.java b/src/test/java/org/olat/util/FunctionalVOUtil.java index 82140b106e354272cbc8bf6bb1ba9257bcedee92..9d36fe070cb403bca0143d767a60a3b3cfa4548c 100644 --- a/src/test/java/org/olat/util/FunctionalVOUtil.java +++ b/src/test/java/org/olat/util/FunctionalVOUtil.java @@ -216,6 +216,18 @@ public class FunctionalVOUtil { return(importCourse(deploymentUrl, "/org/olat/portfolio/Course_including_Forum.zip", "Course_including_Forum.zip", "Course including Forum", "Course including Forum")); } + /** + * @param deploymentUrl + * @return + * @throws URISyntaxException + * @throws IOException + * + * Imports the "Course including Blog" via REST. + */ + public CourseVO importCourseIncludingBlog(URL deploymentUrl) throws URISyntaxException, IOException{ + return(importCourse(deploymentUrl, "/org/olat/portfolio/Course_including_Blog.zip", "Course_including_Blog.zip", "Course including Blog", "Course including Blog")); + } + /** * @param deploymentUrl * @return diff --git a/src/test/resources/org/olat/portfolio/Course_including_Blog.zip b/src/test/resources/org/olat/portfolio/Course_including_Blog.zip new file mode 100644 index 0000000000000000000000000000000000000000..62ec56d7e6f1321396de9cc7e58a1a2969ca585e Binary files /dev/null and b/src/test/resources/org/olat/portfolio/Course_including_Blog.zip differ diff --git a/src/test/resources/org/olat/portfolio/blog.zip b/src/test/resources/org/olat/portfolio/blog.zip index b7d10f9788d15a05f30964506dff03f298495d35..faac98707d2b2959672b11c56b4cd6f8f7c9134c 100644 Binary files a/src/test/resources/org/olat/portfolio/blog.zip and b/src/test/resources/org/olat/portfolio/blog.zip differ