package com.vaadin.v7.tests.server.component.abstractfield;
import org.easymock.EasyMock;
import org.junit.Test;
import com.vaadin.v7.data.Property.ValueChangeEvent;
import com.vaadin.v7.data.Property.ValueChangeListener;
import com.vaadin.v7.data.Property.ValueChangeNotifier;
import com.vaadin.v7.data.util.ObjectProperty;
import com.vaadin.v7.ui.AbstractField;
/**
* Base class for tests for checking that value change listeners for fields are
* not called exactly once when they should be, and not at other times.
*
* Does not check all cases (e.g. properties that do not implement
* {@link ValueChangeNotifier}).
*
* Subclasses should implement {@link #setValue()} and call
* <code>super.setValue(LegacyAbstractField)</code>. Also, subclasses should
* typically override {@link #setValue(AbstractField)} to set the field value
* via <code>changeVariables()</code>.
*/
public abstract class AbstractFieldValueChangeTestBase<T> {
private AbstractField<T> field;
private ValueChangeListener listener;
protected void setUp(AbstractField<T> field) {
this.field = field;
listener = EasyMock.createStrictMock(ValueChangeListener.class);
}
protected ValueChangeListener getListener() {
return listener;
}
/**
* Test that listeners are not called when they have been unregistered.
*/
@Test
public void testRemoveListener() {
getField().setPropertyDataSource(new ObjectProperty<String>(""));
getField().setBuffered(false);
// Expectations and start test
listener.valueChange(EasyMock.isA(ValueChangeEvent.class));
EasyMock.replay(listener);
// Add listener and set the value -> should end up in listener once
getField().addListener(listener);
setValue(getField());
// Ensure listener was called once
EasyMock.verify(listener);
// Remove the listener and set the value -> should not end up in
// listener
getField().removeListener(listener);
setValue(getField());
// Ensure listener still has been called only once
EasyMock.verify(listener);
}
/**
* Common unbuffered case: both writeThrough (auto-commit) and readThrough
* are on. Calling commit() should not cause notifications.
*
* Using the readThrough mode allows changes made to the property value to
* be seen in some cases also when there is no notification of value change
* from the property.
*
* LegacyField value change notifications closely mirror value changes of
* the data source behind the field.
*/
@Test
public void testNonBuffered() {
getField().setPropertyDataSource(new ObjectProperty<String>(""));
getField().setBuffered(false);
expectValueChangeFromSetValueNotCommit();
}
/**
* Fully buffered use where the data source is neither read nor modified
* during editing, and is updated at commit().
*
* LegacyField value change notifications reflect the buffered value in the
* field, not the original data source value changes.
*/
public void testBuffered() {
getField().setPropertyDataSource(new ObjectProperty<String>(""));
getField().setBuffered(true);
expectValueChangeFromSetValueNotCommit();
}
protected void expectValueChangeFromSetValueNotCommit() {
// Expectations and start test
listener.valueChange(EasyMock.isA(ValueChangeEvent.class));
EasyMock.replay(listener);
// Add listener and set the value -> should end up in listener once
getField().addListener(listener);
setValue(getField());
// Ensure listener was called once
EasyMock.verify(listener);
// commit
getField().commit();
// Ensure listener was not called again
EasyMock.verify(listener);
}
protected AbstractField<T> getField() {
return field;
}
/**
* Override in subclasses to set value with changeVariables().
*/
protected void setValue(AbstractField<T> field) {
field.setValue((T) "newValue");
}
}