com.formkiq.web.WorkflowEditorControllerIntegrationTest.java Source code

Java tutorial

Introduction

Here is the source code for com.formkiq.web.WorkflowEditorControllerIntegrationTest.java

Source

/*
 * Copyright (C) 2017 FormKiQ Inc.
 *
 * Licensed 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 com.formkiq.web;

import static com.formkiq.core.api.AbstractRestController.ACCEPT_HEADER_V1;
import static com.formkiq.core.form.bean.ObjectBuilder.STATIC_TEXT_DEFAULT;
import static com.formkiq.core.util.Strings.extractLabelAndValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.formkiq.core.domain.type.FolderFormsListDTO;
import com.formkiq.core.domain.type.FormDTO;
import com.formkiq.core.domain.type.UserDTO;
import com.formkiq.core.form.JSONService;
import com.formkiq.core.form.dto.ArchiveDTO;
import com.formkiq.core.form.dto.FormJSON;
import com.formkiq.core.form.dto.FormJSONFieldType;
import com.formkiq.core.form.dto.Workflow;
import com.formkiq.core.form.dto.WorkflowOutputDocx;
import com.formkiq.core.form.dto.WorkflowOutputFormField;
import com.formkiq.core.form.dto.WorkflowOutputPdfForm;
import com.formkiq.core.service.ArchiveService;
import com.formkiq.core.util.Resources;
import com.formkiq.core.util.Strings;
import com.formkiq.core.util.Zips;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;

/**
 * WorkflowController Edit Integration Test.
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = DEFINED_PORT)
@ActiveProfiles("dev")
public class WorkflowEditorControllerIntegrationTest extends SeleniumTestBase {

    /** ArchiveService. */
    @Autowired
    private ArchiveService archiveService;

    /** {@link JSONService}. */
    @Autowired
    private JSONService jsonService;

    /** OAuth Token. */
    private String token = null;

    /**
     * Add Blank Form.
     */
    private void addBlankForm() {
        click(By.id("button_add_step"));
        click(By.id("button_add_blank_form"));
    }

    /**
     * Add Field to Form.
     * @param type {@link FormJSONFieldType}
     */
    private void addField(final FormJSONFieldType type) {
        WebElement el = findElementBy(By.className("form-section"));
        JavascriptExecutor executor = (JavascriptExecutor) getDriver();
        executor.executeScript("postJSON('/api/flow?execution=' + getExecution() + " + "'&_eventId_fieldadd="
                + el.getAttribute("data-uuid") + ",1&type=" + type + "', null);");
        getDriver().navigate().refresh();
    }

    /**
     * Add New Step.
     * @param event int
     * @param title {@link String}
     */
    private void addNewStep(final int event, final String title) {

        addBlankForm();

        click(By.id("tab_s1e" + event));

        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("fieldeditorform")));

        findElementBy(getBy("input", "data-fieldid", "20")).sendKeys(title);
        //click(By.className("form-modal-update-button"));
        click(By.name("_eventId_next"));

        getWait().until(ExpectedConditions.invisibilityOfElementLocated(By.id("fieldeditorform")));

        assertTrue(findElementBy(By.id("tab_s1e" + event)).getText().endsWith(title));
    }

    /**
     * assert {@link WorkflowOutputPdfFormField}.
     * @param pfield {@link WorkflowOutputPdfFormField}
     * @param form {@link String}
     * @param field {@link String}
     * @param pdffield {@link String}
     */
    private void assertWorkflowOutputFormField(final WorkflowOutputFormField pfield, final String form,
            final String field, final String pdffield) {

        assertEquals(form, pfield.getForm());
        assertEquals(field, pfield.getField());
        assertEquals(pdffield, pfield.getDocumentfieldname());
    }

    @Override
    @Before
    public void before() throws Exception {
        super.before();

        truncateTables("folders");

        this.token = login();
        createFolder(this.token, getDefaultEmail());

        login(getDefaultEmail());
        getDriver().navigate().to(getDefaultHostAndPort() + "/user/dashboard");
        waitForJSandJQueryToLoad();

        assertEquals("FormKiQ Server - Dashboard", getTitle());
    }

    /**
     * Edits a field and checks it's value.
     *
     * @param fieldid {@link String}
     * @param type {@link FormJSONFieldType}
     * @param values {@link Map}
     */
    private void checkEditField(final String fieldid, final FormJSONFieldType type,
            final Map<String, String> values) {

        clickEditFieldButton(fieldid);

        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("fieldeditorform")));

        assertFalse(getDriver().findElement(getBy("select", "data-fieldid", "30")).isDisplayed());

        for (Map.Entry<String, String> e : values.entrySet()) {

            By by = By.xpath("//*[self::textarea|self::input|self::select|self::button]" + "[@data-fieldid='"
                    + e.getKey() + "']");

            String actual = extractLabelAndValue(findElementBy(by).getAttribute("value")).getLeft();

            String expected = extractLabelAndValue(e.getValue()).getLeft();
            assertEquals(expected, actual);
        }
    }

    /**
     * Clicks adding a new workflow.
     */
    private void clickAddNewWorkflow() {
        // when
        findElementBy(By.id("add_workflow")).click();

        // then
        assertEquals("FormKiQ Server - Workflow Editor", getTitle());
    }

    /**
     * Click Edit Field Button.
     * @param fieldid {@link String}
     */
    private void clickEditFieldButton(final String fieldid) {
        waitUntil(new Predicate<WebDriver>() {
            @Override
            public boolean apply(final WebDriver d) {
                try {
                    findElementsBy("button", "data-uuid", fieldid).stream()
                            .filter(s -> s.getAttribute("class").contains("form-field-edit")).findFirst().get()
                            .click();
                    return true;
                } catch (Exception e) {
                    return false;
                }
            }
        });
    }

    /**
     * Click Delete Field Button.
     * @param fieldid {@link String}
     */
    private void clickDeleteFieldButton(final String fieldid) {
        WebElement we = findElementsBy("button", "data-uuid", fieldid).stream()
                .filter(s -> s.getAttribute("class").contains("form-field-delete")).findFirst().get();
        we.click();

        waitUntil(new Predicate<WebDriver>() {
            @Override
            public boolean apply(final WebDriver d) {
                By by = getBy("button", "data-uuid", fieldid);
                return d.findElements(by).isEmpty();
            }
        });
    }

    /**
     * Edits Field.
     *
     * @param fieldid {@link String}
     * @param values {@link Map}
     * @throws InterruptedException InterruptedException
     */
    private void editField(final String fieldid, final Map<String, String> values) throws InterruptedException {

        clickEditFieldButton(fieldid);

        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("fieldeditorform")));

        for (Map.Entry<String, String> e : values.entrySet()) {
            String field = e.getKey();
            String value = e.getValue();

            By by = By.xpath("//*[self::textarea|self::input|self::select|self::button]" + "[@data-fieldid='"
                    + field + "']");

            WebElement element = findElementBy(by);

            assertTrue(element.isDisplayed());
            String tagname = element.getTagName();

            switch (tagname) {
            case "select":
                Select select = new Select(element);
                waitUntilSelectOptionsPopulated(select);
                select.selectByVisibleText(extractLabelAndValue(value).getLeft());
                break;

            case "button":
                element.click();
                break;
            default:
                element.clear();
                element.sendKeys(value);
                break;
            }
        }

        //findElementBy(By.className("form-modal-update-button")).click();
        click(By.name("_eventId_next"));

        getWait().until(ExpectedConditions.invisibilityOfElementLocated(By.id("fieldeditorform")));
    }

    /**
     * Drag and Drop {@link String} elementId to form-context.
     * @param elementId {@link String}
     */
    private void menuDragAndDrop(final String elementId) {
        JavascriptExecutor executor = (JavascriptExecutor) getDriver();
        executor.executeScript("var dataTransferObj = " + "{ setData: function (val) { this.data = val }}\n"
                + "var tget = document.getElementsByClassName" + "('form-section-content')[0];"
                + "var event1 = document.createEvent('MouseEvents');\n"
                + "event1.initEvent('dragstart', true, false);\n" + "document.getElementById('" + elementId
                + "').dispatchEvent(event1);\n" + "" + "var event2 = new CustomEvent('dragover');\n"
                + "event2.dataTransfer=dataTransferObj\n" + "tget.dispatchEvent(event2);\n"
                + "setTimeout(function () {\n" + "var event3 = document.createEvent('MouseEvents');\n"
                + "event3.initEvent('drop', true, false);\n" + "tget.dispatchEvent(event3);\n" + ""
                + "var event4 = document.createEvent('MouseEvents');\n"
                + "event4.initEvent('dragend', true, false);\n" + "tget.dispatchEvent(event4);\n" + "}, 0);\n");
    }

    /**
     * Move Field.
     * @param start {@link String}
     * @param end {@link String}
     */
    private void moveField(final String start, final String end) {
        WebElement el = findElementBy(By.className("form-section"));
        JavascriptExecutor executor = (JavascriptExecutor) getDriver();
        executor.executeScript("postJSON('/api/flow?execution=' + getExecution() + " + "'&_eventId_fieldmove="
                + el.getAttribute("data-uuid") + "," + start + el.getAttribute("data-uuid") + "," + end
                + "', null);");
        getDriver().navigate().refresh();
    }

    /**
     * testAddWorkflow01(). save blank workflow
     *
     * @throws Exception Exceptio
     */
    @Test
    public void testAddWorkflow01() throws Exception {
        // given

        // when
        clickAddNewWorkflow();
        findElementBy(By.id("button_save")).click();

        // then
        String pageSource = getDriver().getPageSource();
        assertTrue(pageSource.contains("At least 1 Form is required"));
    }

    /**
     * testAddWorkflow02(). add workflow, add 0 fields, receive error
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow02() throws Exception {
        // given

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        // then
        assertEquals(getDefaultHostAndPort() + "/user/designer/edit?execution=s1e2", getCurrentUrl());

        // when - add field
        findElementBy(By.id("button_save")).click();

        // then
        assertEquals("FormKiQ Server - Workflow Editor", getTitle());
        assertTrue(getPageSource().contains("At least 1 section is required"));
    }

    /**
     * testAddWorkflow03().
     * add workflow
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow03() throws Exception {
        // given

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        // then
        assertEquals(getDefaultHostAndPort() + "/user/designer/edit?execution=s1e2", getCurrentUrl());

        // when - add field
        menuDragAndDrop("menu-textbox");
        findElementBy(By.id("button_save")).click();

        // then
        assertEquals("FormKiQ Server - Dashboard", getTitle());

        // given
        UserDTO user = getUserDTO(this.token, null);
        String folder = user.getFolders().get(0).getUUID().toString();
        FolderFormsListDTO dto = getFolderFileList(this.token, folder, null);
        assertEquals(1, dto.getForms().size());

        // get file
        byte[] body = getFolderFile(this.token, folder, dto.getForms().get(0).getUUID(),
                MediaType.valueOf(ACCEPT_HEADER_V1 + "+zip"), false).getBody();

        Map<String, byte[]> map = Zips.extractZipToMap(body);
        assertEquals(2, map.size());

        String workflowkey = map.keySet().stream().filter(s -> s.endsWith(".workflow")).findFirst().get();
        String formkey = map.keySet().stream().filter(s -> s.endsWith(".form")).findFirst().get();

        Workflow workflow = this.jsonService.readValue(map.get(workflowkey), Workflow.class);
        assertEquals("New Workflow", workflow.getName());

        FormJSON form = this.jsonService.readValue(map.get(formkey), FormJSON.class);
        assertEquals("New Form", form.getName());
        assertEquals(1, form.getSections().size());
    }

    /**
     * testAddWorkflow04().
     * add static text and then edit..
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow04() throws Exception {
        // given
        FormJSONFieldType type = FormJSONFieldType.STATIC_TEXT;
        ImmutableMap<String, String> values = ImmutableMap.of("70", STATIC_TEXT_DEFAULT);

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-statictext");

        // then
        WebElement e = findElementBy("div", "data-fieldid", "1");
        assertEquals(STATIC_TEXT_DEFAULT, e.getText());
        assertTrue(getPageSource().contains(STATIC_TEXT_DEFAULT));

        checkEditField("1", type, values);
    }

    /**
     * testAddWorkflow05().
     * add Date and then edit..
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow05() throws Exception {
        // given
        FormJSONFieldType typeSelect = FormJSONFieldType.DATE;
        ImmutableMap<String, String> values = ImmutableMap.of("20", "new field", "40", "Immediate[immediate]", "61",
                "", "49", "Date", "50", "Date");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-date");

        // then
        assertTrue(findElementBy("input", "data-fieldid", "1").isDisplayed());

        checkEditField("1", typeSelect, values);
    }

    /**
     * testAddWorkflow06(). add Note and then edit..
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow06() throws Exception {
        // given
        FormJSONFieldType typeSelect = FormJSONFieldType.NOTE;

        ImmutableMap<String, String> values = ImmutableMap.of("20", "new field", "40", "Immediate[immediate]");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-note");

        // then
        assertTrue(findElementBy("textarea", "data-fieldid", "1").isDisplayed());

        checkEditField("1", typeSelect, values);
    }

    /**
     * testAddWorkflow07().
     * add Password and then edit..
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow07() throws Exception {
        // given
        FormJSONFieldType typeSelect = FormJSONFieldType.PASSWORD;
        ImmutableMap<String, String> values = ImmutableMap.of("20", "new field", "40", "Immediate[immediate]");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-password");

        // then
        WebElement element = findElementBy("input", "data-fieldid", "1");
        assertTrue(element.isDisplayed());
        assertEquals("password", element.getAttribute("type"));

        checkEditField("1", typeSelect, values);
    }

    /**
     * testAddWorkflow08().
     * add Photo and then edit..
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow08() throws Exception {
        // given
        FormJSONFieldType typeSelect = FormJSONFieldType.PHOTO;
        ImmutableMap<String, String> values = ImmutableMap.of("20", "new field", "40", "Immediate[immediate]");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-photo");

        // then
        assertTrue(findElementBy("button", "data-fieldid", "1").isDisplayed());

        checkEditField("1", typeSelect, values);
    }

    /**
     * testAddWorkflow09().
     * add Select and then edit..
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow09() throws Exception {
        // given
        FormJSONFieldType typeSelect = FormJSONFieldType.SELECTBOX;
        ImmutableMap<String, String> values = ImmutableMap.of("20", "new field", "40", "Immediate[immediate]", "61",
                "", "60", "", "72", "");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-selectbox");

        // then
        assertTrue(findElementBy("select", "data-fieldid", "1").isDisplayed());

        checkEditField("1", typeSelect, values);
    }

    /**
     * testAddWorkflow10().
     * add Signature Initials and then edit..
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow10() throws Exception {
        // given
        FormJSONFieldType typeSelect = FormJSONFieldType.SIGNATURE_INITIALS;
        ImmutableMap<String, String> values = ImmutableMap.of("20", "new field", "40", "Immediate[immediate]");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-initials");

        // then
        WebElement element = findElementBy("input", "data-fieldid", "1");
        assertTrue(element.isDisplayed());
        assertEquals("XX", element.getAttribute("placeholder"));

        checkEditField("1", typeSelect, values);
    }

    /**
     * testAddWorkflow11().
     * add Signature and then edit..
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow11() throws Exception {
        // given
        FormJSONFieldType typeSelect = FormJSONFieldType.SIGNATURE;
        ImmutableMap<String, String> values = ImmutableMap.of("20", "new field", "40", "Immediate[immediate]");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-signature");

        // then
        WebElement element = findElementBy(By.className("signature-pad"));
        assertTrue(element.isDisplayed());
        assertEquals("", element.getText());

        checkEditField("1", typeSelect, values);
    }

    /**
     * testAddWorkflow12().
     * verify has-error class
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow12() throws Exception {
        // given

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();
        menuDragAndDrop("menu-textbox");

        clickEditFieldButton("1");

        // then
        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("fieldeditorform")));

        // when
        findElementBy(By.id("'FormJSONField'!20")).clear();
        //findElementBy(By.className("form-modal-update-button")).click();
        click(By.name("_eventId_next"));

        // then
        waitUntilClassName(getBy("div", "data-uuid", "20"), "form-group col-xs-12 has-error");
    }

    /**
     * testAddWorkflow13().
     * add textbox and then edit..
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow13() throws Exception {
        // given
        FormJSONFieldType typeSelect = FormJSONFieldType.TEXTBOX;
        ImmutableMap<String, String> values = ImmutableMap.of("20", "new label", "40", "Immediate[immediate]", "44",
                "Numbers[DecimalPad]", "61", "tvariable", "25", "Currency");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-textbox");
        editField("1", values);

        // then
        WebElement element = findElementBy("input", "data-fieldid", "1");
        assertTrue(element.isDisplayed());
        assertEquals("", element.getText());

        checkEditField("1", typeSelect, values);
    }

    /**
     * testAddWorkflow14().
     * add textbox and then edit with custom formatter..
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow14() throws Exception {
        // given
        FormJSONFieldType typeSelect = FormJSONFieldType.TEXTBOX;
        Map<String, String> values = new LinkedHashMap<>();
        values.put("20", "Sample Label");
        values.put("40", "Immediate[immediate]");
        values.put("44", "Numbers[DecimalPad]");
        values.put("25", "Custom");
        values.put("61", "tvariable");
        values.put("24", "(ddd)");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-textbox");
        editField("1", values);

        // then
        WebElement element = findElementBy("input", "data-fieldid", "1");
        assertTrue(element.isDisplayed());

        element.sendKeys("a456");
        assertEquals("(456)", element.getAttribute("value"));

        checkEditField("1", typeSelect, values);
    }

    /**
     * testAddWorkflow15().
     * add formula and then edit.
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow15() throws Exception {
        // given
        FormJSONFieldType typeSelect = FormJSONFieldType.FORMULA;
        ImmutableMap<String, String> values = ImmutableMap.of("20", "Sample Label", "61", "tvariable", "78",
                "12*13");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-formula");
        editField("1", values);

        // then
        WebElement element = findElementBy("input", "data-fieldid", "1");
        assertTrue(element.isDisplayed());
        assertEquals("", element.getText());

        checkEditField("1", typeSelect, values);
    }

    /**
     * testAddWorkflow16().
     * change workflow name.
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow16() throws Exception {
        // given

        // when - add step
        clickAddNewWorkflow();

        findElementBy(By.id("tab_s1e1")).click();

        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("fieldeditorform")));

        findElementBy(By.name("name")).clear();
        findElementBy(By.name("name")).sendKeys("samplewf");
        findElementBy(By.name("21")).click();
        //findElementBy(By.className("form-modal-update-button")).click();
        click(By.name("_eventId_next"));

        // then
        getWait().until(ExpectedConditions.invisibilityOfElementLocated(By.id("fieldeditorform")));

        assertEquals("samplewf", findElementBy(By.id("tab_s1e1")).getText());

        findElementBy(By.id("tab_s1e1")).click();

        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("fieldeditorform")));
        assertEquals("samplewf", findElementBy(By.name("name")).getAttribute("value"));

        assertTrue(findElementBy(By.name("21")).isSelected());
    }

    /**
     * testAddWorkflow17().
     * change form name & step / print steps order.
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow17() throws Exception {
        // given
        String stepsSel = "#steps_table tbody > tr";
        String printstepsSel = "#printsteps_table tbody > tr";

        // when - add step
        clickAddNewWorkflow();

        addBlankForm();

        findElementBy(By.id("tab_s1e2")).click();

        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("fieldeditorform")));

        findElementBy(By.name("name")).sendKeys("samplewf");
        //findElementBy(By.className("form-modal-update-button")).click();
        click(By.name("_eventId_next"));

        // then
        getWait().until(ExpectedConditions.invisibilityOfElementLocated(By.id("fieldeditorform")));

        assertTrue(findElementBy(By.id("tab_s1e2")).getText().endsWith("New Formsamplewf"));

        addBlankForm();

        findElementBy(By.id("tab_s1e1")).click();

        // then
        assertRowEquals(findElements(By.cssSelector(stepsSel)),
                Arrays.asList("Form Name", "New Formsamplewf", "New Form"));
        assertRowEquals(findElements(By.cssSelector(printstepsSel)),
                Arrays.asList("Form Name", "New Formsamplewf", "New Form"));

        // when
        findElementBy(By.id("stepup_0")).click();
        findElementBy(By.id("printstepup_0")).click();

        // then
        assertRowEquals(findElements(By.cssSelector(stepsSel)),
                Arrays.asList("Form Name", "New Formsamplewf", "New Form"));
        assertRowEquals(findElements(By.cssSelector(printstepsSel)),
                Arrays.asList("Form Name", "New Formsamplewf", "New Form"));

        // when
        findElementBy(By.id("stepup_1")).click();
        findElementBy(By.id("printstepup_1")).click();

        // then
        assertRowEquals(findElements(By.cssSelector(stepsSel)),
                Arrays.asList("Form Name", "New Form", "New Formsamplewf"));
        assertRowEquals(findElements(By.cssSelector(printstepsSel)),
                Arrays.asList("Form Name", "New Form", "New Formsamplewf"));

        // when
        findElementBy(By.id("stepdown_0")).click();
        findElementBy(By.id("printstepdown_0")).click();

        // then
        assertRowEquals(findElements(By.cssSelector(stepsSel)),
                Arrays.asList("Form Name", "New Formsamplewf", "New Form"));
        assertRowEquals(findElements(By.cssSelector(printstepsSel)),
                Arrays.asList("Form Name", "New Formsamplewf", "New Form"));

        // when
        findElementBy(By.id("stepdown_1")).click();
        findElementBy(By.id("printstepdown_1")).click();

        // then
        assertRowEquals(findElements(By.cssSelector(stepsSel)),
                Arrays.asList("Form Name", "New Formsamplewf", "New Form"));
        assertRowEquals(findElements(By.cssSelector(printstepsSel)),
                Arrays.asList("Form Name", "New Formsamplewf", "New Form"));
    }

    /**
     * testAddWorkflow18().
     * add 2 textbox and change order
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow18() throws Exception {
        // given
        ImmutableMap<String, String> values0 = ImmutableMap.of("20", "Sample Label", "40", "Immediate[immediate]",
                "44", "Numbers[DecimalPad]", "61", "tvariable", "25", "Currency");

        ImmutableMap<String, String> values1 = ImmutableMap.of("20", "Sample Label2", "40", "Immediate[immediate]",
                "44", "Numbers[DecimalPad]", "61", "tvariable", "25", "Currency");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-textbox");
        editField("1", values0);

        addField(FormJSONFieldType.TEXTBOX);
        editField("2", values1);

        // then
        WebElement element = findElementBy("label", "data-fieldid", "1");
        assertTrue(element.isDisplayed());
        assertEquals("Sample Label", element.getText());

        element = findElementBy("label", "data-fieldid", "2");
        assertTrue(element.isDisplayed());
        assertEquals("Sample Label2", element.getText());

        // when - swap field positions
        moveField("1", "2");

        // then
        assertRowEquals(findElementsWithText(By.xpath("//label[@data-fieldid]")),
                Arrays.asList("Sample Label", "Sample Label2"));
    }

    /**
     * testAddWorkflow19().
     * change section name.
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow19() throws Exception {
        // given
        // when - add step
        clickAddNewWorkflow();
        addBlankForm();
        menuDragAndDrop("menu-textbox");

        findElementBy(By.className("button-section-edit")).click();

        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("fieldeditorform")));

        findElementBy(By.name("title")).sendKeys("samplesection");
        //findElementBy(By.className("form-modal-update-button")).click();
        click(By.name("_eventId_next"));

        // then
        getWait().until(ExpectedConditions.invisibilityOfElementLocated(By.id("fieldeditorform")));

        assertEquals("samplesection", findElementBy(By.className("button-section-edit")).getText().trim());

        // when
        findElementBy(By.className("button-section-edit")).click();

        // then
        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("fieldeditorform")));
        assertEquals("samplesection", findElementBy(By.name("title")).getAttribute("value"));
    }

    /**
     * testAddWorkflow20().
     * set source form
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow20() throws Exception {
        // given
        FormJSONFieldType typeSelect = FormJSONFieldType.TEXTBOX;
        ImmutableMap<String, String> values0 = ImmutableMap.of("20", "Sample Label123", "40",
                "Immediate[immediate]", "25", "Currency");

        // when - add step
        clickAddNewWorkflow();

        addBlankForm();
        findElementBy(By.id("tab_s1e2")).click();

        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("fieldeditorform")));

        findElementBy(getBy("input", "data-fieldid", "20")).sendKeys("samplewf");
        //findElementBy(By.className("form-modal-update-button")).click();
        click(By.name("_eventId_next"));

        // then
        getWait().until(ExpectedConditions.invisibilityOfElementLocated(By.id("fieldeditorform")));

        assertTrue(findElementBy(By.id("tab_s1e2")).getText().endsWith("New Formsamplewf"));

        // when - add field to first form
        menuDragAndDrop("menu-textbox");
        editField("1", values0);

        // given
        ImmutableMap<String, String> values1 = ImmutableMap.of("20", "Sample Label", "40", "Immediate[immediate]",
                "25", "Currency", "81", "New Formsamplewf", "82", "Sample Label123");

        addBlankForm();
        menuDragAndDrop("menu-textbox");
        editField("1", values1);

        // then
        checkEditField("1", typeSelect, values1);
    }

    /**
     * testAddWorkflow21().
     * remove step
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow21() throws Exception {
        // given

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        // then
        assertTrue(getPageSource().contains("tab_s1e2"));

        // when - remove step
        findElementBy(By.id("button-delete-form")).click();

        // then
        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("modal-delete-form-confirm")));

        // when
        findElementBy(By.id("button-delete-form-confirm")).click();

        // then
        assertFalse(getPageSource().contains("tab_s1e2"));
    }

    /**
     * testAddWorkflow22().
     * add/remove static text
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow22() throws Exception {
        // given
        ImmutableMap<String, String> values1 = ImmutableMap.of("20", "Sample Label123", "40",
                "Immediate[immediate]", "25", "Currency");

        ImmutableMap<String, String> values2 = ImmutableMap.of("70", "this is sample text");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-textbox");
        addField(FormJSONFieldType.STATIC_TEXT);

        editField("1", values1);
        editField("2", values2);

        // then
        assertTrue(getPageSource().contains("this is sample text"));

        // when - delete field
        clickDeleteFieldButton("2");

        // then
        waitUntil(new Predicate<WebDriver>() {
            @Override
            public boolean apply(final WebDriver d) {
                return !d.getPageSource().contains("this is sample text");
            }
        });

        // when
        clickDeleteFieldButton("1");

        // then
        waitUntil(new Predicate<WebDriver>() {
            @Override
            public boolean apply(final WebDriver d) {
                try {
                    By by = getBy("button", "data-uuid", "1");
                    d.findElement(by);
                    return false;
                } catch (NoSuchElementException e) {
                    return true;
                }
            }
        });
    }

    /**
     * testAddWorkflow23().
     * add formula and then edit.
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow23() throws Exception {
        // given
        int step = 2;
        ImmutableMap<String, String> values0 = ImmutableMap.of("20", "Sample Label123", "40",
                "Immediate[immediate]", "25", "Currency", "61", "samp");

        // when - add step
        clickAddNewWorkflow();
        addNewStep(step++, "samplewf");

        menuDragAndDrop("menu-textbox");
        editField("1", values0);

        // given
        ImmutableMap<String, String> values1 = ImmutableMap.of("20", "Sample Label", "61", "tvariable", "83",
                "New Formsamplewf", "84", "samp", "85", "");

        // when
        addNewStep(step++, "test");

        menuDragAndDrop("menu-formula");
        editField("1", values1);

        // then
        clickEditFieldButton("1");

        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("fieldeditorform")));

        String actual = findElementBy(By.name("78")).getAttribute("value");
        assertEquals("'New Formsamplewf'!samp", actual);
    }

    /**
     * testAddWorkflow24().
     * add Checkbox and then edit..
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow24() throws Exception {
        // given
        FormJSONFieldType typeSelect = FormJSONFieldType.SWITCH;
        ImmutableMap<String, String> values = ImmutableMap.of("20", "Sample Label", "40", "Immediate[immediate]",
                "61", "tvariable", "60", "option1\noption2");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-switch");
        editField("1", values);

        // then
        assertTrue(findElementBy("input", "data-fieldid", "1").isDisplayed());

        checkEditField("1", typeSelect, values);
    }

    /**
     * testAddWorkflow25().
     * add static text, then add field
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow25() throws Exception {
        // given
        ImmutableMap<String, String> values = ImmutableMap.of("70", "this is sample text");

        // when - add step
        clickAddNewWorkflow();
        addBlankForm();

        menuDragAndDrop("menu-statictext");
        editField("1", values);

        // then
        WebElement e = findElementBy("div", "data-uuid", "1");
        assertEquals("this is sample text", e.getText());

        // when - add field
        addField(FormJSONFieldType.TEXTBOX);

        // then
        e = findElementBy("label", "data-fieldid", "2");
        assertEquals("new field", e.getText());
    }

    /**
     * testAddWorkflow26().
     * edit Workflow Output
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow26() throws Exception {
        // given
        byte[] pdf = Resources.getResourceAsBytes("/sample-form1.pdf");

        // when - add step
        clickAddNewWorkflow();
        findElementBy(By.id("button_add_step")).click();

        JavascriptExecutor executor = (JavascriptExecutor) getDriver();
        executor.executeScript("var myZone, blob, base64Image;\n" + "base64Image = '" + Strings.encode(pdf) + "'\n"
                + "myZone = Dropzone.forElement(document.body);\n"
                + "function base64toBlob(r,e,n){e=e||\"\",n=n||512;for"
                + "(var t=atob(r),a=[],o=0;o<t.length;o+=n){for" + "(var l=t.slice(o,o+n),h=new Array(l.length),"
                + "b=0;b<l.length;b++)h[b]=l.charCodeAt(b);" + "var v=new Uint8Array(h);a.push(v)}"
                + "var c=new Blob(a,{type:e});return c}" + "blob = base64toBlob(base64Image, 'application/pdf');"
                + "blob.name = 'sample.pdf';\n" + "myZone.addFile(blob);");

        // then
        waitUntilPageSourceText("PDF Form Example");

        // when
        findElementBy(By.id("tab_s1e1")).click();
        findElementBy(By.id("output_0")).click();

        // then
        assertTrue(getPageSource().contains("PDF Form Example"));

        // given
        final int index = 5;

        // when
        new Select(findElementBy(By.name("field_1"))).selectByIndex(index);
        findElementBy(By.id("button_save")).click();

        // then
        assertEquals("FormKiQ Server - Dashboard", getTitle());

        // given
        String ttoken = login();
        UserDTO user = getUserDTO(ttoken, null);
        String folder = user.getFolders().get(0).getUUID().toString();

        // when
        FolderFormsListDTO dto = getFolderFileList(ttoken, folder, null);

        // then
        assertFalse(dto.getForms().isEmpty());

        // given
        FormDTO fdto = Collections.max(dto.getForms(), Comparator.comparing(s -> s.getInserteddate()));

        String uuid = fdto.getUUID();

        // when
        byte[] data = getFolderFile(ttoken, folder, uuid, MediaType.valueOf(ACCEPT_HEADER_V1 + "+zip"), false)
                .getBody();
        ArchiveDTO archive = this.archiveService.extractJSONFromZipFile(data);

        // then
        WorkflowOutputPdfForm o = (WorkflowOutputPdfForm) archive.getWorkflow().getOutputs().get(0);
        List<WorkflowOutputFormField> pfields = o.getFields();
        String formname = "PDF Form Example[" + archive.getForms().values().iterator().next().getUUID() + "]";

        int i = 0;
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Given Name:[1]", "Given Name Text Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Address 2:[5]", "Family Name Text Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Address 1:[3]", "Address 1 Text Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "House nr:[4]", "House nr Text Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Address 2:[5]", "Address 2 Text Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Postcode:[6]", "Postcode Text Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "City:[7]", "City Text Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Country:[8]", "Country Combo Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Gender:[9]", "Gender List Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Height (cm):[10]", "Height Formatted Field");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Driving License:[11]",
                "Driving License Check Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Deutsch[12]", "Language 1 Check Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "English[13]", "Language 2 Check Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Franais[14]", "Language 3 Check Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Esperanto[15]", "Language 4 Check Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Latin[16]", "Language 5 Check Box");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Favourite colour:[17]",
                "Favourite Colour List Box");
    }

    /**
     * testAddWorkflow27().
     * edit DOCX Workflow Output
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow27() throws Exception {
        // given
        String docname = "sample1.docx";
        byte[] dat = Resources.getResourceAsBytes("/" + docname);

        // when - add step
        clickAddNewWorkflow();
        findElementBy(By.id("button_add_step")).click();

        JavascriptExecutor executor = (JavascriptExecutor) getDriver();
        executor.executeScript("var myZone, blob, base64Image;\n" + "base64Image = '" + Strings.encode(dat) + "'\n"
                + "myZone = Dropzone.forElement(document.body);\n"
                + "function base64toBlob(r,e,n){e=e||\"\",n=n||512;for"
                + "(var t=atob(r),a=[],o=0;o<t.length;o+=n){for" + "(var l=t.slice(o,o+n),h=new Array(l.length),"
                + "b=0;b<l.length;b++)h[b]=l.charCodeAt(b);" + "var v=new Uint8Array(h);a.push(v)}"
                + "var c=new Blob(a,{type:e});return c}" + "blob = base64toBlob(base64Image, 'application/pdf');"
                + "blob.name = '" + docname + "';" + "myZone.addFile(blob);");

        // then
        assertEquals("sample1", findElementBy(By.id("tab_s1e2")).getText().trim());

        // when
        findElementBy(By.id("tab_s1e1")).click();
        findElementBy(By.id("output_0")).click();

        // then
        assertTrue(getPageSource().contains("sample"));
        WebElement select = findElementBy(By.name("outputDocumentType"));
        assertEquals("DOCX,PDF", select.getText().trim().replaceAll("[\\s]+", ","));
        assertEquals("DOCX", new Select(select).getFirstSelectedOption().getText());

        // given
        final int index = 5;

        // when
        new Select(select).selectByValue("PDF");
        new Select(findElementBy(By.name("field_1"))).selectByIndex(index);
        findElementBy(By.id("button_save")).click();

        // then
        assertEquals("FormKiQ Server - Dashboard", getTitle());

        // given
        String ttoken = login();
        UserDTO user = getUserDTO(ttoken, null);
        String folder = user.getFolders().get(0).getUUID().toString();

        // when
        FolderFormsListDTO dto = getFolderFileList(ttoken, folder, null);

        // then
        assertFalse(dto.getForms().isEmpty());

        // given
        FormDTO fdto = Collections.max(dto.getForms(), Comparator.comparing(s -> s.getInserteddate()));

        String uuid = fdto.getUUID();

        // when
        byte[] data = getFolderFile(ttoken, folder, uuid, MediaType.valueOf(ACCEPT_HEADER_V1 + "+zip"), false)
                .getBody();
        ArchiveDTO archive = this.archiveService.extractJSONFromZipFile(data);

        // then
        WorkflowOutputDocx o = (WorkflowOutputDocx) archive.getWorkflow().getOutputs().get(0);
        List<WorkflowOutputFormField> pfields = o.getFields();
        String formname = "sample1[" + archive.getForms().values().iterator().next().getUUID() + "]";

        int i = 0;
        assertWorkflowOutputFormField(pfields.get(i++), formname, "DAY[1]", "DAY");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Trade Name[5]", "Month");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Year[3]", "Year");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "LegalName[4]", "LegalName");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Trade Name[5]", "Trade Name");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "ADDRESS[6]", "ADDRESS");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "SUITE[7]", "SUITE");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "CITY[8]", "CITY");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "PROVINCE[9]", "PROVINCE");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "POSTALCODE[10]", "POSTALCODE");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "FAX NUMBER[11]", "FAX NUMBER");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "CONTACT NAME[12]", "CONTACT NAME");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "CONTACT TITLE[13]", "CONTACT TITLE");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "EMAIL[14]", "EMAIL");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Lease Date[15]", "Lease Date");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Driver's License[16]", "Driver's License");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Passport[17]", "Passport");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "Checkbox[18]", "Checkbox");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "SIG[19]", "SIG");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "PRINT NAME[20]", "PRINT NAME");
        assertWorkflowOutputFormField(pfields.get(i++), formname, "TITLE[21]", "TITLE");
    }

    /**
     * testAddWorkflow28().
     * add ID Barcode Form
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow28() throws Exception {
        // given

        // when - add step
        clickAddNewWorkflow();
        findElementBy(By.id("button_add_step")).click();
        findElementBy(By.id("button_add_idbarcode_form")).click();

        // then
        assertEquals(getDefaultHostAndPort() + "/user/designer/edit?execution=s1e2", getCurrentUrl());

        assertEquals("ID", findElementBy("label", "data-fieldid", "2").getText());
        assertTrue(findElementBy("input", "data-fieldid", "2").isDisplayed());
    }

    /**
     * testAddWorkflow29().
     * add Equifax Form
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow29() throws Exception {
        // given

        // when - add step
        clickAddNewWorkflow();
        findElementBy(By.id("button_add_step")).click();
        findElementBy(By.id("button_add_equifax_form")).click();

        // then
        assertEquals(getDefaultHostAndPort() + "/user/designer/edit?execution=s1e2", getCurrentUrl());

        assertEquals("First Name", findElementBy("label", "data-fieldid", "2").getText());
        assertTrue(findElementBy("input", "data-fieldid", "2").isDisplayed());
        assertTrue(findElementBy("select", "data-fieldid", "30").isDisplayed());

        assertNoSuchElement(getBy("input", "data-fieldid", "40"));
    }

    /**
     * Cancel Editor Button.
     *
     * @throws Exception Exception
     */
    @Test
    public void testAddWorkflow30() throws Exception {
        // given

        // when
        clickAddNewWorkflow();
        click(By.id("button-cancel"));

        // then
        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("form-modal")));

        // when
        click(By.className("form-modal-close-button"));

        // then
        getWait().until(ExpectedConditions.invisibilityOfElementLocated(By.id("form-modal")));

        // when
        click(By.id("button-cancel"));

        // then
        getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("form-modal")));

        // when
        click(By.className("form-modal-cancel-button"));

        // then
        assertEquals(getDefaultHostAndPort() + "/user/dashboard/index", getCurrentUrl());
    }

    // TODO add label to edit from workflow
    // TODO add Barcode Form
    // TODO Formula Builder test invalid formula

    // TODO WORKFLOW Outputs
    // TODO verify edit permission to see edit link

    // TODO handle FlowEndedException if change URL to past eventid
}