/*
* 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 static org.exoplatform.web.controller.metadata.DescriptorBuilder.*;
import java.net.MalformedURLException;
import java.util.Arrays;
import org.exoplatform.services.resources.Orientation;
import org.exoplatform.web.controller.router.Router;
import org.exoplatform.web.controller.router.RouterConfigException;
/**
* @author <a href="trongtt@gmail.com">Trong Tran</a>
* @version $Revision$
*/
public class TestSkinService extends AbstractSkinServiceTest {
private static boolean isFirstStartup = true;
boolean isDevelopingMode() {
return false;
}
@Override
boolean setUpTestEnvironment() {
return isFirstStartup;
}
Router getRouter() {
Router router;
try {
router = router().add(
route("/skins/{gtn:version}/{gtn:resource}{gtn:compress}{gtn:orientation}.css")
.with(routeParam("gtn:handler").withValue("skin"))
.with(pathParam("gtn:version").matchedBy("[^/]*").preservePath())
.with(pathParam("gtn:orientation").matchedBy("-(lt)|-(rt)|").captureGroup(true))
.with(pathParam("gtn:compress").matchedBy("-(min)|").captureGroup(true))
.with(pathParam("gtn:resource").matchedBy(".+?").preservePath())).build();
return router;
} catch (RouterConfigException e) {
return null;
}
}
@Override
void touchSetUp() {
isFirstStartup = false;
}
public void testRenderURL() {
SkinURL skinURL = skinService.getSkin("mockwebapp/FirstPortlet", "TestSkin").createURL(controllerCtx);
assertEquals("/portal/skins/" + ASSETS_VERSION + "/mockwebapp/skin/FirstPortlet-min-lt.css", skinURL.toString());
skinURL.setOrientation(Orientation.RT);
assertEquals("/portal/skins/" + ASSETS_VERSION + "/mockwebapp/skin/FirstPortlet-min-rt.css", skinURL.toString());
}
public void testCompositeSkin() throws NullPointerException, MalformedURLException {
SkinConfig fSkin = skinService.getSkin("mockwebapp/FirstPortlet", "TestSkin");
SkinConfig sSkin = skinService.getSkin("mockwebapp/SecondPortlet", "TestSkin");
assertNotNull(fSkin);
assertNotNull(sSkin);
Skin merged = skinService.merge(Arrays.asList(fSkin, sSkin));
SkinURL url = merged.createURL(controllerCtx);
url.setOrientation(Orientation.LT);
assertEquals(".FirstPortlet {foo1 : bar1}\n.SecondPortlet {foo2 : bar2}",
skinService.getCSS(newControllerContext(getRouter(), url.toString()), true));
url.setOrientation(Orientation.RT);
assertEquals(".FirstPortlet {foo1 : bar1}\n.SecondPortlet {foo2 : bar2}",
skinService.getCSS(newControllerContext(getRouter(), url.toString()), true));
}
public void testCache() throws Exception {
String resource = "/path/to/test/cache.css";
String url = newSimpleSkin(resource).createURL(controllerCtx).toString();
resResolver.addResource(resource, "foo");
assertEquals("foo", skinService.getCSS(newControllerContext(getRouter(), url), true));
resResolver.addResource(resource, "bar");
assertEquals("foo", skinService.getCSS(newControllerContext(getRouter(), url), true));
}
public void testInvalidateCache() throws Exception {
String resource = "/path/to/test/invalidate/cache.css";
String url = newSimpleSkin(resource).createURL(controllerCtx).toString();
resResolver.addResource(resource, "foo");
assertEquals("foo", skinService.getCSS(newControllerContext(getRouter(), url), true));
resResolver.addResource(resource, "bar");
skinService.invalidateCachedSkin(resource);
assertEquals("bar", skinService.getCSS(newControllerContext(getRouter(), url), true));
}
public void testProcessImportCSS() throws Exception {
String resource = "/process/import/css.css";
String url = newSimpleSkin(resource).createURL(controllerCtx).toString();
resResolver.addResource(resource, "@import url(Portlet/Stylesheet.css); aaa;");
assertEquals(" aaa;", skinService.getCSS(newControllerContext(getRouter(), url), true));
skinService.invalidateCachedSkin(resource);
resResolver.addResource(resource, "@import url('/Portlet/Stylesheet.css'); aaa;");
assertEquals(" aaa;", skinService.getCSS(newControllerContext(getRouter(), url), true));
skinService.invalidateCachedSkin(resource);
// parent file import child css file
resResolver.addResource(resource, "@import url(childCSS/child.css); background:url(images/foo.gif);");
String childResource = "/process/import/childCSS/child.css";
resResolver.addResource(childResource, "background:url(bar.gif);");
/*
* Now test merge and process recursively (run in non-dev mode) We have folder /path/to/parent.css /images/foo.gif
* /childCSS/child.css /bar.gif
*/
assertEquals("background:url(/process/import/childCSS/bar.gif); background:url(/process/import/images/foo.gif);",
skinService.getCSS(newControllerContext(getRouter(), url), true));
url = newSimpleSkin(childResource).createURL(controllerCtx).toString();
assertEquals("background:url(/process/import/childCSS/bar.gif);",
skinService.getCSS(newControllerContext(getRouter(), url), true));
}
public void testProcessImportCrossDomainCSS() throws Exception {
crossDomainCSS("@import url(//example.com/some.css); aaa;");
crossDomainCSS("@import url('//example.com/some.css'); aaa;");
crossDomainCSS("@import url(\"//example.com/some.css\"); aaa;");
crossDomainCSS("@import url(http://example.com/some.css); aaa;");
crossDomainCSS("@import url('http://example.com/some.css'); aaa;");
crossDomainCSS("@import url(\"http://example.com/some.css\"); aaa;");
crossDomainCSS("@import url(https://example.com/some.css); aaa;");
crossDomainCSS("@import url('https://example.com/some.css'); aaa;");
crossDomainCSS("@import url(\"https://example.com/some.css\"); aaa;");
crossDomainCSS("@import '//example.com/some.css'; aaa;");
crossDomainCSS("@import \"//example.com/some.css\"; aaa;");
crossDomainCSS("@import 'http://example.com/some.css'; aaa;");
crossDomainCSS("@import \"http://example.com/some.css\"; aaa;");
crossDomainCSS("@import 'https://example.com/some.css'; aaa;");
crossDomainCSS("@import \"https://example.com/some.css\"; aaa;");
}
private void crossDomainCSS(String crossDomainCss) throws Exception {
String masterCssPath = "/process/import/master.css";
String masterCssUrl = newSimpleSkin(masterCssPath).createURL(controllerCtx).toString();
resResolver.addResource(masterCssPath, crossDomainCss);
assertEquals(crossDomainCss, skinService.getCSS(newControllerContext(getRouter(), masterCssUrl), true));
skinService.invalidateCachedSkin(masterCssPath);
}
public void testLastModifiedSince() throws Exception {
String resource = "/last/modify/since.css";
SkinURL skinURL = newSimpleSkin(resource).createURL(controllerCtx);
resResolver.addResource(resource, "foo");
assertTrue(skinService.getCSS(newControllerContext(getRouter(), skinURL.toString()), true).length() > 0);
long lastModified = skinService.getLastModified(newControllerContext(getRouter(), skinURL.toString()));
Thread.sleep(1000);
assertEquals(lastModified, skinService.getLastModified(newControllerContext(getRouter(), skinURL.toString())));
skinURL.setOrientation(Orientation.RT);
Thread.sleep(1000);
assertTrue(lastModified < skinService.getLastModified(newControllerContext(getRouter(), skinURL.toString())));
}
public void testIsExternalUrl() {
assertFalse(SkinService.isExternalUrl(null));
assertFalse(SkinService.isExternalUrl(""));
assertFalse(SkinService.isExternalUrl("/"));
assertFalse(SkinService.isExternalUrl("/foo"));
assertFalse(SkinService.isExternalUrl("/foo/bar/baz"));
assertFalse(SkinService.isExternalUrl("foo/bar/baz"));
assertFalse(SkinService.isExternalUrl("foo-bar-baz"));
assertFalse(SkinService.isExternalUrl("http"));
assertFalse(SkinService.isExternalUrl("https"));
assertTrue(SkinService.isExternalUrl("//"));
assertTrue(SkinService.isExternalUrl("//foo"));
assertTrue(SkinService.isExternalUrl("//foo/bar/baz"));
assertTrue(SkinService.isExternalUrl("http:"));
assertTrue(SkinService.isExternalUrl("http://foo"));
assertTrue(SkinService.isExternalUrl("http://foo/bar/baz"));
assertTrue(SkinService.isExternalUrl("https:"));
assertTrue(SkinService.isExternalUrl("https://foo"));
assertTrue(SkinService.isExternalUrl("https://foo/bar/baz"));
}
}