grails.testing.web.GrailsWebUnitTest.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of grace-test-support Show documentation
Show all versions of grace-test-support Show documentation
Grace Framework : Grace Test Support
/*
* Copyright 2016-2023 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
*
* https://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 grails.testing.web
import groovy.text.Template
import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.springframework.mock.web.MockHttpSession
import org.springframework.mock.web.MockServletContext
import grails.artefact.TagLibrary
import grails.core.GrailsClass
import grails.core.GrailsControllerClass
import grails.core.gsp.GrailsTagLibClass
import grails.util.GrailsNameUtils
import grails.web.mvc.FlashScope
import grails.web.servlet.mvc.GrailsParameterMap
import org.grails.buffer.GrailsPrintWriter
import org.grails.commons.CodecArtefactHandler
import org.grails.commons.DefaultGrailsCodecClass
import org.grails.core.artefact.ControllerArtefactHandler
import org.grails.core.artefact.gsp.TagLibArtefactHandler
import org.grails.gsp.GroovyPagesTemplateEngine
import org.grails.plugins.codecs.DefaultCodecLookup
import org.grails.plugins.testing.GrailsMockHttpServletRequest
import org.grails.plugins.testing.GrailsMockHttpServletResponse
import org.grails.taglib.TagLibraryLookup
import org.grails.testing.GrailsUnitTest
import org.grails.web.servlet.mvc.GrailsWebRequest
import org.grails.web.util.GrailsApplicationAttributes
@CompileStatic
@Slf4j
trait GrailsWebUnitTest implements GrailsUnitTest {
private final Set loadedCodecs = new HashSet()
static Map groovyPages = [:]
GrailsWebRequest webRequest
GrailsMockHttpServletRequest getRequest() {
(GrailsMockHttpServletRequest) getWebRequest().getCurrentRequest()
}
GrailsMockHttpServletResponse getResponse() {
(GrailsMockHttpServletResponse) getWebRequest().getCurrentResponse()
}
MockServletContext getServletContext() {
(MockServletContext) optionalServletContext
}
Map getViews() {
groovyPages
}
/**
* The {@link org.springframework.mock.web.MockHttpSession} instance
*/
MockHttpSession getSession() {
(MockHttpSession) request.session
}
/**
* @return The status code of the response
*/
int getStatus() {
response.status
}
/**
* The Grails 'params' object which is an instance of {@link grails.web.servlet.mvc.GrailsParameterMap}
*/
GrailsParameterMap getParams() {
webRequest.getParams()
}
/**
* The Grails 'flash' object
* @return
*/
FlashScope getFlash() {
webRequest.getFlashScope()
}
@CompileDynamic
Object mockTagLib(Class> tagLibClass) {
GrailsTagLibClass tagLib = grailsApplication.addArtefact(TagLibArtefactHandler.TYPE, tagLibClass)
TagLibraryLookup tagLookup = applicationContext.getBean(TagLibraryLookup)
defineBeans {
"${tagLib.fullName}"(tagLibClass) { bean ->
bean.autowire = true
}
}
tagLookup.registerTagLib(tagLib)
def taglibObject = applicationContext.getBean(tagLib.fullName)
if (taglibObject instanceof TagLibrary) {
((TagLibrary) taglibObject).setTagLibraryLookup(tagLookup)
}
taglibObject
}
@CompileDynamic
Object mockController(Class> controllerClass) {
createAndEnhanceController(controllerClass)
defineBeans {
"$controllerClass.name"(controllerClass) { bean ->
bean.scope = 'prototype'
bean.autowire = true
}
}
def controller = applicationContext.getBean(controllerClass.name)
if (webRequest == null) {
throw new IllegalAccessException('Cannot access the controller outside of a request. Is the controller referenced in a where: block?')
}
webRequest.request.setAttribute(GrailsApplicationAttributes.CONTROLLER, controller)
webRequest.controllerName = GrailsNameUtils.getLogicalPropertyName(controller.class.name, ControllerArtefactHandler.TYPE)
controller
}
private GrailsClass createAndEnhanceController(Class controllerClass) {
GrailsControllerClass controllerArtefact =
(GrailsControllerClass) grailsApplication.addArtefact(ControllerArtefactHandler.TYPE, controllerClass)
controllerArtefact.initialize()
controllerArtefact
}
void mockTagLibs(Class>... tagLibClasses) {
for (Class c : tagLibClasses) {
mockTagLib c
}
}
void mockCodec(Class> codecClass, boolean reinitialize = true) {
if (loadedCodecs.contains(codecClass)) {
return
}
loadedCodecs << codecClass
DefaultGrailsCodecClass grailsCodecClass = new DefaultGrailsCodecClass(codecClass)
grailsCodecClass.configureCodecMethods()
grailsApplication.addArtefact(CodecArtefactHandler.TYPE, grailsCodecClass)
if (reinitialize) {
applicationContext.getBean(DefaultCodecLookup).reInitialize()
}
}
/**
* Mimics the behavior of the render method in controllers but returns the rendered contents directly
*
* @param args The same arguments as the controller render method accepts
* @return The resulting rendering GSP
*/
String render(Map args) {
String uri = null
Map model
if (args.containsKey('model')) {
model = (Map) args.model
}
else {
model = [:]
}
GrailsApplicationAttributes attributes = webRequest.attributes
if (args.template) {
uri = attributes.getTemplateUri(args.template as String, request)
}
else if (args.view) {
uri = attributes.getViewUri(args.view as String, request)
}
if (uri != null) {
GroovyPagesTemplateEngine engine = applicationContext.getBean(GroovyPagesTemplateEngine)
Template t = engine.createTemplate(uri)
if (t != null) {
def sw = new StringWriter()
renderTemplateToStringWriter(sw, t, model)
return sw.toString()
}
}
null
}
/**
* Renders a template for the given contents and model
*
* @param contents The contents
* @param model The model
* @return The rendered template
*/
String applyTemplate(String contents, Map model = [:]) {
def sw = new StringWriter()
applyTemplate sw, contents, model
sw.toString()
}
/**
* Renders a template for the given contents and model to the provided writer
*
* @param sw The write to write the rendered template to
* @param contents The contents
* @param model The model
*/
void applyTemplate(StringWriter sw, String template, Map params = [:]) {
GroovyPagesTemplateEngine engine = applicationContext.getBean(GroovyPagesTemplateEngine)
Template t = engine.createTemplate(template, 'test_' + System.currentTimeMillis())
renderTemplateToStringWriter(sw, t, params)
}
private renderTemplateToStringWriter(StringWriter sw, Template t, Map params) {
webRequest.controllerName = webRequest.controllerName ?: 'test'
webRequest.actionName = webRequest.actionName ?: 'index'
def w = t.make(params)
def previousOut = webRequest.out
try {
def out = new GrailsPrintWriter(sw)
webRequest.out = out
w.writeTo(out)
}
finally {
webRequest.out = previousOut
}
}
}