com.formkiq.core.service.workflow.WorkflowEditorServiceImplTest.java Source code

Java tutorial

Introduction

Here is the source code for com.formkiq.core.service.workflow.WorkflowEditorServiceImplTest.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.core.service.workflow;

import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.isA;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.tuple.Pair;
import org.bouncycastle.util.Strings;
import org.easymock.EasyMockRunner;
import org.easymock.EasyMockSupport;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.mock.web.MockMultipartHttpServletRequest;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.servlet.ModelAndView;

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.Workflow;
import com.formkiq.core.form.dto.WorkflowOutputPdfForm;
import com.formkiq.core.form.service.FormCalculatorService;
import com.formkiq.core.form.service.FormCalculatorServiceImpl;
import com.formkiq.core.form.service.FormValidatorService;
import com.formkiq.core.form.service.FormValidatorServiceImpl;
import com.formkiq.core.service.ArchiveService;
import com.formkiq.core.service.FolderService;
import com.formkiq.core.service.dto.FormSaveResult;
import com.formkiq.core.service.generator.WorkflowOutputGenerator;
import com.formkiq.core.testdata.TestDataBuilder;
import com.formkiq.core.webflow.FlowState;
import com.formkiq.core.webflow.FlowStateType;
import com.formkiq.core.webflow.WebFlow;
import com.google.common.collect.ImmutableMap;

/**
 * Unit Tests for {@link WorkflowEditorServiceImpl}.
 *
 */
@RunWith(EasyMockRunner.class)
public class WorkflowEditorServiceImplTest extends EasyMockSupport {

    /** WorkflowEditorService. */
    @TestSubject
    private WorkflowEditorServiceImpl ws = new WorkflowEditorServiceImpl();

    /** ArchiveDTO. */
    private ArchiveDTO archive = new ArchiveDTO();

    /** {@link ApplicationContext}. */
    @Mock
    private ApplicationContext context;

    /** ArchiveDTO. */
    @Mock
    private ArchiveDTO mockarchive;

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

    /** Mock. */
    @Mock
    private WebFlow flow;

    /** Mock. */
    @Mock
    private FolderService folderService;

    /** {@link FormCalculatorService}. */
    private FormCalculatorService formCalculatorService = new FormCalculatorServiceImpl();

    /** JSONService. */
    private JSONService jsonService = new JSONService();

    /** Mock. */
    @Mock
    private List<WorkflowOutputGenerator> outputGenerators;

    /** Mock. */
    @Mock
    private HttpServletRequest request;

    /** Mock. */
    @Mock
    private HttpSession session;

    /** Mock. */
    @Mock
    private WorkflowOutputGenerator pdfEditor;

    /** WorkflowService. */
    private WorkflowService workflowService = new WorkflowServiceImpl();

    /** Workflow. */
    private Workflow workflow = new Workflow();

    /** Workflow. */
    @Mock
    private Workflow mockworkflow;

    /** {@link FormValidatorService}. */
    private FormValidatorService validator = new FormValidatorServiceImpl();

    /** Folder UUID. */
    private String folder = UUID.randomUUID().toString();

    /** UUID. */
    private String uuid = UUID.randomUUID().toString();

    /**
     * before.
     */
    @Before
    public void before() {
        ReflectionTestUtils.setField(this.ws, "workflowService", this.workflowService);
        ReflectionTestUtils.setField(this.ws, "jsonService", this.jsonService);

        ReflectionTestUtils.setField(this.ws, "formCalculatorService", this.formCalculatorService);

        ReflectionTestUtils.setField(this.ws, "validatorService", this.validator);
    }

    /**
     * Expect Action.
     * @return {@link Workflow}
     */
    private Workflow expectAction() {
        Workflow wf = new Workflow();
        wf.setSteps(Arrays.asList("1", "2", "3"));
        wf.setPrintsteps(Arrays.asList("1", "2", "3"));

        this.archive.setWorkflow(wf);

        FlowState state = new FlowState(FlowStateType.DEFAULT, wf);

        // when
        expect(this.flow.getCurrentState()).andReturn(state);

        return wf;
    }

