/*
* Sonar Web Plugin
* Copyright (C) 2010 Matthijs Galesloot
* dev@sonar.codehaus.org
*
* 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.sonar.plugins.web.lex;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertNull;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.sonar.channel.CodeReader;
import org.sonar.plugins.web.node.DirectiveNode;
import org.sonar.plugins.web.node.Node;
import org.sonar.plugins.web.node.TagNode;
import org.sonar.plugins.web.node.TextNode;
/**
* @author Matthijs Galesloot
*/
public class PageLexerTest {
@Test
public void testLexer() throws FileNotFoundException {
String fileName = "src/test/resources/src/main/webapp/create-salesorder.xhtml";
PageLexer lexer = new PageLexer();
List<Node> nodeList = lexer.parse(new FileReader(fileName));
assertTrue(nodeList.size() > 50);
// check tagnodes
for (Node node : nodeList) {
if (node instanceof TagNode) {
assertTrue(node.getCode().startsWith("<"));
assertTrue(node.getCode().endsWith(">"));
}
}
showHierarchy(nodeList);
// check hierarchy
for (Node node : nodeList) {
if (node instanceof TagNode) {
TagNode tagNode = (TagNode) node;
if ( !tagNode.isEndElement()) {
if (tagNode.equalsElementName("define")) {
assertTrue("Tag should have children: " + tagNode.getCode(), tagNode.getChildren().size() > 0);
} else if (tagNode.equalsElementName("outputText")) {
assertTrue("Tag should not have children: " + tagNode.getCode(), tagNode.getChildren().size() == 0);
}
}
}
}
}
@Test
public void testRuby() throws FileNotFoundException {
String fileName = "src/test/resources/src/main/webapp/select_user.html.erb";
PageLexer lexer = new PageLexer();
List<Node> nodeList = lexer.parse(new FileReader(fileName));
assertTrue(nodeList.size() > 50);
// TODO - better parsing of erb.
}
private void showHierarchy(List<Node> nodeList) {
StringBuilder sb = new StringBuilder();
for (Node node : nodeList) {
if (node.getClass() == TagNode.class && ((TagNode) node).getParent() == null) {
TagNode root = (TagNode) node;
printTag(sb, root, 0);
// System.out.print(sb.toString());
}
}
}
private void printTag(StringBuilder sb, TagNode node, int indent) {
sb.append('\n');
for (int i = 0; i < indent; i++) {
sb.append(" ");
}
sb.append('<');
sb.append(node.getNodeName());
if (node.getChildren().size() > 0) {
sb.append('>');
for (TagNode child : node.getChildren()) {
printTag(sb, child, indent + 1);
}
sb.append('\n');
for (int i = 0; i < indent; i++) {
sb.append(" ");
}
sb.append("</");
sb.append(node.getNodeName());
sb.append('>');
} else {
sb.append("/>");
}
}
@Test
public void testDirectiveNode() {
String directive = "<!DOCTYPE html "
+ "PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";
DoctypeTokenizer tokenizer = new DoctypeTokenizer("<!DOCTYPE", ">");
List<Node> nodeList = new ArrayList<Node>();
CodeReader codeReader = new CodeReader(directive);
tokenizer.consume(codeReader, nodeList);
assertEquals(nodeList.size(), 1);
Node node = nodeList.get(0);
assertEquals(node.getClass(), DirectiveNode.class);
DirectiveNode directiveNode = (DirectiveNode) node;
assertEquals(4, directiveNode.getAttributes().size());
}
@Test
public void testNestedTagInAttribute() {
String fragment = "<td id=\"typeCellHeader\"<c:if test='${param.typeNormalOrError == \"error\"}'>"
+ "style=\"display:none;\"</c:if>>Type" + "</td>";
StringReader reader = new StringReader(fragment);
PageLexer lexer = new PageLexer();
List<Node> nodeList = lexer.parse(reader);
assertEquals(3, nodeList.size());
assertTrue(nodeList.get(0) instanceof TagNode);
assertTrue(nodeList.get(1) instanceof TextNode);
assertTrue(nodeList.get(2) instanceof TagNode);
TagNode tagNode = (TagNode) nodeList.get(0);
assertEquals(4, tagNode.getAttributes().size());
// the embedded tags are added as attributes
assertNull(tagNode.getAttributes().get(1).getValue());
assertNull(tagNode.getAttributes().get(3).getValue());
}
@Test
public void testNestedScriptlet() {
String fragment = "<option value=\"<%= key -%>\" <%= 'selected' if alert.operator==key -%>>";
StringReader reader = new StringReader(fragment);
PageLexer lexer = new PageLexer();
List<Node> nodeList = lexer.parse(reader);
assertEquals(1, nodeList.size());
TagNode tagNode = (TagNode) nodeList.get(0);
assertEquals(2, tagNode.getAttributes().size());
// the embedded tags are added as attributes
assertEquals(tagNode.getAttributes().get(0).getName(), "value");
assertEquals(tagNode.getAttributes().get(0).getValue(), "<%= key -%>");
assertEquals(tagNode.getAttributes().get(1).getName(), "<%= 'selected' if alert.operator==key -%>");
assertNull(tagNode.getAttributes().get(1).getValue());
}
@Test
public void testNestedTagInValue() {
String fragment = "<td label=\"Hello <c:if test='${param == true}'>World</c:if>\">Type</td>";
StringReader reader = new StringReader(fragment);
PageLexer lexer = new PageLexer();
List<Node> nodeList = lexer.parse(reader);
assertEquals(3, nodeList.size());
assertTrue(nodeList.get(0) instanceof TagNode);
assertTrue(nodeList.get(1) instanceof TextNode);
assertTrue(nodeList.get(2) instanceof TagNode);
TagNode tagNode = (TagNode) nodeList.get(0);
assertEquals(1, tagNode.getAttributes().size());
}
@Test
public void nestedQuotes() {
String fragment = "<tr class=\"<c:if test='${count%2==0}'>even</c:if>"
+ "<c:if test='${count%2!=0}'>odd</c:if><c:if test='${ActionType==\"baseline\"}'> baseline</c:if>\">";
StringReader reader = new StringReader(fragment);
PageLexer lexer = new PageLexer();
List<Node> nodeList = lexer.parse(reader);
assertEquals(1, nodeList.size());
TagNode tagNode = (TagNode) nodeList.get(0);
assertEquals(1, tagNode.getAttributes().size());
}
@Test
public void escapeCharacters() {
String fragment = "<c:when test=\"${citaflagurge eq \\\"S\\\"}\">";
StringReader reader = new StringReader(fragment);
PageLexer lexer = new PageLexer();
List<Node> nodeList = lexer.parse(reader);
assertEquals(1, nodeList.size());
TagNode tagNode = (TagNode) nodeList.get(0);
assertEquals(1, tagNode.getAttributes().size());
}
@Test
public void javaScriptWithNestedTags() throws FileNotFoundException {
String fileName = "src/test/resources/lexer/javascript-nestedtags.jsp";
PageLexer lexer = new PageLexer();
List<Node> nodeList = lexer.parse(new FileReader(fileName));
assertEquals(12, nodeList.size());
// check script node
Node node = nodeList.get(2);
assertTrue(node instanceof TagNode);
TagNode scriptNode = (TagNode) node;
assertEquals("script", scriptNode.getNodeName());
assertEquals(0, scriptNode.getChildren().size());
}
@Test
public void javaScriptWithComments() throws FileNotFoundException {
String fileName = "src/test/resources/lexer/script-with-comments.jsp";
PageLexer lexer = new PageLexer();
List<Node> nodeList = lexer.parse(new FileReader(fileName));
assertEquals(3, nodeList.size());
}
}