diff --git a/cmd/main.go b/cmd/main.go index fbd9193..ee9482c 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -35,5 +35,5 @@ func main() { if err != nil { log.Fatal(err) } - fmt.Printf("ID of created todo: %d", newTodo.Id) + fmt.Printf("ID of created todo: %d\n", newTodo.Id) } diff --git a/internal/todo/repository/inmemory/inmemory.go b/internal/todo/repository/inmemory/inmemory.go index 249e9ca..39cbaef 100644 --- a/internal/todo/repository/inmemory/inmemory.go +++ b/internal/todo/repository/inmemory/inmemory.go @@ -5,20 +5,20 @@ import ( ) type InMemoryTodoRepository struct { - db map[int64]repository.TodoRow + Db map[int64]repository.TodoRow id int64 } func NewInMemoryTodoRepository() InMemoryTodoRepository { return InMemoryTodoRepository{ - db: make(map[int64]repository.TodoRow), + Db: make(map[int64]repository.TodoRow), id: 1, } } func (r *InMemoryTodoRepository) GetById(id int64) (repository.TodoRow, error) { - todo, found := r.db[id] + todo, found := r.Db[id] if !found { return todo, repository.ErrNotFound @@ -29,32 +29,32 @@ func (r *InMemoryTodoRepository) GetById(id int64) (repository.TodoRow, error) { func (r *InMemoryTodoRepository) Create(todo repository.TodoRow) (repository.TodoRow, error) { todo.Id = r.id - r.db[r.id] = todo + r.Db[r.id] = todo r.id++ return todo, nil } func (r *InMemoryTodoRepository) Update(todo repository.TodoRow) error { - _, found := r.db[todo.Id] + _, found := r.Db[todo.Id] if !found { return repository.ErrNotFound } - r.db[todo.Id] = todo + r.Db[todo.Id] = todo return nil } func (r *InMemoryTodoRepository) Delete(id int64) error { - _, found := r.db[id] + _, found := r.Db[id] if !found { return repository.ErrNotFound } - delete(r.db, id) + delete(r.Db, id) return nil } diff --git a/internal/todo/repository/repository.go b/internal/todo/repository/repository.go index 13b9d7d..172c0ba 100644 --- a/internal/todo/repository/repository.go +++ b/internal/todo/repository/repository.go @@ -14,8 +14,8 @@ type TodoRow struct { Done bool } -func NewTodoDbModel(name string, done bool) *TodoRow { - return &TodoRow{Name: name, Done: done} +func NewTodoRow(name string, done bool) TodoRow { + return TodoRow{Name: name, Done: done} } type TodoRepository interface { diff --git a/internal/todo/service/service.go b/internal/todo/service/service.go index b1514f4..3e55ab4 100644 --- a/internal/todo/service/service.go +++ b/internal/todo/service/service.go @@ -1,9 +1,17 @@ package service -import "gitea.michaelthomson.dev/mthomson/habits/internal/todo/repository" +import ( + "errors" + + "gitea.michaelthomson.dev/mthomson/habits/internal/todo/repository" +) + +var ( + ErrNotFound error = errors.New("Todo cannot be found") +) type Todo struct { - Id int64 + Id int64 Name string Done bool } @@ -20,6 +28,10 @@ func TodoRowFromTodo(todo Todo) repository.TodoRow { return repository.TodoRow{Id: todo.Id, Name: todo.Name, Done: todo.Done} } +func (t Todo) Equal(todo Todo) bool { + return t.Id == todo.Id && t.Name == todo.Name && t.Done == todo.Done +} + type TodoGetter interface { GetTodo(id int64) (Todo, error) } @@ -48,6 +60,10 @@ func (s *TodoService) GetTodo(id int64) (Todo, error) { todo, err := s.repo.GetById(id) if err != nil { + if err == repository.ErrNotFound { + return Todo{}, ErrNotFound + } + return Todo{}, err } @@ -67,7 +83,11 @@ func (s *TodoService) CreateTodo(todo Todo) (Todo, error) { } func (s *TodoService) DeleteTodo(id int64) error { - err := s.repo.Delete(id); + err := s.repo.Delete(id) + + if err == repository.ErrNotFound { + return ErrNotFound + } return err } @@ -77,5 +97,9 @@ func (s *TodoService) UpdateTodo(todo Todo) error { err := s.repo.Update(todoRow) + if err == repository.ErrNotFound { + return ErrNotFound + } + return err } diff --git a/internal/todo/service/service_test.go b/internal/todo/service/service_test.go index c7cecea..6fb7422 100644 --- a/internal/todo/service/service_test.go +++ b/internal/todo/service/service_test.go @@ -3,6 +3,7 @@ package service_test import ( "testing" + "gitea.michaelthomson.dev/mthomson/habits/internal/todo/repository" "gitea.michaelthomson.dev/mthomson/habits/internal/todo/repository/inmemory" "gitea.michaelthomson.dev/mthomson/habits/internal/todo/service" ) @@ -17,8 +18,96 @@ func TestCreateTodo(t *testing.T) { _, err := todoService.CreateTodo(todo) - if err != nil { - t.Error(err) - } + AssertNoError(t, err) }) } + +func TestGetTodo(t *testing.T) { + todoRepository := inmemory.NewInMemoryTodoRepository() + + todoRepository.Db[1] = repository.TodoRow{Id: 1, Name: "clean dishes", Done: false} + + todoService := service.NewTodoService(&todoRepository) + + t.Run("Get exisiting todo", func(t *testing.T) { + _, err := todoService.GetTodo(1) + + AssertNoError(t, err) + }) + + t.Run("Get non-existant todo", func(t *testing.T) { + _, err := todoService.GetTodo(2) + + AssertErrors(t, err, service.ErrNotFound) + }) +} + +func TestDeleteTodo(t *testing.T) { + todoRepository := inmemory.NewInMemoryTodoRepository() + + todoRepository.Db[1] = repository.TodoRow{Id: 1, Name: "clean dishes", Done: false} + + todoService := service.NewTodoService(&todoRepository) + + t.Run("Delete exisiting todo", func(t *testing.T) { + err := todoService.DeleteTodo(1) + + AssertNoError(t, err) + }) + + t.Run("Delete non-existant todo", func(t *testing.T) { + err := todoService.DeleteTodo(1) + + AssertErrors(t, err, service.ErrNotFound) + }) +} + +func TestUpdateTodo(t *testing.T) { + todoRepository := inmemory.NewInMemoryTodoRepository() + + todoRepository.Db[1] = repository.TodoRow{Id: 1, Name: "clean dishes", Done: false} + + todoService := service.NewTodoService(&todoRepository) + + t.Run("Update exisiting todo", func(t *testing.T) { + todo := service.Todo{1, "clean dishes", true} + + err := todoService.UpdateTodo(todo) + + AssertNoError(t, err) + + newTodo, err := todoService.GetTodo(1) + + AssertNoError(t, err) + + AssertTodos(t, newTodo, todo) + }) + + t.Run("Update non-existant todo", func(t *testing.T) { + todo := service.Todo{2, "clean dishes", true} + + err := todoService.UpdateTodo(todo) + + AssertErrors(t, err, service.ErrNotFound) + }) +} + +func AssertErrors(t testing.TB, got, want error) { + t.Helper() + if got != want { + t.Errorf("got error: %v, want error: %v", want, got) + } +} + +func AssertNoError(t testing.TB, err error) { + t.Helper() + if err != nil { + t.Errorf("expected no error, got %v", err) + } +} + +func AssertTodos(t testing.TB, got, want service.Todo) { + if !got.Equal(want) { + t.Errorf("got %+v want %+v", got, want) + } +}