/*
 * Copyright 2002-2008 the original author or authors.
 *
 * 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.springframework.samples.petclinic.web;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.springframework.samples.petclinic.Clinic;
import org.springframework.samples.petclinic.Owner;
import org.springframework.samples.petclinic.Pet;
import org.springframework.samples.petclinic.PetType;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.MapBindingResult;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.bind.support.SimpleSessionStatus;

/**
 * Unit tests for {@link PetController}.
 * 
 * @author Chris Beams
 */
public class PetControllerTests {
    private PetController petController;
    private Pet fido;
    private Clinic clinic;
    private Owner fidoOwner;

    private Model model;
    private BindingResult result;
    private SessionStatus status;

    @Before
    public void setUp() {
        model = new ExtendedModelMap();
        result = new MapBindingResult(model.asMap(), "pet");
        status = new SimpleSessionStatus();

        PetType dog = new PetType();
        dog.setId(1);
        dog.setName("dog");

        fido = new Pet();
        fido.setId(1);
        fido.setName("fido");
        fido.setBirthDate(new Date());
        fido.setType(dog);

        fidoOwner = new Owner();
        fidoOwner.setId(99);
        fidoOwner.addPet(fido);

        clinic = EasyMock.createMock(Clinic.class);

        petController = new PetController(clinic);
    }

    @Test
    public void populatePetTypes() {
        Collection<PetType> petTypeList = new ArrayList<PetType>();
        EasyMock.expect(clinic.getPetTypes()).andReturn(petTypeList);
        EasyMock.replay(clinic);

        assertThat(petController.populatePetTypes(), is(petTypeList));
    }

    @Test
    public void setupAddForm() {
        EasyMock.expect(clinic.loadOwner(1)).andReturn(new Owner());
        EasyMock.replay(clinic);

        Model model = new ExtendedModelMap();
        String viewName = petController.add(1, model);
        assertThat(viewName, equalTo(PetController.PET_FORM_VIEW));
        assertTrue(model.containsAttribute("pet"));
        assertNotNull(((Pet) model.asMap().get("pet")).getOwner());
    }

    @Test
    public void setupEditForm() {
        EasyMock.expect(clinic.loadPet(1)).andReturn(new Pet());
        EasyMock.replay(clinic);

        String viewName = petController.edit(1, model);
        assertThat(viewName, equalTo(PetController.PET_FORM_VIEW));
        assertTrue(model.containsAttribute("pet"));
    }

    @Test
    public void submitUpdateWithoutBindingErrors() {
        String viewName = petController.update(fido, result, status);
        assertThat(viewName, equalTo(ViewUtils.getRedirectForOwner(fido.getOwner())));
    }

    @Test
    public void submitUpdateWithBindingErrors() {
        result.addError(new FieldError("pet", "name", "name must not be null"));

        String viewName = petController.update(fido, result, status);
        assertThat(viewName, equalTo(PetController.PET_FORM_VIEW));
    }

    @Test
    public void submitUpdateWithValidationErrors() {
        fido.setName(""); // invalid name

        String viewName = petController.update(fido, result, status);
        assertThat(viewName, equalTo(PetController.PET_FORM_VIEW));
    }

}
