You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@falcon.apache.org by ro...@apache.org on 2015/04/27 16:06:15 UTC

falcon git commit: FALCON-1173 Tests for entities table of search-ui. Contributed by Ruslan Ostafiychuk

Repository: falcon
Updated Branches:
  refs/heads/master a6298f8a7 -> 9124f0152


FALCON-1173 Tests for entities table of search-ui. 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/9124f015
Tree: http://git-wip-us.apache.org/repos/asf/falcon/tree/9124f015
Diff: http://git-wip-us.apache.org/repos/asf/falcon/diff/9124f015

Branch: refs/heads/master
Commit: 9124f015275a780480aa256b8538191ccc96d6e7
Parents: a6298f8
Author: Ruslan Ostafiychuk <ro...@apache.org>
Authored: Wed Apr 22 18:45:36 2015 +0300
Committer: Ruslan Ostafiychuk <ro...@apache.org>
Committed: Mon Apr 27 17:00:29 2015 +0300

----------------------------------------------------------------------
 falcon-regression/CHANGES.txt                   |   4 +-
 .../falcon/regression/ui/search/SearchPage.java | 143 +++++++++++++----
 .../falcon/regression/TestngListener.java       |   7 +-
 .../regression/searchUI/EntitiesTableTest.java  | 155 +++++++++++++++++++
 4 files changed, 279 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/falcon/blob/9124f015/falcon-regression/CHANGES.txt
----------------------------------------------------------------------
diff --git a/falcon-regression/CHANGES.txt b/falcon-regression/CHANGES.txt
index 104c01f..884acfc 100644
--- a/falcon-regression/CHANGES.txt
+++ b/falcon-regression/CHANGES.txt
@@ -5,6 +5,8 @@ Trunk (Unreleased)
   INCOMPATIBLE CHANGES
 
   NEW FEATURES
+   FALCON-1173 Tests for entities table of search-ui (Ruslan Ostafiychuk)
+
    FALCON-1171 Adding search API tests (Paul Isaychuk via Raghav Kumar Gautam)
 
    FALCON-1167 Homepage & Login test for search-ui (Raghav Kumar Gautam via Ruslan Ostafiychuk)
@@ -66,7 +68,7 @@ Trunk (Unreleased)
    via Samarth Gupta)
 
   IMPROVEMENTS
-  
+
    FALCON-1131 Fixing FeedClusterUpdateTest and name confilcts in FALCON-1113(Pragya M 
    via Samarth Gupta) 
 

http://git-wip-us.apache.org/repos/asf/falcon/blob/9124f015/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 8c3ae71..5d3febf 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
@@ -19,7 +19,9 @@
 package org.apache.falcon.regression.ui.search;
 
 import org.apache.falcon.regression.core.util.UIAssert;
+import org.apache.log4j.Logger;
 import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
@@ -28,6 +30,7 @@ import org.testng.Assert;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 /** Page object for the Search Page. */
@@ -106,53 +109,110 @@ public class SearchPage extends AbstractSearchPage {
     }
 
     public List<SearchResult> doSearch(String searchString) {
-        getSearchBox().sendKeys(searchString + "\n");
+        clearSearch();
+        return appendAndSearch(searchString);
+    }
+
+    public List<SearchResult> appendAndSearch(String appendedPart) {
+        for(String queryParam : appendedPart.split("\\s+")) {
+            getSearchBox().sendKeys(queryParam);
+            getSearchBox().sendKeys(Keys.SPACE);
+        }
+        String activeAlert = getActiveAlertText();
+        if (activeAlert != null) {
+            Assert.assertEquals(activeAlert.trim(), "No results matched the search criteria.");
+            return Collections.emptyList();
+        }
         UIAssert.assertDisplayed(resultBlock, "Search result block");
         return getSearchResults();
+
     }
 
