Repository: falcon Updated Branches: refs/heads/master 9da286574 -> 7f9a77fbc
FALCON-1198 Test buttons available on search results page. Contributed by Ruslan Ostafiychuk Project: http://git-wip-us.apache.org/repos/asf/falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/falcon/commit/7f9a77fb Tree: http://git-wip-us.apache.org/repos/asf/falcon/tree/7f9a77fb Diff: http://git-wip-us.apache.org/repos/asf/falcon/diff/7f9a77fb Branch: refs/heads/master Commit: 7f9a77fbcfd2dec29bf01044d295d1e39a8ec6a7 Parents: 9da2865 Author: Ruslan Ostafiychuk <[email protected]> Authored: Wed May 6 17:40:51 2015 +0300 Committer: Ruslan Ostafiychuk <[email protected]> Committed: Thu May 7 10:11:47 2015 +0300 ---------------------------------------------------------------------- falcon-regression/CHANGES.txt | 2 + .../core/enumsAndConstants/MerlinConstants.java | 6 +- .../org/apache/falcon/request/BaseRequest.java | 3 +- .../org/apache/falcon/request/RequestKeys.java | 2 - .../falcon/regression/ui/search/SearchPage.java | 61 +++++++++- .../searchUI/EntitiesTableReflectionTest.java | 116 ++++++++++++++++--- 6 files changed, 167 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/falcon/blob/7f9a77fb/falcon-regression/CHANGES.txt ---------------------------------------------------------------------- diff --git a/falcon-regression/CHANGES.txt b/falcon-regression/CHANGES.txt index 5d2400c..56827be 100644 --- a/falcon-regression/CHANGES.txt +++ b/falcon-regression/CHANGES.txt @@ -5,6 +5,8 @@ Trunk (Unreleased) INCOMPATIBLE CHANGES NEW FEATURES + FALCON-1198 Test buttons available on search results page (Ruslan Ostafiychuk) + FALCON-1187 Test that changes made via API are reflected on UI (Ruslan Ostafiychuk via Raghav Kumar Gautam) http://git-wip-us.apache.org/repos/asf/falcon/blob/7f9a77fb/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java index 7f0f5c7..299be67 100644 --- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java +++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java @@ -19,7 +19,6 @@ package org.apache.falcon.regression.core.enumsAndConstants; import org.apache.falcon.regression.core.util.Config; -import org.apache.falcon.request.RequestKeys; import org.apache.hadoop.conf.Configuration; import org.testng.Assert; import org.apache.log4j.Logger; @@ -54,7 +53,8 @@ public final class MerlinConstants { "https://repo1.maven.org/maven2/org/apache/oozie/oozie-examples/4.1.0/oozie-examples-4.1.0.jar"); /** the user that is going to run tests. */ - public static final String CURRENT_USER_NAME = System.getProperty("user.name"); + public static final String CURRENT_USER_NAME = Config.getProperty("current_user_name", + System.getProperty("user.name")); /** keytab of current user. */ private static final String CURRENT_USER_KEYTAB_STR = "current_user_keytab"; /** group of the current user. */ @@ -80,8 +80,6 @@ public final class MerlinConstants { public static final String USER2_NAME; private static HashMap<String, String> keyTabMap; private static HashMap<String, String> passwordMap; - public static final String ACL_OWNER = Config.getProperty("ACL.OWNER", RequestKeys.CURRENT_USER); - public static final String ACL_GROUP = Config.getProperty("ACL.GROUP", "default"); public static final String USER_REALM = Config.getProperty("USER.REALM", ""); public static final String WASB_CONTAINER = Config.getProperty("wasb.container", ""); public static final String WASB_SECRET = Config.getProperty("wasb.secret", ""); http://git-wip-us.apache.org/repos/asf/falcon/blob/7f9a77fb/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/BaseRequest.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/BaseRequest.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/BaseRequest.java index a70ceeb..7157111 100644 --- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/BaseRequest.java +++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/BaseRequest.java @@ -19,6 +19,7 @@ package org.apache.falcon.request; import org.apache.commons.net.util.TrustManagerUtils; +import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants; import org.apache.falcon.regression.core.helpers.entity.AbstractEntityHelper; import org.apache.falcon.security.FalconAuthorizationToken; import org.apache.hadoop.security.authentication.client.AuthenticatedURL; @@ -96,7 +97,7 @@ public class BaseRequest { this.method = method; this.url = url; this.requestData = null; - this.user = (null == user) ? RequestKeys.CURRENT_USER : user; + this.user = (null == user) ? MerlinConstants.CURRENT_USER_NAME : user; this.uri = new URI(url); target = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme()); this.headers = new ArrayList<>(); http://git-wip-us.apache.org/repos/asf/falcon/blob/7f9a77fb/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/RequestKeys.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/RequestKeys.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/RequestKeys.java index 3232978..b2e38b2 100644 --- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/RequestKeys.java +++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/RequestKeys.java @@ -32,6 +32,4 @@ public final class RequestKeys { public static final String COOKIE = "Cookie"; public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; public static final String NEGOTIATE = "Negotiate"; - public static final String CURRENT_USER = System - .getProperty("user.name"); } http://git-wip-us.apache.org/repos/asf/falcon/blob/7f9a77fb/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/SearchPage.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/SearchPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/SearchPage.java index 9ad2591..aabd9ca 100644 --- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/SearchPage.java +++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/SearchPage.java @@ -18,6 +18,7 @@ package org.apache.falcon.regression.ui.search; +import org.apache.falcon.regression.core.util.TimeUtil; import org.apache.falcon.regression.core.util.UIAssert; import org.apache.log4j.Logger; import org.openqa.selenium.By; @@ -31,10 +32,16 @@ import org.testng.Assert; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.EnumSet; import java.util.List; +import java.util.Set; /** Page object for the Search Page. */ public class SearchPage extends AbstractSearchPage { + + private static final String CLASS_OF_SELECTED_ROW = "rowSelected"; + private static final int ANIMATION_DELAY = 2; + public SearchPage(WebDriver driver) { super(driver); } @@ -78,8 +85,7 @@ public class SearchPage extends AbstractSearchPage { final SearchResult searchResult = SearchResult.create(entityName); final String[] allClasses = oneResultElement.getAttribute("class").split(" "); - final String classOfSelectedRow = "rowSelected"; - if (Arrays.asList(allClasses).contains(classOfSelectedRow)) { + if (Arrays.asList(allClasses).contains(CLASS_OF_SELECTED_ROW)) { searchResult.withChecked(true); } @@ -162,6 +168,26 @@ public class SearchPage extends AbstractSearchPage { UIAssert.assertNotDisplayed(resultBlock, "Search result block"); } + public void selectRow(int row) { + changeRowClickedStatus(row, true); + } + + public void deselectRow(int row) { + changeRowClickedStatus(row, false); + } + + private void changeRowClickedStatus(int row, boolean checked) { + WebElement checkboxBlock = resultBlock.findElements(By.className("entityRow")).get(row - 1); + if (checked != checkboxBlock.getAttribute("class").contains(CLASS_OF_SELECTED_ROW)) { + checkboxBlock.findElement(By.xpath("./td/input")).click(); + } + } + + public void clickSelectAll() { + resultBlock.findElement(By.xpath(".//input[@ng-model='selectedAll']")).click(); + } + + /** Class representing search query displayed in the search box. */ public static final class SearchQuery { private WebElement searchBlock; @@ -254,6 +280,37 @@ public class SearchPage extends AbstractSearchPage { } } + public Set<Button> getButtons(boolean active) { + List<WebElement> buttons = resultBlock.findElement(By.className("buttonsRow")) + .findElements(By.className("btn")); + Set<Button> result = EnumSet.noneOf(Button.class); + for (WebElement button : buttons) { + if ((button.getAttribute("disabled") == null) == active) { + result.add(Button.valueOf(button.getText())); + } + } + return result; + } + + public void clickButton(Button button) { + resultBlock.findElement(By.className("buttonsRow")) + .findElements(By.className("btn")).get(button.ordinal()).click(); + TimeUtil.sleepSeconds(ANIMATION_DELAY); + } + + /** + * Buttons available for entities in result box. + */ + public enum Button { + Schedule, + Resume, + Suspend, + Edit, + Copy, + Delete, + XML + } + /** Class representing search result displayed on the entity table page. */ public static final class SearchResult { private boolean isChecked = false; http://git-wip-us.apache.org/repos/asf/falcon/blob/7f9a77fb/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/EntitiesTableReflectionTest.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/EntitiesTableReflectionTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/EntitiesTableReflectionTest.java index 8d64a0e..cbad93a 100644 --- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/EntitiesTableReflectionTest.java +++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/EntitiesTableReflectionTest.java @@ -18,24 +18,31 @@ package org.apache.falcon.regression.searchUI; +import org.apache.falcon.regression.Entities.ProcessMerlin; import org.apache.falcon.regression.core.bundle.Bundle; import org.apache.falcon.regression.core.util.AssertUtil; import org.apache.falcon.regression.core.util.BundleUtil; import org.apache.falcon.regression.core.util.OSUtil; -import org.apache.falcon.regression.core.util.Util; import org.apache.falcon.regression.testHelper.BaseUITestClass; import org.apache.falcon.regression.ui.pages.Page.EntityStatus; import org.apache.falcon.regression.ui.search.LoginPage; import org.apache.falcon.regression.ui.search.SearchPage; +import org.apache.falcon.regression.ui.search.SearchPage.Button; import org.apache.hadoop.security.authentication.client.AuthenticationException; import org.testng.Assert; import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import javax.xml.bind.JAXBException; import java.io.IOException; import java.net.URISyntaxException; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; /** UI tests for entities table with search results. */ @Test(groups = "search-ui") @@ -44,20 +51,37 @@ public class EntitiesTableReflectionTest extends BaseUITestClass { private String aggregateWorkflowDir = baseTestDir + "/aggregator"; private SearchPage searchPage = null; + private String twoProcessesNameStart; + private Map<String, String> processesMap = new TreeMap<>(); @BeforeClass(alwaysRun = true) - public void setup() - throws URISyntaxException, IOException, AuthenticationException, InterruptedException, - JAXBException { + public void setup() throws IOException { uploadDirToClusters(aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE); openBrowser(); searchPage = LoginPage.open(getDriver()).doDefaultLogin(); + } + + @BeforeMethod(alwaysRun = true) + public void submitEntities() + throws URISyntaxException, IOException, AuthenticationException, InterruptedException, + JAXBException { bundles[0] = BundleUtil.readELBundle(); bundles[0] = new Bundle(bundles[0], servers.get(0)); bundles[0].generateUniqueBundle(this); bundles[0].setProcessWorkflow(aggregateWorkflowDir); - bundles[0].submitBundle(prism); - + bundles[0].submitClusters(prism); + bundles[0].submitFeeds(prism); + + ProcessMerlin process = bundles[0].getProcessObject(); + twoProcessesNameStart = process.getName() + '-'; + process.setName(twoProcessesNameStart + 1); + bundles[0].setProcessData(process.toString()); + prism.getProcessHelper().submitEntity(process.toString()); + processesMap.put(process.getName(), process.toString()); + + process.setName(twoProcessesNameStart + 2); + prism.getProcessHelper().submitEntity(process.toString()); + processesMap.put(process.getName(), process.toString()); } @Test @@ -96,20 +120,84 @@ public class EntitiesTableReflectionTest extends BaseUITestClass { } @Test + public void testActionButtonsNotScheduled() { + Assert.assertEquals(searchPage.doSearch(twoProcessesNameStart).size(), 2, + "Two results should be present"); + + Assert.assertEquals(searchPage.getButtons(true), EnumSet.noneOf(Button.class), + "There should be zero active buttons"); + Assert.assertEquals(searchPage.getButtons(false), EnumSet.allOf(Button.class), + "All buttons should be disabled"); + + searchPage.selectRow(1); + Assert.assertEquals(searchPage.getButtons(false), EnumSet.of(Button.Resume, Button.Suspend), + "List of disabled buttons is not correct"); + searchPage.selectRow(2); + Assert.assertEquals(searchPage.getButtons(true), EnumSet.of(Button.Schedule, Button.Delete), + "List of active buttons is not correct"); + searchPage.deselectRow(2); + Assert.assertEquals(searchPage.getButtons(false), EnumSet.of(Button.Resume, Button.Suspend), + "List of disabled buttons is not correct"); + } + + @Test public void testActionsPauseResume() throws URISyntaxException, - AuthenticationException, InterruptedException, IOException, JAXBException { - String processName = Util.readEntityName(bundles[0].getProcessData()); - Assert.assertEquals(searchPage.doSearch(processName).size(), 1, - "One result should be present"); - Assert.assertEquals(searchPage.doSearch(processName).get(0).getStatus(), - EntityStatus.SUBMITTED, "Status of process should be SUBMITTED"); + AuthenticationException, InterruptedException, IOException { + Assert.assertEquals(searchPage.doSearch(twoProcessesNameStart).size(), 2, + "Two results should be present after deletion"); + + //select first process + searchPage.selectRow(1); + searchPage.clickButton(Button.Schedule); + List<SearchPage.SearchResult> results = searchPage.getSearchResults(); + String firstProcess = processesMap.get(results.get(0).getEntityName()); + String secondProcess = processesMap.get(results.get(1).getEntityName()); + + Assert.assertEquals(results.get(0).getStatus(), EntityStatus.RUNNING, + "Status of scheduled process should be RUNNING"); + Assert.assertTrue(prism.getProcessHelper().getStatus(firstProcess).getMessage() + .contains("RUNNING"), "First process should be RUNNING via API"); + //select two processes + searchPage.clickSelectAll(); + Assert.assertEquals(searchPage.getButtons(true), EnumSet.of(Button.Delete), + "Only 'Delete' should be available for processes with different statuses"); + + searchPage.deselectRow(1); + searchPage.clickButton(Button.Schedule); + + Assert.assertEquals(searchPage.getSearchResults().get(1).getStatus(), EntityStatus.RUNNING, + "Status of scheduled process should be RUNNING"); + Assert.assertTrue(prism.getProcessHelper().getStatus(secondProcess).getMessage() + .contains("RUNNING"), "Second process should be RUNNING via API"); + + searchPage.selectRow(1); + searchPage.selectRow(2); + searchPage.clickButton(Button.Suspend); + + Assert.assertEquals(searchPage.getSearchResults().get(0).getStatus(), EntityStatus.SUSPENDED, + "Status of scheduled process should be SUSPENDED"); + Assert.assertTrue(prism.getProcessHelper().getStatus(firstProcess).getMessage() + .contains("SUSPENDED"), "First process should be SUSPENDED via API"); + + Assert.assertEquals(results.get(1).getStatus(), EntityStatus.SUSPENDED, + "Status of scheduled process should be RUNNING"); + Assert.assertTrue(prism.getProcessHelper().getStatus(secondProcess).getMessage() + .contains("SUSPENDED"), "Second process should be SUSPENDED via API"); + + searchPage.clickSelectAll(); + Assert.assertEquals(searchPage.getButtons(true), EnumSet.of(Button.Resume, Button.Delete), + "List of active buttons is not correct after selecting two SUSPENDED processes"); } - @AfterClass(alwaysRun = true) + @AfterMethod(alwaysRun = true) public void tearDown() { removeTestClassEntities(); - closeBrowser(); } + + @AfterClass(alwaysRun = true) + public void tearDownClass() { + closeBrowser(); + } }
