" + UI.line() +
+ "View common events: \n" + "viewcommonevents");
+ printLine();
+ }
+
+ public static void printAddForAll(Task task) {
+ System.out.println("The following task is added for all users: " + task.toString());
+ }
+
+ public static void printEmptyDirectory() {
+ System.out.println("Directory is empty.");
+ }
+
+ public static void printLine() {
+ System.out.println("____________________________________________________________");
+ }
+
+ public static String line() {
+ return ("\n_________________________________________\n");
+ }
+
+ /**
+ *
+ * Prints the overlapping free time for each day in the format:
+ * ----------------------
+ * Shared Free Time on [day]
+ * HH:mm - HH:mm: Overlapping Free Time
+ */
+ public static void printSharedTime(Timetable merged) {
+ for (String day : Timetable.DAYS) {
+ UI.printLine();
+ System.out.println("Shared free time on " + day + ":");
+ findOverlappingFreeTime(merged.getWeeklyTasks().get(day), day);
+
+ }
+ }
+
+ public static void printCompareUsers(String user1, String user2) {
+ System.out.println("Comparing timetables of " + user1 + " and " + user2 + ": ");
+ }
+
+ public static void printComparingAll() {
+ System.out.println("Comparing all timetables: ");
+ }
+
+ /**
+ * Prints tasks of the day specified.
+ *
+ * @param day day of the week the task is on.
+ */
+ public static void printTasksOfTheDay(String day, Map> weeklyTask) {
+ String capitalizedDay = day.substring(0, 1).toUpperCase() + day.substring(1);
+ if (weeklyTask.get(capitalizedDay).isEmpty()) {
+ UI.printNoTask(day);
+ return;
+ }
+ System.out.println("_________________________________________");
+ UI.printDayHeader(capitalizedDay);
+ int count = 1;
+ for (Task task : weeklyTask.get(capitalizedDay)) {
+ UI.printTaskInList(count, task.toString());
+ count++;
+ }
+ }
+
+ public static void printTimeFrame(LocalTime time1, String time2) {
+ System.out.println(" "+time1 + " - " + time2);
+ }
+ public static void printTimeFrame(LocalTime time1, LocalTime time2) {
+ System.out.println(" "+time1 + " - " + time2);
+ }
+ public static void printFullDay() {
+ System.out.println(" None");
+ }
+ public static void printFreeDay(String day) {
+ System.out.println(" ** Whole day is free on " + day);
+ }
+ public static void printNoTask(String day) {
+ System.out.println("No task for " + day + "!");
+ }
+ public static void printDayHeader(String day) {
+ System.out.println(day + " :");
+ }
+ public static void printTaskInList(int count, String task) {
+ System.out.println(" "+count + ". " + task);
+ }
+
+ public static void printNext() {
+ System.out.println("Your next task is: ");
+ }
+
+ public static void printNoTasks() {
+ System.out.println("You have no tasks today. ");
+ }
+
+ public static void printNoUsers() {
+ System.out.println("Please add a user before adding tasks.");
+ }
+
+ public static void printClashTasks() {
+ System.out.println("The task you want to add clashes with existing tasks. Please check again.");
+ }
+}
diff --git a/src/test/java/seedu/duke/DukeTest.java b/src/test/java/seedu/duke/DukeTest.java
index 2dda5fd651..6ca414e690 100644
--- a/src/test/java/seedu/duke/DukeTest.java
+++ b/src/test/java/seedu/duke/DukeTest.java
@@ -1,12 +1,44 @@
package seedu.duke;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
+import java.time.LocalTime;
class DukeTest {
@Test
public void sampleTest() {
assertTrue(true);
}
+
+ @Test
+ public void testAddTask() {
+ UserList userlist = new UserList();
+ User user = new User("Test User");
+ userlist.addUser(user);
+ Task task = new Task("Lecture", "Monday", "1:00", "2:00", "f");
+ user.getTimetable().addUserTask("Monday", task);
+ assertEquals("Lecture", task.description);
+ assertEquals(LocalTime.parse("01:00"), task.startTime);
+ }
+ @Test
+ public void testAddUser() {
+ UserList userList = new UserList();
+ User user = new User("Test User");
+ userList.addUser(user);
+
+ // Verify that the user is added to the list
+ assertEquals(1, userList.getListLength());
+ assertEquals(user, userList.getActiveUser());
+ assertTrue(userList.getUsers().contains(user));
+
+ User user2 = new User("Test User 2");
+ userList.addUser(user2);
+
+ assertEquals(2, userList.getListLength());
+ assertEquals(user, userList.getActiveUser());
+ assertTrue(userList.getUsers().contains(user));
+ assertTrue(userList.getUsers().contains(user2));
+ }
}
diff --git a/src/test/java/seedu/duke/InputValidatorTest.java b/src/test/java/seedu/duke/InputValidatorTest.java
new file mode 100644
index 0000000000..afc8bd4544
--- /dev/null
+++ b/src/test/java/seedu/duke/InputValidatorTest.java
@@ -0,0 +1,253 @@
+package seedu.duke;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import seedu.duke.exceptions.InvalidDayException;
+import seedu.duke.exceptions.InvalidFormatException;
+class InputValidatorTest {
+ @Test
+ public void testAddUser() {
+ String[] inputList = {
+ "adduser john",
+ "adduser john100 ",
+ "ADDUSEr j",
+ "ADDUSER xjohnx",
+ "addUser 20 "
+ };
+ for (String input : inputList) {
+ try {
+ InputValidator.validateAddUserInput(input);
+ } catch (InvalidFormatException e){
+ fail();
+ }
+ }
+ }
+
+ @Test
+ public void testValidChangeTaskTimingFormat() {
+ String validInput = "changeTaskTiming /on monday /index 1 /from 09:00 /to 10:00";
+ try {
+ InputValidator.validateChangeTaskTiming(validInput);
+ } catch (InvalidFormatException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ @Test
+ public void testInvalidChangeTaskTimingFormat() {
+ String invalidInput = "changeTaskTiming /on monday /index 1 /from 09:00";
+ try {
+ InputValidator.validateChangeTaskTiming(invalidInput);
+ fail("Expected InvalidFormatException");
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid changeTaskTiming format. Expected format: changeTaskTiming " +
+ "/on [day] /index [index] /from [new start time] /to [new end time]", e.getMessage());
+ }
+ }
+ @Test
+ public void testValidChangeTaskTypeFormat() {
+ String validInput = "changetasktype /on Monday /index 1 /type f";
+ try {
+ InputValidator.validateChangeTaskType(validInput);
+ } catch (InvalidFormatException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ @Test
+ public void testInvalidChangeTaskTypeFormat() {
+ String invalidInput = "changetasktype /on Monday /index 1 /type a";
+ try {
+ InputValidator.validateChangeTaskType(invalidInput);
+ fail("Expected InvalidFormatException");
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid changeTaskType format. Expected format: " +
+ "changeTaskType /on [day] /index [index] /type [f/c]", e.getMessage());
+ }
+ }
+ @Test
+ public void testValidAddRepeatTaskFormat() {
+ String validInput = "addRepeatTask /task lec /on monday tuesday /from 08:00 /to 10:00 /type f";
+ try {
+ InputValidator.validateAddRepeatTask(validInput);
+ } catch (InvalidFormatException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ @Test
+ public void testInvalidAddRepeatTaskFormat() {
+ String invalidInput = "addRepeatTask /task lec /from 08:00 /to 10:00 /type f";
+ try {
+ InputValidator.validateAddRepeatTask(invalidInput);
+ fail("Expected InvalidFormatException");
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid addRepeatTask format. Expected format: addRepeatTask /task " +
+ "[description] /on [day(s)] /from [start time] /to [end time] /type [f/c]", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testValidateDay() {
+ String[] inputList = {"monday", "tuesday", "wednesday", "thursday", "friday", "Monday", "MONDAY"};
+ for (String input : inputList) {
+ try {
+ InputValidator.validateDay(input);
+ } catch (InvalidDayException e) {
+ fail();
+ }
+ }
+ }
+
+ @Test
+ public void testAddTask() {
+ String[] inputList = {
+ "addtask /on MONDAY /task walk dogs /from 10:00 /to 16:00 /type c",
+ "ADDTASK /on tuesday /task walk dogs /from 00:00 /to 23:59 /type f",
+ "addtask /on MONDAY /task walk dogs100 /from 10:00 /to 16:00 /type c",
+ "Addtask /on sunday /task walk dogssSS /from 10:00 /to 16:00 /type f",
+ "addtask /on Friday /task walk dogs /from 10:00 /to 16:00 /type c"
+ };
+ for (String input : inputList) {
+ try {
+ InputValidator.validateAddTaskInput(input);
+ } catch (InvalidFormatException e){
+ fail();
+ }
+ }
+ }
+
+ @Test
+ public void testInvalidAddTask() {
+ //addtask mispelled
+ String invalidInput1 = "addtas /on MONDAY /task walk dogs /from 10:00 /to 16:00 /type c";
+ try {
+ InputValidator.validateAddTaskInput(invalidInput1);
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid addtask format. " +
+ "Expected format: addtask /on [day] /task [description] /from [start time] /to [end time] " +
+ "/type [f/c]", e.getMessage());
+ }
+ //No space between from time and "/to"
+ String invalidInput2 = "addtask /on MONDAY /task walk dogs /from 10:00/to 16:00 /type c";
+ try {
+ InputValidator.validateAddTaskInput(invalidInput2);
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid addtask format. " +
+ "Expected format: addtask /on [day] /task [description] /from [start time] /to [end time] " +
+ "/type [f/c]", e.getMessage());
+ }
+ //Monday extra y
+ String invalidInput3 = "addtask /on MONDAYy /task walk dogs /from 10:00 /to 16:00 /type c";
+ try {
+ InputValidator.validateAddTaskInput(invalidInput3);
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid addtask format. " +
+ "Expected format: addtask /on [day] /task [description] /from [start time] /to [end time] " +
+ "/type [f/c]", e.getMessage());
+ }
+ //different type v
+ String invalidInput4 = "addtask /on MONDAY /task walk dogs /from 10:00 /to 16:00 /type v";
+ try {
+ InputValidator.validateAddTaskInput(invalidInput4);
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid addtask format. " +
+ "Expected format: addtask /on [day] /task [description] /from [start time] /to [end time] " +
+ "/type [f/c]", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testDeleteTask() {
+ String[] inputList = {
+ "deletetask /on MONDAY /index 1",
+ "deletetask /on saturday /index 100",
+ "Deletetask /on MONDAY /index 12",
+ "DELETETASK /on tuesdAY /index 1",
+ "deleteTASK /on saturday /index 4000"
+ };
+ for (String input : inputList) {
+ try {
+ InputValidator.validateDeleteTaskInput(input);
+ } catch (InvalidFormatException e){
+ fail();
+ }
+ }
+ }
+
+
+ @Test
+ public void testCompare() {
+ String[] inputList = {"compare john jill", "COMPARE john jill ", "COMpare john bill", "comPArE jane yu"};
+ for (String input : inputList) {
+ try {
+ InputValidator.validateCompareInput(input);
+ } catch (InvalidFormatException e) {
+ fail();
+ }
+ }
+ }
+
+ @Test
+ public void testInvalidCompare() {
+ String invalidInput1 = "compare john jack jill";
+ try {
+ InputValidator.validateCompareInput(invalidInput1);
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid compare format. " +
+ "Expected format: compare ", e.getMessage());
+ }
+ String invalidInput2 = "compar john jack ";
+ try {
+ InputValidator.validateCompareInput(invalidInput2);
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid compare format. " +
+ "Expected format: compare ", e.getMessage());
+ }
+ String invalidInput3 = "compare jo";
+ try {
+ InputValidator.validateCompareInput(invalidInput3);
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid compare format. " +
+ "Expected format: compare ", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testCompareAll() {
+ String[] inputList = {"compareall ", "COMPAREALL ", "COMpareAll", "comPArEall"};
+ for (String input : inputList) {
+ try {
+ InputValidator.validateCompareAllInput(input);
+ } catch (InvalidFormatException e) {
+ fail();
+ }
+ }
+ }
+
+ @Test
+ public void testInvalidCompareAll() {
+ String invalidInput1 = "compareall l";
+ try {
+ InputValidator.validateCompareAllInput(invalidInput1);
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid compareall format. " +
+ "Expected format: compareall", e.getMessage());
+ }
+ String invalidInput2 = "comparall ";
+ try {
+ InputValidator.validateCompareAllInput(invalidInput2);
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid compareall format. " +
+ "Expected format: compareall", e.getMessage());
+ }
+ String invalidInput3 = "compareallllll";
+ try {
+ InputValidator.validateCompareAllInput(invalidInput3);
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid compareall format. " +
+ "Expected format: compareall", e.getMessage());
+ }
+ }
+}
diff --git a/src/test/java/seedu/duke/ParserTest.java b/src/test/java/seedu/duke/ParserTest.java
new file mode 100644
index 0000000000..0ba0caea35
--- /dev/null
+++ b/src/test/java/seedu/duke/ParserTest.java
@@ -0,0 +1,246 @@
+package seedu.duke;
+
+import org.junit.jupiter.api.Test;
+import seedu.duke.exceptions.InvalidDayException;
+import seedu.duke.exceptions.InvalidFormatException;
+import seedu.duke.exceptions.InvalidUserException;
+import seedu.duke.exceptions.NoUserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+class ParserTest {
+ UserList userlist = new UserList();
+
+ @Test
+ public void sampleTest() {
+ assertTrue(true);
+ }
+
+ @Test
+ public void adduserCommandTest() throws InvalidDayException, InvalidFormatException, InvalidUserException,
+ NoUserException, IOException {
+ Parser.parseCommand("addUser User1", userlist);
+
+ assertEquals(1, userlist.getListLength());
+ assertEquals("User1", userlist.getActiveUser().getName());
+
+ Parser.parseCommand("addUser User2", userlist);
+ Parser.parseCommand("addUser User3", userlist);
+ Parser.parseCommand("addUser User4", userlist);
+
+ assertEquals(4, userlist.getListLength());
+ }
+
+ @Test
+ public void invalidAdduserCommandTest() {
+ try {
+ Parser.parseCommand("addUser", userlist);
+ fail();
+ } catch (Exception e) {
+ assertEquals("[ERROR] Invalid addUser format. Expected format: adduser ",
+ e.getMessage());
+ }
+
+ try {
+ Parser.parseCommand("addUser User1", userlist);
+ Parser.parseCommand("addUser User1", userlist);
+ fail();
+ } catch (Exception e) {
+ assertEquals("User already exists. Use a different name. ", e.getMessage());
+ }
+ }
+
+ @Test
+ public void compareCommandTest() {
+ User user1 = new User("User1");
+ User user2 = new User("User2");
+ userlist.addUser(user1);
+ userlist.addUser(user2);
+
+ try {
+ Parser.parseCommand("compare User1 User1", userlist);
+ Parser.parseCommand("compare user1 user1", userlist);
+ Parser.parseCommand("compare User1 User2", userlist);
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void switchCommandTest() throws InvalidDayException, InvalidFormatException, InvalidUserException,
+ NoUserException, IOException {
+ User user1 = new User("User1");
+ User user2 = new User("User2");
+ userlist.addUser(user1);
+ userlist.addUser(user2);
+ Parser.parseCommand("switch User2", userlist);
+
+ assertEquals(2, userlist.getListLength());
+ assertEquals("User2", userlist.getActiveUser().getName());
+ }
+
+ @Test
+ public void invalidSwitchCommandTest() {
+ User user1 = new User("User1");
+ User user2 = new User("User2");
+ userlist.addUser(user1);
+ userlist.addUser(user2);
+
+ try {
+ Parser.parseCommand("switch", userlist);
+ fail();
+ } catch (InvalidFormatException e) {
+ assertEquals("[ERROR] Invalid switch format. Expected format: switch ",
+ e.getMessage());
+ } catch (Exception e) {
+ fail();
+ }
+
+ try {
+ Parser.parseCommand("switch noUser", userlist);
+ fail();
+ } catch (InvalidUserException e) {
+ assertEquals("User does not exist!", e.getMessage());
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void addTaskCommandTest() throws InvalidDayException, InvalidUserException, InvalidFormatException,
+ NoUserException, IOException {
+
+ //
+ Storage.setFolderPath("test_data");
+ User.setFolderPath("test_data");
+
+ User user1 = new User("User1");
+ userlist.addUser(user1);
+
+ Parser.parseCommand("addtask /on Monday /task test1 /from 9:00 /to 11:00 /type f", userlist);
+ Parser.parseCommand("addtask /on Monday /task test2 /from 13:00 /to 15:00 /type f", userlist);
+ ArrayList testTasksMon = user1.getTimetable().getWeeklyTasks().get("Monday");
+ ArrayList testTasksTue = user1.getTimetable().getWeeklyTasks().get("Tuesday");
+
+ assertEquals("test1", testTasksMon.get(0).getDescription());
+ assertEquals("09:00", testTasksMon.get(0).getStartTime().toString());
+ assertEquals("11:00", testTasksMon.get(0).getEndTime().toString());
+
+ assertEquals("test2", testTasksMon.get(1).getDescription());
+ assertEquals("13:00", testTasksMon.get(1).getStartTime().toString());
+ assertEquals("15:00", testTasksMon.get(1).getEndTime().toString());
+
+ try {
+ String testDescription = testTasksTue.get(1).getDescription();
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ assertEquals("Index 1 out of bounds for length 0", e.getMessage());
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void invalidAddTaskCommandTest() {
+ User user1 = new User("User1");
+ userlist.addUser(user1);
+
+ String expectedErrorMessage = "[ERROR] Invalid addtask format. Expected format: addtask /on [day]" +
+ " /task [description] /from [start time] /to [end time] /type [f/c]";
+ String[] testMessages = {"addtask",
+ "addtask /on Monday",
+ "addtask /on Monday /task description",
+ "addtask /on Monday /task description /from 09:00 /to 11:00",
+ "addtask Monday description 09:00 11:00",
+ "addtask /on MONDAY /task description /from 09:00 /to 11:00"};
+ for (String message : testMessages) {
+ try {
+ Parser.parseCommand(message, userlist);
+ fail();
+ } catch (Exception e) {
+ assertEquals(expectedErrorMessage, e.getMessage());
+ }
+ }
+
+ try {
+ Parser.parseCommand("addtask /on Oneday /task lecture /from 9:00 /to 11:00 /type f", userlist);
+ } catch (Exception e) {
+ assertEquals("[ERROR] Invalid day. Please enter a day from Monday - Sunday.", e.getMessage());
+ }
+
+ try {
+ Parser.parseCommand("addtask /on Monday /task lecture /from 9:00 /to 25:00 /type f", userlist);
+ } catch (Exception e) {
+ assertEquals("Text '25:00' could not be parsed: Invalid value for HourOfDay" +
+ " (valid values 0 - 23): 25", e.getMessage());
+ }
+ }
+
+ @Test
+ public void addForAllTest() throws InvalidDayException, InvalidUserException, InvalidFormatException,
+ NoUserException, IOException {
+ Storage.setFolderPath("test_data");
+ User.setFolderPath("test_data");
+
+ User user1 = new User("User1");
+ User user2 = new User("User2");
+ userlist.addUser(user1);
+ userlist.addUser(user2);
+
+ Parser.parseCommand("addforall /on Monday /task lecture /from 9:00 /to 11:00", userlist);
+
+ Task addedTaskUser1 = user1.getTimetable().getWeeklyTasks().get("Monday").get(0);
+ Task addedTaskUser2 = user1.getTimetable().getWeeklyTasks().get("Monday").get(0);
+
+ assertEquals("lecture", addedTaskUser1.getDescription());
+ assertEquals("lecture", addedTaskUser2.getDescription());
+ assertEquals("09:00", addedTaskUser2.getStartTime().toString());
+ assertEquals("11:00", addedTaskUser2.getEndTime().toString());
+ }
+
+ @Test
+ public void changeTaskTypeTest() throws InvalidDayException, NoUserException, IOException,
+ InvalidUserException, InvalidFormatException {
+ Storage.setFolderPath("test_data");
+ User.setFolderPath("test_data");
+
+ User user1 = new User("User1");
+ userlist.addUser(user1);
+ Parser.parseCommand("addtask /on Monday /task test1 /from 9:00 /to 11:00 /type f", userlist);
+ Task task = user1.getTimetable().getWeeklyTasks().get("Monday").get(0);
+ assertEquals("f", task.getType());
+
+ Parser.parseCommand("changetasktype /on Monday /index 1 /type c", userlist);
+ assertEquals("c", task.getType());
+
+ Parser.parseCommand("changetasktype /on Monday /index 1 /type c", userlist);
+ assertEquals("c", task.getType());
+ }
+
+ @Test
+ public void invalidChangeTaskTypeTest() throws InvalidDayException, NoUserException, IOException,
+ InvalidUserException, InvalidFormatException {
+ Storage.setFolderPath("test_data");
+ User.setFolderPath("test_data");
+
+ User user1 = new User("User1");
+ userlist.addUser(user1);
+ Parser.parseCommand("addtask /on Monday /task test1 /from 9:00 /to 11:00 /type f", userlist);
+ Task task = user1.getTimetable().getWeeklyTasks().get("Monday").get(0);
+ assertEquals("f", task.getType());
+
+ try {
+ Parser.parseCommand("changetasktype /on Monday /index 2 /type c", userlist);
+ fail();
+ } catch (InvalidFormatException e) {
+ assertEquals("The selected task does not exist. ", e.getMessage());
+ } catch (IOException e) {
+ fail();
+ }
+ }
+}
diff --git a/src/test/java/seedu/duke/StorageTest.java b/src/test/java/seedu/duke/StorageTest.java
new file mode 100644
index 0000000000..fec75e3aac
--- /dev/null
+++ b/src/test/java/seedu/duke/StorageTest.java
@@ -0,0 +1,142 @@
+package seedu.duke;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Scanner;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.duke.Parser.DAYS;
+import static seedu.duke.Storage.folderPath;
+import static seedu.duke.Storage.setFolderPath;
+import static seedu.duke.Storage.writeToFile;
+import static seedu.duke.Storage.extractTaskInfo;
+import static seedu.duke.Storage.BOX_OUTLINE;
+import static seedu.duke.Storage.BOX_OUTLINE_FOR_WEDNESDAY;
+import static seedu.duke.Storage.BOX_OUTLINE_FOR_FRIDAY;
+import static seedu.duke.Storage.LINE_SEPARATOR;
+
+
+public class StorageTest {
+
+ private static String filePath;
+
+ @BeforeEach
+ void setUp() {
+ String userName = "testUser";
+ filePath = "test_data/" + userName + ".txt";
+ setFolderPath("test_data");
+ User.setFolderPath("test_data");
+ File folder = new File(folderPath);
+ boolean folderCreated;
+ if (!folder.exists()) {
+ folderCreated = folder.mkdirs();
+ if (folderCreated) {
+ System.out.println("Folder created successfully.");
+ } else {
+ System.out.println("Failed to create folder.");
+ }
+ } else {
+ System.out.println("Folder already exists.");
+ }
+ }
+
+
+ @AfterAll
+ static void resetFolderPath() {
+ Storage.setFolderPath("data");
+ User.setFolderPath("data");
+ }
+
+ @Test
+ void testStorageInit() {
+ User testUser = new User("testUser");
+ assertEquals("test_data/testUser.txt", testUser.getStorage().getFilePath());
+ }
+
+ @Test
+ void testSetFolderPath() {
+ Storage.setFolderPath("testPath");
+ assertEquals("testPath", Storage.getFolderPath());
+ }
+
+ @Test
+ void testAddExistingUsers() throws IOException {
+ setFolderPath("test_data");
+ String userName = "testUser";
+
+ writeToFile(filePath, "Username: " + userName, false);
+ UserList userList = new UserList();
+ Storage.addExistingUsers(userList);
+ assertTrue(userList.containsUser(userName), "UserList should contain the added user");
+ }
+
+ @Test
+ public void testAddNewUserToFolder() {
+ UserList userList = new UserList();
+ User newUser = new User("testAddUser");
+ userList.addUser(newUser);
+ newUser.getStorage().addUserInFolder();
+
+ File directory = new File(folderPath);
+ File file = new File(directory, "testAddUser.txt");
+ System.out.println(directory.getAbsolutePath());
+ assertTrue(file.exists());
+ }
+
+ @Test
+ public void testWriteToFile() throws Exception {
+ User testUser = new User("testUser");
+ testUser.getTimetable().addUserTask("Monday", new Task("lecture", "Monday", "10:00", "11:00", "c"));
+
+ testUser.getStorage().writeTaskInFile(testUser);
+
+ Scanner scanner = new Scanner(new File(filePath));
+ assertTrue(scanner.hasNextLine(), "Empty file.");
+ assertEquals("Username: testUser", scanner.nextLine().trim(), "First line should contain the username");
+ }
+
+ @Test
+ public void testExtractTaskInfo() {
+ String line = "1. 01:00 - 02:00: lecture (type: c)";
+ Task task = extractTaskInfo(line, "Monday");
+ assertEquals("lecture", task.getDescription());
+ assertEquals("01:00", task.getStartTime().toString());
+ assertEquals("02:00", task.getEndTime().toString());
+ assertEquals("c", task.getType());
+ }
+
+ @Test
+ public void testLoadData() throws IOException {
+ writeToFile(filePath, "Username: " + "testUser" + "\n", false);
+ for (String day : DAYS) {
+ String outline;
+ switch (day) {
+ case ("Wednesday"):
+ outline = BOX_OUTLINE_FOR_WEDNESDAY;
+ break;
+ case ("Friday"):
+ outline = BOX_OUTLINE_FOR_FRIDAY;
+ break;
+ default:
+ outline = BOX_OUTLINE;
+ break;
+ }
+ writeToFile(filePath, outline, true);
+ writeToFile(filePath, "| " + day + " |" + "\n", true);
+ writeToFile(filePath, outline, true);
+
+ if (day.equals("Monday")) {
+ writeToFile(filePath, "1. 01:00 - 02:00: lecture (type: c)", true);
+ } else if (day.equals("Thursday")) {
+ writeToFile(filePath, "2. 02:00 - 03:00: lecture (type: f)", true);
+ }
+ writeToFile(filePath, LINE_SEPARATOR, true);
+ writeToFile(filePath, "\n", true);
+ }
+ }
+}
diff --git a/src/test/java/seedu/duke/TimetableTest.java b/src/test/java/seedu/duke/TimetableTest.java
new file mode 100644
index 0000000000..b7af23eb0e
--- /dev/null
+++ b/src/test/java/seedu/duke/TimetableTest.java
@@ -0,0 +1,90 @@
+package seedu.duke;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalTime;
+
+class TimetableTest {
+ @Test
+ public void testAddUserTask() {
+ Timetable timetable = new Timetable();
+ Task task = new Task("Study","2024-03-18", "09:00", "11:00","f");
+
+ timetable.addUserTask("Tuesday", task);
+
+ //timetable.printTasksOfTheDay("Tuesday");
+ assertEquals(1, timetable.getWeeklyTasks().get("Tuesday").size());
+ assertEquals(task, timetable.getWeeklyTasks().get("Tuesday").get(0));
+ }
+ @Test
+ public void testCompareTimetables() {
+ Timetable timetable1 = new Timetable();
+ Timetable timetable2 = new Timetable();
+ Task task1 = new Task("Study","2024-03-18", "09:00", "11:00","f");
+ Task task2 = new Task("Study","2024-03-18", "07:00", "10:00","f");
+ timetable1.addUserTask("Monday", task1);
+ timetable2.addUserTask("Monday", task2);
+
+ Timetable.compareTimetable(timetable1, timetable2);
+ }
+ @Test
+ public void testChangeFlexibleTaskTiming_correctInput() {
+ Timetable timetable = new Timetable();
+ Task flexibleTask = new Task("lec", "monday", "09:00", "11:00", "f");
+ timetable.addUserTask("monday", flexibleTask);
+ try {
+ timetable.changeFlexibleTaskTiming("monday", 0, LocalTime.of(11, 0),
+ LocalTime.of(12, 0));
+ } catch (Exception e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+ @Test
+ public void testChangeFlexibleTaskTiming_invalidIndex(){
+ Timetable timetable = new Timetable();
+ try{
+ timetable.changeFlexibleTaskTiming("monday", 0, LocalTime.of(11, 0),
+ LocalTime.of(12, 0));
+ fail("Expected IndexOutOfBoundsException");
+ } catch(IndexOutOfBoundsException e){
+ assertEquals("Invalid index", e.getMessage());
+ }
+ }
+ @Test
+ public void testChangeFlexibleTaskTiming_nonFlexibleTask() {
+ Timetable timetable = new Timetable();
+ Task nonFlexibleTask = new Task("lec", "monday", "09:00", "11:00", "c");
+ timetable.addUserTask("monday", nonFlexibleTask);
+ try {
+ timetable.changeFlexibleTaskTiming("monday", 0, LocalTime.of(11, 0), LocalTime.of(12, 0));
+ fail("Expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertEquals("Task on monday at index 1 is not flexible, " +
+ "timings cannot be changed.", e.getMessage());
+ }
+ }
+ @Test
+ public void testChangeTaskType_validInput() {
+ Timetable timetable = new Timetable();
+ Task task = new Task("lec", "monday", "09:00", "11:00", "f");
+ timetable.addUserTask("monday", task);
+ try {
+ timetable.changeTaskType("monday", 0, "c");
+ } catch (Exception e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+ @Test
+ public void testChangeTaskType_invalidIndex() {
+ Timetable timetable = new Timetable();
+ try {
+ timetable.changeTaskType("monday", 0, "c");
+ fail("Expected IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ assertEquals("Invalid index", e.getMessage());
+ }
+ }
+}
diff --git a/test_data/User1.txt b/test_data/User1.txt
new file mode 100644
index 0000000000..c5f331da6d
--- /dev/null
+++ b/test_data/User1.txt
@@ -0,0 +1,43 @@
+Username: User1
++---------+
+| Monday |
++---------+
+1. 09:00 - 11:00: test1 (type: c)
+.................................................................................................
+
++---------+
+| Tuesday |
++---------+
+No task :)
+.................................................................................................
+
++-------------+
+| Wednesday |
++-------------+
+No task :)
+.................................................................................................
+
++---------+
+| Thursday |
++---------+
+No task :)
+.................................................................................................
+
++------+
+| Friday |
++------+
+No task :)
+.................................................................................................
+
++---------+
+| Saturday |
++---------+
+No task :)
+.................................................................................................
+
++---------+
+| Sunday |
++---------+
+No task :)
+.................................................................................................
+
diff --git a/test_data/User2.txt b/test_data/User2.txt
new file mode 100644
index 0000000000..4a28a75079
--- /dev/null
+++ b/test_data/User2.txt
@@ -0,0 +1,43 @@
+Username: User2
++---------+
+| Monday |
++---------+
+1. 09:00 - 11:00: lecture (type: common)
+.................................................................................................
+
++---------+
+| Tuesday |
++---------+
+No task :)
+.................................................................................................
+
++-------------+
+| Wednesday |
++-------------+
+No task :)
+.................................................................................................
+
++---------+
+| Thursday |
++---------+
+No task :)
+.................................................................................................
+
++------+
+| Friday |
++------+
+No task :)
+.................................................................................................
+
++---------+
+| Saturday |
++---------+
+No task :)
+.................................................................................................
+
++---------+
+| Sunday |
++---------+
+No task :)
+.................................................................................................
+
diff --git a/test_data/User3.txt b/test_data/User3.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/test_data/User4.txt b/test_data/User4.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/test_data/testAddUser.txt b/test_data/testAddUser.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/test_data/testUser.txt b/test_data/testUser.txt
new file mode 100644
index 0000000000..f7c6c3dddf
--- /dev/null
+++ b/test_data/testUser.txt
@@ -0,0 +1 @@
+Username: testUser
\ No newline at end of file
diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT
index 892cb6cae7..f658c87e1c 100644
--- a/text-ui-test/EXPECTED.TXT
+++ b/text-ui-test/EXPECTED.TXT
@@ -1,9 +1,112 @@
-Hello from
- ____ _
-| _ \ _ _| | _____
-| | | | | | | |/ / _ \
-| |_| | |_| | < __/
-|____/ \__,_|_|\_\___|
-
-What is your name?
-Hello James Gosling
+Timetable comparison app opened.
+Folder created successfully.
+Note: use hh:mm 24hr time format (ex. 13:00)
+List of available commands:
+_________________________________________
+View list of commands (what you are looking at):
+help
+_________________________________________
+List all users:
+list
+_________________________________________
+Exit the app:
+bye
+_________________________________________
+View current user:
+current
+_________________________________________
+View timetable of current user:
+view
+_________________________________________
+View your next task:
+next
+_________________________________________
+Add new user:
+adduser
+_________________________________________
+Switch to user:
+switch
+_________________________________________
+Add task for current user:
+addtask /on /task /from /to /type
+_________________________________________
+Add task for current user (check duplicates):
+addtwdc /on /task /from /to /type
+_________________________________________
+Add a task for all users:
+addforall /on /task /from /to
+_________________________________________
+Add a task that repeats over certain days:
+addrepeattask /on /task /from /to /type
+_________________________________________
+Add a task for certain users:
+addfor /user /on /task /from /to /type
+_________________________________________
+Delete task:
+deletetask
+_________________________________________
+Change a task's timing:
+changetasktiming /on /index /from /to
+_________________________________________
+Change a task's type:
+changetasktype /on /index /type
+_________________________________________
+Compare timetables of all users:
+compareall
+_________________________________________
+Compare timetables between two users:
+compare
+_________________________________________
+List today's tasks:
+todaytasks
+_________________________________________
+List urgent tasks within certain timeframe:
+urgent /in
+_________________________________________
+View common events:
+viewcommonevents
+____________________________________________________________
+New user added: Simon
+The active user is: Simon
+File created: Simon.txt
+The following task is added: lecture (Monday from 09:00 to 11:00) type: f
+Timetable has been written to data/Simon.txt
+New user added: Tim
+File created: Tim.txt
+The active user is: Tim
+The following task is added: lecture (Monday from 09:00 to 11:00) type: f
+Timetable has been written to data/Tim.txt
+_________________________________________
+Monday :
+ 1. lecture (Monday from 09:00 to 11:00) type: f
+No task for Tuesday!
+No task for Wednesday!
+No task for Thursday!
+No task for Friday!
+No task for Saturday!
+No task for Sunday!
+Comparing timetables of Simon and Tim:
+____________________________________________________________
+Shared free time on Monday:
+ 00:00 - 09:00
+ 11:00 - 23:59
+____________________________________________________________
+Shared free time on Tuesday:
+ ** Whole day is free on Tuesday
+____________________________________________________________
+Shared free time on Wednesday:
+ ** Whole day is free on Wednesday
+____________________________________________________________
+Shared free time on Thursday:
+ ** Whole day is free on Thursday
+____________________________________________________________
+Shared free time on Friday:
+ ** Whole day is free on Friday
+____________________________________________________________
+Shared free time on Saturday:
+ ** Whole day is free on Saturday
+____________________________________________________________
+Shared free time on Sunday:
+ ** Whole day is free on Sunday
+[ERROR] Invalid day. Please enter a day from Monday - Sunday.
+Bye.
diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt
index f6ec2e9f95..e38cfc6f9f 100644
--- a/text-ui-test/input.txt
+++ b/text-ui-test/input.txt
@@ -1 +1,9 @@
-James Gosling
\ No newline at end of file
+adduser simon
+addtask /on Monday /task lecture /from 9:00 /to 11:00 /type f
+adduser tim
+switch tim
+addtask /on Monday /task lecture /from 9:00 /to 11:00 /type f
+view
+compare simon tim
+addtask /on Eightday /task lecture /from 9:00 /to 11:00 /type f
+bye
diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat
index 25ac7a2989..181ca9d40c 100644
--- a/text-ui-test/runtest.bat
+++ b/text-ui-test/runtest.bat
@@ -16,4 +16,8 @@ java -jar %jarloc% < ..\..\text-ui-test\input.txt > ..\..\text-ui-test\ACTUAL.TX
cd ..\..\text-ui-test
+:: PowerShell commands to trim trailing spaces
+powershell -Command "(Get-Content -Path EXPECTED.TXT) | ForEach-Object { $_.TrimEnd() } | Set-Content -Path EXPECTED.TXT"
+powershell -Command "(Get-Content -Path ACTUAL.TXT) | ForEach-Object { $_.TrimEnd() } | Set-Content -Path ACTUAL.TXT"
+
FC ACTUAL.TXT EXPECTED.TXT >NUL && ECHO Test passed! || Echo Test failed!
diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh
index 1dcbd12021..fade424594 100755
--- a/text-ui-test/runtest.sh
+++ b/text-ui-test/runtest.sh
@@ -12,6 +12,10 @@ java -jar $(find ../build/libs/ -mindepth 1 -print -quit) < input.txt > ACTUAL.
cp EXPECTED.TXT EXPECTED-UNIX.TXT
dos2unix EXPECTED-UNIX.TXT ACTUAL.TXT
+
+sed -i'' -e 's/[[:space:]]*$//' EXPECTED-UNIX.TXT
+sed -i'' -e 's/[[:space:]]*$//' ACTUAL.TXT
+
diff EXPECTED-UNIX.TXT ACTUAL.TXT
if [ $? -eq 0 ]
then