/**
* Copyright 2010 Molindo GmbH
*
* 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 org.wicketstuff.mergedresources;
import static org.apache.wicket.Application.DEPLOYMENT;
import static org.apache.wicket.Application.DEVELOPMENT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.InputStream;
import org.apache.wicket.Application;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.WebRequestCycle;
import org.apache.wicket.util.io.IOUtils;
import org.apache.wicket.util.string.StringList;
import org.apache.wicket.util.tester.WicketTester;
import org.junit.Test;
import org.wicketstuff.mergedresources.ResourceMount.SuffixMismatchStrategy;
import org.wicketstuff.mergedresources.components.ComponentB;
import org.wicketstuff.mergedresources.components.MyForm;
import org.wicketstuff.mergedresources.components.PanelOne;
public class ResourceMountTest {
static final ResourceReference CSS_COMPONENT_B = new ResourceReference(ComponentB.class, "ComponentB.css");
static final ResourceReference CSS_PANEL_ONE = new ResourceReference(PanelOne.class, "PanelOne.css");
static final ResourceReference CSS_MY_FORM = new ResourceReference(MyForm.class, "MyForm.css");
static final ResourceReference CSS_PRINT_COMPONENT_B = new ResourceReference(ComponentB.class,
"ComponentB-print.css");
static final ResourceReference CSS_PRINT_PANEL_ONE = new ResourceReference(PanelOne.class, "PanelOne-print.css");
static final ResourceReference JS_COMPONENT_B = new ResourceReference(ComponentB.class, "ComponentB.js");
static final ResourceReference JS_PANEL_ONE = new ResourceReference(PanelOne.class, "PanelOne.js");
static final ResourceReference JS_MY_FORM = new ResourceReference(MyForm.class, "MyForm.js");
private static final ResourceReference[] MERGED_CSS = { CSS_COMPONENT_B, CSS_PANEL_ONE, CSS_MY_FORM };
private static final ResourceReference[] MERGED_CSS_PRINT = { CSS_PRINT_COMPONENT_B, CSS_PRINT_PANEL_ONE };
private static final ResourceReference[] MERGED_JS = { JS_COMPONENT_B, JS_PANEL_ONE, JS_MY_FORM };
/**
* Verify that the test page renders as expected (i.e. with each resource
* listed separately) during development.
*/
@Test
public void testRender_development() throws Exception {
WicketTester tester = doRender(DEVELOPMENT);
tester.assertResultPage(ResourceMountTest.class, "ResourceMountTestPage-development-expected.html");
}
/**
* Verify that the test page renders as expected (i.e. with merged resource
* href and src attributes) during deployment.
*/
@Test
public void testRender_deployment() throws Exception {
WicketTester tester = doRender(DEPLOYMENT);
tester.assertResultPage(ResourceMountTest.class, "ResourceMountTestPage-deployment-expected.html");
}
/**
* Verify that individual, non-merged resources can be succesfully
* downloaded in development mode.
*/
@Test
public void testDownload_development() throws IOException {
WicketTester tester = doRender(DEVELOPMENT);
assertDownloaded(tester, "static/styles.css/ComponentB.css", CSS_COMPONENT_B);
assertDownloaded(tester, "static/styles.css/PanelOne.css", CSS_PANEL_ONE);
assertDownloaded(tester, "static/styles.css/MyForm.css", CSS_MY_FORM);
assertDownloaded(tester, "static/styles-print.css/ComponentB-print.css", CSS_PRINT_COMPONENT_B);
assertDownloaded(tester, "static/styles-print.css/PanelOne-print.css", CSS_PRINT_PANEL_ONE);
assertDownloaded(tester, "static/scripts.js/ComponentB.js", JS_COMPONENT_B);
assertDownloaded(tester, "static/scripts.js/PanelOne.js", JS_PANEL_ONE);
}
/**
* Verify that resources are merged during deployment and can be
* successfully downloaded.
*/
@Test
public void testDownload_deployment() throws IOException {
WicketTester tester = doRender(DEPLOYMENT);
assertDownloaded(tester, "static/styles.css", MERGED_CSS);
assertDownloaded(tester, "static/styles-print.css", MERGED_CSS_PRINT);
assertDownloaded(tester, "static/scripts.js", MERGED_JS);
}
/**
* Verify that an exception is thrown if we execute build() without
* specifying a path first.
*/
@Test(expected = IllegalStateException.class)
public void testMissingPath() {
ResourceMount b = new ResourceMount();
b.addResourceSpec(CSS_COMPONENT_B);
b.mount(new WicketTester().getApplication());
fail("mount must throw exception");
}
/**
* Verify that an exception is thrown if we execute build() without
* specifying a resource first.
*/
@Test
public void testMissingResource() {
ResourceMount b = new ResourceMount();
b.setPath("/styles/all.css");
assertNull(b.build(new WicketTester().getApplication()));
}
@Test
public void testGetSuffix() {
assertEquals("js", ResourceMount.getSuffix("/foo.js"));
assertEquals("css", ResourceMount.getSuffix("foo.css"));
assertNull(ResourceMount.getSuffix(".htaccess"));
assertEquals("css", ResourceMount.getSuffix("...strange.css"));
assertNull(ResourceMount.getSuffix("/foo.bar/baz"));
assertNull(ResourceMount.getSuffix("/foo/."));
assertNull(ResourceMount.getSuffix("/"));
assertNull(ResourceMount.getSuffix("/foo"));
assertNull(ResourceMount.getSuffix("/foo/bar"));
}
@Test(expected = WicketRuntimeException.class)
public void testSuffixMismatch() {
new ResourceMount().setPath("/foo.css").addResourceSpecs(CSS_COMPONENT_B, JS_COMPONENT_B)
.mount(new WicketTester().getApplication());
fail("mount must throw exception");
}
@Test
public void testIgnoredSuffixMismatch() {
new ResourceMount().setPath("/foo.css").setSuffixMismatchStrategy(SuffixMismatchStrategy.IGNORE)
.addResourceSpecs(CSS_COMPONENT_B, JS_COMPONENT_B).mount(new WicketTester().getApplication());
}
@Test
public void testNonMergedSuffixMismatch() {
new ResourceMount().setPath("/img").setNoVersion().addResourceSpec(HomePage.class, "test.png")
.mount(new WicketTester().getApplication());
}
/**
* Render the HomePage in either DEVELOPMENT or DEPLOYMENT mode.
*/
private WicketTester doRender(final String mode) {
WicketTester tester = new WicketTester(new MergedApp() {
@Override
public String getConfigurationType() {
return mode;
}
});
tester.startPage(HomePage.class);
tester.assertRenderedPage(HomePage.class);
return tester;
}
private void assertDownloaded(WicketTester tester, String uri, ResourceReference... refs) throws IOException {
ResourceSpec[] specs = new ResourceSpec[refs.length];
for (int i = 0; i < refs.length; i++) {
specs[i] = new ResourceSpec(refs[i]);
}
assertDownloaded(tester, uri, specs);
}
/**
* Download the resource at the given URI and make sure its contents are
* identical to a merged list of files from the test fixture.
*/
private void assertDownloaded(WicketTester tester, String uri, ResourceSpec... specs) throws IOException {
StringList expected = new StringList();
for (ResourceSpec spec : specs) {
InputStream is = spec.getScope().getResourceAsStream(spec.getFile());
try {
expected.add(IOUtils.toString(is, "UTF-8"));
} finally {
IOUtils.closeQuietly(is);
}
}
WebRequestCycle wrc = tester.setupRequestAndResponse(false);
tester.getServletRequest().setURL(uri);
tester.processRequestCycle(wrc);
// Note: merging adds two newlines between each merged file
assertEquals(expected.join("\n\n"), tester.getServletResponse().getDocument());
}
/**
* Test app that mounts merged resources.
*/
static class MergedApp extends WebApplication {
@Override
public Class<? extends WebPage> getHomePage() {
return HomePage.class;
}
@Override
protected void init() {
super.init();
ResourceMount mount = new ResourceMount(Application.DEVELOPMENT.equals(getConfigurationType()));
mount.setMinifyCss(false).setMinifyJs(false);
ResourceMount.mountWicketResourcesMerged("/wicket", this, mount);
mount.clone().setPath("/static/styles.css").addResourceSpecs(MERGED_CSS).mount(this);
mount.clone().setPath("/static/styles-print.css").addResourceSpecs(MERGED_CSS_PRINT).mount(this);
mount.clone().setPath("/static/scripts.js").addResourceSpecs(MERGED_JS).mount(this);
}
}
}