/* * 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.scripting.javascript.wrapper; import java.text.SimpleDateFormat; import java.util.Calendar; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.Value; import org.apache.sling.scripting.javascript.RepositoryScriptingTestBase; import org.apache.sling.scripting.javascript.internal.ScriptEngineHelper; /** Test the ScriptableNode class "live", by retrieving * Nodes from a Repository and executing javascript code * using them. */ public class ScriptableNodeTest extends RepositoryScriptingTestBase { private Node node; private Property textProperty; private String testText; private Property numProperty; private double testNum; private Property calProperty; private Calendar testCal; private ScriptEngineHelper.Data data; @Override protected void setUp() throws Exception { super.setUp(); node = getNewNode(); testText = "Test-" + System.currentTimeMillis(); node.setProperty("text", testText); node.setProperty("otherProperty", node.getPath()); testNum = System.currentTimeMillis(); node.setProperty("num", testNum); testCal = Calendar.getInstance(); node.setProperty("cal", testCal); data = new ScriptEngineHelper.Data(); data.put("node", node); textProperty = node.getProperty("text"); data.put("property", textProperty); numProperty = node.getProperty("num"); data.put("numProperty", numProperty); calProperty = node.getProperty("cal"); data.put("calProperty", calProperty); } public void testDefaultValue() throws Exception { final ScriptEngineHelper.Data data = new ScriptEngineHelper.Data(); data.put("node", getTestRootNode()); assertEquals( getTestRootNode().getPath(), script.evalToString("out.print(node)", data) ); } public void testPrimaryNodeType() throws Exception { final ScriptEngineHelper.Data data = new ScriptEngineHelper.Data(); data.put("node", getTestRootNode()); assertEquals( "nt:unstructured", script.evalToString("out.print(node.getPrimaryNodeType().getName())", data) ); } public void testPrimaryNodeTypeProperty() throws Exception { final ScriptEngineHelper.Data data = new ScriptEngineHelper.Data(); data.put("node", getTestRootNode()); assertEquals( "nt:unstructured", script.evalToString("out.print(node['jcr:primaryType'])", data) ); } public void testViaPropertyNoWrappers() throws Exception { assertEquals( testText, script.evalToString("out.print(property.value.string)", data) ); } public void testViaPropertyWithWrappers() throws Exception { assertEquals( textProperty.getString(), script.evalToString("out.print(property)", data) ); } public void testViaNodeDirectPropertyAccess() throws Exception { assertEquals( testText, script.evalToString("out.print(node.text)", data) ); } public void testViaPropertyNoWrappersNum() throws Exception { assertEquals( testNum, script.eval("numProperty.value.getDouble()", data) ); } public void testViaPropertyWithWrappersNum() throws Exception { assertEquals( testNum, script.eval("0+numProperty", data) ); } public void testViaNodeDirectPropertyAccessNum() throws Exception { assertEquals( testNum, script.eval("node.num", data) ); } public void testViaPropertyNoWrappersCal() throws Exception { assertEquals( testCal.getTimeInMillis(), script.eval("calProperty.value.getDate().getTimeInMillis()", data) ); } public void testViaNodeDirectPropertyAccessCal() throws Exception { final SimpleDateFormat f = new SimpleDateFormat(ScriptableCalendar.ECMA_DATE_FORMAT, ScriptableCalendar.DATE_FORMAT_LOCALE); final String expected = f.format(testCal.getTime()); assertEquals( expected, script.evalToString("out.print(node.cal)", data) ); } public void testCalDateClass() throws Exception { assertEquals( "number", script.evalToString("out.print(typeof node.cal.date.time)", data) ); } public void testPropertyParent() throws Exception { // need to use node.getProperty('num') to have a ScriptableProperty, // node.num only returns a wrapped value assertEquals( "nt:unstructured", script.eval("node.getProperty('num').parent['jcr:primaryType']", data) ); } public void testPropertyAncestor() throws Exception { // call getAncestor which is not explicitly defined in ScriptableProperty, // to verify that all Property methods are available and that we get a // correctly wrapped result (SLING-397) assertEquals( "rep:root", script.eval("node.getProperty('num').getAncestor(0)['jcr:primaryType']", data) ); } public void testPropertiesIterationNoWrapper() throws Exception { final String code = "var props = node.getProperties();" + " for(i in props) { out.print(props[i].name); out.print(' '); }" ; final String result = script.evalToString(code, data); final String [] names = { "text", "otherProperty" }; for(String name : names) { assertTrue("result (" + result + ") contains '" + name + "'", result.contains(name)); } } public void testAddNodeDefaultType() throws Exception { final String path = "subdt_" + System.currentTimeMillis(); final String code = "var n = node.addNode('" + path + "');\n" + "out.print(n['jcr:primaryType']);\n" ; assertEquals("nt:unstructured", script.evalToString(code, data)); } public void testAddNodeSpecificType() throws Exception { final String path = "subst_" + System.currentTimeMillis(); final String code = "var n = node.addNode('" + path + "', 'nt:folder');\n" + "out.print(n['jcr:primaryType']);\n" ; assertEquals("nt:folder", script.evalToString(code, data)); } public void testGetNode() throws Exception { final String path = "subgn_" + System.currentTimeMillis(); final String code = "node.addNode('" + path + "', 'nt:resource');\n" + "var n=node.getNode('" + path + "');\n" + "out.print(n['jcr:primaryType']);\n" ; assertEquals("nt:resource", script.evalToString(code, data)); } public void testGetProperty() throws Exception { final String code = "out.print(node.getProperty('text'));"; assertEquals(testText, script.evalToString(code, data)); } public void testGetNodesNoPattern() throws Exception { final String path = "subgnnp_" + System.currentTimeMillis(); final String code = "node.addNode('" + path + "_A');\n" + "node.addNode('" + path + "_B');\n" + "var nodes = node.getNodes();\n" + "for (i in nodes) { out.print(nodes[i].getName() + ' '); }\n" ; assertEquals(path + "_A " + path + "_B ", script.evalToString(code, data)); } public void testGetNodesWithPattern() throws Exception { final String path = "subgnnp_" + System.currentTimeMillis(); final String code = "node.addNode('1_" + path + "_A');\n" + "node.addNode('1_" + path + "_B');\n" + "node.addNode('2_" + path + "_C');\n" + "var nodes = node.getNodes('1_*');\n" + "for (i in nodes) { out.print(nodes[i].getName() + ' '); }\n" ; assertEquals("1_" + path + "_A 1_" + path + "_B ", script.evalToString(code, data)); } public void testRemoveNode() throws Exception { final String code = "node.addNode('toremove');\n" + "out.print(node.hasNode('toremove'))\n" + "out.print(' ')\n" + "node.getNode('toremove').remove()\n" + "out.print(node.hasNode('toremove'))\n" ; assertEquals("true false", script.evalToString(code, data)); } /** Test SLING-389 */ public void testForCurrentNode() throws Exception { final String code = "for (var a in node) {}; out.print('ok')"; assertEquals("ok", script.evalToString(code, data)); } public void testChildNodeAccess() throws Exception { final String path = "subtcna_" + System.currentTimeMillis(); final String code = "node.addNode('" + path + "');\n" + "var n=node.getNode('" + path + "');\n" + "out.print(n['jcr:primaryType']);\n" + "out.print(' ');\n" + "var n2=node['" + path + "'];\n" + "out.print(n2['jcr:primaryType']);\n" ; assertEquals("nt:unstructured nt:unstructured", script.evalToString(code, data)); } /** Verify that the getAncestor() method (which is not explicitely defined in ScriptableNode) * is available, to check SLING-397. */ public void testGetAncestor() throws Exception { { final String code = "out.print(node.getAncestor(0).getPath());"; assertEquals("/", script.evalToString(code, data)); } { final String code = "out.print(node.getAncestor(0)['jcr:primaryType']);"; assertEquals("rep:root", script.evalToString(code, data)); } } public void testIsNodeType() throws Exception { final String code = "out.print(node.isNodeType('nt:unstructured'));\n" + "out.print(' ');\n" + "out.print(node.isNodeType('nt:file'));" ; assertEquals("true false", script.evalToString(code, data)); } public void testGetSession() throws Exception { assertEquals( "Root node found via node.session", "/", script.eval("node.session.getRootNode().getPath()", data) ); assertEquals( "Root node found via node.getSession()", "/", script.eval("node.getSession().getRootNode().getPath()", data) ); } /** * Test for regressing this issue: * https://issues.apache.org/jira/browse/SLING-534 */ public void testMultiValReferencePropLookup() throws Exception { Node refNode1 = getNewNode(); refNode1.addMixin("mix:referenceable"); Node refNode2 = getNewNode(); refNode2.addMixin("mix:referenceable"); node.setProperty("singleRef", refNode1); node.setProperty("multiRef", new Value[] { session.getValueFactory().createValue(refNode1), session.getValueFactory().createValue(refNode2) }); String code = "node['singleRef']"; assertTrue(script.eval(code, data) instanceof Node); code = "node.multiRef[0]"; assertTrue(script.eval(code, data) instanceof Node); } }