xlawrence 2005/07/08 16:50:16 CEST
Added files:
core/src/java/org/jahia/services/htmlparser WAIValidator.java
core/src/test/src/java/org/jahia/services/htmlparser
WAIValidatorTest.java
Log:
First version of the WAI validator (bronze level)
Revision Changes Path
1.1 +807 -0
jahia/core/src/java/org/jahia/services/htmlparser/WAIValidator.java (new)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/java/org/jahia/services/htmlparser/WAIValidator.java?rev=1.1&content-type=text/plain
1.1 +252 -0
jahia/core/src/test/src/java/org/jahia/services/htmlparser/WAIValidatorTest.java
(new)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/test/src/java/org/jahia/services/htmlparser/WAIValidatorTest.java?rev=1.1&content-type=text/plain
Index: WAIValidator.java
====================================================================
/*
* ____.
* __/\ ______| |__/\. _______
* __ .____| | \ | +----+ \
* _______| /--| | | - \ _ | : - \_________
* \\______: :---| : : | : | \________>
* |__\---\_____________:______: :____|____:_____\
* /_____|
*
* . . . i n j a h i a w e t r u s t . . .
*
*
*
* ----- BEGIN LICENSE BLOCK -----
* Version: JCSL 1.0
*
* The contents of this file are subject to the Jahia Community Source License
* 1.0 or later (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.jahia.org/license
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the rights, obligations and limitations governing use of the contents
* of the file. The Original and Upgraded Code is the Jahia CMS and Portal
* Server. The developer of the Original and Upgraded Code is JAHIA Ltd. JAHIA
* Ltd. owns the copyrights in the portions it created. All Rights Reserved.
*
* The Shared Modifications are Jahia View Helper.
*
* The Developer of the Shared Modifications is Jahia Solution Sàrl.
* Portions created by the Initial Developer are Copyright (C) 2002 by the
* Initial Developer. All Rights Reserved.
*
* ----- END LICENSE BLOCK -----
*/
package org.jahia.services.htmlparser;
import org.jahia.engines.validation.EngineValidationHelper;
import org.jahia.engines.validation.ValidationError;
import org.jahia.utils.JahiaTools;
import org.cyberneko.html.parsers.DOMFragmentParser;
import org.w3c.dom.Node;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.DOMException;
import org.w3c.dom.html.HTMLDocument;
import org.w3c.dom.html.HTMLBodyElement;
import org.w3c.dom.html.HTMLAnchorElement;
import org.w3c.dom.html.HTMLImageElement;
import org.w3c.dom.html.HTMLAreaElement;
import org.w3c.dom.html.HTMLFormElement;
import org.w3c.dom.html.HTMLTableElement;
import org.w3c.dom.html.HTMLFrameElement;
import org.apache.html.dom.HTMLDocumentImpl;
import org.apache.html.dom.HTMLAnchorElementImpl;
import org.apache.html.dom.HTMLImageElementImpl;
import org.apache.html.dom.HTMLAreaElementImpl;
import org.apache.html.dom.HTMLFormElementImpl;
import org.apache.html.dom.HTMLTableElementImpl;
import org.apache.html.dom.HTMLFrameElementImpl;
import org.apache.html.dom.HTMLTableCaptionElementImpl;
import org.apache.html.dom.HTMLTableRowElementImpl;
import org.apache.html.dom.HTMLLabelElementImpl;
import org.apache.html.dom.HTMLInputElementImpl;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
/**
* This class is used to validate an HTML fragment against the WAI (Accessiweb
* Section 508) rules. All the 55 "Bronze" criterias can be found here: <br/>
* <a
href="http://www.accessiweb.org/fr/Label%5FAccessibilite/criteres%5Faccessiweb/55%5Faccessiweb%5Fbronze/"
* target="_blank">Accessiweb</a>
*
* @author Xavier Lawrence
*/
public class WAIValidator {
private static final org.apache.log4j.Logger logger =
org.apache.log4j.Logger.getLogger(WAIValidator.class);
protected final DOMFragmentParser parser = new DOMFragmentParser();
private boolean isDataTable = true;
private int formLevel;
protected final HashMap linkToDest = new HashMap();
/**
* Validates a HTML fragment represented as a String.
* @param inputHTML The html fragment
*
* @return EngineValidationHelper containing the validation errors, in
case
* of no errors, an empty EngineValidationHelper is returned.
*
* @throws IOException If problems occured with the Temporary file
* used to store the input HTML fragment.
*/
public EngineValidationHelper validate( final String inputHTML )
throws IOException {
final EngineValidationHelper evh = new EngineValidationHelper();
final HTMLDocument document = new HTMLDocumentImpl();
final DocumentFragment fragment = document.createDocumentFragment();
final File tempFile = File.createTempFile("tmp", ".html");
try {
final FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(inputHTML.getBytes());
fos.flush();
fos.close();
parser.parse(tempFile.getAbsolutePath(), fragment);
} catch (Exception e) {
logger.error("Error parsing HTML fragment !", e);
final ValidationError error = new
ValidationError(WAIValidator.class,
"Unable to parse HTML fragment: " + e.getMessage());
evh.addError(error);
return evh;
} finally {
if (tempFile != null) {
tempFile.delete();
}
}
// The DOMFragmentParser generates a HTML and a BODY element which are
// of no interest for us. We select the HTMLBodyElement which will
then
// be consumed in the validateHtml method. It is the starting root
element
// of the HTML fragment.
linkToDest.clear();
final HTMLBodyElement node =
(HTMLBodyElement)fragment.getFirstChild().
getFirstChild();
final List errors = validateHtml(node);
for (int i=0; i<errors.size(); i++) {
evh.addError((ValidationError)errors.get(i));
}
return evh;
}
/**
* Validates an HTML fragment starting from the body element.
*
* @param node The HTMLBodyElement implementation node.
* @return A list of ValidationError Objects, the list will be emtpy in
case
* no errors occured.
*/
protected List validateHtml( final HTMLBodyElement node ) {
final List errors = new ArrayList();
try {
validateHtml(node, errors, 0);
} catch (DOMException de) {
logger.error("Cannot validate html: "+ de.getMessage(), de);
final ValidationError ve = new ValidationError(this,
"Cannot validate html: "+ de.getMessage());
errors.add(ve);
}
return errors;
}
/**
* Recursive method that goes through all the nodes of the parsed HTML
tree.
*
* @param node The current Node being processed.
* @param errors The List of errors reported so far
* @param level The level in the Tree of the node being processed
*
* @throws DOMException If something goes wrong.
*/
private void validateHtml( final Node node, final List errors,
int level) throws DOMException {
Node child;
if (processNode(node, errors, level)) {
child = node.getFirstChild();
level++;
} else {
return;
}
while (child != null) {
validateHtml(child, errors, level);
child = child.getNextSibling();
}
}
/**
* Method that tests the class of the given node and invokes the proper
* validation method.
*
* @param node The current Node
* @param errors The List of reported errors so far
* @param level The level of the Node in the DOM tree.
*
* @return True if the next Node to process is a Child Node, False if the
* next Node has to be a Sibling Node.
*
* @throws DOMException If something goes wrong.
*/
private boolean processNode( final Node node, final List errors,
final int level) throws DOMException {
resetIsDataTable(level);
final Class childClass = node.getClass();
final ValidationError err;
if (childClass == HTMLAnchorElementImpl.class) {
err = validateLink((HTMLAnchorElement)node);
} else if (childClass == HTMLImageElementImpl.class) {
err = validateImage((HTMLImageElement)node);
} else if (childClass == HTMLAreaElementImpl.class) {
err = validateAreaShape((HTMLAreaElement)node);
} else if (childClass == HTMLFormElementImpl.class) {
errors.addAll(validateForm((HTMLFormElement)node,
level));
return false;
} else if (childClass == HTMLTableElementImpl.class) {
errors.addAll(validateTable((HTMLTableElement)node));
return false;
} else if (childClass == HTMLFrameElementImpl.class) {
err = validateFrame((HTMLFrameElement)node);
} else {
logger.debug("Ignoring node of type: " + childClass);
return true;
}
if (err != null) { errors.add(err); }
return true;
}
/**
* Sets the isDataTable boolean to false and stores the level of the Node
* which invoked this method. The variable is used to distinguish data
Tables,
* which need to be validated, against formatting or form tables which
don't.
*
* @param level The level of the Form tag being processed.
*/
protected void setIsDataTable(int level) {
if (! isDataTable) {
throw new IllegalStateException("isDataTable allready set");
}
formLevel = level;
isDataTable = false;
}
/**
* If the level given in parameter is equal to the formLevel which
* previously set the isDataTable to false, then we have finished
* processing the form and we can set the variable back to true.
*
* @param level The level of the tag being processed.
*/
protected void resetIsDataTable(int level) {
if (level == formLevel) {
isDataTable = true;
}
}
/**
* Validates a link Element.
*
* @param node The HTMLAnchorElement.
* @return ValidationError or null if no error occured.
*/
protected ValidationError validateLink( final HTMLAnchorElement node )
throws DOMException {
logger.info("validateLink");
// Criteria 6.1
final String linkValue = JahiaTools.text2XMLEntityRef(
node.getFirstChild().getNodeValue(), 1);
final int length = linkValue.length();
if (length > 80) {
final ValidationError ve = new ValidationError(this,
"Link value should not be longer than 80 characters.
Length = " +
length);
return ve;
}
// Criteria 6.3
final Node title = node.getAttributes().getNamedItem("title");
if (title == null) {
final ValidationError ve = new ValidationError(this,
"Missing 'title' attribute for 'hyperlink' element");
return ve;
}
// Criteria 6.3 bis
final String titleValue = JahiaTools.text2XMLEntityRef(
title.getNodeValue(), 1);
final int length2 = titleValue.length();
if (length2 > 80) {
final ValidationError ve = new ValidationError(this,
"Attribute 'title' should not be longer than 80
characters. Length = " +
length2);
return ve;
}
// Criteria 6.5
final String hrefValue =
node.getAttributes().getNamedItem("href").getNodeValue();
if (linkToDest.containsKey(linkValue)) {
final String dest = (String)linkToDest.get(linkValue);
if (! hrefValue.equals(dest)) {
final ValidationError ve = new ValidationError(this,
"All same link values should point to the same
destination");
return ve;
}
} else {
linkToDest.put(linkValue, hrefValue);
}
return null;
}
/**
* Validates an Img Element.
*
* @param node The HTMLImageElement.
* @return ValidationError or null if no error occured.
*/
protected ValidationError validateImage( final HTMLImageElement node ) {
logger.info("validateImage");
// Criteria 1.1
final Node alt = node.getAttributes().getNamedItem("alt");
if (alt == null) {
final Node src = node.getAttributes().getNamedItem("src");
final String srcText;
if (src == null) {
srcText = "n/a";
} else {
srcText = src.getNodeValue();
}
final ValidationError ve = new ValidationError(this,
"Missing 'alt' attribute for image " + srcText);
return ve;
}
// Criteria 1.4
final String altValue =
JahiaTools.text2XMLEntityRef(alt.getNodeValue(), 1);
final int length = altValue.length();
if (length > 60) {
final ValidationError ve = new ValidationError(this,
"Attribute 'alt' should not be longer than 60 characters.
Length = " +
length + ". Use attribute 'longdesc' if you want a longer
description");
return ve;
}
return null;
}
/**
* Validates an Area Element.
*
* @param node The HTMLAreaElement.
* @return ValidationError or null if no error occured.
*/
protected ValidationError validateAreaShape( final HTMLAreaElement node )
{
logger.info("validateAreaShape");
// Criteria 1.1
if (node.getAttributes().getNamedItem("shape") != null) {
final Node alt = node.getAttributes().getNamedItem("alt");
if (alt == null) {
final ValidationError ve = new ValidationError(this,
"Missing 'alt' attribute for 'area' element");
return ve;
}
}
return null;
}
/**
* Validates a Table Element.
*
* @param node The HTMLFormElement.
* @return A List of ValidationError Objects.
*/
protected List validateTable( final HTMLTableElement node ) {
logger.info("validateTable");
final List errors = new ArrayList();
if (! isDataTable) { return errors; }
/*
*
<TABLE border="1"
summary="This table charts the number of cups
of coffee consumed by each senator, the type
of coffee (decaf or regular), and whether
taken with sugar.">
<CAPTION>Cups of coffee consumed by each senator</CAPTION>
<TR>
<TH id="t1">Name</TH>
<TH id="t2">Cups</TH>
<TH id="t3" abbr="Type">Type of Coffee</TH>
<TH id="t4">Sugar?</TH>
<TR>
<TD headers="t1">T. Sexton</TD>
<TD headers="t2">10</TD>
<TD headers="t3">Espresso</TD>
<TD headers="t4">No</TD>
<TR>
<TD headers="t1">J. Dinnen</TD>
<TD headers="t2">5</TD>
<TD headers="t3">Decaf</TD>
<TD headers="t4">Yes</TD>
</TABLE>
*
*
<TABLE border="1"
summary="This table charts the number of cups
of coffee consumed by each senator, the type
of coffee (decaf or regular), and whether
taken with sugar.">
<CAPTION>Cups of coffee consumed by each senator</CAPTION>
<TR>
<TH scope="col">Name</TH>
<TH scope="col">Cups</TH>
<TH scope="col" abbr="Type">Type of Coffee</TH>
<TH scope="col">Sugar?</TH>
<TR>
<TD>T. Sexton</TD>
<TD>10</TD>
<TD>Espresso</TD>
<TD>No</TD>
<TR>
<TD>J. Dinnen</TD>
<TD>5</TD>
<TD>Decaf</TD>
<TD>Yes</TD>
</TABLE>
*
*/
// Criteria 5.1
final Node summary = node.getAttributes().getNamedItem("summary");
if (summary == null) {
final ValidationError ve = new ValidationError(this,
"Missing 'summary' attribute for 'table' element");
errors.add(ve);
return errors;
}
Node caption = node.getFirstChild();
while (caption != null &&
caption.getClass() != HTMLTableCaptionElementImpl.class) {
caption = caption.getNextSibling();
}
// Criteria 5.2
if (caption == null) {
final ValidationError ve = new ValidationError(this,
"Missing 'caption' element for 'table' element");
errors.add(ve);
return errors;
}
// Criteria 5.3
Node header = node.getFirstChild();
while (header != null &&
header.getClass() != HTMLTableRowElementImpl.class) {
header = header.getNextSibling();
}
header = node.getFirstChild();
// get the first row
while (! "tr".equals(header.getNodeName().toLowerCase())) {
header = header.getNextSibling();
}
header = header.getFirstChild();
final ArrayList ids = new ArrayList();
int scopes = 0;
while (header != null) {
if (! "th".equals(header.getNodeName().toLowerCase())) {
final ValidationError ve = new ValidationError(this,
"The first row of a 'table' element should contain
'th' elements only");
errors.add(ve);
return errors;
}
final Node scope = header.getAttributes().getNamedItem("scope");
final Node id = header.getAttributes().getNamedItem("id");
if ((scope == null && id == null) || (scope != null && id !=
null)) {
final ValidationError ve = new ValidationError(this,
"'th' elements should have an attribute 'scope', set
to 'col', OR an 'id' attribute");
errors.add(ve);
return errors;
}
if (id == null) {
if (! "col".equals(scope.getNodeValue().toLowerCase())) {
final ValidationError ve = new ValidationError(this,
"The 'th' elements of the first row of the table
should have a 'col' scope");
errors.add(ve);
return errors;
}
scopes++;
} else {
final String value = id.getNodeValue();
if (! ids.contains(value)) {
ids.add(value);
}
}
header = header.getNextSibling();
}
if (scopes > 0 && ids.size() > 0) {
final ValidationError ve = new ValidationError(this,
"The 'th' elements of the first row of the table should
all use the same attribute");
errors.add(ve);
return errors;
}
// check the rest of the table cells
if (ids.size() > 0) {
final List headers = new ArrayList();
processTable(node, headers, errors);
final ArrayList ids2 = (ArrayList)ids.clone();
for (int i=0; i<ids2.size(); i++) {
final String value = (String)ids2.get(i);
if (headers.contains(value)) {
headers.remove(value);
ids.remove(value);
}
}
if (headers.size() > 0) {
for (int i=0; i<headers.size(); i++) {
final ValidationError ve = new ValidationError(this,
"Attribute 'header' (" + headers.get(i) + ") has
no corresponding 'id'");
errors.add(ve);
}
}
}
return errors;
}
/**
* Recursive method to process a Table element and all its children
*
* @param node The current node of the Table.
* @param headers The current list of 'headers' attributes (present in
tds)
* @param errors The current list of errors
*/
protected void processTable( final Node node, final List headers,
final List errors ){
// Criteria 5.4
if ( "td".equals(node.getNodeName().toLowerCase())) {
final Node header = node.getAttributes().getNamedItem("headers");
if (header == null) {
final ValidationError ve = new ValidationError(this,
"Missing 'headers' attribute for 'td' element");
errors.add(ve);
} else {
final String value = header.getNodeValue();
if (! headers.contains(value)) {
headers.add(value);
}
}
}
Node child = node.getFirstChild();
while (child != null) {
processTable(child, headers, errors);
child = child.getNextSibling();
}
}
/**
* Validates a Form Element.
*
* @param node The HTMLFormElement.
* @param level The level of the root form node in relation to the top
root
* node of the html fragment.
* @return A List of ValidationError Objects.
*/
protected List validateForm( final HTMLFormElement node,
final int level) {
logger.info("validateForm");
setIsDataTable(level);
final ArrayList fors = new ArrayList();
final ArrayList ids = new ArrayList();
final ArrayList errors = new ArrayList();
/*
<FORM action="..." method="post">
<LABEL for="firstname">First name: </LABEL>
<INPUT type="text" id="firstname">
*/
processForm(node, fors, ids, errors);
final ArrayList fors2 = (ArrayList)fors.clone();
for (int i=0; i<fors2.size(); i++) {
final String value = (String)fors2.get(i);
if (ids.contains(value)) {
fors.remove(value);
ids.remove(value);
}
}
if (fors.size() > 0) {
for (int i=0; i<fors.size(); i++) {
final ValidationError ve = new ValidationError(this,
"They are no 'id' attribute in any 'input' element
for attribute 'for' (" +
fors.get(i) + "). Check all your 'label' elements in
the 'form'");
errors.add(ve);
}
}
if (ids.size() > 0) {
for (int i=0; i<ids.size(); i++) {
final ValidationError ve = new ValidationError(this,
"All text 'input' elements should have a
corresponding 'label' element." +
"'Input' element with id (" + ids.get(i) + ") has no
label");
errors.add(ve);
}
}
return errors;
}
/**
* Recursive method to process a Form element and all its children
*
* @param node The current node of the Form.
* @param fors The current list of 'for' attributes (present in labels)
* @param ids The current list of 'id' attributes (present in text inputs)
* @param errors The current list of errors
*/
private void processForm(final Node node, final List fors, final List ids,
final List errors) {
// Criteria 11.1
if (node.getClass() == HTMLLabelElementImpl.class) {
final Node forAttr = node.getAttributes().getNamedItem("for");
if (forAttr == null) {
final ValidationError ve = new ValidationError(this,
"Missing 'for' attribute for 'label' element");
errors.add(ve);
} else {
final String value = forAttr.getNodeValue();
if (! fors.contains(value)) {
fors.add(value);
}
}
} else if (node.getClass() == HTMLInputElementImpl.class) {
if (
"text".equals(node.getAttributes().getNamedItem("type").getNodeValue()) ) {
final Node idAttr = node.getAttributes().getNamedItem("id");
if (idAttr == null) {
final ValidationError ve = new ValidationError(this,
"Missing 'id' attribute for 'input' element");
errors.add(ve);
} else {
final String value = idAttr.getNodeValue();
if (! ids.contains(value)) {
ids.add(value);
}
}
}
}
Node child = node.getFirstChild();
while (child != null) {
processForm(child, fors, ids, errors);
child = child.getNextSibling();
}
}
/**
* Validates a Frame Element.
*
* @param node The HTMLFrameElement.
* @return ValidationError or null if no error occured.
*/
protected ValidationError validateFrame( final HTMLFrameElement node ) {
logger.info("validateFrame");
// Criteria 2.1
final Node name = node.getAttributes().getNamedItem("name");
if (name == null) {
final ValidationError ve = new ValidationError(this,
"Missing 'name' attribute for 'frame' element");
return ve;
}
// Criteria 2.1 (Remarque)
final String nameValue =
JahiaTools.text2XMLEntityRef(name.getNodeValue(), 1);
if (nameValue.indexOf(' ') > -1) {
final ValidationError ve = new ValidationError(this,
"Attribute 'name' cannot contain any white space");
return ve;
}
// Criteria 2.5
final Node title = node.getAttributes().getNamedItem("title");
if (title == null) {
final ValidationError ve = new ValidationError(this,
"Missing 'title' attribute for 'frame' element");
return ve;
}
// Criteria 2.10
final Node scrolling = node.getAttributes().getNamedItem("scrolling");
if (scrolling != null &&
"no".equals(scrolling.getNodeValue().toLowerCase())) {
final ValidationError ve = new ValidationError(this,
"Scrolling should be set to at least 'auto' for frame " +
nameValue);
return ve;
}
return null;
}
/**
* Prints the content (at Log4j INFO level) of a Node and all its siblings
* and children if the recursive parameter is set to TRUE.
*
* @param node The starting root node
* @param indent The indent to put to distinguish bewteen levels
* @param recursive If False, prints only the current Node
*
* @param throws DOMException If something goes wrong with node values
*/
public static void print( final Node node, final String indent,
final boolean recursive) throws DOMException {
final StringBuffer buff = new StringBuffer();
buff.append(indent).
append(node.getClass().getName()).
append(": NodeName '").append(node.getNodeName()
).append("'").
append(", Attributes ");
if (node.getAttributes() != null &&
node.getAttributes().getLength() > 0) {
buff.append("{");
for (int i=0; i<node.getAttributes().getLength(); i++) {
final Node n = node.getAttributes().item(i);
buff.append(n.getNodeName()).append("=").
append(n.getNodeValue()).append(",");
}
buff.deleteCharAt(buff.length() - 1);
buff.append("}");
} else {
buff.append("{}");
}
buff.append(", NodeValue '").append(node.getNodeValue() ).append("'");
logger.info(buff.toString());
if (! recursive) { return; }
Node child = node.getFirstChild();
while (child != null) {
print(child, indent + "\t", true);
child = child.getNextSibling();
}
}
public String toString() {
return getClass().getName();
}
}
Index: WAIValidatorTest.java
====================================================================
/*
* ____.
* __/\ ______| |__/\. _______
* __ .____| | \ | +----+ \
* _______| /--| | | - \ _ | : - \_________
* \\______: :---| : : | : | \________>
* |__\---\_____________:______: :____|____:_____\
* /_____|
*
* . . . i n j a h i a w e t r u s t . . .
*
*
*
* ----- BEGIN LICENSE BLOCK -----
* Version: JCSL 1.0
*
* The contents of this file are subject to the Jahia Community Source License
* 1.0 or later (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.jahia.org/license
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the rights, obligations and limitations governing use of the contents
* of the file. The Original and Upgraded Code is the Jahia CMS and Portal
* Server. The developer of the Original and Upgraded Code is JAHIA Ltd. JAHIA
* Ltd. owns the copyrights in the portions it created. All Rights Reserved.
*
* The Shared Modifications are Jahia View Helper.
*
* The Developer of the Shared Modifications is Jahia Solution Sàrl.
* Portions created by the Initial Developer are Copyright (C) 2002 by the
* Initial Developer. All Rights Reserved.
*
* ----- END LICENSE BLOCK -----
*/
package org.jahia.services.htmlparser;
import junit.framework.*;
import junitx.framework.OrderedTestSuite;
import org.jahia.engines.validation.EngineValidationHelper;
import org.jahia.engines.validation.ValidationError;
import org.cyberneko.html.parsers.DOMFragmentParser;
import org.w3c.dom.Node;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.html.HTMLDocument;
import org.w3c.dom.html.HTMLBodyElement;
import org.w3c.dom.html.HTMLAnchorElement;
import org.w3c.dom.html.HTMLFormElement;
import org.w3c.dom.html.HTMLTableElement;
import org.apache.html.dom.HTMLDocumentImpl;
import java.io.*;
/**
*
* @author Xavier Lawrence
*/
public class WAIValidatorTest extends TestCase {
private static final org.apache.log4j.Logger logger =
org.apache.log4j.Logger.getLogger(WAIValidatorTest.class);
protected final String table =
"<table width=\"200\" border=\"1\" summary=\"yop\">" +
"<tr>" +
"<th scope=\"col\">yop</th>" +
"<th scope=\"col\"> </th>" +
"<th scope=\"col\"> </th>" +
"</tr>" +
"<tr>" +
"<td headers=\"good\">a</td>" +
"<td headers=\"good\"> </td>" +
"<td headers=\"good\"> </td>" +
"</tr>" +
"<tr>" +
"<td headers=\"good\"> </td>" +
"<td headers=\"good\"> </td>" +
"<td headers=\"good\"> </td>" +
"</tr>" +
"<caption>Enorme</caption>" +
"</table>";
protected final String table2 =
"<TABLE border=\"1\"" +
"summary=\"This table charts the number of cups" +
"of coffee consumed by each senator, the type" +
"of coffee (decaf or regular), and whether" +
"taken with sugar.\">" +
"<CAPTION>Cups of coffee consumed by each senator</CAPTION>" +
"<TR>" +
"<TH id=\"t1\">Name</TH>" +
"<TH id=\"t2\">Cups</TH>" +
"<TH id=\"t3\" abbr=\"Type\">Type of Coffee</TH>" +
"<TH id=\"t4\">Sugar?</TH>" +
"<TR>" +
"<TD headers=\"t12\">T. Sexton</TD>" +
"<TD headers=\"t2\">10</TD>" +
"<TD headers=\"t3\">Espresso</TD>" +
"<TD headers=\"t4\">No</TD>" +
"<TR>" +
"<TD headers=\"t1\">J. Dinnen</TD>" +
"<TD headers=\"t2\">5</TD>" +
"<TD headers=\"t3\">Decaf</TD>" +
"<TD headers=\"t4\">Yes</TD>" +
"</TABLE>" ;
protected final String links =
"<p> Le 1er super lien " +
"<a title=' prout'
href=\"/jahia/Jahia/lang/en/pid/3\">888888888888888888888888888888888888888888888888888888888888888888888888888848</a>"
+
"</p>" +
"<p> Le 2ème super lien " +
"<a title=' prout' class='link'
href=\"/jahia/Jahia/lang/en/pid/2\" >c'est super </a>" +
"</p>";
protected final String form =
"<FORM action=\"...\" method=\"post\">" +
"<TABLE>" +
"<TR>" +
"<TD><LABEL for=\"fname\">First Name</LABEL>" +
"<TD><INPUT type=\"text\" name=\"firstname\"
id=\"fname\">" +
"</TR>" +
"<TR>" +
"<TD><LABEL for=\"lname\">Last Name</LABEL>" +
"<TD><INPUT type=\"text\" name=\"lastname\"
id=\"lname\">" +
"</TR>" +
"</TABLE>" +
"<INPUT type=\"submit\" value=\"Send\"> <INPUT
type=\"reset\">" +
"</FORM>";
public WAIValidatorTest(String testName) {
super(testName);
}
public static Test suite() {
return new OrderedTestSuite(WAIValidatorTest.class);
}
/**
* Test of validate method, of class
org.jahia.services.htmlparser.WAIValidator.
*/
public void testzValidate() throws Exception {
logger.info("*** testValidate ***");
final StringBuffer buff = new StringBuffer();
buff.append("<html>");
buff.append(form);
buff.append(table);
buff.append(table2);
buff.append(links);
buff.append("</html> ");
final WAIValidator waiValidator = new WAIValidator();
final EngineValidationHelper evh =
waiValidator.validate(buff.toString());
logger.info("evh: "+ evh);
assertTrue(evh == null || !evh.hasErrors());
}
/**
* Test of print method, of class
org.jahia.services.htmlparser.WAIValidator.
*/
public void testPrint() throws Exception {
logger.info("*** testPrint ***");
final File tempFile = File.createTempFile("tmp", ".html");
final StringBuffer buff = new StringBuffer();
buff.append("<html>");
buff.append(form);
buff.append(table);
buff.append(table2);
buff.append(links);
buff.append("</html> ");
try {
final FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(buff.toString().getBytes());
fos.flush();
fos.close();
final DOMFragmentParser parser = new DOMFragmentParser();
final EngineValidationHelper evh = new EngineValidationHelper();
final HTMLDocument document = new HTMLDocumentImpl();
final DocumentFragment fragment =
document.createDocumentFragment();
parser.parse(tempFile.getAbsolutePath(), fragment);
WAIValidator.print(fragment, " ", true);
assertTrue(fragment != null);
} catch (Exception e) {
throw e;
} finally {
tempFile.delete();
}
}
/**
* Test of validateTable method, of class
org.jahia.services.htmlparser.WAIValidator.
*/
public void testValidateTable() throws Exception {
logger.info("*** testValidateTable ***");
final StringBuffer buff = new StringBuffer();
buff.append("<html>");
buff.append(table);
buff.append(table2);
buff.append("</html> ");
final WAIValidator waiValidator = new WAIValidator();
final EngineValidationHelper evh =
waiValidator.validate(buff.toString());
logger.info("evh: "+ evh);
assertTrue(evh == null || !evh.hasErrors());
}
/**
* Test of validateLink method, of class
org.jahia.services.htmlparser.WAIValidator.
*/
public void testValidateLink() throws Exception {
logger.info("*** testValidateLink ***");
final StringBuffer buff = new StringBuffer();
buff.append("<html>");
buff.append(links);
buff.append("</html> ");
final WAIValidator waiValidator = new WAIValidator();
final EngineValidationHelper evh =
waiValidator.validate(buff.toString());
logger.info("evh: "+ evh);
assertTrue(evh == null || !evh.hasErrors());
}
/**
* Test of validateForm method, of class
org.jahia.services.htmlparser.WAIValidator.
*/
public void testValidateForm() throws Exception {
logger.info("*** testValidateForm ***");
final StringBuffer buff = new StringBuffer();
buff.append("<html>");
buff.append(form);
buff.append("</html> ");
final WAIValidator waiValidator = new WAIValidator();
final EngineValidationHelper evh =
waiValidator.validate(buff.toString());
logger.info("evh: "+ evh);
assertTrue(evh == null || !evh.hasErrors());
}
}