/**
 * ÀÌ ¼Ò½º´Â Spring ÇÁ·¹ÀÓ¿öÅ© ¿öÅ©ºÏ¿¡¼­ »ç¿ëÇÑ ¿¹Á¦ ¼Ò½ºÀÔ´Ï´Ù. 
 * ÀÌ ¼Ò½º´Â ¸ðµç °³¹ßÀÚµéÀÌ ÀÚÀ¯·Ó°Ô ¼öÁ¤ ¹× ¹èÆ÷ÇÒ ¼ö ÀÖ½À´Ï´Ù. 
 * ´Ü, ÀÌ ¼Ò½º¸¦ ±â¹ÝÀ¸·Î »õ·Î¿î ¾ÖÇÃ¸®ÄÉÀÌ¼ÇÀ» °³¹ßÇÒ °æ¿ì ÃâÃ³¸¦ ¸í½ÃÇØ ÁÖ½Ã¸é µË´Ï´Ù. 
 */
package net.javajigi.user.web;

import java.util.HashMap;
import java.util.Map;

import junit.framework.TestCase;
import net.javajigi.user.model.User;
import net.javajigi.user.service.UserService;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.easymock.MockControl;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.servlet.ModelAndView;
import org.springmodules.commons.validator.DefaultBeanValidator;
import org.springmodules.commons.validator.DefaultValidatorFactory;

public class UserFormControllerTest extends TestCase {
	protected final Log logger = LogFactory.getLog(getClass());

	private MockControl control = null;

	private UserService mock = null;

	private UserFormController c = null;

	private MockHttpServletRequest request = null;

	private ModelAndView mv = null;

	protected void setUp() throws Exception {
		control = MockControl.createControl(UserService.class);
		mock = (UserService) control.getMock();
		c = new UserFormController();
		c.setUserService(mock);
		c.setCommandName("user");
		c.setCommandClass(User.class);
		c.setFormView("user/edit");
		c.setSuccessView("redirect:/user/listUser.do");

		Validator[] validators = { getValidator(), new UserValidator() };
		c.setValidators(validators);

		StaticApplicationContext ctx = new StaticApplicationContext();
		Map properties = new HashMap();
		properties.put("basename", "Messages");
		ctx.registerSingleton("messageSource",
				ResourceBundleMessageSource.class, new MutablePropertyValues(
						properties));

		ctx.refresh();
		c.setApplicationContext(ctx);

	}

	private DefaultBeanValidator getValidator() {
		DefaultBeanValidator validator = new DefaultBeanValidator();
		DefaultValidatorFactory factory = new DefaultValidatorFactory();
		factory.setValidationConfigLocations(new Resource[] {
				new ClassPathResource("/WEB-INF/validator-rules.xml"),
				new ClassPathResource("/WEB-INF/validation.xml") });
		validator.setValidatorFactory(factory);
		return validator;
	}

	protected void tearDown() throws Exception {
		request = null;
	}

	public void testAddForm() throws Exception {
		request = new MockHttpServletRequest("GET", "/user/editUser.do");

		mv = c.handleRequest(request, new MockHttpServletResponse());
		assertEquals("user/edit", mv.getViewName());
	}

	public void testEditForm() throws Exception {
		User user = populateUser();

		mock.findUser("javajigi");
		control.setReturnValue(user);
		control.replay();

		request = new MockHttpServletRequest("GET", "/user/editUser.do");
		request.addParameter("userId", "javajigi");

		mv = c.handleRequest(request, new MockHttpServletResponse());
		assertEquals("user/edit", mv.getViewName());
		assertEquals(user, mv.getModel().get("user"));
	}

	public void testAdd() throws Exception {
		User user = populateUser();

		mock.findUser("javajigi");
		control.setReturnValue(user);
		mock.addUser(user);
		control.setReturnValue(1);
		control.replay();

		request = new MockHttpServletRequest("POST", "/user/editUser.do");
		request.addParameter("userId", "javajigi");
		request.addParameter("password", "password");
		request.addParameter("password2", "password");
		request.addParameter("name", "¹ÚÀç¼º");
		request.addParameter("email", "javajigi@javajigi.net");
		request.addParameter("admin", "true");
		request.addParameter("add", "È¸¿ø°¡ÀÔ");

		mv = c.handleRequest(request, new MockHttpServletResponse());
		Errors errors = (Errors) mv.getModel().get(
				BindException.ERROR_KEY_PREFIX + "user");
		assertNull(errors);
		assertEquals("redirect:/index.do", mv.getViewName());
	}

	public void testAddRequiredValidationError() throws Exception {
		User user = populateUser();

		mock.findUser("javajigi");
		control.setReturnValue(user);
		mock.addUser(user);
		control.setReturnValue(1);
		control.replay();

		request = new MockHttpServletRequest("POST", "/user/editUser.do");
		request.addParameter("userId", "javajigi");
		request.addParameter("add", "È¸¿ø°¡ÀÔ");

		mv = c.handleRequest(request, new MockHttpServletResponse());
		Errors errors = (Errors) mv.getModel().get(
				BindException.ERROR_KEY_PREFIX + "user");
		assertNotNull(errors);
		assertEquals(2, errors.getErrorCount());
		assertEquals("user/edit", mv.getViewName());
	}

	public void testAddValidationError() throws Exception {
		User user = populateUser();

		mock.findUser("javajigi");
		control.setReturnValue(user);
		mock.addUser(user);
		control.setReturnValue(1);
		control.replay();

		request = new MockHttpServletRequest("POST", "/user/editUser.do");
		request.addParameter("userId", "javajigi");
		request.addParameter("password", "password");
		request.addParameter("password2", "passw");
		request.addParameter("name", "¹ÚÀç¼º");
		request.addParameter("email", "javajigi@");
		request.addParameter("admin", "true");
		request.addParameter("add", "È¸¿ø°¡ÀÔ");

		mv = c.handleRequest(request, new MockHttpServletResponse());
		Errors errors = (Errors) mv.getModel().get(
				BindException.ERROR_KEY_PREFIX + "user");
		assertNotNull(errors);
		assertEquals(2, errors.getErrorCount());
		assertEquals("user/edit", mv.getViewName());
	}

	public void testEdit() throws Exception {
		User user = populateUser();

		mock.findUser("javajigi");
		control.setReturnValue(user);
		mock.updateUser(user);
		control.setReturnValue(1);
		control.replay();

		request = new MockHttpServletRequest("POST", "/user/editUser.do");
		request.addParameter("userId", "javajigi");
		request.addParameter("password", "password");
		request.addParameter("password2", "password");
		request.addParameter("name", "¹ÚÀç¼º");
		request.addParameter("email", "javajigi@javajigi.net");
		request.addParameter("admin", "true");
		request.addParameter("modify", "¼öÁ¤");

		mv = c.handleRequest(request, new MockHttpServletResponse());

		assertEquals("redirect:/index.do", mv.getViewName());
		Errors errors = (Errors) mv.getModel().get(
				BindException.ERROR_KEY_PREFIX + "user");
		assertNull(errors);
		assertEquals("redirect:/index.do", mv.getViewName());
	}

	private User populateUser() {
		User user = new User();
		user.setUserId("javajigi");
		user.setPassword("password");
		user.setName("¹ÚÀç¼º");
		user.setEmail("javajigi@gmail.com");
		user.setAdmin(true);

		return user;
	}
}