/**
* Copyright (C) 2012-2017 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 ninja.template;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import ninja.Context;
import ninja.Result;
import ninja.Results;
import ninja.utils.NinjaProperties;
import ninja.utils.ResponseStreams;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Tests for JSONP render.
*/
public class TemplateEngineJsonPTest {
Logger logger;
NinjaProperties properties;
Context context;
ResponseStreams responseStreams;
Result result;
ObjectMapper objectMapper;
ByteArrayOutputStream outputStream;
@Before
public void setUp() throws IOException {
logger = mock(Logger.class);
properties = mock(NinjaProperties.class);
context = mock(Context.class);
responseStreams = mock(ResponseStreams.class);
result = Results.jsonp().render(Collections.singletonList(123));
objectMapper = new ObjectMapper();
outputStream = new ByteArrayOutputStream();
when(properties.getWithDefault("ninja.jsonp.callbackParameter",
TemplateEngineJsonP.DEFAULT_CALLBACK_PARAMETER_NAME)).thenReturn("callback");
when(context.finalizeHeaders(result)).thenReturn(responseStreams);
when(responseStreams.getOutputStream()).thenReturn(outputStream);
}
@Test
public void testCorrectFlow() throws IOException {
when(context.getParameter("callback", TemplateEngineJsonP.DEFAULT_CALLBACK_PARAMETER_VALUE)).thenReturn("App.callback");
TemplateEngineJsonP jsonpEngine = new TemplateEngineJsonP(objectMapper, properties);
jsonpEngine.invoke(context, result);
String jsonp = new String(outputStream.toByteArray(), "UTF-8");
assertEquals("App.callback([123])", jsonp);
verify(context).finalizeHeaders(result);
}
@Test
public void testMissingCallbackVariableFlow() throws IOException {
TemplateEngineJsonP jsonpEngine = new TemplateEngineJsonP(objectMapper, properties);
jsonpEngine.invoke(context, result);
String jsonp = new String(outputStream.toByteArray(), "UTF-8");
assertEquals(TemplateEngineJsonP.DEFAULT_CALLBACK_PARAMETER_VALUE + "([123])", jsonp);
verify(context).finalizeHeaders(result);
}
@Test
public void testBadCallbackNameFlow() throws IOException {
when(context.getParameter("callback", TemplateEngineJsonP.DEFAULT_CALLBACK_PARAMETER_VALUE)).thenReturn(".callback");
TemplateEngineJsonP jsonpEngine = new TemplateEngineJsonP(objectMapper, properties);
jsonpEngine.invoke(context, result);
String jsonp = new String(outputStream.toByteArray(), "UTF-8");
assertEquals(TemplateEngineJsonP.DEFAULT_CALLBACK_PARAMETER_VALUE + "([123])", jsonp);
verify(context).finalizeHeaders(result);
}
@Test
public void testIsThisASecureCallbackName() {
assertTrue("simple function", TemplateEngineJsonP.isThisASecureCallbackName("onResponse"));
assertTrue("object function", TemplateEngineJsonP.isThisASecureCallbackName("MyPath.path"));
assertTrue("object function", TemplateEngineJsonP.isThisASecureCallbackName("MyApp.Path.myCallback123"));
assertTrue("object function, path with numbers",
TemplateEngineJsonP.isThisASecureCallbackName("MyApp123.Path789.myCallback123"));
assertTrue("complex path", TemplateEngineJsonP.isThisASecureCallbackName("Ext.data.JsonP.callback4"));
assertTrue("complex path, $ in identity.", TemplateEngineJsonP.isThisASecureCallbackName("$42.ajaxHandler"));
assertFalse("wrong first character", TemplateEngineJsonP.isThisASecureCallbackName("42$.q"));
assertFalse("period in the front, simple", TemplateEngineJsonP.isThisASecureCallbackName(".onResponse"));
assertFalse("period in the end, simple", TemplateEngineJsonP.isThisASecureCallbackName("onResponse."));
assertFalse("period in the front, object function", TemplateEngineJsonP.isThisASecureCallbackName(".MyPath.path"));
assertFalse("period in the end, complex path", TemplateEngineJsonP.isThisASecureCallbackName("MyPath.path.path2."));
assertFalse("two subsequent periods", TemplateEngineJsonP.isThisASecureCallbackName("MyPath..path.path2"));
assertFalse("function call", TemplateEngineJsonP.isThisASecureCallbackName("alert(document.cookie)"));
// Cases not supported by the validator.
assertFalse("simple array", TemplateEngineJsonP.isThisASecureCallbackName("somearray[12345]"));
assertFalse("unicode characters", TemplateEngineJsonP.isThisASecureCallbackName("\\u0062oo"));
assertFalse("unicode characters", TemplateEngineJsonP.isThisASecureCallbackName("\\u0020"));
}
}