-    public SearchQuery getSearchQuery() {
-        final WebElement queryGroup = searchBlock.findElement(By.className("tag-list"));
-        final List<WebElement> queryParts = queryGroup.findElements(By.tagName("li"));
-        if (queryParts.size() == 0) {
-            return SearchQuery.create(null);
-        } else {
-            final WebElement namePart = queryParts.remove(0);
-            final WebElement nameLabel = namePart.findElement(By.tagName("strong"));
-            Assert.assertEquals(nameLabel.getText(), "NAME: ", "Name label of query");
-            final WebElement nameElem = namePart.findElement(By.tagName("span"));
-            SearchQuery searchQuery = SearchQuery.create(nameElem.getText());
-            for (WebElement tagPart : queryParts) {
-                final WebElement tagLabel = tagPart.findElement(By.tagName("strong"));
-                Assert.assertEquals(tagLabel.getText(), "TAG: ", "Tag label of query");
-                final WebElement tagElem = tagPart.findElement(By.tagName("span"));
-                searchQuery.withTag(tagElem.getText());
+    private String getActiveAlertText() {
+        List<WebElement> alerts = driver.findElements(By.className("ng-animate"));
+        if (!alerts.isEmpty()) {
+            WebElement last = alerts.get(alerts.size() - 1);
+            if (last.isDisplayed()) {
+                return last.getText();
             }
-            return searchQuery;
         }
+        return null;
     }
 
+    public SearchQuery getSearchQuery() {
+        return new SearchQuery(searchBlock);
+    }
+
+    public void clearSearch() {
+        getSearchBox().clear();
+        SearchQuery query = getSearchQuery();
+        for (int i = 0; i < query.getElementsNumber(); i++) {
+            removeLastParam();
+        }
+    }
+
+    public void removeLastParam() {
+        getSearchBox().sendKeys(Keys.BACK_SPACE);
+        getSearchBox().sendKeys(Keys.BACK_SPACE);
+    }
+
+
     public void checkNoResult() {
         UIAssert.assertNotDisplayed(resultBlock, "Search result block");
     }
 
     /** Class representing search query displayed in the search box. */
     public static final class SearchQuery {
-        private final String name;
-
+        private WebElement searchBlock;
+        private String name;
+        private String type;
+        private int elementsNumber;
         private final List<String> tags = new ArrayList<>();
+        private static final Logger LOGGER = Logger.getLogger(SearchQuery.class);
 
-        private SearchQuery(String name) {
-            this.name = name;
+        public SearchQuery(WebElement searchBlock) {
+            this.searchBlock = searchBlock;
+            updateElements();
         }
 
-        public static SearchQuery create(String name) {
-            return new SearchQuery(name);
+        private SearchQuery updateElements() {
+            name = null;
+            type = null;
+            tags.clear();
+            final WebElement queryGroup = searchBlock.findElement(By.className("tag-list"));
+            final List<WebElement> queryParts = queryGroup.findElements(By.tagName("li"));
+            elementsNumber = queryParts.size();
+            for (WebElement queryPart : queryParts) {
+                final WebElement queryLabel = queryPart.findElement(By.tagName("strong"));
+                final String queryText = queryPart.findElement(By.tagName("span")).getText();
+                switch (queryLabel.getText().trim()) {
+                case "NAME:":
+                    if (name != null) {
+                        LOGGER.warn(String.format("NAME block is already added: '%s' => '%s'",
+                            name, queryText));
+                    }
+                    name = queryText;
+                    break;
+                case "TAG:":
+                    tags.add(queryText);
+                    break;
+                case "TYPE:":
+                    if (type != null) {
+                        LOGGER.warn(String.format("TYPE block is already added: '%s' => '%s'",
+                            type, queryText));
+                    }
+                    type = queryText;
+                    break;
+                default:
+                    Assert.fail("There should be only TAGs or TYPE");
+                }
+            }
+            return this;
         }
 
-        public SearchQuery withTag(String tag) {
-            tags.add(tag);
-            return this;
+
+        public String getType() {
+            return type;
         }
 
         public String getName() {
@@ -162,6 +222,35 @@ public class SearchPage extends AbstractSearchPage {
         public List<String> getTags() {
             return tags;
         }
+
+        public int getElementsNumber() {
+            return elementsNumber;
+        }
+
+        /**
+         * Delete element by index (1, 2, 3,..).
+         * @param index of element in search query.
+         * @return true if deletion was successful
+         */
+        public boolean deleteByIndex(int index) {
+            if (index > elementsNumber || index < 1) {
+                LOGGER.warn("There is no element with index=" + index);
+                return false;
+            }
+            int oldElementsNumber = elementsNumber;
+            final WebElement queryGroup = searchBlock.findElement(By.className("tag-list"));
+            final List<WebElement> queryParts = queryGroup.findElements(By.tagName("li"));
+            queryParts.get(index - 1).findElement(By.className("remove-button")).click();
+            this.updateElements();
+            boolean result = oldElementsNumber == elementsNumber + 1;
+            LOGGER.info(String.format(
+                "Element with index=%d was%s deleted", index, result ? "" : "n't"));
+            return result;
+        }
+
+        public boolean deleteLast() {
+            return deleteByIndex(elementsNumber);
+        }
     }
 
     /** Class representing search result displayed on the entity table page. */

http://git-wip-us.apache.org/repos/asf/falcon/blob/9124f015/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java
index e3aac1d..8d8677c 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java
@@ -116,8 +116,11 @@ public class TestngListener implements ITestListener, IExecutionListener {
             byte[] scrFile =
                 ((TakesScreenshot)BaseUITestClass.getDriver()).getScreenshotAs(OutputType.BYTES);
             try {
-                String filename = OSUtil.getPath("target", "surefire-reports", "screenshots", String.format("%s.%s.png",
-                        result.getTestClass().getRealClass().getSimpleName(), result.getName()));
+                String params = Arrays.toString(result.getParameters());
+                params = params.replaceAll("[<>\":\\\\/\\|\\?\\*]", ""); //remove <>:"/\|?*
+                String filename = OSUtil.getPath("target", "surefire-reports", "screenshots",
+                    String.format("%s.%s.(%s).png", result.getTestClass().getRealClass()
+                        .getSimpleName(), result.getName(), params));
                 FileUtils.writeByteArrayToFile(new File(filename), scrFile);
             } catch (IOException e) {
                 LOGGER.info("Saving screenshot FAILED: " + e.getCause());

http://git-wip-us.apache.org/repos/asf/falcon/blob/9124f015/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/EntitiesTableTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/EntitiesTableTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/EntitiesTableTest.java
new file mode 100644
index 0000000..88db7fe
--- /dev/null
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/EntitiesTableTest.java
@@ -0,0 +1,155 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.falcon.regression.searchUI;
+
+import org.apache.commons.lang3.StringUtils;
+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.testHelper.BaseUITestClass;
+import org.apache.falcon.regression.ui.search.LoginPage;
+import org.apache.falcon.regression.ui.search.SearchPage;
+import org.apache.hadoop.security.authentication.client.AuthenticationException;
+import org.apache.log4j.Logger;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import javax.xml.bind.JAXBException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+
+/** UI tests for entities table with search results. */
+@Test(groups = "search-ui")
+public class EntitiesTableTest extends BaseUITestClass {
+    private static final Logger LOGGER = Logger.getLogger(EntitiesTableTest.class);
+    private String baseTestDir = cleanAndGetTestDir();
+    private String aggregateWorkflowDir = baseTestDir + "/aggregator";
+
+    private SearchPage searchPage = null;
+    private String[] tags = {"first=correctvalue", "second=one", "third=one", "fourth=one",
+        "fifth=one", "sixth=one", "seventh=one", "eighth=one", "ninth=one", "tenth=one", };
+    private String baseProcessName;
+
+    /**
+     * Submit one cluster, 2 feeds and 10 processes with 1 to 10 tags (1st process has 1 tag,
+     * 2nd - two tags.. 10th has 10 tags).
+     * @throws URISyntaxException
+     * @throws IOException
+     * @throws AuthenticationException
+     * @throws InterruptedException
+     * @throws JAXBException
+     */
+    @BeforeClass(alwaysRun = true)
+    public void setup()
+        throws URISyntaxException, IOException, AuthenticationException, InterruptedException,
+        JAXBException {
+        uploadDirToClusters(aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE);
+        openBrowser();
+        searchPage = LoginPage.open(getDriver()).doDefaultLogin();
+        bundles[0] = BundleUtil.readELBundle();
+        bundles[0] = new Bundle(bundles[0], servers.get(0));
+        bundles[0].generateUniqueBundle(this);
+        bundles[0].submitClusters(prism);
+        bundles[0].submitFeeds(prism);
+        bundles[0].setProcessWorkflow(aggregateWorkflowDir);
+        ProcessMerlin process = bundles[0].getProcessObject();
+        baseProcessName = process.getName();
+        for (int i = 1; i <= 10; i++) {
+            process.setName(baseProcessName + '-' + i);
+            process.setTags(StringUtils.join(Arrays.copyOfRange(tags, 0, i), ','));
+            AssertUtil.assertSucceeded(prism.getProcessHelper().submitEntity(process.toString()));
+        }
+
+    }
+
+    @AfterClass(alwaysRun = true)
+    public void tearDown() throws IOException {
+        removeTestClassEntities();
+        closeBrowser();
+    }
+
+    /**
+     * Search entities with invalid params. Zero entities should be shown.
+     */
+    @Test(dataProvider = "getInvalidFilters")
+    public void testSearchBoxInvalidFilter(String invalidSearch) {
+        Assert.assertEquals(searchPage.doSearch(invalidSearch).size(), 0,
+            "There should be 0 results with query='" + invalidSearch + "'");
+    }
+
+
+    @DataProvider
+    public Object[][] getInvalidFilters() {
+        return new String[][]{
+            {"notnameofentity"},
+            {"* othertag=sometag"},
+            {"* first=other"},
+            {"XX" + bundles[0].getProcessName().substring(2)},
+        };
+    }
+
+    /**
+     * All processes should be found with first tag. Add tags one by one. Only one process
+     * should be found with all tags.
+     */
+    @Test
+    public void testSearchBoxManyParams() {
+        searchPage.doSearch(baseProcessName);
+        for (int i = 0; i < 10; i++) {
+            Assert.assertEquals(searchPage.appendAndSearch(tags[i]).size(), 10 - i,
+                "There should be " + (10 - i) + " results");
+        }
+    }
+
+    /**
+     * Only one process should be found with all tags. Delete tags one by one. All processes
+     * should be found with first tag. Zero entities should be shown after cleaning all params.
+     */
+    @Test(dataProvider = "getBoolean")
+    public void testSearchBoxCleanSingleParam(boolean deleteByClick) {
+        searchPage.doSearch(this.getClass().getSimpleName() + ' ' + StringUtils.join(tags, ' '));
+        for (int i = 1; i <= 10; i++) {
+            Assert.assertEquals(searchPage.getSearchResults().size(), i,
+                "There should be " + i + " results");
+            if (deleteByClick) {
+                searchPage.getSearchQuery().deleteLast();
+            } else {
+                searchPage.removeLastParam();
+            }
+        }
+        if (deleteByClick) {
+            searchPage.getSearchQuery().deleteLast();
+        } else {
+            searchPage.removeLastParam();
+        }
+        Assert.assertEquals(searchPage.getSearchResults().size(), 0,
+            "There should be 0 results");
+    }
+
+    @DataProvider
+    public Object[][] getBoolean() {
+        return new Boolean[][]{{Boolean.TRUE}, {Boolean.FALSE}};
+    }
+}