    /**
     * testEventAddStep01().
     * Add step
     * @throws IOException IOException
     */
    @SuppressWarnings("unchecked")
    @Test
    public void testEventAddStep01() throws IOException {
        // given
        this.archive.setWorkflow(this.workflow);

        // when
        expect(this.flow.getData()).andReturn(this.archive);

        this.flow.setStates(isA(List.class));
        this.flow.setEventId(2);

        replayAll();
        this.ws.eventIdaddstep(this.flow, this.request, null);

        // then
        verifyAll();

        assertEquals(1, this.archive.getForms().size());
        FormJSON form = this.archive.getForms().values().iterator().next();
        assertEquals("New Form", form.getName());
        assertNotNull(form.getUUID());

        assertEquals(1, this.workflow.getSteps().size());
        assertEquals(1, this.workflow.getPrintsteps().size());
        assertTrue(this.workflow.getSteps().contains(form.getUUID()));
        assertTrue(this.workflow.getPrintsteps().contains(form.getUUID()));
    }

    /**
     * testEventAddStep02().
     * Add step - MultipartHttpServletRequest
     * @throws IOException IOException
     */
    @SuppressWarnings("unchecked")
    @Test
    public void testEventAddStep02() throws IOException {
        // given
        this.archive.setWorkflow(this.workflow);
        MockMultipartHttpServletRequest req = new MockMultipartHttpServletRequest();
        req.setRequestURI("/home");

        byte[] content = Strings.toByteArray("test");
        req.addFile(new MockMultipartFile("sample.pdf", "sample.pdf", "", content));

        // when
        expect(this.flow.getData()).andReturn(this.archive);

        this.flow.setStates(isA(List.class));
        this.flow.setEventId(1);

        Map<String, WorkflowOutputGenerator> map = ImmutableMap.of("test", this.pdfEditor);
        expect(this.context.getBeansOfType(WorkflowOutputGenerator.class)).andReturn(map);
        expect(this.pdfEditor.getNewWorkflowOutputDocument()).andReturn(new WorkflowOutputPdfForm());
        this.pdfEditor.generate(this.archive, "sample.pdf", content);

        replayAll();
        this.ws.eventIdaddstep(this.flow, req, null);

        // then
        verifyAll();
    }

    /**
     * testEventForms01().
     * _eventId_forms.
     * @throws IOException IOException
     */
    @Test
    public void testEventForms01() throws IOException {
        // given
        ArchiveDTO arch = new ArchiveDTO();
        Workflow wf = new Workflow();

        FormJSON form0 = TestDataBuilder.createSimpleForm();
        FormJSON form1 = TestDataBuilder.createStoreReceipt();

        wf.setSteps(Arrays.asList(form0.getUUID(), form1.getUUID()));

        arch.setWorkflow(wf);
        arch.addForm(form0);
        arch.addForm(form1);

        // when
        expect(this.flow.getData()).andReturn(arch);

        replayAll();
        FormJSONField result = this.ws.eventIdforms(this.flow, new String[] { "81" });

        // then
        verifyAll();

        assertEquals("Simple Form[" + form0.getUUID() + "],Store Receipt[" + form1.getUUID() + "]",
                String.join(",", result.getOptions()));
    }

    /**
     * testEventIdformfields01().
     * @throws Exception Exception
     */
    @Test
    public void testEventIdformfields01() throws Exception {
        // given
        String formUUID = UUID.randomUUID().toString();
        String param81 = "Test[" + formUUID + "]";
        FormJSON testform = TestDataBuilder.createSimpleForm();

        // when
        expect(this.flow.getData()).andReturn(this.mockarchive);
        expect(this.request.getParameter("81")).andReturn(param81);
        expect(this.mockarchive.getForm(formUUID)).andReturn(testform);

        replayAll();
        FormJSONField field = this.ws.eventIdformfields(this.flow, this.request, null);

        // verify
        verifyAll();

        assertEquals("Total ($)[1]", String.join(",", field.getOptions()));
    }

    /**
     * testEventIdformulaformfields01().
     * no variables
     * @throws Exception Exception
     */
    @Test
    public void testEventIdformulaformfields01() throws Exception {
        // given
        String formUUID = UUID.randomUUID().toString();
        String param81 = "Test[" + formUUID + "]";
        FormJSON testform = TestDataBuilder.createSimpleForm();

        // when
        expect(this.flow.getData()).andReturn(this.mockarchive);
        expect(this.request.getParameter("83")).andReturn(param81);
        expect(this.mockarchive.getForm(formUUID)).andReturn(testform);

        replayAll();
        FormJSONField field = this.ws.eventIdformulaformfields(this.flow, this.request);

        // verify
        verifyAll();

        assertEquals("", String.join(",", field.getOptions()));
    }

