ObservableControllerTest.java 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. package org.leumasjaffe.observer;
  2. import static org.junit.jupiter.api.Assertions.*;
  3. import static org.mockito.Mockito.*;
  4. import java.util.function.BiConsumer;
  5. import java.util.function.BiFunction;
  6. import java.util.function.Consumer;
  7. import javax.swing.JFormattedTextField;
  8. import javax.swing.JTextField;
  9. import org.junit.jupiter.api.BeforeEach;
  10. import org.junit.jupiter.api.Test;
  11. import org.junit.jupiter.api.extension.ExtendWith;
  12. import org.mockito.Mock;
  13. import org.mockito.Spy;
  14. import org.mockito.junit.jupiter.MockitoExtension;
  15. @ExtendWith(MockitoExtension.class)
  16. class ObservableControllerTest extends SwingTestCase {
  17. private static class Value extends Observable.Instance {
  18. String str = "<INIT>";
  19. String get() { return str; }
  20. void set(String value) { this.str = value; }
  21. }
  22. @Spy MockObserverListener signal;
  23. @Mock Consumer<Value> onEmpty;
  24. @Spy Value value;
  25. @Spy JTextField component;
  26. @Spy JFormattedTextField formatted;
  27. @BeforeEach
  28. void setUp() {
  29. signal.setObserved(value);
  30. clearInvocations(signal);
  31. }
  32. @Test
  33. void testThrowsOnNullForAnythingButEmptyHandler() {
  34. assertThrows(NullPointerException.class,
  35. () -> ObservableController.from((JTextField) null, Value::get, Value::set));
  36. assertThrows(NullPointerException.class,
  37. () -> ObservableController.<JFormattedTextField, Value, String>from(null, Value::get, Value::set));
  38. assertThrows(NullPointerException.class,
  39. () -> ObservableController.from(component, null, Value::set));
  40. assertThrows(NullPointerException.class,
  41. () -> ObservableController.from(component, Value::get, null));
  42. assertThrows(NullPointerException.class,
  43. () -> ObservableController.from(null, (str, model) -> false, (comp, model) -> {}));
  44. assertThrows(NullPointerException.class,
  45. () -> ObservableController.from(component, (BiFunction<String, Value, Boolean>) null, (comp, model) -> {}));
  46. assertThrows(NullPointerException.class,
  47. () -> ObservableController.from(component, (str, model) -> false, null));
  48. assertThrows(NullPointerException.class,
  49. () -> ObservableController.from((JTextField) null, Value::get, Value::set, null));
  50. assertThrows(NullPointerException.class,
  51. () -> ObservableController.from(null, Value::get, Value::set, (String) null));
  52. assertThrows(NullPointerException.class,
  53. () -> ObservableController.from(component, null, Value::set, null));
  54. assertThrows(NullPointerException.class,
  55. () -> ObservableController.from(component, Value::get, null, null));
  56. assertThrows(NullPointerException.class,
  57. () -> ObservableController.from(null, (str, model) -> false, (comp, model) -> {}, null));
  58. assertThrows(NullPointerException.class,
  59. () -> ObservableController.from(component, (BiFunction<String, Value, Boolean>) null, (comp, model) -> {}, null));
  60. assertThrows(NullPointerException.class,
  61. () -> ObservableController.from(component, (str, model) -> false, null, null));
  62. assertDoesNotThrow(() -> ObservableController.from(component, Value::get, Value::set));
  63. assertDoesNotThrow(() -> ObservableController.from(component, Value::get, Value::set, null));
  64. assertDoesNotThrow(() -> ObservableController.from(component, (str, model) -> false, (comp, model) -> {}));
  65. assertDoesNotThrow(() -> ObservableController.from(component, (str, model) -> false, (comp, model) -> {}, null));
  66. assertDoesNotThrow(() -> ObservableController.<JFormattedTextField, Value, String>from(formatted, Value::get, Value::set));
  67. assertDoesNotThrow(() -> ObservableController.from(formatted, Value::get, Value::set, (String) null));
  68. }
  69. @Test
  70. void testCanLinkComponentToObjectBeanlike() {
  71. final ObservableListener<JTextField, Value> listener =
  72. ObservableController.from(component, Value::get, Value::set);
  73. listener.setObserved(value);
  74. verify(component).setText("<INIT>");
  75. component.setText("Hello");
  76. waitForSwing();
  77. verify(value).set(eq("Hello"));
  78. verify(signal).updateWasSignalled();
  79. }
  80. @Test
  81. void testWillNotSignalOnNonChangingOperation() {
  82. final ObservableListener<JTextField, Value> listener =
  83. ObservableController.from(component, Value::get, Value::set);
  84. listener.setObserved(value);
  85. component.setText("<INIT>");
  86. waitForSwing();
  87. verify(signal, never()).updateWasSignalled();
  88. verify(value, never()).set(eq("<INIT>"));
  89. }
  90. @Test
  91. void testWillNotFireUpdateIfModelHasNotChanged() {
  92. final ObservableListener<JTextField, Value> listener =
  93. ObservableController.from(component, Value::get, Value::set);
  94. listener.setObserved(value);
  95. ObserverDispatch.notifySubscribers(value);
  96. verify(component, times(1)).setText("<INIT>");
  97. }
  98. @Test
  99. void testByDefaultWeIgnoreEmptyString() {
  100. final ObservableListener<JTextField, Value> listener =
  101. ObservableController.from(component, Value::get, Value::set);
  102. listener.setObserved(value);
  103. component.setText("");
  104. waitForSwing();
  105. verify(value, never()).set(eq(""));
  106. verify(signal, never()).updateWasSignalled();
  107. }
  108. @Test
  109. void testCanProvideEmptyStringHandler() {
  110. final ObservableListener<JTextField, Value> listener =
  111. ObservableController.from(component, Value::get, Value::set,
  112. onEmpty);
  113. listener.setObserved(value);
  114. component.setText("");
  115. waitForSwing();
  116. verify(onEmpty).accept(same(value));
  117. verify(signal, never()).updateWasSignalled();
  118. }
  119. @Test
  120. void testIfUpdateModelReturnsFalseThenWeDontSignal() {
  121. final ObservableListener<JTextField, Value> listener =
  122. ObservableController.from(component, (str, model) -> false,
  123. (comp, model) -> {});
  124. listener.setObserved(value);
  125. component.setText("Something");
  126. waitForSwing();
  127. verify(signal, never()).updateWasSignalled();
  128. }
  129. @Test
  130. void testIfUpdateModelReturnsTrueThenWeSignal() {
  131. final ObservableListener<JTextField, Value> listener =
  132. ObservableController.from(component, (str, model) -> true,
  133. (comp, model) -> {});
  134. listener.setObserved(value);
  135. component.setText("Something");
  136. waitForSwing();
  137. verify(signal).updateWasSignalled();
  138. }
  139. @Test
  140. void testIfSignalledThenConsumerIsInvoked() {
  141. @SuppressWarnings("unchecked")
  142. BiConsumer<JTextField, Value> updateComp = mock(BiConsumer.class);
  143. final ObservableListener<JTextField, Value> listener =
  144. ObservableController.from(component, (str, model) -> false,
  145. updateComp);
  146. listener.setObserved(value);
  147. ObserverDispatch.notifySubscribers(value);
  148. verify(updateComp, times(2)).accept(same(component), same(value));
  149. }
  150. @Test
  151. void testFormattedAffectValueOverText() {
  152. final ObservableListener<JFormattedTextField, Value> listener =
  153. ObservableController.<JFormattedTextField, Value, String>from(
  154. formatted, Value::get, Value::set);
  155. listener.setObserved(value);
  156. value.set("1");
  157. ObserverDispatch.notifySubscribers(value);
  158. verify(formatted).setValue(eq("1"));
  159. }
  160. @Test
  161. void testFormattedManipulatingTextDoesntPropogate() {
  162. final ObservableListener<JFormattedTextField, Value> listener =
  163. ObservableController.<JFormattedTextField, Value, String>from(
  164. formatted, Value::get, Value::set);
  165. listener.setObserved(value);
  166. formatted.setText("1");
  167. waitForSwing();
  168. verify(value, never()).set(eq("1"));
  169. }
  170. @Test
  171. void testFormattedManipulatingValuePropogates() {
  172. final ObservableListener<JFormattedTextField, Value> listener =
  173. ObservableController.<JFormattedTextField, Value, String>from(
  174. formatted, Value::get, Value::set);
  175. listener.setObserved(value);
  176. formatted.setValue("1");
  177. waitForSwing();
  178. verify(value).set(eq("1"));
  179. }
  180. @Test
  181. void testFormattedManipulatingValueDoesNothingWhenEqual() {
  182. final ObservableListener<JFormattedTextField, Value> listener =
  183. ObservableController.<JFormattedTextField, Value, String>from(
  184. formatted, Value::get, Value::set);
  185. listener.setObserved(value);
  186. formatted.setValue("<INIT>");
  187. waitForSwing();
  188. verify(value, never()).set(any());
  189. }
  190. @Test
  191. void testFormattedManipulatingModelDoesNothingWhenEqual() {
  192. final ObservableListener<JFormattedTextField, Value> listener =
  193. ObservableController.<JFormattedTextField, Value, String>from(
  194. formatted, Value::get, Value::set);
  195. listener.setObserved(value);
  196. clearInvocations(formatted);
  197. ObserverDispatch.notifySubscribers(value);
  198. verify(formatted, never()).setValue(any());
  199. }
  200. @Test
  201. void testFormattedCanProvideEmptyStringHandler() {
  202. final ObservableListener<JFormattedTextField, Value> listener =
  203. ObservableController.from(formatted, Value::get, Value::set,
  204. onEmpty);
  205. listener.setObserved(value);
  206. formatted.setValue("");
  207. waitForSwing();
  208. verify(onEmpty).accept(same(value));
  209. verify(signal, never()).updateWasSignalled();
  210. }
  211. @Test
  212. void testFormattedCanProvideDefaultValueOnEmpty() {
  213. final ObservableListener<JFormattedTextField, Value> listener =
  214. ObservableController.from(formatted, Value::get, Value::set,
  215. "<DEFAULT>");
  216. listener.setObserved(value);
  217. formatted.setValue("");
  218. waitForSwing();
  219. verify(signal, never()).updateWasSignalled();
  220. verify(value).set(eq("<DEFAULT>"));
  221. verify(value, never()).set(eq(""));
  222. }
  223. }