info.magnolia.integrationtests.uitest.SecurityAppUITest.java Source code

Java tutorial

Introduction

Here is the source code for info.magnolia.integrationtests.uitest.SecurityAppUITest.java

Source

/**
 * This file Copyright (c) 2014-2016 Magnolia International
 * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
 *
 *
 * This file is dual-licensed under both the Magnolia
 * Network Agreement and the GNU General Public License.
 * You may elect to use one or the other of these licenses.
 *
 * This file is distributed in the hope that it will be
 * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
 * Redistribution, except as permitted by whichever of the GPL
 * or MNA you select, is prohibited.
 *
 * 1. For the GPL license (GPL), you can redistribute and/or
 * modify this file under the terms of the GNU General
 * Public License, Version 3, as published by the Free Software
 * Foundation.  You should have received a copy of the GNU
 * General Public License, Version 3 along with this program;
 * if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 2. For the Magnolia Network Agreement (MNA), this file
 * and the accompanying materials are made available under the
 * terms of the MNA which accompanies this distribution, and
 * is available at http://www.magnolia-cms.com/mna.html
 *
 * Any modifications to this file must keep this entire header
 * intact.
 *
 */
package info.magnolia.integrationtests.uitest;

import static org.junit.Assert.*;
import static org.openqa.selenium.support.ui.ExpectedConditions.*;

import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

/**
 * UI tests for SecurityApp.
 * <ul>
 * <li>edit standard user</li>
 * <li>edit system user</li>
 * <li>edit group</li>
 * <li>edit role</li>
 * <li>edit public user</li>
 * <li>And try to
 * <ul>
 * <li>create folders</li>
 * <li>copy users/groups/roles</li>
 * <li>move users/groups/roles</li>
 * </ul>
 * </li>
 * </ul>
 */
