88
99import javax .swing .*;
1010import java .awt .*;
11+ import java .awt .event .MouseEvent ;
1112import java .awt .event .MouseListener ;
1213import java .awt .event .MouseMotionListener ;
1314import java .io .IOException ;
1415import java .nio .file .Files ;
1516import java .nio .file .Path ;
1617import java .util .Arrays ;
18+ import java .util .List ;
1719
1820import static java .nio .file .Files .deleteIfExists ;
1921import static org .assertj .core .api .BDDAssertions .then ;
@@ -26,9 +28,12 @@ class EditorTest {
2628
2729 private static final String TEST_LEVEL_NAME = "testEditorLevel" ;
2830 private static final Path TEST_LEVEL_PATH = Path .of ("levels" , TEST_LEVEL_NAME + ".txt" );
31+
2932 private static final int TEST_ROWS = 10 ;
3033 private static final int TEST_COLUMNS = 10 ;
31-
34+
35+ private static final int Y_OFFSET = Editor .TILE_SIZE ; // Vertical offset for grid positioning
36+
3237 private Editor editor ;
3338
3439 @ BeforeEach
@@ -83,85 +88,147 @@ void editor_has_required_components() {
8388 void editor_has_correct_mouse_listeners () {
8489 MouseListener [] mouseListeners = editor .getMouseListeners ();
8590 then (mouseListeners .length ).isPositive ();
86-
91+
8792 MouseMotionListener [] mouseMotionListeners = editor .getMouseMotionListeners ();
8893 then (mouseMotionListeners .length ).isPositive ();
8994 }
90-
95+
9196 @ Test
9297 void player_button_sets_content_to_worker_on_floor () {
9398 // Given
9499 JButton button = findComponentByNameAsType (editor , Editor .Component .PLAYER_BUTTON .name (), JButton .class );
95-
100+
96101 // When - Simulate button click
97102 button .doClick ();
98-
103+
99104 then (editor .getContent ()).isEqualTo (TileType .WORKER_ON_FLOOR );
100105 }
101106
107+ @ Test
108+ void save_button_saves_valid_level () throws Exception {
109+ // Given
110+ // Set up a valid level with one player, one box, and one target
111+ JButton playerButton = findComponentByNameAsType (editor , Editor .Component .PLAYER_BUTTON .name (), JButton .class );
112+ JButton boxButton = findComponentByNameAsType (editor , Editor .Component .BOX_BUTTON .name (), JButton .class );
113+ JButton targetButton = findComponentByNameAsType (editor , Editor .Component .TARGET_BUTTON .name (), JButton .class );
114+ JButton saveButton = findComponentByNameAsType (editor , Editor .Component .SAVE_BUTTON .name (), JButton .class );
115+
116+ // Add elements at their expected positions
117+ playerButton .doClick ();
118+ var player = new ExpectedAt (1 , 1 );
119+ editor .mousePressed (mouseEventAt (
120+ Editor .X_OFFSET + player .x * Editor .TILE_SIZE ,
121+ Y_OFFSET + player .y * Editor .TILE_SIZE
122+ ));
123+
124+ boxButton .doClick ();
125+ var box = new ExpectedAt (2 , 2 );
126+ editor .mousePressed (mouseEventAt (
127+ Editor .X_OFFSET + box .x * Editor .TILE_SIZE ,
128+ Y_OFFSET + box .y * Editor .TILE_SIZE
129+ ));
130+
131+ targetButton .doClick ();
132+ var target = new ExpectedAt (3 , 3 );
133+ editor .mousePressed (mouseEventAt (
134+ Editor .X_OFFSET + target .x * Editor .TILE_SIZE ,
135+ Y_OFFSET + target .y * Editor .TILE_SIZE
136+ ));
137+
138+ // When
139+ saveButton .doClick ();
140+
141+ // Then - Verify the file was created and contains valid content
142+ then (TEST_LEVEL_PATH ).exists ();
143+ List <String > lines = Files .readAllLines (TEST_LEVEL_PATH );
144+
145+ then (lines ).hasSize (TEST_ROWS );
146+ then (lines ).allSatisfy (line ->
147+ then (line .length ()).isEqualTo (TEST_COLUMNS )
148+ );
149+
150+ // Verify the level contains the expected characters (converted from tile types)
151+ then (lines .get (player .y ).charAt (player .x )) .isEqualTo (TileType .WORKER_ON_FLOOR .getCode ());
152+ then (lines .get (box .y ).charAt (box .x )) .isEqualTo (TileType .UNSTORED_BOX .getCode ());
153+ then (lines .get (target .y ).charAt (target .x )) .isEqualTo (TileType .STORAGE_AREA .getCode ());
154+ }
155+
156+ private MouseEvent mouseEventAt (int x , int y ) {
157+ return new MouseEvent (
158+ editor , // Component source
159+ MouseEvent .MOUSE_PRESSED , // Event type
160+ System .currentTimeMillis (), // When
161+ 0 , // No modifiers
162+ x , // x-coordinate
163+ y , // y-coordinate
164+ 1 , // Click count
165+ false // Popup trigger
166+ );
167+ }
168+
102169 @ Test
103170 void background_button_sets_content_to_outside () {
104171 // Given
105172 JButton button = findComponentByNameAsType (editor , Editor .Component .BACKGROUND_BUTTON .name (), JButton .class );
106-
173+
107174 // When - Simulate button click
108175 button .doClick ();
109-
176+
110177 then (editor .getContent ()).isEqualTo (TileType .OUTSIDE );
111178 }
112179
113180 @ Test
114181 void box_button_sets_content_to_unstored_box () {
115182 // Given
116183 JButton button = findComponentByNameAsType (editor , Editor .Component .BOX_BUTTON .name (), JButton .class );
117-
184+
118185 // When - Simulate button click
119186 button .doClick ();
120-
187+
121188 then (editor .getContent ()).isEqualTo (TileType .UNSTORED_BOX );
122189 }
123190
124191 @ Test
125192 void box_on_target_button_sets_content_to_stored_box () {
126193 // Given
127194 JButton button = findComponentByNameAsType (editor , Editor .Component .BOX_ON_TARGET_BUTTON .name (), JButton .class );
128-
195+
129196 // When - Simulate button click
130197 button .doClick ();
131-
198+
132199 then (editor .getContent ()).isEqualTo (TileType .STORED_BOX );
133200 }
134201
135202 @ Test
136203 void player_on_target_button_sets_content_to_worker_in_storage_area () {
137204 // Given
138205 JButton button = findComponentByNameAsType (editor , Editor .Component .PLAYER_ON_TARGET_BUTTON .name (), JButton .class );
139-
206+
140207 // When - Simulate button click
141208 button .doClick ();
142-
209+
143210 then (editor .getContent ()).isEqualTo (TileType .WORKER_IN_STORAGE_AREA );
144211 }
145212
146213 @ Test
147214 void wall_button_sets_content_to_wall () {
148215 // Given
149216 JButton button = findComponentByNameAsType (editor , Editor .Component .WALL_BUTTON .name (), JButton .class );
150-
217+
151218 // When - Simulate button click
152219 button .doClick ();
153-
220+
154221 then (editor .getContent ()).isEqualTo (TileType .WALL );
155222 }
156223
157224 @ Test
158225 void target_button_sets_content_to_storage_area () {
159226 // Given
160227 JButton button = findComponentByNameAsType (editor , Editor .Component .TARGET_BUTTON .name (), JButton .class );
161-
228+
162229 // When - Simulate button click
163230 button .doClick ();
164-
231+
165232 then (editor .getContent ()).isEqualTo (TileType .STORAGE_AREA );
166233 }
167234
@@ -241,4 +308,10 @@ ExitHandler defaultExitHandler() {
241308 then (Files .exists (TEST_LEVEL_PATH )).isFalse ();
242309 verify (mockExitHandler ).exit (ExitHandler .SUCCESS );
243310 }
311+
312+ /**
313+ * Represents expected positions in the test grid.
314+ */
315+ private record ExpectedAt (int x , int y ) {
316+ }
244317}
0 commit comments