    /**
     * testEventIdformulaformfields02().
     * with variables
     * @throws Exception Exception
     */
    @Test
    public void testEventIdformulaformfields02() throws Exception {
        // given
        String formUUID = UUID.randomUUID().toString();
        String param81 = "Test[" + formUUID + "]";
        FormJSON testform = TestDataBuilder.createStoreReceipt();

        // when
        expect(this.flow.getData()).andReturn(this.mockarchive);
        expect(this.request.getParameter("83")).andReturn(param81);
        expect(this.mockarchive.getForm(formUUID)).andReturn(testform);

        replayAll();
        FormJSONField field = this.ws.eventIdformulaformfields(this.flow, this.request);

        // verify
        verifyAll();

        assertEquals("$subtotal,$tax,$delivery,$total", String.join(",", field.getOptions()));
    }

    /**
     * testEventIdformulaformfieldvar01().
     * adding variable from current form
     * @throws IOException IOException
     */
    @Test
    public void testEventIdformulaformfieldvar01() throws IOException {
        // given
        FormJSON testform = TestDataBuilder.createStoreReceipt();
        FlowState state = new FlowState(FlowStateType.DEFAULT, testform);
        String[] param78 = new String[] {};
        String[] param83 = new String[] { "Test[" + testform.getUUID() + "]" };
        String[] param84 = new String[] { "$subtotal" };

        // when
        expect(this.flow.getCurrentState()).andReturn(state);
        expect(this.request.getParameterValues("78")).andReturn(param78);
        expect(this.request.getParameterValues("83")).andReturn(param83);
        expect(this.request.getParameterValues("84")).andReturn(param84);

        replayAll();

        FormJSONField result = this.ws.eventIdformulaformfieldvar(this.flow, this.request);

        // then
        verifyAll();

        assertEquals("$subtotal", result.getValue());
    }

    /**
     * testEventIdformulaformfieldvar02().
     * adding variable from different form
     * @throws IOException IOException
     */
    @Test
    public void testEventIdformulaformfieldvar02() throws IOException {
        // given
        FormJSON testform = TestDataBuilder.createStoreReceipt();
        FormJSON currentform = TestDataBuilder.createSimpleForm();
        FlowState state = new FlowState(FlowStateType.DEFAULT, currentform);
        String[] param78 = new String[] { "7*" };
        String[] param83 = new String[] { testform.getName() + "[" + testform.getUUID() + "]" };
        String[] param84 = new String[] { "$subtotal" };

        // when
        expect(this.flow.getCurrentState()).andReturn(state);
        expect(this.request.getParameterValues("78")).andReturn(param78);
        expect(this.request.getParameterValues("83")).andReturn(param83);
        expect(this.request.getParameterValues("84")).andReturn(param84);

        replayAll();

        FormJSONField result = this.ws.eventIdformulaformfieldvar(this.flow, this.request);

        // then
        verifyAll();

        assertEquals("7*'Store Receipt'!$subtotal", result.getValue());
    }

    /**
     * testEventIdremoveform01().
     */
    @SuppressWarnings("boxing")
    @Test
    public void testEventIdremoveform01() {
        // given
        FormJSON testform = TestDataBuilder.createSimpleForm();
        List<String> steps = Arrays.asList(testform.getUUID());
        this.workflow.setSteps(new ArrayList<>(steps));
        this.workflow.setPrintsteps(new ArrayList<>(steps));
        FlowState state = new FlowState(FlowStateType.DEFAULT, testform);

        // when
        expect(this.flow.getData()).andReturn(this.mockarchive);
        expect(this.mockarchive.getWorkflow()).andReturn(this.workflow);
        expect(this.flow.getCurrentState()).andReturn(state).times(2);

        this.mockarchive.removeForm(testform);
        expect(this.flow.removeState(state)).andReturn(true);

        replayAll();
        this.ws.eventIdremoveform(this.flow, this.request);

        // then
        verifyAll();

        assertEquals(0, this.workflow.getSteps().size());
        assertEquals(0, this.workflow.getPrintsteps().size());
    }

