/*
 * Copyright 2004-2005 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.codehaus.groovy.grails.web.servlet

import org.codehaus.groovy.grails.web.servlet.mvc.AbstractGrailsControllerTests
import org.codehaus.groovy.grails.support.MockStringResourceLoader

/**
 * Tests for the render method
 *
 * @author Graeme Rocher
 */
class RenderMethodTests extends AbstractGrailsControllerTests {

    void testRenderMethodWithStatus() {
        def mockController = ga.getControllerClass("RenderController").newInstance()
        mockController.renderMessageWithStatus.call()

        def response = mockController.response
        assertEquals "test", response.contentAsString
        assertEquals 500, response.status
    }

    // bug GRAILS-3393
    void testMissingNamedArgumentKey() {

        def mockController = ga.getControllerClass("RenderController").newInstance()
        shouldFail(MissingMethodException) {
            mockController.renderBug.call()
        }
    }

    void testRenderObject() {
        def mockController = ga.getControllerClass("RenderController").newInstance()
        mockController.renderObject.call()

        def response = mockController.response
        assertEquals "bar", response.contentAsString
    }

    void testRenderList() {
        def mockController = ga.getControllerClass("RenderController").newInstance()
        mockController.renderList.call()

        def response = mockController.response
        assertEquals "[1, 2, 3]", response.contentAsString
    }

    void testRenderMap() {
        def mockController = ga.getControllerClass("RenderController").newInstance()
        mockController.renderMap.call()

        def response = mockController.response
        assertEquals '["a":1, "b":2]', response.contentAsString
    }

    void testRenderText() {
        runTest {
            def mockController = ga.getControllerClass("RenderController").newInstance()
            mockController.renderText.call()

            def request = mockController.request
            assert request != null
            def response = mockController.response

            assert response != null

            assertEquals "test render", response.contentAsString
        }
    }

    void testRenderXml() {
        runTest {
            def mockController = ga.getControllerClass("RenderController").newInstance()

            mockController.renderXML.call()

            def request = mockController.request
            assert request != null
            def response = mockController.response

            assert response != null

            assertEquals "<hello>world</hello>", response.contentAsString
            assertEquals "text/xml;charset=utf-8", response.contentType
        }
    }

    void testRenderView() {
        def mockController = ga.getControllerClass("RenderController").newInstance()

        mockController.renderView.call()

        assert mockController.modelAndView

        assertEquals '/render/testView', mockController.modelAndView.viewName
    }

    void testRenderViewWithContentType() {
        def mockController = ga.getControllerClass("RenderController").newInstance()

        mockController.renderXmlView.call()

        assert mockController.modelAndView

        assertEquals '/render/xmlView', mockController.modelAndView.viewName
        assertEquals 'text/xml;charset=utf-8', response.contentType
    }

    void testRenderTemplate() {
        def mockController = ga.getControllerClass("RenderController").newInstance()

        request.setAttribute( GrailsApplicationAttributes.CONTROLLER, mockController)
        def resourceLoader = new MockStringResourceLoader()
        resourceLoader.registerMockResource "/render/_testTemplate.gsp", 'hello ${hello}!'
        appCtx.groovyPagesTemplateEngine.resourceLoader = resourceLoader
        webRequest.controllerName = "render"
        mockController.renderTemplate.call()

        def response = mockController.response

        assertEquals "hello world!", response.contentAsString
        assertEquals "text/html;charset=utf-8", response.contentType
    }

    void testRenderTemplateWithCollectionUsingImplicitITVariable() {
        def mockController = ga.getControllerClass('RenderController').newInstance()

        request.setAttribute GrailsApplicationAttributes.CONTROLLER, mockController
        def resourceLoader = new MockStringResourceLoader()
        resourceLoader.registerMockResource '/render/_peopleTemplate.gsp', '${it.firstName} ${it.middleName}<br/>'
        appCtx.groovyPagesTemplateEngine.resourceLoader = resourceLoader
        webRequest.controllerName = 'render'
        mockController.renderTemplateWithCollection.call()

        def resopnse = mockController.response
        assertEquals 'Jacob Ray<br/>Zachary Scott<br/>', response.contentAsString
    }

    void testRenderTemplateWithCollectionUsingExplicitVariableName() {
        def mockController = ga.getControllerClass('RenderController').newInstance()

        request.setAttribute GrailsApplicationAttributes.CONTROLLER, mockController
        def resourceLoader = new MockStringResourceLoader()
        resourceLoader.registerMockResource '/render/_peopleTemplate.gsp', '${person.firstName} ${person.middleName}<br/>'
        appCtx.groovyPagesTemplateEngine.resourceLoader = resourceLoader
        webRequest.controllerName = 'render'
        mockController.renderTemplateWithCollectionAndExplicitVarName.call()

        def resopnse = mockController.response
        assertEquals 'Jacob Ray<br/>Zachary Scott<br/>', response.contentAsString
    }

    void testRenderTemplateWithContentType() {
        def mockController = ga.getControllerClass("RenderController").newInstance()

        request.setAttribute( GrailsApplicationAttributes.CONTROLLER, mockController)
        def resourceLoader = new MockStringResourceLoader()
        resourceLoader.registerMockResource "/render/_xmlTemplate.gsp", '<hello>world</hello>'
        appCtx.groovyPagesTemplateEngine.resourceLoader = resourceLoader
        webRequest.controllerName = "render"
        mockController.renderXmlTemplate.call()

        def response = mockController.response

        assertEquals "<hello>world</hello>", response.contentAsString
        assertEquals "text/xml;charset=utf-8", response.contentType
    }

    protected void onSetUp() {
        gcl.parseClass(
'''
class RenderController {

    def renderBug = {
      render(view:'login', [foo:"bar"])
    }

    def renderView = {
        render(view:'testView')
    }
    def renderXmlView = {
        render(view:'xmlView', contentType:'text/xml')
    }
    def renderObject = {
        render new RenderTest(foo:"bar")
    }
    def renderMessageWithStatus = {
        render text:"test", status:500
    }
    def renderList = {
        render( [1,2,3] )
    }
    def renderMap = {
        render( [a:1, b:2] )
    }
    def renderText = {
        render "test render"
    }
    def renderXML = {
        render(contentType:"text/xml") {
            hello("world")
        }
    }
    def renderTemplate = {
        render(template:"testTemplate", model:[hello:"world"])
    }
    def renderTemplateWithCollection = {
        def people = [[firstName: 'Jacob', middleName: 'Ray'], [firstName: 'Zachary', middleName: 'Scott']]
           render(template:"peopleTemplate", collection: people)
       }
    def renderTemplateWithCollectionAndExplicitVarName = {
            def people = [[firstName: 'Jacob', middleName: 'Ray'], [firstName: 'Zachary', middleName: 'Scott']]
               render(var: 'person', template:"peopleTemplate", collection: people)
    }
    def renderXmlTemplate = {
        render(template:"xmlTemplate",contentType:"text/xml")
    }
}
class RenderTest {
    String foo

    String toString() { foo }
}
'''
        )
    }
}
