| package org.codehaus.groovy.grails.scaffolding; |
| |
| import groovy.lang.Closure; |
| import groovy.lang.GroovyClassLoader; |
| import groovy.lang.GroovyObject; |
| import groovy.lang.MissingMethodException; |
| import groovy.lang.MissingPropertyException; |
| import groovy.lang.ProxyMetaClass; |
| |
| import java.util.Properties; |
| |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.codehaus.groovy.grails.commons.DefaultGrailsApplication; |
| import org.codehaus.groovy.grails.commons.GrailsApplication; |
| import org.codehaus.groovy.grails.commons.metaclass.PropertyAccessProxyMetaClass; |
| import org.codehaus.groovy.grails.commons.spring.SpringConfig; |
| import org.codehaus.groovy.grails.orm.hibernate.cfg.DefaultGrailsDomainConfiguration; |
| import org.codehaus.groovy.grails.web.metaclass.ControllerDynamicMethods; |
| import org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper; |
| import org.codehaus.groovy.grails.web.servlet.mvc.SimpleGrailsControllerHelper; |
| import org.hibernate.SessionFactory; |
| import org.springframework.beans.MutablePropertyValues; |
| import org.springframework.beans.factory.config.BeanDefinition; |
| import org.springframework.beans.factory.config.ConstructorArgumentValues; |
| import org.springframework.beans.factory.support.RootBeanDefinition; |
| import org.springframework.context.ConfigurableApplicationContext; |
| import org.springframework.context.support.GenericApplicationContext; |
| import org.springframework.mock.web.MockHttpServletRequest; |
| import org.springframework.mock.web.MockHttpServletResponse; |
| import org.springframework.mock.web.MockServletContext; |
| import org.springframework.test.AbstractDependencyInjectionSpringContextTests; |
| import org.springframework.web.servlet.ModelAndView; |
| import org.springmodules.beans.factory.drivers.xml.XmlApplicationContextDriver; |
| |
| public class ControllerScaffoldingTests extends |
| AbstractDependencyInjectionSpringContextTests { |
| |
| private GenericApplicationContext localContext; |
| private ConfigurableApplicationContext appCtx; |
| private GrailsApplication grailsApplication; |
| private SessionFactory sessionFactory; |
| private Class domainClass; |
| private Class controllerClass; |
| |
| protected void onSetUp() throws Exception { |
| GroovyClassLoader cl = new GroovyClassLoader(); |
| Thread.currentThread().setContextClassLoader(cl); |
| |
| |
| Class tmpClass = cl.parseClass( "class ScaffoldController {\n" + |
| "@Property boolean scaffold = true" + |
| "}" ); |
| |
| |
| Class tmpClass2 = cl.parseClass( "class Scaffold {\n" + |
| "@Property Long id\n" + |
| "@Property Long version\n" + |
| "@Property String name\n" + |
| "}" ); |
| |
| this.controllerClass = tmpClass; |
| this.domainClass = tmpClass2; |
| |
| //grailsApplication = new DefaultGrailsApplication(,cl); |
| this.localContext = new GenericApplicationContext(super.applicationContext); |
| |
| |
| |
| ConstructorArgumentValues args = new ConstructorArgumentValues(); |
| args.addGenericArgumentValue(new Class[]{ controllerClass, domainClass}); |
| args.addGenericArgumentValue(cl); |
| MutablePropertyValues propValues = new MutablePropertyValues(); |
| |
| BeanDefinition grailsApplicationBean = new RootBeanDefinition(DefaultGrailsApplication.class,args,propValues); |
| |
| localContext.registerBeanDefinition( "grailsApplication", grailsApplicationBean ); |
| this.localContext.refresh(); |
| |
| /*BeanDefinition applicationEventMulticaster = new RootBeanDefinition(SimpleApplicationEventMulticaster.class); |
| context.registerBeanDefinition( "applicationEventMulticaster ", applicationEventMulticaster);*/ |
| |
| this.grailsApplication = (GrailsApplication)localContext.getBean("grailsApplication"); |
| DefaultGrailsDomainConfiguration config = new DefaultGrailsDomainConfiguration(); |
| config.setGrailsApplication(this.grailsApplication); |
| Properties props = new Properties(); |
| props.put("hibernate.connection.username","sa"); |
| props.put("hibernate.connection.password",""); |
| props.put("hibernate.connection.url","jdbc:hsqldb:mem:grailsDB"); |
| props.put("hibernate.connection.driver_class","org.hsqldb.jdbcDriver"); |
| props.put("hibernate.dialect","org.hibernate.dialect.HSQLDialect"); |
| props.put("hibernate.hbm2ddl.auto","create-drop"); |
| config.setProperties(props); |
| //originalClassLoader = Thread.currentThread().getContextClassLoader(); |
| Thread.currentThread().setContextClassLoader(cl); |
| this.sessionFactory = config.buildSessionFactory(); |
| assertNotNull(this.sessionFactory); |
| |
| |
| |
| SpringConfig springConfig = new SpringConfig(grailsApplication); |
| this.appCtx = (ConfigurableApplicationContext) |
| new XmlApplicationContextDriver().getApplicationContext( |
| springConfig.getBeanReferences(), this.localContext); |
| |
| assertNotNull(appCtx); |
| |
| GroovyObject domainObject = (GroovyObject)domainClass.newInstance(); |
| domainObject.setProperty("name", "fred"); |
| domainObject.invokeMethod("save", new Object[0]); |
| |
| GroovyObject domainObject2 = (GroovyObject)domainClass.newInstance(); |
| domainObject2.setProperty("name", "wilma"); |
| domainObject2.invokeMethod("save", new Object[0]); |
| |
| super.onSetUp(); |
| } |
| |
| public void testScaffoldList() throws Exception { |
| |
| MockHttpServletRequest request = new MockHttpServletRequest(); |
| MockHttpServletResponse response = new MockHttpServletResponse(); |
| request.setRequestURI("/scaffold/list"); |
| |
| GroovyObject go = configureDynamicGO(controllerClass, grailsApplication,request,response); |
| |
| // first test redirection within the same controller |
| try { |
| Closure closure = (Closure)go.getProperty("list"); |
| Object returnValue = closure.call(); |
| assertNotNull(returnValue); |
| assertTrue(returnValue instanceof ModelAndView); |
| ModelAndView mv = (ModelAndView)returnValue; |
| assertEquals("/scaffold/list",mv.getViewName()); |
| assertTrue(mv.getModel().containsKey("scaffoldList")); |
| } |
| catch(MissingMethodException mme) { |
| fail("Missing method exception should not have been thrown!"); |
| } |
| catch(MissingPropertyException mpex) { |
| fail("Missing property exception should not have been thrown!"); |
| } |
| } |
| |
| public void testScaffoldDelete() throws Exception { |
| |
| MockHttpServletRequest request = new MockHttpServletRequest(); |
| MockHttpServletResponse response = new MockHttpServletResponse(); |
| request.setRequestURI("/scaffold/delete"); |
| request.addParameter("id", "1"); |
| |
| GroovyObject go = configureDynamicGO(controllerClass, grailsApplication,request,response); |
| |
| // first test redirection within the same controller |
| try { |
| Closure closure = (Closure)go.getProperty("delete"); |
| Object returnValue = closure.call(); |
| assertNotNull(returnValue); |
| assertTrue(returnValue instanceof ModelAndView); |
| ModelAndView mv = (ModelAndView)returnValue; |
| // should delegate to list |
| assertEquals("/scaffold/list",mv.getViewName()); |
| assertTrue(mv.getModel().containsKey("scaffoldList")); |
| assertNull(mv.getModel().get("scaffold")); |
| } |
| catch(MissingMethodException mme) { |
| fail("Missing method exception should not have been thrown!"); |
| } |
| catch(MissingPropertyException mpex) { |
| fail("Missing property exception should not have been thrown!"); |
| } |
| } |
| |
| public void testScaffoldSave() throws Exception { |
| |
| MockHttpServletRequest request = new MockHttpServletRequest(); |
| MockHttpServletResponse response = new MockHttpServletResponse(); |
| request.setRequestURI("/scaffold/save"); |
| request.addParameter("name", "dino"); |
| |
| GroovyObject go = configureDynamicGO(controllerClass, grailsApplication,request,response); |
| |
| // first test redirection within the same controller |
| try { |
| Closure closure = (Closure)go.getProperty("save"); |
| Object returnValue = closure.call(); |
| assertNotNull(returnValue); |
| assertTrue(returnValue instanceof ModelAndView); |
| ModelAndView mv = (ModelAndView)returnValue; |
| // should end up at the show view |
| assertEquals("/scaffold/show",mv.getViewName()); |
| // and contain the appropriate model |
| assertTrue(mv.getModel().containsKey("scaffold")); |
| GroovyObject domainObject = (GroovyObject)mv.getModel().get("scaffold"); |
| assertNotNull(domainObject); |
| assertEquals("dino", domainObject.getProperty("name")); |
| } |
| catch(MissingMethodException mme) { |
| fail("Missing method exception should not have been thrown!"); |
| } |
| catch(MissingPropertyException mpex) { |
| fail("Missing property exception should not have been thrown!"); |
| } |
| } |
| |
| public void testScaffoldUpdate() throws Exception { |
| |
| MockHttpServletRequest request = new MockHttpServletRequest(); |
| MockHttpServletResponse response = new MockHttpServletResponse(); |
| request.setRequestURI("/scaffold/update"); |
| request.addParameter("id", "1"); |
| request.addParameter("name", "fredjnr"); |
| |
| GroovyObject go = configureDynamicGO(controllerClass, grailsApplication,request,response); |
| |
| // first test redirection within the same controller |
| try { |
| Closure closure = (Closure)go.getProperty("update"); |
| Object returnValue = closure.call(); |
| assertNotNull(returnValue); |
| assertTrue(returnValue instanceof ModelAndView); |
| ModelAndView mv = (ModelAndView)returnValue; |
| // should end up at the show view |
| assertEquals("/scaffold/show",mv.getViewName()); |
| // and contain the appropriate model |
| assertTrue(mv.getModel().containsKey("scaffold")); |
| GroovyObject domainObject = (GroovyObject)mv.getModel().get("scaffold"); |
| assertNotNull(domainObject); |
| assertEquals("fredjnr", domainObject.getProperty("name")); |
| } |
| catch(MissingMethodException mme) { |
| fail("Missing method exception should not have been thrown!"); |
| } |
| catch(MissingPropertyException mpex) { |
| fail("Missing property exception should not have been thrown!"); |
| } |
| } |
| |
| public void testScaffoldShow() throws Exception { |
| |
| MockHttpServletRequest request = new MockHttpServletRequest(); |
| MockHttpServletResponse response = new MockHttpServletResponse(); |
| request.setRequestURI("/scaffold/show"); |
| request.addParameter("id", "1"); |
| |
| GroovyObject go = configureDynamicGO(controllerClass, grailsApplication,request,response); |
| |
| // first test redirection within the same controller |
| try { |
| Closure closure = (Closure)go.getProperty("show"); |
| Object returnValue = closure.call(); |
| assertNotNull(returnValue); |
| assertTrue(returnValue instanceof ModelAndView); |
| ModelAndView mv = (ModelAndView)returnValue; |
| assertEquals("/scaffold/show",mv.getViewName()); |
| assertTrue(mv.getModel().containsKey("scaffold")); |
| |
| // now try a rubish id |
| request = new MockHttpServletRequest(); |
| request.setRequestURI("/scaffold/show"); |
| request.addParameter("id", "13423"); |
| go = configureDynamicGO(controllerClass, grailsApplication,request,response); |
| |
| closure = (Closure)go.getProperty("show"); |
| returnValue = closure.call(); |
| assertNotNull(returnValue); |
| assertTrue(returnValue instanceof ModelAndView); |
| mv = (ModelAndView)returnValue; |
| assertEquals("/scaffold/show",mv.getViewName()); |
| assertTrue(mv.getModel().containsKey("scaffold")); |
| |
| // now try a different action name that uses the same class |
| // to implement scaffolding |
| request = new MockHttpServletRequest(); |
| request.setRequestURI("/scaffold/edit"); |
| request.addParameter("id", "1"); |
| go = configureDynamicGO(controllerClass, grailsApplication,request,response); |
| |
| closure = (Closure)go.getProperty("edit"); |
| returnValue = closure.call(); |
| assertNotNull(returnValue); |
| assertTrue(returnValue instanceof ModelAndView); |
| mv = (ModelAndView)returnValue; |
| assertEquals("/scaffold/edit",mv.getViewName()); |
| assertTrue(mv.getModel().containsKey("scaffold")); |
| |
| } |
| catch(MissingMethodException mme) { |
| fail("Missing method exception should not have been thrown!"); |
| } |
| catch(MissingPropertyException mpex) { |
| fail("Missing property exception should not have been thrown!"); |
| } |
| } |
| |
| |
| |
| private GroovyObject configureDynamicGO(Class groovyClass,GrailsApplication application, HttpServletRequest request, HttpServletResponse response) |
| throws Exception { |
| ProxyMetaClass pmc = PropertyAccessProxyMetaClass.getInstance(groovyClass); |
| // proof of concept to try out proxy meta class |
| |
| BeanDefinition bd = new RootBeanDefinition(groovyClass,false); |
| localContext.registerBeanDefinition( groovyClass.getName(), bd ); |
| |
| |
| GrailsControllerHelper helper = new SimpleGrailsControllerHelper(application,this.appCtx, new MockServletContext()); |
| GroovyObject go = (GroovyObject)groovyClass.newInstance(); |
| pmc.setInterceptor( new ControllerDynamicMethods(go,helper,request,response) ); |
| |
| |
| go.setMetaClass( pmc ); |
| return go; |
| } |
| |
| protected String[] getConfigLocations() { |
| return new String[] { "org/codehaus/groovy/grails/scaffolding/grails-scaffolding-tests.xml" }; |
| } |
| |
| |
| } |