Tue, 28 Jul 2020 14:27:14 +0200
bugfix: modified state is reset even when saving fails + more tests
1 package de.uapcore.sudoku;
3 import org.junit.jupiter.api.AfterEach;
4 import org.junit.jupiter.api.BeforeEach;
5 import org.junit.jupiter.api.Test;
7 import javax.swing.*;
8 import java.awt.*;
9 import java.awt.event.KeyEvent;
10 import java.lang.reflect.InvocationTargetException;
11 import java.util.concurrent.TimeUnit;
13 import static org.junit.jupiter.api.Assertions.*;
15 class SudokuTextFieldTest {
17 private void dispatch(SudokuTextField tf, KeyEvent pressed) {
18 final var released = new KeyEvent(tf, KeyEvent.KEY_RELEASED, pressed.getWhen()+1,
19 pressed.getModifiersEx(), pressed.getKeyCode(), pressed.getKeyChar());
20 final KeyEvent typed;
21 if (pressed.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
22 typed = new KeyEvent(tf, KeyEvent.KEY_TYPED, pressed.getWhen(),
23 pressed.getModifiersEx(), KeyEvent.VK_UNDEFINED, pressed.getKeyChar());
24 } else {
25 typed = null;
26 }
27 tf.requestFocusInWindow();
28 tf.dispatchEvent(pressed);
29 if (typed != null) {
30 tf.dispatchEvent(typed);
31 }
32 tf.dispatchEvent(released);
33 }
35 private JFrame testFrame;
37 @BeforeEach
38 void createTestFrame() {
39 // we have to use a visible frame for the events to be dispatched
40 testFrame = new JFrame();
41 testFrame.setVisible(true);
42 }
44 @AfterEach
45 void disposeTestFrame() {
46 testFrame.setVisible(false);
47 testFrame.dispose();
48 }
50 private SudokuTextField createTestSubject() {
51 final var tf = new SudokuTextField();
52 testFrame.add(tf);
53 return tf;
54 }
56 @Test
57 void setValue() {
58 // given
59 final var tf = createTestSubject();
60 for (int i = 0 ; i <= 9 ; i++) {
61 // when
62 tf.setValue(i);
63 // then
64 assertEquals(i, tf.getValue());
65 assertEquals(i == 0 ? "" : String.valueOf(i), tf.getText());
66 assertFalse(tf.isModified());
67 }
68 }
70 @Test
71 void setInvalidValue() {
72 // given
73 final var tf = createTestSubject();
74 // when / then
75 assertThrows(IllegalArgumentException.class, () -> tf.setValue(10));
76 assertThrows(IllegalArgumentException.class, () -> tf.setValue(-1));
77 assertFalse(tf.isModified());
78 }
80 @Test
81 void testModifiedByCall() {
82 // given
83 final var tf = createTestSubject();
84 // then initially
85 assertFalse(tf.isModified());
86 // when
87 tf.setModified(true);
88 // then
89 assertTrue(tf.isModified());
90 // when
91 tf.setModified(false);
92 // then
93 assertFalse(tf.isModified());
94 }
96 @Test
97 void testModifiedByKeystroke() throws InvocationTargetException, InterruptedException {
98 // given
99 final var tf = createTestSubject();
100 assertFalse(tf.isModified());
101 final var event = new KeyEvent(tf, KeyEvent.KEY_PRESSED, System.currentTimeMillis(),
102 0, KeyEvent.VK_4, '4');
103 SwingUtilities.invokeAndWait(() -> {
104 // when
105 dispatch(tf, event);
106 // then
107 assertTrue(tf.isModified());
108 });
109 }
111 @Test
112 void testTextChangeByKeystore() throws InvocationTargetException, InterruptedException {
113 // given
114 final var tf = createTestSubject();
115 assertEquals("", tf.getText());
116 final var event = new KeyEvent(tf, KeyEvent.KEY_PRESSED, System.currentTimeMillis(),
117 0, KeyEvent.VK_4, '4');
118 SwingUtilities.invokeAndWait(() -> {
119 // when
120 dispatch(tf, event);
121 // then
122 assertEquals("4", tf.getText());
123 });
124 }
126 @Test
127 void testNumpad() throws InvocationTargetException, InterruptedException {
128 // given
129 final var tf = createTestSubject();
130 assertEquals("", tf.getText());
131 final var event = new KeyEvent(tf, KeyEvent.KEY_PRESSED, System.currentTimeMillis(),
132 0, KeyEvent.VK_NUMPAD4, '4');
133 SwingUtilities.invokeAndWait(() -> {
134 // when
135 dispatch(tf, event);
136 // then
137 assertEquals("4", tf.getText());
138 });
139 }
141 @Test
142 void testTextOverwriteByKeystore() throws InvocationTargetException, InterruptedException {
143 // given
144 final var tf = createTestSubject();
145 tf.setText("6");
146 tf.selectAll();
147 final var event = new KeyEvent(tf, KeyEvent.KEY_PRESSED, System.currentTimeMillis(),
148 0, KeyEvent.VK_4, '4');
149 SwingUtilities.invokeAndWait(() -> {
150 // when
151 dispatch(tf, event);
152 // then
153 assertEquals("4", tf.getText());
154 });
155 }
157 @Test
158 void testNumbersOnly() throws InvocationTargetException, InterruptedException {
159 // given
160 final var tf = createTestSubject();
161 tf.setText("6");
162 tf.selectAll();
163 final var event = new KeyEvent(tf, KeyEvent.KEY_PRESSED, System.currentTimeMillis(),
164 0, KeyEvent.VK_A, 'a');
165 SwingUtilities.invokeAndWait(() -> {
166 // when
167 dispatch(tf, event);
168 // then
169 assertEquals("6", tf.getText());
170 });
171 }
173 @Test
174 void testSingleDigit() throws InvocationTargetException, InterruptedException {
175 // given
176 final var tf = createTestSubject();
177 assertEquals("", tf.getText());
178 final var firstEvent = new KeyEvent(tf, KeyEvent.KEY_PRESSED, System.currentTimeMillis(),
179 0, KeyEvent.VK_A, '4');
180 final var secondEvent = new KeyEvent(tf, KeyEvent.KEY_PRESSED, System.currentTimeMillis(),
181 0, KeyEvent.VK_A, '6');
182 SwingUtilities.invokeAndWait(() -> {
183 // when
184 dispatch(tf, firstEvent);
185 dispatch(tf, secondEvent);
186 // then
187 assertEquals("4", tf.getText());
188 });
189 }
191 @Test
192 void testBackspace() throws InvocationTargetException, InterruptedException {
193 // given
194 final var tf = createTestSubject();
195 assertEquals("", tf.getText());
196 final var typeFour = new KeyEvent(tf, KeyEvent.KEY_PRESSED, System.currentTimeMillis(),
197 0, KeyEvent.VK_A, '4');
198 final var typeBackspace = new KeyEvent(tf, KeyEvent.KEY_PRESSED, System.currentTimeMillis(),
199 0, KeyEvent.VK_BACK_SPACE, KeyEvent.CHAR_UNDEFINED);
200 final var typeSix = new KeyEvent(tf, KeyEvent.KEY_PRESSED, System.currentTimeMillis(),
201 0, KeyEvent.VK_A, '6');
202 SwingUtilities.invokeAndWait(() -> {
203 // when
204 dispatch(tf, typeFour);
205 dispatch(tf, typeBackspace);
206 dispatch(tf, typeSix);
207 // then
208 assertEquals("6", tf.getText());
209 });
210 }
212 @Test
213 void testFocusGained() throws InvocationTargetException, InterruptedException {
214 final var tf = createTestSubject();
215 SwingUtilities.invokeAndWait(() -> {
216 // given
217 tf.setText("5");
218 assertNull(tf.getSelectedText());
219 // when
220 tf.requestFocusInWindow();
221 });
222 // give WM time to deliver the event
223 TimeUnit.MILLISECONDS.sleep(100);
224 // then
225 SwingUtilities.invokeAndWait(() -> assertEquals("5", tf.getSelectedText()));
226 }
228 @Test
229 void testFocusLost() throws InvocationTargetException, InterruptedException {
230 final var tf = createTestSubject();
231 final var focusStealer = new TextField();
232 testFrame.add(focusStealer);
233 SwingUtilities.invokeAndWait(() -> {
234 // given
235 tf.setText("5");
236 tf.selectAll();
237 assertEquals("5", tf.getSelectedText());
238 // when
239 focusStealer.requestFocusInWindow();
240 });
241 // give WM time to deliver the event
242 TimeUnit.MILLISECONDS.sleep(100);
243 // then
244 SwingUtilities.invokeAndWait(() -> assertNull(tf.getSelectedText()));
245 }
247 @Test
248 void testFont() {
249 final var tf = new SudokuTextField();
250 assertEquals(18, tf.getFont().getSize());
251 }
253 @Test
254 void testAlignment() {
255 final var tf = new SudokuTextField();
256 assertEquals(JTextField.CENTER, tf.getHorizontalAlignment());
257 }
259 @Test
260 void testBackground() {
261 final var tf = new SudokuTextField();
262 assertEquals(Color.WHITE, tf.getBackground());
263 }
265 @Test
266 void testSize() {
267 final var tf = new SudokuTextField();
268 final var expected = new Dimension(40, 40);
269 assertEquals(expected, tf.getMinimumSize());
270 assertEquals(expected, tf.getPreferredSize());
271 assertEquals(expected, tf.getMaximumSize());
272 }
274 @Test
275 void testBorder() {
276 final var tf = new SudokuTextField();
277 assertNull(tf.getBorder());
278 }
279 }