/*
 * $Id: TestCopyFormToContext.java 471754 2006-11-06 14:55:09Z husted $
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.struts.chain.commands.generic;

import org.apache.commons.chain2.impl.ContextBase;
import org.apache.struts.action.ActionForm;
import org.apache.struts.chain.contexts.MockActionContext;
import org.apache.struts.config.ActionConfig;
import org.apache.struts.config.FormBeanConfig;
import org.apache.struts.config.FormPropertyConfig;
import org.apache.struts.config.impl.ModuleConfigImpl;
import org.apache.struts.mock.MockFormBean;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * @version $Id: TestCopyFormToContext.java 161516 2005-04-15 19:22:47Z
 *          germuska $
 */
public class TestCopyFormToContext {

    /** contextKey */
    private static final String POST_EXECUTION_CONTEXT_KEY = "afterTest";

    /** context */
    private MockActionContext context = null;

    /**
     * setUp
     */
    @Before
    public void setUp() {
        this.context = new MockActionContext(new ContextBase());

        ModuleConfigImpl moduleConfig = new ModuleConfigImpl("/");

        this.context.setModuleConfig(moduleConfig);

        FormBeanConfig fooFBC = new FormBeanConfig();

        fooFBC.setName("foo");
        fooFBC.setType("org.apache.struts.mock.MockFormBean");
        moduleConfig.addFormBeanConfig(fooFBC);

        FormBeanConfig barFBC = new FormBeanConfig();

        barFBC.setName("bar");
        // use a different type so we can verify lookups better
        barFBC.setType("org.apache.struts.mock.MockActionForm");

        FormPropertyConfig fpc = new FormPropertyConfig();

        fpc.setName("property");
        fpc.setType("java.lang.String");
        fpc.setInitial("test");
        barFBC.addFormPropertyConfig(fpc);
        moduleConfig.addFormBeanConfig(barFBC);

        ActionConfig testActionConfig = new ActionConfig();

        testActionConfig.setPath("/Test");
        testActionConfig.setName("foo");
        testActionConfig.setScope("request");
        moduleConfig.addActionConfig(testActionConfig);

        // otherwise, ActionConfigMatcher will be null and we'll get an NPE...
        moduleConfig.freeze();
    }

    /**
     * testLookupByNameAndRequestScope
     */
    @Test
    public void testLookupByNameAndRequestScope() {
        CopyFormToContext command = new CopyFormToContext();
        String formName = "foo";

        command.setFormName(formName);
        command.setScope("request");
        command.setToKey(POST_EXECUTION_CONTEXT_KEY);

        Assert.assertNull(this.context.get(POST_EXECUTION_CONTEXT_KEY));
        Assert.assertNull(this.context.getRequestScope().get(formName));
        Assert.assertNull(this.context.getSessionScope().get(formName));

        command.execute(this.context);

        Assert.assertNotNull(this.context.get(POST_EXECUTION_CONTEXT_KEY));
        Assert.assertNotNull(this.context.getRequestScope().get(formName));
        Assert.assertNull(this.context.getSessionScope().get(formName));

        Assert.assertSame(this.context.get(POST_EXECUTION_CONTEXT_KEY),
                this.context.getRequestScope().get(formName));

        ActionForm theForm =
            (ActionForm) this.context.get(POST_EXECUTION_CONTEXT_KEY);

        Assert.assertTrue(theForm instanceof MockFormBean);
    }

    /**
     * testLookupByActionPath
     */
    @Test
    public void testLookupByActionPath() {
        CopyFormToContext command = new CopyFormToContext();

        command.setActionPath("/Test");
        command.setToKey(POST_EXECUTION_CONTEXT_KEY);

        // we know this, even though it's not being used for the lookup.
        String formName = "foo";

        Assert.assertNull(this.context.get(POST_EXECUTION_CONTEXT_KEY));
        Assert.assertNull(this.context.getRequestScope().get(formName));
        Assert.assertNull(this.context.getSessionScope().get(formName));

        command.execute(this.context);

        Assert.assertNotNull(this.context.get(POST_EXECUTION_CONTEXT_KEY));
        Assert.assertNotNull(this.context.getRequestScope().get(formName));
        Assert.assertNull(this.context.getSessionScope().get(formName));

        Assert.assertSame(this.context.get(POST_EXECUTION_CONTEXT_KEY),
                this.context.getRequestScope().get(formName));

        ActionForm theForm =
            (ActionForm) this.context.get(POST_EXECUTION_CONTEXT_KEY);

        Assert.assertTrue(theForm instanceof MockFormBean);
    }

