Package org.apache.tapestry.form

Source Code of org.apache.tapestry.form.FormSupportTest

// Copyright 2005 The Apache Software Foundation
//
// 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 org.apache.tapestry.form;

import static org.easymock.EasyMock.checkOrder;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.isA;

import java.util.HashMap;
import java.util.Map;

import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.Location;
import org.apache.tapestry.BaseComponentTestCase;
import org.apache.tapestry.IEngine;
import org.apache.tapestry.IForm;
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.IRender;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.NestedMarkupWriter;
import org.apache.tapestry.PageRenderSupport;
import org.apache.tapestry.StaleLinkException;
import org.apache.tapestry.TapestryUtils;
import org.apache.tapestry.engine.ILink;
import org.apache.tapestry.event.BrowserEvent;
import org.apache.tapestry.event.EventTarget;
import org.apache.tapestry.internal.event.impl.ComponentEventInvoker;
import org.apache.tapestry.listener.ListenerInvoker;
import org.apache.tapestry.services.ResponseBuilder;
import org.apache.tapestry.valid.IValidationDelegate;
import org.testng.annotations.Test;

/**
* Tests for {@link org.apache.tapestry.form.FormSupportImpl}.
*
* @author Howard M. Lewis Ship
* @since 4.0
*/
@Test
public class FormSupportTest extends BaseComponentTestCase
{
    protected FormSupport newFormSupport(IMarkupWriter writer, IRequestCycle cycle, IForm form)
    {
        return new FormSupportImpl(writer, cycle, form);
    }    
   
    protected FormSupport newFormSupport(IRequestCycle cycle)
    {
        return new FormSupportImpl(cycle);
    }   

    private IRender newComponentRenderBody(final FormSupport fs, final IFormComponent component,
            final IMarkupWriter nested)
    {
        return newComponentsRenderBody(fs, new IFormComponent[]
        { component }, nested);
    }

    private IRender newComponentsRenderBody(final FormSupport fs, final IFormComponent[] component,
            final IMarkupWriter nested)
    {
        return new IRender()
        {
            public void render(IMarkupWriter writer, IRequestCycle cycle)
            {
                assertEquals(nested, writer);

                for (int i = 0; i < component.length; i++)
                    fs.getElementId(component[i]);
            }
        };
    }

    private IValidationDelegate newDelegate()
    {
        return newMock(IValidationDelegate.class);
    }

    protected IEngine newEngine()
    {
        return newMock(IEngine.class);
    }

    private IFormComponent newField()
    {
        return newMock(IFormComponent.class);
    }

    private IFormComponent newFormComponent(String id, String name)
    {
        IFormComponent component = newMock(IFormComponent.class);
        checkOrder(component, false);
       
        expect(component.getSpecifiedId()).andReturn(id);

        component.setName(name);
        component.setClientId(name);
       
        return component;
    }

    private IFormComponent newFormComponent(String id, String extendedId, Location location)
    {
        IFormComponent component = newMock(IFormComponent.class);

        expect(component.getSpecifiedId()).andReturn(id);
       
        trainGetExtendedId(component, extendedId);
        trainGetLocation(component, location);

        return component;
    }

    public void test_Cancel_Rewind()
    {
        IMarkupWriter writer = newWriter();
        IRequestCycle cycle = newCycle();
        IValidationDelegate delegate = newDelegate();
        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, true);

        trainGetPageRenderSupport(cycle, null);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        delegate.clear();
       
        trainGetParameter(cycle, FormSupportImpl.SUBMIT_MODE, "cancel");
       
        // Create a body, just to provie it doesn't get invoked.
       
        IRender body = newMock(IRender.class);
       
        form.setBody(body);
       
        replay();
       
        assertEquals(FormConstants.SUBMIT_CANCEL, fs.rewind());
       
