package com.tddinaction.j2ee.web.view.velocity;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.StringWriter;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.junit.Before;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public abstract class VelocityTestCase {
private VelocityContext context;
private Document document;
@Before
public void setUp() throws Exception {
context = new VelocityContext();
}
protected String getWebRoot() {
return ".";
}
protected Document getResponse() {
return document;
}
protected void setAttribute(String name, Object value) {
context.put(name, value);
}
protected void render(String templatePath) throws Exception {
String template = readFileContent(new File(getWebRoot(),
templatePath));
String renderedHtml = renderTemplate(template);
this.document = parseHtml(renderedHtml);
}
private String renderTemplate(String template) throws Exception {
VelocityEngine engine = new VelocityEngine();
engine.init();
StringWriter writer = new StringWriter();
engine.evaluate(context, writer, "test", template);
return writer.toString();
}
private Document parseHtml(String html) throws Exception {
return parseXml(html);
}
private Document parseXml(String xml) throws Exception {
DocumentBuilder b = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
return b.parse(new ByteArrayInputStream(xml.getBytes()));
}
private String readFileContent(File file) throws Exception {
FileReader reader = new FileReader(file);
StringWriter writer = new StringWriter();
char[] buffer = new char[8096];
int r = -1;
while ((r = reader.read(buffer)) != -1) {
writer.write(buffer, 0, r);
}
reader.close();
return String.valueOf(writer);
}
protected void assertFormFieldPresent(String name)
throws Exception {
assertNodeExists(xpathForField(name));
}
protected void assertFormSubmitButtonPresent(String name)
throws Exception {
assertNodeExists("//form//input[@type='submit' and @name='"
+ name + "']");
}
protected void assertFormFieldValue(String name,
String expectedValue) throws Exception {
String xpath = xpathForField(name);
assertFormFieldPresent(name);
String actual = getString(xpath + "/@value");
assertEquals(expectedValue, actual);
}
private String xpathForField(String name) {
return "//form//input[@name='" + name + "']";
}
private void assertNodeExists(String xpath) throws Exception {
assertNotNull("Node doesn't exist: " + xpath, getNode(xpath));
}
private Node getNode(String xpath) throws Exception {
return (Node) evaluate(xpath, XPathConstants.NODE);
}
private String getString(String xpath) throws Exception {
return (String) evaluate(xpath, XPathConstants.STRING);
}
private Object evaluate(String xpath, QName type)
throws Exception {
XPath engine = XPathFactory.newInstance().newXPath();
return engine.evaluate(xpath, getResponse(), type);
}
protected void assertTextPresent(String text) throws Exception {
StringBuilder buffer = new StringBuilder(10000);
collectTextContent(document, buffer);
assertTrue("Text not found on page: " + text, buffer
.toString().contains(text));
}
private void collectTextContent(Node node, StringBuilder buffer) {
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.TEXT_NODE) {
buffer.append(child.getNodeValue());
} else if (child.getNodeType() == Node.ELEMENT_NODE) {
collectTextContent(child, buffer);
}
}
}
}