blob: 9483c75954244d1d932f6f8044e2b891e5329700 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.sling.launchpad.webapp.integrationtest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.apache.sling.commons.testing.integration.HttpTestBase;
import org.apache.sling.servlets.post.SlingPostConstants;
/** Test creating Nodes and rendering them in JSON */
public class JsonRenderingTest extends HttpTestBase {
private final String testPath = "/" + getClass().getSimpleName();
private String postUrl;
private String testText;
private String jsonUrl;
private String createdNodeUrl;
@Override
protected void setUp() throws Exception {
super.setUp();
// set test values
testText = "This is a test " + System.currentTimeMillis();
// create the test node, under a path that's specific to this class to
// allow collisions
postUrl = HTTP_BASE_URL + testPath + "_"
+ System.currentTimeMillis()
+ SlingPostConstants.DEFAULT_CREATE_SUFFIX;
final Map<String, String> props = new HashMap<String, String>();
props.put("text", testText);
createdNodeUrl = testClient.createNode(postUrl, props);
jsonUrl = createdNodeUrl + ".json";
}
/** test our assertJavascript method with static json */
public void testAssertJavascript() throws IOException {
final String json = "{ 'a' : '123', 'b' : '456' }";
assertJavascript("123456", json, "out.println(data.a + data.b)");
}
public void testNonRecursive() throws IOException {
final String json = getContent(jsonUrl, CONTENT_TYPE_JSON);
assertJavascript(testText, json, "out.println(data.text)");
}
/** Create a node with children, verify that we get them back in JSON format */
public void testRecursiveOneLevel() throws IOException {
final Map<String, String> props = new HashMap<String, String>();
props.put("text", testText);
final String parentNodeUrl = testClient.createNode(postUrl, props);
final String[] children = { "A", "B", "C" };
for (String child : children) {
props.put("child", child);
testClient.createNode(parentNodeUrl + "/" + child, props);
}
final String json = getContent(parentNodeUrl + ".1.json",
CONTENT_TYPE_JSON);
assertJavascript(testText, json, "out.print(data.text)");
for (String child : children) {
assertJavascript(child, json, "out.print(data['" + child
+ "'].child)");
assertJavascript(testText, json, "out.print(data['" + child
+ "'].text)");
}
}
/**
* Create a node with children, verify that we do not get them back in JSON
* format if using recursion level=0
*/
public void testRecursiveZeroLevels() throws IOException {
final Map<String, String> props = new HashMap<String, String>();
props.put("text", testText);
final String parentNodeUrl = testClient.createNode(postUrl, props);
final String[] children = { "A", "B", "C" };
for (String child : children) {
props.put("child", child);
testClient.createNode(parentNodeUrl + "/" + child, props);
}
// .json and .0.json must both return 0 levels
final String[] extensions = { ".json", ".0.json" };
for (String extension : extensions) {
final String json = getContent(parentNodeUrl + extension,
CONTENT_TYPE_JSON);
assertJavascript(testText, json, "out.print(data.text)");
for (String child : children) {
final String testInfo = "extension: " + extension;
assertJavascript("undefined", json, "out.print(typeof data['"
+ child + "'])", testInfo);
}
}
}
/** Test to see if node.infinity returns 300 when there are too many nodes */
public void testRecursiveInfinityTooDeep() throws IOException {
final Map<String, String> props = new HashMap<String, String>();
for (int i = 0; i < 20;i++) {
props.put("a" + i + "/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s", "yes");
}
final String url = testClient.createNode(postUrl, props);
final String json = getContent(url + ".infinity.json",
CONTENT_TYPE_JSON, null, 300);
System.err.println("Url: " + url + "\npostUrl: " + postUrl);
// Get the resource url. (everything after the port)
// We skip http://localhost:8888/org.apache.sling.launchpad.testing-6-SNAPSHOT/
// or http://localhost:8888/
String resourceUrl = url;
final int toSkip = resourceUrl.contains("/org.apache.sling.launchpad") ? 4 : 3;
for (int i = toSkip;i>0;i--) {
resourceUrl = resourceUrl.substring(resourceUrl.indexOf("/") + 1);
}
for (int i = 10; i >=0; i--) {
assertJavascript("/" + resourceUrl + "." + i + ".json", json, "out.print(data[" + (10 - i) + "])");
}
}
/** Test the "infinity" recursion level */
public void testRecursiveInfinity() throws IOException {
final Map<String, String> props = new HashMap<String, String>();
props.put("text", testText);
props.put("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y", "yes");
final String url = testClient.createNode(postUrl, props);
final String json = getContent(url + ".infinity.json",
CONTENT_TYPE_JSON);
assertJavascript(testText, json, "out.print(data.text)");
assertJavascript("yes", json,
"out.print(data.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y)");
}
public void testInvalidLevel() throws IOException {
assertHttpStatus(createdNodeUrl + ".notAnIntegerOnPurpose.json",
HttpServletResponse.SC_BAD_REQUEST);
}
public void testEscapedStrings() throws IOException {
final Map<String, String> props = new HashMap<String, String>();
props.put("dq", "Some text with \"double quotes\"");
props.put("sq", "Some text with 'single quotes'");
props.put("cb", "Some text with {curly brackets}");
props.put("sb", "Some text with [square brackets]");
props.put("eol", "Some text with end\nof\nlines\nand\ttabs");
props.put("html",
"Some text with <body class=\"black\" mode=\'none yet\'/> html-like tags");
props.put("bs", "Some text with \\backslashes \\here and \\\"there\"");
final String location = testClient.createNode(postUrl, props);
final String json = getContent(location + ".json", CONTENT_TYPE_JSON);
int counter = 0;
for (String key : props.keySet()) {
counter++;
assertJavascript(props.get(key), json, "out.println(data." + key
+ ")");
}
}
public void testAccentedStrings() throws IOException {
final Map<String, String> props = new HashMap<String, String>();
props.put("a", "Les amis en \u00E9t\u00E9 au ch\u00E2teau");
props.put("b", "The \u00B0 degree sign and \u00F1 ntilde");
props.put("c", "The \u0429 cyrillic capital letter shcha");
props.put("d", "The \u13C8 cherokee letter qui");
final String location = testClient.createNode(postUrl, props, null,
true);
final String json = getContent(location + ".json", CONTENT_TYPE_JSON);
for (String key : props.keySet()) {
assertJavascript(props.get(key), json, "out.println(data." + key
+ ")");
}
}
protected static int countOccurences(String str, char toCount) {
int result = 0;
for(char c : str.toCharArray()) {
if(c == toCount) {
result++;
}
}
return result;
}
public void testTidyNonRecursive() throws IOException {
// Count end-of-line chars, there must be more in the tidy form
int noTidyCount = countOccurences(getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON), '\n');
int tidyCount = countOccurences(getContent(createdNodeUrl + ".tidy.json", CONTENT_TYPE_JSON), '\n');
int delta = tidyCount - noTidyCount;
// Output contains two properties so at least two EOL chars
int min = 2;
assertTrue("The .tidy selector should add at least 2 EOL chars to json output (delta=" + delta + ")", delta > min);
}
public void testTidyRecursive() throws IOException {
final Map<String, String> props = new HashMap<String, String>();
props.put("text", testText);
props.put("a/b", "yes");
final String url = testClient.createNode(postUrl, props);
int noTidyCount = countOccurences(getContent(url + ".infinity.json", CONTENT_TYPE_JSON), '\n');
int tidyCount = countOccurences(getContent(url + ".tidy.infinity.json", CONTENT_TYPE_JSON), '\n');
int delta = tidyCount - noTidyCount;
// Output contains 3 properties and a subnode with one, so at least 5 EOL chars
int min = 5;
assertTrue("The .tidy selector should add at least 2 EOL chars to json output (delta=" + delta + ")", delta > min);
}
public void testRootNoRecursion() throws IOException {
final String json = getContent(HTTP_BASE_URL + "/.json", CONTENT_TYPE_JSON);
assertJavascript("rep:root", json, "out.print(data['jcr:primaryType'])");
assertJavascript("undefined", json, "out.print(typeof data['jcr:system'])");
}
public void testRootWithRecursion() throws IOException {
final String json = getContent(HTTP_BASE_URL + "/.1.json", CONTENT_TYPE_JSON);
assertJavascript("rep:root", json, "out.print(data['jcr:primaryType'])");
assertJavascript("rep:system", json, "out.print(data['jcr:system']['jcr:primaryType'])");
}
}