    /**
     * testEventIdremoveformfield01().
     * remove field.
     */
    @Test
    public void testEventIdremoveformfield01() {
        // given
        FormJSON form = TestDataBuilder.createAllFields();
        int fieldcount = form.getSections().get(0).getFields().size();
        assertTrue(fieldcount > 0);

        String[] fieldids = new String[] { "2" };
        FlowState state = new FlowState(FlowStateType.DEFAULT, form);

        // when
        expect(this.flow.getCurrentState()).andReturn(state);

        replayAll();
        this.ws.eventIdremoveformfield(this.flow, this.request, fieldids);

        // then
        verifyAll();

        int fieldcount2 = form.getSections().get(0).getFields().size();
        assertEquals(fieldcount2, fieldcount - 1);
    }

    /**
     * testEventIdremoveprintstep01()
     * remove print step.
     */
    @Test
    public void testEventIdremoveprintstep01() {
        // given
        String[] fieldids = new String[] { "1" };
        this.workflow.setPrintsteps(new ArrayList<>(Arrays.asList("1", "2", "3")));

        // when
        expect(this.flow.getData()).andReturn(this.mockarchive);
        expect(this.mockarchive.getWorkflow()).andReturn(this.workflow);

        replayAll();
        this.ws.eventIdremoveprintstep(this.flow, fieldids);

        // then
        verifyAll();

        assertEquals("1,3", String.join(",", this.workflow.getPrintsteps()));
    }

    /**
     * testEventIdremoveprintstep02()
     * remove -1 print step.
     */
    @Test
    public void testEventIdremoveprintstep02() {
        // given
        String[] fieldids = new String[] { "" };
        this.workflow.setPrintsteps(new ArrayList<>(Arrays.asList("1", "2", "3")));

        // when
        expect(this.flow.getData()).andReturn(this.mockarchive);
        expect(this.mockarchive.getWorkflow()).andReturn(this.workflow);

        replayAll();
        this.ws.eventIdremoveprintstep(this.flow, fieldids);

        // then
        verifyAll();

        assertEquals("1,2,3", String.join(",", this.workflow.getPrintsteps()));
    }

    /**
     * testEventIdremoveprintstep03()
     * remove 10th print step.
     */
    @Test
    public void testEventIdremoveprintstep03() {
        // given
        String[] fieldids = new String[] { "10" };
        this.workflow.setPrintsteps(new ArrayList<>(Arrays.asList("1", "2", "3")));

        // when
        expect(this.flow.getData()).andReturn(this.mockarchive);
        expect(this.mockarchive.getWorkflow()).andReturn(this.workflow);

        replayAll();
        this.ws.eventIdremoveprintstep(this.flow, fieldids);

        // then
        verifyAll();

        assertEquals("1,2,3", String.join(",", this.workflow.getPrintsteps()));
    }

    /**
     * testEventStepdown01().
     * _eventId_stepdown up.
     * @throws IOException IOException
     */
    @Test
    public void testEventStepdown01() throws IOException {
        // given
        Workflow wf = expectAction();

        replayAll();
        this.ws.eventIdstepdown(this.flow, this.request, new String[] { "0" });

        // then
        verifyAll();

        assertEquals("2,1,3", String.join(",", wf.getSteps()));
        assertEquals("1,2,3", String.join(",", wf.getPrintsteps()));
    }

    /**
     * testEventStepdown02().
     * _eventId_stepdown up at max size.
     * @throws IOException IOException
     */
    @Test
    public void testEventStepdown02() throws IOException {
        // given

        // when
        Workflow wf = expectAction();

        replayAll();
        this.ws.eventIdstepdown(this.flow, this.request, new String[] { "2" });

        // then
        verifyAll();

        assertEquals("1,2,3", String.join(",", wf.getSteps()));
        assertEquals("1,2,3", String.join(",", wf.getPrintsteps()));
    }

    /**
     * testEventStepdown03().
     * _eventId_stepdown up at max size.
     * @throws IOException IOException
     */
    @Test
    public void testEventStepdown03() throws IOException {
        // given

        // when
        Workflow wf = expectAction();

        replayAll();
        this.ws.eventIdstepdown(this.flow, this.request, new String[] { "-1" });

        // then
        verifyAll();

        assertEquals("1,2,3", String.join(",", wf.getSteps()));
        assertEquals("1,2,3", String.join(",", wf.getPrintsteps()));
    }

