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/05/22 12:32:50 UTC

falcon git commit: FALCON-1229 Tests for instance page on SearchUI. Contributed by Ruslan Ostafiychuk

Repository: falcon
Updated Branches:
  refs/heads/master 637900145 -> 1afb51079


FALCON-1229 Tests for instance page on SearchUI. 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/1afb5107
Tree: http://git-wip-us.apache.org/repos/asf/falcon/tree/1afb5107
Diff: http://git-wip-us.apache.org/repos/asf/falcon/diff/1afb5107

Branch: refs/heads/master
Commit: 1afb51079a7ebfdaca1cddb39c0c555ea58fdbcd
Parents: 6379001
Author: Ruslan Ostafiychuk <ro...@apache.org>
Authored: Thu May 21 17:31:19 2015 +0300
Committer: Ruslan Ostafiychuk <ro...@apache.org>
Committed: Fri May 22 13:32:09 2015 +0300

----------------------------------------------------------------------
 falcon-regression/CHANGES.txt                   |   2 +
 .../falcon/regression/ui/search/EntityPage.java |   7 +
 .../regression/ui/search/InstancePage.java      | 114 +++++++++++
 .../regression/searchUI/InstancePageTest.java   | 193 +++++++++++++++++++
 4 files changed, 316 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/falcon/blob/1afb5107/falcon-regression/CHANGES.txt
----------------------------------------------------------------------
diff --git a/falcon-regression/CHANGES.txt b/falcon-regression/CHANGES.txt
index c6da36d..b64f11e 100644
--- a/falcon-regression/CHANGES.txt
+++ b/falcon-regression/CHANGES.txt
@@ -5,6 +5,8 @@ Trunk (Unreleased)
   INCOMPATIBLE CHANGES
 
   NEW FEATURES
+   FALCON-1229 Tests for instance page on SearchUI (Ruslan Ostafiychuk)
+
    FALCON-1216 Cluster setup wizard multiple tests (Paul Isaychuk via Ruslan Ostafiychuk)
 
    FALCON-1202 Add tests for EntityPage (Raghav Kumar Gautam)

http://git-wip-us.apache.org/repos/asf/falcon/blob/1afb5107/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/EntityPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/EntityPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/EntityPage.java
index 0b7057e..5dabc7c 100644
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/EntityPage.java
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/EntityPage.java
@@ -38,6 +38,7 @@ import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
 import org.openqa.selenium.support.FindBys;
+import org.openqa.selenium.support.PageFactory;
 import org.openqa.selenium.support.ui.Select;
 import org.testng.asserts.SoftAssert;
 
@@ -589,6 +590,12 @@ public class EntityPage extends AbstractSearchPage {
         }
     }
 
+
+    public InstancePage openInstance(String nominalTime) {
+        instanceListBox.findElement(By.xpath("//button[contains(.,'" + nominalTime + "')]")).click();
+        return PageFactory.initElements(driver, InstancePage.class);
+    }
+
     /**
      * Class representing summary of one instance.
      */

