diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index ace169665e..530b8505c2 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -14,10 +14,11 @@ */ public class Duke { + public static final String WELCOME_MESSAGE = "Hello! I'm Duke. What would you like to do today?"; + /** The file path where the data of the chatbot is stored */ private static final String FILE_PATH = "data/tasks.txt"; - private final Storage storage; private final TaskList tasks; diff --git a/src/main/java/duke/gui/MainWindow.java b/src/main/java/duke/gui/MainWindow.java index ebbc604b73..88cb10c8e5 100644 --- a/src/main/java/duke/gui/MainWindow.java +++ b/src/main/java/duke/gui/MainWindow.java @@ -1,5 +1,7 @@ package duke.gui; +import static duke.Duke.WELCOME_MESSAGE; + import duke.Duke; import duke.command.CommandResult; import duke.data.exception.DukeException; @@ -25,9 +27,13 @@ public class MainWindow extends AnchorPane { private Duke duke; + /** + * Initializes the main window with the given welcome message. + */ @FXML public void initialize() { scrollPane.vvalueProperty().bind(dialogContainer.heightProperty()); + addDukeDialog(WELCOME_MESSAGE); } public void setDuke(Duke d) { diff --git a/src/main/resources/images/DaUser.png b/src/main/resources/images/DaUser.png deleted file mode 100644 index 3c82f45461..0000000000 Binary files a/src/main/resources/images/DaUser.png and /dev/null differ diff --git a/src/main/resources/view/UserDialogBox.fxml b/src/main/resources/view/UserDialogBox.fxml index 4ac84b3263..3e3ce1e02a 100644 --- a/src/main/resources/view/UserDialogBox.fxml +++ b/src/main/resources/view/UserDialogBox.fxml @@ -15,10 +15,6 @@ - - - - diff --git a/src/test/java/duke/data/task/TaskListTest.java b/src/test/java/duke/data/task/TaskListTest.java index 382491acdb..c28ab86420 100644 --- a/src/test/java/duke/data/task/TaskListTest.java +++ b/src/test/java/duke/data/task/TaskListTest.java @@ -10,22 +10,23 @@ import org.junit.jupiter.api.Test; import duke.data.exception.DukeException; +import duke.data.exception.InvalidTaskIndexException; public class TaskListTest { @Test - public void removeTask_invalidIndex_throwsDukeException() { + public void remove_invalidIndex_throwsInvalidTaskIndexException() { TaskList taskList = new TaskList( new Todo("todo"), new Deadline("deadline", LocalDate.now()), new Event("event", LocalDate.now(), LocalDate.now()) ); - assertThrows(DukeException.class, () -> taskList.remove(-1)); - assertThrows(DukeException.class, () -> taskList.remove(4)); + assertThrows(InvalidTaskIndexException.class, () -> taskList.remove(-1)); + assertThrows(InvalidTaskIndexException.class, () -> taskList.remove(4)); } @Test - public void removeTask_validIndexIndex_taskNotInList() { + public void remove_validIndexIndex_taskNotInList() { Task toRemove = new Todo("toRemove"); TaskList taskList = new TaskList( new Todo("todo"), diff --git a/src/test/java/duke/parser/ParserTest.java b/src/test/java/duke/parser/ParserTest.java index 15ff2f1c7f..0e140b4d52 100644 --- a/src/test/java/duke/parser/ParserTest.java +++ b/src/test/java/duke/parser/ParserTest.java @@ -1,7 +1,7 @@ package duke.parser; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.Test; @@ -9,9 +9,21 @@ import duke.command.AddDeadlineCommand; import duke.command.AddEventCommand; import duke.command.AddTodoCommand; -import duke.command.Command; +import duke.command.ClearCommand; +import duke.command.DeleteCommand; import duke.command.ExitCommand; +import duke.command.FindCommand; +import duke.command.HelpCommand; +import duke.command.ListCommand; +import duke.command.MarkCommand; +import duke.command.UnmarkCommand; import duke.data.exception.DukeException; +import duke.data.exception.InvalidDateException; +import duke.data.exception.InvalidKeywordException; +import duke.data.exception.InvalidTaskArgumentException; +import duke.data.exception.InvalidTaskIndexException; + + public class ParserTest { @@ -28,119 +40,290 @@ public void parse_invalidCommandWord_throwsDukeException() { @Test public void parse_byeCommandWord_returnsExitCommand() { try { - assertEquals(Parser.parse("bye").getClass(), ExitCommand.class); + assertTrue(Parser.parse("bye") instanceof ExitCommand); } catch (DukeException e) { fail(e.getMessage()); } } @Test - public void parse_emptyTodoDescription_throwsDukeException() { + public void parse_emptyTodoDescription_throwsInvalidTaskArgumentException() { try { Parser.parse("todo"); - } catch (DukeException e) { + } catch (InvalidTaskArgumentException e) { return; + } catch (DukeException e) { + fail(e.getMessage()); } fail("Add Todo Command was successfully constructed with empty description."); } @Test public void parse_validTodo_returnsAddTodoCommand() { - Command command; try { - command = Parser.parse("todo desc abc"); + assertTrue(Parser.parse("todo desc") instanceof AddTodoCommand); + assertTrue(Parser.parse("todo desc abc") instanceof AddTodoCommand); } catch (DukeException e) { fail(e.getMessage()); - return; } - - assertEquals(command.getClass(), AddTodoCommand.class); } @Test - public void parse_emptyDeadlineDescription_throwsDukeException() { + public void parse_emptyDeadlineDescription_throwsInvalidTaskArgumentException() { try { Parser.parse("deadline"); - } catch (DukeException e) { + } catch (InvalidTaskArgumentException e) { return; + } catch (DukeException e) { + fail(e.getMessage()); } fail("Add Deadline Command was successfully constructed with empty description."); } @Test - public void parse_emptyDeadlineBy_throwsDukeException() { + public void parse_emptyDeadlineBy_throwsInvalidTaskArgumentException() { try { Parser.parse("deadline desc"); - } catch (DukeException e) { + } catch (InvalidTaskArgumentException e) { return; + } catch (DukeException e) { + fail(e.getMessage()); } fail("Add Deadline Command was successfully constructed without /by field."); } @Test - public void parse_invalidDeadlineBy_throwsDukeException() { + public void parse_invalidDeadlineBy_throwsInvalidDateException() { try { Parser.parse("deadline desc /by invalid"); - } catch (DukeException e) { + } catch (InvalidDateException e) { return; + } catch (DukeException e) { + fail(e.getMessage()); } fail("Add Deadline Command was successfully constructed with invalid /by field."); } @Test public void parse_validDeadline_returnsAddDeadlineCommand() { - Command command; try { - command = Parser.parse("deadline desc /by 2023-01-01"); + assertTrue(Parser.parse("deadline desc /by 2023-01-01") instanceof AddDeadlineCommand); + assertTrue(Parser.parse("deadline desc /by 1999-12-30") instanceof AddDeadlineCommand); } catch (DukeException e) { fail(e.getMessage()); - return; } - - assertEquals(command.getClass(), AddDeadlineCommand.class); } @Test - public void parse_emptyEventDescription_throwsDukeException() { + public void parse_emptyEventDescription_throwsInvalidTaskArgumentException() { try { Parser.parse("event"); - } catch (DukeException e) { + } catch (InvalidTaskArgumentException e) { return; + } catch (DukeException e) { + fail(e.getMessage()); } fail("Add Event Command was successfully constructed with empty description."); } @Test - public void parse_invalidEventFrom_throwsDukeException() { + public void parse_invalidEventFrom_throwsInvalidDateException() { try { - Parser.parse("deadline desc /from invalid /to 2023-01-01"); - } catch (DukeException e) { + Parser.parse("event desc /from invalid /to 2023-01-01"); + } catch (InvalidDateException e) { return; + } catch (DukeException e) { + fail(e.getMessage()); } fail("Add Event Command was successfully constructed with invalid /from field."); } @Test - public void parse_invalidEventTo_throwsDukeException() { + public void parse_invalidEventTo_throwsInvalidDatetException() { try { - Parser.parse("deadline desc /from 2023-01-01 /to invalid"); - } catch (DukeException e) { + Parser.parse("event desc /from 2023-01-01 /to invalid"); + } catch (InvalidDateException e) { return; + } catch (DukeException e) { + fail(e.getMessage()); } fail("Add Event Command was successfully constructed with invalid /to field."); } @Test public void parse_validEvent_returnsAddEventCommand() { - Command command; try { - command = Parser.parse("event desc /from 2023-01-01 /to 2024-01-01"); + assertTrue(Parser.parse("event desc /from 2023-01-31 /to 2024-01-01") instanceof AddEventCommand); + assertTrue(Parser.parse("event desc /from 2020-01-31 /to 2024-01-01") instanceof AddEventCommand); + } catch (DukeException e) { + fail(e.getMessage()); + } + } + + @Test + public void parse_listCommand_returnsListCommand() { + try { + assertTrue(Parser.parse("list") instanceof ListCommand); + } catch (DukeException e) { + fail(e.getMessage()); + } + } + + @Test + public void parse_clearCommand_returnsClearCommand() { + try { + assertTrue(Parser.parse("clear") instanceof ClearCommand); } catch (DukeException e) { fail(e.getMessage()); + } + } + + @Test + public void parse_emptyKeyword_throwsInvalidKeywordException() { + try { + Parser.parse("find"); + } catch (InvalidKeywordException e) { return; + } catch (DukeException e) { + fail(e.getMessage()); } + fail("Find Command was successfully constructed with empty keyword."); + } - assertEquals(command.getClass(), AddEventCommand.class); + @Test + public void parse_multipleKeyword_throwsInvalidKeywordException() { + try { + Parser.parse("find a b"); + } catch (InvalidKeywordException e) { + return; + } catch (DukeException e) { + fail(e.getMessage()); + } + fail("Find Command was successfully constructed with multiple keywords."); + } + + @Test + public void parse_validKeyword_returnsFindCommand() { + try { + assertTrue(Parser.parse("find a") instanceof FindCommand); + assertTrue(Parser.parse("find abc") instanceof FindCommand); + assertTrue(Parser.parse("find keyword") instanceof FindCommand); + } catch (DukeException e) { + fail(e.getMessage()); + } } + + @Test + public void parse_helpCommand_returnsHelpCommand() { + try { + assertTrue(Parser.parse("help") instanceof HelpCommand); + assertTrue(Parser.parse("help anything") instanceof HelpCommand); + } catch (DukeException e) { + fail(e.getMessage()); + } + } + + @Test + public void parse_emptyMarkIndex_throwsInvalidTaskIndexException() { + try { + Parser.parse("mark"); + } catch (InvalidTaskIndexException e) { + return; + } catch (DukeException e) { + fail(e.getMessage()); + } + fail("Mark Command was successfully constructed with no index."); + } + + @Test + public void parse_invalidMarkIndex_throwsInvalidTaskIndexException() { + try { + Parser.parse("mark invalid"); + } catch (InvalidTaskIndexException e) { + return; + } catch (DukeException e) { + fail(e.getMessage()); + } + fail("Mark Command was successfully constructed with invalid index."); + } + + @Test + public void parse_validMarkIndex_returnsMarkCommand() { + try { + assertTrue(Parser.parse("mark 1") instanceof MarkCommand); + assertTrue(Parser.parse("mark 999") instanceof MarkCommand); + } catch (DukeException e) { + fail(e.getMessage()); + } + } + + @Test + public void parse_emptyUnmarkIndex_throwsInvalidTaskIndexException() { + try { + Parser.parse("unmark"); + } catch (InvalidTaskIndexException e) { + return; + } catch (DukeException e) { + fail(e.getMessage()); + } + fail("Unmark Command was successfully constructed with no index."); + } + + @Test + public void parse_invalidUnmarkIndex_throwsInvalidTaskIndexException() { + try { + Parser.parse("unmark invalid"); + } catch (InvalidTaskIndexException e) { + return; + } catch (DukeException e) { + fail(e.getMessage()); + } + fail("Unmark Command was successfully constructed with invalid index."); + } + + @Test + public void parse_validUnmarkIndex_returnsUnmarkCommand() { + try { + assertTrue(Parser.parse("unmark 1") instanceof UnmarkCommand); + assertTrue(Parser.parse("unmark 999") instanceof UnmarkCommand); + } catch (DukeException e) { + fail(e.getMessage()); + } + } + + @Test + public void parse_emptyDeleteIndex_throwsInvalidTaskIndexException() { + try { + Parser.parse("delete"); + } catch (InvalidTaskIndexException e) { + return; + } catch (DukeException e) { + fail(e.getMessage()); + } + fail("Delete Command was successfully constructed with no index."); + } + + @Test + public void parse_invalidDeleteIndex_throwsInvalidTaskIndexException() { + try { + Parser.parse("delete invalid"); + } catch (InvalidTaskIndexException e) { + return; + } catch (DukeException e) { + fail(e.getMessage()); + } + fail("Delete Command was successfully constructed with invalid index."); + } + + @Test + public void parse_validDeleteIndex_returnsUnmarkCommand() { + try { + assertTrue(Parser.parse("delete 1") instanceof DeleteCommand); + assertTrue(Parser.parse("delete 999") instanceof DeleteCommand); + } catch (DukeException e) { + fail(e.getMessage()); + } + } + }