com.formkiq.web.WorkflowAddControllerIntegrationTest.java Source code

Java tutorial

Introduction

Here is the source code for com.formkiq.web.WorkflowAddControllerIntegrationTest.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.FormFinder.findField;
import static com.formkiq.core.form.FormFinder.findValueByKey;
import static com.formkiq.core.form.bean.ObjectBuilder.buildArchiveDTO;
import static com.formkiq.core.util.Resources.getResourceAsString;
import static com.formkiq.core.util.Strings.CHARSET_UTF8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang3.tuple.Pair;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Action;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
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.QueueDTO;
import com.formkiq.core.domain.type.QueueListDTO;
import com.formkiq.core.domain.type.UserDTO;
import com.formkiq.core.equifax.service.EquifaxServiceLocal;
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.FormJSONField;
import com.formkiq.core.form.dto.FormJSONFieldType;
import com.formkiq.core.form.dto.FormJSONSection;
import com.formkiq.core.form.dto.Workflow;
import com.formkiq.core.service.ArchiveService;
import com.formkiq.core.service.generator.pdfbox.PdfEditorServiceImpl;
import com.formkiq.core.service.queue.DocSignQueueMessage;
import com.formkiq.core.service.workflow.WorkflowEditorService;
import com.formkiq.core.testdata.TestDataBuilder;
import com.formkiq.core.util.Resources;
import com.formkiq.core.util.Strings;
import com.formkiq.core.util.Zips;
import com.formkiq.core.webflow.WebFlow;

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

    /** Sample Form 2 Title. */
    private static final String SAMPLE_FORM2 = "Public Service Health Care " + "Plan (PSHCP) Claim Form";

    /** Sample Form 2 Title. */
    private static final String SAMPLE_FORM_2_HTML_TITLE = "FormKiQ Server - " + SAMPLE_FORM2;

    /** JSON Default Format. */
    private SimpleDateFormat jsonDateFormat = new SimpleDateFormat(JSONService.DEFAULT_DATE_FORMAT);

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

    /** {@link EquifaxServiceLocal}. */
    @Autowired
    private EquifaxServiceLocal equifaxService;

    /** JSONService. */
    @Autowired
    private JSONService jsonService;

    /** {@link PdfEditorServiceImpl}.*/
    @Autowired
    private PdfEditorServiceImpl pdfEditorService;

    /** {@link WorkflowEditorService}. */
    @Autowired
    private WorkflowEditorService workflowEditorService;

    /**
     * Assert FormJSONField.
     * @param field {@link FormJSONField}
     * @param id int
     * @param label {@link String}
     * @param type {@link String}
     * @param value {@link String}
     */
    private void assertField(final FormJSONField field, final int id, final String label,
            final FormJSONFieldType type, final String value) {
        assertEquals(id, field.getId());
        assertEquals(label, field.getLabel());
        assertEquals(type, field.getType());
        assertEquals(value, field.getValue());
    }

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

        truncateTables("folders", "folder_forms");
    }

    /**
     * Logs in and click the first workflow.
     */
    private void clickCreateWorkflow() {
        login(getDefaultEmail());
        getDriver().navigate().to(getDefaultHostAndPort() + "/user/dashboard");
        waitForJSandJQueryToLoad();

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

        findElementBy(By.id("add_entry_0")).click();
    }

    /**
     * Fill Docsign Form.
     */
    private void fillDocsign() {
        findElementBy(By.name("2")).sendKeys("jacksmith@formkiq.com");
        findElementBy(By.name("3")).sendKeys("Jack Smith");
        findElementBy(By.name("4")).sendKeys("sign this");
        findElementBy(By.name("5")).sendKeys("John Smith");
    }

    /**
     * fill Schedule B.
     */
    private void fillScheduleB() {
        findElementBy(By.name("2")).sendKeys("10");
        findElementBy(By.name("3")).sendKeys("111");
        findElementBy(By.name("4")).sendKeys("2222222");
        findElementBy(By.name("5")).sendKeys("33333");
        findElementBy(By.name("6")).sendKeys("123 Main St.");
    }

    /**
     * Fill Signature.
     * @param datafieldid {@link String}
     */
    private void fillSignature(final String datafieldid) {

        WebElement element = findElementBy("canvas", "data-fieldid", datafieldid);

        final int startXY = 50;
        Actions builder = new Actions(getDriver());
        Action drawAction = builder.moveToElement(element, startXY, startXY).clickAndHold()
                .moveByOffset(startXY, startXY).release().build();
        drawAction.perform();
    }

    /**
     * Find Href URL in string.
     * @param s {@link String}
     * @return {@link String}
     */
    private String findHrefUrl(final String s) {
        Pattern p = Pattern.compile("href=\"(.*?)\"");
        Matcher m = p.matcher(s);
        String url = null;
        if (m.find()) {
            url = m.group(1); // this variable should contain the link URL
        }

        return url;
    }

    /**
     * Find the index position for {@link FormJSONFieldType}.
     * @param type {@link FormJSONFieldType}
     * @return int
     */
    private int findIndex(final FormJSONFieldType type) {
        return Arrays.asList(FormJSONFieldType.values()).indexOf(type) + 1;
    }

    /**
     * Get Submit Buttons.
     * @return {@link List}
     */
    private List<WebElement> getSubmitButtons() {
        List<WebElement> elements = getDriver().findElements(By.xpath("//*[@type='submit']"));
        return elements;
    }

    /**
     * Click Submit Button by name.
     * @param name {@link String}
     * @param text {@link String}
     */
    private void submitByName(final String name, final String text) {
        submitByName(name, text, TIMEOUT);
    }

    /**
     * Click Submit Button by name.
     * @param name {@link String}
     * @param text {@link String}
     * @param timeout long
     */
    private void submitByName(final String name, final String text, final long timeout) {

        List<WebElement> elements = getSubmitButtons();
        for (WebElement element : elements) {
            if (name.equals(element.getAttribute("name"))) {
                assertEquals(text, element.getText());
                element.click();
                break;
            }
        }
    }

    /**
     * testWorkflow01().
     * get workflow as ADMIN
     * @throws Exception Exception
     */
    @Test
    public void testCreateWorkflow01() throws Exception {
        // given
        final long sleep = 250L;
        FormJSON form = TestDataBuilder.createStoreReceipt();
        Workflow workflow = TestDataBuilder.createWorkflow(form);

        String token = login();
        String folder = createFolder(token, getDefaultEmail());

        addFileToFolder(token, folder, workflow, form);

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

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

        findElementBy(By.className("add_0")).click();

        // then (verify on correct page)
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Store Receipt", getTitle());

        // when (enter data)
        WebElement element = findElementBy(By.name("1"));
        element.sendKeys("10");

        element = findElementBy(By.name("1"));
        assertEquals("10", element.getAttribute("value"));

        JavascriptExecutor jsExecutor = (JavascriptExecutor) getDriver();
        jsExecutor.executeScript("calculate();", element);

        Thread.sleep(sleep);

        getDriver().navigate().refresh();

        // then (verify data calculations)
        element = findElementBy(By.name("2"));
        assertEquals("$0.70", element.getAttribute("value"));

        element = findElementBy(By.name("3"));
        assertEquals("$7.99", element.getAttribute("value"));

        element = findElementBy(By.name("4"));
        assertEquals("$18.69", element.getAttribute("value"));

        List<WebElement> elements = getSubmitButtons();
        assertEquals(1, elements.size());

        // when (submit)
        submitByName("_eventId_next", "Next");

        // then verify complete
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e2", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Sample WF Complete", getTitle());

        assertTrue(getDriver().getPageSource().contains("end-of-document"));

        String pageSource = getDriver().getPageSource();
        assertTrue(pageSource.contains("The workflow has been saved."));

        FolderFormsListDTO formlist = getFolderFileList(token, folder, workflow.getUUID());

        assertEquals(1, formlist.getForms().size());
        FormDTO fdto = formlist.getForms().get(0);
        assertNotEquals(workflow.getUUID(), fdto.getUUID());

        byte[] data = getFolderFile(token, folder, fdto.getUUID(), MediaType.valueOf(ACCEPT_HEADER_V1 + "+zip"),
                false).getBody();
        ArchiveDTO archive = this.archiveService.extractJSONFromZipFile(data);
        workflow = archive.getWorkflow();

        assertNotNull(workflow);
        assertEquals(1, archive.getForms().size());
        form = archive.getForms().values().iterator().next();

        assertTrue(workflow.getSteps().contains(form.getUUID()));
        assertEquals(workflow.getParentUUID(), form.getParentUUID());

        int i = 1;
        assertEquals("$10.00", findField(form, i++).get().getValue());
        assertEquals("$0.70", findField(form, i++).get().getValue());
        assertEquals("$7.99", findField(form, i++).get().getValue());
        assertEquals("$18.69", findField(form, i++).get().getValue());
    }

    /**
     * testWorkflow02().
     * save form but fails validation
     * @throws Exception Exception
     */
    @Test
    public void testCreateWorkflow02() throws Exception {
        // given
        FormJSON form = TestDataBuilder.createStoreReceipt();
        Workflow workflow = TestDataBuilder.createWorkflow(form);

        String token = login();
        String folder = createFolder(token, getDefaultEmail());

        addFileToFolder(token, folder, workflow, form);

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

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

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

        // then (verify on correct page)
        assertEquals("FormKiQ Server - Store Receipt", getTitle());

        // when (enter data)
        submitByName("_eventId_next", "Next");

        // then verify summary
        assertNotEquals("FormKiQ Server - Workflow Sample WF", getTitle());
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());

        String pageSource = getDriver().getPageSource();
        assertFalse(pageSource.contains("end-of-document"));

        List<WebElement> elements = getDriver().findElements(By.xpath("//*[@class='fa fa-exclamation-circle']"));
        assertEquals(form.getSections().get(0).getFields().size(), elements.size());
        assertEquals("Field required", elements.get(0).getText());
    }

    /**
     * testWorkflow03().
     * Fill Form, Press Next then change URL to previous form
     * @throws Exception Exception
     */
    @Test
    public void testCreateWorkflow03() throws Exception {
        // given
        FormJSON form0 = TestDataBuilder.createStoreReceipt();
        FormJSON form1 = TestDataBuilder.createSimpleForm();
        Workflow workflow = TestDataBuilder.createWorkflow(form0, form1);

        String token = login();
        String folder = createFolder(token, getDefaultEmail());

        addFileToFolder(token, folder, workflow, form0, form1);

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

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

        findElementBy(By.className("add_0")).click();

        // then (verify on correct page)
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Store Receipt", getTitle());

        // when (enter data)
        WebElement element = findElementBy(By.name("1"));
        element.sendKeys("10");
        findElementBy(By.id("nextbutton")).click();

        // then verify summary
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e2", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Simple Form", getTitle());

        // when move to previous page
        findElementBy(By.id("previousbutton")).click();

        // then verify summary
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Store Receipt", getTitle());
    }

    /**
     * testCreateWorkflow04().
     * test all fields
     * @throws Exception Exception
     */
    @Test
    public void testCreateWorkflow04() throws Exception {
        // given
        String sigtext = getResourceAsString("/signature.txt");
        FormJSON form = TestDataBuilder.createAllFields();
        Workflow workflow = TestDataBuilder.createWorkflow(form);

        String token = login();
        String folder = createFolder(token, getDefaultEmail());

        addFileToFolder(token, folder, workflow, form);

        clickCreateWorkflow();

        // then (verify on correct page)
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - All Forms", getTitle());

        // given
        // checkbox
        findElementByName("" + (findIndex(FormJSONFieldType.SWITCH))).click();

        // date
        findElementByName("" + (findIndex(FormJSONFieldType.DATE))).sendKeys("2017/07/05");

        // note
        findElementByName("" + (findIndex(FormJSONFieldType.NOTE))).sendKeys("This\nis\nthe\nsample\ntext\ndata.");

        // password
        findElementByName(FormJSONFieldType.PASSWORD.name()).sendKeys("pass");

        // photo
        JavascriptExecutor js = (JavascriptExecutor) getDriver();
        js.executeScript("document.getElementById(\"'All Forms'!" + (findIndex(FormJSONFieldType.PHOTO))
                + "\").value = '" + sigtext + "'");

        // selectbox
        selectByIndex("" + (findIndex(FormJSONFieldType.SELECTBOX)), 1);

        // signature
        fillSignature("" + (findIndex(FormJSONFieldType.SIGNATURE)));

        // initials
        findElementByName("" + (findIndex(FormJSONFieldType.SIGNATURE_INITIALS))).sendKeys("MF");

        // input
        findElementByName(FormJSONFieldType.TEXTBOX.name()).sendKeys("Sample Input field");

        // when
        submitByName("_eventId_next", "Next");

        // then verify summary
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e2", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Sample WF Complete", getTitle());
    }

    /**
     * testCreateWorkflow05().
     * test all fields required, Press Next verify page,
     * then change URL to event 2
     * @throws Exception Exception
     */
    @Test
    public void testCreateWorkflow05() throws Exception {
        // given
        FormJSON form = TestDataBuilder.createAllFields();
        Workflow workflow = TestDataBuilder.createWorkflow(form);

        String token = login();
        String folder = createFolder(token, getDefaultEmail());

        addFileToFolder(token, folder, workflow, form);

        clickCreateWorkflow();

        // then (verify on correct page)
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - All Forms", getTitle());

        // when
        submitByName("_eventId_next", "Next");

        // then (verify on correct page)
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - All Forms", getTitle());

        // when
        getDriver().navigate().to(getDefaultHostAndPort() + "/flow/workflow?execution=s1e2");

        // then (verify on correct page)
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - All Forms", getTitle());
    }

    /**
     * testCreateWorkflow06().
     * test idbarcode type , Press Next verify page,
     * @throws Exception Exception
     */
    @Test
    public void testCreateWorkflow06() throws Exception {
        // given
        FormJSON form = TestDataBuilder.createIdBarcode();
        Workflow workflow = TestDataBuilder.createWorkflow(form);

        String token = login();
        String folder = createFolder(token, getDefaultEmail());

        addFileToFolder(token, folder, workflow, form);

        clickCreateWorkflow();

        // then (verify on correct page)
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Sample WF Complete", getTitle());
    }

    /**
     * testCreateWorkflow07().
     * test invalid built in type,
     * @throws Exception Exception
     */
    @Test
    public void testCreateWorkflow07() throws Exception {
        // given
        FormJSON form = TestDataBuilder.createIdBarcode();
        form.setBuiltintype("FJKSDFDSF");
        Workflow workflow = TestDataBuilder.createWorkflow(form);

        String token = login();
        String folder = createFolder(token, getDefaultEmail());

        addFileToFolder(token, folder, workflow, form);

        clickCreateWorkflow();

        // then (verify on correct page)
        assertEquals(getDefaultHostAndPort() + "/flow/notsupported.html", getDriver().getCurrentUrl());
        assertEquals("Workflow not Supported", getTitle());
        String pageSource = getDriver().getPageSource();
        assertTrue(pageSource.contains("Workflow is not supported"));
    }

    /**
     * TODO route testCreateWorkflow11 to email to signature.
     * testCreateWorkflow08().
     * test Docsign workflow
     * @throws Exception Exception
     */
    @Test
    @Ignore
    public void testCreateWorkflow08() throws Exception {
        //given
        FormJSON f0 = TestDataBuilder.createScheduleB();
        FormJSON f1 = TestDataBuilder.createDocSign();
        Workflow workflow = TestDataBuilder.createWorkflow(f0, f1);
        workflow.setPrintsteps(Arrays.asList(f0.getUUID()));

        String token = login();
        String folder = createFolder(token, getDefaultEmail());
        UserDTO user = getUserDTO(token, null);
        String userid = user.getUUID().toString();

        addFileToFolder(token, folder, workflow, f0, f1);

        // when
        clickCreateWorkflow();

        // then (verify on correct page)
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Schedule B", getTitle());

        assertEquals(f0.getSections().get(1).getFields().size(),
                getDriver().findElements(By.className("col-xs-12")).size());
        assertEquals(2, getDriver().findElements(By.className("col-xs-6")).size());

        // when
        fillScheduleB();

        submitByName("_eventId_next", "Next");

        // then
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e2", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Submit for Signing", getTitle());

        // when
        fillDocsign();

        submitByName("_eventId_next", "Next");

        // then
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e3", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Sample WF Complete", getTitle());

        // when (goto summary -> complete)
        submitByName("_eventId_next", " Submit for Signature");

        // then
        String pageSource = getDriver().getPageSource();
        assertTrue(pageSource.contains("The workflow has been saved."));
        assertNotNull(findElementBy(By.id("pdfbutton")));

        // verify email is sent for signing
        verifyFolderFileList(token, folder, workflow, "ROUTED", "Sample WF");
        Pair<QueueDTO, DocSignQueueMessage> pair = verifyQueueMessage(token, userid, folder);

        String signUrl = verifyDocsignEmail();
        assertEquals(
                "https://www.formkiq.com/flow/sign/" + pair.getRight().getFormid() + "/" + pair.getLeft().getUUID(),
                signUrl);

        logout();

        // given
        signUrl = signUrl.replaceAll("https://www.formkiq.com", getDefaultHostAndPort());

        // when (sign document)
        getDriver().navigate().to(signUrl);

        // then
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Sample WF Summary", getTitle());
        assertEquals(2, getDriver().findElements(By.className("col-xs-6")).size());

        // when (submit missing signtures)
        submitByName("_eventId_next", " Sign Document");

        // then
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Sample WF Summary", getTitle());
        assertEquals(2, getDriver().findElements(By.className("has-error")).stream().filter(s -> s.isDisplayed())
                .collect(Collectors.toList()).size());

        // when (add signature to document)
        fillSignature("7");
        fillSignature("8");

        JavascriptExecutor js = (JavascriptExecutor) getDriver();
        js.executeScript("document.getElementById('latitude').value = '111'");
        js.executeScript("document.getElementById('longitude').value = '222'");

        submitByName("_eventId_next", " Sign Document");

        // then
        final int stepCount = 3;
        Pair<Workflow, Map<String, byte[]>> pwf = verifyFolderFileList(token, folder, workflow, "ACTIVE",
                "Sample WF");

        Workflow cworkflow = pwf.getLeft();
        Map<String, byte[]> map = pwf.getRight();
        verifyDocsignResult(map);

        assertNotEquals(workflow.getUUID(), cworkflow.getUUID());

        int i = 0;
        assertEquals(stepCount, cworkflow.getSteps().size());
        assertTrue(map.containsKey(cworkflow.getSteps().get(i++) + ".form"));
        assertTrue(map.containsKey(cworkflow.getSteps().get(i++) + ".form"));
        assertTrue(map.containsKey(cworkflow.getSteps().get(i++) + ".form"));
        assertEquals(2, map.keySet().stream().filter(s -> s.endsWith(".signature")).count());
        assertEquals(cworkflow.getUUID() + ".pdf",
                map.keySet().stream().filter(s -> s.endsWith(".pdf")).collect(Collectors.joining(", ")));

        // verify token is deleted once signed.
        QueueListDTO msgs = getQueueMessages(token, userid);
        assertEquals(0, msgs.getMessages().size());

        verifyCompleteEmail();
    }

    /**
     * testCreateWorkflow09().
     * test invalid signing use.
     * @throws Exception Exception
     */
    @Test
    public void testCreateWorkflow09() throws Exception {
        //given
        String doc = UUID.randomUUID().toString();
        String stoken = UUID.randomUUID().toString();
        String signurl = getDefaultHostAndPort() + "/flow/sign/" + doc + "/" + stoken;

        // when (sign document)
        getDriver().navigate().to(signurl);

        // then
        assertEquals(getDefaultHostAndPort() + "/login", getDriver().getCurrentUrl());
    }

    /**
     * testCreateWorkflow10().
     * test Equifax workflow
     * @throws Exception Exception
     */
    @Test
    public void testCreateWorkflow10() throws Exception {
        //given
        String resp = Resources.getResourceAsString("/equifax/response.txt");
        this.equifaxService.setResponse(resp);

        MockHttpServletRequest request = new MockHttpServletRequest();
        Workflow workflow = TestDataBuilder.createWorkflow();
        ArchiveDTO archive = new ArchiveDTO();
        archive.setWorkflow(workflow);
        WebFlow flow = new WebFlow(1, null, Collections.emptyList());
        flow.setData(archive);

        this.workflowEditorService.eventIdaddstep(flow, request, new String[] { "equifaxcc" });

        FormJSON equifaxForm = archive.getForms().values().iterator().next();
        findValueByKey(equifaxForm, "membernumber").get().setValue("1234567890");
        findValueByKey(equifaxForm, "securitycode").get().setValue("99");
        findValueByKey(equifaxForm, "customercode").get().setValue("555");
        workflow = TestDataBuilder.createWorkflow(equifaxForm);

        String token = login();
        String folder = createFolder(token, getDefaultEmail());
        addFileToFolder(token, folder, workflow, equifaxForm);

        // when
        clickCreateWorkflow();

        // then (verify on correct page)
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Equifax Credit Check", getTitle());

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

        // when
        fillEquifaxForm();

        submitByName("_eventId_next", "Next");

        // then
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e2", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Sample WF Complete", getTitle());

        // TODO remove summary
        // when (goto summary -> complete)
        submitByName("_eventId_next", " Submit");

        final int count = 3;
        Pair<Workflow, Map<String, byte[]>> pwf = verifyFolderFileList(token, folder, workflow, "ACTIVE",
                "Sample WF");
        Map<String, byte[]> map = pwf.getRight();
        assertEquals(count, map.size());

        String key = map.keySet().stream().filter(s -> s.endsWith(".form")).findFirst().get();
        FormJSON form = this.jsonService.readValue(map.get(key), FormJSON.class);

        assertNotNull(findValueByKey(form, "equifax_credit_check_id").get().getValue());
        assertEquals("https://uat.equifax.ca/sts/processinquiry.asp", findValueByKey(form, "url").get().getValue());
        assertNotNull(findValueByKey(form, "request").get().getValue());
        assertNotNull(findValueByKey(form, "response").get().getValue());
        assertNotNull(findValueByKey(form, "requesttype").get().getValue());
        assertNotNull(findValueByKey(form, "inserteddate").get().getValue());
        assertEquals(getDefaultEmail(), findValueByKey(form, "requester").get().getValue());
        assertEquals("25,000", findValueByKey(form, "approvedamount").get().getValue());
    }

    /**
     * testCreateWorkflow11().
     * fillout and generate and sign fillable PDF
     * @throws Exception Exception
     */
    @Test
    public void testCreateWorkflow11() throws Exception {
        // given
        String pdfname = "sample-form2.pdf";
        byte[] data = Resources.getResourceAsBytes("/" + pdfname);
        ArchiveDTO archive = buildArchiveDTO(pdfname);
        this.pdfEditorService.generate(archive, pdfname, data);

        String token = login();
        String folder = createFolder(token, getDefaultEmail());
        addFileToFolder(token, folder, archive);

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

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

        findElementBy(By.className("add_0")).click();

        // then (verify on correct page)
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals(SAMPLE_FORM_2_HTML_TITLE, getTitle());

        fillSampleForm2();

        // when (submit)
        submitByName("_eventId_next", "Next");

        // then verify summary
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e2", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Signature", getTitle());
        assertEquals(1, findElements(getBy("button", "data-fieldid", "55")).size());
        assertEquals(0, getDriver().findElements(getBy("img", "data-fieldid", "55")).size());

        // when (go back
        submitByName("_eventId_prev", "Previous");

        // then
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals(SAMPLE_FORM_2_HTML_TITLE, getTitle());

        // when
        findElementBy(By.name("1")).sendKeys("Smith123");
        submitByName("_eventId_next", "Next");

        // then
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e2", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - Signature", getTitle());

        // when (signature)
        click(By.className("button-sig"));

        JavascriptExecutor jsExecutor = (JavascriptExecutor) getDriver();
        jsExecutor.executeScript("signaturemetadata('555','999');");

        // 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 (signature)
        click(By.className("button-sig"));

        // then
        fillSignature("55");

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

        // then
        getWait().until(ExpectedConditions.invisibilityOfElementLocated(By.id("form-modal")));
        assertEquals(0, getDriver().findElements(getBy("button", "data-fieldid", "55")).size());
        assertEquals(1, findElements(getBy("img", "data-fieldid", "55")).size());

        // when
        submitByName("_eventId_next", " Submit", TIMEOUT * 2);

        // then complete page
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e3", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - sample-form2.pdf Complete", getTitle());

        Workflow workflow = archive.getWorkflow();

        Pair<Workflow, Map<String, byte[]>> pwf = verifyFolderFileList(token, folder, workflow, "ACTIVE",
                "sample-form2.pdf");
        workflow = pwf.getLeft();
        Map<String, byte[]> map = pwf.getRight();

        assertEquals(getDefaultHostAndPort() + "/api/folders/files/" + folder + "/" + workflow.getUUID() + ".pdf",
                findElementBy(By.id("pdflink")).getAttribute("href"));

        assertEquals(SAMPLE_FORM2 + ".pdf",
                map.keySet().stream().filter(s -> s.endsWith(".pdf")).collect(Collectors.joining(", ")));

        assertEquals(1, map.keySet().stream().filter(s -> s.endsWith(".pdf")).count());

        assertEquals(1, map.keySet().stream().filter(s -> s.endsWith(".signature")).count());

        FormJSON f1 = this.jsonService.readValue(map.get(workflow.getSteps().get(1) + ".form"), FormJSON.class);

        assertTrue(f1.getAssetData().containsKey(f1.getSections().get(0).getFields().get(0).getValue()));
        assertEquals("555", findValueByKey(f1, "latitude").get().getValue());
        assertEquals("999", findValueByKey(f1, "longitude").get().getValue());
        assertEquals("0:0:0:0:0:0:0:1", findValueByKey(f1, "ipaddress").get().getValue());
        assertEquals("", findValueByKey(f1, "xforwardedfor").get().getValue());

        assertNotNull(this.jsonService.stringToDate(findValueByKey(f1, "inserteddate").get().getValue()));

        byte[] pdf = map.get(SAMPLE_FORM2 + ".pdf");

        PDDocument document = PDDocument.load(pdf);
        try {
            PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
            assertEquals("SmithSmith123", acroForm.getField("lastName").getValueAsString());
            assertEquals("John", acroForm.getField("firstName").getValueAsString());
            assertEquals(1, document.getSignatureDictionaries().size());
        } finally {
            document.close();
        }

        // TODO verify audit
    }

    /**
     * fill sample-form2.pdf.
     */
    private void fillSampleForm2() {
        int i = 1;
        // when - fill out Member information
        i = fillMemberInformation(i);

        // Coordination of benefits
        i = fillCorrdinationOfBenefits(i);

        // Spouse / Dependent Children Expenses
        i = fillSpouseDependentExpenses(i);

        // Information about your claim
        i = fillClaimInformation(i);

        // Authorization and signature
        i = fillAuthorizationAndSignatures(i);
    }

    /**
     * testCreateWorkflow11.
     * @param j int
     * @return int
     */
    private int fillAuthorizationAndSignatures(final int j) {
        int i = j;
        i++;
        findElementBy(By.name("" + i++)).sendKeys("2018");
        findElementBy(By.name("" + i++)).sendKeys("01");
        findElementBy(By.name("" + i++)).sendKeys("30");
        return i;
    }

    /**
     * testCreateWorkflow11.
     * @param j int
     * @return int
     */
    private int fillClaimInformation(final int j) {
        int i = j;
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Yes'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'No'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Yes'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'No'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Yes'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'No'")).click();
        findElementBy(By.name("" + i++)).sendKeys("2018");
        findElementBy(By.name("" + i++)).sendKeys("12");
        findElementBy(By.name("" + i++)).sendKeys("28");
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Yes'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'No'")).click();
        findElementBy(By.name("" + i++)).sendKeys("1015"); // submitted
        return i;
    }

    /**
     * testCreateWorkflow11.
     * @param j int
     * @return int
     */
    private int fillSpouseDependentExpenses(final int j) {
        int i = j;
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Spouse'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Son'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Daughter'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'Other'")).click();
        findElementBy(By.name("" + i++)).sendKeys("Jack");
        findElementBy(By.name("" + i++)).sendKeys("Smith");
        findElementBy(By.name("" + i++)).sendKeys("2010"); // birthdate 1
        findElementBy(By.name("" + i++)).sendKeys("03"); // birthdate 2
        findElementBy(By.name("" + i++)).sendKeys("22"); // birthdate 3
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Spouse'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Son'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Daughter'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'Other'")).click();
        findElementBy(By.name("" + i++)).sendKeys("Jane"); // Spouse first
        findElementBy(By.name("" + i++)).sendKeys("Smith"); // Spouse last
        findElementBy(By.name("" + i++)).sendKeys("1969"); // birthdate 1
        findElementBy(By.name("" + i++)).sendKeys("05"); // birthdate 2
        findElementBy(By.name("" + i++)).sendKeys("27"); // birthdate 3
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Spouse'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Son'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Daughter'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'Other'")).click();
        findElementBy(By.name("" + i++)).sendKeys("Suze"); // Spouse first
        findElementBy(By.name("" + i++)).sendKeys("Smith"); // Spouse last
        findElementBy(By.name("" + i++)).sendKeys("2012"); // birthdate 1
        findElementBy(By.name("" + i++)).sendKeys("06"); // birthdate 2
        findElementBy(By.name("" + i++)).sendKeys("28"); // birthdate 3
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Spouse'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Son'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Daughter'")).click();
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'Other'")).click();
        findElementBy(By.name("" + i++)).sendKeys("Frank"); // Spouse first
        findElementBy(By.name("" + i++)).sendKeys("Smith"); // Spouse last
        findElementBy(By.name("" + i++)).sendKeys("2014"); // birthdate 1
        findElementBy(By.name("" + i++)).sendKeys("07"); // birthdate 2
        findElementBy(By.name("" + i++)).sendKeys("30"); // birthdate 3
        return i;
    }

    /**
     * testCreateWorkflow11.
     * @param j int
     * @return int
     */
    private int fillCorrdinationOfBenefits(final int j) {
        int i = j;
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'No'")).click(); // Spouse Another plan
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'Yes'")).click(); // Spouse Another plan
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'No'")).click(); // Spouse Another plan
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'Yes'")).click(); // Spouse Another plan
        findElementBy(By.name("" + i++)).sendKeys("Smith"); // Spouse diff plan
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Male'")).click(); // Gender
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'female'")).click(); // Gender
        findElementBy(By.name("" + i++)).sendKeys("5551234"); // Spouse Contract
        findElementBy(By.name("" + i++)).sendKeys("55554321"); // Spouse Cert No
        return i;
    }

    /**
     * testCreateWorkflow11.
     * @param j int
     * @return int
     */
    private int fillMemberInformation(final int j) {
        int i = j;
        findElementBy(By.name("" + i++)).sendKeys("Smith"); // last name
        findElementBy(By.name("" + i++)).sendKeys("John"); // first name
        findElementBy(By.name("" + i++)).sendKeys("John"); // certificate
        findElementBy(By.name("" + i++)).sendKeys("555"); // phone number 1
        findElementBy(By.name("" + i++)).sendKeys("555"); // phone number 2
        findElementBy(By.name("" + i++)).sendKeys("1212"); // phone number 3
        findElementBy(By.name("" + i++)).sendKeys("2000"); // birthdate 1
        findElementBy(By.name("" + i++)).sendKeys("01"); // birthdate 2
        findElementBy(By.name("" + i++)).sendKeys("19"); // birthdate 3

        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Eng'")).click(); // Language Required
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'Fr'")).click(); // Language Required
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i + "!'Male'")).click(); // Gender
        findElementBy(By.id("'Public Service Health Care Plan (PSHCP) Claim Form'!" + i++ + "!'Female'")).click(); // Gender
        findElementBy(By.name("" + i++)).sendKeys("123 Main"); // Street
        findElementBy(By.name("" + i++)).sendKeys("708"); // Apartment
        findElementBy(By.name("" + i++)).sendKeys("New York"); // City
        findElementBy(By.name("" + i++)).sendKeys("NY"); // Province
        findElementBy(By.name("" + i++)).sendKeys("90210"); // Postal Code
        return i;
    }

    /**
     * testCreateWorkflow12().
     * test selecting checkbox and refreshing page to make sure it
     * is still selected
     * @throws Exception Exception
     */
    @Test
    public void testCreateWorkflow12() throws Exception {
        // given
        FormJSON form = TestDataBuilder.createAllFields();
        Workflow workflow = TestDataBuilder.createWorkflow(form);

        String token = login();
        String folder = createFolder(token, getDefaultEmail());

        addFileToFolder(token, folder, workflow, form);

        clickCreateWorkflow();

        // then (verify on correct page)
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertEquals("FormKiQ Server - All Forms", getTitle());

        // given
        // checkbox
        findElementByName("" + (findIndex(FormJSONFieldType.SWITCH))).click();

        // when
        submitByName("_eventId_next", "Next");

        // then verify summary
        assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl());
        assertTrue(findElementByName("" + (findIndex(FormJSONFieldType.SWITCH))).isSelected());
    }

    /**
     * fill equifax form.
     */
    private void fillEquifaxForm() {
        findElementBy("input", "data-valuekey", "suffix").sendKeys("mr");
        findElementBy("input", "data-valuekey", "firstname").sendKeys("mr");
        findElementBy("input", "data-valuekey", "familyname").sendKeys("mr");
        findElementBy("input", "data-valuekey", "birthdate").sendKeys("2017-01-01T12:12:12-0600");
        findElementBy("input", "data-valuekey", "homephonenumber").sendKeys("555-555-5555");
        findElementBy("input", "data-valuekey", "streetno0").sendKeys("123");
        findElementBy("input", "data-valuekey", "streetname0").sendKeys("main");
        findElementBy("input", "data-valuekey", "city0").sendKeys("test");
        findElementBy("input", "data-valuekey", "province0").sendKeys("mb");
        findElementBy("input", "data-valuekey", "postalcode0").sendKeys("90210");
    }

    /**
     * Verify Completion Email.
     * @throws IOException IOException
     * @throws MessagingException MessagingException
     */
    private void verifyCompleteEmail() throws IOException, MessagingException {

        assertEquals(0, getMailSender().getMessages().size());
        assertEquals(1, getMailSender().getMimeMessages().size());

        MimeMessage msg = getMailSender().getMimeMessages().get(0);
        assertEquals("Completed signing Sample WF", msg.getSubject());
        assertEquals("test@formkiq.com", msg.getAllRecipients()[0].toString());

        Multipart multipart = (Multipart) msg.getContent();
        assertEquals(1, multipart.getCount());

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        msg.writeTo(out);

        String s = out.toString(CHARSET_UTF8.name());
        assertFalse(s.contains("${sendername}"));
        assertFalse(s.contains("${signername}"));
        assertFalse(s.contains("${doc}"));
        assertFalse(s.contains("${stoken}"));
        assertTrue(s.contains("has reviewed and signed the document"));

        out.close();
    }

    /**
     * verify email is sent for signing.
     * @return {@link String} The signing URL.
     * @throws IOException IOException
     * @throws MessagingException MessagingException
     */
    private String verifyDocsignEmail() throws IOException, MessagingException {

        assertEquals(0, getMailSender().getMessages().size());
        assertEquals(1, getMailSender().getMimeMessages().size());

        MimeMessage msg = getMailSender().getMimeMessages().get(0);
        assertTrue(msg.getSubject().endsWith("sign this"));
        assertTrue(msg.getAllRecipients()[0].toString().endsWith("jacksmith@formkiq.com"));

        Multipart multipart = (Multipart) msg.getContent();
        assertEquals(1, multipart.getCount());

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        msg.writeTo(out);

        String s = out.toString(CHARSET_UTF8.name());
        assertTrue(s.contains("John Smith"));
        assertTrue(s.contains("Jack Smith"));
        assertFalse(s.contains("${sendername}"));
        assertFalse(s.contains("${signername}"));
        assertFalse(s.contains("${doc}"));
        assertFalse(s.contains("${stoken}"));
        assertTrue(s.contains("Please review the document and sign at the link above"));

        out.close();

        getMailSender().reset();

        return findHrefUrl(s);
    }

    /**
     * Verify the Docsign Result.
     * @param map {@link Map}
     * @throws IOException IOException
     * @throws ParseException ParseException
     */
    private void verifyDocsignResult(final Map<String, byte[]> map) throws IOException, ParseException {

        final int numberOfSteps = 3;
        final int numberOfFields = 5;

        String workflowname = map.entrySet().stream().filter(e -> e.getKey().endsWith(".workflow")).findFirst()
                .get().getKey();

        String s = Strings.toString(map.get(workflowname));
        Workflow w = this.jsonService.readValue(s, Workflow.class);
        assertEquals(numberOfSteps, w.getSteps().size());
        String step = w.getSteps().get(w.getSteps().size() - 1);

        byte[] formdata = map.get(step + ".form");

        FormJSON r = this.jsonService.readValue(Strings.toString(formdata), FormJSON.class);
        assertEquals(w.getParentUUID(), r.getParentUUID());
        assertEquals("docsignresult", r.getBuiltintype());
        assertEquals(1, r.getSections().size());

        FormJSONSection section = r.getSections().get(0);
        assertEquals(numberOfFields, section.getFields().size());

        FormJSONField f0 = section.getFields().get(0);
        assertEquals(1, f0.getId());
        assertEquals("Inserted Date", f0.getLabel());
        assertEquals(FormJSONFieldType.TEXTBOX, f0.getType());
        assertNotNull(this.jsonDateFormat.parse(f0.getValue()));

        int i = 1;
        assertField(section.getFields().get(i), ++i, "IP Address", FormJSONFieldType.TEXTBOX, "0:0:0:0:0:0:0:1");

        assertField(section.getFields().get(i), ++i, "X-FORWARDED-FOR", FormJSONFieldType.TEXTBOX, "");

        assertField(section.getFields().get(i), ++i, "Latitude", FormJSONFieldType.TEXTBOX, "111");

        assertField(section.getFields().get(i), ++i, "Longitude", FormJSONFieldType.TEXTBOX, "222");
    }

    /**
     * Verify Folder File List for testSign01().
     * @param token {@link String}
     * @param folder {@link String}
     * @param workflow {@link Workflow}
     * @param status {@link String}
     * @param name {@link String}
     *
     * @throws IOException IOException
     * @return {@link Pair}
     */
    private Pair<Workflow, Map<String, byte[]>> verifyFolderFileList(final String token, final String folder,
            final Workflow workflow, final String status, final String name) throws IOException {

        FolderFormsListDTO dto = getFolderFileList(token, folder, workflow.getUUID());

        assertEquals(1, dto.getForms().size());
        assertEquals(name, dto.getForms().get(0).getName());
        assertEquals("WORKFLOW", dto.getForms().get(0).getType());
        assertEquals(status, dto.getForms().get(0).getStatus());

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

        Map<String, byte[]> map = Zips.extractZipToMap(body);
        String workflowKey = workflowUUID + ".workflow";
        Workflow wf = this.jsonService.readValue(map.get(workflowKey), Workflow.class);

        return Pair.of(wf, map);
    }

    /**
     * Verify Queue Messages for testSign01().
     * @param token {@link String}
     * @param userid {@link String}
     * @param folder {@link String}
     * @return {@link Pair}
     * @throws Exception Exception
     */
    private Pair<QueueDTO, DocSignQueueMessage> verifyQueueMessage(final String token, final String userid,
            final String folder) throws Exception {

        QueueListDTO msgs = getQueueMessages(token, userid);
        assertEquals(1, msgs.getMessages().size());
        QueueDTO queueDTO = msgs.getMessages().get(0);
        assertNotNull(queueDTO.getUUID());
        DocSignQueueMessage dmsg = this.jsonService.readValue(queueDTO.getMessage(), DocSignQueueMessage.class);

        assertEquals(folder, dmsg.getFolderid());
        assertNotNull(dmsg.getAssetid());
        assertNotNull(dmsg.getFormid());
        assertNotNull(dmsg.getUserid());
        assertTrue(dmsg.getSigner1email().endsWith("jacksmith@formkiq.com"));
        assertTrue(dmsg.getSigner1name().endsWith("Jack Smith"));
        assertEquals(userid, dmsg.getUserid());

        return Pair.of(queueDTO, dmsg);
    }

    // TODO backbutton...
}