http://git-wip-us.apache.org/repos/asf/falcon/blob/1afb5107/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/InstancePage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/InstancePage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/InstancePage.java
new file mode 100644
index 0000000..1fce0a2
--- /dev/null
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/InstancePage.java
@@ -0,0 +1,114 @@
+/**
+ * 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.ui.search;
+
+import org.apache.falcon.regression.core.util.UIAssert;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+import org.openqa.selenium.support.FindBys;
+import org.openqa.selenium.support.PageFactory;
+
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * Class representation of Search UI entity page.
+ */
+public class InstancePage extends AbstractSearchPage {
+    private final String nominalTime;
+
+    /**
+     * Possible instance actions available on instance page.
+     */
+    public enum Button {
+        Resume,
+        Suspend,
+        Stop
+    }
+
+    public InstancePage(WebDriver driver) {
+        super(driver);
+        nominalTime = driver.findElement(By.xpath("//h3")).getText().split("\\|")[1].trim();
+    }
+
+
+    @FindBys({
+            @FindBy(className = "detailsBox"),
+            @FindBy(className = "row")
+    })
+    private WebElement detailsBox;
+
+    @FindBys({
+            @FindBy(xpath = "//h3/a")
+    })
+    private WebElement entityLink;
+
+
+
+    @Override
+    public void checkPage() {
+        UIAssert.assertDisplayed(detailsBox, "Dependency box");
+        UIAssert.assertDisplayed(entityLink, "Link to parrent entity");
+    }
+
+    public InstancePage refreshPage() {
+        return backToEntityPage().openInstance(nominalTime);
+    }
+
+    public String getStatus() {
+        return driver.findElement(By.xpath("//h4[@class='instance-title']/span")).getText();
+    }
+
+    public String getEntityName() {
+        return entityLink.getText();
+    }
+
+    public boolean isLineagePresent() {
+        List<WebElement> lineage = driver.findElements(By.className("lineage-graph"));
+        return !lineage.isEmpty() && lineage.get(0).isDisplayed();
+    }
+
+
+    public Set<Button> getButtons(boolean active) {
+        List<WebElement> buttons = detailsBox.findElement(By.className("buttonCell"))
+                .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) {
+        detailsBox.findElement(By.className("buttonCell"))
+                .findElements(By.className("btn")).get(button.ordinal()).click();
+        waitForAngularToFinish();
+    }
+
+    public EntityPage backToEntityPage() {
+        entityLink.click();
+        return PageFactory.initElements(driver, EntityPage.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/falcon/blob/1afb5107/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/InstancePageTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/InstancePageTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/InstancePageTest.java
new file mode 100644
index 0000000..0152b42
--- /dev/null
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/InstancePageTest.java
@@ -0,0 +1,193 @@
+/**
+ * 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.falcon.entity.v0.EntityType;
+import org.apache.falcon.entity.v0.Frequency;
+import org.apache.falcon.regression.core.bundle.Bundle;
+import org.apache.falcon.regression.core.helpers.ColoHelper;
+import org.apache.falcon.regression.core.util.*;
+import org.apache.falcon.regression.testHelper.BaseUITestClass;
+import org.apache.falcon.regression.ui.search.EntityPage;
+import org.apache.falcon.regression.ui.search.InstancePage;
+import org.apache.falcon.regression.ui.search.LoginPage;
+import org.apache.falcon.regression.ui.search.SearchPage;
+import org.apache.falcon.resource.InstancesResult;
+import org.apache.oozie.client.CoordinatorAction;
+import org.apache.oozie.client.OozieClient;
+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 java.io.IOException;
+import java.util.EnumSet;
+
+/**
+ * Tests for Search UI Instance Page.
+ */
+@Test(groups = "search-ui")
+public class InstancePageTest extends BaseUITestClass {
+
+    private final ColoHelper cluster = servers.get(0);
+    private final OozieClient clusterOC = serverOC.get(0);
+    private String baseTestHDFSDir = cleanAndGetTestDir();
+    private String aggregateWorkflowDir = baseTestHDFSDir + "/aggregator";
+    private String feedInputPath = baseTestHDFSDir + "/input" + MINUTE_DATE_PATTERN;
+    private String feedOutputPath = baseTestHDFSDir + "/output" + MINUTE_DATE_PATTERN;
+    private SearchPage searchPage;
+    private InstancePage instancePage;
+    private String instance = "2010-01-02T01:00Z";
+    private String processName;
+
+    @BeforeClass(alwaysRun = true)
+    public void setup() {
+        openBrowser();
+        searchPage = LoginPage.open(getDriver()).doDefaultLogin();
+    }
+
+    @BeforeMethod(alwaysRun = true)
+    public void submitEntities() throws Exception {
+        cleanAndGetTestDir();
+        HadoopUtil.uploadDir(serverFS.get(0), aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE);
+        bundles[0] = BundleUtil.readELBundle();
+        bundles[0] = new Bundle(bundles[0], cluster);
+        bundles[0].generateUniqueBundle(this);
+        bundles[0].setInputFeedDataPath(feedInputPath);
+        bundles[0].setProcessWorkflow(aggregateWorkflowDir);
+        bundles[0].setProcessValidity("2010-01-02T01:00Z", "2010-01-02T01:01Z");
+        bundles[0].setProcessInputStartEnd("now(0, 0)", "now(0, 0)");
+        bundles[0].setProcessPeriodicity(5, Frequency.TimeUnit.minutes);
+        bundles[0].setOutputFeedPeriodicity(5, Frequency.TimeUnit.minutes);
+        bundles[0].setOutputFeedLocationData(feedOutputPath);
+        bundles[0].submitAndScheduleProcess();
+        processName = bundles[0].getProcessName();
+        searchPage.refresh();
+        InstanceUtil.waitTillInstanceReachState(clusterOC, processName, 1,
+                CoordinatorAction.Status.WAITING, EntityType.PROCESS, 5);
+    }
+
+    @Test
+    public void testInstancePageStatusWaitingRunning() throws Exception {
+        instancePage = searchPage.openEntityPage(processName).openInstance(instance);
+        checkInstanceStatuses(InstancesResult.WorkflowStatus.WAITING);
+
+        Assert.assertEquals(instancePage.getButtons(false), EnumSet.allOf(InstancePage.Button.class),
+            "All buttons should be disabled for WAITING instance");
+
+        OozieUtil.createMissingDependencies(cluster, EntityType.PROCESS, processName, 0);
+
+        InstanceUtil.waitTillInstanceReachState(clusterOC, processName, 1,
+                CoordinatorAction.Status.RUNNING, EntityType.PROCESS, 5);
+
+        instancePage = instancePage.refreshPage();
+        checkInstanceStatuses(InstancesResult.WorkflowStatus.RUNNING);
+        Assert.assertEquals(instancePage.getButtons(false), EnumSet.of(InstancePage.Button.Resume),
+                "Only 'Resume' button should be disabled for RUNNING instance");
+    }
+
+    @Test
+    public void testInstancePagePauseResume() throws Exception {
+        OozieUtil.createMissingDependencies(cluster, EntityType.PROCESS, processName, 0);
+        InstanceUtil.waitTillInstanceReachState(clusterOC, processName, 1,
+                CoordinatorAction.Status.RUNNING, EntityType.PROCESS, 5);
+
+        instancePage = searchPage.openEntityPage(processName).openInstance(instance);
+        checkInstanceStatuses(InstancesResult.WorkflowStatus.RUNNING);
+
+        instancePage.clickButton(InstancePage.Button.Suspend);
+        checkInstanceStatuses(InstancesResult.WorkflowStatus.SUSPENDED);
+
+        Assert.assertEquals(instancePage.getButtons(false), EnumSet.of(InstancePage.Button.Suspend),
+                "Only 'Suspend' button should be disabled for SUSPENDED instance");
+
+        instancePage.clickButton(InstancePage.Button.Resume);
+        checkInstanceStatuses(InstancesResult.WorkflowStatus.RUNNING);
+    }
+
+    @Test
+    public void testInstancePageKillRerun() throws Exception {
+        OozieUtil.createMissingDependencies(cluster, EntityType.PROCESS, processName, 0);
+        InstanceUtil.waitTillInstanceReachState(clusterOC, processName, 1,
+                CoordinatorAction.Status.RUNNING, EntityType.PROCESS, 5);
+
+        instancePage = searchPage.openEntityPage(processName).openInstance(instance);
+        checkInstanceStatuses(InstancesResult.WorkflowStatus.RUNNING);
+
+        instancePage.clickButton(InstancePage.Button.Stop);
+        checkInstanceStatuses(InstancesResult.WorkflowStatus.KILLED);
+
+        Assert.assertEquals(instancePage.getButtons(true), EnumSet.of(InstancePage.Button.Resume),
+                "Only 'Resume' button should be active for KILLED instance");
+
+        instancePage.clickButton(InstancePage.Button.Resume);
+        checkInstanceStatuses(InstancesResult.WorkflowStatus.RUNNING);
+    }
+
+    @Test
+    public void testInstancePageInfo() throws Exception {
+        OozieUtil.createMissingDependencies(cluster, EntityType.PROCESS, processName, 0);
+        InstanceUtil.waitTillInstanceReachState(clusterOC, processName, 1,
+                CoordinatorAction.Status.SUCCEEDED, EntityType.PROCESS, 5);
+
+        EntityPage entityPage = searchPage.openEntityPage(processName);
+        EntityPage.OneInstanceSummary summary = EntityPage.InstanceSummary
+                .getOneSummary(entityPage.getInstanceSummary().getSummary(), instance);
+        Assert.assertNotNull(summary, "Instance not found on entity page");
+        Assert.assertEquals(summary.getStatus(), "SUCCEEDED", "Unexpected status on entity page");
+
+        instancePage = entityPage.openInstance(instance);
+        checkInstanceStatuses(InstancesResult.WorkflowStatus.SUCCEEDED);
+
+        Assert.assertEquals(instancePage.getEntityName(), processName, "Process name isn't shown correctly");
+
+        Assert.assertTrue(instancePage.isLineagePresent(), "Lineage graph should be present");
+    }
+
+    @Test
+    public void testHeader() {
+        instancePage = searchPage.openEntityPage(processName).openInstance(instance);
+        instancePage.getPageHeader().checkHeader();
+
+    }
+
+
+    private void checkInstanceStatuses(InstancesResult.WorkflowStatus status) throws Exception {
+        InstancesResult.Instance[] instances = prism.getProcessHelper()
+                .listInstances(processName, "start=" + instance, null).getInstances();
+        Assert.assertNotNull(instance, "Instances not found via API");
+        Assert.assertEquals(instances.length, 1, "Only one instance expected via API");
+        Assert.assertEquals(instances[0].getStatus(), status, "Unexpected status via API");
+
+        Assert.assertEquals(instancePage.getStatus(), status.toString(), "Unexpected status on UI");
+    }
+
+
+    @AfterMethod(alwaysRun = true)
+    public void tearDown() throws IOException {
+        removeTestClassEntities();
+    }
+
+    @AfterClass(alwaysRun = true)
+    public void tearDownClass() {
+        closeBrowser();
+    }
+}