You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DeclarativeTestBaseBase.java 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. * Copyright 2000-2016 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.tests.design;
  17. import static java.nio.charset.StandardCharsets.UTF_8;
  18. import static org.junit.Assert.assertNull;
  19. import java.io.ByteArrayInputStream;
  20. import java.io.ByteArrayOutputStream;
  21. import java.util.ArrayList;
  22. import java.util.Collection;
  23. import java.util.Collections;
  24. import java.util.HashSet;
  25. import java.util.List;
  26. import java.util.logging.Handler;
  27. import java.util.logging.LogRecord;
  28. import java.util.logging.Logger;
  29. import org.jsoup.Jsoup;
  30. import org.jsoup.nodes.Attribute;
  31. import org.jsoup.nodes.BooleanAttribute;
  32. import org.jsoup.nodes.Element;
  33. import org.jsoup.nodes.Node;
  34. import org.jsoup.nodes.TextNode;
  35. import org.junit.Assert;
  36. import com.vaadin.ui.AbstractComponent;
  37. import com.vaadin.ui.Component;
  38. import com.vaadin.ui.declarative.Design;
  39. import com.vaadin.ui.declarative.DesignContext;
  40. import com.vaadin.ui.declarative.ShouldWriteDataDelegate;
  41. public abstract class DeclarativeTestBaseBase<T extends Component> {
  42. private static final class AlwaysWriteDelegate
  43. implements ShouldWriteDataDelegate {
  44. private static final long serialVersionUID = -6345914431997793599L;
  45. @Override
  46. public boolean shouldWriteData(Component component) {
  47. return true;
  48. }
  49. }
  50. public static final ShouldWriteDataDelegate ALWAYS_WRITE_DATA = new AlwaysWriteDelegate();
  51. public interface EqualsAsserter<TT> {
  52. public void assertObjectEquals(TT o1, TT o2);
  53. }
  54. protected T read(String design) {
  55. return (T) Design
  56. .read(new ByteArrayInputStream(design.getBytes(UTF_8)));
  57. }
  58. protected DesignContext readAndReturnContext(String design) {
  59. return Design.read(new ByteArrayInputStream(design.getBytes(UTF_8)),
  60. null);
  61. }
  62. protected String write(T object, boolean writeData) {
  63. DesignContext dc = new DesignContext();
  64. if (writeData) {
  65. dc.setShouldWriteDataDelegate(
  66. DeclarativeTestBaseBase.ALWAYS_WRITE_DATA);
  67. }
  68. return write(object, dc);
  69. }
  70. protected String write(T object, DesignContext context) {
  71. try {
  72. ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  73. context.setRootComponent(object);
  74. Design.write(context, outputStream);
  75. return outputStream.toString(UTF_8.name());
  76. } catch (Exception e) {
  77. throw new RuntimeException(e);
  78. }
  79. }
  80. protected void assertEquals(Object o1, Object o2) {
  81. assertEquals("", o1, o2);
  82. }
  83. protected void assertEquals(String message, Object o1, Object o2) {
  84. if (o1 == null) {
  85. assertNull(message, o2);
  86. return;
  87. }
  88. if (o2 == null) {
  89. assertNull(message, o1);
  90. return;
  91. }
  92. if (!(o1 instanceof Collection && o2 instanceof Collection)) {
  93. Assert.assertEquals(o1.getClass(), o2.getClass());
  94. }
  95. if (o1 instanceof Object[]) {
  96. Object[] a1 = ((Object[]) o1);
  97. Object[] a2 = ((Object[]) o2);
  98. Assert.assertEquals(message + ": array length", a1.length,
  99. a2.length);
  100. for (int i = 0; i < a1.length; i++) {
  101. assertEquals(message + ": element " + i, a1[i], a2[i]);
  102. }
  103. return;
  104. }
  105. List<EqualsAsserter<Object>> comparators = getComparators(o1);
  106. if (!comparators.isEmpty()) {
  107. for (EqualsAsserter<Object> ec : comparators) {
  108. ec.assertObjectEquals(o1, o2);
  109. }
  110. } else {
  111. Assert.assertEquals(message, o1, o2);
  112. }
  113. }
  114. private List<EqualsAsserter<Object>> getComparators(Object o1) {
  115. List<EqualsAsserter<Object>> result = new ArrayList<>();
  116. getComparators(o1.getClass(), result);
  117. return result;
  118. }
  119. private void getComparators(Class<?> c,
  120. List<EqualsAsserter<Object>> result) {
  121. if (c == null || !isVaadin(c)) {
  122. return;
  123. }
  124. EqualsAsserter<Object> comparator = (EqualsAsserter<Object>) getComparator(
  125. c);
  126. if (c.getSuperclass() != Object.class) {
  127. getComparators(c.getSuperclass(), result);
  128. }
  129. for (Class<?> i : c.getInterfaces()) {
  130. getComparators(i, result);
  131. }
  132. if (!result.contains(comparator)) {
  133. result.add(comparator);
  134. }
  135. }
  136. protected abstract <TT> EqualsAsserter<TT> getComparator(Class<TT> c);
  137. private boolean isVaadin(Class<?> c) {
  138. return c.getPackage() != null
  139. && c.getPackage().getName().startsWith("com.vaadin");
  140. }
  141. public static class TestLogHandler {
  142. final List<String> messages = new ArrayList<>();
  143. Handler handler = new Handler() {
  144. @Override
  145. public void publish(LogRecord record) {
  146. messages.add(record.getMessage());
  147. }
  148. @Override
  149. public void flush() {
  150. }
  151. @Override
  152. public void close() throws SecurityException {
  153. }
  154. };
  155. public TestLogHandler() {
  156. Logger.getLogger(AbstractComponent.class.getName()).getParent()
  157. .addHandler(handler);
  158. }
  159. public String getMessages() {
  160. if (messages.isEmpty()) {
  161. return "";
  162. }
  163. String r = "";
  164. for (String message : messages) {
  165. r += message + "\n";
  166. }
  167. return r;
  168. }
  169. }
  170. public T testRead(String design, T expected) {
  171. TestLogHandler l = new TestLogHandler();
  172. T read = read(design);
  173. assertEquals(expected, read);
  174. Assert.assertEquals("", l.getMessages());
  175. return read;
  176. }
  177. public DesignContext readComponentAndCompare(String design, T expected) {
  178. TestLogHandler l = new TestLogHandler();
  179. DesignContext context = readAndReturnContext(design);
  180. assertEquals(expected, context.getRootComponent());
  181. Assert.assertEquals("", l.getMessages());
  182. return context;
  183. }
  184. public void testWrite(String expected, T component) {
  185. TestLogHandler l = new TestLogHandler();
  186. testWrite(expected, component, false);
  187. Assert.assertEquals("", l.getMessages());
  188. }
  189. public void testWrite(String expectedDesign, T component,
  190. boolean writeData) {
  191. String written = write(component, writeData);
  192. Element producedElem = Jsoup.parse(written).body().child(0);
  193. Element comparableElem = Jsoup.parse(expectedDesign).body().child(0);
  194. String produced = elementToHtml(producedElem);
  195. String comparable = elementToHtml(comparableElem);
  196. Assert.assertEquals(comparable, produced);
  197. }
  198. public void testWrite(T component, String expected, DesignContext context) {
  199. String written = write(component, context);
  200. Element producedElem = Jsoup.parse(written).body().child(0);
  201. Element comparableElem = Jsoup.parse(expected).body().child(0);
  202. String produced = elementToHtml(producedElem);
  203. String comparable = elementToHtml(comparableElem);
  204. Assert.assertEquals(comparable, produced);
  205. }
  206. protected Element createElement(Component c) {
  207. return new DesignContext().createElement(c);
  208. }
  209. private String elementToHtml(Element producedElem) {
  210. StringBuilder stringBuilder = new StringBuilder();
  211. elementToHtml(producedElem, stringBuilder);
  212. return stringBuilder.toString();
  213. }
  214. /**
  215. * Produce predictable html (attributes in alphabetical order), always
  216. * include close tags
  217. */
  218. private String elementToHtml(Element producedElem, StringBuilder sb) {
  219. HashSet<String> booleanAttributes = new HashSet<>();
  220. List<String> names = new ArrayList<>();
  221. for (Attribute a : producedElem.attributes().asList()) {
  222. names.add(a.getKey());
  223. if (a instanceof BooleanAttribute) {
  224. booleanAttributes.add(a.getKey());
  225. }
  226. }
  227. Collections.sort(names);
  228. sb.append('<').append(producedElem.tagName());
  229. for (String attrName : names) {
  230. sb.append(' ').append(attrName);
  231. if (!booleanAttributes.contains(attrName)) {
  232. sb.append('=').append("\'").append(producedElem.attr(attrName))
  233. .append("\'");
  234. }
  235. }
  236. sb.append('>');
  237. for (Node child : producedElem.childNodes()) {
  238. if (child instanceof Element) {
  239. elementToHtml((Element) child, sb);
  240. } else if (child instanceof TextNode) {
  241. String text = ((TextNode) child).text();
  242. sb.append(text.trim());
  243. }
  244. }
  245. sb.append("</").append(producedElem.tagName()).append('>');
  246. return sb.toString();
  247. }
  248. protected String stripOptionTags(String design) {
  249. return design.replaceAll("[ \n]*<option(.*)</option>[ \n]*", "");
  250. }
  251. }