        verify();
    }

    public void test_Complex_Render()
    {
        IMarkupWriter writer = newWriter();
        NestedMarkupWriter nested = newNestedWriter();
        IRequestCycle cycle = newCycle();
        ResponseBuilder builder = newMock(ResponseBuilder.class);
        IValidationDelegate delegate = newDelegate();
        ILink link = newLink();
        IRender render = newRender();

        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, false);
       
        PageRenderSupport support = newPageRenderSupport();

        trainGetPageRenderSupport(cycle, support);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        final IFormComponent barney1 = newFormComponent("barney", "barney");
        final IFormComponent wilma = newFormComponent("wilma", "wilma");
        final IFormComponent barney2 = newFormComponent("barney", "barney_0");

        IRender body = newComponentsRenderBody(fs, new IFormComponent[]
        { barney1, wilma, barney2 }, nested);

        form.setBody(body);

        trainRegister(support, form, "myform");

        trainGetParameterNames(link, new String[]
        { "service" });
        trainGetParameterValues(link, "service", new String[]
        { "fred" });

        trainGetNestedWriter(writer, nested);

        trainGetURL(link, null, "/app");

        writer.begin("form");
        writer.attribute("method", "post");
        writer.attribute("action", "/app");
       
        writer.attribute("id", "myform");

        render.render(writer, cycle);

        writer.println();

        trainHiddenBlock(cycle, builder, writer, form, "fred", "barney,wilma,barney_0");

        nested.close();

        writer.end();
       
        trainGetFocusField(delegate, "wilma");
       
        // effectively means someone else has already claimed focus
       
        trainGetFieldFocus(cycle, null);
       
        support.addInitializationScript(form, "dojo.require(\"tapestry.form\");tapestry.form.focusField('wilma');");
        cycle.setAttribute(FormSupportImpl.FIELD_FOCUS_ATTRIBUTE, Boolean.TRUE);
       
        replay();

        fs.render("post", render, link, null, null);

        verify();
    }

    public void test_Complex_Rewind()
    {
        IMarkupWriter writer = newWriter();
        IRequestCycle cycle = newCycle();
        IValidationDelegate delegate = newDelegate();
        MockForm form = new MockForm(delegate);
        ListenerInvoker listenerInvoker = newMock(ListenerInvoker.class);
       
        ComponentEventInvoker invoker = new ComponentEventInvoker();
        invoker.setInvoker(listenerInvoker);
       
        trainIsRewound(cycle, form, true);
        trainGetPageRenderSupport(cycle, null);
       
        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);
       
        verify();

        delegate.clear();
       
        trainCycleForRewind(cycle, "barney,wilma,barney_0", null);

        final IFormComponent barney1 = newFormComponent("barney", "barney");
        final IFormComponent wilma = newFormComponent("wilma", "wilma");
        final IFormComponent barney2 = newFormComponent("barney", "barney_0");

        IRender body = newComponentsRenderBody(fs, new IFormComponent[]
        { barney1, wilma, barney2 }, writer);

        form.setBody(body);
        form.setEventInvoker(invoker);
       
        trainExtractBrowserEvent(cycle);
       
        replay();
       
        Map props = new HashMap();
        props.put("id", "bsId");
        BrowserEvent event = new BrowserEvent("onclick", new EventTarget(props));
       
        invoker.invokeFormListeners(fs, cycle, event);
       
        assertEquals(FormConstants.SUBMIT_NORMAL, fs.rewind());

        verify();
    }

    public void test_Complex_Submit_Event_Handler()
    {
        IMarkupWriter writer = newWriter();
        NestedMarkupWriter nested = newNestedWriter();
        IRequestCycle cycle = newCycle();
        ResponseBuilder builder = newMock(ResponseBuilder.class);
        IValidationDelegate delegate = newDelegate();
        PageRenderSupport support = newPageRenderSupport();
        ILink link = newLink();
        IRender render = newRender();
       
        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, false);
        trainGetPageRenderSupport(cycle, support);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();
       
        form.setBody(new IRender()
        {
            public void render(IMarkupWriter pwriter, IRequestCycle pcycle)
            {
                fs.addEventHandler(FormEventType.SUBMIT, "mySubmit1");
                fs.addEventHandler(FormEventType.SUBMIT, "mySubmit2");
                fs.addEventHandler(FormEventType.SUBMIT, "mySubmit3");
            }
        });

        trainRegister(support, form, "myform");

        trainGetParameterNames(link, new String[]
        { "service" });

        trainGetParameterValues(link, "service", new String[]
        { "fred" });

        trainGetNestedWriter(writer, nested);

        trainGetURL(link, null, "/app");

        writer.begin("form");
        writer.attribute("method", "post");
        writer.attribute("action", "/app");

        writer.attribute("id", "myform");
       
        support.addInitializationScript(form, "Tapestry.onsubmit('myform', function (event)"
                + "\n{\n  mySubmit1();\n  mySubmit2();\n  mySubmit3();\n});\n");
       
        render.render(writer, cycle);

        writer.println();

        trainHiddenBlock(cycle, builder, writer, form, "fred", "");

        nested.close();

        writer.end();
       
        // Side test: what if no focus field?

        trainGetFocusField(delegate, null);
       
        replay();

        fs.render("post", render, link, null, null);

        verify();
    }

    public void test_Encoding_Type()
    {
        IMarkupWriter writer = newWriter();
        NestedMarkupWriter nested = newNestedWriter();
        IRequestCycle cycle = newCycle();
        ResponseBuilder builder = newMock(ResponseBuilder.class);
        IValidationDelegate delegate = newDelegate();
        PageRenderSupport support = newPageRenderSupport();
        ILink link = newLink();
        IRender render = newRender();

        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, false);

        trainGetPageRenderSupport(cycle, support);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        form.setBody(new IRender()
        {
            public void render(IMarkupWriter pwriter, IRequestCycle pcycle)
            {
                fs.setEncodingType("foo/bar");
            }
        });

        trainRegister(support, form, "myform");

        trainGetParameterNames(link, new String[]
        { "service" });

        trainGetParameterValues(link, "service", new String[]
        { "fred" });

        trainGetNestedWriter(writer, nested);

        trainGetURL(link, null, "/app");

        writer.begin("form");
        writer.attribute("method", "post");
        writer.attribute("action", "/app");
       
        writer.attribute("id", "myform");
        writer.attribute("enctype", "foo/bar");

        render.render(writer, cycle);

        writer.println();

        trainHiddenBlock(cycle, builder, writer, form, "fred", "");

        nested.close();

        writer.end();

        trainGetFocusField(delegate, null);

        replay();

        fs.render("post", render, link, null, null);

        verify();
    }

    public void test_Field_Prerender_Twice()
    {
        IFormComponent field = newField();
        IMarkupWriter writer = newWriter();
        NestedMarkupWriter nested = newNestedWriter();
        IRequestCycle cycle = newCycle();
        Location l = newLocation();
       
        ResponseBuilder builder = newMock(ResponseBuilder.class);

        trainGetExtendedId(field, "foo.bar");

        trainGetNestedWriter(writer, nested);
       
        expect(cycle.getAttribute(TapestryUtils.FIELD_PRERENDER)).andReturn(null);
        cycle.setAttribute(TapestryUtils.FIELD_PRERENDER, field);
       
        expect(cycle.getResponseBuilder()).andReturn(builder);
       
        builder.render(nested, field, cycle);
       
        cycle.removeAttribute(TapestryUtils.FIELD_PRERENDER);
       
        expect(nested.getBuffer()).andReturn("NESTED CONTENT");

        replay();

        FormSupport fs = newFormSupport(cycle);
       
        fs.prerenderField(writer, field, l);
       
        verify();

        trainGetExtendedId(field, "foo.bar");

        replay();

        try
        {
            fs.prerenderField(writer, field, l);
            unreachable();
        }
        catch (ApplicationRuntimeException ex)
        {
            assertEquals(
                    "Field EasyMock for interface org.apache.tapestry.form.IFormComponent has already been pre-rendered. "
                            + "This exception may indicate that a FieldLabel rendered, but the corresponding field did not.",
                    ex.getMessage());

            assertSame(l, ex.getLocation());
            assertSame(field, ex.getComponent());
        }

        verify();

    }

    public void test_Hidden_Values()
    {
        IMarkupWriter writer = newWriter();
        NestedMarkupWriter nested = newNestedWriter();
        IRequestCycle cycle = newCycle();
        ResponseBuilder builder = newMock(ResponseBuilder.class);
        IValidationDelegate delegate = newDelegate();
        PageRenderSupport support = newPageRenderSupport();
        ILink link = newLink();
        IRender render = newRender();

        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, false);

        trainGetPageRenderSupport(cycle, support);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        form.setBody(new IRender()
        {
            public void render(IMarkupWriter pwriter, IRequestCycle pcycle)
            {
                fs.addHiddenValue("hidden1", "value1");
                fs.addHiddenValue("hidden2", "id2", "value2");
            }
        });

        trainRegister(support, form, "myform");

        trainGetParameterNames(link, new String[]
        { "service" });

        trainGetParameterValues(link, "service", new String[]
        { "fred" });

        trainGetNestedWriter(writer, nested);

        trainGetURL(link, null, "/app");

        writer.begin("form");
        writer.attribute("method", "post");
        writer.attribute("action", "/app");
       
        writer.attribute("id", "myform");

        render.render(writer, cycle);

        writer.println();
       
        expect(cycle.getResponseBuilder()).andReturn(builder);
       
        expect(builder.contains(form)).andReturn(false);
       
        trainDiv(writer, form);

        trainHidden(writer, "formids", "");
        trainHidden(writer, "service", "fred");
        trainHidden(writer, "submitmode", "");
        trainHidden(writer, FormConstants.SUBMIT_NAME_PARAMETER, "");
        trainHidden(writer, "hidden1", "value1");
        trainHidden(writer, "hidden2", "id2", "value2");

        writer.end();

        nested.close();

        writer.end();

        trainGetFocusField(delegate, null);

        replay();

        fs.render("post", render, link, null, null);

        verify();
    }

    public void test_Invalid_Encoding_Type()
    {
        IMarkupWriter writer = newWriter();
        NestedMarkupWriter nested = newNestedWriter();
        IRequestCycle cycle = newCycle();
        IValidationDelegate delegate = newDelegate();
        PageRenderSupport support = newPageRenderSupport();
        ILink link = newLink();
        IRender render = newRender();

        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, false);

        trainGetPageRenderSupport(cycle, support);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        form.setBody(new IRender()
        {
            public void render(IMarkupWriter pwriter, IRequestCycle pcycle)
            {
                fs.setEncodingType("foo/bar");
                fs.setEncodingType("zip/zap");
            }
        });

        trainRegister(support, form, "myform");

        trainGetParameterNames(link, new String[]
        { "service" });

        trainGetParameterValues(link, "service", new String[]
        { "fred" });

        trainGetNestedWriter(writer, nested);

        replay();

        try
        {
            fs.render("post", render, link, null, null);
            unreachable();
        }
        catch (ApplicationRuntimeException ex)
        {
            assertEquals(
                    "Components within form SomePage/myform have requested conflicting encoding types 'foo/bar' and 'zip/zap'.",
                    ex.getMessage());
            assertSame(form, ex.getComponent());
        }

        verify();
    }

    public void test_Refresh_Rewind()
    {
        IMarkupWriter writer = newWriter();
        IRequestCycle cycle = newCycle();
        IValidationDelegate delegate = newDelegate();
        MockForm form = new MockForm(delegate);
        ComponentEventInvoker invoker = org.easymock.classextension.EasyMock.createMock(ComponentEventInvoker.class);
       
        trainIsRewound(cycle, form, true);

        trainGetPageRenderSupport(cycle, null);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        delegate.clear();

        trainCycleForRewind(cycle, "refresh", "barney", null);

        final IFormComponent component = newFormComponent("barney", "barney");

        IRender body = newComponentRenderBody(fs, component, writer);

        form.setBody(body);
        form.setEventInvoker(invoker);
       
        trainExtractBrowserEvent(cycle);
       
        invoker.invokeFormListeners(eq(fs), eq(cycle), isA(BrowserEvent.class));
       
        replay();

        assertEquals(FormConstants.SUBMIT_REFRESH, fs.rewind());

        verify();
    }

    public void test_Render_Extra_Reserved_Ids()
    {
        IMarkupWriter writer = newWriter();
        NestedMarkupWriter nested = newNestedWriter();
        IRequestCycle cycle = newCycle();
        ResponseBuilder builder = newMock(ResponseBuilder.class);
        IValidationDelegate delegate = newDelegate();
        PageRenderSupport support = newPageRenderSupport();
        ILink link = newLink();
        IRender render = newRender();

        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, false);

        trainGetPageRenderSupport(cycle, support);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        final IFormComponent component = newFormComponent("action", "action_0");

        IRender body = newComponentRenderBody(fs, component, nested);

        form.setBody(body);

        trainRegister(support, form, "myform");

        trainGetParameterNames(link, new String[]
        { "action" });

        trainGetParameterValues(link, "action", new String[]
        { "fred" });

        trainGetNestedWriter(writer, nested);

        trainGetURL(link, null, "/app");

        writer.begin("form");
        writer.attribute("method", "post");
        writer.attribute("action", "/app");
       
        writer.attribute("id", "myform");

        render.render(writer, cycle);

        writer.println();
       
        expect(cycle.getResponseBuilder()).andReturn(builder);
       
        expect(builder.contains(form)).andReturn(false);
       
        trainDiv(writer, form);

        trainHidden(writer, "formids", "action_0");
        trainHidden(writer, "action", "fred");
        trainHidden(writer, "reservedids", "action");
        trainHidden(writer, "submitmode", "");
        trainHidden(writer, FormConstants.SUBMIT_NAME_PARAMETER, "");

        writer.end();

        nested.close();

        writer.end();

        trainGetFocusField(delegate, null);

        replay();

        fs.render("post", render, link, null, null);

        verify();
    }

    public void test_Reset_Event_Handler()
    {
        IMarkupWriter writer = newWriter();
        NestedMarkupWriter nested = newNestedWriter();
        IRequestCycle cycle = newCycle();
        ResponseBuilder builder = newMock(ResponseBuilder.class);
       
        IValidationDelegate delegate = newDelegate();
        PageRenderSupport support = newPageRenderSupport();
        ILink link = newLink();
        IRender render = newRender();

        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, false);

        trainGetPageRenderSupport(cycle, support);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        form.setBody(new IRender()
        {
            public void render(IMarkupWriter pwriter, IRequestCycle pcycle)
            {
                fs.addEventHandler(FormEventType.RESET, "myReset1");
                fs.addEventHandler(FormEventType.RESET, "myReset2");
            }
        });

        trainRegister(support, form, "myform");

        trainGetParameterNames(link, new String[]
        { "service" });

        trainGetParameterValues(link, "service", new String[]
        { "fred" });

        trainGetNestedWriter(writer, nested);
       
        trainGetURL(link, null, "/app");
       
        writer.begin("form");
        writer.attribute("method", "post");
        writer.attribute("action", "/app");
       
        writer.attribute("id", "myform");
       
        support.addInitializationScript(form, "Tapestry.onreset('myform', function (event)"
                + "\n{\n  myReset1();\n  myReset2();\n});\n");
       
        render.render(writer, cycle);

        writer.println();

        trainHiddenBlock(cycle, builder, writer, form, "fred", "");

        nested.close();

        writer.end();

        trainGetFocusField(delegate, null);

        replay();

        fs.render("post", render, link, null, null);

        verify();
    }

    public void test_Rewind_Extra_Reserved_Ids()
    {
        IMarkupWriter writer = newWriter();
        IRequestCycle cycle = newCycle();
        IValidationDelegate delegate = newDelegate();
        ComponentEventInvoker invoker =
            org.easymock.classextension.EasyMock.createMock(ComponentEventInvoker.class);
       
        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, true);

        trainGetPageRenderSupport(cycle, null);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        delegate.clear();

        trainCycleForRewind(cycle, "action_0", "action");

        final IFormComponent component = newFormComponent("action", "action_0");

        IRender body = newComponentRenderBody(fs, component, writer);

        form.setBody(body);
        form.setEventInvoker(invoker);
       
        trainExtractBrowserEvent(cycle);
       
        invoker.invokeFormListeners(eq(fs), eq(cycle), isA(BrowserEvent.class));
       
        replay();

        assertEquals(FormConstants.SUBMIT_NORMAL, fs.rewind());

        verify();
    }

    public void test_Rewind_Mismatch()
    {
        IMarkupWriter writer = newWriter();
        IRequestCycle cycle = newCycle();
        IValidationDelegate delegate = newDelegate();

        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, true);
        trainGetPageRenderSupport(cycle, null);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        Location l = newLocation();

        delegate.clear();

        // So, the scenario here is that component "pebbles" was inside
        // some kind of conditional that evaluated to true during the render,
        // but is now false on the rewind.

        trainCycleForRewind(cycle, "barney,wilma,pebbles,barney_0", null);
       
        final IFormComponent barney1 = newFormComponent("barney", "barney");
        final IFormComponent wilma = newFormComponent("wilma", "wilma");
        final IFormComponent barney2 = newFormComponent("barney", "SomePage/barney", l);
       
        IRender body = newComponentsRenderBody(fs, new IFormComponent[]
        { barney1, wilma, barney2 }, writer);

        form.setBody(body);

        replay();

        try
        {
            fs.rewind();
            unreachable();
        }
        catch (StaleLinkException ex)
        {
            assertEquals(
                    "Rewind of form SomePage/myform expected allocated id #3 to be 'pebbles', but was 'barney_0' (requested by component SomePage/barney).",
                    ex.getMessage());
            assertSame(barney2, ex.getComponent());
            assertSame(l, ex.getLocation());
        }

        verify();
    }

    public void test_Rewind_Too_Long()
    {
        IMarkupWriter writer = newWriter();
        IRequestCycle cycle = newCycle();
        IValidationDelegate delegate = newDelegate();

        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, true);
        trainGetPageRenderSupport(cycle, null);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        Location l = newLocation();

        delegate.clear();

        // So, the scenario here is that component "barney" was inside
        // some kind of loop that executed once on the render, but twice
        // on the rewind (i.e., an additional object was added in between).

        trainCycleForRewind(cycle, "barney,wilma", null);

        final IFormComponent barney1 = newFormComponent("barney", "barney");
        final IFormComponent wilma = newFormComponent("wilma", "wilma");
        final IFormComponent barney2 = newFormComponent("barney", "SomePage/barney", l);

        IRender body = newComponentsRenderBody(fs, new IFormComponent[]
        { barney1, wilma, barney2 }, writer);

        form.setBody(body);

        replay();

        try
        {
            fs.rewind();
            unreachable();
        }
        catch (StaleLinkException ex)
        {
            assertEquals(
                    "Rewind of form SomePage/myform expected only 2 form elements, but an additional id was requested by component SomePage/barney.",
                    ex.getMessage());
            assertSame(barney2, ex.getComponent());
            assertSame(l, ex.getLocation());
        }

        verify();
    }

    public void test_Rewind_Too_Short()
    {
        Location l = newLocation();
        IMarkupWriter writer = newWriter();
        IRequestCycle cycle = newCycle();
        IValidationDelegate delegate = newDelegate();
        ComponentEventInvoker invoker =
            org.easymock.classextension.EasyMock.createMock(ComponentEventInvoker.class);
       
        MockForm form = new MockForm(delegate, l);

        trainIsRewound(cycle, form, true);
        trainGetPageRenderSupport(cycle, null);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        delegate.clear();

        // So, the scenario here is that component "barney" was inside
        // some kind of loop that executed twice on the render, but only once
        // on the rewind (i.e., the object was deleted in between).

        trainCycleForRewind(cycle, "barney,wilma,barney$0", null);

        final IFormComponent barney1 = newFormComponent("barney", "barney");
        final IFormComponent wilma = newFormComponent("wilma", "wilma");

        IRender body = newComponentsRenderBody(fs, new IFormComponent[]
        { barney1, wilma }, writer);

        form.setBody(body);
        form.setEventInvoker(invoker);
       
        trainExtractBrowserEvent(cycle);
       
        invoker.invokeFormListeners(eq(fs), eq(cycle), isA(BrowserEvent.class));
       
        replay();

        try
        {
            fs.rewind();
            unreachable();
        }
        catch (StaleLinkException ex)
        {
            assertEquals(
                    "Rewind of form SomePage/myform expected 1 more form elements, starting with id 'barney$0'.",
                    ex.getMessage());
            assertSame(form, ex.getComponent());
            assertSame(l, ex.getLocation());
        }

        verify();
    }

    public void test_Simple_Render()
    {
        IMarkupWriter writer = newWriter();
        NestedMarkupWriter nested = newNestedWriter();
        IRequestCycle cycle = newCycle();
        ResponseBuilder builder = newMock(ResponseBuilder.class);
        IValidationDelegate delegate = newDelegate();
        ILink link = newLink();
        IRender render = newRender();

        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, false);

        PageRenderSupport support = newPageRenderSupport();

        trainGetPageRenderSupport(cycle, support);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        final IFormComponent component = newFormComponent("barney", "barney");

        IRender body = newComponentRenderBody(fs, component, nested);

        form.setBody(body);

        trainRegister(support, form, "myform");

        trainGetParameterNames(link, new String[]
        { "service" });
        trainGetParameterValues(link, "service", new String[]
        { "fred" });

        trainGetNestedWriter(writer, nested);

        trainGetURL(link, null, "/app");

        writer.begin("form");
        writer.attribute("method", "post");
        writer.attribute("action", "/app");
       
        writer.attribute("id", "myform");

        render.render(writer, cycle);

        writer.println();

        trainHiddenBlock(cycle, builder, writer, form, "fred", "barney");

        nested.close();

        writer.end();

        trainGetFocusField(delegate, "barney");

        // Side test: check for another form already grabbing focus

        trainGetFieldFocus(cycle, null);
       
        support.addInitializationScript(form, "dojo.require(\"tapestry.form\");tapestry.form.focusField('barney');");
       
        cycle.setAttribute(FormSupportImpl.FIELD_FOCUS_ATTRIBUTE, Boolean.TRUE);
       
        replay();

        fs.render("post", render, link, null, null);

        verify();
    }

    public void test_Simple_Render_With_Deferred_Runnable()
    {
        IMarkupWriter writer = newWriter();
        NestedMarkupWriter nested = newNestedWriter();
        IRequestCycle cycle = newCycle();
        ResponseBuilder builder = newMock(ResponseBuilder.class);
        IValidationDelegate delegate = newDelegate();
        ILink link = newLink();
        IRender render = newRender();

        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, false);

        PageRenderSupport support = newPageRenderSupport();

        trainGetPageRenderSupport(cycle, support);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        IRender body = new IRender()
        {
            public void render(final IMarkupWriter pwriter, IRequestCycle pcycle)
            {
                fs.addDeferredRunnable(new Runnable()
                {

                    public void run()
                    {
                        pwriter.print("DEFERRED");
                    }

                });
            }

        };
       
        form.setBody(body);

        trainRegister(support, form, "myform");

        trainGetParameterNames(link, new String[]
        { "service" });
        trainGetParameterValues(link, "service", new String[]
        { "fred" });

        trainGetNestedWriter(writer, nested);
       
        nested.print("DEFERRED");
       
        trainGetURL(link, null, "/app");

        writer.begin("form");
        writer.attribute("method", "post");
        writer.attribute("action", "/app");
       
        writer.attribute("id", "myform");

        render.render(writer, cycle);

        writer.println();

        trainHiddenBlock(cycle, builder, writer, form, "fred", "");
       
        nested.close();

        writer.end();

        trainGetFocusField(delegate, null);

        replay();

        fs.render("post", render, link, null, null);

        verify();
    }

    public void test_Simple_Render_With_Scheme()
    {
        IMarkupWriter writer = newWriter();
        NestedMarkupWriter nested = newNestedWriter();
        IRequestCycle cycle = newCycle();
        ResponseBuilder builder = newMock(ResponseBuilder.class);
        IValidationDelegate delegate = newDelegate();
        ILink link = newLink();
        IRender render = newRender();
       
        MockForm form = new MockForm(delegate);
       
        trainIsRewound(cycle, form, false);

        PageRenderSupport support = newPageRenderSupport();

        trainGetPageRenderSupport(cycle, support);
       
        replay();
       
        final FormSupport fs = newFormSupport(writer, cycle, form);
       
        verify();

        final IFormComponent component = newFormComponent("barney", "barney");

        IRender body = newComponentRenderBody(fs, component, nested);

        form.setBody(body);

        trainRegister(support, form, "myform");

        trainGetParameterNames(link, new String[]
        { "service" });
        trainGetParameterValues(link, "service", new String[]
        { "fred" });

        trainGetNestedWriter(writer, nested);

        trainGetURL(link, "https", "https://foo.bar/app", 443);

        writer.begin("form");
        writer.attribute("method", "post");
        writer.attribute("action", "https://foo.bar/app");
       
        writer.attribute("id", "myform");

        render.render(writer, cycle);

        writer.println();

        trainHiddenBlock(cycle, builder, writer, form, "fred", "barney");

        nested.close();

        writer.end();
       
        trainGetFocusField(delegate, "barney");
       
        // Side test: check for another form already grabbing focus
       
        trainGetFieldFocus(cycle, Boolean.TRUE);
       
        // support.addInitializationScript(form, "tapestry.form.focusField('barney');");
       
        // cycle.setAttribute(FormSupportImpl.FIELD_FOCUS_ATTRIBUTE, true);
       
        replay();

        fs.render("post", render, link, "https", new Integer(443));

        verify();
    }

    public void test_Simple_Rewind()
    {
        IMarkupWriter writer = newWriter();
        IRequestCycle cycle = newCycle();
        IValidationDelegate delegate = newDelegate();
        MockForm form = new MockForm(delegate);
        ComponentEventInvoker invoker =
            org.easymock.classextension.EasyMock.createMock(ComponentEventInvoker.class);
       
        trainIsRewound(cycle, form, true);

        trainGetPageRenderSupport(cycle, null);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        delegate.clear();

        trainCycleForRewind(cycle, "barney", null);

        final IFormComponent component = newFormComponent("barney", "barney");

        IRender body = newComponentRenderBody(fs, component, writer);

        form.setBody(body);
        form.setEventInvoker(invoker);
       
        trainExtractBrowserEvent(cycle);
       
        invoker.invokeFormListeners(eq(fs), eq(cycle), isA(BrowserEvent.class));
       
        replay();

        assertEquals(FormConstants.SUBMIT_NORMAL, fs.rewind());

        verify();
    }

    public void test_Simple_Rewind_With_Deferred_Runnable()
    {
        IMarkupWriter writer = newWriter();
        IRequestCycle cycle = newCycle();
        IValidationDelegate delegate = newDelegate();
        MockForm form = new MockForm(delegate);
        ComponentEventInvoker invoker =
            org.easymock.classextension.EasyMock.createMock(ComponentEventInvoker.class);
       
        trainIsRewound(cycle, form, true);

        trainGetPageRenderSupport(cycle, null);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();

        delegate.clear();

        trainCycleForRewind(cycle, "", null);

        trainExtractBrowserEvent(cycle);
       
        writer.print("DEFERRED");
       
        invoker.invokeFormListeners(eq(fs), eq(cycle), isA(BrowserEvent.class));
       
        replay();

        IRender body = new IRender()
        {

            public void render(final IMarkupWriter pwriter, IRequestCycle pcycle)
            {
                fs.addDeferredRunnable(new Runnable()
                {
                    public void run()
                    {
                        pwriter.print("DEFERRED");
                    }

                });
            }

        };

        form.setBody(body);
        form.setEventInvoker(invoker);
       
        assertEquals(FormConstants.SUBMIT_NORMAL, fs.rewind());

        verify();
    }

    public void test_Simple_Submit_Event_Handler()
    {
        IMarkupWriter writer = newWriter();
        NestedMarkupWriter nested = newNestedWriter();
        IRequestCycle cycle = newCycle();
        ResponseBuilder builder = newMock(ResponseBuilder.class);
        IValidationDelegate delegate = newDelegate();
        ILink link = newLink();
        IRender render = newRender();

        MockForm form = new MockForm(delegate);

        trainIsRewound(cycle, form, false);

        PageRenderSupport support = newPageRenderSupport();

        trainGetPageRenderSupport(cycle, support);

        replay();

        final FormSupport fs = newFormSupport(writer, cycle, form);

        verify();
       
        trainRegister(support, form, "myform");
       
        trainGetParameterNames(link, new String[]
        { "service" });
        trainGetParameterValues(link, "service", new String[]
        { "fred" });
       
        trainGetNestedWriter(writer, nested);
       
        trainGetURL(link, null, "/app");

        writer.begin("form");
        writer.attribute("method", "post");
        writer.attribute("action", "/app");
       
        writer.attribute("id", "myform");
       
        form.setBody(new IRender()
        {
            public void render(IMarkupWriter pwriter, IRequestCycle pcycle)
            {
                fs.addEventHandler(FormEventType.SUBMIT, "mySubmit()");
            }
        });
       
        support.addInitializationScript(form, "Tapestry.onsubmit('myform', function (event)"
                + "\n{\n  mySubmit();\n});\n");
       
        render.render(writer, cycle);
       
        writer.println();

        trainHiddenBlock(cycle, builder, writer, form, "fred", "");

        nested.close();

        writer.end();

        trainGetFocusField(delegate, null);

        replay();

        fs.render("post", render, link, null, null);

        verify();
    }

    private void trainCycleForRewind(IRequestCycle cycle, String allocatedIds, String reservedIds)
    {
        trainCycleForRewind(cycle, "submit", allocatedIds, reservedIds);
    }

    private void trainCycleForRewind(IRequestCycle cycle, String submitMode, String allocatedIds,
            String reservedIds)
    {
        trainGetParameter(cycle, FormSupportImpl.SUBMIT_MODE, submitMode);
        trainGetParameter(cycle, FormSupportImpl.FORM_IDS, allocatedIds);
        trainGetParameter(cycle, FormSupportImpl.RESERVED_FORM_IDS, reservedIds);
    }

    protected void trainDiv(IMarkupWriter writer, IForm form)
    {
        writer.begin("div");
        writer.attribute("style", "display:none;");
        writer.attribute("id", form.getName() + "hidden");
    }

    private void trainGetFieldFocus(IRequestCycle cycle, Object value)
    {
        expect(cycle.getAttribute(FormSupportImpl.FIELD_FOCUS_ATTRIBUTE)).andReturn(value);
    }

    private void trainGetFocusField(IValidationDelegate delegate, String fieldName)
    {
        expect(delegate.getFocusField()).andReturn(fieldName);
    }

    private void trainGetURL(ILink link, String scheme, String URL, int port)
    {
        // This will change shortly, with the new scheme parameter passed into FormSupport.render()

        expect(link.getURL(scheme, null, port, null, false)).andReturn(URL);
    }
   
    private void trainGetURL(ILink link, String scheme, String URL)
    {
      trainGetURL(link, scheme, URL, 0);
    }

    private void trainHidden(IMarkupWriter writer, String name, String value)
    {
        writer.beginEmpty("input");
        writer.attribute("type", "hidden");
        writer.attribute("name", name);
        writer.attribute("value", value);
        writer.println();
    }

    private void trainHidden(IMarkupWriter writer, String name, String id, String value)
    {
        writer.beginEmpty("input");
        writer.attribute("type", "hidden");
        writer.attribute("name", name);
        writer.attribute("id", id);
        writer.attribute("value", value);
        writer.println();
    }

    protected void trainHiddenBlock(IRequestCycle cycle, ResponseBuilder builder,
            IMarkupWriter writer, IForm form,
            String serviceName, String formIds)
    {
        expect(cycle.getResponseBuilder()).andReturn(builder);
       
        expect(builder.contains(form)).andReturn(false);
       
        trainDiv(writer, form);
       
        trainHidden(writer, "formids", formIds);
        trainHidden(writer, "service", serviceName);
        trainHidden(writer, "submitmode", "");
        trainHidden(writer, FormConstants.SUBMIT_NAME_PARAMETER, "");

        writer.end();
    }

    protected void trainIsRewound(IRequestCycle cycle, IForm form, boolean isRewound)
    {
        expect(cycle.isRewound(form)).andReturn(isRewound);
    }

    private void trainRegister(PageRenderSupport support, IForm form, String formId)
    {
        support.addInitializationScript(form, "dojo.require(\"tapestry.form\");"
                + "tapestry.form.registerForm(\"" + formId + "\");");
    }
}
TOP

Related Classes of org.apache.tapestry.form.FormSupportTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.