/*
 * 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.myfaces.test.base;

import java.util.Iterator;

/**
 * <p>Abstract base class for testing <code>ViewController</code>
 * implementations.</p>
 *
 * <p><strong>WARNING</strong> - If you choose to subclass this class, be sure
 * your <code>setUp()</code> and <code>tearDown()</code> methods call
 * <code>super.setUp()</code> and <code>super.tearDown()</code> respectively,
 * and that you implement your own <code>suite()</code> method that exposes
 * the test methods for your test case.</p>
 */
public abstract class AbstractViewControllerTestCase extends AbstractJsfTestCase {

    // ------------------------------------------------------------ Constructors


    /**
     * <p>Construct a new instance of this test case.</p>
     *
     * @param name Test case name
     */
    public AbstractViewControllerTestCase(String name) {
        super(name);
    }


    // ---------------------------------------------------- Overall Test Methods


    // ------------------------------------------------------ Instance Variables


    // ------------------------------------------------------- Protected Methods


    /**
     * <p>Test that the specified number of messages have been queued on the
     * <code>FacesContext</code> instance, without regard to matching a
     * particular client identifier.</p>
     *
     * @param expected The expected number of messages
     */
    protected void checkMessageCount(int expected) {

        int actual = 0;
        Iterator messages = facesContext.getMessages();
        while (messages.hasNext()) {
            messages.next();
            actual++;
        }
        assertEquals("Complete message count", expected, actual);

    }


    /**
     * <p>Test that the specified number of messages have been queued on the
     * <code>FacesContext</code> instance, for the specified client id.</p>
     *
     * @param clientId Client identifier of the component for which to
     *  count queued messages
     * @param expected The expected number of messages
     */
    protected void checkMessageCount(String clientId, int expected) {

        int actual = 0;
        Iterator messages = facesContext.getMessages(clientId);
        while (messages.hasNext()) {
            messages.next();
            actual++;
        }
        assertEquals("Complete message count", expected, actual);

    }


}