public class SecurityAppUITest extends AbstractMagnoliaUITest {
    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SecurityAppUITest.class);

    public static final String PUBLIC_USERS_APP_NAME = "Public Users";

    public static final String GROUP = "group";
    public static final String USER = "user";
    public static final String ROLE = "role";

    /*
     * Standard users
     */

    @Test
    public void testAddAndRemoveStandardUser() {
        testAddAndRemoveUser("Users", "test-std-user", "test-password");
    }

    @Test
    public void testEditStandardUser() {
        testEditUser("Users", "peter", "peter1");
    }

    @Test
    public void testCreateFolderAndCopyAndMoveStandardUser() {
        // GIVEN
        openSecuritySubApp("Users");

        // WHEN/THEN
        doTestCreateFolderAndCopyAndMoveSecurityAppItem(USER, "test-folder-move", "peter", "new-test-user-move");
    }

    @Test
    public void testCreateFolderAndCopyAndDragAndDropStandardUser() {
        // GIVEN
        openSecuritySubApp("Users");

        // WHEN/THEN
        doTestCreateFolderAndCopyAndDnDSecurityAppItem(USER, "test-folder-dnd", "peter", "new-test-user-dnd");
    }

    /*
     * System users
     */

    @Test
    public void testAddAndRemoveSystemUser() {
        testAddAndRemoveUser("System Users", "test-sys-user", "test-password");
    }

    @Test
    public void testEditSystemUser() {
        // GIVEN
        addSystemUser("system-user");
        // WHEN / THEN
        testEditUser("System Users", "system-user", "system-user-edit");
        // Cleanup
        deleteSecurityAppItem(USER, "system-user");
    }

    @Test
    public void testCreateFolderCopyAndMoveSystemUser() {
        // GIVEN
        addSystemUser("system-user-move");
        openSecuritySubApp("System Users");

        // WHEN / THEN
        doTestCreateFolderAndCopyAndMoveSecurityAppItem(USER, "test-sys-folder-move", "system-user-move",
                "new-test-sys-user-move");

        // Cleanup
        deleteSecurityAppItem(USER, "system-user-move");
    }

    @Test
    public void testCreateFolderCopyAndDragAndDropSystemUser() {
        // GIVEN
        addSystemUser("system-user-dnd");
        openSecuritySubApp("System Users");

        // WHEN / THEN
        doTestCreateFolderAndCopyAndDnDSecurityAppItem(USER, "test-sys-folder-dnd", "system-user-dnd",
                "new-test-sys-user-dnd");

        // Cleanup
        deleteSecurityAppItem(USER, "system-user-dnd");
    }

    /*
     * Groups
     */

    @Test
    public void testAddAndRemoveGroup() {
        // GIVEN
        final String groupName = "test-group";
        openSecuritySubApp("Groups");

        // WHEN 1
        addSecurityAppItem(GROUP, groupName);

        // THEN 1
        waitUntil(visibilityOfElementLocated(byTreeTableItem(groupName)));

        // WHEN 2
        deleteSecurityAppItem(GROUP, groupName);

        // THEN 2
        waitUntil(elementIsGone(byTreeTableItem(groupName)));
    }

    @Test
    public void testEditGroup() {
        // GIVEN
        final String groupName = "test-group";
        openSecuritySubApp("Groups");
        addSecurityAppItem(GROUP, groupName);
        waitUntil(visibilityOfElementLocated(byTreeTableItem(groupName)));

        // WHEN / THEN
        doTestEditGroup(groupName, groupName + "1");

        // Cleanup
        deleteSecurityAppItem(GROUP, groupName);
    }

    @Test
    public void testCreateFolderCopyAndMoveGroup() {
        // GIVEN
        openSecuritySubApp("Groups");

        // WHEN/THEN
        doTestCreateFolderAndCopyAndMoveSecurityAppItem(GROUP, "test-folder-move", "employees",
                "new-test-group-move");
    }

    @Test
    public void testCreateFolderCopyAndDragAndDropGroup() {
        // GIVEN
        openSecuritySubApp("Groups");
        addSecurityAppItem(GROUP, "group-dnd");

        // WHEN / THEN
        doTestCreateFolderAndCopyAndDnDSecurityAppItem(GROUP, "test-sys-folder-dnd", "group-dnd",
                "new-test-group-dnd");

        // Cleanup
        deleteSecurityAppItem(GROUP, "group-dnd");
    }

    /*
     * Roles
     */

    @Test
    public void testAddAndRemoveRole() {
        // GIVEN
        final String roleName = "test-role";
        openSecuritySubApp("Roles");

        // WHEN 1
        addSecurityAppItem(ROLE, roleName);

        // THEN 1
        waitUntil(visibilityOfElementLocated(byTreeTableItem(roleName)));

        // WHEN 2
        deleteSecurityAppItem(ROLE, roleName);

        // THEN 2
        waitUntil(elementIsGone(byTreeTableItem(roleName)));
    }

    @Test
    public void testEditRole() {
        // GIVEN
        final String roleName = "test-role";
        openSecuritySubApp("Roles");
        addSecurityAppItem(ROLE, roleName);
        waitUntil(visibilityOfElementLocated(byTreeTableItem(roleName)));

        // WHEN / THEN
        doTestEditRole(roleName, roleName + "1");

        // Cleanup
        deleteSecurityAppItem(ROLE, roleName);
    }

    @Test
    public void testCreateFolderCopyAndMoveRole() {
        // GIVEN
        openSecuritySubApp("Roles");
        addSecurityAppItem(ROLE, "role-move");

        // WHEN/THEN
        doTestCreateFolderAndCopyAndMoveSecurityAppItem(ROLE, "test-folder-move", "role-move",
                "new-test-role-move");

        // Cleanup
        deleteSecurityAppItem(ROLE, "role-move");
    }

    @Test
    public void testCreateFolderCopyAndDragAndDropRole() {
        // GIVEN
        openSecuritySubApp("Roles");
        addSecurityAppItem(ROLE, "role-dnd");

        // WHEN / THEN
        doTestCreateFolderAndCopyAndDnDSecurityAppItem(ROLE, "test-sys-folder-dnd", "role-dnd",
                "new-test-role-dnd");

        // Cleanup
        deleteSecurityAppItem(ROLE, "role-dnd");
    }

    /*
     * Public users
     */

    @Test
    public void testAddAndRemovePublicUser() {
        testAddAndRemoveUser(PUBLIC_USERS_APP_NAME, "test-pub-user", "test-password");
    }

    /**
     * Adds a new user and deletes him afterwards.
     */
    private void testAddAndRemoveUser(final String subAppName, final String userName, final String password) {
        // GIVEN
        openSecuritySubApp(subAppName);

        // WHEN 1
        addUser(userName, password);

        // THEN 1
        if (PUBLIC_USERS_APP_NAME.equals(subAppName)) {
            expandTreeAndSelectAnElement(getHierarchicalPath(userName));
        }
        waitUntil(visibilityOfElementLocated(byTreeTableItem(userName)));

        // WHEN 2
        deleteSecurityAppItem(USER, userName);

        // THEN 2
        waitUntil(elementIsGone(byTreeTableItem(userName)));
    }

    private String getHierarchicalPath(String name) {
        final String lcName = name.toLowerCase();
        if (lcName.length() < 3) {
            return "/" + name;
        }
        return "/" + String.valueOf(lcName.charAt(0)) + "/" + StringUtils.left(lcName, 2) + "/" + name;
    }

    /**
     * Edits (renames) an existing user and restores its previous state afterwards.
     */
    private void testEditUser(final String subAppName, final String userName, final String newUserName) {
        // GIVEN
        openSecuritySubApp(subAppName);

        // WHEN 1
        renameSecurityAppItem(USER, userName, newUserName);

        // THEN 1
        waitUntil(visibilityOfElementLocated(byTreeTableItem(newUserName)));

        // WHEN 2
        renameSecurityAppItem(USER, newUserName, userName);

        // THEN 2
        waitUntil(visibilityOfElementLocated(byTreeTableItem(userName)));
        waitUntil(elementIsGone(byTreeTableItem(newUserName)));
    }

    private void doTestEditGroup(String groupName, String newGroupName) {
        // WHEN 1
        renameSecurityAppItem(GROUP, groupName, newGroupName);

        // THEN 1
        waitUntil(visibilityOfElementLocated(byTreeTableItem(newGroupName)));

        // WHEN 2
        renameSecurityAppItem(GROUP, newGroupName, groupName);
        addGroupToGroup(groupName, "developers");
        addRoleToGroup(groupName, "anonymous");

        // THEN 2
        waitUntil(visibilityOfElementLocated(byTreeTableItem(groupName)));
        waitUntil(elementIsGone(byTreeTableItem(newGroupName)));
    }

    private void addRoleToGroup(String groupName, String anonymous) {

    }

    private void addGroupToGroup(String groupName, String developers) {

    }

    private void doTestEditRole(String roleName, String newRoleName) {
        // WHEN 1
        renameSecurityAppItem(ROLE, roleName, newRoleName);

        // THEN 1
        assertTrue(getTreeTableItem(newRoleName).isDisplayed());

        // WHEN 2
        renameSecurityAppItem(ROLE, newRoleName, roleName);

        // THEN 2
        assertTrue(getTreeTableItem(roleName).isDisplayed());
        // TODO: the below generates a 10s delay (getElement() times out then return a NonExistingWebElement impl)
        waitUntil(elementIsGone(byTreeTableItem(newRoleName)));
    }

    /**
     * Creates a folder, renames it, clones an existing item and renames it and uses
     * move dialog to move that new item to the new folder.
     * Removes both afterwards.
     */
    private void doTestCreateFolderAndCopyAndMoveSecurityAppItem(String itemTypeCaption, String folderName,
            String itemNameToCopy, String newItemName) {
        // WHEN
        addFolder(folderName);
        duplicateSecurityAppItem(itemTypeCaption, itemNameToCopy, newItemName);

        waitUntil(visibilityOfElementLocated(byTreeTableItem(newItemName)));

        getActionBarItem(getMoveActionName(itemTypeCaption)).click();
        waitUntil(dialogIsOpen("Move destination"));

        getMoveDialogElement(folderName).click();

        getDialogCommitButton().click();
        waitUntil(dialogIsClosed("Move destination"));

        refreshTreeView();

        // THEN
        waitUntil(visibilityOfElementLocated(byTreeTableItem(newItemName)));

        // Delete user and folder
        deleteSecurityAppItem(itemTypeCaption, newItemName);
        deleteFolder(folderName);

        waitUntil(elementIsGone(byTreeTableItem(folderName)));
    }

    /**
     * Creates a folder, renames it, clones an existing user and renames it and uses
     * drag and drop to move that new user to the new folder.
     * Removes both afterwards.
     */
    private void doTestCreateFolderAndCopyAndDnDSecurityAppItem(String itemTypeCaption, String folderName,
            String itemNameToCopy, String newItemName) {
        // WHEN
        addFolder(folderName);
        duplicateSecurityAppItem(itemTypeCaption, itemNameToCopy, newItemName);
        waitUntil(visibilityOfElementLocated(byTreeTableItem(newItemName)));
        waitUntil(visibilityOfElementLocated(byTreeTableItem(folderName)));

        getTreeTableItemRow(folderName).click(); // TODO: Because of a bug uncovered by the changes from MGNLUI-2927 we have to explicitly ensure that the dnd target is visibly by selecting it.

        dragAndDropElement(getTreeTableItemRow(newItemName), getTreeTableItemRow(folderName));

        // THEN
        By treeExpanderLocator = byTreeTableItemExpander(folderName);
        waitUntil(elementToBeClickable(treeExpanderLocator));
        getElement(treeExpanderLocator).click();
        assertTrue(getTreeTableItem(newItemName).isDisplayed());

        // Delete item and folder
        deleteSecurityAppItem(itemTypeCaption, newItemName);
        deleteFolder(folderName);

        waitUntil(elementIsGone(byTreeTableItem(folderName)));
    }

    /**
     * Adds a folder and renames it.
     * New folder names are always "untitled".
     */
    private WebElement addFolder(String folderName) {
        // Create "untitled" folder
        getActionBarItem("Add folder").click();
        if (!isTreeTableItemSelected("untitled")) {
            getTreeTableItem("untitled").click();
        }

        // Rename folder
        getActionBarItem("Rename folder").click();
        waitUntil(dialogIsOpen("Rename folder"));

        getDialogInputByLabel("Folder Name").clear();
        sendKeysToDialogField("Folder Name", folderName);
        getDialogCommitButton().click();

        waitUntil(dialogIsClosed("Rename folder"));
        assertNotNull(getTreeTableItem(folderName));

        return getTreeTableItemRow(folderName);
    }

    private void sendKeysToDialogField(String fieldName, String keys) {
        WebElement dialogField = getDialogInputByLabel(fieldName);
        sendKeysToDialogField(dialogField, keys);
    }

    private void sendKeysToDialogField(WebElement dialogField, String keys) {
        dialogField.click();
        dialogField.sendKeys(keys);
        dialogField.findElement(By.xpath("..")).click();
    }

    /**
     * Deletes folder (but doesn't check whether it's empty or not).
     */
    private void deleteFolder(String folderName) {
        deleteSecurityAppItem("folder", folderName);
    }

    /**
     * Duplicates a user and renames it.
     */
    private WebElement duplicateSecurityAppItem(String itemTypeCaption, String originalName, String newName) {
        refreshTreeView();
        if (!isTreeTableItemSelected(originalName)) {
            getTreeTableItem(originalName).click();
        }

        // Duplicate user
        getActionBarItem(getDuplicateActionName(itemTypeCaption)).click();

        // Rename user
        renameSecurityAppItem(itemTypeCaption, originalName + "0", newName); // Duplicate item action adds "0" to node name

        assertNotNull(getTreeTableItem(newName));

        // Select the new element
        if (!isTreeTableItemSelected(newName)) {
            getTreeTableItem(newName).click();
        }

        return getTreeTableItemRow(newName);
    }

    /**
     * Adds an user.
     */
    private void addUser(String username, String password) {
        getActionBarItem(getAddItemActionName(USER)).click();
        waitUntil(dialogIsOpen(StringUtils.capitalize(USER)));

        sendKeysToDialogField(getItemNameFieldLabel(USER), username);
        sendKeysToDialogField(getPassword(), password);
        sendKeysToDialogField(getPasswordConfirmation(), password);

        getDialogCommitButton().click();

        waitUntil(dialogIsClosed(StringUtils.capitalize(USER)));
    }

    /**
     * Adds a system user and closes app afterwards.
     */
    private void addSystemUser(String userName) {
        openSecuritySubApp("System Users");

        addUser(userName, userName + "-password");

        closeApp();
    }

    /**
     * Renames existing user.
     */
    private void renameSecurityAppItem(String itemTypeCaption, String itemName, String newItemName) {
        refreshTreeView();
        if (!isTreeTableItemSelected(itemName)) {
            getTreeTableItem(itemName).click();
        }
        getActionBarItem(getEditItemActionName(itemTypeCaption)).click();
        waitUntil(dialogIsOpen(StringUtils.capitalize(itemTypeCaption)));

        getDialogInputByLabel(getItemNameFieldLabel(itemTypeCaption)).clear();
        sendKeysToDialogField(getItemNameFieldLabel(itemTypeCaption), newItemName);

        delay("Let the name change propagate");
        getDialogCommitButton().click();

        waitUntil(dialogIsClosed(StringUtils.capitalize(itemTypeCaption)));
    }

    private String getItemNameFieldLabel(String itemTypeId) {
        return StringUtils.capitalize(itemTypeId) + " name";
    }

    private String getEditItemActionName(String itemTypeCaption) {
        return "Edit " + itemTypeCaption;
    }

    private String getAddItemActionName(String itemTypeCaption) {
        return "Add " + itemTypeCaption;
    }

    private String getDeleteActionName(String itemTypeCaption) {
        return "Delete " + itemTypeCaption;
    }

    private String getMoveActionName(String itemTypeCaption) {
        return "Move " + itemTypeCaption;
    }

    private String getDuplicateActionName(String itemTypeCaption) {
        return "Duplicate " + itemTypeCaption;
    }

    /**
     * Adds arbitrary security app item (user/system user/group/role).
     */
    private void addSecurityAppItem(String itemTypeCaption, String itemName) {
        getEnabledActionBarItem(getAddItemActionName(itemTypeCaption)).click();
        waitUntil(dialogIsOpen(StringUtils.capitalize(itemTypeCaption)));

        sendKeysToDialogField(getItemNameFieldLabel(itemTypeCaption), itemName);

        getDialogCommitButton().click();
        waitUntil(dialogIsClosed(StringUtils.capitalize(itemTypeCaption)));

        // de-select created item
        if (isTreeTableItemSelected(itemName)) {
            getTreeTableItem(itemName).click();
        }
    }

    private void openSecuritySubApp(String subAppName) {
        getAppIcon("Security").click();
        waitUntil(appIsLoaded());
        openTabWithCaption(subAppName);
        waitUntil(tabIsOpen(subAppName));
    }

    /**
     * Deletes a groups.
     */
    private void deleteSecurityAppItem(String itemTypeCaption, String itemName) {
        refreshTreeView();
        if (!isTreeTableItemSelected(itemName)) {
            getTreeTableItem(itemName).click();
        }
        getActionBarItem(getDeleteActionName(itemTypeCaption)).click();
        getDialogConfirmButton().click();

        takeScreenshot("dialog-confirm-button-clicked");

        // Wait until the confirmation dialog is gone and the loading indicator is not visible anymore
        // Using presenceOfAllElementsLocatedBy - we don't want the NoSuchElementException, we want to ensure the list is empty
        waitUntil(
                not(presenceOfAllElementsLocatedBy(By.xpath("//*[contains(@class, 'dialog-root-confirmation')]"))));
        // loading-indicator is always in the dom, we just need to check it's not visible
        waitUntil(not(visibilityOfElementLocated(By.xpath("//*[contains(@class, 'v-loading-indicator')]"))));

        takeScreenshot("dialog-confirm-should-be-gone");

        waitUntil(elementIsGone(byTreeTableItem(itemName)));
    }

    private WebElement getTableBody() {
        return getElementByXpath("//div[contains(@class, 'v-table-row-spacer')]");
    }

    private WebElement getDialogInputByLabel(String label) {
        return getElementByXpath(
                "//div[contains(@class, 'v-form-field-section')]/div[contains(text(), '%s')]/following-sibling::div/input",
                label);
    }

    private WebElement getPasswordContainer() {
        return getElementByXpath(
                "//div[contains(@class, 'v-form-field-section')]/div[contains(text(), 'Password')]/following-sibling::div");
    }

    public WebElement getPassword() {
        return getPasswordContainer().findElement(By.xpath(".//div/div/div[2]/input"));
    }

    public WebElement getPasswordConfirmation() {
        return getPasswordContainer().findElement(By.xpath(".//div/div/div[4]/input"));
    }

}