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/20 16:20:37 UTC

falcon git commit: FALCON-1216 Cluster setup wizard multiple tests. Contributed by Paul Isaychuk

Repository: falcon
Updated Branches:
  refs/heads/master ea30dc410 -> 24d28a71b


FALCON-1216 Cluster setup wizard multiple tests. Contributed by Paul Isaychuk


Project: http://git-wip-us.apache.org/repos/asf/falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/falcon/commit/24d28a71
Tree: http://git-wip-us.apache.org/repos/asf/falcon/tree/24d28a71
Diff: http://git-wip-us.apache.org/repos/asf/falcon/diff/24d28a71

Branch: refs/heads/master
Commit: 24d28a71be00935d29e1f7e6bcab816d8de66571
Parents: ea30dc4
Author: Ruslan Ostafiychuk <ro...@apache.org>
Authored: Wed May 20 17:19:30 2015 +0300
Committer: Ruslan Ostafiychuk <ro...@apache.org>
Committed: Wed May 20 17:19:30 2015 +0300

----------------------------------------------------------------------
 falcon-regression/CHANGES.txt                   |   4 +-
 .../regression/Entities/ClusterMerlin.java      | 158 ++++++-
 .../core/enumsAndConstants/MerlinConstants.java |   1 +
 .../falcon/regression/core/util/BundleUtil.java |   4 +
 .../falcon/regression/core/util/UIAssert.java   |   1 -
 .../ui/search/AbstractSearchPage.java           |  13 +
 .../regression/ui/search/ClusterWizardPage.java | 449 +++++++++++++++++++
 .../regression/ui/search/NewClusterPage.java    |  44 --
 .../falcon/regression/ui/search/PageHeader.java |   4 +-
 .../falcon/regression/ui/search/SearchPage.java |  12 -
 .../regression/searchUI/ClusterSetupTest.java   | 261 +++++++++++
 .../src/test/resources/ELbundle/cluster-0.1.xml |   2 +-
 12 files changed, 891 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/CHANGES.txt
----------------------------------------------------------------------
diff --git a/falcon-regression/CHANGES.txt b/falcon-regression/CHANGES.txt
index 5e2d0f9..c6da36d 100644
--- a/falcon-regression/CHANGES.txt
+++ b/falcon-regression/CHANGES.txt
@@ -5,6 +5,8 @@ Trunk (Unreleased)
   INCOMPATIBLE CHANGES
 
   NEW FEATURES
+   FALCON-1216 Cluster setup wizard multiple tests (Paul Isaychuk via Ruslan Ostafiychuk)
+
    FALCON-1202 Add tests for EntityPage (Raghav Kumar Gautam)
 
    FALCON-1210 Process Setup tests for testing header and general step default scenario (Raghav Kumar Gautam)
@@ -79,7 +81,7 @@ Trunk (Unreleased)
    via Samarth Gupta)
 
   IMPROVEMENTS
-   FALCON-1226 Stabilize testActionsPauseResume()
+   FALCON-1226 Stabilize testActionsPauseResume() (Ruslan Ostafiychuk)
 
    FALCON-1225 remove text line containing "Copyright" from regression 
    log4j.properties(Samarth Gupta)

http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ClusterMerlin.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ClusterMerlin.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ClusterMerlin.java
index d8305c8..4912be9 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ClusterMerlin.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/Entities/ClusterMerlin.java
@@ -28,17 +28,24 @@ import org.apache.falcon.entity.v0.cluster.Interface;
 import org.apache.falcon.entity.v0.cluster.Interfaces;
 import org.apache.falcon.entity.v0.cluster.Interfacetype;
 import org.apache.falcon.entity.v0.cluster.Location;
+import org.apache.falcon.entity.v0.cluster.Locations;
+import org.apache.falcon.entity.v0.cluster.Properties;
+import org.apache.falcon.entity.v0.cluster.Property;
+import org.apache.falcon.regression.core.util.Util;
+import org.apache.log4j.Logger;
 import org.testng.Assert;
