93
93
* .awaitAndCheck();
94
94
* }
95
95
*
96
- * private static List< Window> createTestUI() {
96
+ * private static Window createTestUI() {
97
97
* JFrame testUI = new JFrame("Test UI");
98
98
* testUI.setSize(250, 150);
99
- * return List.of( testUI) ;
99
+ * return testUI;
100
100
* }
101
101
* }
102
102
* }</pre>
108
108
* the provided {@code createTestUI} on the Event Dispatch Thread (EDT),
109
109
* and it will automatically position the test UI and make it visible.
110
110
* <p>
111
+ * The {@code Builder.testUI} methods accept interfaces which create one window
112
+ * or a list of windows if the test needs multiple windows,
113
+ * or directly a single window, an array of windows or a list of windows.
114
+ * <p>
111
115
* Alternatively, use one of the {@code PassFailJFrame} constructors to
112
116
* create an object, then create secondary test UI, register it
113
117
* with {@code PassFailJFrame}, position it and make it visible.
144
148
* <li>to enable screenshots.</li>
145
149
* </ul>
146
150
*/
147
- public class PassFailJFrame {
151
+ public final class PassFailJFrame {
148
152
149
153
private static final String TITLE = "Test Instruction Frame" ;
150
154
private static final long TEST_TIMEOUT = 5 ;
@@ -263,12 +267,18 @@ private PassFailJFrame(Builder builder) throws InterruptedException,
263
267
this (builder .title , builder .instructions , builder .testTimeOut ,
264
268
builder .rows , builder .columns , builder .screenCapture );
265
269
266
- if (builder .windowCreator != null ) {
270
+ if (builder .windowListCreator != null ) {
267
271
invokeOnEDT (() ->
268
- builder .testWindows = builder .windowCreator .createTestUI ());
272
+ builder .testWindows = builder .windowListCreator .createTestUI ());
273
+ if (builder .testWindows == null ) {
274
+ throw new IllegalStateException ("Window list creator returned null list" );
275
+ }
269
276
}
270
277
271
278
if (builder .testWindows != null ) {
279
+ if (builder .testWindows .isEmpty ()) {
280
+ throw new IllegalStateException ("Window list is empty" );
281
+ }
272
282
addTestWindow (builder .testWindows );
273
283
builder .testWindows
274
284
.forEach (w -> w .addWindowListener (windowClosingHandler ));
@@ -279,17 +289,15 @@ private PassFailJFrame(Builder builder) throws InterruptedException,
279
289
builder .positionWindows
280
290
.positionTestWindows (unmodifiableList (builder .testWindows ),
281
291
builder .instructionUIHandler );
282
-
283
- windowList .forEach (w -> w .setVisible (true ));
284
292
});
285
293
} else if (builder .testWindows .size () == 1 ) {
286
294
Window window = builder .testWindows .get (0 );
287
295
positionTestWindow (window , builder .position );
288
- window .setVisible (true );
289
296
} else {
290
297
positionTestWindow (null , builder .position );
291
298
}
292
299
}
300
+ showAllWindows ();
293
301
}
294
302
295
303
/**
@@ -370,7 +378,7 @@ private static void createUI(String title, String instructions,
370
378
frame .add (buttonsPanel , BorderLayout .SOUTH );
371
379
frame .pack ();
372
380
frame .setLocationRelativeTo (null );
373
- windowList . add (frame );
381
+ addTestWindow (frame );
374
382
}
375
383
376
384
private static JTextComponent configurePlainText (String instructions ,
@@ -401,14 +409,27 @@ private static JTextComponent configureHTML(String instructions,
401
409
402
410
403
411
/**
404
- * Creates one or more windows for test UI.
412
+ * Creates a test UI window .
405
413
*/
406
414
@ FunctionalInterface
407
415
public interface WindowCreator {
416
+ /**
417
+ * Creates a window for test UI.
418
+ * This method is called by the framework on the EDT.
419
+ * @return a test UI window
420
+ */
421
+ Window createTestUI ();
422
+ }
423
+
424
+ /**
425
+ * Creates a list of test UI windows.
426
+ */
427
+ @ FunctionalInterface
428
+ public interface WindowListCreator {
408
429
/**
409
430
* Creates one or more windows for test UI.
410
431
* This method is called by the framework on the EDT.
411
- * @return a list of windows.
432
+ * @return a list of test UI windows
412
433
*/
413
434
List <? extends Window > createTestUI ();
414
435
}
@@ -424,8 +445,13 @@ public interface PositionWindows {
424
445
* the instruction UI frame was positioned on the screen.
425
446
* <p>
426
447
* The list of the test windows contains the windows
427
- * that were passed to the framework via
428
- * {@link Builder#testUI(WindowCreator) testUI} method.
448
+ * that were passed to the framework via the
449
+ * {@link Builder#testUI(Window...) testUI(Window...)} method or
450
+ * that were created with {@code WindowCreator}
451
+ * or {@code WindowListCreator} which were passed via
452
+ * {@link Builder#testUI(WindowCreator) testUI(WindowCreator)} or
453
+ * {@link Builder#testUI(WindowListCreator) testUI(WindowListCreator)}
454
+ * correspondingly.
429
455
*
430
456
* @param testWindows the list of test windows
431
457
* @param instructionUI information about the instruction frame
@@ -799,6 +825,29 @@ public static synchronized void addTestWindow(Collection<? extends Window> testW
799
825
windowList .addAll (testWindows );
800
826
}
801
827
828
+ /**
829
+ * Displays all the windows in {@code windowList}.
830
+ *
831
+ * @throws InterruptedException if the thread is interrupted while
832
+ * waiting for the event dispatch thread to finish running
833
+ * the {@link #showUI() showUI}
834
+ * @throws InvocationTargetException if an exception is thrown while
835
+ * the event dispatch thread executes {@code showUI}
836
+ */
837
+ private static void showAllWindows ()
838
+ throws InterruptedException , InvocationTargetException {
839
+ invokeOnEDT (PassFailJFrame ::showUI );
840
+ }
841
+
842
+ /**
843
+ * Displays all the windows in {@code windowList}; it has to be called on
844
+ * the EDT — use {@link #showAllWindows() showAllWindows} to ensure it.
845
+ */
846
+ private static synchronized void showUI () {
847
+ windowList .forEach (w -> w .setVisible (true ));
848
+ }
849
+
850
+
802
851
/**
803
852
* Forcibly pass the test.
804
853
* <p>The sample usage:
@@ -841,7 +890,7 @@ public static final class Builder {
841
890
private boolean screenCapture ;
842
891
843
892
private List <? extends Window > testWindows ;
844
- private WindowCreator windowCreator ;
893
+ private WindowListCreator windowListCreator ;
845
894
private PositionWindows positionWindows ;
846
895
private InstructionUI instructionUIHandler ;
847
896
@@ -877,39 +926,109 @@ public Builder screenCapture() {
877
926
return this ;
878
927
}
879
928
929
+ /**
930
+ * Adds a {@code WindowCreator} which the framework will use
931
+ * to create the test UI window.
932
+ *
933
+ * @param windowCreator a {@code WindowCreator}
934
+ * to create the test UI window
935
+ * @return this builder
936
+ * @throws IllegalArgumentException if {@code windowCreator} is {@code null}
937
+ * @throws IllegalStateException if a window creator
938
+ * or a list of test windows is already set
939
+ */
940
+ public Builder testUI (WindowCreator windowCreator ) {
941
+ if (windowCreator == null ) {
942
+ throw new IllegalArgumentException ("The window creator can't be null" );
943
+ }
944
+
945
+ checkWindowsLists ();
946
+
947
+ this .windowListCreator = () -> List .of (windowCreator .createTestUI ());
948
+ return this ;
949
+ }
950
+
951
+ /**
952
+ * Adds a {@code WindowListCreator} which the framework will use
953
+ * to create a list of test UI windows.
954
+ *
955
+ * @param windowListCreator a {@code WindowListCreator}
956
+ * to create test UI windows
957
+ * @return this builder
958
+ * @throws IllegalArgumentException if {@code windowListCreator} is {@code null}
959
+ * @throws IllegalStateException if a window creator
960
+ * or a list of test windows is already set
961
+ */
962
+ public Builder testUI (WindowListCreator windowListCreator ) {
963
+ if (windowListCreator == null ) {
964
+ throw new IllegalArgumentException ("The window list creator can't be null" );
965
+ }
966
+
967
+ checkWindowsLists ();
968
+
969
+ this .windowListCreator = windowListCreator ;
970
+ return this ;
971
+ }
972
+
973
+ /**
974
+ * Adds an already created test UI window.
975
+ * The window is positioned and shown automatically.
976
+ *
977
+ * @param window a test UI window
978
+ * @return this builder
979
+ */
880
980
public Builder testUI (Window window ) {
881
981
return testUI (List .of (window ));
882
982
}
883
983
984
+ /**
985
+ * Adds an array of already created test UI windows.
986
+ *
987
+ * @param windows an array of test UI windows
988
+ * @return this builder
989
+ */
884
990
public Builder testUI (Window ... windows ) {
885
991
return testUI (List .of (windows ));
886
992
}
887
993
888
- public Builder testUI (List <Window > windows ) {
994
+ /**
995
+ * Adds a list of already created test UI windows.
996
+ *
997
+ * @param windows a list of test UI windows
998
+ * @return this builder
999
+ * @throws IllegalArgumentException if {@code windows} is {@code null}
1000
+ * or the list contains {@code null}
1001
+ * @throws IllegalStateException if a window creator
1002
+ * or a list of test windows is already set
1003
+ */
1004
+ public Builder testUI (List <? extends Window > windows ) {
889
1005
if (windows == null ) {
890
1006
throw new IllegalArgumentException ("The list of windows can't be null" );
891
1007
}
892
1008
if (windows .stream ()
893
1009
.anyMatch (Objects ::isNull )) {
894
- throw new IllegalArgumentException ("The windows list can't contain null" );
1010
+ throw new IllegalArgumentException ("The list of windows can't contain null" );
895
1011
}
896
1012
897
- if (windowCreator != null ) {
898
- throw new IllegalStateException ("windowCreator is already set" );
899
- }
1013
+ checkWindowsLists ();
1014
+
900
1015
this .testWindows = windows ;
901
1016
return this ;
902
1017
}
903
1018
904
- public Builder testUI (WindowCreator windowCreator ) {
905
- if (windowCreator == null ) {
906
- throw new IllegalArgumentException ("The window creator can't be null" );
1019
+ /**
1020
+ * Verifies the state of window list and window creator.
1021
+ *
1022
+ * @throws IllegalStateException if a windows list creator
1023
+ * or a list of test windows is already set
1024
+ */
1025
+ private void checkWindowsLists () {
1026
+ if (windowListCreator != null ) {
1027
+ throw new IllegalStateException ("Window list creator is already set" );
907
1028
}
908
1029
if (testWindows != null ) {
909
- throw new IllegalStateException ("testWindows are already set" );
1030
+ throw new IllegalStateException ("The list of test windows is already set" );
910
1031
}
911
- this .windowCreator = windowCreator ;
912
- return this ;
913
1032
}
914
1033
915
1034
public Builder positionTestUI (PositionWindows positionWindows ) {
@@ -951,13 +1070,13 @@ private void validate() {
951
1070
}
952
1071
953
1072
if (position == null
954
- && (testWindows != null || windowCreator != null )) {
1073
+ && (testWindows != null || windowListCreator != null )) {
955
1074
956
1075
position = Position .HORIZONTAL ;
957
1076
}
958
1077
959
1078
if (positionWindows != null ) {
960
- if (testWindows == null && windowCreator == null ) {
1079
+ if (testWindows == null && windowListCreator == null ) {
961
1080
throw new IllegalStateException ("To position windows, "
962
1081
+ "provide an a list of windows to the builder" );
963
1082
}
0 commit comments