Selaa lähdekoodia

Support HTML entities when reading/writing declarative format #18882

Change-Id: I08099673c5dd0d688d3243e5fd169edb05f046f3
tags/7.6.0.alpha7
Maciej Przepióra 8 vuotta sitten
vanhempi
commit
5c875228d9

+ 6
- 4
server/src/com/vaadin/ui/AbstractSelect.java Näytä tiedosto

@@ -55,6 +55,7 @@ import com.vaadin.shared.ui.dd.VerticalDropLocation;
import com.vaadin.ui.declarative.DesignAttributeHandler;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.DesignException;
import com.vaadin.ui.declarative.DesignFormatter;

/**
* <p>
@@ -2232,12 +2233,13 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
}

String itemId;
String caption = DesignFormatter.unencodeFromTextNode(child.html());
if (child.hasAttr("item-id")) {
itemId = child.attr("item-id");
addItem(itemId);
setItemCaption(itemId, child.html());
setItemCaption(itemId, caption);
} else {
addItem(itemId = child.html());
addItem(itemId = caption);
}

if (child.hasAttr("icon")) {
@@ -2300,10 +2302,10 @@ public abstract class AbstractSelect extends AbstractField<Object> implements

String caption = getItemCaption(itemId);
if (caption != null && !caption.equals(itemId.toString())) {
element.html(caption);
element.html(DesignFormatter.encodeForTextNode(caption));
element.attr("item-id", itemId.toString());
} else {
element.html(itemId.toString());
element.html(DesignFormatter.encodeForTextNode(itemId.toString()));
}

Resource icon = getItemIcon(itemId);

+ 13
- 3
server/src/com/vaadin/ui/Button.java Näytä tiedosto

@@ -22,9 +22,9 @@ import java.util.Collection;

import org.jsoup.nodes.Attributes;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Parser;

import com.vaadin.event.Action;
import com.vaadin.event.FieldEvents.FocusAndBlurServerRpcImpl;
import com.vaadin.event.ShortcutAction;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.event.ShortcutAction.ModifierKey;
@@ -35,6 +35,7 @@ import com.vaadin.shared.ui.button.ButtonServerRpc;
import com.vaadin.shared.ui.button.ButtonState;
import com.vaadin.ui.declarative.DesignAttributeHandler;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.DesignFormatter;
import com.vaadin.util.ReflectTools;

/**
@@ -573,14 +574,19 @@ public class Button extends AbstractFocusable implements
public void readDesign(Element design, DesignContext designContext) {
super.readDesign(design, designContext);
Attributes attr = design.attributes();
String content = design.html();
setCaption(content);
String content;
// plain-text (default is html)
Boolean plain = DesignAttributeHandler.readAttribute(
DESIGN_ATTR_PLAIN_TEXT, attr, Boolean.class);
if (plain == null || !plain) {
setHtmlContentAllowed(true);
content = design.html();
} else {
// content is not intended to be interpreted as HTML,
// so html entities need to be decoded
content = DesignFormatter.unencodeFromTextNode(design.html());
}
setCaption(content);
if (attr.hasKey("icon-alt")) {
setIconAlternateText(DesignAttributeHandler.readAttribute(
"icon-alt", attr, String.class));
@@ -630,6 +636,10 @@ public class Button extends AbstractFocusable implements
// plain-text (default is html)
if (!isHtmlContentAllowed()) {
design.attr(DESIGN_ATTR_PLAIN_TEXT, "");
// encode HTML entities
if (content != null) {
design.html(DesignFormatter.encodeForTextNode(content));
}
}
// icon-alt
DesignAttributeHandler.writeAttribute("icon-alt", attr,

+ 7
- 3
server/src/com/vaadin/ui/Grid.java Näytä tiedosto

@@ -108,6 +108,7 @@ import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.declarative.DesignAttributeHandler;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.DesignException;
import com.vaadin.ui.declarative.DesignFormatter;
import com.vaadin.ui.renderers.HtmlRenderer;
import com.vaadin.ui.renderers.Renderer;
import com.vaadin.ui.renderers.TextRenderer;
@@ -2273,7 +2274,9 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
setHtml(cellElement.html());
}
} else {
setText(cellElement.html());
// text – need to unescape HTML entities
setText(DesignFormatter.unencodeFromTextNode(cellElement
.html()));
}
}
}
@@ -4981,7 +4984,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
/*
* This method is a workaround for the fact that Vaadin re-applies
* widget dimensions (height/width) on each state change event. The
* original design was to have setHeight an setHeightByRow be equals,
* original design was to have setHeight and setHeightByRow be equals,
* and whichever was called the latest was considered in effect.
*
* But, because of Vaadin always calling setHeight on the widget, this
@@ -6752,7 +6755,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
Object value = datasource.getItem(itemId)
.getItemProperty(c.getPropertyId()).getValue();
tableRow.appendElement("td").append(
(value != null ? value.toString() : ""));
(value != null ? DesignFormatter
.encodeForTextNode(value.toString()) : ""));
}
}
}

+ 10
- 4
server/src/com/vaadin/ui/Label.java Näytä tiedosto

@@ -31,6 +31,7 @@ import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.shared.ui.label.LabelState;
import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.DesignFormatter;

/**
* Label component for showing non-editable short texts.
@@ -585,14 +586,18 @@ public class Label extends AbstractComponent implements Property<String>,
public void readDesign(Element design, DesignContext designContext) {
super.readDesign(design, designContext);
String innerHtml = design.html();
if (innerHtml != null && !"".equals(innerHtml)) {
setValue(innerHtml);
}
if (design.hasAttr(DESIGN_ATTR_PLAIN_TEXT)) {
boolean plainText = design.hasAttr(DESIGN_ATTR_PLAIN_TEXT);
if (plainText) {
setContentMode(ContentMode.TEXT);
} else {
setContentMode(ContentMode.HTML);
}
if (innerHtml != null && !"".equals(innerHtml)) {
if (plainText) {
innerHtml = DesignFormatter.unencodeFromTextNode(innerHtml);
}
setValue(innerHtml);
}
}

/*
@@ -625,6 +630,7 @@ public class Label extends AbstractComponent implements Property<String>,
// plain-text (default is html)
if (getContentMode() == ContentMode.TEXT) {
design.attr(DESIGN_ATTR_PLAIN_TEXT, "");
design.html(DesignFormatter.encodeForTextNode(getValue()));
}
}
}

+ 9
- 0
server/src/com/vaadin/ui/OptionGroup.java Näytä tiedosto

@@ -33,6 +33,7 @@ import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
import com.vaadin.shared.ui.optiongroup.OptionGroupConstants;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.DesignFormatter;

/**
* Configures select to be used as an option group.
@@ -276,6 +277,14 @@ public class OptionGroup extends AbstractSelect implements
if (!isItemEnabled(itemId)) {
elem.attr("disabled", "");
}
if (isHtmlContentAllowed()) {
// need to unencode HTML entities. AbstractSelect.writeDesign can't
// check if HTML content is allowed, so it always encodes entities
// like '>', '<' and '&'; in case HTML content is allowed this is
// undesirable so we need to unencode entities. Entities other than
// '<' and '>' will be taken care by Jsoup.
elem.html(DesignFormatter.unencodeFromTextNode(elem.html()));
}

return elem;
}

+ 8
- 4
server/src/com/vaadin/ui/Table.java Näytä tiedosto

@@ -69,6 +69,7 @@ import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.declarative.DesignAttributeHandler;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.DesignException;
import com.vaadin.ui.declarative.DesignFormatter;
import com.vaadin.util.ReflectTools;

/**
@@ -279,7 +280,7 @@ public class Table extends AbstractSelect implements Action.Container,
ICON_ONLY(ItemCaptionMode.ICON_ONLY),
/**
* Row caption mode: Item captions are read from property specified with
* {@link #setItemCaptionPropertyId(Object)}.
* {@link #setItemCaptionPropertyId(Object)} .
*/
PROPERTY(ItemCaptionMode.PROPERTY);

