]> source.dussan.org Git - vaadin-framework.git/commitdiff
Test cases for #4394: value change listeners triggered multiple times.
authorHenri Sara <henri.sara@itmill.com>
Tue, 23 Mar 2010 12:51:43 +0000 (12:51 +0000)
committerHenri Sara <henri.sara@itmill.com>
Tue, 23 Mar 2010 12:51:43 +0000 (12:51 +0000)
svn changeset:12040/svn branch:6.3

tests/src/com/vaadin/tests/server/components/TestComboBoxValueChange.java [new file with mode: 0644]
tests/src/com/vaadin/tests/server/components/TestFieldValueChange.java [new file with mode: 0644]
tests/src/com/vaadin/tests/server/components/TestTextFieldValueChange.java [new file with mode: 0644]

diff --git a/tests/src/com/vaadin/tests/server/components/TestComboBoxValueChange.java b/tests/src/com/vaadin/tests/server/components/TestComboBoxValueChange.java
new file mode 100644 (file)
index 0000000..f104fbe
--- /dev/null
@@ -0,0 +1,30 @@
+package com.vaadin.tests.server.components;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import com.vaadin.ui.AbstractField;\r
+import com.vaadin.ui.ComboBox;\r
+\r
+/**\r
+ * Check that the value change listener for a combo box is triggered exactly\r
+ * once when setting the value, at the correct time.\r
+ * \r
+ * See <a href="http://dev.vaadin.com/ticket/4394">Ticket 4394</a>.\r
+ */\r
+public class TestComboBoxValueChange extends TestFieldValueChange {\r
+    @Override\r
+    protected void setUp() throws Exception {\r
+        ComboBox combo = new ComboBox();\r
+        combo.addItem("myvalue");\r
+        super.setUp(combo);\r
+    }\r
+\r
+    @Override\r
+    protected void setValue(AbstractField field) {\r
+        Map<String, Object> variables = new HashMap<String, Object>();\r
+        variables.put("selected", new String[] { "myvalue" });\r
+        field.changeVariables(field, variables);\r
+    }\r
+\r
+}\r
diff --git a/tests/src/com/vaadin/tests/server/components/TestFieldValueChange.java b/tests/src/com/vaadin/tests/server/components/TestFieldValueChange.java
new file mode 100644 (file)
index 0000000..2749f16
--- /dev/null
@@ -0,0 +1,165 @@
+package com.vaadin.tests.server.components;\r
+\r
+import junit.framework.TestCase;\r
+\r
+import org.easymock.EasyMock;\r
+\r
+import com.vaadin.data.Property.ValueChangeEvent;\r
+import com.vaadin.data.Property.ValueChangeListener;\r
+import com.vaadin.data.Property.ValueChangeNotifier;\r
+import com.vaadin.data.util.ObjectProperty;\r
+import com.vaadin.ui.AbstractField;\r
+\r
+/**\r
+ * Base class for tests for checking that value change listeners for fields are\r
+ * not called exactly once when they should be, and not at other times.\r
+ * \r
+ * Does not check all cases (e.g. properties that do not implement\r
+ * {@link ValueChangeNotifier}).\r
+ * \r
+ * Subclasses should implement {@link #setValue()} and call\r
+ * <code>super.setValue(AbstractField)</code>. Also, subclasses should typically\r
+ * override {@link #setValue(AbstractField)} to set the field value via\r
+ * <code>changeVariables()</code>.\r
+ */\r
+public abstract class TestFieldValueChange extends TestCase {\r
+\r
+    private AbstractField field;\r
+    private ValueChangeListener listener;\r
+\r
+    protected void setUp(AbstractField field) throws Exception {\r
+        this.field = field;\r
+        listener = EasyMock.createStrictMock(ValueChangeListener.class);\r
+\r
+    }\r
+\r
+    /**\r
+     * Test that listeners are not called when they have been unregistered.\r
+     */\r
+    public void testRemoveListener() {\r
+        getField().setPropertyDataSource(new ObjectProperty(""));\r
+        getField().setWriteThrough(true);\r
+        getField().setReadThrough(true);\r
+\r
+        // Expectations and start test\r
+        listener.valueChange(EasyMock.isA(ValueChangeEvent.class));\r
+        EasyMock.replay(listener);\r
+\r
+        // Add listener and set the value -> should end up in listener once\r
+        getField().addListener(listener);\r
+        setValue(getField());\r
+\r
+        // Ensure listener was called once\r
+        EasyMock.verify(listener);\r
+\r
+        // Remove the listener and set the value -> should not end up in\r
+        // listener\r
+        getField().removeListener(listener);\r
+        setValue(getField());\r
+\r
+        // Ensure listener still has been called only once\r
+        EasyMock.verify(listener);\r
+    }\r
+\r
+    /**\r
+     * Common unbuffered case: both writeThrough (auto-commit) and readThrough\r
+     * are on. Calling commit() should not cause notifications.\r
+     * \r
+     * Using the readThrough mode allows changes made to the property value to\r
+     * be seen in some cases also when there is no notification of value change\r
+     * from the property.\r
+     * \r
+     * Field value change notifications closely mirror value changes of the data\r
+     * source behind the field.\r
+     */\r
+    public void testWriteThroughReadThrough() {\r
+        getField().setPropertyDataSource(new ObjectProperty(""));\r
+        getField().setWriteThrough(true);\r
+        getField().setReadThrough(true);\r
+\r
+        expectValueChangeFromSetValueNotCommit();\r
+    }\r
+\r
+    /**\r
+     * Fully buffered use where the data source is neither read nor modified\r
+     * during editing, and is updated at commit().\r
+     * \r
+     * Field value change notifications reflect the buffered value in the field,\r
+     * not the original data source value changes.\r
+     */\r
+    public void testNoWriteThroughNoReadThrough() {\r
+        getField().setPropertyDataSource(new ObjectProperty(""));\r
+        getField().setWriteThrough(false);\r
+        getField().setReadThrough(false);\r
+\r
+        expectValueChangeFromSetValueNotCommit();\r
+    }\r
+\r
+    /**\r
+     * Less common partly buffered case: writeThrough (auto-commit) is on and\r
+     * readThrough is off. Calling commit() should not cause notifications.\r
+     * \r
+     * Without readThrough activated, changes to the data source that do not\r
+     * cause notifications are not reflected by the field value.\r
+     * \r
+     * Field value change notifications correspond to changes made to the data\r
+     * source value through the text field or the (notifying) property.\r
+     */\r
+    public void testWriteThroughNoReadThrough() {\r
+        getField().setPropertyDataSource(new ObjectProperty(""));\r
+        getField().setWriteThrough(true);\r
+        getField().setReadThrough(false);\r
+\r
+        expectValueChangeFromSetValueNotCommit();\r
+    }\r
+\r
+    /**\r
+     * Partly buffered use where the data source is read but not nor modified\r
+     * during editing, and is updated at commit().\r
+     * \r
+     * When used like this, a field is updated from the data source if necessary\r
+     * when its value is requested and the property value has changed but the\r
+     * field has not been modified in its buffer.\r
+     * \r
+     * Field value change notifications reflect the buffered value in the field,\r
+     * not the original data source value changes.\r
+     */\r
+    public void testNoWriteThroughReadThrough() {\r
+        getField().setPropertyDataSource(new ObjectProperty(""));\r
+        getField().setWriteThrough(false);\r
+        getField().setReadThrough(true);\r
+\r
+        expectValueChangeFromSetValueNotCommit();\r
+    }\r
+\r
+    protected void expectValueChangeFromSetValueNotCommit() {\r
+        // Expectations and start test\r
+        listener.valueChange(EasyMock.isA(ValueChangeEvent.class));\r
+        EasyMock.replay(listener);\r
+\r
+        // Add listener and set the value -> should end up in listener once\r
+        getField().addListener(listener);\r
+        setValue(getField());\r
+\r
+        // Ensure listener was called once\r
+        EasyMock.verify(listener);\r
+\r
+        // commit\r
+        getField().commit();\r
+\r
+        // Ensure listener was not called again\r
+        EasyMock.verify(listener);\r
+    }\r
+\r
+    protected AbstractField getField() {\r
+        return field;\r
+    }\r
+\r
+    /**\r
+     * Override in subclasses to set value with changeVariables().\r
+     */\r
+    protected void setValue(AbstractField field) {\r
+        field.setValue("newValue");\r
+    }\r
+\r
+}\r
diff --git a/tests/src/com/vaadin/tests/server/components/TestTextFieldValueChange.java b/tests/src/com/vaadin/tests/server/components/TestTextFieldValueChange.java
new file mode 100644 (file)
index 0000000..74161a9
--- /dev/null
@@ -0,0 +1,39 @@
+package com.vaadin.tests.server.components;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import com.vaadin.ui.AbstractField;\r
+import com.vaadin.ui.TextField;\r
+\r
+/**\r
+ * Check that the value change listener for a text field is triggered exactly\r
+ * once when setting the value, at the correct time.\r
+ * \r
+ * See <a href="http://dev.vaadin.com/ticket/4394">Ticket 4394</a>.\r
+ */\r
+public class TestTextFieldValueChange extends TestFieldValueChange {\r
+\r
+    @Override\r
+    protected void setUp() throws Exception {\r
+        super.setUp(new TextField());\r
+    }\r
+\r
+    /**\r
+     * Case where the text field only uses its internal buffer, no external\r
+     * property data source.\r
+     */\r
+    public void testNoDataSource() {\r
+        getField().setPropertyDataSource(null);\r
+\r
+        expectValueChangeFromSetValueNotCommit();\r
+    }\r
+\r
+    @Override\r
+    protected void setValue(AbstractField field) {\r
+        Map<String, Object> variables = new HashMap<String, Object>();\r
+        variables.put("text", "newValue");\r
+        field.changeVariables(field, variables);\r
+    }\r
+\r
+}\r