    /**
     * testEventStepup01().
     * _eventId_stepup. No Change.
     * @throws IOException IOException
     */
    @Test
    public void testEventStepup01() throws IOException {
        // given
        Workflow wf = expectAction();

        replayAll();
        this.ws.eventIdstepup(this.flow, this.request, new String[] { "0" });

        // then
        verifyAll();

        assertEquals("1,2,3", String.join(",", wf.getSteps()));
        assertEquals("1,2,3", String.join(",", wf.getPrintsteps()));
    }

    /**
     * testEventStepup02().
     * _eventId_stepup up at max size.
     * @throws IOException IOException
     */
    @Test
    public void testEventStepup02() throws IOException {
        // given
        Workflow wf = expectAction();

        // when
        replayAll();
        this.ws.eventIdstepup(this.flow, this.request, new String[] { "3" });

        // then
        verifyAll();

        assertEquals("1,2,3", String.join(",", wf.getSteps()));
        assertEquals("1,2,3", String.join(",", wf.getPrintsteps()));
    }

    /**
     * testEventStepup03().
     * _eventId_stepup up at max size.
     * @throws IOException IOException
     */
    @Test
    public void testEventStepup03() throws IOException {
        // given
        Workflow wf = expectAction();

        // when
        replayAll();
        this.ws.eventIdstepup(this.flow, this.request, new String[] { "-1" });

        // then
        verifyAll();

        assertEquals("1,2,3", String.join(",", wf.getSteps()));
        assertEquals("1,2,3", String.join(",", wf.getPrintsteps()));
    }

    /**
     * testEventStepup04().
     * _eventId_stepup last item of list.
     * @throws IOException IOException
     */
    @Test
    public void testEventStepup04() throws IOException {
        // given
        Workflow wf = expectAction();

        // when
        replayAll();
        this.ws.eventIdstepup(this.flow, this.request, new String[] { "2" });

        // then
        verifyAll();

        assertEquals("1,3,2", String.join(",", wf.getSteps()));
        assertEquals("1,2,3", String.join(",", wf.getPrintsteps()));
    }

    /**
     * testEventStepup05().
     * _eventId_stepup item 1.
     * @throws IOException IOException
     */
    @Test
    public void testEventStepup05() throws IOException {
        // given
        Workflow wf = expectAction();

        // when
        replayAll();
        this.ws.eventIdstepup(this.flow, this.request, new String[] { "1" });

        // then
        verifyAll();

        assertEquals("2,1,3", String.join(",", wf.getSteps()));
        assertEquals("1,2,3", String.join(",", wf.getPrintsteps()));
    }

    /**
     * testPrintStepdown01().
     * _eventId_printstepup up.
     * @throws IOException IOException
     */
    @Test
    public void testPrintStepdown01() throws IOException {
        // given
        Workflow wf = expectAction();

        // when
        replayAll();
        this.ws.eventIdprintstepdown(this.flow, this.request, new String[] { "0" });

        // then
        verifyAll();

        assertEquals("1,2,3", String.join(",", wf.getSteps()));
        assertEquals("2,1,3", String.join(",", wf.getPrintsteps()));
    }

    /**
     * testPrintStepup01().
     * _eventId_printstepup last item of list.
     * @throws IOException IOException
     */
    @Test
    public void testPrintStepup01() throws IOException {
        // given
        Workflow wf = expectAction();

        // when
        replayAll();
        this.ws.eventIdprintstepup(this.flow, this.request, new String[] { "2" });

        // then
        verifyAll();

        assertEquals("1,2,3", String.join(",", wf.getSteps()));
        assertEquals("1,3,2", String.join(",", wf.getPrintsteps()));
    }

    /**
     * testSave01().
     * has errors
     * @throws IOException IOException
     */
    @Test
    public void testSave01() throws IOException {
        // given
        String execution = "s1e1";
        String sha1hash = UUID.randomUUID().toString();

        Map<String, String> errors = ImmutableMap.of("errors", "1");
        FormSaveResult saveResult = new FormSaveResult(null, "", errors);

        // when
        expect(this.request.getParameter("execution")).andReturn(execution);
        expect(this.request.getSession()).andReturn(this.session);
        expect(this.session.getAttribute("s1")).andReturn(this.flow);
        expect(this.flow.getData()).andReturn(this.archive);

        expect(this.flow.getParameter("folder")).andReturn(this.folder);
        expect(this.flow.getParameter("sha1hash")).andReturn(sha1hash);

        expect(this.folderService.saveForm(this.folder, this.archive, sha1hash, false)).andReturn(saveResult);

        this.flow.setParameter("errors", errors);

        replayAll();
        Map<String, String> result = this.ws.save(this.request);

        // then
        verifyAll();

        assertFalse(result.isEmpty());
    }