@@ -2055,7 +2056,9 @@ public class Table extends AbstractSelect implements Action.Container,
} else if (minPageBufferIndex < pageBufferFirstIndex) {
newCachedRowCount -= pageBufferFirstIndex - minPageBufferIndex;
}
/* calculate the internal location of the new rows within the new cache */
/*
* calculate the internal location of the new rows within the new cache
*/
int firstIndexInNewPageBuffer = firstIndex - pageBufferFirstIndex
- rowsFromBeginning;

@@ -6199,7 +6202,8 @@ public class Table extends AbstractSelect implements Action.Container,
}
Iterator<?> propertyIt = propertyIds.iterator();
for (Element e : elems) {
String columnValue = e.html();
String columnValue = DesignFormatter.unencodeFromTextNode(e
.html());
Object propertyId = propertyIt.next();
if (header) {
setColumnHeader(propertyId, columnValue);
@@ -6240,7 +6244,7 @@ public class Table extends AbstractSelect implements Action.Container,
}
Object[] data = new String[cells.size()];
for (int c = 0; c < cells.size(); ++c) {
data[c] = cells.get(c).html();
data[c] = DesignFormatter.unencodeFromTextNode(cells.get(c).html());
}

Object itemId = addItem(data,

+ 3
- 2
server/src/com/vaadin/ui/TextArea.java Näytä tiedosto

@@ -21,6 +21,7 @@ import org.jsoup.nodes.Element;
import com.vaadin.data.Property;
import com.vaadin.shared.ui.textarea.TextAreaState;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.DesignFormatter;

/**
* A text field that supports multi line editing.
@@ -145,7 +146,7 @@ public class TextArea extends AbstractTextField {
@Override
public void readDesign(Element design, DesignContext designContext) {
super.readDesign(design, designContext);
setValue(design.html());
setValue(DesignFormatter.unencodeFromTextNode(design.html()));
}

/*
@@ -157,7 +158,7 @@ public class TextArea extends AbstractTextField {
@Override
public void writeDesign(Element design, DesignContext designContext) {
super.writeDesign(design, designContext);
design.html(getValue());
design.html(DesignFormatter.encodeForTextNode(getValue()));
}

@Override

+ 51
- 0
server/src/com/vaadin/ui/declarative/DesignFormatter.java Näytä tiedosto

@@ -28,12 +28,15 @@ import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;

import org.jsoup.parser.Parser;

import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.converter.StringToBigDecimalConverter;
import com.vaadin.data.util.converter.StringToDoubleConverter;
import com.vaadin.data.util.converter.StringToFloatConverter;
import com.vaadin.event.ShortcutAction;
import com.vaadin.server.Resource;
import com.vaadin.ui.AbstractSelect;
import com.vaadin.ui.declarative.converters.DesignDateConverter;
import com.vaadin.ui.declarative.converters.DesignEnumConverter;
import com.vaadin.ui.declarative.converters.DesignObjectConverter;
@@ -360,4 +363,52 @@ public class DesignFormatter implements Serializable {
return findConverterFor(sourceType, false);
}

/**
* <p>
* Encodes <em>some</em> special characters in a given input String to make
* it ready to be written as contents of a text node. WARNING: this will
* e.g. encode "&lt;someTag&gt;" to "&amp;lt;someTag&amp;gt;" as this method
* doesn't do any parsing and assumes that there are no intended HTML
* elements in the input. Only some entities are actually encoded:
* &amp;,&lt;, &gt; It's assumed that other entities are taken care of by
* Jsoup.
* </p>
* <p>
* Typically, this method will be used by components to encode data (like
* option items in {@link AbstractSelect}) when dumping to HTML format
* </p>
*
* @since
* @param input
* String to be encoded
* @return String with &amp;,&lt; and &gt; replaced with their HTML entities
*/
public static String encodeForTextNode(String input) {
if (input == null) {
return null;
}
return input.replace("&", "&amp;").replace(">", "&gt;")
.replace("<", "&lt;");
}

/**
* <p>
* Decodes HTML entities in a text from text node and replaces them with
* actual characters.
* </p>
*
* <p>
* Typically this method will be used by components to read back data (like
* option items in {@link AbstractSelect}) from HTML. Note that this method
* unencodes more characters than {@link #encodeForTextNode(String)} encodes
* </p>
*
* @since
* @param input
* @return
*/
public static String unencodeFromTextNode(String input) {
return Parser.unescapeEntities(input, false);
}

}

+ 13
- 6
server/tests/src/com/vaadin/tests/design/DeclarativeTestBaseBase.java Näytä tiedosto

@@ -36,6 +36,18 @@ import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.ShouldWriteDataDelegate;

public abstract class DeclarativeTestBaseBase<T extends Component> {
private static final class AlwaysWriteDelegate implements
ShouldWriteDataDelegate {
private static final long serialVersionUID = -6345914431997793599L;

@Override
public boolean shouldWriteData(Component component) {
return true;
}
}

public static final ShouldWriteDataDelegate ALWAYS_WRITE_DATA = new AlwaysWriteDelegate();

public interface EqualsAsserter<TT> {
public void assertObjectEquals(TT o1, TT o2);
}
@@ -55,12 +67,7 @@ public abstract class DeclarativeTestBaseBase<T extends Component> {

DesignContext dc = new DesignContext();
if (writeData) {
dc.setShouldWriteDataDelegate(new ShouldWriteDataDelegate() {
@Override
public boolean shouldWriteData(Component component) {
return true;
}
});
dc.setShouldWriteDataDelegate(DeclarativeTestBaseBase.ALWAYS_WRITE_DATA);
}
dc.setRootComponent(object);
Design.write(dc, outputStream);

+ 22
- 0
server/tests/src/com/vaadin/tests/server/component/abstractselect/AbstractSelectDeclarativeTest.java Näytä tiedosto

@@ -26,6 +26,7 @@ import com.vaadin.data.util.IndexedContainer;
import com.vaadin.server.ExternalResource;
import com.vaadin.server.Resource;
import com.vaadin.tests.design.DeclarativeTestBase;
import com.vaadin.tests.design.DeclarativeTestBaseBase;
import com.vaadin.ui.AbstractSelect;
import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
import com.vaadin.ui.ComboBox;
@@ -257,6 +258,27 @@ public class AbstractSelectDeclarativeTest extends
|| "true".equals(e.attr("multi-select")));
}

@Test
public void testHtmlEntities() {
String design = "<v-combo-box>"
+ " <option item-id=\"one\">&gt; One</option>"
+ " <option>&gt; Two</option>" + "</v-combo-box>";
AbstractSelect read = read(design);

Assert.assertEquals("> One", read.getItemCaption("one"));

AbstractSelect underTest = new ComboBox();
underTest.addItem("> One");

Element root = new Element(Tag.valueOf("v-combo-box"), "");
DesignContext dc = new DesignContext();
dc.setShouldWriteDataDelegate(DeclarativeTestBaseBase.ALWAYS_WRITE_DATA);
underTest.writeDesign(root, dc);

Assert.assertEquals("&gt; One", root.getElementsByTag("option").first()
.html());
}

public ComboBox createSingleSelectWithOnlyAttributes() {
ComboBox cb = new ComboBox();
Container dataSource = new IndexedContainer();

+ 3
- 3
server/tests/src/com/vaadin/tests/server/component/abstractselect/OptionGroupDeclarativeTests.java Näytä tiedosto

@@ -128,13 +128,13 @@ public class OptionGroupDeclarativeTests extends
og.addItems("foo", "bar", "baz", "bang");

og.setItemCaption("foo", "<b>True</b>");
og.setItemCaption("bar", "<font color='red'>False</font>");
og.setItemCaption("bar", "<font color=\"red\">False</font>");

//@formatter:off
String expected =
"<v-option-group>"
+ "<option item-id=\"foo\"><b>True</b></option>"
+ "<option item-id=\"bar\"><font color='red'>False</font></option>"
+ "<option item-id=\"foo\">&lt;b&gt;True&lt;/b&gt;</option>"
+ "<option item-id=\"bar\">&lt;font color=\"red\"&gt;False&lt;/font&gt;</option>"
+ "<option>baz</option>"
+ "<option>bang</option>"
+ "</v-option-group>";

+ 39
- 0
server/tests/src/com/vaadin/tests/server/component/button/ButtonDeclarativeTest.java Näytä tiedosto

@@ -15,6 +15,9 @@
*/
package com.vaadin.tests.server.component.button;

import org.jsoup.nodes.Element;
import org.jsoup.parser.Tag;
import org.junit.Assert;
import org.junit.Test;

import com.vaadin.event.ShortcutAction.KeyCode;
@@ -22,6 +25,7 @@ import com.vaadin.event.ShortcutAction.ModifierKey;
import com.vaadin.tests.design.DeclarativeTestBase;
import com.vaadin.ui.Button;
import com.vaadin.ui.NativeButton;
import com.vaadin.ui.declarative.DesignContext;

/**
* Tests declarative support for implementations of {@link Button} and
@@ -71,6 +75,41 @@ public class ButtonDeclarativeTest extends DeclarativeTestBase<Button> {
testButtonAndNativeButton(design, true, "", expectedWritten);
}

@Test
public void testHtmlEntitiesInCaption() {
String designPlainText = "<v-button plain-text=\"true\">&gt; One</v-button>";
String expectedCaptionPlainText = "> One";

Button read = read(designPlainText);
Assert.assertEquals(expectedCaptionPlainText, read.getCaption());

designPlainText = designPlainText
.replace("v-button", "v-native-button");
Button nativeButton = read(designPlainText);
Assert.assertEquals(expectedCaptionPlainText, nativeButton.getCaption());

String designHtml = "<v-button>&gt; One</v-button>";
String expectedCaptionHtml = "&gt; One";
read = read(designHtml);
Assert.assertEquals(expectedCaptionHtml, read.getCaption());

designHtml = designHtml.replace("v-button", "v-native-button");
nativeButton = read(designHtml);
Assert.assertEquals(expectedCaptionHtml, nativeButton.getCaption());

read = new Button("&amp; Test");
read.setHtmlContentAllowed(true);
Element root = new Element(Tag.valueOf("v-button"), "");
read.writeDesign(root, new DesignContext());
assertEquals("&amp; Test", root.html());

read.setHtmlContentAllowed(false);
root = new Element(Tag.valueOf("v-button"), "");
read.writeDesign(root, new DesignContext());
assertEquals("&amp;amp; Test", root.html());

}

public void testButtonAndNativeButton(String design, boolean html,
String caption) {
testButtonAndNativeButton(design, html, caption, design);

+ 134
- 47
server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridHeaderFooterDeclarativeTest.java Näytä tiedosto

@@ -15,6 +15,9 @@
*/
package com.vaadin.tests.server.component.grid.declarative;

import org.jsoup.nodes.Element;
import org.jsoup.parser.Tag;
import org.junit.Assert;
import org.junit.Test;

import com.vaadin.shared.ui.label.ContentMode;
@@ -23,21 +26,27 @@ import com.vaadin.ui.Grid.Column;
import com.vaadin.ui.Grid.FooterRow;
import com.vaadin.ui.Grid.HeaderRow;
import com.vaadin.ui.Label;
import com.vaadin.ui.declarative.DesignContext;

public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase {

@Test
public void testSingleDefaultHeader() {
String design = "<v-grid><table>"//
//@formatter:off
String design = "<v-grid><table>"
+ "<colgroup>"
+ " <col sortable='' property-id='Column1'>"
+ " <col sortable='' property-id='Column2'>"
+ " <col sortable='' property-id='Column3'>"
+ "</colgroup>" //
+ "<thead>" //
+ " <tr default=''><th plain-text=''>Column1<th plain-text=''>Column2<th plain-text=''>Column3</tr>" //
+ "</thead>" //
+ "</colgroup>"
+ "<thead>"
+ " <tr default=''>"
+ " <th plain-text=''>Column1</th>"
+ " <th plain-text=''>Column2</th>"
+ " <th plain-text=''>Column3</tr>"
+ "</thead>"
+ "</table></v-grid>";
//@formatter:on
Grid grid = new Grid();
grid.addColumn("Column1", String.class);
grid.addColumn("Column2", String.class);
@@ -49,15 +58,18 @@ public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase {

@Test
public void testSingleDefaultHTMLHeader() {
String design = "<v-grid><table>"//
//@formatter:off
String design = "<v-grid><table>"
+ "<colgroup>"
+ " <col sortable='' property-id='Column1'>"
+ " <col sortable='' property-id='Column2'>"
+ " <col sortable='' property-id='Column3'>" + "</colgroup>" //
+ "<thead>" //
+ " <tr default=''><th>Column1<th>Column2<th>Column3</tr>" //
+ "</thead>" //
+ " <col sortable='' property-id='Column3'>"
+ "</colgroup>"
+ "<thead>"
+ " <tr default=''><th>Column1<th>Column2<th>Column3</tr>"
+ "</thead>"
+ "</table></v-grid>";
//@formatter:on
Grid grid = new Grid();
grid.addColumn("Column1", String.class);
grid.addColumn("Column2", String.class);
@@ -74,13 +86,14 @@ public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase {

@Test
public void testNoHeaderRows() {
String design = "<v-grid><table>"//
//@formatter:off
String design = "<v-grid><table>"
+ "<colgroup>"
+ " <col sortable='' property-id='Column1'>"
+ "</colgroup>" //
+ "<thead />" //
+ "</colgroup>"
+ "<thead />"
+ "</table></v-grid>";
//@formatter:on
Grid grid = new Grid();
grid.addColumn("Column1", String.class);
grid.removeHeaderRow(grid.getDefaultHeaderRow());
@@ -91,18 +104,20 @@ public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase {

@Test
public void testMultipleHeadersWithColSpans() {
String design = "<v-grid><table>"//
//@formatter:off
String design = "<v-grid><table>"
+ "<colgroup>"
+ " <col sortable='' property-id='Column1'>"
+ " <col sortable='' property-id='Column2'>"
+ " <col sortable='' property-id='Column3'>"
+ "</colgroup>" //
+ "<thead>" //
+ "</colgroup>"
+ "<thead>"
+ " <tr><th colspan=3>Baz</tr>"
+ " <tr default=''><th>Column1<th>Column2<th>Column3</tr>" //
+ " <tr><th>Foo<th colspan=2>Bar</tr>" //
+ "</thead>" //
+ " <tr default=''><th>Column1<th>Column2<th>Column3</tr>"
+ " <tr><th>Foo<th colspan=2>Bar</tr>"
+ "</thead>"
+ "</table></v-grid>";
//@formatter:on
Grid grid = new Grid();
grid.addColumn("Column1", String.class);
grid.addColumn("Column2", String.class);
@@ -125,17 +140,19 @@ public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase {

@Test
public void testSingleDefaultFooter() {
String design = "<v-grid><table>"//
//@formatter:off
String design = "<v-grid><table>"
+ "<colgroup>"
+ " <col sortable='' property-id='Column1'>"
+ " <col sortable='' property-id='Column2'>"
+ " <col sortable='' property-id='Column3'>"
+ "</colgroup>" //
+ "</colgroup>"
+ "<thead />" // No headers read or written
+ "<tfoot>" //
+ " <tr><td plain-text=''>Column1<td plain-text=''>Column2<td plain-text=''>Column3</tr>" //
+ "</tfoot>" //
+ "<tfoot>"
+ " <tr><td plain-text=''>Column1<td plain-text=''>Column2<td plain-text=''>Column3</tr>"
+ "</tfoot>"
+ "</table></v-grid>";
//@formatter:on
Grid grid = new Grid();
grid.addColumn("Column1", String.class);
grid.addColumn("Column2", String.class);
@@ -154,16 +171,19 @@ public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase {

@Test
public void testSingleDefaultHTMLFooter() {
String design = "<v-grid><table>"//
//@formatter:off
String design = "<v-grid><table>"
+ "<colgroup>"
+ " <col sortable='' property-id='Column1'>"
+ " <col sortable='' property-id='Column2'>"
+ " <col sortable='' property-id='Column3'>" + "</colgroup>" //
+ " <col sortable='' property-id='Column3'>"
+ "</colgroup>"
+ "<thead />" // No headers read or written
+ "<tfoot>" //
+ " <tr><td>Column1<td>Column2<td>Column3</tr>" //
+ "</tfoot>" //
+ "<tfoot>"
+ " <tr><td>Column1<td>Column2<td>Column3</tr>"
+ "</tfoot>"
+ "</table></v-grid>";
//@formatter:on
Grid grid = new Grid();
grid.addColumn("Column1", String.class);
grid.addColumn("Column2", String.class);
@@ -182,19 +202,21 @@ public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase {

@Test
public void testMultipleFootersWithColSpans() {
String design = "<v-grid><table>"//
//@formatter:off
String design = "<v-grid><table>"
+ "<colgroup>"
+ " <col sortable='' property-id='Column1'>"
+ " <col sortable='' property-id='Column2'>"
+ " <col sortable='' property-id='Column3'>"
+ "</colgroup>" //
+ "</colgroup>"
+ "<thead />" // No headers read or written.
+ "<tfoot>" //
+ "<tfoot>"
+ " <tr><td colspan=3>Baz</tr>"
+ " <tr><td>Column1<td>Column2<td>Column3</tr>" //
+ " <tr><td>Foo<td colspan=2>Bar</tr>" //
+ "</tfoot>" //
+ " <tr><td>Column1<td>Column2<td>Column3</tr>"
+ " <tr><td>Foo<td colspan=2>Bar</tr>"
+ "</tfoot>"
+ "</table></v-grid>";
//@formatter:on
Grid grid = new Grid();
grid.addColumn("Column1", String.class);
grid.addColumn("Column2", String.class);
@@ -219,15 +241,16 @@ public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase {

@Test
public void testComponentInGridHeader() {
String design = "<v-grid><table>"//
//@formatter:off
String design = "<v-grid><table>"
+ "<colgroup>"
+ " <col sortable='' property-id='Column1'>"
+ "</colgroup>" //
+ "<thead>" //
+ "</colgroup>"
+ "<thead>"
+ "<tr default=''><th><v-label><b>Foo</b></v-label></tr>"
+ "</thead>"//
+ "</thead>"
+ "</table></v-grid>";
//@formatter:on
Label component = new Label("<b>Foo</b>");
component.setContentMode(ContentMode.HTML);

@@ -241,16 +264,17 @@ public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase {

@Test
public void testComponentInGridFooter() {
String design = "<v-grid><table>"//
//@formatter:off
String design = "<v-grid><table>"
+ "<colgroup>"
+ " <col sortable='' property-id='Column1'>"
+ "</colgroup>" //
+ "</colgroup>"
+ "<thead />" // No headers read or written
+ "<tfoot>" //
+ "<tr><td><v-label><b>Foo</b></v-label></tr>"//
+ "</tfoot>" //
+ "<tfoot>"
+ "<tr><td><v-label><b>Foo</b></v-label></tr>"
+ "</tfoot>"
+ "</table></v-grid>";
//@formatter:on
Label component = new Label("<b>Foo</b>");
component.setContentMode(ContentMode.HTML);

@@ -262,4 +286,67 @@ public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase {
testRead(design, grid, true);
testWrite(design, grid);
}

@Test
public void testHtmlEntitiesinGridHeaderFooter() {
// @formatter off
String design = "<v-grid><table>" + "<colgroup>"
+ " <col sortable=\"true\" property-id=\"> test\">"
+ "</colgroup>" + "<thead>"
+ " <tr><th plain-text=\"true\">&gt; Test</th></tr>"
+ "</thead>" + "<tfoot>"
+ " <tr><td plain-text=\"true\">&gt; Test</td></tr>"
+ "</tfoot>" + "<tbody />" + "</table></v-grid>";
// @formatter off
Grid grid = read(design);
String actualHeader = grid.getHeaderRow(0).getCell("> test").getText();
String actualFooter = grid.getFooterRow(0).getCell("> test").getText();
String expected = "> Test";

Assert.assertEquals(expected, actualHeader);
Assert.assertEquals(expected, actualFooter);

design = design.replace("plain-text=\"true\"", "");
grid = read(design);
actualHeader = grid.getHeaderRow(0).getCell("> test").getHtml();
actualFooter = grid.getFooterRow(0).getCell("> test").getHtml();
expected = "&gt; Test";

Assert.assertEquals(expected, actualHeader);
Assert.assertEquals(expected, actualFooter);

grid = new Grid();
grid.setColumns("test");
HeaderRow header = grid.addHeaderRowAt(0);
FooterRow footer = grid.addFooterRowAt(0);
grid.removeHeaderRow(grid.getDefaultHeaderRow());

// entities should be encoded when writing back, not interpreted as HTML
header.getCell("test").setText("&amp; Test");
footer.getCell("test").setText("&amp; Test");

Element root = new Element(Tag.valueOf("v-grid"), "");
grid.writeDesign(root, new DesignContext());

Assert.assertEquals("&amp;amp; Test", root.getElementsByTag("th")
.get(0).html());
Assert.assertEquals("&amp;amp; Test", root.getElementsByTag("td")
.get(0).html());

header = grid.addHeaderRowAt(0);
footer = grid.addFooterRowAt(0);

// entities should not be encoded, this is already given as HTML
header.getCell("test").setHtml("&amp; Test");
footer.getCell("test").setHtml("&amp; Test");

root = new Element(Tag.valueOf("v-grid"), "");
grid.writeDesign(root, new DesignContext());

Assert.assertEquals("&amp; Test", root.getElementsByTag("th").get(0)
.html());
Assert.assertEquals("&amp; Test", root.getElementsByTag("td").get(0)
.html());

}
}

+ 24
- 0
server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridInlineDataDeclarativeTest.java Näytä tiedosto

@@ -15,8 +15,10 @@
*/
package com.vaadin.tests.server.component.grid.declarative;

import org.junit.Assert;
import org.junit.Test;

import com.vaadin.data.Container;
import com.vaadin.ui.Grid;

public class GridInlineDataDeclarativeTest extends GridDeclarativeTestBase {
@@ -32,6 +34,7 @@ public class GridInlineDataDeclarativeTest extends GridDeclarativeTestBase {
+ "<tr><td>Foo</tr>" //
+ "<tr><td>Bar</tr>" //
+ "<tr><td>Baz</tr>" //
+ "</tbody>"
+ "</table></v-grid>";

Grid grid = new Grid();
@@ -59,6 +62,7 @@ public class GridInlineDataDeclarativeTest extends GridDeclarativeTestBase {
+ "<tbody>" //
+ "<tr><td>Foo<td>Bar<td>Baz</tr>" //
+ "<tr><td>My<td>Summer<td>Car</tr>" //
+ "</tbody>"
+ "</table></v-grid>";

Grid grid = new Grid();
@@ -87,6 +91,7 @@ public class GridInlineDataDeclarativeTest extends GridDeclarativeTestBase {
+ "<tbody>" //
+ "<tr><td>Bar<td>Baz<td>Foo</tr>" //
+ "<tr><td>Summer<td>Car<td>My</tr>" //
+ "</tbody>"
+ "</table></v-grid>";

Grid grid = new Grid();
@@ -103,4 +108,23 @@ public class GridInlineDataDeclarativeTest extends GridDeclarativeTestBase {
testWrite(design, grid, true);
testRead(design, grid, true, true);
}
@Test
public void testHtmlEntities() {
String design = "<v-grid><table>"//
+ "<colgroup>"
+ " <col property-id='test' />"
+ "</colgroup>" //
+ "<thead />" // No headers read or written
+ "<tbody>"
+ " <tr><td>&amp;Test</tr></td>"
+ "</tbody>"
+ "</table></v-grid>";
Grid read = read(design);
Container cds = read.getContainerDataSource();
Assert.assertEquals("&amp;Test",
cds.getItem(cds.getItemIds().iterator().next())
.getItemProperty("test").getValue());
}
}

+ 32
- 4
server/tests/src/com/vaadin/tests/server/component/label/LabelDeclarativeTest.java Näytä tiedosto

@@ -15,11 +15,16 @@
*/
package com.vaadin.tests.server.component.label;

import org.jsoup.nodes.Element;
import org.jsoup.parser.Tag;
import org.junit.Assert;
import org.junit.Test;

import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.tests.design.DeclarativeTestBase;
import com.vaadin.ui.Label;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.DesignFormatter;

/**
* Tests declarative support for implementations of {@link Label}.
@@ -57,11 +62,11 @@ public class LabelDeclarativeTest extends DeclarativeTestBase<Label> {

@Test
public void testPlainText() {
String design = "<v-label plain-text>This is only <b>text</b>"
String design = "<v-label plain-text>This is only &lt;b&gt;text&lt;/b&gt;"
+ " and will contain visible tags</v-label>";
Label l = createLabel(
"This is only \n<b>text</b> and will contain visible tags",
null, false);
"This is only <b>text</b> and will contain visible tags", null,
false);
testRead(design, l);
testWrite(design, l);
}
@@ -84,6 +89,29 @@ public class LabelDeclarativeTest extends DeclarativeTestBase<Label> {
testWrite(design, l);
}

@Test
public void testHtmlEntities() {
String design = "<v-label plain-text=\"true\">&gt; Test</v-label>";
Label read = read(design);
Assert.assertEquals("> Test", read.getValue());

design = design.replace("plain-text=\"true\"", "");
read = read(design);
Assert.assertEquals("&gt; Test", read.getValue());

Label label = new Label("&amp; Test");
label.setContentMode(ContentMode.TEXT);

Element root = new Element(Tag.valueOf("v-label"), "");
label.writeDesign(root, new DesignContext());
Assert.assertEquals("&amp;amp; Test", root.html());

label.setContentMode(ContentMode.HTML);
root = new Element(Tag.valueOf("v-label"), "");
label.writeDesign(root, new DesignContext());
Assert.assertEquals("&amp; Test", root.html());
}

private Label createLabel(String content, String caption, boolean html) {
Label label = new Label();
label.setContentMode(html ? ContentMode.HTML : ContentMode.TEXT);
@@ -91,7 +119,7 @@ public class LabelDeclarativeTest extends DeclarativeTestBase<Label> {
label.setValue(content);
}
if (caption != null) {
label.setCaption(caption);
label.setCaption(DesignFormatter.encodeForTextNode(caption));
}
return label;
}

+ 28
- 0
server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTest.java Näytä tiedosto

@@ -15,6 +15,7 @@
*/
package com.vaadin.tests.server.component.table;

import org.junit.Assert;
import org.junit.Test;

import com.vaadin.server.ExternalResource;
@@ -24,6 +25,7 @@ import com.vaadin.ui.Table.Align;
import com.vaadin.ui.Table.ColumnHeaderMode;
import com.vaadin.ui.Table.RowHeaderMode;
import com.vaadin.ui.Table.TableDragMode;
import com.vaadin.ui.declarative.Design;

/**
* Test declarative support for {@link Table}.
@@ -166,4 +168,30 @@ public class TableDeclarativeTest extends TableDeclarativeTestBase {
testRead(design, table);
testWrite(design, table, true);
}
@Test
public void testHtmlEntities() {
String design = "<v-table>"
+ "<table>"
+ " <colgroup>"
+ " <col property-id=\"test\""
+ " </colgroup>"
+ " <thead>"
+ " <tr><th>&amp; Test</th></tr>"
+ " </thead>"
+ " <tbody>"
+ " <tr item-id=\"test\"><td>&amp; Test</tr>"
+ " </tbody>"
+ " <tfoot>"
+ " <tr><td>&amp; Test</td></tr>"
+ " </tfoot>"
+ "</table>"
+ "</v-table>";
Table read = read(design);
Assert.assertEquals("& Test",
read.getContainerProperty("test", "test").getValue());
Assert.assertEquals("& Test", read.getColumnHeader("test"));
Assert.assertEquals("& Test", read.getColumnFooter("test"));
}
}

+ 22
- 0
server/tests/src/com/vaadin/tests/server/component/textarea/TextAreaDeclarativeTest.java Näytä tiedosto

@@ -15,10 +15,16 @@
*/
package com.vaadin.tests.server.component.textarea;

import java.io.IOException;

import org.jsoup.nodes.Element;
import org.jsoup.parser.Tag;
import org.junit.Assert;
import org.junit.Test;

import com.vaadin.tests.design.DeclarativeTestBase;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.declarative.DesignContext;

/**
* Tests declarative support for implementations of {@link TextArea}.
@@ -38,4 +44,20 @@ public class TextAreaDeclarativeTest extends DeclarativeTestBase<TextArea> {
testRead(design, ta);
testWrite(design, ta);
}

@Test
public void testHtmlEntities() throws IOException {
String design = "<v-text-area>&amp; Test</v-text-area>";
TextArea read = read(design);
Assert.assertEquals("& Test", read.getValue());

read.setValue("&amp; Test");

DesignContext dc = new DesignContext();
Element root = new Element(Tag.valueOf("v-text-area"), "");
read.writeDesign(root, dc);

Assert.assertEquals("&amp;amp; Test", root.html());

}
}

Loading…
Peruuta
Tallenna