From c6ac5780a7dbf4eaa82b1cfafcadcb70529a1bbf 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 14:38:59 +0200 Subject: [PATCH] OO-348: implemented test case. --- .../repository/FunctionalCatalogTest.java | 89 +++++++- .../org/olat/util/FunctionalCourseUtil.java | 205 +++++++++++++++++- .../util/FunctionalRepositorySiteUtil.java | 27 ++- .../java/org/olat/util/FunctionalUtil.java | 55 +++++ 4 files changed, 356 insertions(+), 20 deletions(-) diff --git a/src/test/java/org/olat/repository/FunctionalCatalogTest.java b/src/test/java/org/olat/repository/FunctionalCatalogTest.java index 2b6d555aa9e..b55f4efa353 100644 --- a/src/test/java/org/olat/repository/FunctionalCatalogTest.java +++ b/src/test/java/org/olat/repository/FunctionalCatalogTest.java @@ -28,6 +28,7 @@ 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.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -38,6 +39,7 @@ import org.olat.util.FunctionalCourseUtil; import org.olat.util.FunctionalRepositorySiteUtil; import org.olat.util.FunctionalUtil; import org.olat.util.FunctionalVOUtil; +import org.olat.util.FunctionalRepositorySiteUtil.RepositorySiteAction; import com.thoughtworks.selenium.DefaultSelenium; @@ -46,18 +48,24 @@ import com.thoughtworks.selenium.DefaultSelenium; * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com */ public class FunctionalCatalogTest { + public final static int COURSES = 2; 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" - }; + }; + public final static String[] SUBCATECORY_PATHS_INCLUDING_RESOURCE = { + SUBCATEGORY_PATHS[1], + SUBCATEGORY_PATHS[2] + }; + @Deployment(testable = false) public static WebArchive createDeployment() { return ArquillianDeployments.createDeployment(); @@ -100,28 +108,87 @@ public class FunctionalCatalogTest { * prerequisites for test created via REST */ /* import wiki */ - RepositoryEntryVO[] wikiVO = new RepositoryEntryVO[2]; + RepositoryEntryVO[] wikiVO = new RepositoryEntryVO[COURSES]; - wikiVO[0] = functionalVOUtil.importWiki(deploymentUrl); - wikiVO[1] = functionalVOUtil.importWiki(deploymentUrl); + for(int i = 0; i < COURSES; i++){ + wikiVO[i] = functionalVOUtil.importWiki(deploymentUrl); + } /* import course */ - CourseVO[] courseVO = new CourseVO[2]; - - courseVO[0] = functionalVOUtil.importEmptyCourse(deploymentUrl); - courseVO[1] = functionalVOUtil.importEmptyCourse(deploymentUrl); + CourseVO[] courseVO = new CourseVO[COURSES]; + for(int i = 0; i < COURSES; i++){ + courseVO[i] = functionalVOUtil.importEmptyCourse(deploymentUrl); + } + /* * create or configure content */ + /* create categories */ + for(int i = 0; i < SUBCATEGORY_PATHS.length; i++){ + String currentPath = SUBCATEGORY_PATHS[i]; + String currentName = currentPath.substring(currentPath.lastIndexOf('/') + 1); + String currentDescription = SUBCATEGORY_DESCRIPTIONS[i]; + + Assert.assertTrue(functionalRepositorySiteUtil.createCatalogSubcategory(browser, currentPath, currentName, currentDescription)); + } - //TODO:JK: implement me + /* edit course and publish thereby adding it to catalog */ + for(int i = 0; i < COURSES; i++){ + /* open course in edit mode */ + Assert.assertTrue(functionalRepositorySiteUtil.openCourse(browser, courseVO[i].getRepoEntryKey())); + + Assert.assertTrue(functionalCourseUtil.openCourseEditor(browser)); + + /* choose wiki */ + String currentPath = SUBCATEGORY_PATHS[i]; + String currentName = currentPath.substring(currentPath.lastIndexOf('/') + 1); + + Assert.assertTrue(functionalCourseUtil.createWiki(browser, currentName + " wiki", "colaborative " + currentName + " wiki")); + Assert.assertTrue(functionalCourseUtil.chooseWiki(browser, wikiVO[i].getKey())); + + /* publish course */ + Assert.assertTrue(functionalCourseUtil.publishEntireCourse(browser, null, SUBCATEGORY_PATHS[i])); + + /* close course */ + Assert.assertTrue(functionalCourseUtil.closeActiveTab(browser)); + } /* * verify content */ + /* open catalog */ + Assert.assertTrue(functionalUtil.openSite(browser, FunctionalUtil.OlatSite.LEARNING_RESOURCES)); + + Assert.assertTrue(functionalRepositorySiteUtil.openActionByMenuTree(browser, RepositorySiteAction.CATALOG)); - //TODO:JK: implement me + /* verify resources */ + for(int i = 0; i < COURSES; i++){ + String[] selectors = functionalRepositorySiteUtil.createCatalogSelectors(SUBCATECORY_PATHS_INCLUDING_RESOURCE[i]); + + for(String currentSelector: selectors){ + /* click first course and retrieve business path */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(functionalRepositorySiteUtil.getCourseModuleIconCss()) + .append("')]"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + String businessPath0 = functionalUtil.currentBusinessPath(browser); + + /* open course and retrieve business path */ + functionalRepositorySiteUtil.openCourse(browser, courseVO[i].getRepoEntryKey()); + + String businessPath1 = functionalUtil.currentBusinessPath(browser); + + /* assert collected business paths to be equal */ + Assert.assertEquals(businessPath1, businessPath0); + } + } } } diff --git a/src/test/java/org/olat/util/FunctionalCourseUtil.java b/src/test/java/org/olat/util/FunctionalCourseUtil.java index 87752e9d50d..5e2f633da0a 100644 --- a/src/test/java/org/olat/util/FunctionalCourseUtil.java +++ b/src/test/java/org/olat/util/FunctionalCourseUtil.java @@ -21,6 +21,9 @@ package org.olat.util; import java.net.MalformedURLException; import java.net.URI; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; @@ -35,6 +38,8 @@ import com.thoughtworks.selenium.Selenium; public class FunctionalCourseUtil { private final static OLog log = Tracing.createLoggerFor(FunctionalCourseUtil.class); + private final static Pattern categoryPattern = Pattern.compile("/([^/]+)"); + public final static String COURSE_RUN_CSS = "o_course_run"; public final static String COURSE_OPEN_EDITOR_CSS = "o_sel_course_open_editor"; @@ -81,9 +86,15 @@ public class FunctionalCourseUtil { 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_CSS = "o_sel_search_referenceable_entries"; + 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_ALL_RESOURCES_CSS = "o_sel_repo_popup_all_resources"; + public final static String REPOSITORY_POPUP_MY_RESOURCES_CSS = "o_sel_repo_popup_my_resources"; + public final static String REPOSITORY_POPUP_SEARCH_RESOURCES_CSS = "o_sel_repo_popup_search_resources"; + public final static String MAP_EDIT_CSS = "o_sel_edit_map"; public final static String BLOG_NO_POSTS_CSS = "o_blog_no_posts"; @@ -312,7 +323,14 @@ public class FunctionalCourseUtil { private String feedChooseRepositoryFileCss; private String mapChooseRepositoryFileCss; + private String repositoryPopupCss; + private String repositoryPopupCreateResourceCss; + private String repositoryPopupImportResourceCss; + + private String repositoryPopupAllResourcesCss; + private String repositoryPopupMyResourcesCss; + private String repositoryPopupSearchResourcesCss; private String mapEditCss; @@ -370,7 +388,14 @@ public class FunctionalCourseUtil { setFeedChooseRepositoryFileCss(FEED_CHOOSE_REPOSITORY_FILE_CSS); setMapChooseRepositoryFileCss(MAP_CHOOSE_REPOSITORY_FILE_CSS); + setRepositoryPopupCss(REPOSITORY_POPUP_CSS); + setRepositoryPopupCreateResourceCss(REPOSITORY_POPUP_CREATE_RESOURCE_CSS); + setRepositoryPopupImportResourceCss(REPOSITORY_POPUP_IMPORT_RESOURCE_CSS); + + setRepositoryPopupAllResourcesCss(REPOSITORY_POPUP_ALL_RESOURCES_CSS); + setRepositoryPopupMyResourcesCss(REPOSITORY_POPUP_MY_RESOURCES_CSS); + setRepositoryPopupSearchResourcesCss(REPOSITORY_POPUP_SEARCH_RESOURCES_CSS); setMapEditCss(MAP_EDIT_CSS); @@ -403,7 +428,7 @@ public class FunctionalCourseUtil { public boolean open(Selenium browser, int nth){ StringBuffer selectorBuffer = new StringBuffer(); - selectorBuffer.append("xpath=//ul[contains(@class, 'b_tree_l1')]//li[") + selectorBuffer.append("xpath=(//ul[contains(@class, 'b_tree_l1')]//li)[") .append(nth + 1) .append("]//a"); @@ -412,6 +437,30 @@ public class FunctionalCourseUtil { return(true); } + /** + * @param browser + * @param alias + * @param nth + * @return true on success + * + * Opens the nth course element of course node type specified by alias in the current course. + */ + public boolean open(Selenium browser, CourseNodeAlias alias, int nth){ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//ul[contains(@class, 'b_tree_l1')]//li]//a[contains(@class, '") + .append(alias.getIconCss()) + .append("')])[") + .append(nth + 1) + .append("]"); + + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + return(true); + } + /** * @param browser * @param courseId @@ -632,9 +681,35 @@ public class FunctionalCourseUtil { * Creates xpath selectors to select catalog within the tree. */ public String[] createCatalogSelectors(String path){ - //TODO:JK: implement me + if(path == null || + !path.startsWith("/")){ + return(null); + } - return(null); + Matcher categoryMatcher = categoryPattern.matcher(path); + ArrayList<String> selectors = new ArrayList<String>(); + + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//li//a[contains(@class, '") + .append(functionalUtil.getTreeNodeAnchorCss()) + .append("')]//a"); + + selectors.add(selectorBuffer.toString()); + + while(categoryMatcher.find()){ + StringBuffer selector = new StringBuffer(); + + selector.append("xpath=//li//a[contains(@class, '") + .append(functionalUtil.getTreeNodeAnchorCss()) + .append("')]//a//span[text()='") + .append(categoryMatcher.group(1)) + .append("')]/.."); + + selectors.add(selector.toString()); + } + + return((String[]) selectors.toArray()); } /** @@ -1236,6 +1311,69 @@ public class FunctionalCourseUtil { return(functionalUtil.openContentTab(browser, tab.ordinal())); } + private boolean chooseRepositoryResource(Selenium browser, String chooseRepositoryCss, long key){ + /* click on "choose, create or import file" button */ + StringBuffer selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(chooseRepositoryCss) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + functionalUtil.waitForPageToLoad(browser); + + /* click search link */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//a[contains(@class, '") + .append(getRepositoryPopupSearchResourcesCss()) + .append("')]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + /* type key and search */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(FunctionalRepositorySiteUtil.SearchField.ID.getEntryCss()) + .append("')]//input[@type='text']"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.type(selectorBuffer.toString(), Long.toString(key)); + + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=(//div[contains(@class, '") + .append(getRepositoryPopupCss()) + .append("')]//a[contains(@class, '") + .append(functionalUtil.getButtonCss()) + .append("')])[last()]"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + /* choose resource */ + selectorBuffer = new StringBuffer(); + + selectorBuffer.append("xpath=//div[contains(@class, '") + .append(FunctionalRepositorySiteUtil.SearchField.ID.getEntryCss()) + .append("')]//tr[contains(@class, '") + .append(functionalUtil.getTableFirstChildCss()) + .append("') and contains(@class, '") + .append(functionalUtil.getTableLastChildCss()) + .append("')]//td[contains(@class, '") + .append(functionalUtil.getTableLastChildCss()) + .append("')]//a"); + + functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString()); + browser.click(selectorBuffer.toString()); + + return(true); + } + /** * @param browser * @param chooseRepositoryCss @@ -1331,6 +1469,23 @@ public class FunctionalCourseUtil { return(true); } + /** + * @param browser + * @param wikiId + * @return + * + * Choose an existing wiki. + */ + public boolean chooseWiki(Selenium browser, long wikiId){ + if(!openCourseEditorWikiTab(browser, CourseEditorWikiTab.LEARNING_CONTENT)) + return(false); + + if(!chooseRepositoryResource(browser, getWikiChooseRepositoryFileCss(), wikiId)){ + return(false); + } + + return(true); + } /** * @param browser * @param title @@ -1696,6 +1851,14 @@ public class FunctionalCourseUtil { this.mapChooseRepositoryFileCss = mapChooseRepositoryFileCss; } + public String getRepositoryPopupCss() { + return repositoryPopupCss; + } + + public void setRepositoryPopupCss(String repositoryPopupCss) { + this.repositoryPopupCss = repositoryPopupCss; + } + public String getRepositoryPopupCreateResourceCss() { return repositoryPopupCreateResourceCss; } @@ -1704,6 +1867,42 @@ public class FunctionalCourseUtil { this.repositoryPopupCreateResourceCss = repositoryPopupCreateResourceCss; } + public String getRepositoryPopupImportResourceCss() { + return repositoryPopupImportResourceCss; + } + + public void setRepositoryPopupImportResourceCss( + String repositoryPopupImportResourceCss) { + this.repositoryPopupImportResourceCss = repositoryPopupImportResourceCss; + } + + public String getRepositoryPopupAllResourcesCss() { + return repositoryPopupAllResourcesCss; + } + + public void setRepositoryPopupAllResourcesCss( + String repositoryPopupAllResourcesCss) { + this.repositoryPopupAllResourcesCss = repositoryPopupAllResourcesCss; + } + + public String getRepositoryPopupMyResourcesCss() { + return repositoryPopupMyResourcesCss; + } + + public void setRepositoryPopupMyResourcesCss( + String repositoryPopupMyResourcesCss) { + this.repositoryPopupMyResourcesCss = repositoryPopupMyResourcesCss; + } + + public String getRepositoryPopupSearchResourcesCss() { + return repositoryPopupSearchResourcesCss; + } + + public void setRepositoryPopupSearchResourcesCss( + String repositoryPopupSearchResourcesCss) { + this.repositoryPopupSearchResourcesCss = repositoryPopupSearchResourcesCss; + } + public String getMapEditCss() { return mapEditCss; } diff --git a/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java b/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java index f6848077ab1..5a427dd9406 100644 --- a/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java +++ b/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java @@ -20,6 +20,7 @@ package org.olat.util; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -73,6 +74,8 @@ public class FunctionalRepositorySiteUtil { public final static String CATALOG_SUBCATEGORY_ICON_CSS = "o_catalog_sub_icon"; public final static String CATALOG_SUBCATEGORY_LIST_CSS = "o_catalog_itemlist"; + public final static String COURSE_MODULE_ICON_CSS = "o_CourseModule_icon"; + public enum Column { AC, TYPE, @@ -277,6 +280,8 @@ public class FunctionalRepositorySiteUtil { private String catalogSubcategoryListCss; private String catalogSubcategoryIconCss; + private String courseModuleIconCss; + private String importCourseCss; private String importCPLearningContentCss; private String importScormCss; @@ -348,6 +353,8 @@ public class FunctionalRepositorySiteUtil { setCatalogSubcategoryListCss(CATALOG_SUBCATEGORY_LIST_CSS); setCatalogSubcategoryIconCss(CATALOG_SUBCATEGORY_ICON_CSS); + setCourseModuleIconCss(COURSE_MODULE_ICON_CSS); + setImportCourseCss(IMPORT_COURSE_CSS); setImportCPLearningContentCss(IMPORT_CP_LEARNING_CONTENT_CSS); setImportScormCss(IMPORT_SCORM_CSS); @@ -398,23 +405,23 @@ public class FunctionalRepositorySiteUtil { } Matcher categoryMatcher = categoryPattern.matcher(path); - String[] selectors = new String[categoryMatcher.groupCount()]; + ArrayList<String> selectors = new ArrayList<String>(); - for(int i = 0; categoryMatcher.find(); i++){ + while(categoryMatcher.find()){ StringBuffer selector = new StringBuffer(); selector.append("xpath=//div[contains(@class, '") .append(getCatalogSubcategoryListCss()) .append("')]//a//span[contains(@class, '") .append(getCatalogSubcategoryIconCss()) - .append("' and text()='") + .append("') and text()='") .append(categoryMatcher.group(1)) - .append("')]/.."); + .append("']/.."); - selectors[i] = selector.toString(); + selectors.add(selector.toString()); } - return(selectors); + return((String[]) selectors.toArray()); } /** @@ -1295,6 +1302,14 @@ public class FunctionalRepositorySiteUtil { this.catalogSubcategoryIconCss = catalogSubcategoryIconCss; } + public String getCourseModuleIconCss() { + return courseModuleIconCss; + } + + public void setCourseModuleIconCss(String courseModuleIconCss) { + this.courseModuleIconCss = courseModuleIconCss; + } + public String getImportCourseCss() { return importCourseCss; } diff --git a/src/test/java/org/olat/util/FunctionalUtil.java b/src/test/java/org/olat/util/FunctionalUtil.java index e9a07e7857a..3b4bb5d050e 100644 --- a/src/test/java/org/olat/util/FunctionalUtil.java +++ b/src/test/java/org/olat/util/FunctionalUtil.java @@ -104,7 +104,12 @@ public class FunctionalUtil { public final static String MCE_CONTENT_BODY_CSS = "mceContentBody"; + public final static String BUTTON_CSS = "b_button"; public final static String BUTTON_DIRTY_CSS = "b_button_dirty"; + 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 TREE_NODE_ANCHOR_CSS = "x-tree-node-anchor"; + public final static String TREE_NODE_CSS = "x-tree-node"; public final static String NOTIFICATION_BOX_CSS = "o_sel_info_message"; @@ -145,7 +150,12 @@ public class FunctionalUtil { private String mceContentBodyCss; + private String buttonCss; private String buttonDirtyCss; + private String tableFirstChildCss; + private String tableLastChildCss; + private String treeNodeAnchorCss; + private String treeNodeCss; private FunctionalHomeSiteUtil functionalHomeSiteUtil; private FunctionalGroupsSiteUtil functionalGroupsSiteUtil; @@ -205,7 +215,12 @@ public class FunctionalUtil { mceContentBodyCss = MCE_CONTENT_BODY_CSS; + buttonCss = BUTTON_CSS; buttonDirtyCss = BUTTON_DIRTY_CSS; + tableFirstChildCss = TABLE_FIRST_CHILD_CSS; + tableLastChildCss = TABLE_LAST_CHILD_CSS; + treeNodeAnchorCss = TREE_NODE_ANCHOR_CSS; + treeNodeCss = TREE_NODE_CSS; functionalHomeSiteUtil = new FunctionalHomeSiteUtil(this); functionalGroupsSiteUtil = new FunctionalGroupsSiteUtil(this); @@ -1178,6 +1193,14 @@ public class FunctionalUtil { this.functionalAdministrationSiteUtil = functionalAdministrationSiteUtil; } + public String getButtonCss() { + return buttonCss; + } + + public void setButtonCss(String buttonCss) { + this.buttonCss = buttonCss; + } + public String getButtonDirtyCss() { return buttonDirtyCss; } @@ -1185,4 +1208,36 @@ public class FunctionalUtil { public void setButtonDirtyCss(String buttonDirtyCss) { this.buttonDirtyCss = buttonDirtyCss; } + + public String getTableFirstChildCss() { + return tableFirstChildCss; + } + + public void setTableFirstChildCss(String tableFirstChildCss) { + this.tableFirstChildCss = tableFirstChildCss; + } + + public String getTableLastChildCss() { + return tableLastChildCss; + } + + public void setTableLastChildCss(String tableLastChildCss) { + this.tableLastChildCss = tableLastChildCss; + } + + public String getTreeNodeAnchorCss() { + return treeNodeAnchorCss; + } + + public void setTreeNodeAnchorCss(String treeNodeAnchorCss) { + this.treeNodeAnchorCss = treeNodeAnchorCss; + } + + public String getTreeNodeCss() { + return treeNodeCss; + } + + public void setTreeNodeCss(String treeNodeCss) { + this.treeNodeCss = treeNodeCss; + } } -- GitLab