1/* Copyright 2008 the original author or authors.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *      http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15package grails.test
16
17import groovy.xml.StreamingMarkupBuilder
18import grails.util.GrailsNameUtils
19
20/**
21 * Support class for writing unit tests for controllers. Its main job
22 * is to mock the various properties and methods that Grails injects
23 * into controllers. By default it determines what controller to mock
24 * based on the name of the test, but this can be overridden by one
25 * of the constructors.
26 *
27 * @author Graeme Rocher
28 * @author Peter Ledbrook
29 */
30class ControllerUnitTestCase extends MvcUnitTestCase {
31
32    protected controller
33
34    /**
35     * Creates a new test case for the controller that is in the same
36     * package as the test case and has the same prefix before "Controller"
37     * in its name. For example, if the class name of the test were
38     * <code>org.example.TestControllerTests</code>, this constructor
39     * would mock <code>org.example.TestController</code>.
40     */
41    ControllerUnitTestCase() {
42        super("Controller")
43    }
44
45    /**
46     * Creates a new test case for the given controller class.
47     */
48    ControllerUnitTestCase(Class controllerClass) {
49        super(controllerClass)
50    }
51
52    protected void setUp() {
53        super.setUp()
54        mockController(testClass)
55        controller = newInstance()
56    }
57
58    Class getControllerClass() {
59        return testClass
60    }
61
62    /**
63     * Mocks a command object class, providing a "validate()" method
64     * and access to the "errors" property.
65     */
66    protected mockCommandObject(Class clazz) {
67        registerMetaClass(clazz)
68        MockUtils.mockCommandObject(clazz, errorsMap)
69    }
70
71    /**
72     * Sets an XML string as the body of the mock HTTP request. The
73     * string is converted to bytes based on a UTF-8 encoding.
74     */
75    protected void setXmlRequestContent(String content) {
76        setXmlRequestContent("UTF-8", content)
77    }
78
79    /**
80     * Sets an XML string as the body of the mock HTTP request. The
81     * given string is converted to bytes according to the given encoding.
82     */
83    protected void setXmlRequestContent(String encoding, String content) {
84        mockRequest.contentType = "application/xml; charset=$encoding"
85        mockRequest.content = content.getBytes(encoding)
86    }
87
88    /**
89     * Sets the body of the mock HTTP request to some XML. The XML is
90     * provided as an XmlBuilder-compliant closure. The XML is encoded
91     * to bytes using UTF-8.
92     */
93    protected void setXmlRequestContent(Closure c) {
94        setXmlRequestContent("UTF-8", c)
95    }
96
97    /**
98     * Sets the body of the mock HTTP request to some XML. The XML is
99     * provided as an XmlBuilder-compliant closure. The XML is encoded
100     * to bytes using the specified encoding.
101     */
102    protected void setXmlRequestContent(String encoding, Closure c) {
103        def xml = new StreamingMarkupBuilder(encoding: encoding).bind(c)
104        def out = new ByteArrayOutputStream()
105        out << xml
106
107        mockRequest.contentType = "application/xml; charset=$encoding"
108        mockRequest.content = out.toByteArray()
109    }
110
111    protected Object newInstance() {
112        def instance = super.newInstance()
113        webRequest.controllerName = GrailsNameUtils.getLogicalPropertyName(
114      		  instance.getClass().name, "Controller")
115        return instance
116    }
117}
118