/** * <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.selenium.page.course; import java.util.ArrayList; import java.util.List; import org.jboss.arquillian.graphene.Graphene; import org.junit.Assert; import org.olat.selenium.page.graphene.OOGraphene; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; /** * * Initial date: 20.06.2014<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class CourseEditorPageFragment { public static final By editorBy = By.className("o_course_editor"); public static final By createNodeButton = By.className("o_sel_course_editor_create_node"); public static final By createNodeModalBy = By.id("o_course_editor_choose_nodetype"); public static final By publishButtonBy = By.className("o_sel_course_editor_publish"); public static final By toolbarBackBy = By.cssSelector("li.o_breadcrumb_back>a"); public static final By navBarNodeConfiguration = By.cssSelector("ul.o_node_config>li>a"); public static final By chooseCpButton = By.className("o_sel_cp_choose_repofile"); public static final By chooseWikiButton = By.className("o_sel_wiki_choose_repofile"); public static final By chooseTestButton = By.className("o_sel_test_choose_repofile"); public static final By chooseFeedButton = By.className("o_sel_feed_choose_repofile"); public static final By chooseScormButton = By.className("o_sel_scorm_choose_repofile"); public static final By choosePortfolioButton = By.className("o_sel_map_choose_repofile"); public static final By changeNodeToolsMenu = By.cssSelector("ul.o_sel_course_editor_change_node"); public static final By changeNodeToolsMenuCaret = By.cssSelector("a.o_sel_course_editor_change_node"); public static final By tabNavTabsBy = By.cssSelector("ul.nav.nav-tabs"); public static final List<By> chooseRepoEntriesButtonList = new ArrayList<>(); static { chooseRepoEntriesButtonList.add(chooseCpButton); chooseRepoEntriesButtonList.add(chooseWikiButton); chooseRepoEntriesButtonList.add(chooseTestButton); chooseRepoEntriesButtonList.add(chooseFeedButton); chooseRepoEntriesButtonList.add(chooseScormButton); chooseRepoEntriesButtonList.add(choosePortfolioButton); } private WebDriver browser; public CourseEditorPageFragment(WebDriver browser) { this.browser = browser; } public static CourseEditorPageFragment getEditor(WebDriver browser) { OOGraphene.waitElement(editorBy, 5, browser); OOGraphene.closeBlueMessageWindow(browser); return new CourseEditorPageFragment(browser); } public CourseEditorPageFragment assertOnEditor() { OOGraphene.waitElement(editorBy, 5, browser); List<WebElement> editorEls = browser.findElements(editorBy); Assert.assertFalse(editorEls.isEmpty()); Assert.assertTrue(editorEls.get(0).isDisplayed()); return this; } public CourseEditorPageFragment assertOnWarning() { By warningBy = By.cssSelector("div.modal-dialog div.alert.alert-warning"); OOGraphene.waitElement(warningBy, 2, browser); List<WebElement> warningEls = browser.findElements(warningBy); Assert.assertFalse(warningEls.isEmpty()); OOGraphene.closeModalDialogWindow(browser); return this; } /** * Select the root course element. */ public CourseEditorPageFragment selectRoot() { By rootNodeBy = By.cssSelector("span.o_tree_link.o_tree_l0>a"); browser.findElement(rootNodeBy).click(); OOGraphene.waitBusy(browser); By rootNodeActiveBy = By.cssSelector("span.o_tree_link.o_tree_l0.active"); OOGraphene.waitElement(rootNodeActiveBy, 5, browser); return this; } public EasyConditionConfigPage selectTabVisibility() { By passwordTabBy = By.cssSelector("fieldset.o_sel_course_visibility_condition_form"); selectTab(passwordTabBy); return new EasyConditionConfigPage(browser); } /** * Select the tab where the password setting are * @return */ public CourseEditorPageFragment selectTabPassword() { By passwordTabBy = By.cssSelector("fieldset.o_sel_course_node_password_config"); return selectTab(passwordTabBy); } public CourseEditorPageFragment setPassword(String password) { By switchBy = By.cssSelector(".o_sel_course_password_condition_switch input[type='checkbox']"); browser.findElement(switchBy).click(); OOGraphene.waitBusy(browser); By passwordBy = By.cssSelector(".o_sel_course_password_condition_value input[type='text']"); browser.findElement(passwordBy).sendKeys(password); By saveBy = By.cssSelector("fieldset.o_sel_course_node_password_config button.btn-primary"); browser.findElement(saveBy).click(); OOGraphene.waitBusy(browser); return this; } /** * Select the tab score in a structure node. * */ public CourseEditorPageFragment selectTabScore() { By scoreTabBy = By.cssSelector("fieldset.o_sel_structure_score"); return selectTab(scoreTabBy); } private CourseEditorPageFragment selectTab(By tabBy) { //make sure the tab bar is loaded By navBarBy = By.cssSelector("ul.o_node_config"); OOGraphene.waitElement(navBarBy, 5, browser); List<WebElement> tabLinks = browser.findElements(navBarNodeConfiguration); boolean found = false; a_a: for(WebElement tabLink:tabLinks) { tabLink.click(); OOGraphene.waitBusy(browser); OOGraphene.waitElement(tabNavTabsBy, 5, browser); List<WebElement> chooseRepoEntry = browser.findElements(tabBy); if(chooseRepoEntry.size() > 0) { found = true; break a_a; } } Assert.assertTrue("Found the tab", found); return this; } /** * Enable passed and points by nodes * @return */ public CourseEditorPageFragment enableRootScoreByNodes() { By enablePointBy = By.cssSelector("fieldset.o_sel_structure_score .o_sel_has_score input[type='checkbox']"); browser.findElement(enablePointBy).click(); OOGraphene.waitBusy(browser); //scform.scoreNodeIndents By enablePointNodesBy = By.cssSelector("fieldset.o_sel_structure_score input[type='checkbox'][name='scform.scoreNodeIndents']"); List<WebElement> pointNodeEls = browser.findElements(enablePointNodesBy); for(WebElement pointNodeEl:pointNodeEls) { pointNodeEl.click(); OOGraphene.waitBusy(browser); } By enablePassedBy = By.cssSelector("fieldset.o_sel_structure_score .o_sel_has_passed input[type='checkbox']"); browser.findElement(enablePassedBy).click(); OOGraphene.waitBusy(browser); By passedInheritBy = By.cssSelector("fieldset.o_sel_structure_score input[type='radio'][name='passedType'][value='inherit']"); browser.findElement(passedInheritBy).click(); OOGraphene.waitBusy(browser); By enablePassedNodesBy = By.cssSelector("fieldset.o_sel_structure_score input[type='checkbox'][name='scform.passedNodeIndents']"); List<WebElement> enablePassedNodeEls = browser.findElements(enablePassedNodesBy); for(WebElement enablePassedNodeEl:enablePassedNodeEls) { enablePassedNodeEl.click(); OOGraphene.waitBusy(browser); } //save By submitBy = By.cssSelector("fieldset.o_sel_structure_score button.btn.btn-primary"); browser.findElement(submitBy).click(); OOGraphene.waitBusy(browser); return this; } /** * Create a new course element * @param nodeAlias The type of the course element * @return */ public CourseEditorPageFragment createNode(String nodeAlias) { OOGraphene.waitElement(createNodeButton, 5, browser); browser.findElement(createNodeButton).click(); OOGraphene.waitElement(createNodeModalBy, browser); //modal WebElement createNodeModal = browser.findElement(createNodeModalBy); //create the node By node = By.className("o_sel_course_editor_node-" + nodeAlias); WebElement createNodeLink = createNodeModal.findElement(node); Assert.assertTrue(createNodeLink.isDisplayed()); createNodeLink.click(); OOGraphene.waitBusy(browser); return this; } /** * Set the course element title and short title * * @param title * @return */ public CourseEditorPageFragment nodeTitle(String title) { By shortTitle = By.cssSelector("div.o_sel_node_editor_shorttitle input"); WebElement shortTitleEl = browser.findElement(shortTitle); shortTitleEl.clear(); shortTitleEl.sendKeys(title); By longtitle = By.cssSelector("div.o_sel_node_editor_title input"); WebElement titleEl = browser.findElement(longtitle); titleEl.clear(); titleEl.sendKeys(title); By saveButton = By.cssSelector("button.o_sel_node_editor_submit"); browser.findElement(saveButton).click(); OOGraphene.waitBusy(browser); return this; } public String getRestUrl() { By openerBy = By.cssSelector("a.o_opener"); browser.findElement(openerBy).click(); By urlBy = By.cssSelector("div.o_copy_code"); OOGraphene.waitElement(urlBy, browser); String url = null; List<WebElement> urlEls = browser.findElements(urlBy); for(WebElement urlEl:urlEls) { String text = urlEl.getText(); if(text.contains("http")) { url = text.trim(); break; } } Assert.assertNotNull(url); return url; } public CourseEditorPageFragment moveUnder(String targetNodeTitle) { if(!browser.findElement(changeNodeToolsMenu).isDisplayed()) { openChangeNodeToolsMenu(); } By changeNodeLinkBy = By.cssSelector("a.o_sel_course_editor_move_node"); browser.findElement(changeNodeLinkBy).click(); OOGraphene.waitBusy(browser); By targetNodeBy = By.xpath("//div[contains(@class,'o_tree_insert_tool')]//a[contains(@title,'" + targetNodeTitle + "')]"); browser.findElement(targetNodeBy).click(); OOGraphene.waitBusy(browser); By underBy = By.xpath("//div[contains(@class,'o_tree_insert_tool')]//a[i[contains(@class,'o_icon_node_under')]]"); browser.findElement(underBy).click(); OOGraphene.waitBusy(browser); By saveBy = By.cssSelector("div.modal-content div.o_button_group a.btn-primary"); browser.findElement(saveBy).click(); OOGraphene.waitBusy(browser); OOGraphene.waitAndCloseBlueMessageWindow(browser); return this; } public CourseEditorPageFragment selectNode(String nodeTitle) { By targetNodeBy = By.xpath("//div[contains(@class,'o_editor_menu')]//a[contains(@title,'" + nodeTitle + "')]"); browser.findElement(targetNodeBy).click(); OOGraphene.waitBusy(browser); return this; } /** * Open the tools drop-down * @return */ public CourseEditorPageFragment openChangeNodeToolsMenu() { browser.findElement(changeNodeToolsMenuCaret).click(); OOGraphene.waitElement(changeNodeToolsMenu, browser); return this; } /** * Loop the tabs of the course element configuration to find * the one with a button to select a repository entry. * * @return */ public CourseEditorPageFragment selectTabLearnContent() { List<WebElement> tabLinks = browser.findElements(navBarNodeConfiguration); boolean found = false; a_a: for(WebElement tabLink:tabLinks) { tabLink.click(); OOGraphene.waitBusy(browser); for(By chooseRepoEntriesButton: chooseRepoEntriesButtonList) { List<WebElement> chooseRepoEntry = browser.findElements(chooseRepoEntriesButton); if(chooseRepoEntry.size() > 0) { found = true; break a_a; } } } Assert.assertTrue("Found the tab learn content", found); return this; } /** * @see chooseResource * @param resourceTitle * @return */ public CourseEditorPageFragment chooseCP(String resourceTitle) { return chooseResource(chooseCpButton, resourceTitle); } /** * @see chooseResource * @param resourceTitle * @return */ public CourseEditorPageFragment chooseWiki(String resourceTitle) { return chooseResource(chooseWikiButton, resourceTitle); } /** * @see chooseResource * @param resourceTitle * @return */ public CourseEditorPageFragment chooseTest(String resourceTitle) { return chooseResource(chooseTestButton, resourceTitle); } /** * @see chooseResource * @param resourceTitle * @return */ public CourseEditorPageFragment chooseScorm(String resourceTitle) { return chooseResource(chooseScormButton, resourceTitle); } /** * Choose a portfolio, v1.0 or v2.0 * * @param resourceTitle The name of the binder / portfolio * @return */ public CourseEditorPageFragment choosePortfolio(String resourceTitle) { return chooseResource(choosePortfolioButton, resourceTitle); } /** * Click the choose button, which open the resource chooser. Select * the "My entries" segment, search the rows for the resource title, * and select it. * * * @param chooseButton The By of the choose button in the course node editor * @param resourceTitle The resource title to find * @return */ public CourseEditorPageFragment chooseResource(By chooseButton, String resourceTitle) { browser.findElement(chooseButton).click(); OOGraphene.waitBusy(browser); //popup By referenceableEntriesBy = By.className("o_sel_search_referenceable_entries"); OOGraphene.waitElement(referenceableEntriesBy, 1, browser); WebElement popup = browser.findElement(referenceableEntriesBy); popup.findElement(By.cssSelector("a.o_sel_repo_popup_my_resources")).click(); OOGraphene.waitBusy(browser); //find the row WebElement selectRow = null; List<WebElement> rows = popup.findElements(By.cssSelector("div.o_segments_content table.o_table tr")); for(WebElement row:rows) { String text = row.getText(); if(text.contains(resourceTitle)) { selectRow = row; break; } } Assert.assertNotNull(selectRow); //find the select in the row WebElement selectLink = selectRow.findElement(By.xpath("//a[contains(@href,'rtbSelectLink')]")); selectLink.click(); OOGraphene.waitBusy(browser); //double check that the resource is selected (search the preview link) By previewLink = By.xpath("//a/span[text()[contains(.,'" + resourceTitle + "')]]"); browser.findElement(previewLink); return this; } /** * Create a wiki from the chooser popup * @param resourceTitle * @return */ public CourseEditorPageFragment createWiki(String resourceTitle) { return createResource(chooseWikiButton, resourceTitle, null); } /** * Create a QTI 1.2 test from the chooser popup * @param resourceTitle * @return */ public CourseEditorPageFragment createQTI12Test(String resourceTitle) { return createResource(chooseTestButton, resourceTitle, "FileResource.TEST"); } /** * Create a podcast or a blog * @param resourceTitle * @return */ public CourseEditorPageFragment createFeed(String resourceTitle) { return createResource(chooseFeedButton, resourceTitle, null); } /** * Create a portfolio template * @param resourceTitle * @return */ public CourseEditorPageFragment createPortfolio(String resourceTitle) { return createResource(choosePortfolioButton, resourceTitle, null); } private CourseEditorPageFragment createResource(By chooseButton, String resourceTitle, String resourceType) { OOGraphene.closeBlueMessageWindow(browser); browser.findElement(chooseButton).click(); OOGraphene.waitBusy(browser); //popup WebElement popup = browser.findElement(By.className("o_sel_search_referenceable_entries")); popup.findElement(By.cssSelector("a.o_sel_repo_popup_my_resources")).click(); OOGraphene.waitBusy(browser); //click create List<WebElement> createEls = popup.findElements(By.className("o_sel_repo_popup_create_resource")); if(createEls.isEmpty()) { //open drop down popup.findElement(By.className("o_sel_repo_popup_create_resources")).click(); //choose the right type By selectType = By.xpath("//ul[contains(@class,'o_sel_repo_popup_create_resources')]//a[contains(@onclick,'" + resourceType + "')]"); popup.findElement(selectType).click(); OOGraphene.waitBusy(browser); } else { popup.findElement(By.className("o_sel_repo_popup_create_resource")).click(); OOGraphene.waitBusy(browser); } //fill the create form return fillCreateForm(resourceTitle); } private CourseEditorPageFragment fillCreateForm(String displayName) { OOGraphene.waitModalDialog(browser); By inputBy = By.cssSelector("div.modal.o_sel_author_create_popup div.o_sel_author_displayname input"); browser.findElement(inputBy).sendKeys(displayName); By submitBy = By.cssSelector("div.modal.o_sel_author_create_popup .o_sel_author_create_submit"); browser.findElement(submitBy).click(); OOGraphene.waitBusy(browser); OOGraphene.waitAndCloseBlueMessageWindow(browser); return this; } /** * Don't forget to set access * * @return */ public CoursePageFragment autoPublish() { //back By breadcrumpBackBy = By.cssSelector("#o_main_toolbar li.o_breadcrumb_back a"); browser.findElement(breadcrumpBackBy).click(); OOGraphene.waitBusy(browser); //auto publish By autoPublishBy = By.cssSelector("div.modal a.o_sel_course_quickpublish_auto"); browser.findElement(autoPublishBy).click(); OOGraphene.waitBusy(browser); OOGraphene.waitAndCloseBlueMessageWindow(browser); return new CoursePageFragment(browser); } /** * Open the publish process * @return */ public PublisherPageFragment publish() { WebElement publishButton = browser.findElement(publishButtonBy); Assert.assertTrue(publishButton.isDisplayed()); publishButton.click(); By modalBy = By.className("modal"); OOGraphene.waitElement(modalBy, browser); WebElement modal = browser.findElement(By.className("modal")); return Graphene.createPageFragment(PublisherPageFragment.class, modal); } /** * Click the back button * * @return */ public CoursePageFragment clickToolbarBack() { browser.findElement(toolbarBackBy).click(); OOGraphene.waitBusy(browser); OOGraphene.closeBlueMessageWindow(browser); By mainId = By.id("o_main"); OOGraphene.waitElement(mainId, 5, browser); return new CoursePageFragment(browser); } }