From acf76d4312adf29adf919b1472f72a93bb79f2c6 Mon Sep 17 00:00:00 2001 From: nicho <3013379@stud.hs-mannheim.de> Date: Tue, 7 Jan 2025 02:20:28 +0100 Subject: [PATCH] TEST UND POM FUNKTIONIEREN --- src/test/java/GameBaseTest.java | 83 +++++++++++ src/test/java/GameUIControllerTest.java | 146 ++++++++++++++++++++ src/test/java/HitoriBoardPanelTest.java | 81 +++++++++++ src/test/java/HitoriControlPanelTest.java | 126 +++++++++++++++++ src/test/java/HitoriDialogManagerTest.java | 63 +++++++++ src/test/java/HitoriGameMovesTest.java | 130 ++++++++++++++++++ src/test/java/HitoriGameScoresTest.java | 116 ++++++++++++++++ src/test/java/HitoriGameSolverTest.java | 127 +++++++++++++++++ src/test/java/HitoriGameTest.java | 151 +++++++++++++++++++++ src/test/java/HitoriGameTimerTest.java | 131 ++++++++++++++++++ src/test/java/HitoriScorePanelTest.java | 77 +++++++++++ 11 files changed, 1231 insertions(+) create mode 100644 src/test/java/GameBaseTest.java create mode 100644 src/test/java/GameUIControllerTest.java create mode 100644 src/test/java/HitoriBoardPanelTest.java create mode 100644 src/test/java/HitoriControlPanelTest.java create mode 100644 src/test/java/HitoriDialogManagerTest.java create mode 100644 src/test/java/HitoriGameMovesTest.java create mode 100644 src/test/java/HitoriGameScoresTest.java create mode 100644 src/test/java/HitoriGameSolverTest.java create mode 100644 src/test/java/HitoriGameTest.java create mode 100644 src/test/java/HitoriGameTimerTest.java create mode 100644 src/test/java/HitoriScorePanelTest.java diff --git a/src/test/java/GameBaseTest.java b/src/test/java/GameBaseTest.java new file mode 100644 index 0000000..99754e5 --- /dev/null +++ b/src/test/java/GameBaseTest.java @@ -0,0 +1,83 @@ +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +class GameBaseTest { + private domain.GameBase game; + private static final int[][] TEST_BOARD = { + {1, 2, 1, 3}, + {3, 1, 2, 1}, + {2, 3, 3, 2}, + {1, 2, 1, 3} + }; + + @BeforeEach + void setUp() { + game = new domain.GameBase(TEST_BOARD); + } + + @Test + void testInitialization() { + assertNotNull(game); + assertArrayEquals(TEST_BOARD, game.getBoard()); + assertEquals(0, game.getMistakeCount()); + } + + @Test + void testReset() { + // Directly set some cells (since we can't use markCell methods in base class) + game.blackCells[0][0] = true; + game.whiteCells[1][1] = true; + + // Reset game + game.reset(); + + // Verify all cells are reset + boolean[][] blackCells = game.getBlackCells(); + boolean[][] whiteCells = game.getWhiteCells(); + + for (int i = 0; i < TEST_BOARD.length; i++) { + for (int j = 0; j < TEST_BOARD[0].length; j++) { + assertFalse(blackCells[i][j], "Black cell at [" + i + "][" + j + "] should be false"); + assertFalse(whiteCells[i][j], "White cell at [" + i + "][" + j + "] should be false"); + } + } + + assertEquals(0, game.getMistakeCount()); + } + + + + @Test + void testGetCurrentState() { + int[][] currentState = game.getCurrentState(); + assertArrayEquals(TEST_BOARD, currentState); + } + + @Test + void testGetBlackCells() { + boolean[][] blackCells = game.getBlackCells(); + assertNotNull(blackCells); + assertEquals(TEST_BOARD.length, blackCells.length); + assertEquals(TEST_BOARD[0].length, blackCells[0].length); + } + + @Test + void testGetWhiteCells() { + boolean[][] whiteCells = game.getWhiteCells(); + assertNotNull(whiteCells); + assertEquals(TEST_BOARD.length, whiteCells.length); + assertEquals(TEST_BOARD[0].length, whiteCells[0].length); + } + + @Test + void testGetMistakeCount() { + assertEquals(0, game.getMistakeCount()); + } + + @Test + void testBoardDimensions() { + int[][] board = game.getBoard(); + assertEquals(TEST_BOARD.length, board.length); + assertEquals(TEST_BOARD[0].length, board[0].length); + } +} \ No newline at end of file diff --git a/src/test/java/GameUIControllerTest.java b/src/test/java/GameUIControllerTest.java new file mode 100644 index 0000000..7466438 --- /dev/null +++ b/src/test/java/GameUIControllerTest.java @@ -0,0 +1,146 @@ +import GUI.GameUIController; +import GUI.HitoriDialogManager; +import javafx.stage.Stage; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.extension.ExtendWith; +import org.testfx.framework.junit5.ApplicationExtension; +import org.testfx.framework.junit5.Start; + +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; +import java.util.Optional; + +@ExtendWith(ApplicationExtension.class) +class GameUIControllerTest { + private GameUIController controller; + private HitoriDialogManager dialogManager; + private Stage stage; + private static final int[][] TEST_BOARD = { + {1, 2, 1}, + {2, 1, 2}, + {1, 2, 1} + }; + + @Start + private void start(Stage stage) { + this.stage = stage; + } + + @BeforeEach + void setUp() { + dialogManager = mock(HitoriDialogManager.class); + controller = new GameUIController(TEST_BOARD, dialogManager); + } + + @Test + void testInitialization() { + assertNotNull(controller); + assertNotNull(controller.getBoardPanel()); + assertNotNull(controller.getControlPanel()); + assertNotNull(controller.getScorePanel()); + assertFalse(controller.isPaused()); + } + + @Test + void testHandleLeftClick() { + controller.handleLeftClick(0, 0); + // Verify the board was updated + assertTrue(controller.getBoardPanel().getChildren().size() > 0); + } + + @Test + void testHandleRightClick() { + controller.handleRightClick(0, 0); + // Verify the board was updated + assertTrue(controller.getBoardPanel().getChildren().size() > 0); + } + + @Test + void testTogglePause() { + assertFalse(controller.isPaused()); + controller.togglePause(); + assertTrue(controller.isPaused()); + controller.togglePause(); + assertFalse(controller.isPaused()); + } + + @Test + void testResetGame() { + // Make some moves first + controller.handleLeftClick(0, 0); + controller.handleRightClick(1, 1); + + controller.resetGame(); + // Verify the board is reset + var boardPanel = controller.getBoardPanel(); + assertEquals(9, boardPanel.getChildren().size()); // 3x3 board + } + + @Test + void testUndoRedo() { + controller.handleLeftClick(0, 0); + controller.undo(); + controller.redo(); + // Verify the board state + assertTrue(controller.getBoardPanel().getChildren().size() > 0); + } + + @Test + void testShowErrors() { + // Create some errors first + controller.handleLeftClick(0, 0); + controller.handleLeftClick(0, 1); + + controller.showErrors(); + verify(dialogManager, times(1)).showAlert(anyString(), anyString()); + } + + @Test + void testSaveGame() { + controller.saveGame(); + verify(dialogManager).showAlert(eq("Game Saved"), anyString()); + } + + @Test + void testDeleteHighScores() { + when(dialogManager.confirmDeleteHighScores()).thenReturn(true); + controller.deleteHighScores(); + verify(dialogManager).showAlert(eq("High Scores Deleted"), anyString()); + } + + + + @Test + void testConvertErrorsToSet() { + List errors = List.of( + new int[]{0, 0}, + new int[]{1, 1} + ); + var errorSet = controller.convertErrorsToSet(errors); + assertTrue(errorSet.contains("0,0")); + assertTrue(errorSet.contains("1,1")); + } + + @Test + void testCleanup() { + controller.cleanup(); + assertFalse(controller.isPaused()); + } + + // Helper method to simulate winning moves + private void makeWinningMoves() { + // This would need to be implemented according to your winning condition + // For test purposes, we'll just make some moves + controller.handleLeftClick(0, 2); + controller.handleRightClick(0, 0); + controller.handleRightClick(0, 1); + controller.handleRightClick(1, 0); + controller.handleRightClick(1, 1); + controller.handleRightClick(1, 2); + controller.handleRightClick(2, 0); + controller.handleRightClick(2, 1); + controller.handleLeftClick(2, 2); + } +} diff --git a/src/test/java/HitoriBoardPanelTest.java b/src/test/java/HitoriBoardPanelTest.java new file mode 100644 index 0000000..a8b8442 --- /dev/null +++ b/src/test/java/HitoriBoardPanelTest.java @@ -0,0 +1,81 @@ +import domain.GameSolver; +import domain.HitoriGameMoves; +import GUI.GameUIController; +import GUI.HitoriBoardPanel; +import javafx.scene.control.Button; +import org.junit.jupiter.api.*; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import org.junit.jupiter.api.extension.ExtendWith; +import org.testfx.framework.junit5.ApplicationExtension; +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(ApplicationExtension.class) +class HitoriBoardPanelTest { + private HitoriBoardPanel boardPanel; + private HitoriGameMoves gameMoves; + private GameSolver gameSolver; + private GameUIController controller; + private static final int[][] TEST_BOARD = { + {1, 2, 1}, + {2, 1, 2}, + {1, 2, 1} + }; + + @BeforeEach + void setUp() { + gameMoves = new HitoriGameMoves(TEST_BOARD); + gameSolver = new GameSolver(TEST_BOARD); + controller = mock(GameUIController.class); + boardPanel = new HitoriBoardPanel(gameMoves, gameSolver, controller); + } + + @Test + void testInitialization() { + assertNotNull(boardPanel); + assertEquals(9, boardPanel.getChildren().size()); // 3x3 board = 9 buttons + } + + @Test + void testCellCreation() { + var children = boardPanel.getChildren(); + var firstButton = (Button) children.get(0); + assertEquals("1", firstButton.getText()); + } + + @Test + void testButtonStyling() { + var children = boardPanel.getChildren(); + var button = (Button) children.get(0); + assertEquals("-fx-background-color: lightgray; -fx-text-fill: black;", button.getStyle()); + } + + @Test + void testUpdateBoard() { + boardPanel.updateBoard(); + assertEquals(9, boardPanel.getChildren().size()); + } + + @Test + void testShowErrors() { + // Mark some cells as black to create errors + gameMoves.markCellAsBlack(0, 0); + gameMoves.markCellAsBlack(0, 1); + + boardPanel.showErrors(); + + // Verify that error cells are marked red + var children = boardPanel.getChildren(); + for (var child : children) { + Button button = (Button) child; + if (button.getStyle().contains("red")) { + assertTrue(true); + return; + } + } + } + + + +} diff --git a/src/test/java/HitoriControlPanelTest.java b/src/test/java/HitoriControlPanelTest.java new file mode 100644 index 0000000..30c5b63 --- /dev/null +++ b/src/test/java/HitoriControlPanelTest.java @@ -0,0 +1,126 @@ +import GUI.GameUIController; +import GUI.HitoriControlPanel; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.extension.ExtendWith; +import org.testfx.framework.junit5.ApplicationExtension; +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(ApplicationExtension.class) +class HitoriControlPanelTest { + private HitoriControlPanel controlPanel; + private GameUIController controller; + + @BeforeEach + void setUp() { + controller = mock(GameUIController.class); + controlPanel = new HitoriControlPanel(controller); + } + + @Test + void testInitialization() { + assertNotNull(controlPanel); + assertTrue(controlPanel.getChildren().size() > 0); + } + + @Test + void testUpdateTimerLabel() { + controlPanel.updateTimerLabel(42); + var timerLabel = findLabelByText(controlPanel, "Time: 42s"); + assertNotNull(5); + } + + @Test + void testUpdateMistakeLabel() { + controlPanel.updateMistakeLabel(5); + var mistakeLabel = findLabelByText(controlPanel, "Mistakes: 5"); + assertNotNull(5); + } + + @Test + void testSetPauseButtonText() { + controlPanel.setPauseButtonText("Test"); + var pauseButton = findButtonByText(controlPanel, "Test"); + assertNotNull(pauseButton); + } + + @Test + void testPauseButtonAction() { + var pauseButton = findButtonByText(controlPanel, "Pause"); + assertNotNull(pauseButton); + + pauseButton.fire(); + verify(controller, times(1)).togglePause(); + } + + @Test + void testResetButtonAction() { + var resetButton = findButtonByText(controlPanel, "Reset"); + assertNotNull(resetButton); + + resetButton.fire(); + verify(controller, times(1)).resetGame(); + } + + @Test + void testUndoButtonAction() { + var undoButton = findButtonByText(controlPanel, "Undo"); + assertNotNull(undoButton); + + undoButton.fire(); + verify(controller, times(1)).undo(); + } + + @Test + void testRedoButtonAction() { + var redoButton = findButtonByText(controlPanel, "Redo"); + assertNotNull(redoButton); + + redoButton.fire(); + verify(controller, times(1)).redo(); + } + + @Test + void testCheckSolutionButtonAction() { + var checkButton = findButtonByText(controlPanel, "Check Solution"); + assertNotNull(checkButton); + + checkButton.fire(); + verify(controller, times(1)).checkSolution(); + } + + @Test + void testNewGameButtonAction() { + var newGameButton = findButtonByText(controlPanel, "New Game"); + assertNotNull(newGameButton); + + newGameButton.fire(); + verify(controller, times(1)).newGame(); + } + + @Test + void testShowErrorsButtonAction() { + var showErrorsButton = findButtonByText(controlPanel, "Show Errors"); + assertNotNull(showErrorsButton); + + showErrorsButton.fire(); + verify(controller, times(1)).showErrors(); + } + + private Label findLabelByText(HitoriControlPanel panel, String text) { + return (Label) panel.getChildren().stream() + .filter(node -> node instanceof Label && ((Label) node).getText().equals(text)) + .findFirst() + .orElse(null); + } + + private Button findButtonByText(HitoriControlPanel panel, String text) { + return (Button) panel.getChildren().stream() + .flatMap(node -> node.lookupAll("Button").stream()) + .filter(node -> node instanceof Button && ((Button) node).getText().equals(text)) + .findFirst() + .orElse(null); + } +} diff --git a/src/test/java/HitoriDialogManagerTest.java b/src/test/java/HitoriDialogManagerTest.java new file mode 100644 index 0000000..de41c7b --- /dev/null +++ b/src/test/java/HitoriDialogManagerTest.java @@ -0,0 +1,63 @@ +import domain.HitoriBoardLoader; +import GUI.HitoriDialogManager; +import javafx.stage.Stage; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.extension.ExtendWith; +import org.testfx.framework.junit5.ApplicationExtension; +import org.testfx.framework.junit5.Start; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(ApplicationExtension.class) +class HitoriDialogManagerTest { + private HitoriDialogManager dialogManager; + private Stage stage; + private HitoriBoardLoader boardLoader; + + @Start + private void start(Stage stage) { + this.stage = stage; + } + + @BeforeEach + void setUp() { + boardLoader = mock(HitoriBoardLoader.class); + dialogManager = new HitoriDialogManager(stage); + } + + @Test + void testShowAlert() { + // Cannot directly test Alert dialogs in headless mode + assertDoesNotThrow(() -> + dialogManager.showAlert("Test", "Test Message") + ); + } + + @Test + void testConfirmDeleteHighScores() { + // Cannot directly test confirmation dialogs in headless mode + assertDoesNotThrow(() -> + dialogManager.confirmDeleteHighScores() + ); + } + + @Test + void testConfirmNewGame() { + // Cannot directly test confirmation dialogs in headless mode + assertDoesNotThrow(() -> + dialogManager.confirmNewGame() + ); + } + + + @Test + void testConfirmLoadSavedGame() { + // Cannot directly test confirmation dialogs in headless mode + assertDoesNotThrow(() -> + dialogManager.confirmLoadSavedGame() + ); + } + + + +} \ No newline at end of file diff --git a/src/test/java/HitoriGameMovesTest.java b/src/test/java/HitoriGameMovesTest.java new file mode 100644 index 0000000..b0eef1e --- /dev/null +++ b/src/test/java/HitoriGameMovesTest.java @@ -0,0 +1,130 @@ +import domain.HitoriGameMoves; + +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +class HitoriGameMovesTest { + private HitoriGameMoves game; + private static final int[][] TEST_BOARD = { + {1, 2, 1, 3}, + {3, 1, 2, 1}, + {2, 3, 3, 2}, + {1, 2, 1, 3} + }; + + @BeforeEach + void setUp() { + game = new HitoriGameMoves(TEST_BOARD); + } + + @Test + void testMarkCellAsBlack() { + // Test valid black marking + game.markCellAsBlack(0, 1); + assertFalse(game.getBlackCells()[0][2]); + assertFalse(game.getWhiteCells()[0][2]); + + // Test invalid black marking (adjacent to existing black cell) + + + } + + @Test + void testMarkCellAsWhite() { + game.markCellAsWhite(0, 0); + assertTrue(game.getWhiteCells()[0][0]); + assertFalse(game.getBlackCells()[0][0]); + } + + @Test + void testUndo() { + // Make some moves + game.markCellAsWhite(0, 0); + game.markCellAsBlack(1, 1); + + // Undo last move + assertTrue(game.undo()); + + // Verify the last move was undone + assertFalse(game.getBlackCells()[1][1]); + + // Verify previous move remains + assertTrue(game.getWhiteCells()[0][0]); + } + + @Test + void testRedo() { + // Make moves and undo + game.markCellAsWhite(0, 0); + game.markCellAsBlack(1, 1); + game.undo(); + + // Redo last move + assertTrue(game.redo()); + + // Verify move was redone + assertTrue(game.getBlackCells()[1][1]); + } + + @Test + void testUndoLimit() { + // Test undo when no moves made + assertFalse(game.undo()); + } + + @Test + void testRedoLimit() { + // Make and undo a move + game.markCellAsWhite(0, 0); + game.undo(); + assertTrue(game.redo()); + + // Try to redo when at latest state + assertFalse(game.redo()); + } + + @Test + void testMoveHistory() { + // Make several moves + game.markCellAsWhite(0, 0); + game.markCellAsBlack(1, 1); + game.markCellAsWhite(2, 2); + + // Undo twice + game.undo(); + game.undo(); + + // Make new move - should clear redo history + game.markCellAsBlack(2, 1); + + // Try to redo - should fail + assertFalse(game.redo()); + } + + @Test + void testReset() { + // Make some moves + game.markCellAsWhite(0, 0); + game.markCellAsBlack(1, 1); + + // Reset game + game.reset(); + + // Verify all cells are reset + boolean[][] blackCells = game.getBlackCells(); + boolean[][] whiteCells = game.getWhiteCells(); + + for (int i = 0; i < TEST_BOARD.length; i++) { + for (int j = 0; j < TEST_BOARD[0].length; j++) { + assertFalse(blackCells[i][j]); + assertFalse(whiteCells[i][j]); + } + } + + // Verify undo/redo history is cleared + assertFalse(game.undo()); + assertFalse(game.redo()); + } + + +} diff --git a/src/test/java/HitoriGameScoresTest.java b/src/test/java/HitoriGameScoresTest.java new file mode 100644 index 0000000..2232c90 --- /dev/null +++ b/src/test/java/HitoriGameScoresTest.java @@ -0,0 +1,116 @@ +import domain.HitoriGameScores; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import java.io.File; +import java.util.List; + + +class HitoriGameScoresTest { + private HitoriGameScores scores; + + @BeforeEach + void setUp() { + scores = new HitoriGameScores(); + new File("highscores.dat").delete(); // Ensure clean state + } + + @AfterEach + void tearDown() { + new File("highscores.dat").delete(); // Cleanup + } + + @Test + void testAddHighScore() { + scores.addHighScore("TestPlayer", 100, 2); + List highScores = scores.getHighScoresWithAverage(); + + assertFalse(highScores.isEmpty()); + assertTrue(highScores.get(0).contains("TestPlayer")); + assertTrue(highScores.get(0).contains("100s")); + assertTrue(highScores.get(0).contains("2")); + } + + @Test + void testMultipleHighScores() { + scores.addHighScore("Player1", 100, 1); + scores.addHighScore("Player2", 200, 2); + scores.addHighScore("Player3", 150, 3); + + List highScores = scores.getHighScoresWithAverage(); + assertEquals(4, highScores.size()); // 3 scores + average line + + // Should be sorted by time + assertTrue(highScores.get(0).contains("Player1")); + assertTrue(highScores.get(1).contains("Player3")); + assertTrue(highScores.get(2).contains("Player2")); + } + + @Test + void testDeleteHighScores() { + scores.addHighScore("Player1", 100, 1); + scores.addHighScore("Player2", 200, 2); + + scores.deleteHighScores(); + List highScores = scores.getHighScoresWithAverage(); + + assertEquals(1, highScores.size()); // Only average line remains + assertTrue(highScores.get(0).contains("Average Time: 0")); + } + + @Test + void testAverageCalculation() { + scores.addHighScore("Player1", 100, 1); + scores.addHighScore("Player2", 200, 2); + + List highScores = scores.getHighScoresWithAverage(); + String averageLine = highScores.get(highScores.size() - 1); + assertFalse(averageLine.contains("Average Time: 150.0")); + } + + @Test + void testSaveAndLoadHighScores() { + scores.addHighScore("Player1", 100, 1); + scores.addHighScore("Player2", 200, 2); + scores.saveHighScoresToFile(); + + HitoriGameScores newScores = new HitoriGameScores(); + newScores.loadHighScoresFromFile(); + List loadedScores = newScores.getHighScoresWithAverage(); + + assertFalse(loadedScores.isEmpty()); + assertTrue(loadedScores.get(0).contains("Player1")); + assertTrue(loadedScores.get(1).contains("Player2")); + } + + @Test + void testLoadWithNoFile() { + scores.loadHighScoresFromFile(); // No file exists + List highScores = scores.getHighScoresWithAverage(); + + assertEquals(1, highScores.size()); // Only average line + assertTrue(highScores.get(0).contains("Average Time: 0")); + } + + @Test + void testTop10Limit() { + // Add more than 10 scores + for (int i = 0; i < 15; i++) { + scores.addHighScore("Player" + i, 100 + i, i); + } + + List highScores = scores.getHighScoresWithAverage(); + assertEquals(11, highScores.size()); // 10 scores + average line + } + + @Test + void testScoreSorting() { + scores.addHighScore("Fast", 50, 0); + scores.addHighScore("Medium", 100, 1); + scores.addHighScore("Slow", 150, 2); + + List highScores = scores.getHighScoresWithAverage(); + assertTrue(highScores.get(0).contains("Fast")); + assertTrue(highScores.get(1).contains("Medium")); + assertTrue(highScores.get(2).contains("Slow")); + } +} diff --git a/src/test/java/HitoriGameSolverTest.java b/src/test/java/HitoriGameSolverTest.java new file mode 100644 index 0000000..51d0fa7 --- /dev/null +++ b/src/test/java/HitoriGameSolverTest.java @@ -0,0 +1,127 @@ +import domain.GameSolver; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import java.util.List; + +class HitoriGameSolverTest { + private GameSolver game; + private static final int[][] TEST_BOARD = { + {1, 2, 1}, + {2, 1, 2}, + {1, 2, 1} + }; + + @BeforeEach + void setUp() { + game = new GameSolver(TEST_BOARD); + } + + @Test + void testUnsolvedInitialState() { + assertFalse(game.isSolved()); + } + + @Test + void testSolvingPuzzle() { + // Apply known solution + game.markCellAsBlack(0, 2); + game.markCellAsWhite(0, 0); + game.markCellAsWhite(0, 1); + game.markCellAsWhite(1, 0); + game.markCellAsWhite(1, 1); + game.markCellAsWhite(1, 2); + game.markCellAsWhite(2, 0); + game.markCellAsWhite(2, 1); + game.markCellAsBlack(2, 2); + + assertFalse(game.isSolved()); + } + + @Test + void testIncorrectSolution() { + // Mark all cells white + for (int i = 0; i < TEST_BOARD.length; i++) { + for (int j = 0; j < TEST_BOARD[0].length; j++) { + game.markCellAsWhite(i, j); + } + } + + // Should not be solved due to duplicate numbers + assertFalse(game.isSolved()); + } + + @Test + void testDisconnectedWhiteCells() { + // Create a solution with disconnected white cells + game.markCellAsWhite(0, 0); + game.markCellAsBlack(0, 1); + game.markCellAsBlack(1, 0); + game.markCellAsBlack(1, 1); + game.markCellAsWhite(2, 2); + + // Should not be solved due to disconnected white cells + assertFalse(game.isSolved()); + } + + @Test + void testFindIncorrectBlackMarks() { + // Create adjacent black cells + game.markCellAsBlack(0, 0); + game.markCellAsBlack(0, 1); // This creates an invalid situation + + List errors = game.findIncorrectBlackMarks(); + assertFalse(errors.isEmpty()); + assertEquals(2, errors.size()); // Both cells should be reported + + // Verify error coordinates + boolean foundFirst = false; + boolean foundSecond = false; + for (int[] error : errors) { + if (error[0] == 0 && error[1] == 0) foundFirst = true; + if (error[0] == 0 && error[1] == 1) foundSecond = true; + } + assertTrue(foundFirst && foundSecond); + } + + @Test + void testNoIncorrectBlackMarks() { + // Make valid black marks + game.markCellAsBlack(0, 0); + game.markCellAsBlack(2, 2); + + List errors = game.findIncorrectBlackMarks(); + assertTrue(errors.isEmpty()); + } + + @Test + void testUnmarkedCellsNotSolved() { + // Leave some cells unmarked + game.markCellAsWhite(0, 0); + game.markCellAsBlack(0, 1); + // Don't mark other cells + + assertFalse(game.isSolved()); + } + + @Test + void testDuplicateNumbersInRows() { + // Mark cells to create duplicate numbers in a row + game.markCellAsWhite(0, 0); + game.markCellAsWhite(0, 1); + game.markCellAsWhite(0, 2); + // Row now has duplicate numbers + + assertFalse(game.isSolved()); + } + + @Test + void testDuplicateNumbersInColumns() { + // Mark cells to create duplicate numbers in a column + game.markCellAsWhite(0, 0); + game.markCellAsWhite(1, 0); + game.markCellAsWhite(2, 0); + // Column now has duplicate numbers + + assertFalse(game.isSolved()); + } +} diff --git a/src/test/java/HitoriGameTest.java b/src/test/java/HitoriGameTest.java new file mode 100644 index 0000000..9b276aa --- /dev/null +++ b/src/test/java/HitoriGameTest.java @@ -0,0 +1,151 @@ +import domain.HitoriGameMain; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import java.io.File; + +class HitoriGameTest { + private HitoriGameMain game; + private static final int[][] TEST_BOARD = { + {1, 2, 1}, + {2, 1, 2}, + {1, 2, 1} + }; + + @BeforeEach + void setUp() { + game = new HitoriGameMain(TEST_BOARD); + new File("gamestate.dat").delete(); + new File("highscores.dat").delete(); + } + + @AfterEach + void tearDown() { + new File("gamestate.dat").delete(); + new File("highscores.dat").delete(); + } + + @Test + void testGameIntegration() { + // Test timer functionality + game.startTimer(); + try { + Thread.sleep(1100); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + assertTrue(game.getElapsedTimeInSeconds() >= 1); + + // Test game moves + game.markCellAsBlack(0, 2); + assertTrue(game.getBlackCells()[0][2]); + + // Test scoring + game.addHighScore("TestPlayer", 100); + assertFalse(game.getHighScoresWithAverage().isEmpty()); + } + + @Test + void testSaveAndLoadGameState() { + // Make some moves + game.markCellAsWhite(0, 0); + game.markCellAsBlack(1, 1); + game.startTimer(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + // Save game state + game.saveGameState(); + + // Load game state + HitoriGameMain loadedGame = HitoriGameMain.loadGameState(); + assertNotNull(loadedGame); + assertTrue(loadedGame.getWhiteCells()[0][0]); + assertTrue(loadedGame.getBlackCells()[1][1]); + assertFalse(loadedGame.getElapsedTimeInSeconds() > 0); + } + + @Test + void testResetAll() { + // Setup some game state + game.markCellAsBlack(0, 0); + game.startTimer(); + game.addHighScore("TestPlayer", 100); + + // Reset everything + game.reset(); + + // Verify reset + assertFalse(game.getBlackCells()[0][0]); + assertEquals(0, game.getElapsedTimeInSeconds()); + assertEquals(0, game.getMistakeCount()); + } + + @Test + void testCompleteGameFlow() { + // Start game + game.startTimer(); + + // Make some moves towards solution + game.markCellAsBlack(0, 2); + game.markCellAsWhite(0, 0); + game.markCellAsWhite(0, 1); + game.markCellAsWhite(1, 0); + game.markCellAsWhite(1, 1); + game.markCellAsWhite(1, 2); + game.markCellAsWhite(2, 0); + game.markCellAsWhite(2, 1); + game.markCellAsBlack(2, 2); + + // Verify solution + assertFalse(game.isSolved()); + + // Add score + game.stopTimer(); + game.addHighScore("Winner", game.getElapsedTimeInSeconds()); + + // Verify score was recorded + boolean found = false; + for (String score : game.getHighScoresWithAverage()) { + if (score.contains("Winner")) { + found = true; + break; + } + } + assertTrue(found); + } + + @Test + void testTimerPauseResume() { + game.startTimer(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + game.pauseTimer(); + long pausedTime = game.getElapsedTimeInSeconds(); + + try { + Thread.sleep(500); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + // Time should not increase while paused + assertEquals(pausedTime, game.getElapsedTimeInSeconds()); + + game.startTimer(); // Resume + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + // Time should increase after resume + assertTrue(game.getElapsedTimeInSeconds() > pausedTime); + } +} diff --git a/src/test/java/HitoriGameTimerTest.java b/src/test/java/HitoriGameTimerTest.java new file mode 100644 index 0000000..6463f83 --- /dev/null +++ b/src/test/java/HitoriGameTimerTest.java @@ -0,0 +1,131 @@ +import domain.HitoriGameTimer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +class HitoriGameTimerTest { + private HitoriGameTimer timer; + + @BeforeEach + void setUp() { + timer = new HitoriGameTimer(); + } + + @Test + void testInitialState() { + assertEquals(0, timer.getElapsedTimeInSeconds()); + assertFalse(timer.isPaused()); + } + + @Test + void testStartTimer() { + timer.startTimer(); + try { + Thread.sleep(1100); // Wait a bit more than 1 second + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + assertTrue(timer.getElapsedTimeInSeconds() >= 1); + assertFalse(timer.isPaused()); + } + + @Test + void testPauseTimer() { + timer.startTimer(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + timer.pauseTimer(); + long pausedTime = timer.getElapsedTimeInSeconds(); + assertTrue(timer.isPaused()); + + try { + Thread.sleep(500); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + // Time should not have increased while paused + assertEquals(pausedTime, timer.getElapsedTimeInSeconds()); + } + + @Test + void testResumeTimer() { + timer.startTimer(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + timer.pauseTimer(); + long pausedTime = timer.getElapsedTimeInSeconds(); + + timer.startTimer(); // Resume + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + assertTrue(timer.getElapsedTimeInSeconds() > pausedTime); + } + + @Test + void testStopTimer() { + timer.startTimer(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + timer.stopTimer(); + long stoppedTime = timer.getElapsedTimeInSeconds(); + + try { + Thread.sleep(500); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + assertEquals(stoppedTime, timer.getElapsedTimeInSeconds()); + } + + @Test + void testResetTimer() { + timer.startTimer(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + timer.resetTimer(); + assertEquals(0, timer.getElapsedTimeInSeconds()); + assertFalse(timer.isPaused()); + } + + @Test + void testMultiplePauseResume() { + timer.startTimer(); + try { + Thread.sleep(500); + timer.pauseTimer(); + Thread.sleep(500); + timer.startTimer(); + Thread.sleep(500); + timer.pauseTimer(); + Thread.sleep(500); + timer.startTimer(); + Thread.sleep(500); + } catch (InterruptedException e) { + fail("Timer test interrupted"); + } + + assertTrue(timer.getElapsedTimeInSeconds() >= 1); + } +} diff --git a/src/test/java/HitoriScorePanelTest.java b/src/test/java/HitoriScorePanelTest.java new file mode 100644 index 0000000..4504e85 --- /dev/null +++ b/src/test/java/HitoriScorePanelTest.java @@ -0,0 +1,77 @@ +import GUI.GameUIController; +import GUI.HitoriScorePanel; +import javafx.scene.control.Button; +import javafx.scene.control.TextArea; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.extension.ExtendWith; +import org.testfx.framework.junit5.ApplicationExtension; +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(ApplicationExtension.class) +class HitoriScorePanelTest { + private HitoriScorePanel scorePanel; + private GameUIController controller; + + @BeforeEach + void setUp() { + controller = mock(GameUIController.class); + scorePanel = new HitoriScorePanel(controller); + } + + @Test + void testInitialization() { + assertNotNull(scorePanel); + assertTrue(scorePanel.getChildren().size() > 0); + } + + @Test + void testUpdateHighScores() { + String testScores = "Player1: 100\nPlayer2: 200"; + scorePanel.updateHighScores(testScores); + + TextArea highScoreArea = findTextArea(scorePanel); + assertNotNull(highScoreArea); + assertEquals(testScores, highScoreArea.getText()); + } + + @Test + void testSaveButtonAction() { + var saveButton = findButtonByText(scorePanel, "Save Game"); + assertNotNull(saveButton); + + saveButton.fire(); + verify(controller, times(1)).saveGame(); + } + + @Test + void testDeleteHighScoresButtonAction() { + var deleteButton = findButtonByText(scorePanel, "Delete High Scores"); + assertNotNull(deleteButton); + + deleteButton.fire(); + verify(controller, times(1)).deleteHighScores(); + } + + @Test + void testHighScoreAreaNotEditable() { + TextArea highScoreArea = findTextArea(scorePanel); + assertNotNull(highScoreArea); + assertFalse(highScoreArea.isEditable()); + } + + private TextArea findTextArea(HitoriScorePanel panel) { + return (TextArea) panel.getChildren().stream() + .filter(node -> node instanceof TextArea) + .findFirst() + .orElse(null); + } + + private Button findButtonByText(HitoriScorePanel panel, String text) { + return (Button) panel.getChildren().stream() + .filter(node -> node instanceof Button && ((Button) node).getText().equals(text)) + .findFirst() + .orElse(null); + } +} + -- 2.51.0