/* * Copyright (C) 2011 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.portal.resource; import java.io.StringWriter; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletContext; import org.exoplatform.component.test.web.WebAppImpl; import org.exoplatform.container.PortalContainer; import org.exoplatform.web.ControllerContext; import org.exoplatform.web.application.javascript.JavascriptConfigParser; import org.exoplatform.web.application.javascript.JavascriptConfigService; import org.exoplatform.web.application.javascript.ScriptResources; import org.gatein.common.io.IOTools; import org.gatein.portal.controller.resource.ResourceId; import org.gatein.portal.controller.resource.ResourceScope; import org.gatein.portal.controller.resource.script.FetchMode; import org.gatein.portal.controller.resource.script.ScriptResource; import org.json.JSONObject; import org.w3c.dom.Document; /** * @author <a href="mailto:phuong.vu@exoplatform.com">Vu Viet Phuong</a> * @version $Id$ */ public class TestJavascriptConfigService extends AbstractWebResourceTest { private static final ControllerContext CONTROLLER_CONTEXT = new MockControllerContext(); private static ServletContext mockServletContext; private JavascriptConfigService jsService; @Override protected void setUp() throws Exception { final PortalContainer portalContainer = getContainer(); jsService = portalContainer.getComponentInstanceOfType(JavascriptConfigService.class); if (mockServletContext == null) { Map<String, String> resources = new HashMap<String, String>(6); resources.put("/js/script1.js", "aaa;"); resources.put("/js/script2.js", "bbb;"); resources.put("/js/module1.js", "ccc;"); resources.put("/js/module2.js", "ddd;"); resources.put("/js/common.js", "kkk;"); resources.put("/js/pluginTest.js", "iii;"); //trim all space character: tab, space, non-breaking space... resources.put("/js/normalize_test.js", " \n \t /* // */ // /* \n /* /* */ \n ggg; // /* */ \n"); mockServletContext = new MockJSServletContext("mockwebapp", resources); jsService.registerContext(new WebAppImpl(mockServletContext, Thread.currentThread().getContextClassLoader())); URL url = portalContainer.getPortalClassLoader().getResource("mockwebapp/gatein-resources.xml"); Document document = GateInResourcesSchemaValidator.validate(url); ScriptResources scriptResources = new JavascriptConfigParser(mockServletContext, document).parse(); jsService.add(scriptResources); } } public void testGetScript() throws Exception { // no wrapper for SCRIPTS String script1 = "aaa;" + "\nif (typeof define === 'function' && define.amd && !require.specified('SHARED/script1')) {define('SHARED/script1');}"; String script2 = "bbb;" + "\nif (typeof define === 'function' && define.amd && !require.specified('SHARED/script2')) {define('SHARED/script2');}"; assertReader(script1, jsService.getScript(new ResourceId(ResourceScope.SHARED, "script1"), null)); assertReader(script2, jsService.getScript(new ResourceId(ResourceScope.SHARED, "script2"), null)); // wrapper for MODULE // test for Alias : module1 is used with 'm1' alias String module1 = "\ndefine('SHARED/module1', [], function() {" + "\nvar require = eXo.require, requirejs = eXo.require,define = eXo.define;\neXo.define.names=[];\neXo.define.deps=[];" + "\nreturn ccc;\n});"; assertReader(module1, jsService.getScript(new ResourceId(ResourceScope.SHARED, "module1"), null)); // module2 depends on module1 // test for Alias : module1 is used with 'mod1' alias, module2 use default name for alias String module2 = "\ndefine('SHARED/module2', [\"SHARED/module1\"], function(mod1) {" + "\nvar require = eXo.require, requirejs = eXo.require,define = eXo.define;\neXo.define.names=[\"mod1\"];\neXo.define.deps=[mod1];" + "\nreturn ddd;\n});"; assertReader(module2, jsService.getScript(new ResourceId(ResourceScope.SHARED, "module2"), null)); } public void testCommonJS() throws Exception { String commonjs = "\ndefine('SHARED/commonjs', [\"require\",\"exports\",\"module\"], function(require,exports,module) {" + "\nvar require = eXo.require, requirejs = eXo.require,define = eXo.define;\neXo.define.names=[\"require\",\"exports\",\"module\"];" + "\neXo.define.deps=[eXo.require,exports,module];" + "\nreturn kkk;\n});"; assertReader(commonjs, jsService.getScript(new ResourceId(ResourceScope.SHARED, "commonjs"), null)); } public void testRequireJSPlugin() throws Exception { String pluginTest = "\ndefine('SHARED/pluginTest', [\"SHARED/text!/path/to/file.js\",\"SHARED/text!/path/to/file2.js\"]," + " function(text,text_1) {" + "\nvar require = eXo.require, requirejs = eXo.require,define = eXo.define;\n" + "eXo.define.names=[\"text!/path/to/file.js\",\"text!/path/to/file2.js\"];" + "\neXo.define.deps=[text,text_1];" + "\nreturn iii;\n});"; assertReader(pluginTest, jsService.getScript(new ResourceId(ResourceScope.SHARED, "pluginTest"), null)); } public void testGroupingScript() throws Exception { String module1 = "\n//Begin SHARED/module1\ndefine('SHARED/module1', [], function() {" + "\nvar require = eXo.require, requirejs = eXo.require,define = eXo.define;\neXo.define.names=[];\neXo.define.deps=[];" + "\nreturn ccc;\n});\n//End SHARED/module1"; String module2 = "\n//Begin SHARED/module2\ndefine('SHARED/module2', [\"SHARED/module1\"], function(mod1) {" + "\nvar require = eXo.require, requirejs = eXo.require,define = eXo.define;\neXo.define.names=[\"mod1\"];\neXo.define.deps=[mod1];" + "\nreturn ddd;\n});\n//End SHARED/module2"; StringWriter buffer = new StringWriter(); IOTools.copy(jsService.getScript(new ResourceId(ResourceScope.GROUP, "fooGroup"), null), buffer); // the order of module1, and module2 in group is not known String result = buffer.toString(); result = result.replace(module1, ""); result = result.replace(module2, ""); assertTrue(result.isEmpty()); } public void testGetJSConfig() throws Exception { JSONObject config = jsService.getJSConfig(CONTROLLER_CONTEXT, null); // All SCRIPTS and remote resource have to had dependencies declared in shim configuration JSONObject shim = config.getJSONObject("shim"); assertNotNull(shim); JSONObject remoteDep = shim.getJSONObject("remote2"); assertNotNull(remoteDep); assertEquals("{\"deps\":[\"remote1\"]}", remoteDep.toString()); JSONObject scriptDep = shim.getJSONObject("SHARED/script2"); assertNotNull(scriptDep); assertEquals("{\"deps\":[\"SHARED/script1\"]}", scriptDep.toString()); // requireJS need a map of all resourceIDs and urls // requireJS add ".js" automatically so we truncate it from url JSONObject paths = config.getJSONObject("paths"); assertNotNull(paths); // Return remote module/script url as it's declared in gatein-resources.xml assertEquals("http://js/remote1", paths.getString("remote1")); assertEquals("http://js/remote2", paths.getString("remote2")); // module1 and module2 are grouped assertEquals("/mock_context/mock_url_of_fooGroup", paths.getString("SHARED/module1")); assertEquals("/mock_context/mock_url_of_fooGroup", paths.getString("SHARED/module2")); // navController url for scripts assertEquals("/mock_context/mock_url_of_script1", paths.getString("SHARED/script1")); assertEquals("/mock_context/mock_url_of_script2", paths.getString("SHARED/script2")); } public void testGenerateURL() throws Exception { ResourceId remote1 = new ResourceId(ResourceScope.SHARED, "remote1"); String remoteURL = jsService.generateURL(CONTROLLER_CONTEXT, remote1, false, false, null); // Return remote module/script url as it's declared in gatein-resources.xml assertEquals("http://js/remote1.js", remoteURL); ResourceId module1 = new ResourceId(ResourceScope.SHARED, "module1"); remoteURL = jsService.generateURL(CONTROLLER_CONTEXT, module1, false, false, null); assertEquals("/mock_context/mock_url_of_module1.js", remoteURL); } public void testNormalize() throws Exception { String normalizedJS = "\ndefine('SHARED/normalize_test', [], function() {" + "\nvar require = eXo.require, requirejs = eXo.require,define = eXo.define;\neXo.define.names=[];\neXo.define.deps=[];" + "\nreturn ggg; // /* */ \n\n});"; assertReader(normalizedJS, jsService.getScript(new ResourceId(ResourceScope.SHARED, "normalize_test"), null)); } public void testResolveIDs() { Map<ResourceId, FetchMode> tmp = new HashMap<ResourceId, FetchMode>(); tmp.put(new ResourceId(ResourceScope.SHARED, "script2"), null); Map<ScriptResource, FetchMode> ids = jsService.resolveIds(tmp); // Only resolve dependencies for SCRIPTS assertEquals(2, ids.size()); List<ScriptResource> result = new ArrayList<ScriptResource>(ids.keySet()); assertEquals("script1", result.get(0).getId().getName()); assertEquals("script2", result.get(1).getId().getName()); tmp.clear(); // module2 depends on module1 but we don't resolve dependencies for it tmp.put(new ResourceId(ResourceScope.SHARED, "module2"), null); ids = jsService.resolveIds(tmp); assertEquals(1, ids.size()); assertEquals("module2", ids.keySet().iterator().next().getId().getName()); } /* * public void testCommonJScripts() { assertEquals(5, jsService.getCommonJScripts().size()); * assertTrue(jsService.isModuleLoaded("js.test1")); assertTrue(jsService.isModuleLoaded("js.test2")); * assertTrue(jsService.isModuleLoaded("js.test3")); assertTrue(jsService.isModuleLoaded("js.test4")); * assertTrue(jsService.isModuleLoaded("js.test7")); * * assertFalse(jsService.isModuleLoaded("js.test5")); * * // InputStream script = jsService.getScript(new ResourceId(ResourceScope.SHARED, "common"), "js.test1"); * assertNotNull(script); } */ /* * public void testPortalJScript() throws IOException { Collection<Javascript> site = jsService.getPortalJScripts("site1"); * assertEquals(1, site.size()); Iterator<Javascript> iterator = site.iterator(); * assertEquals(mockServletContext.getContextPath() + "/js/test5.js", iterator.next().getPath()); * * // InputStream script = jsService.getScript(new ResourceId(ResourceScope.PORTAL, "site1")); assertNotNull(script); * assertEquals("", read(script)); * * site = jsService.getPortalJScripts("site2"); assertEquals(2, site.size()); iterator = site.iterator(); * assertEquals(mockServletContext.getContextPath() + "/js/test6.js", iterator.next().getPath()); * assertEquals(mockServletContext.getContextPath() + "/js/test5.js", iterator.next().getPath()); * * // script = jsService.getScript(new ResourceId(ResourceScope.PORTAL, "site2")); assertNotNull(script); assertEquals("", * read(script)); * * // assertNull(jsService.getPortalJScripts("classic")); assertNull(jsService.getScript(new * ResourceId(ResourceScope.PORTAL, "classic"))); * * // jsService.removePortalJScripts("site1"); assertNull(jsService.getPortalJScripts("site1")); * assertNull(jsService.getScript(new ResourceId(ResourceScope.PORTAL, "site1"))); * * // Javascript portalJScript = Javascript.create(new ResourceId(ResourceScope.PORTAL, "/portal"), "portal1", * "/mockwebapp", "/portal", Integer.MAX_VALUE); jsService.addPortalJScript(portalJScript); String jScript = * jsService.getJScript(portalJScript.getPath()); assertNull(jScript); assertEquals("", read(script)); * resResolver.addResource(portalJScript.getPath(), "bar1"); jScript = jsService.getJScript(portalJScript.getPath()); * assertEquals("bar1", jScript); } */ }