--- /dev/null
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.tests.design;
+
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+
+import com.vaadin.ui.Component;
+
+public abstract class DeclarativeTestBase<T extends Component> extends
+ DeclarativeTestBaseBase<T> {
+
+ private static boolean debug = false;
+
+ private final Map<Class<?>, EqualsAsserter<?>> comparators = new HashMap<Class<?>, EqualsAsserter<?>>();
+ private static EqualsAsserter standardEqualsComparator = new EqualsAsserter<Object>() {
+
+ @Override
+ public void assertObjectEquals(Object o1, Object o2) {
+ Assert.assertEquals(o1, o2);
+ }
+ };
+
+ public class IntrospectorEqualsAsserter<T> implements EqualsAsserter<T> {
+
+ private Class<T> c;
+
+ public IntrospectorEqualsAsserter(Class<T> c) {
+ this.c = c;
+ }
+
+ @Override
+ public void assertObjectEquals(T o1, T o2) {
+ try {
+ BeanInfo bi = Introspector.getBeanInfo(c);
+ for (PropertyDescriptor pd : bi.getPropertyDescriptors()) {
+ Method readMethod = pd.getReadMethod();
+ Method writeMethod = pd.getWriteMethod();
+ if (readMethod == null || writeMethod == null) {
+ continue;
+ }
+ try {
+ c.getDeclaredMethod(readMethod.getName());
+ } catch (Exception e) {
+ // Not declared in this class, will be tested by parent
+ // class tester
+ if (debug) {
+ System.out.println("Skipped " + c.getSimpleName()
+ + "." + readMethod.getName());
+ }
+ continue;
+ }
+
+ if (debug) {
+ System.out.println("Testing " + c.getSimpleName() + "."
+ + readMethod.getName());
+ }
+ Object v1 = readMethod.invoke(o1);
+ Object v2 = readMethod.invoke(o2);
+ assertEquals(pd.getDisplayName(), v1, v2);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Override
+ protected EqualsAsserter getComparator(Class c) {
+ com.vaadin.tests.design.DeclarativeTestBaseBase.EqualsAsserter<?> comp = comparators
+ .get(c);
+ if (comp == null) {
+ if (c.isEnum()) {
+ return standardEqualsComparator;
+ }
+ if (debug) {
+ System.out.println("No comparator found for " + c.getName()
+ + ". Using introspector.");
+ }
+ return new IntrospectorEqualsAsserter<T>(c);
+ }
+ return comp;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.tests.design;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Attribute;
+import org.jsoup.nodes.Element;
+import org.junit.Assert;
+
+import com.vaadin.ui.Component;
+import com.vaadin.ui.declarative.Design;
+
+public abstract class DeclarativeTestBaseBase<T extends Component> {
+ public interface EqualsAsserter<TT> {
+ public void assertObjectEquals(TT o1, TT o2);
+ }
+
+ protected T read(String design) {
+ try {
+ return (T) Design.read(new ByteArrayInputStream(design
+ .getBytes("UTF-8")));
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected String write(T object) {
+ try {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ Design.write(object, outputStream);
+ return outputStream.toString("UTF-8");
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected void assertEquals(Object o1, Object o2) {
+ assertEquals("", o1, o2);
+ }
+
+ protected void assertEquals(String message, Object o1, Object o2) {
+ if (o1 == null) {
+ Assert.assertEquals(message, null, o2);
+ return;
+ }
+ if (o2 == null) {
+ Assert.assertEquals(message, null, o1);
+ return;
+ }
+
+ if (o1 instanceof Collection && o2 instanceof Collection) {
+
+ } else {
+ Assert.assertEquals(o1.getClass(), o2.getClass());
+ }
+
+ List<EqualsAsserter<Object>> comparators = getComparators(o1);
+ if (!comparators.isEmpty()) {
+ for (EqualsAsserter<Object> ec : comparators) {
+ ec.assertObjectEquals(o1, o2);
+ }
+ } else {
+ Assert.assertEquals(message, o1, o2);
+ }
+ }
+
+ private List<EqualsAsserter<Object>> getComparators(Object o1) {
+ List<EqualsAsserter<Object>> result = new ArrayList<EqualsAsserter<Object>>();
+ getComparators(o1.getClass(), result);
+ return result;
+ }
+
+ private void getComparators(Class<?> c, List<EqualsAsserter<Object>> result) {
+ if (c == null || !isVaadin(c)) {
+ return;
+ }
+ EqualsAsserter<Object> comparator = (EqualsAsserter<Object>) getComparator(c);
+ if (c.getSuperclass() != Object.class) {
+ getComparators(c.getSuperclass(), result);
+ }
+ for (Class<?> i : c.getInterfaces()) {
+ getComparators(i, result);
+ }
+
+ if (!result.contains(comparator)) {
+ result.add(comparator);
+ }
+ }
+
+ protected abstract <TT> EqualsAsserter<TT> getComparator(Class<TT> c);
+
+ private boolean isVaadin(Class<?> c) {
+ return c.getPackage().getName().startsWith("com.vaadin");
+ }
+
+ public void testRead(String design, T expected) {
+ assertEquals(expected, read(design));
+ }
+
+ public void testWrite(String design, T expected) {
+ String written = write(expected);
+
+ Element producedElem = Jsoup.parse(written).body().child(0);
+ Element comparableElem = Jsoup.parse(design).body().child(0);
+
+ String produced = elementToHtml(producedElem);
+ String comparable = elementToHtml(comparableElem);
+
+ Assert.assertEquals(comparable, produced);
+ }
+
+ private String elementToHtml(Element producedElem) {
+ StringBuilder stringBuilder = new StringBuilder();
+ elementToHtml(producedElem, stringBuilder);
+ return stringBuilder.toString();
+ }
+
+ /**
+ * Produce predictable html (attributes in alphabetical order), always
+ * include close tags
+ */
+ private String elementToHtml(Element producedElem, StringBuilder sb) {
+ ArrayList<String> names = new ArrayList<String>();
+ for (Attribute a : producedElem.attributes().asList()) {
+ names.add(a.getKey());
+ }
+ Collections.sort(names);
+
+ sb.append("<" + producedElem.tagName() + "");
+ for (String attrName : names) {
+ sb.append(" ").append(attrName).append("=").append("\'")
+ .append(producedElem.attr(attrName)).append("\'");
+ }
+ sb.append(">");
+ for (Element child : producedElem.children()) {
+ elementToHtml(child, sb);
+ }
+ sb.append("</").append(producedElem.tagName()).append(">");
+ return sb.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.tests.server.component.absolutelayout;
+
+import org.junit.Test;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.AbsoluteLayout;
+import com.vaadin.ui.Button;
+
+/**
+ * Tests declarative support for implementations of {@link AbsoluteLayout}.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class AbsoluteLayoutDeclarativeTest extends
+ DeclarativeTestBase<AbsoluteLayout> {
+
+ @Test
+ public void testPlainTextRead() {
+ testRead(getDesign(), getExpected());
+ }
+
+ @Test
+ public void testPlainTextWrite() {
+ testWrite(getDesign(), getExpected());
+ }
+
+ protected String getDesign() {
+ return "<v-absolute-layout>"
+ + "<v-button :top='100px' :left='0px' :z-index=21>OK</v-button>"
+ + "<v-button :bottom='0px' :right='0px'>Cancel</v-button>"
+ + "</v-absolute-layout>";
+ }
+
+ protected AbsoluteLayout getExpected() {
+ AbsoluteLayout c = new AbsoluteLayout();
+ Button b1 = new Button("OK");
+ b1.setCaptionAsHtml(true);
+ Button b2 = new Button("Cancel");
+ b2.setCaptionAsHtml(true);
+
+ c.addComponent(b1, "top: 100px; left: 0px; z-index: 21");
+ c.addComponent(b2, "bottom: 0px; right: 0px;");
+ System.out.println(c.getComponentCount());
+ return c;
+ };
+
+ @Test
+ public void testEmpty() {
+ testRead("<v-absolute-layout/>", new AbsoluteLayout());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.tests.server.component.abstractfield;
+
+import org.junit.Test;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.AbstractField;
+import com.vaadin.ui.TextField;
+
+/**
+ * Tests declarative support for implementations of {@link AbstractField}.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class AbstractFieldDeclarativeTest extends
+ DeclarativeTestBase<AbstractField<?>> {
+
+ @Test
+ public void testPlainTextRead() {
+ testRead(getDesign(), getExpected());
+ }
+
+ @Test
+ public void testPlainTextWrite() {
+ testWrite(getDesign(), getExpected());
+ }
+
+ protected String getDesign() {
+ return "<v-text-field buffered='true' validation-visible='false' invalid-committed='true'"
+ + " invalid-allowed='false' required='true' required-error='This is a required field'"
+ + " conversion-error='Input {0} cannot be parsed' tabindex=3 readonly='true'/>";
+ }
+
+ protected AbstractField getExpected() {
+ TextField tf = new TextField();
+ tf.setBuffered(true);
+ tf.setValidationVisible(false);
+ tf.setInvalidCommitted(true);
+ tf.setInvalidAllowed(false);
+ tf.setRequired(true);
+ tf.setRequiredError("This is a required field");
+ tf.setConversionError("Input {0} cannot be parsed");
+ tf.setTabIndex(3);
+ tf.setReadOnly(true);
+ return tf;
+ };
+
+}
--- /dev/null
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.tests.server.component.button;
+
+import org.junit.Test;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.Button;
+
+/**
+ * Tests declarative support for implementations of {@link Button}.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class ButtonDeclarativeTest extends DeclarativeTestBase<Button> {
+
+ @Test
+ public void testPlainTextRead() {
+ testRead(getDesignPlainText(), getExpectedPlainText());
+ }
+
+ @Test
+ public void testPlainTextWrite() {
+ testWrite(getDesignPlainText(), getExpectedPlainText());
+ }
+
+ protected String getDesignPlainText() {
+ return "<v-button plain-text=''></v-button>";
+ }
+
+ protected Button getExpectedPlainText() {
+ Button c = new Button();
+ c.setCaption("");
+ return c;
+ };
+
+ @Test
+ public void testHtmlRead() {
+ testRead(getDesignHtml(), getExpectedHtml());
+ }
+
+ @Test
+ public void testHtmlWrite() {
+ testWrite(getDesignHtml(), getExpectedHtml());
+ }
+
+ protected String getDesignHtml() {
+ return "<v-button />";
+ }
+
+ protected Button getExpectedHtml() {
+ Button c = new Button();
+ c.setCaption("");
+ c.setCaptionAsHtml(true);
+ return c;
+ };
+
+}
--- /dev/null
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.tests.server.component.checkbox;
+
+import org.junit.Test;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.CheckBox;
+
+/**
+ * Tests declarative support for implementations of {@link CheckBox}.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class CheckboxDeclarativeTest extends DeclarativeTestBase<CheckBox> {
+
+ protected String getDesign() {
+ return "<v-check-box checked='true' />";
+ }
+
+ protected CheckBox getExpectedResult() {
+ CheckBox c = new CheckBox();
+ c.setValue(true);
+ return c;
+ };
+
+ @Test
+ public void read() {
+ testRead(getDesign(), getExpectedResult());
+ }
+
+ @Test
+ public void write() {
+ testWrite(getDesign(), getExpectedResult());
+ }
+
+ @Test
+ public void testEmpty() {
+ testRead("<v-check-box>", new CheckBox());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.tests.server.component.label;
+
+import org.junit.Test;
+
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.Label;
+
+/**
+ * Tests declarative support for implementations of {@link Label}.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class LabelDeclarativeTest extends DeclarativeTestBase<Label> {
+
+ @Test
+ public void testDefaultRead() {
+ testRead(getDefaultDesign(), getDefaultExpected());
+ }
+
+ @Test
+ public void testDefaultWrite() {
+ testWrite(getDefaultDesign(), getDefaultExpected());
+ }
+
+ protected String getDefaultDesign() {
+ return "<v-label>Hello world!</v-label>";
+ }
+
+ protected Label getDefaultExpected() {
+ Label tf = new Label();
+ tf.setContentMode(ContentMode.HTML);
+ tf.setValue("Hello world!");
+ return tf;
+ };
+
+ @Test
+ public void testRichRead() {
+ testRead(getRichDesign(), getRichExpected());
+ }
+
+ @Test
+ public void testRichWrite() {
+ testWrite(getRichDesign(), getRichExpected());
+ }
+
+ protected String getRichDesign() {
+ return "<v-label>This is <b><u>Rich</u></b> content!</v-label>";
+ }
+
+ protected Label getRichExpected() {
+ Label tf = new Label();
+ tf.setContentMode(ContentMode.HTML);
+ tf.setValue("This is \n<b><u>Rich</u></b> content!");
+ return tf;
+ };
+
+ @Test
+ public void testPlainTextRead() {
+ testRead(getPlainTextDesign(), getPlainTextExpected());
+ }
+
+ @Test
+ public void testPlainTextWrite() {
+ testWrite(getPlainTextDesign(), getPlainTextExpected());
+ }
+
+ protected String getPlainTextDesign() {
+ return "<v-label plain-text>This is only <b>text</b> and will contain visible tags</v-label>";
+ }
+
+ protected Label getPlainTextExpected() {
+ Label tf = new Label();
+ tf.setContentMode(ContentMode.TEXT);
+ tf.setValue("This is only \n<b>text</b> and will contain visible tags");
+ return tf;
+ };
+
+}
--- /dev/null
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.tests.server.component.textarea;
+
+import org.junit.Test;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.TextArea;
+
+/**
+ * Tests declarative support for implementations of {@link TextArea}.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class TextAreaDeclarativeTest extends DeclarativeTestBase<TextArea> {
+
+ @Test
+ public void testRead() {
+ testRead(getDesign(), getExpected());
+ }
+
+ @Test
+ public void testWrite() {
+ testWrite(getDesign(), getExpected());
+ }
+
+ protected String getDesign() {
+ return "<v-text-area rows=6 wordwrap=false>Hello World!</v-text-area>";
+ }
+
+ protected TextArea getExpected() {
+ TextArea tf = new TextArea();
+ tf.setRows(6);
+ tf.setWordwrap(false);
+ tf.setValue("Hello World!");
+ return tf;
+ };
+
+}
--- /dev/null
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.tests.server.component.textfield;
+
+import org.junit.Test;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.TextField;
+
+/**
+ * Tests declarative support for implementations of {@link TextField}.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class TextFieldDeclarativeTest extends DeclarativeTestBase<TextField> {
+
+ @Test
+ public void testPlainTextRead() {
+ testRead(getDesign(), getExpected());
+ }
+
+ @Test
+ public void testPlainTextWrite() {
+ testWrite(getDesign(), getExpected());
+ }
+
+ protected String getDesign() {
+ return "<v-text-field/>";
+ }
+
+ protected TextField getExpected() {
+ TextField tf = new TextField();
+ return tf;
+ };
+
+}