You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by sv...@apache.org on 2016/08/01 08:49:46 UTC
wicket git commit: WICKET-6220 improved support for void elements;
unified code for createTagsXXX and createTagXX
Repository: wicket
Updated Branches:
refs/heads/WICKET-6220-tag-tester-void-elements b27e6aca9 -> 069735395
WICKET-6220 improved support for void elements; unified code for createTagsXXX and createTagXX
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/06973539
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/06973539
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/06973539
Branch: refs/heads/WICKET-6220-tag-tester-void-elements
Commit: 069735395955b6a68347fae61217df05811d8a43
Parents: b27e6ac
Author: Sven Meier <sv...@apache.org>
Authored: Mon Aug 1 10:49:21 2016 +0200
Committer: Sven Meier <sv...@apache.org>
Committed: Mon Aug 1 10:49:21 2016 +0200
----------------------------------------------------------------------
.../apache/wicket/util/tester/TagTester.java | 302 +++++++------------
.../wicket/util/tester/TagTesterTest.java | 114 ++++++-
2 files changed, 214 insertions(+), 202 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/06973539/wicket-core/src/main/java/org/apache/wicket/util/tester/TagTester.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/util/tester/TagTester.java b/wicket-core/src/main/java/org/apache/wicket/util/tester/TagTester.java
index 04f8280..610b181 100644
--- a/wicket-core/src/main/java/org/apache/wicket/util/tester/TagTester.java
+++ b/wicket-core/src/main/java/org/apache/wicket/util/tester/TagTester.java
@@ -16,20 +16,22 @@
*/
package org.apache.wicket.util.tester;
+import static org.apache.wicket.markup.parser.filter.HtmlHandler.requiresCloseTag;
+
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
-import java.util.Map;
+import java.util.Stack;
+import java.util.function.Function;
import java.util.regex.Pattern;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.markup.parser.XmlPullParser;
import org.apache.wicket.markup.parser.XmlTag;
-import org.apache.wicket.markup.parser.filter.HtmlHandler;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.string.Strings;
import org.apache.wicket.util.value.IValueMap;
-
/**
* Tag tester is used to test that a generated markup tag contains the correct attributes, values
* etc. This can be done instead of comparing generated markup with some expected markup. The
@@ -359,7 +361,8 @@ public class TagTester
*/
public String getValue()
{
- if (openTag == closeTag) {
+ if (openTag == closeTag)
+ {
return null;
}
@@ -374,85 +377,33 @@ public class TagTester
* that it will return the first tag which matches the criteria.
*
* @param markup
- * the markup to look for the tag to create the <code>TagTester</code> from
- * the value which the attribute must have
+ * the markup to look for the tag to create the <code>TagTester</code> from the value
+ * which the attribute must have
* @return the <code>TagTester</code> which matches the tag by name in the markup
*/
- public static TagTester createTagByAttribute(String markup, String tagName)
+ public static TagTester createTagByName(String markup, String tagName)
{
- TagTester tester = null;
-
- if (Strings.isEmpty(markup) == false && Strings.isEmpty(tagName) == false)
+ List<TagTester> tester = createTags(markup, xmlTag -> xmlTag.getName().equalsIgnoreCase(tagName), true);
+ if ((tester == null) || (tester.size() == 0))
{
- try
- {
- // remove the CDATA and
- // the id attribute of the component because it is often the same as the element's id
- markup = AJAX_COMPONENT_CDATA_OPEN.matcher(markup).replaceAll("<component>");
- markup = AJAX_COMPONENT_CDATA_CLOSE.matcher(markup).replaceAll("</component>");
-
- XmlPullParser parser = new XmlPullParser();
- parser.parse(markup);
-
- XmlTag elm;
- XmlTag openTag = null;
- XmlTag closeTag = null;
- int level = 0;
- while ((elm = parser.nextTag()) != null && closeTag == null)
- {
- XmlTag xmlTag = elm;
-
- String xmlTagName = xmlTag.getName();
- if (openTag == null && xmlTagName.equalsIgnoreCase(tagName))
- {
- if (xmlTag.isOpen())
- {
- openTag = xmlTag;
- }
- else if (xmlTag.isOpenClose())
- {
- openTag = xmlTag;
- closeTag = xmlTag;
- }
- }
- else if (openTag != null)
- {
- String openTagName = openTag.getName();
- if (xmlTag.isOpen() && xmlTagName.equals(openTagName))
- {
- level++;
- }
-
- if (xmlTag.isClose())
- {
- if (xmlTagName.equals(openTagName))
- {
- if (level == 0)
- {
- closeTag = xmlTag;
- closeTag.setOpenTag(openTag);
- }
- else
- {
- level--;
- }
- }
- }
- }
- }
-
- if (openTag != null && closeTag != null)
- {
- tester = new TagTester(parser, openTag, closeTag);
- }
- }
- catch (Exception e)
- {
- throw new WicketRuntimeException(e);
- }
+ return null;
}
+ return tester.get(0);
+ }
- return tester;
+ /**
+ * Static factory method for creating a <code>TagTester</code> based on a tag name. Please note
+ * that it will return the first tag which matches the criteria.
+ *
+ * @param markup
+ * the markup to look for the tag to create the <code>TagTester</code> from the value
+ * which the attribute must have
+ * @return the <code>TagTester</code> which matches the tag by name in the markup
+ */
+ @Deprecated
+ public static TagTester createTagByAttribute(String markup, String tagName)
+ {
+ return createTagByName(markup, tagName);
}
/**
@@ -472,97 +423,18 @@ public class TagTester
*/
public static TagTester createTagByAttribute(String markup, String attribute, String value)
{
- TagTester tester = null;
-
- if (Strings.isEmpty(markup) == false && Strings.isEmpty(attribute) == false &&
- Strings.isEmpty(value) == false)
+ List<TagTester> tester = createTagsByAttribute(markup, attribute, value, true);
+ if ((tester == null) || (tester.size() == 0))
{
- try
- {
- // remove the CDATA and
- // the id attribute of the component because it is often the same as the element's id
- markup = AJAX_COMPONENT_CDATA_OPEN.matcher(markup).replaceAll("<component>");
- markup = AJAX_COMPONENT_CDATA_CLOSE.matcher(markup).replaceAll("</component>");
-
- XmlPullParser parser = new XmlPullParser();
- parser.parse(markup);
-
- XmlTag elm;
- XmlTag openTag = null;
- XmlTag closeTag = null;
- int level = 0;
- while ((elm = parser.nextTag()) != null && closeTag == null)
- {
- XmlTag xmlTag = elm;
-
- if (openTag == null)
- {
- IValueMap attributeMap = xmlTag.getAttributes();
-
- for (Map.Entry<String, Object> entry : attributeMap.entrySet())
- {
- String attr = entry.getKey();
- if (attr.equals(attribute) && value.equals(entry.getValue()))
- {
- if (xmlTag.isOpen())
- {
- openTag = xmlTag;
- }
- else if (xmlTag.isOpenClose())
- {
- openTag = xmlTag;
- closeTag = xmlTag;
- }
- }
- }
- }
- else
- {
- if (xmlTag.isOpen() && xmlTag.getName().equals(openTag.getName()))
- {
- level++;
- }
-
- if (xmlTag.isClose())
- {
- if (xmlTag.getName().equals(openTag.getName()))
- {
- if (level == 0)
- {
- closeTag = xmlTag;
- closeTag.setOpenTag(openTag);
- }
- else
- {
- level--;
- }
- }
- }
- }
- }
-
- if (openTag != null && closeTag != null)
- {
- tester = new TagTester(parser, openTag, closeTag);
- }
- else if (openTag != null)
- {
- tester = new TagTester(parser, openTag, openTag);
- }
- }
- catch (Exception e)
- {
- throw new WicketRuntimeException(e);
- }
+ return null;
}
-
- return tester;
+ return tester.get(0);
}
/**
* Static factory method for creating a <code>TagTester</code> based on a tag found by an
* attribute with a specific value. Please note that it will return the first tag which matches
- * the criteria. It's therefore good for attributes such as "id" or "wicket:id", but only if
+ * the criteria. It's therefore good for attributes suck as "id" or "wicket:id", but only if
* "wicket:id" is unique in the specified markup.
*
* @param markup
@@ -574,14 +446,33 @@ public class TagTester
* @return the <code>TagTester</code> which matches the tag in the markup, that has the given
* value on the given attribute
*/
+ @Deprecated
public static TagTester createTagsByAttribute(String markup, String attribute, String value)
{
- List<TagTester> tester = createTagsByAttribute(markup, attribute, value, true);
- if ((tester == null) || (tester.size() == 0))
+ return createTagByAttribute(markup, attribute, value);
+ }
+
+ /**
+ * find the correct openTag to the given closeTag and remove all unclosed openTags between both
+ * in given array {@code stack}
+ *
+ * @param closeTag
+ * tag to search for corresponding openTag
+ * @param stack
+ * array of unclosed openTags
+ * @return corresponding openTag or {@code null}
+ */
+ private static XmlTag findOpenTag(XmlTag closeTag, Stack<XmlTag> stack)
+ {
+ while (stack.size() > 0)
{
- return null;
+ XmlTag popped = stack.pop();
+ if (popped.getName().equals(closeTag.getName()))
+ {
+ return popped;
+ }
}
- return tester.get(0);
+ return null;
}
/**
@@ -601,13 +492,20 @@ public class TagTester
* @return the <code>TagTester</code> which matches the tag in the markup, that has the given
* value on the given attribute
*/
- public static List<TagTester> createTagsByAttribute(String markup, String attribute,
- String value, boolean stopAfterFirst)
+ public static List<TagTester> createTagsByAttribute(String markup, String attribute, String value, boolean stopAfterFirst)
+ {
+ if (Strings.isEmpty(attribute) || Strings.isEmpty(value)) {
+ return Collections.emptyList();
+ }
+
+ return createTags(markup, xmlTag -> value.equals(xmlTag.getAttributes().get(attribute)), stopAfterFirst);
+ }
+
+ public static List<TagTester> createTags(String markup, Function<XmlTag, Boolean> accept, boolean stopAfterFirst)
{
List<TagTester> testers = new ArrayList<>();
- if ((Strings.isEmpty(markup) == false) && (Strings.isEmpty(attribute) == false) &&
- (Strings.isEmpty(value) == false))
+ if ((Strings.isEmpty(markup) == false))
{
try
{
@@ -619,70 +517,74 @@ public class TagTester
XmlPullParser parser = new XmlPullParser();
parser.parse(markup);
- XmlTag elm;
XmlTag openTag = null;
XmlTag closeTag = null;
- int level = 0;
- while ((elm = parser.nextTag()) != null)
+
+ // temporary Tag-Hierarchy after openTag
+ Stack<XmlTag> stack = new Stack<>();
+
+ while (true)
{
- XmlTag xmlTag = elm;
+ XmlTag xmlTag = parser.nextTag();
+ if (xmlTag == null)
+ {
+ break;
+ }
+
if (openTag == null)
{
- IValueMap attributeMap = xmlTag.getAttributes();
- for (Map.Entry<String, Object> entry : attributeMap.entrySet())
+ if (accept.apply(xmlTag))
{
- if (entry.getKey().equals(attribute) && value.equals(entry.getValue()))
+ if (xmlTag.isOpen())
{
- if (xmlTag.isOpen())
- {
- openTag = xmlTag;
- }
- else if (xmlTag.isOpenClose())
- {
- openTag = xmlTag;
- closeTag = xmlTag;
- }
+ openTag = xmlTag;
+ }
+ else if (xmlTag.isOpenClose())
+ {
+ openTag = xmlTag;
+ closeTag = xmlTag;
}
}
}
else
{
- if (xmlTag.isOpen() && xmlTag.getName().equals(openTag.getName()))
+ if (xmlTag.isOpen() && !xmlTag.isOpenClose())
{
- level++;
+ stack.push(xmlTag);
}
-
if (xmlTag.isClose())
{
- if (xmlTag.getName().equals(openTag.getName()))
+ XmlTag foundTag = findOpenTag(xmlTag, stack);
+ if (foundTag == null)
{
- if (level == 0)
+ if (xmlTag.getName().equals(openTag.getName()))
{
closeTag = xmlTag;
closeTag.setOpenTag(openTag);
}
+ else if (requiresCloseTag(openTag.getName()) == false)
+ {
+ // no closeTag for current openTag (allowed)
+ closeTag = openTag;
+ }
else
{
- level--;
+ // no closeTag for current openTag (invalid structure)
+ // thus reset state
+ openTag = null;
+ closeTag = null;
}
}
}
}
- if ((openTag != null) && (closeTag != null) && (level == 0))
+ if ((openTag != null) && (closeTag != null))
{
TagTester tester = new TagTester(parser, openTag, closeTag);
testers.add(tester);
openTag = null;
closeTag = null;
}
- else if (openTag != null && !HtmlHandler.requiresCloseTag(openTag.getName()))
- {
- TagTester tester = new TagTester(parser, openTag, openTag);
- testers.add(tester);
- openTag = null;
- closeTag = null;
- }
if (stopAfterFirst && (closeTag != null))
{
@@ -698,4 +600,4 @@ public class TagTester
return testers;
}
-}
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/06973539/wicket-core/src/test/java/org/apache/wicket/util/tester/TagTesterTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/util/tester/TagTesterTest.java b/wicket-core/src/test/java/org/apache/wicket/util/tester/TagTesterTest.java
index d184869..f992310 100644
--- a/wicket-core/src/test/java/org/apache/wicket/util/tester/TagTesterTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/util/tester/TagTesterTest.java
@@ -342,7 +342,117 @@ public class TagTesterTest extends Assert
@Test
public void valueFromTagsByAttribute()
{
- TagTester tagTester = TagTester.createTagsByAttribute(MARKUP_1, "id", "test2");
+ TagTester tagTester = TagTester.createTagByAttribute(MARKUP_1, "id", "test2");
assertEquals("mock", tagTester.getValue());
}
-}
+
+ private static final String MARKUP =
+ "<wicket:panel>" +
+ "<ul wicket:id=\"container\">" +
+ "<wicket:container wicket:id=\"items\">" +
+ "<li wicket:id=\"item\" id=\"item1\">" +
+ "<p wicket:id=\"p\" id=\"p1\">" +
+ "<img wicket:id=\"img\" src=\"bild1.jpg\">" +
+ "</p>" +
+ "<hr wicket:id=\"hr\" id=\"hr1\"/>" +
+ "</li>" +
+ "<li wicket:id=\"item\" id=\"item2\">" +
+ "<p wicket:id=\"p\" id=\"p2\">" +
+ "<img wicket:id=\"img\" src=\"bild2.jpg\">" +
+ "<hr wicket:id=\"hr\" id=\"hr2\"/>" +
+ "</li>" +
+ "</wicket:container>" +
+ "</ul>" +
+ "</wicket:panel>";
+
+ private static final String WRONG_MARKUP =
+ "<wicket:panel>" +
+ "<ul wicket:id=\"container\">" +
+ "<wicket:container wicket:id=\"items\">" +
+ "<li wicket:id=\"item\" id=\"item1\">" +
+ "<span wicket:id=\"p\" id=\"p1\">" +
+ "<img wicket:id=\"img\" src=\"bild1.jpg\">" +
+ "<hr wicket:id=\"hr\" id=\"hr1\"/>" +
+ "</li>" +
+ "<li wicket:id=\"item\" id=\"item2\">" +
+ "<span wicket:id=\"p\" id=\"p2\">" +
+ "<img wicket:id=\"img\" src=\"bild2.jpg\">" +
+ "<hr wicket:id=\"hr\" id=\"hr2\"/>" +
+ "</span>" +
+ "</li>" +
+ "</wicket:container>" +
+ "</ul>" +
+ "</wicket:panel>";
+
+ /**
+ * WICKET-6220
+ */
+ @Test
+ public void testOpenAndClose() {
+ List<TagTester> tags = TagTester.createTagsByAttribute(MARKUP, "wicket:id", "item", false);
+ assertEquals(2, tags.size());
+ assertEquals("li", tags.get(0).getName());
+ assertEquals("item1", tags.get(0).getAttribute("id"));
+ assertEquals("<p wicket:id=\"p\" id=\"p1\"><img wicket:id=\"img\" src=\"bild1.jpg\"></p><hr wicket:id=\"hr\" id=\"hr1\"/>", tags.get(0).getValue());
+ assertEquals("li", tags.get(1).getName());
+ assertEquals("item2", tags.get(1).getAttribute("id"));
+ assertEquals("<p wicket:id=\"p\" id=\"p2\"><img wicket:id=\"img\" src=\"bild2.jpg\"><hr wicket:id=\"hr\" id=\"hr2\"/>", tags.get(1).getValue());
+ }
+
+ /**
+ * WICKET-6220
+ */
+ @Test
+ public void testWrongHtmlStructure() {
+ List<TagTester> tags = TagTester.createTagsByAttribute(WRONG_MARKUP, "wicket:id", "p", false);
+ assertEquals(1, tags.size());
+ assertEquals("span", tags.get(0).getName());
+ assertEquals("p2", tags.get(0).getAttribute("id"));
+ assertEquals("<img wicket:id=\"img\" src=\"bild2.jpg\"><hr wicket:id=\"hr\" id=\"hr2\"/>", tags.get(0).getValue());
+ }
+
+ /**
+ * WICKET-6220
+ */
+ @Test
+ public void testOpenOrClose() {
+ List<TagTester> tags = TagTester.createTagsByAttribute(MARKUP, "wicket:id", "p", false);
+ assertEquals(2, tags.size());
+ assertEquals("p", tags.get(0).getName());
+ assertEquals("p1", tags.get(0).getAttribute("id"));
+ assertEquals("<img wicket:id=\"img\" src=\"bild1.jpg\">", tags.get(0).getValue());
+ assertEquals("p", tags.get(1).getName());
+ assertEquals("p2", tags.get(1).getAttribute("id"));
+ assertEquals("<p wicket:id=\"p\" id=\"p2\">", tags.get(1).getMarkup());
+ }
+
+ /**
+ * WICKET-6220
+ */
+ @Test
+ public void testOpen() {
+ List<TagTester> tags = TagTester.createTagsByAttribute(MARKUP, "wicket:id", "img", false);
+ assertEquals(2, tags.size());
+ assertEquals("img", tags.get(0).getName());
+ assertEquals("bild1.jpg", tags.get(0).getAttribute("src"));
+ assertEquals("<img wicket:id=\"img\" src=\"bild1.jpg\">", tags.get(0).getMarkup());
+ assertEquals("img", tags.get(1).getName());
+ assertEquals("bild2.jpg", tags.get(1).getAttribute("src"));
+ assertEquals("<img wicket:id=\"img\" src=\"bild2.jpg\">", tags.get(1).getMarkup());
+ }
+
+ /**
+ * WICKET-6220
+ */
+ @Test
+ public void testOpenClose() {
+ List<TagTester> tags = TagTester.createTagsByAttribute(MARKUP, "wicket:id", "hr", false);
+ assertEquals(2, tags.size());
+ assertEquals("hr", tags.get(0).getName());
+ assertEquals("hr1", tags.get(0).getAttribute("id"));
+ assertEquals("<hr wicket:id=\"hr\" id=\"hr1\"/>", tags.get(0).getMarkup());
+ assertEquals("hr", tags.get(1).getName());
+ assertEquals("hr2", tags.get(1).getAttribute("id"));
+ assertEquals("<hr wicket:id=\"hr\" id=\"hr2\"/>", tags.get(1).getMarkup());
+ }
+}
\ No newline at end of file