diff --git a/domain-model.png b/domain-model.png new file mode 100644 index 000000000..5e44d85ae Binary files /dev/null and b/domain-model.png differ diff --git a/src/main/java/com/booleanuk/core/TodoList.java b/src/main/java/com/booleanuk/core/TodoList.java index 675adaf0b..17739e973 100644 --- a/src/main/java/com/booleanuk/core/TodoList.java +++ b/src/main/java/com/booleanuk/core/TodoList.java @@ -1,5 +1,108 @@ package com.booleanuk.core; +import java.util.*; + public class TodoList { + Map tasks; + + public TodoList(Map tasks) { + this.tasks = tasks; + } + + public Boolean addTask(String taskName) { + taskName = taskName.strip().toLowerCase(); + if (taskName.isBlank()) { + return null; + } + + for (String key : tasks.keySet()) { + if (taskName.equals(key.toLowerCase())) { + return false; + } + } + tasks.put(taskName, false); // not completed by default + return true; + } + + public List getTasks() { + return new ArrayList<>(tasks.keySet()); + } + + public List getCompletedTasks() { + List completedTasks = new ArrayList<>(); + for (String key : tasks.keySet()) { + if (tasks.get(key)) { + completedTasks.add(key); + } + } + return completedTasks; + } + + public List getIncompleteTasks() { + List incompleteTasks = new ArrayList<>(); + for (String key : tasks.keySet()) { + if (!tasks.get(key)) { + incompleteTasks.add(key); + } + } + return incompleteTasks; + } + + public Boolean changeTaskStatus(String taskName) { + taskName = taskName.strip().toLowerCase(); + if (taskName.isBlank()) + return false; + + for (String key : tasks.keySet()) { + if (taskName.equals(key.toLowerCase())) { + tasks.put(key, !tasks.get(key)); + return true; + } + } + return false; + } + + public List searchTask(String searchString) { + List searchResults = new ArrayList<>(); + + for (String key : tasks.keySet()) { + if (key.toLowerCase().contains(searchString)) { + searchResults.add(key); + } + } + + if (searchResults.isEmpty()) { + searchResults.add("No tasks found"); + } + + return searchResults; + } + + public Boolean removeTask(String taskName) { + taskName = taskName.strip().toLowerCase(); + if (taskName.isBlank()) { + return false; + } + + for (String key : tasks.keySet()) { + if (taskName.equals(key.toLowerCase())) { + tasks.remove(key); + return true; + } + } + return false; + } + + public List getAllTasksOrdered(boolean descending) { + + List sortedTasks = new ArrayList<>(tasks.keySet()); + + if (!descending) { + return sortedTasks.stream().sorted().toList(); + } else { + return sortedTasks.stream().sorted().toList().reversed(); + } + } + } diff --git a/src/main/java/com/booleanuk/extension/Task.java b/src/main/java/com/booleanuk/extension/Task.java new file mode 100644 index 000000000..dc785981c --- /dev/null +++ b/src/main/java/com/booleanuk/extension/Task.java @@ -0,0 +1,49 @@ +package com.booleanuk.extension; + +import java.time.LocalDateTime; + +public class Task { + private int id; + private String name; + private boolean completed; + private LocalDateTime creationDate; + + public Task(int id, String name, boolean completed, LocalDateTime creationDate) { + this.id = id; + this.name = name; + this.completed = completed; + this.creationDate = creationDate; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isCompleted() { + return completed; + } + + public void setCompleted(boolean completionStatus) { + this.completed = completionStatus; + } + + public LocalDateTime getCreationDate() { + return creationDate; + } + + public void setCreationDate(LocalDateTime creationDate) { + this.creationDate = creationDate; + } +} diff --git a/src/main/java/com/booleanuk/extension/TodoListExtension.java b/src/main/java/com/booleanuk/extension/TodoListExtension.java new file mode 100644 index 000000000..d0c3c0e8e --- /dev/null +++ b/src/main/java/com/booleanuk/extension/TodoListExtension.java @@ -0,0 +1,46 @@ +package com.booleanuk.extension; + +import java.time.LocalDateTime; +import java.util.List; + +public class TodoListExtension { + + List tasks; + + public TodoListExtension(List tasks) { + this.tasks = tasks; + } + + public String searchTaskById(int taskId) { + return tasks.stream() + .filter(t -> t.getId() == taskId) + .findFirst() + .map(Task::getName) + .orElse("No task found"); + } + + public Boolean updateTaskNameById(int taskId, String newName) { + return tasks.stream() + .filter(t -> t.getId() == taskId) + .findFirst() + .map(t -> { t.setName(newName); return true;}) + .orElse(false); + } + + public Boolean changeTaskStatusById(int taskId) { + return tasks.stream() + .filter(t -> t.getId() == taskId) + .findFirst() + .map(t -> {t.setCompleted(!t.isCompleted()); return true;}) + .orElse(false); + } + + public LocalDateTime getTaskCreationDate(int taskId) { + return tasks.stream() + .filter(t -> t.getId() == taskId) + .findFirst() + .map(Task::getCreationDate) + .orElse(null); + } + +} diff --git a/src/test/java/com/booleanuk/core/TodoListTest.java b/src/test/java/com/booleanuk/core/TodoListTest.java index 0bef779a4..fcb6c9e90 100644 --- a/src/test/java/com/booleanuk/core/TodoListTest.java +++ b/src/test/java/com/booleanuk/core/TodoListTest.java @@ -3,11 +3,262 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + class TodoListTest { + + Map tasks = null; + + /* + addTask(String taskName) + */ + @Test + public void addTaskNotAlreadyInTaskListShouldReturnTrue() { + this.tasks = new LinkedHashMap<>(); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(true, tl.addTask("Eat")); + Assertions.assertEquals(true, tl.addTask("Work out")); + Assertions.assertEquals(true, tl.addTask("Do some programming")); + } + + @Test + public void addTaskAlreadyInTaskListShouldReturnFalse() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", false); + tasks.put("Work out", false); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(false, tl.addTask("Eat")); + Assertions.assertEquals(false, tl.addTask("eat")); + Assertions.assertEquals(false, tl.addTask("Work out")); + Assertions.assertEquals(false, tl.addTask("work out")); + } + + @Test + public void addTaskInvalidNameShouldReturnNull() { + this.tasks = new LinkedHashMap<>(); + + TodoList tl = new TodoList(tasks); + + Assertions.assertNull(tl.addTask(" ")); + Assertions.assertNull(tl.addTask(" ")); + Assertions.assertNull(tl.addTask("")); + } + + /* + getTasks() + */ + @Test + public void getTasksTaskMapNotEmpty() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", false); + tasks.put("Work out", false); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(List.of("Eat", "Work out"), tl.getTasks()); + } + + @Test + public void getTasksWhenMapIsEmpty() { + this.tasks = new LinkedHashMap<>(); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(List.of(), tl.getTasks()); + } + + /* + getCompletedTasks() + */ + @Test + public void getCompletedTasksWhenCompletedTasksExist() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", true); + tasks.put("Work out", true); + tasks.put("Do some programming", false); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(List.of("Eat", "Work out"), tl.getCompletedTasks()); + } + + @Test + public void getCompletedTasksWhenCompletedTasksDontExist() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", false); + tasks.put("Work out", false); + tasks.put("Do some programming", false); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(List.of(), tl.getCompletedTasks()); + } + + /* + getIncompleteTasks + */ + @Test + public void getIncompleteTasksWhenIncompleteTasksExist() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", true); + tasks.put("Work out", true); + tasks.put("Do some programming", false); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(List.of("Do some programming"), tl.getIncompleteTasks()); + } + + @Test + public void getIncompleteTasksWhenIncompleteTasksDontExist() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", false); + tasks.put("Work out", false); + tasks.put("Do some programming", true); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(List.of("Eat", "Work out"), tl.getIncompleteTasks()); + } + + /* + changeTaskStatus(String taskName) + */ @Test - public void exampleTest() { - String hello = "Hello"; - Assertions.assertEquals("Hello", hello); - Assertions.assertNotEquals("Goodbye", hello); + public void changeTaskStatusWhenTaskExistsAndIsIncomplete() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", false); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(true, tl.changeTaskStatus("Eat")); + Assertions.assertEquals(true, tasks.get("Eat")); + Assertions.assertEquals(true, tl.changeTaskStatus("eat")); + Assertions.assertEquals(false, tasks.get("Eat")); + } + + @Test + public void changeTaskStatusWhenTaskExistsAndIsCompleted() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", true); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(true, tl.changeTaskStatus("Eat")); + Assertions.assertEquals(false, tasks.get("Eat")); + Assertions.assertEquals(true, tl.changeTaskStatus("eat")); + Assertions.assertEquals(true, tasks.get("Eat")); + } + + @Test + public void changeTaskStatusWhenTasksDoesNotExist() { + this.tasks = new LinkedHashMap<>(); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(false, tl.changeTaskStatus("Eat")); + Assertions.assertEquals(false, tl.changeTaskStatus("work out")); + } + + /* + searchTask(String searchString) + */ + @Test + public void searchTaskResultFound() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", false); + tasks.put("Work out", false); + tasks.put("Do some programming today", false); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(List.of("Eat", "Work out", "Do some programming today"), tl.searchTask("t")); + Assertions.assertEquals(List.of("Work out", "Do some programming today"), tl.searchTask("o")); + Assertions.assertEquals(List.of("Eat"), tl.searchTask("eat")); + } + + @Test + public void searchTaskResultNotFound() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", false); + tasks.put("Work out", false); + tasks.put("Do some programming today", false); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(List.of("No tasks found"), tl.searchTask("z")); + Assertions.assertEquals(List.of("No tasks found"), tl.searchTask("zx")); + Assertions.assertEquals(List.of("No tasks found"), tl.searchTask(":123!")); + } + + /* + removeTask(String taskName) + */ + @Test + public void removeTaskThatExists() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", false); + tasks.put("Work out", false); + tasks.put("Do some programming today", false); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(true, tl.removeTask("Eat")); + Assertions.assertEquals(true, tl.removeTask("work out")); + Assertions.assertEquals(true, tl.removeTask("Do some programming Today")); + } + + @Test + public void removeTaskThatDoesNotExist() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", false); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(false, tl.removeTask("work out")); + Assertions.assertEquals(false, tl.removeTask("Do some programming Today")); + } + + /* + getAllTasksOrdered(boolean descending) + */ + @Test + public void getAllTasksOrderedWhenNoTasksExist() { + this.tasks = new LinkedHashMap<>(); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(List.of(), tl.getAllTasksOrdered(false)); + Assertions.assertEquals(List.of(), tl.getAllTasksOrdered(true)); + } + + @Test + public void getAllTasksOrderedAscending() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", false); + tasks.put("Work out", false); + tasks.put("Do some programming today", false); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(List.of("Do some programming today", "Eat", "Work out"), tl.getAllTasksOrdered(false)); + } + + @Test + public void getAllTasksOrderedDescending() { + this.tasks = new LinkedHashMap<>(); + tasks.put("Eat", false); + tasks.put("Work out", false); + tasks.put("Do some programming today", false); + + TodoList tl = new TodoList(tasks); + + Assertions.assertEquals(List.of("Work out", "Eat", "Do some programming today"), tl.getAllTasksOrdered(true)); } } diff --git a/src/test/java/com/booleanuk/extension/TodoListExtensionTest.java b/src/test/java/com/booleanuk/extension/TodoListExtensionTest.java new file mode 100644 index 000000000..4e5db6ed4 --- /dev/null +++ b/src/test/java/com/booleanuk/extension/TodoListExtensionTest.java @@ -0,0 +1,101 @@ +package com.booleanuk.extension; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +public class TodoListExtensionTest { + + List tasks = null; + + @Test + public void searchTaskByIdTaskNotExistsReturnsMessage() { + tasks = new ArrayList<>(); + + TodoListExtension tl = new TodoListExtension(tasks); + + Assertions.assertEquals("No task found", tl.searchTaskById(1)); + } + + @Test + public void searchTaskByIdExistsReturnsTaskName() { + tasks = new ArrayList<>(); + LocalDateTime taskDate = LocalDateTime.now(); + tasks.add(new Task(1, "Eat", false, taskDate)); + + TodoListExtension tl = new TodoListExtension(tasks); + + Assertions.assertEquals("Eat", tl.searchTaskById(1)); + } + + @Test + public void updateTaskNameByIdTaskNotExist() { + tasks = new ArrayList<>(); + + TodoListExtension tl = new TodoListExtension(tasks); + + Assertions.assertEquals(false, tl.updateTaskNameById(1, "New name")); + } + + @Test + public void updateTaskNameByIdTaskExists() { + tasks = new ArrayList<>(); + LocalDateTime taskDate = LocalDateTime.now(); + Task t = new Task(1, "Eat", false, taskDate); + tasks.add(t); + + TodoListExtension tl = new TodoListExtension(tasks); + + Assertions.assertEquals(true, tl.updateTaskNameById(1, "New name")); + Assertions.assertEquals("New name", t.getName()); + } + + @Test + public void changeTaskCompletionStatusTaskNotExist() { + tasks = new ArrayList<>(); + + TodoListExtension tl = new TodoListExtension(tasks); + + Assertions.assertEquals(false, tl.changeTaskStatusById(1)); + } + + @Test + public void changeTaskCompletionStatusTaskExists() { + tasks = new ArrayList<>(); + LocalDateTime taskDate = LocalDateTime.now(); + Task t = new Task(1, "Eat", false, taskDate); + tasks.add(t); + + TodoListExtension tl = new TodoListExtension(tasks); + + Assertions.assertEquals(true, tl.changeTaskStatusById(1)); + Assertions.assertTrue(t.isCompleted()); + Assertions.assertEquals(true, tl.changeTaskStatusById(1)); + Assertions.assertFalse(t.isCompleted()); + } + + @Test + public void getDateAndTimeByIdTaskNotExistReturnsNull() { + tasks = new ArrayList<>(); + + TodoListExtension tl = new TodoListExtension(tasks); + + Assertions.assertNull(tl.getTaskCreationDate(1)); + } + + @Test + public void getDateAndTimeByIdTaskExists() { + tasks = new ArrayList<>(); + LocalDateTime taskDate = LocalDateTime.now(); + Task t = new Task(1, "Eat", false, taskDate); + tasks.add(t); + + TodoListExtension tl = new TodoListExtension(tasks); + + Assertions.assertEquals(taskDate, tl.getTaskCreationDate(1)); + } + +}