Permalink
Browse files

Add Kotlin based ScriptTemplateView rendering test

Kotlin JSR 223 support currently requires kotlin-script-util
dependency (jcabi-aether, maven-core and aether-api can be
excluded since they are only used for live import of
dependencies and bring a lot of JARs in the classpath) and a
/META-INF/services/javax.script.ScriptEngineFactory
file specifying the ScriptEngineFactory to use, in that case
org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory.

Issue: SPR-15059
  • Loading branch information...
1 parent ef43400 commit badde3a479a53e1dd0777dd1bd5b55cb1021cf9e @sdeleuze sdeleuze committed Jan 1, 2017
View
@@ -969,6 +969,15 @@ project("spring-webmvc") {
testCompile("org.mozilla:rhino:1.7.7.1")
testRuntime("org.jruby:jruby:9.1.6.0")
testRuntime("org.python:jython-standalone:2.5.3")
+ // Ideally, kotlin-script-runtime should be enough for JSR-223, but that's not
+ // the case yet, so we depend on kotlin-script-util and exclude these
+ // dependencies only used for artifact retrieval. Point raised to Kotlin team.
+ testRuntime("org.jetbrains.kotlin:kotlin-compiler:${kotlinVersion}")
+ testRuntime("org.jetbrains.kotlin:kotlin-script-util:${kotlinVersion}") {
+ exclude group: "com.jcabi", module: "jcabi-aether"
+ exclude group: "org.apache.maven", module: "maven-core"
+ exclude group: "org.sonatype.aether", module: "aether-api"
+ }
testRuntime("org.webjars:underscorejs:1.8.3")
testRuntime("org.glassfish:javax.el:3.0.1-b08")
testRuntime("com.sun.xml.bind:jaxb-core:${jaxbVersion}")
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2002-2015 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.springframework.web.servlet.view.script;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.ServletContext;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Before;
+import org.junit.Test;
+import static org.mockito.Mockito.mock;
+
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.mock.web.test.MockHttpServletRequest;
+import org.springframework.mock.web.test.MockHttpServletResponse;
+import org.springframework.mock.web.test.MockServletContext;
+import org.springframework.web.context.WebApplicationContext;
+
+/**
+ * Unit tests for Kotlin script templates running on Kotlin JSR 223 support
+ *
+ * @author Sebastien Deleuze
+ */
+public class KotlinScriptTemplateTests {
+
+ private WebApplicationContext webAppContext;
+
+ private ServletContext servletContext;
+
+
+ @Before
+ public void setup() {
+ this.webAppContext = mock(WebApplicationContext.class);
+ this.servletContext = new MockServletContext();
+ this.servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.webAppContext);
+ }
+
+ @Test
+ public void renderTemplate() throws Exception {
+ Map<String, Object> model = new HashMap<>();
+ model.put("title", "Layout example");
+ model.put("body", "This is the body");
+ MockHttpServletResponse response = renderViewWithModel("org/springframework/web/servlet/view/script/kotlin/template.kts",
+ model, ScriptTemplatingConfiguration.class);
+ assertEquals("<html><head><title>Layout example</title></head><body><p>This is the body</p></body></html>",
+ response.getContentAsString());
+ }
+
+ private MockHttpServletResponse renderViewWithModel(String viewUrl, Map<String, Object> model, Class<?> configuration) throws Exception {
+ ScriptTemplateView view = createViewWithUrl(viewUrl, configuration);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ view.renderMergedOutputModel(model, request, response);
+ return response;
+ }
+
+ private ScriptTemplateView createViewWithUrl(String viewUrl, Class<?> configuration) throws Exception {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.register(configuration);
+ ctx.refresh();
+
+ ScriptTemplateView view = new ScriptTemplateView();
+ view.setApplicationContext(ctx);
+ view.setUrl(viewUrl);
+ view.afterPropertiesSet();
+ return view;
+ }
+
+
+ @Configuration
+ static class ScriptTemplatingConfiguration {
+
+ @Bean
+ public ScriptTemplateConfigurer kotlinScriptConfigurer() {
+ ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
+ configurer.setEngineName("kotlin");
+ configurer.setScripts("org/springframework/web/servlet/view/script/kotlin/render.kts");
+ configurer.setRenderFunction("render");
+ return configurer;
+ }
+ }
+
+}
@@ -0,0 +1 @@
+org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory
@@ -0,0 +1,10 @@
+import javax.script.*
+
+// TODO Use engine.eval(String, Bindings) when https://youtrack.jetbrains.com/issue/KT-15450 will be fixed
+fun render(template: String, model: Map<String, Any>, url: String): String {
+ val engine = ScriptEngineManager().getEngineByName("kotlin")
+ val bindings = SimpleBindings()
+ bindings.putAll(model)
+ engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE)
+ return engine.eval(template) as String
+}
@@ -0,0 +1 @@
+"""<html><head><title>${bindings["title"]}</title></head><body><p>${bindings["body"]}</p></body></html>"""

0 comments on commit badde3a

Please sign in to comment.