blob: b1a335fa6fbd444df940a2f4a3adb681be6b0d7e [file] [log] [blame]
package org.apache.tapestry5.internal.services;
import org.apache.tapestry5.dom.Document
import org.apache.tapestry5.dom.Element
import org.apache.tapestry5.dom.XMLMarkupModel
import org.apache.tapestry5.internal.test.InternalBaseTestCase
import org.apache.tapestry5.json.JSONArray
import org.apache.tapestry5.services.javascript.InitializationPriority
import org.apache.tapestry5.services.javascript.ModuleManager
import org.apache.tapestry5.services.javascript.StylesheetLink
import org.apache.tapestry5.services.javascript.StylesheetOptions
import org.easymock.EasyMock
import org.easymock.IAnswer
import org.testng.annotations.Test
import static org.easymock.EasyMock.eq
import static org.easymock.EasyMock.isA
class DocumentLinkerImplTest extends InternalBaseTestCase {
def check(Document document, String expectedContent) throws Exception {
// TestNG's assertEquals() is actually more useful here than Groovy's assert. Normally,
// it's the other way around.
assertEquals document.toString(), expectedContent.trim()
}
@Test
void exception_if_missing_html_root_element_and_javascript() {
Document document = new Document()
document.newRootElement("not-html").text("not an HTML document")
DocumentLinkerImpl linker = new DocumentLinkerImpl(null, true, false, "1.2.3")
// Only checked if there's something to link.
linker.addLibrary("foo.js")
linker.addScript(InitializationPriority.NORMAL, "doSomething();")
try {
linker.updateDocument(document)
unreachable()
} catch (RuntimeException ex) {
assert ex.message ==
"The root element of the rendered document was <not-html>, not <html>. A root element of <html> is needed when linking JavaScript and stylesheet resources."
}
}
@Test
void logged_error_if_missing_html_element_and_css() {
Document document = new Document()
document.newRootElement("not-html").text("not an HTML document")
DocumentLinkerImpl linker = new DocumentLinkerImpl(null, true, false, "1.2.3")
// Only checked if there's something to link.
linker.addStylesheetLink(new StylesheetLink("style.css"))
replay()
linker.updateDocument(document)
// Check that document is unchanged.
check document, "<not-html>not an HTML document</not-html>"
verify()
}
@Test
void missing_root_element_is_a_noop() {
Document document = new Document()
DocumentLinkerImpl linker = new DocumentLinkerImpl(null, true, false, "1.2.3")
linker.addLibrary("foo.js")
linker.addScript(InitializationPriority.NORMAL, "doSomething();")
// No root element is not an error, even though there's work to do.
// The failure to render is reported elsewhere.
linker.updateDocument(document)
}
@Test
void add_script_links() throws Exception {
Document document = new Document(new XMLMarkupModel())
document.newRootElement("html").element("body").element("p").text("Ready to be updated with scripts.")
def manager = mockModuleManager(["core.js", "foo.js", "bar/baz.js"], [new JSONArray("t5/core/pageinit:evalJavaScript", "pageINIT();")])
DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, true, false, "1.2.3")
replay()
linker.addLibrary("core.js")
linker.addLibrary("foo.js")
linker.addLibrary("bar/baz.js")
linker.addScript(InitializationPriority.NORMAL, "pageINIT();")
linker.updateDocument(document)
check document, '''
<?xml version="1.0"?>
<html><body data-page-initialized="false"><p>Ready to be updated with scripts.</p><!--MM-CONFIG--><!--MM-INIT--></body></html>
'''
verify()
}
/**
* TAP5-446
*/
@Test
void include_generator_meta() throws Exception {
Document document = new Document(new XMLMarkupModel())
document.newRootElement("html").element("body").element("p").text("Ready to be marked with generator meta.")
DocumentLinkerImpl linker = new DocumentLinkerImpl(null, false, false, "1.2.3")
linker.updateDocument(document)
check document, '''
<?xml version="1.0"?>
<html><head><meta content="Apache Tapestry Framework (version 1.2.3)" name="generator"/></head><body data-page-initialized="true"><p>Ready to be marked with generator meta.</p></body></html>
'''
}
/**
* TAP5-584
*/
@Test
void omit_generator_meta_on_no_html_root() throws Exception {
Document document = new Document(new XMLMarkupModel())
document.newRootElement("no_html").text("Generator meta only added if root is html tag.")
DocumentLinkerImpl linker = new DocumentLinkerImpl(null, false, false, "1.2.3")
linker.updateDocument(document)
check document, '''
<?xml version="1.0"?>
<no_html>Generator meta only added if root is html tag.</no_html>
'''
}
@Test
void add_style_links() throws Exception {
Document document = new Document(new XMLMarkupModel())
document.newRootElement("html").element("body").element("p").text("Ready to be updated with styles.")
DocumentLinkerImpl linker = new DocumentLinkerImpl(null, true, false, "1.2.3")
linker.addStylesheetLink(new StylesheetLink("foo.css"))
linker.addStylesheetLink(new StylesheetLink("bar/baz.css", new StylesheetOptions("print")))
linker.updateDocument(document)
check document, '''
<?xml version="1.0"?>
<html><head><link type="text/css" rel="stylesheet" href="foo.css"/><link media="print" type="text/css" rel="stylesheet" href="bar/baz.css"/></head><body data-page-initialized="true"><p>Ready to be updated with styles.</p></body></html>
'''
}
@Test
void existing_head_used_if_present() throws Exception {
Document document = new Document(new XMLMarkupModel())
document.newRootElement("html").element("head").comment(" existing head ").container.element("body").text(
"body content")
DocumentLinkerImpl linker = new DocumentLinkerImpl(null, true, false, "1.2.3")
linker.addStylesheetLink(new StylesheetLink("foo.css"))
linker.updateDocument(document)
check document, '''
<?xml version="1.0"?>
<html><head><!-- existing head --><link type="text/css" rel="stylesheet" href="foo.css"/></head><body data-page-initialized="true">body content</body></html>
'''
}
@Test
void add_script() throws Exception {
Document document = new Document()
document.newRootElement("html").element("body").element("p").text("Ready to be updated with scripts.")
def manager = mockModuleManager([], [new JSONArray("t5/core/pageinit:evalJavaScript", "doSomething();")])
DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, true, true, "1.2.3")
replay()
linker.addScript(InitializationPriority.IMMEDIATE, "doSomething();")
linker.updateDocument(document)
check document, '''
<html><body data-page-initialized="false"><script type="text/javascript">document.write("<div class=\\"pageloading-mask\\"><div></div></div>");</script><p>Ready to be updated with scripts.</p><!--MM-CONFIG--><!--MM-INIT--></body></html>
'''
verify()
}
/**
* Perhaps the linker should create the &lt;body&gt; element in this case? In the meantime,
*/
@Test
void no_body_element() throws Exception {
Document document = new Document(new XMLMarkupModel())
document.newRootElement("html").element("notbody").element("p").text("Ready to be updated with scripts.")
def manager = mockModuleManager(["foo.js"], [])
DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, true, false, "1.2.3")
replay()
linker.addLibrary("foo.js")
linker.updateDocument(document)
check document, '''
<?xml version="1.0"?>
<html><notbody><p>Ready to be updated with scripts.</p></notbody><body data-page-initialized="false"><!--MM-CONFIG--><!--MM-INIT--></body></html>
'''
verify()
}
@Test
void immediate_initialization() throws Exception {
Document document = new Document()
Element head = document.newRootElement("html").element("head")
head.element("meta")
head.element("script")
def manager = mockModuleManager([], [new JSONArray("['immediate/module:myfunc', {'fred':'barney'}]")])
DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, true, false, "1.2.3")
replay()
linker.addInitialization(InitializationPriority.IMMEDIATE, "immediate/module", "myfunc", new JSONArray("[{ 'fred' : 'barney' }]"))
linker.updateDocument(document)
check document, '''
<html><head><meta/><script></script></head><body data-page-initialized="false"><!--MM-CONFIG--><!--MM-INIT--></body></html>
'''
verify()
}
@Test
void ie_conditional_stylesheet() throws Exception {
Document document = new Document()
document.newRootElement("html")
DocumentLinkerImpl linker = new DocumentLinkerImpl(null, true, false, "1.2.3")
linker.addStylesheetLink(new StylesheetLink("everybody.css"))
linker.addStylesheetLink(new StylesheetLink("just_ie.css", new StylesheetOptions().withCondition("IE")))
linker.updateDocument(document)
check document, '''
<html><head><link type="text/css" rel="stylesheet" href="everybody.css"/>
<!--[if IE]>
<link type="text/css" rel="stylesheet" href="just_ie.css"/>
<![endif]-->
</head><body data-page-initialized="true"></body></html>
'''
}
@Test
void stylesheet_insertion_point() throws Exception {
Document document = new Document()
document.newRootElement("html")
DocumentLinkerImpl linker = new DocumentLinkerImpl(null, true, false, "1.2.3")
linker.addStylesheetLink(new StylesheetLink("whatever.css"))
linker.addStylesheetLink(new StylesheetLink("insertion-point.css", new StylesheetOptions().asAjaxInsertionPoint()))
linker.updateDocument(document)
check document, '''
<html><head><link type="text/css" rel="stylesheet" href="whatever.css"/><link type="text/css" rel="stylesheet t-ajax-insertion-point" href="insertion-point.css"/></head><body data-page-initialized="true"></body></html>
'''
}
@Test
void module_based_INIT() throws Exception {
Document document = new Document()
Element head = document.newRootElement("html").element("head")
head.element("meta")
def manager = mockModuleManager([], ["my/module",
new JSONArray("my/other/module:normal", 111, 222),
new JSONArray("my/other/module:late", 333, 444)])
DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, true, false, "1.2.3")
replay()
linker.addInitialization(InitializationPriority.NORMAL, "my/module", null, null)
linker.addInitialization(InitializationPriority.NORMAL, "my/other/module", "normal", new JSONArray(111, 222))
linker.addInitialization(InitializationPriority.LATE, "my/other/module", "late", new JSONArray(333, 444))
linker.updateDocument(document)
check document, '''
<html><head><meta/></head><body data-page-initialized="false"><!--MM-CONFIG--><!--MM-INIT--></body></html>
'''
verify()
}
@Test
void module_INIT_with_no_parameters_coalesce() throws Exception {
Document document = new Document()
Element head = document.newRootElement("html").element("head")
head.element("meta")
def manager = mockModuleManager([], ["my/module",
new JSONArray("my/other/module:normal", 111, 222)])
DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, true, false, "1.2.3")
replay()
linker.addInitialization(InitializationPriority.NORMAL, "my/module", null, null)
linker.addInitialization(InitializationPriority.NORMAL, "my/other/module", "normal", new JSONArray(111, 222))
linker.addInitialization(InitializationPriority.NORMAL, "my/module", null, new JSONArray());
linker.updateDocument(document)
check document, '''
<html><head><meta/></head><body data-page-initialized="false"><!--MM-CONFIG--><!--MM-INIT--></body></html>
'''
verify()
}
private ModuleManager mockModuleManager(def libraryURLs, def inits) {
ModuleManager mock = newMock(ModuleManager);
expect(mock.writeConfiguration(isA(Element),
eq([]))).andAnswer({
def body = EasyMock.currentArguments[0]
body.comment("MM-CONFIG")
} as IAnswer).once()
expect(mock.writeInitialization(isA(Element),
eq(libraryURLs),
eq(inits))).andAnswer({
def body = EasyMock.currentArguments[0];
body.comment("MM-INIT");
} as IAnswer).once()
return mock;
}
}