+import org.testng.asserts.SoftAssert;
 
 import javax.xml.bind.JAXBException;
 import java.io.StringWriter;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 /** Class for representing a cluster xml. */
 public class ClusterMerlin extends Cluster {
-
+    private static final Logger LOGGER = Logger.getLogger(ClusterMerlin.class);
     public ClusterMerlin(String clusterData) {
         final Cluster cluster = (Cluster) TestEntityUtil.fromString(EntityType.CLUSTER,
                 clusterData);
@@ -104,6 +111,155 @@ public class ClusterMerlin extends Cluster {
         }
     }
 
+    /**
+     * Cleans all properties and returns empty cluster as a draft (as we can't create cluster e.g from empty string).
+     */
+    public ClusterMerlin getEmptyCluster() {
+        ClusterMerlin clusterMerlin = new ClusterMerlin(this.toString());
+        clusterMerlin.setName("");
+        clusterMerlin.setDescription(null);
+        clusterMerlin.setColo(null);
+        clusterMerlin.setTags(null);
+        clusterMerlin.setInterfaces(new Interfaces());
+        clusterMerlin.setLocations(new Locations());
+        clusterMerlin.getACL().setGroup("");
+        clusterMerlin.getACL().setOwner("");
+        clusterMerlin.setProperties(new Properties());
+        return clusterMerlin;
+    }
+
+    public void addLocation(ClusterLocationType type, String path) {
+        Location newLocation = new Location();
+        newLocation.setName(type);
+        newLocation.setPath(path);
+        getLocations().getLocations().add(newLocation);
+    }
+
+    public void addProperty(String name, String value) {
+        Property property = new Property();
+        property.setName(name);
+        property.setValue(value);
+        getProperties().getProperties().add(property);
+    }
+
+    public void addInterface(Interfacetype type, String endpoint, String version) {
+        Interface iface = new Interface();
+        iface.setType(type);
+        iface.setEndpoint(endpoint);
+        iface.setVersion(version);
+        getInterfaces().getInterfaces().add(iface);
+    }
+
+    public void assertEquals(ClusterMerlin cluster) {
+        LOGGER.info(String.format("Comparing : source: %n%s%n and cluster: %n%n%s",
+            Util.prettyPrintXml(toString()), Util.prettyPrintXml(cluster.toString())));
+        SoftAssert softAssert = new SoftAssert();
+        softAssert.assertEquals(name, cluster.getName(), "Cluster name is different.");
+        softAssert.assertEquals(colo, cluster.getColo(), "Cluster colo is different.");
+        softAssert.assertEquals(description, cluster.getDescription(), "Cluster description is different.");
+        softAssert.assertEquals(tags, cluster.getTags(), "Cluster tags are different.");
+        softAssert.assertTrue(interfacesEqual(interfaces.getInterfaces(), cluster.getInterfaces().getInterfaces()),
+            "Cluster interfaces are different");
+        softAssert.assertTrue(locationsEqual(locations.getLocations(), cluster.getLocations().getLocations()),
+            "Cluster locations are different");
+        softAssert.assertEquals(acl.getGroup(), cluster.getACL().getGroup(), "Cluster acl group is different.");
+        softAssert.assertEquals(acl.getOwner(), cluster.getACL().getOwner(), "Cluster acl owner is different.");
+        softAssert.assertEquals(acl.getPermission(), cluster.getACL().getPermission(),
+            "Cluster acl permissions is different.");
+        softAssert.assertTrue(propertiesEqual(properties.getProperties(), cluster.getProperties().getProperties()),
+            "Cluster properties are different.");
+        softAssert.assertAll();
+    }
+
+    private static boolean checkEquality(String str1, String str2, String message){
+        if (!str1.equals(str2)) {
+            LOGGER.info(String.format("Cluster %s are different: %s and %s.", message, str1, str2));
+            return false;
+        }
+        return true;
+    }
+
+    private static boolean interfacesEqual(List<Interface> srcInterfaces, List<Interface> trgInterfaces) {
+        if (srcInterfaces.size() == trgInterfaces.size()) {
+            boolean equality = false;
+            for(Interface iface1: srcInterfaces){
+                for(Interface iface2 : trgInterfaces) {
+                    if (iface2.getType().value().equals(iface1.getType().value())) {
+                        equality = checkEquality(iface1.getEndpoint(), iface2.getEndpoint(),
+                            iface1.getType().value() + " interface endpoints");
+                        equality &= checkEquality(iface1.getVersion(), iface2.getVersion(),
+                            iface1.getType().value() + " interface versions");
+                    }
+                }
+            }
+            return equality;
+        } else {
+            return false;
+        }
+    }
+
+    private static boolean propertiesEqual(List<Property> srcProps, List<Property> trgProps) {
+        if (srcProps.size() == trgProps.size()) {
+            boolean equality = true;
+            for(Property prop1: srcProps){
+                for(Property prop2 : trgProps) {
+                    if (prop2.getName().equals(prop1.getName())) {
+                        equality &= checkEquality(prop1.getValue(), prop2.getValue(),
+                            prop1.getName() + " property values");
+                    }
+                }
+            }
+            return equality;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Compares two lists of locations.
+     */
+    private static boolean locationsEqual(List<Location> srcLocations, List<Location> objLocations) {
+        if (srcLocations.size() != objLocations.size()) {
+            return false;
+        }
+    nextType:
+        for (ClusterLocationType type : ClusterLocationType.values()) {
+            List<Location> locations1 = new ArrayList<>();
+            List<Location> locations2 = new ArrayList<>();
+            //get locations of the same type
+            for (int i = 0; i < srcLocations.size(); i++) {
+                if (srcLocations.get(i).getName() == type) {
+                    locations1.add(srcLocations.get(i));
+                }
+                if (objLocations.get(i).getName() == type) {
+                    locations2.add(objLocations.get(i));
+                }
+            }
+            //compare locations of the same type. At least 1 match should be present.
+            if (locations1.size() != locations2.size()) {
+                return false;
+            }
+            for (Location location1 : locations1) {
+                for (Location location2 : locations2) {
+                    if (location1.getPath().equals(location2.getPath())) {
+                        continue nextType;
+                    }
+                }
+            }
+            return false;
+        }
+        return true;
+    }
+
+    public List<Location> getLocation(ClusterLocationType type) {
+        List<Location> locationsOfType = new ArrayList<>();
+        for(Location location : locations.getLocations()) {
+            if (location.getName() == type) {
+                locationsOfType.add(location);
+            }
+        }
+        return locationsOfType;
+    }
     @Override
     public EntityType getEntityType() {
         return EntityType.CLUSTER;

http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/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 299be67..4682b6b 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
@@ -48,6 +48,7 @@ public final class MerlinConstants {
     /** Working location to use in cluster xml. */
     public static final String WORKING_LOCATION = Config.getProperty("merlin.working.location",
         "/tmp/falcon-regression-working");
+    public static final String TEMP_LOCATION = Config.getProperty("merlin.temp.location", "/tmp");
 
     public static final String OOZIE_EXAMPLE_LIB = Config.getProperty("merlin.oozie_example_lib",
             "https://repo1.maven.org/maven2/org/apache/oozie/oozie-examples/4.1.0/oozie-examples-4.1.0.jar");

http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/BundleUtil.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/BundleUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/BundleUtil.java
index 7baa7dd..761ebe7 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/BundleUtil.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/BundleUtil.java
@@ -125,6 +125,10 @@ public final class BundleUtil {
                 working.setName(ClusterLocationType.WORKING);
                 working.setPath(MerlinConstants.WORKING_LOCATION);
                 clusterMerlin.getLocations().getLocations().add(working);
+                final Location temp = new Location();
+                temp.setName(ClusterLocationType.TEMP);
+                temp.setPath(MerlinConstants.TEMP_LOCATION);
+                clusterMerlin.getLocations().getLocations().add(temp);
                 final String protectionPropName = "hadoop.rpc.protection";
                 final String protectionPropValue = Config.getProperty(protectionPropName);
                 if (StringUtils.isNotEmpty(protectionPropValue)) {

http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java
index f4befd4..c86fb4b 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/UIAssert.java
@@ -31,7 +31,6 @@ public final class UIAssert {
     }
     private static final Logger LOGGER = Logger.getLogger(UIAssert.class);
 
-
     public static void assertDisplayed(WebElement element, String webElementName) {
         LOGGER.info(String.format("Checking if WebElement '%s' is displayed", webElementName));
         int timeoutSeconds = 2;

http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java
index 3550604..2778dcc 100644
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java
@@ -29,6 +29,8 @@ import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
 import org.openqa.selenium.support.PageFactory;
 
+import java.util.List;
+
 /** Parent page object for all the search ui pages. */
 public abstract class AbstractSearchPage extends Page {
 
@@ -82,4 +84,15 @@ public abstract class AbstractSearchPage extends Page {
         LOGGER.info("angular is done continuing...");
     }
 
+    public String getActiveAlertText() {
+        WebElement alertsBlock = driver.findElement(By.className("messages-to-show"));
+        List<WebElement> alerts = alertsBlock.findElements(By.className("ng-animate"));
+        if (!alerts.isEmpty()) {
+            WebElement last = alerts.get(alerts.size() - 1);
+            if (last.isDisplayed()) {
+                return last.getText();
+            }
+        }
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ClusterWizardPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ClusterWizardPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ClusterWizardPage.java
new file mode 100644
index 0000000..300a3d6
--- /dev/null
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/ClusterWizardPage.java
@@ -0,0 +1,449 @@
+/**
+ * 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.commons.lang.StringUtils;
+import org.apache.falcon.entity.v0.cluster.ACL;
+import org.apache.falcon.entity.v0.cluster.ClusterLocationType;
+import org.apache.falcon.entity.v0.cluster.Interface;
+import org.apache.falcon.entity.v0.cluster.Interfacetype;
+import org.apache.falcon.entity.v0.cluster.Location;
+import org.apache.falcon.entity.v0.cluster.Property;
+import org.apache.falcon.regression.Entities.ClusterMerlin;
+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;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+import org.openqa.selenium.support.FindBys;
+import org.testng.Assert;
+
+import java.util.List;
+
+/** Page object of the Cluster creation page. */
+public class ClusterWizardPage extends AbstractSearchPage {
+    private static final Logger LOGGER = Logger.getLogger(ClusterWizardPage.class);
+    @FindBys({
+        @FindBy(className = "mainUIView"),
+        @FindBy(className = "clusterForm")
+    })
+    private WebElement clusterBox;
+    @FindBy(id = "cluster.step1")
+    private WebElement next;
+    @FindBy(id = "cluster.step2")
+    private WebElement save;
+    @FindBy(id = "cluster.backToStep1")
+    private WebElement previous;
+    @FindBy(xpath = "//a[contains(text(), 'Cancel')]")
+    private WebElement cancel;
+    @FindBy(id = "cluster.editXML")
+    private WebElement editXML;
+    @FindBy(xpath = "//div[contains(@class, 'clusterSummaryRow')][h4]")
+    private WebElement summaryBox;
+    @FindBy(xpath = "//div[contains(@class, 'xmlPreviewContainer')]//textarea")
+    private WebElement xmlPreview;
+
+    public ClusterWizardPage(WebDriver driver) {
+        super(driver);
+    }
+
+    @Override
+    public void checkPage() {
+        UIAssert.assertDisplayed(clusterBox, "Cluster box");
+    }
+
+    /**
+     * Fills cluster setup forms with values retrieved from Filling object.
+     */
+    public void fillForm(ClusterMerlin cluster) {
+        setName(cluster.getName());
+        setColo(cluster.getColo());
+        setDescription(cluster.getDescription());
+        setTags(cluster.getTags());
+        ACL acl = cluster.getACL();
+        setOwner(acl.getOwner());
+        setGroup(acl.getGroup());
+        setPermissions(acl.getPermission());
+        for(Interface iface : cluster.getInterfaces().getInterfaces()) {
+            setInterface(iface);
+        }
+        for (Property property : cluster.getProperties().getProperties()) {
+            addProperty(property.getName(), property.getValue());
+        }
+        setLocations(cluster.getLocations().getLocations());
+    }
+
+    /**
+     * Methods to fill specific wizard fields.
+     */
+    public void setName(String name) {
+        WebElement nameInput = driver.findElement(By.xpath("//div[label[text()='Name']]/input"));
+        nameInput.clear();
+        sendKeysSlowly(nameInput, name);
+    }
+
+    public void setColo(String colo) {
+        WebElement coloInput = clusterBox.findElement(By.xpath("//div[label[text()='Colo']]/input"));
+        coloInput.clear();
+        sendKeysSlowly(coloInput, colo);
+    }
+
+    public void setDescription(String description) {
+        WebElement descriptionInput = clusterBox.findElement(By.xpath("//div[label[text()='Description']]/input"));
+        descriptionInput.clear();
+        sendKeysSlowly(descriptionInput, description);
+    }
+
+    public void setOwner(String owner) {
+        WebElement ownerInput = clusterBox.findElement(By.xpath("//div[label[text()='Owner']]/input"));
+        ownerInput.clear();
+        sendKeysSlowly(ownerInput, owner);
+    }
+
+    public void setGroup(String group) {
+        WebElement groupInput = clusterBox.findElement(By.xpath("//div[label[text()='Group']]/input"));
+        groupInput.clear();
+        sendKeysSlowly(groupInput, group);
+    }
+
+    public void setPermissions(String permissions) {
+        WebElement permissionsInput = clusterBox.findElement(By.xpath("//div[label[text()='Permissions']]/input"));
+        permissionsInput.clear();
+        sendKeysSlowly(permissionsInput, permissions);
+    }
+
+    /**
+     * Common method to fill interfaces.
+     */
+    public void setInterface(Interface iface) {
+        String root = String.format("//div[contains(., '%s')]", iface.getType().value());
+        String xpath = root + "/div/input[contains(@ng-model, '%s')]";
+        WebElement ifaceEndpoint = clusterBox.findElement(By.xpath(String.format(xpath, "_interface._endpoint")));
+        WebElement ifaceVersion = clusterBox.findElement(By.xpath(String.format(xpath, "_interface._version")));
+        ifaceEndpoint.clear();
+        sendKeysSlowly(ifaceEndpoint, iface.getEndpoint());
+        if (iface.getVersion() != null) {
+            ifaceVersion.clear();
+            sendKeysSlowly(ifaceVersion, iface.getVersion());
+        }
+    }
+
+    /**
+     * Populates form with tags.
+     */
+    public void setTags(String tagsStr){
+        if (!StringUtils.isEmpty(tagsStr)) {
+            String [] tags = tagsStr.split(",");
+            for (int i = 0; i < tags.length; i++) {
+                if (i > 0){
+                    clickAddTag();
+                }
+                String key = tags[i].trim().split("=")[0];
+                String value = tags[i].trim().split("=")[1];
+                addTag(key, value);
+            }
+        }
+    }
+
+    /**
+     * Populates last (empty) tag and value fields and creates new fields.
+     * @param key tag key
+     * @param value tag value
+     */
+    public void addTag(String key, String value) {
+        List<WebElement> tagInputs = clusterBox.findElements(By.xpath("//input[@ng-model='tag.key']"));
+        List<WebElement> valueInputs = clusterBox.findElements(By.xpath("//input[@ng-model='tag.value']"));
+        WebElement tagInput = tagInputs.get(tagInputs.size()-1);
+        sendKeysSlowly(tagInput, key);
+        WebElement valueInput = valueInputs.get(valueInputs.size() - 1);
+        sendKeysSlowly(valueInput, value);
+    }
+
+    public void clickAddTag() {
+        clusterBox.findElement(By.xpath("//button[contains(., 'add tag')]")).click();
+    }
+
+    public void clickDeleteTag() {
+        List<WebElement> buttons = clusterBox
+            .findElements(By.xpath("//div[@class='row dynamic-table-spacer ng-scope']//button[contains(.,'delete')]"));
+        buttons.get(buttons.size() - 1).click();
+    }
+
+    /**
+     * Fills property fields and creates new empty property fields.
+     */
+    public void addProperty(String name, String value) {
+        List<WebElement> propInputs = clusterBox.findElements(By.xpath("//input[@ng-model='property._name']"));
+        List<WebElement> valueInputs = clusterBox.findElements(By.xpath("//input[@ng-model='property._value']"));
+        WebElement propInput = propInputs.get(propInputs.size()-1);
+        sendKeysSlowly(propInput, name);
+        WebElement valueInput = valueInputs.get(valueInputs.size()-1);
+        sendKeysSlowly(valueInput, value);
+        clickAddProperty();
+    }
+
+    public void clickAddProperty() {
+        clusterBox.findElement(By.xpath("//button[contains(., 'add property')]")).click();
+    }
+
+    /**
+     * Method to set locations. Location can be only one of ClusterLocationType. So adding new location only after
+     * respective compulsory location was filled.
+     * @param locations locations
+     */
+    public void setLocations(List<Location> locations) {
+        boolean staging = false, temp = false, working = false;
+        for(Location location : locations) {
+            WebElement pathInput = null;
+            if (location.getName() == ClusterLocationType.STAGING && !staging) {
+                pathInput = clusterBox.findElement(By.id("location.staging"));
+                staging = true;
+            } else  if (location.getName() == ClusterLocationType.TEMP && !temp) {
+                pathInput = clusterBox.findElement(By.id("location.temp"));
+                temp = true;
+            } else if (location.getName() == ClusterLocationType.WORKING && !working) {
+                pathInput = clusterBox.findElement(By.id("location.working"));
+                working = true;
+            } else {
+                fillAdditionalLocation(location);
+            }
+            if (pathInput != null) {
+                pathInput.clear();
+                sendKeysSlowly(pathInput, location.getPath());
+            }
+        }
+    }
+
+    /**
+     * Method populates last location fields with values and creates new fields.
+     */
+    public void fillAdditionalLocation(Location location) {
+        List<WebElement> allNameInputs = clusterBox
+            .findElements(By.xpath("//input[contains(@ng-model, 'location._name')]"));
+        sendKeysSlowly(allNameInputs.get(allNameInputs.size() - 1), location.getName().value());
+        List<WebElement> allPathInputs = clusterBox
+            .findElements(By.xpath("//input[contains(@ng-model, 'location._path')]"));
+        sendKeysSlowly(allPathInputs.get(allPathInputs.size() - 1), location.getPath());
+    }
+
+    public void clickAddLocation() {
+        clusterBox.findElement(By.xpath("//button[contains(., 'add location')]")).click();
+    }
+
+    public void clickDeleteLocation() {
+        List<WebElement> buttons = clusterBox
+            .findElements(By.xpath("//div[@class='row ng-scope']//button[contains(.,'delete')]"));
+        Assert.assertFalse(buttons.isEmpty(), "Delete button should be present.");
+        buttons.get(buttons.size() - 1).click();
+    }
+
+    public boolean checkElementByContent(String elementTag, String content) {
+        List<WebElement> elements = clusterBox.findElements(By.xpath("//" + elementTag));
+        for(WebElement element : elements) {
+            if (element.getAttribute("value").equals(content)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public ClusterMerlin getXmlPreview() {
+        //preview block fetches changes slower then they appear on the form
+        TimeUtil.sleepSeconds(1);
+        String previewData = xmlPreview.getAttribute("value");
+        return new ClusterMerlin(previewData);
+    }
+
+    /**
+     * Retrieves hte value of the summary box and parses it to cluster properties.
+     * @param draft empty cluster to contain all properties.
+     * @return cluster filled with properties from the summary.
+     */
+    public ClusterMerlin getSummary(ClusterMerlin draft) {
+        ClusterMerlin cluster = new ClusterMerlin(draft.toString());
+        String summaryBoxText = summaryBox.getText();
+        LOGGER.info("Summary block text : " + summaryBoxText);
+
+        String[] slices;
+        //retrieve basic properties
+        String basicProps = summaryBoxText.split("ACL")[0];
+        for (String line : basicProps.split("\\n")) {
+            slices = line.split(" ");
+            String label = slices[0].replace(":", "").trim();
+            String value = slices[1].trim();
+            switch (label) {
+            case "Name":
+                cluster.setName(value);
+                break;
+            case "Colo":
+                cluster.setColo(value);
+                break;
+            case "Description":
+                cluster.setDescription(value);
+                break;
+            case "Tags":
+                cluster.setTags(value);
+                break;
+            default:
+                break;
+            }
+        }
+        //retrieve ALC
+        String propsLeft = summaryBoxText.split("ACL")[1];
+        String[] acl = propsLeft.split("Interfaces")[0].split(" ");
+        cluster.getACL().setOwner(acl[1]);
+        cluster.getACL().setGroup(acl[3]);
+        cluster.getACL().setPermission(acl[5].trim());
+
+        //retrieve interfaces
+        propsLeft = propsLeft.split("Interfaces")[1];
+        boolean propertiesPresent = propsLeft.contains("Properties");
+        String nextLabel = propertiesPresent ? "Properties" : "Locations";
+        String interfaces = propsLeft.split(nextLabel)[0].trim();
+        for (String line : interfaces.split("\\n")) {
+            slices = line.split(" ");
+            String label = slices[0].replace(":", "").trim();
+            String endpoint = slices[1].trim();
+            String version = slices[3].trim();
+            switch (label) {
+            case "readonly":
+                cluster.addInterface(Interfacetype.READONLY, endpoint, version);
+                break;
+            case "write":
+                cluster.addInterface(Interfacetype.WRITE, endpoint, version);
+                break;
+            case "execute":
+                cluster.addInterface(Interfacetype.EXECUTE, endpoint, version);
+                break;
+            case "workflow":
+                cluster.addInterface(Interfacetype.WORKFLOW, endpoint, version);
+                break;
+            case "messaging":
+                cluster.addInterface(Interfacetype.MESSAGING, endpoint, version);
+                break;
+            case "registry":
+                cluster.addInterface(Interfacetype.REGISTRY, endpoint, version);
+                break;
+            default:
+                break;
+            }
+        }
+        //retrieve properties
+        if (propertiesPresent) {
+            propsLeft = propsLeft.split("Properties")[1];
+            String properties = propsLeft.split("Locations")[0].trim();
+            for (String line : properties.split("\\n")) {
+                slices = line.split(":");
+                cluster.addProperty(slices[0].trim(), slices[1].trim());
+            }
+        }
+        //retrieve locations
+        propsLeft = propsLeft.split("Locations")[1].trim();
+        for (String line : propsLeft.split("\\n")) {
+            slices = line.split(":");
+            String label = slices[0].trim();
+            String path = slices[1].trim();
+            switch (label) {
+            case "staging":
+                cluster.addLocation(ClusterLocationType.STAGING, path);
+                break;
+            case "temp":
+                cluster.addLocation(ClusterLocationType.TEMP, path);
+                break;
+            default:
+                cluster.addLocation(ClusterLocationType.WORKING, path);
+                break;
+            }
+        }
+        return cluster;
+    }
+
+    /**
+     * Clicks on cancel button.
+     */
+    public void cancel() {
+        cancel.click();
+    }
+
+    /**
+     * Clicks on editXml button.
+     */
+    private void clickEditXml() {
+        editXML.click();
+        String disabled = xmlPreview.getAttribute("disabled");
+        Assert.assertEquals(disabled, null, "Xml preview should be enabled.");
+    }
+
+    /**
+     *  Click on next button which is the same as finish step 1.
+     */
+    public void clickNext() {
+        next.click();
+        Assert.assertTrue(summaryBox.isDisplayed(), "Summary box should be displayed.");
+    }
+
+    /**
+     * Click on save button.
+     */
+    public void clickSave() {
+        save.click();
+    }
+
+    /**
+     * Checks whether alert has appeared and does it contains expected message.
+     * @param alertMessage expected message
+     */
+    public void checkSubmissionAlert(boolean shouldSucceed, String alertMessage) {
+        String className = "alert ng-binding bg-danger";
+        if (shouldSucceed) {
+            className = "alert ng-binding bg-success";
+        }
+        waitForElement(String.format("//div[contains(@class, '%s')]", className), DEFAULT_TIMEOUT, "Alert not found.");
+        //alert message is not a content of a div, but is product of the script
+        //so we can't just retrieve it as usually
+        String alertText = ((JavascriptExecutor)driver).executeScript(String.format(
+            "return (function(){return document.getElementsByClassName('%s')[0].textContent;})();",
+            className)).toString().trim();
+        Assert.assertEquals(alertText, alertMessage);
+    }
+
+    /**
+     * Clicks on previous button.
+     */
+    public void clickPrevious() {
+        previous.click();
+        UIAssert.assertDisplayed(clusterBox, "Cluster box");
+    }
+
+    public void checkRegistry() {
+        clusterBox.findElement(By.xpath("//input[@type='checkbox']")).click();
+    }
+
+    /**
+     * Checks whether registry interface is enabled for input or not.
+     */
+    public boolean isRegistryEnabled() {
+        WebElement endpoint = clusterBox.findElement(By.xpath("(//input[@ng-model='_interface._endpoint'])[6]"));
+        WebElement version = clusterBox.findElement(By.xpath("(//input[@ng-model='_interface._version'])[6]"));
+        return endpoint.isEnabled() && version.isEnabled();
+    }
+}

http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/NewClusterPage.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/NewClusterPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/NewClusterPage.java
deleted file mode 100644
index fa8349b..0000000
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/NewClusterPage.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * 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.WebDriver;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.FindBy;
-import org.openqa.selenium.support.FindBys;
-
-/** Page object of the Cluster creation page. */
-public class NewClusterPage extends AbstractSearchPage {
-
-    @FindBys({
-        @FindBy(className = "mainUIView"),
-        @FindBy(className = "clusterForm")
-    })
-    private WebElement clusterBox;
-
-    public NewClusterPage(WebDriver driver) {
-        super(driver);
-    }
-
-    @Override
-    public void checkPage() {
-        UIAssert.assertDisplayed(clusterBox, "Cluster box");
-    }
-}

http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/PageHeader.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/PageHeader.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/PageHeader.java
index 8af6101..c84cfe5 100644
--- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/PageHeader.java
+++ b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/PageHeader.java
@@ -180,12 +180,12 @@ public class PageHeader {
         driver.get(oldUrl);
     }
 
-    public NewClusterPage doCreateCluster() {
+    public ClusterWizardPage doCreateCluster() {
         UIAssert.assertDisplayed(clusterCreateButton, "Cluster create button");
         Assert.assertEquals(clusterCreateButton.getText(), "Cluster",
             "Unexpected text on create cluster button");
         clusterCreateButton.click();
-        final NewClusterPage clusterPage = PageFactory.initElements(driver, NewClusterPage.class);
+        final ClusterWizardPage clusterPage = PageFactory.initElements(driver, ClusterWizardPage.class);
         clusterPage.checkPage();
         return clusterPage;
     }

http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/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 14f0d6c..b3bbeab 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
@@ -158,18 +158,6 @@ public class SearchPage extends AbstractSearchPage {
 
     }
 
-    private String getActiveAlertText() {
-        WebElement alertsBlock = driver.findElement(By.className("messages-to-show"));
-        List<WebElement> alerts = alertsBlock.findElements(By.className("ng-animate"));
-        if (!alerts.isEmpty()) {
-            WebElement last = alerts.get(alerts.size() - 1);
-            if (last.isDisplayed()) {
-                return last.getText();
-            }
-        }
-        return null;
-    }
-
     public SearchQuery getSearchQuery() {
         return new SearchQuery(searchBlock);
     }

http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ClusterSetupTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ClusterSetupTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ClusterSetupTest.java
new file mode 100644
index 0000000..95854ca
--- /dev/null
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/searchUI/ClusterSetupTest.java
@@ -0,0 +1,261 @@
+/**
+ * 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.cluster.ClusterLocationType;
+import org.apache.falcon.entity.v0.cluster.Interface;
+import org.apache.falcon.entity.v0.cluster.Location;
+import org.apache.falcon.entity.v0.cluster.Property;
+import org.apache.falcon.regression.Entities.ClusterMerlin;
+import org.apache.falcon.regression.core.bundle.Bundle;
+import org.apache.falcon.regression.core.helpers.ColoHelper;
+import org.apache.falcon.regression.core.util.BundleUtil;
+import org.apache.falcon.regression.testHelper.BaseUITestClass;
+import org.apache.falcon.regression.ui.search.ClusterWizardPage;
+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.testng.Assert;
+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.net.URISyntaxException;
+import java.util.List;
+
+/**
+ * Tests for cluster setup page.
+ */
+public class ClusterSetupTest extends BaseUITestClass{
+    private ClusterWizardPage clusterSetup = null;
+    private ColoHelper cluster = servers.get(0);
+    private ClusterMerlin sourceCluster;
+
+    @BeforeClass(alwaysRun = true)
+    public void prepareCluster() throws IOException {
+        bundles[0] = BundleUtil.readELBundle();
+        bundles[0] = new Bundle(bundles[0], cluster);
+        bundles[0].generateUniqueBundle(this);
+    }
+
+    @BeforeMethod(alwaysRun = true)
+    public void setup() {
+        openBrowser();
+        SearchPage homePage = LoginPage.open(getDriver()).doDefaultLogin();
+        clusterSetup = homePage.getPageHeader().doCreateCluster();
+        clusterSetup.checkPage();
+        sourceCluster = bundles[0].getClusterElement();
+        //add custom cluster properties
+        sourceCluster.setTags("myTag1=myValue1");
+        sourceCluster.setDescription("description");
+    }
+
+    @Test
+    public void testHeader() {
+        clusterSetup.getPageHeader().checkHeader();
+    }
+
+    /**
+     * Default cluster creation scenario. Populate fields with valid values. Click next. Return back and click
+     * next again. Check that all values are present on Summary page. Save cluster.
+     * Check the cluster definition trough /definition API.
+     */
+    @Test
+    public void testDefaultScenario()
+        throws URISyntaxException, AuthenticationException, InterruptedException, IOException {
+        clusterSetup.fillForm(sourceCluster);
+        clusterSetup.clickNext();
+        clusterSetup.clickPrevious();
+        clusterSetup.clickNext();
+        ClusterMerlin summaryBlock = clusterSetup.getSummary(sourceCluster.getEmptyCluster());
+        //summary block should contain the same info as source
+        sourceCluster.assertEquals(summaryBlock);
+        clusterSetup.clickSave();
+        String alertText = clusterSetup.getActiveAlertText();
+        Assert.assertEquals(alertText, "falcon/default/Submit successful (cluster) " + sourceCluster.getName());
+        ClusterMerlin definition = new ClusterMerlin(cluster.getClusterHelper()
+            .getEntityDefinition(bundles[0].getClusterElement().toString()).getMessage());
+        //definition should be the same that the source
+        sourceCluster.assertEquals(definition);
+    }
+
+    /**
+     * Populate fields with valid values. Check that changes are reflected on XMLPreview block. Click next.
+     * Check that XML is what we have populated on the previous step.
+     */
+    @Test
+    public void testXmlPreview() {
+        clusterSetup.fillForm(sourceCluster);
+        ClusterMerlin generalStepPreview = clusterSetup.getXmlPreview();
+        cleanGeneralPreview(generalStepPreview);
+        sourceCluster.assertEquals(generalStepPreview);
+        clusterSetup.clickNext();
+        ClusterMerlin summaryStepPreview = clusterSetup.getXmlPreview();
+        sourceCluster.assertEquals(summaryStepPreview);
+        generalStepPreview.assertEquals(summaryStepPreview);
+    }
+
+    private void cleanGeneralPreview(ClusterMerlin clusterMerlin) {
+        //On general step xml preview has extra empty values which should be removed to compare data.
+        List<Location> locations = clusterMerlin.getLocations().getLocations();
+        int last = locations.size() - 1;
+        if (locations.get(last).getName() == null && locations.get(last).getPath().isEmpty()) {
+            locations.remove(last);
+        }
+        List<Interface> interfaces = clusterMerlin.getInterfaces().getInterfaces();
+        last = interfaces.size() - 1;
+        if (interfaces.get(last).getEndpoint().isEmpty() && interfaces.get(last).getVersion().isEmpty()) {
+            interfaces.remove(last);
+        }
+        List<Property> properties = clusterMerlin.getProperties().getProperties();
+        last = properties.size() - 1;
+        if (properties.get(last).getName().isEmpty() && properties.get(last).getValue().isEmpty()) {
+            properties.remove(last);
+        }
+    }
+
+    /**
+     * Add location to cluster. Check that it is present. Check XML preview has it.
+     * Delete the location. Check that it has been deleted from wizard window.
+     */
+    @Test
+    public void testAddDeleteLocation() {
+        //to make addLocation button enabled
+        sourceCluster.addLocation(ClusterLocationType.WORKING, "/one-another-temp");
+        clusterSetup.fillForm(sourceCluster);
+
+        //check without extra location
+        ClusterMerlin preview = clusterSetup.getXmlPreview();
+        cleanGeneralPreview(preview);
+        sourceCluster.assertEquals(preview);
+
+        //add one more location to the form and check results
+        String path = "/one-extra-working";
+        Location location = new Location();
+        location.setName(ClusterLocationType.WORKING);
+        location.setPath(path);
+        clusterSetup.clickAddLocation();
+        clusterSetup.fillAdditionalLocation(location);
+        Assert.assertTrue(clusterSetup.checkElementByContent("input", path), "Location should be present.");
+        preview = clusterSetup.getXmlPreview();
+        cleanGeneralPreview(preview);
+        //add location to source to compare equality
+        sourceCluster.addLocation(ClusterLocationType.WORKING, path);
+        sourceCluster.assertEquals(preview);
+
+        //delete location and check results
+        clusterSetup.clickDeleteLocation();
+        Assert.assertFalse(clusterSetup.checkElementByContent("input", path), "Location should be absent.");
+        preview = clusterSetup.getXmlPreview();
+        cleanGeneralPreview(preview);
+        //remove location from source to check equality
+        int last = sourceCluster.getLocations().getLocations().size() - 1;
+        sourceCluster.getLocations().getLocations().remove(last);
+        sourceCluster.assertEquals(preview);
+    }
+
+    /**
+     * Add tag to cluster. Check that it is present. Check XML preview has it.
+     * Delete the tag. Check that it has been deleted from wizard window.
+     */
+    @Test
+    public void testAddDeleteTag() {
+        clusterSetup.fillForm(sourceCluster);
+
+        //check without extra tag
+        ClusterMerlin preview = clusterSetup.getXmlPreview();
+        cleanGeneralPreview(preview);
+        sourceCluster.assertEquals(preview);
+
+        //add one more tag to the form and check results
+        clusterSetup.clickAddTag();
+        clusterSetup.addTag("myTag2", "myValue2");
+        Assert.assertTrue(clusterSetup.checkElementByContent("input", "myTag2"), "Tag should be present");
+        Assert.assertTrue(clusterSetup.checkElementByContent("input", "myValue2"), "Tag should be present");
+        preview = clusterSetup.getXmlPreview();
+        cleanGeneralPreview(preview);
+        //add tag to source to compare equality
+        sourceCluster.setTags("myTag1=myValue1,myTag2=myValue2");
+        sourceCluster.assertEquals(preview);
+
+        //delete location and check results
+        clusterSetup.clickDeleteTag();
+        Assert.assertFalse(clusterSetup.checkElementByContent("input", "myTag2"), "Tag should be absent.");
+        Assert.assertFalse(clusterSetup.checkElementByContent("input", "myValue2"), "Tag should be absent.");
+        preview = clusterSetup.getXmlPreview();
+        cleanGeneralPreview(preview);
+        //remove location from source to check equality
+        sourceCluster.setTags("myTag1=myValue1");
+        sourceCluster.assertEquals(preview);
+    }
+
+    /**
+     * Check that staging interface is unavailable by default but becomes available when we set matching checkbox.
+     */
+    @Test
+    public void testRegistryInterface() {
+        Assert.assertFalse(clusterSetup.isRegistryEnabled(), "Registry should be disabled.");
+        clusterSetup.checkRegistry();
+        Assert.assertTrue(clusterSetup.isRegistryEnabled(), "Registry should be enabled.");
+        clusterSetup.checkRegistry();
+        Assert.assertFalse(clusterSetup.isRegistryEnabled(), "Registry should be disabled again.");
+    }
+
+    /**
+     * Populate working location with value pointing to directory with wider permissions then 755.
+     * Check that user is not allowed to create a cluster and is notified with an alert.
+     */
+    @Test
+    public void testLocationsBadPermissions() throws IOException {
+        //reverse staging and working location dirs
+        String staging = sourceCluster.getLocation(ClusterLocationType.STAGING).get(0).getPath();
+        String working = sourceCluster.getLocation(ClusterLocationType.WORKING).get(0).getPath();
+        sourceCluster.getLocation(ClusterLocationType.WORKING).get(0).setPath(staging);
+        sourceCluster.getLocation(ClusterLocationType.STAGING).get(0).setPath(working);
+        clusterSetup.fillForm(sourceCluster);
+        clusterSetup.clickNext();
+        clusterSetup.clickSave();
+        String alertMessage = clusterSetup.getActiveAlertText();
+        Assert.assertEquals(alertMessage,
+            String.format("Path %s has permissions: rwxrwxrwx, should be rwxr-xr-x", staging));
+    }
+
+    /**
+     * Provide locations which are formally correct but don't exist.
+     * Check that user can't create cluster and has been notified with an alert.
+     */
+    @Test
+    public void testLocationsNonExistent() throws IOException {
+        String nonExistent = "/non-existent-directory";
+        sourceCluster.getLocation(ClusterLocationType.STAGING).get(0).setPath(nonExistent);
+        clusterSetup.fillForm(sourceCluster);
+        clusterSetup.clickNext();
+        clusterSetup.clickSave();
+        String alertMessage = clusterSetup.getActiveAlertText();
+        Assert.assertEquals(alertMessage,
+            String.format("Location %s for cluster %s must exist.", nonExistent, sourceCluster.getName()));
+    }
+
+    @AfterMethod(alwaysRun = true)
+    public void tearDown() throws IOException {
+        removeTestClassEntities();
+        closeBrowser();
+    }
+}

http://git-wip-us.apache.org/repos/asf/falcon/blob/24d28a71/falcon-regression/merlin/src/test/resources/ELbundle/cluster-0.1.xml
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/resources/ELbundle/cluster-0.1.xml b/falcon-regression/merlin/src/test/resources/ELbundle/cluster-0.1.xml
index 6478384..5d8a189 100644
--- a/falcon-regression/merlin/src/test/resources/ELbundle/cluster-0.1.xml
+++ b/falcon-regression/merlin/src/test/resources/ELbundle/cluster-0.1.xml
@@ -25,7 +25,7 @@
 			version="0.20.2" />
 		<interface type="execute" endpoint="hdfs://host:54311" version="0.20.2" />
 		<interface type="workflow" endpoint="http://host:11000/oozie/"
-			version="3.1" />
+			version="3.1.0" />
 		<interface type="messaging" endpoint="tcp://host:61616?daemon=true"
 			version="5.1.6" />
 	</interfaces>