    /**
     * testLookupByNameAndSessionScope
     */
    @Test
    public void testLookupByNameAndSessionScope() {
        CopyFormToContext command = new CopyFormToContext();
        String formName = "bar";

        command.setFormName(formName);
        command.setScope("session");
        command.setToKey(POST_EXECUTION_CONTEXT_KEY);

        Assert.assertNull(this.context.get(POST_EXECUTION_CONTEXT_KEY));
        Assert.assertNull(this.context.getRequestScope().get(formName));
        Assert.assertNull(this.context.getSessionScope().get(formName));

        command.execute(this.context);

        Assert.assertNotNull(this.context.get(POST_EXECUTION_CONTEXT_KEY));
        Assert.assertNull(this.context.getRequestScope().get(formName));
        Assert.assertNotNull(this.context.getSessionScope().get(formName));

        Assert.assertSame(this.context.get(POST_EXECUTION_CONTEXT_KEY),
                this.context.getSessionScope().get(formName));
    }

    /**
     * testExceptionHandlingWithNullFormName
     */
    @Test
    public void testExceptionHandlingWithNullFormName() {
        CopyFormToContext command = new CopyFormToContext();

        // skip setting form name to test exception
        // command.setFormName(formName);
        command.setScope("session");
        command.setToKey(POST_EXECUTION_CONTEXT_KEY);

        String formName = "bar";
        Assert.assertNull(this.context.get(POST_EXECUTION_CONTEXT_KEY));
        Assert.assertNull(this.context.getRequestScope().get(formName));
        Assert.assertNull(this.context.getSessionScope().get(formName));

        try {
            command.execute(this.context);
            Assert.fail("Execution should throw an exception when form name is not set.");
        } catch (final IllegalStateException e) {
            e.printStackTrace();
        }
    }

    /**
     * testExceptionHandlingWithNullEverything
     */
    @Test
    public void testExceptionHandlingWithNullEverything() {
        CopyFormToContext command = new CopyFormToContext();
        String formName = "bar";

        // skip setting form name to test exception
        // command.setFormName(formName);
        // command.setScope("session");
        // command.setToKey(POST_EXECUTION_CONTEXT_KEY);
        Assert.assertNull(this.context.get(POST_EXECUTION_CONTEXT_KEY));
        Assert.assertNull(this.context.getRequestScope().get(formName));
        Assert.assertNull(this.context.getSessionScope().get(formName));

        try {
            command.execute(this.context);
            Assert.fail("Execution should throw an exception when no properties are set.");
        } catch (final IllegalStateException e) {
            e.printStackTrace();
        }
    }

    /**
     * testCopyToDefaultContextKey
     */
    @Test
    public void testCopyToDefaultContextKey() {
        CopyFormToContext command = new CopyFormToContext();
        String formName = "foo";

        command.setFormName(formName);
        command.setScope("request");

        Assert.assertNull(this.context.getActionForm());
        Assert.assertNull(this.context.getRequestScope().get(POST_EXECUTION_CONTEXT_KEY));
        Assert.assertNull(this.context.getSessionScope().get(POST_EXECUTION_CONTEXT_KEY));

        command.execute(this.context);

        Assert.assertNotNull(this.context.getActionForm());
        Assert.assertNotNull(this.context.getRequestScope().get(formName));
        Assert.assertNull(this.context.getSessionScope().get(formName));

        Assert.assertSame(this.context.getActionForm(),
                this.context.getRequestScope().get(formName));

        ActionForm theForm = this.context.getActionForm();

        Assert.assertTrue(theForm instanceof MockFormBean);
    }
}
