grails.plugin.json.view.test.JsonViewTest.groovy Maven / Gradle / Ivy
package grails.plugin.json.view.test
import grails.core.GrailsApplication
import grails.plugin.json.view.JsonViewConfiguration
import grails.plugin.json.view.JsonViewTemplateEngine
import grails.plugin.json.view.api.JsonView
import grails.plugin.json.view.api.jsonapi.DefaultJsonApiIdRenderer
import grails.plugin.json.view.api.jsonapi.JsonApiIdRenderStrategy
import grails.views.api.HttpView
import grails.views.api.http.Response
import grails.web.mapping.LinkGenerator
import grails.web.mime.MimeUtility
import groovy.json.JsonSlurper
import groovy.text.Template
import groovy.transform.CompileStatic
import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext
import org.grails.datastore.mapping.model.MappingContext
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.MessageSource
import org.springframework.context.support.StaticMessageSource
import org.springframework.http.HttpStatus
/**
* A trait that test classes can implement to add support for easily testing JSON views
*
* @author Graeme Rocher
* @since 1.1.0
*/
@CompileStatic
trait JsonViewTest {
@Autowired(required = false)
MessageSource messageSource = new StaticMessageSource()
@Autowired(required = false)
MappingContext mappingContext = {
def ctx = new KeyValueMappingContext("test")
ctx.setCanInitializeEntities(true)
return ctx
}()
@Autowired(required = false)
MimeUtility mimeUtility
@Autowired(required = false)
LinkGenerator linkGenerator = new TestLinkGenerator(mappingContext)
@Autowired(required = false)
JsonViewConfiguration viewConfiguration = new JsonViewConfiguration()
@Autowired(required = false)
void setGrailsApplication(GrailsApplication grailsApplication) {
viewConfiguration.setGrailsApplication(grailsApplication)
}
@Autowired(required = false)
JsonApiIdRenderStrategy jsonApiIdRenderStrategy = new DefaultJsonApiIdRenderer()
@Lazy JsonViewTemplateEngine templateEngine = {
def templateEngine = new JsonViewTemplateEngine(viewConfiguration, Thread.currentThread().contextClassLoader)
if(messageSource != null) {
templateEngine.setMessageSource(messageSource)
}
templateEngine.setLinkGenerator(linkGenerator)
if(mimeUtility != null) {
templateEngine.setMimeUtility(mimeUtility)
}
if(mappingContext != null) {
templateEngine.setMappingContext(mappingContext)
}
templateEngine.setJsonApiIdRenderStrategy(jsonApiIdRenderStrategy)
return templateEngine
}()
/**
* Render a template for the given source
*
* @param source The raw source of the template
* @param model The model
*
* @return The result
*/
JsonRenderResult render(String source) {
render(source, Collections.emptyMap(), null)
}
/**
* Render a template for the given source
*
* @param source The raw source of the template
* @param model The model
*
* @return The result
*/
JsonRenderResult render(String source, Map model) {
render(source, model, null)
}
/**
* Render a template for the given source
*
* @param source The raw source of the template
* @param model The model
* @param configurer The configurer
*
* @return The result
*/
JsonRenderResult render(String source, Map model, @DelegatesTo(TestRequestConfigurer) Closure configurer) {
def template = templateEngine.createTemplate(source)
return produceResult(template, model, configurer)
}
/**
* Render a template for the given source
*
* @param source The raw source of the template
* @param model The model
* @param configurer The configurer
*
* @return The result
*/
JsonRenderResult render(String source, @DelegatesTo(TestRequestConfigurer) Closure configurer) {
def template = templateEngine.createTemplate(source)
return produceResult(template, Collections.emptyMap(), configurer)
}
/**
* Render one of the GSON views in the grails-app/views directory for the given arguments
*
* @param arguments The named arguments: 'template', 'view' and 'model'
*
* @return The render result
*/
JsonRenderResult render(Map arguments) {
render arguments, null
}
/**
* Render one of the GSON views in the grails-app/views directory for the given arguments
*
* @param arguments The named arguments: 'template', 'view' and 'model'
* @param configurer The configurer for modifying the request state of the view
*
* @return The render result
*/
JsonRenderResult render(Map arguments, @DelegatesTo(TestRequestConfigurer) Closure configurer) {
String viewUri
if( arguments.template ) {
viewUri = templateEngine
.viewUriResolver
.resolveTemplateUri(null, arguments.template.toString())
}
else if( arguments.view ) {
viewUri = arguments.view.toString()
}
else {
throw new IllegalArgumentException("Either a 'view' or 'template' argument is required!")
}
def template = templateEngine.resolveTemplate(viewUri)
if(template == null) {
throw new IllegalArgumentException("No view or template found for URI $viewUri")
}
def model = arguments.model instanceof Map ? (Map)arguments.model : [:]
return produceResult(template, model, configurer)
}
private JsonRenderResult produceResult(Template template, Map model, Closure configurer) {
JsonView writable = (JsonView) template.make(model)
if (configurer != null) {
def rc = new TestRequestConfigurer(writable)
configurer.delegate = rc
configurer.call()
}
def result = new JsonRenderResult()
if (writable instanceof HttpView) {
def httpView = (HttpView) writable
httpView.setResponse(new TestHttpResponse(result))
}
def sw = new StringWriter()
writable.writeTo(sw)
def str = sw.toString()
result.jsonText = str
result.json = new JsonSlurper().parseText(str)
return result
}
static class TestHttpResponse implements Response {
final JsonRenderResult result
TestHttpResponse(JsonRenderResult result) {
this.result = result
}
@Override
void header(String name, String value) {
result.headers[name] = value
}
@Override
void header(Map nameAndValue) {
result.headers.putAll(nameAndValue)
}
@Override
void headers(Map namesAndValues) {
result.headers.putAll(namesAndValues)
}
@Override
void contentType(String contentType) {
result.contentType = contentType
}
@Override
void encoding(String encoding) {
// ignore
}
@Override
void status(int status) {
result.status = HttpStatus.valueOf(status)
}
@Override
void status(int status, String message) {
result.status = HttpStatus.valueOf(status)
result.message = message
}
@Override
void status(HttpStatus status) {
result.status = status
result.message = status.getReasonPhrase()
}
@Override
void status(HttpStatus status, String message) {
result.status = status
result.message = message
}
}
} © 2015 - 2025 Weber Informatics LLC | Privacy Policy