    /**
     * testSave02().
     * no errors
     * @throws IOException IOException
     */
    @Test
    public void testSave02() throws IOException {
        // given
        String execution = "s1e1";
        String sha1hash = UUID.randomUUID().toString();

        Map<String, String> errors = new HashMap<>();
        FormSaveResult saveResult = new FormSaveResult(null, "", errors);

        // when
        expect(this.request.getParameter("execution")).andReturn(execution).times(2);
        expect(this.request.getSession()).andReturn(this.session).anyTimes();
        expect(this.session.getAttribute("s1")).andReturn(this.flow).times(2);
        expect(this.flow.getData()).andReturn(this.archive);

        expect(this.flow.getParameter("folder")).andReturn(this.folder);
        expect(this.flow.getParameter("sha1hash")).andReturn(sha1hash);

        expect(this.folderService.saveForm(this.folder, this.archive, sha1hash, false)).andReturn(saveResult);

        expect(this.flow.getSessionKey()).andReturn(execution);
        this.session.removeAttribute("s1");

        replayAll();
        Map<String, String> result = this.ws.save(this.request);

        // then
        verifyAll();

        assertTrue(result.isEmpty());
    }

    /**
     * testSave03().
     * saving throws exception
     * @throws IOException IOException
     */
    @Test
    public void testSave03() throws IOException {
        // given
        String execution = "s1e1";
        String sha1hash = UUID.randomUUID().toString();
        RuntimeException exception = new RuntimeException("dummy error");

        // when
        expect(this.request.getParameter("execution")).andReturn(execution);
        expect(this.request.getSession()).andReturn(this.session).anyTimes();
        expect(this.session.getAttribute("s1")).andReturn(this.flow);
        expect(this.flow.getData()).andReturn(this.archive);

        expect(this.flow.getParameter("folder")).andReturn(this.folder);
        expect(this.flow.getParameter("sha1hash")).andReturn(sha1hash);

        expect(this.folderService.saveForm(this.folder, this.archive, sha1hash, false)).andThrow(exception);

        this.flow.setParameter(eq("errors"), isA(Map.class));

        replayAll();
        Map<String, String> result = this.ws.save(this.request);

        // then
        verifyAll();

        assertEquals(1, result.size());
        assertEquals("dummy error", result.get("error"));
    }

    /**
     * testStartEdit01().
     * @throws IOException IOException
     *
     */
    @Test
    public void testStartEdit01() throws IOException {
        // given
        MockHttpServletRequest req = new MockHttpServletRequest();
        FormJSON form = TestDataBuilder.createAllFields();
        String sha1hash = UUID.randomUUID().toString();
        String step = UUID.randomUUID().toString();
        List<String> steps = Arrays.asList(step);

        // when
        expect(this.archiveService.get(this.folder, this.uuid, false))
                .andReturn(Pair.of(this.mockarchive, sha1hash));

        expect(this.mockarchive.getWorkflow()).andReturn(this.mockworkflow).times(2);

        expect(this.mockworkflow.getSteps()).andReturn(steps);
        expect(this.mockarchive.getForm(step)).andReturn(form);

        replayAll();

        Pair<ModelAndView, WebFlow> result = this.ws.startEdit(req, this.folder, this.uuid);

        // then
        verifyAll();

        final int states = 5;

        ModelAndView mav = result.getLeft();
        assertEquals("redirect:/user/designer/edit?execution=s1e1", mav.getViewName());

        WebFlow wf = result.getRight();
        assertEquals(states, wf.getStates().size());
    }

    /**
     * testStartEdit02().
     * start on new entry, IE: UUID is null
     * @throws IOException IOException
     *
     */
    @Test
    public void testStartEdit02() throws IOException {
        // given
        String uuidNull = null;
        MockHttpServletRequest req = new MockHttpServletRequest();

        // when
        replayAll();

        Pair<ModelAndView, WebFlow> result = this.ws.startEdit(req, this.folder, uuidNull);

        // then
        verifyAll();

        final int states = 4;

        ModelAndView mav = result.getLeft();
        assertEquals("redirect:/user/designer/edit?execution=s1e1", mav.getViewName());

        WebFlow wf = result.getRight();
        assertEquals(states, wf.getStates().size());
    }
}