package service import ( "testing" "github.com/simpletodoapp/go-todo-app/internal/dto" "github.com/simpletodoapp/go-todo-app/internal/model" "gorm.io/driver/sqlite" "gorm.io/gorm" ) // setupTestDB sets up an in-memory SQLite database for testing func setupTestDB(t *testing.T) *gorm.DB { db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{}) if err != nil { t.Fatalf("Failed to connect to in-memory database: %v", err) } // Auto-migrate the schema err = db.AutoMigrate(&model.Todo{}) if err != nil { t.Fatalf("Failed to migrate test database: %v", err) } return db } // populateTestData adds test data to the database func populateTestData(t *testing.T, db *gorm.DB) { todos := []model.Todo{ { Title: "Test Todo 1", Description: "Test Description 1", Completed: false, }, { Title: "Test Todo 2", Description: "Test Description 2", Completed: true, }, } for _, todo := range todos { if err := db.Create(&todo).Error; err != nil { t.Fatalf("Failed to create test data: %v", err) } } } func TestGetTodos(t *testing.T) { db := setupTestDB(t) populateTestData(t, db) service := NewTodoService(db) // Test getting all todos todos, err := service.GetTodos(0, 100, nil) if err != nil { t.Fatalf("Failed to get todos: %v", err) } if len(todos) != 2 { t.Errorf("Expected 2 todos, got %d", len(todos)) } // Test filtering by completed completed := true todos, err = service.GetTodos(0, 100, &completed) if err != nil { t.Fatalf("Failed to get completed todos: %v", err) } if len(todos) != 1 { t.Errorf("Expected 1 completed todo, got %d", len(todos)) } if !todos[0].Completed { t.Errorf("Expected todo to be completed, got %t", todos[0].Completed) } // Test pagination todos, err = service.GetTodos(1, 1, nil) if err != nil { t.Fatalf("Failed to get paginated todos: %v", err) } if len(todos) != 1 { t.Errorf("Expected 1 todo with pagination, got %d", len(todos)) } } func TestCreateTodo(t *testing.T) { db := setupTestDB(t) service := NewTodoService(db) // Create a new todo todoCreate := dto.TodoCreate{ TodoBase: dto.TodoBase{ Title: "New Todo", Description: "New Description", Completed: false, }, } todo, err := service.CreateTodo(todoCreate) if err != nil { t.Fatalf("Failed to create todo: %v", err) } if todo.ID == 0 { t.Errorf("Expected todo ID to be set, got %d", todo.ID) } if todo.Title != "New Todo" { t.Errorf("Expected title to be 'New Todo', got '%s'", todo.Title) } if todo.Description != "New Description" { t.Errorf("Expected description to be 'New Description', got '%s'", todo.Description) } if todo.Completed != false { t.Errorf("Expected completed to be false, got %t", todo.Completed) } } func TestGetTodoByID(t *testing.T) { db := setupTestDB(t) populateTestData(t, db) service := NewTodoService(db) // Get a todo by ID todo, err := service.GetTodoByID(1) if err != nil { t.Fatalf("Failed to get todo by ID: %v", err) } if todo == nil { t.Fatalf("Expected todo to be found, got nil") } if todo.ID != 1 { t.Errorf("Expected todo ID to be 1, got %d", todo.ID) } // Test non-existent todo todo, err = service.GetTodoByID(999) if err != nil { t.Fatalf("Expected no error for non-existent todo, got %v", err) } if todo != nil { t.Errorf("Expected nil for non-existent todo, got %+v", todo) } } func TestUpdateTodo(t *testing.T) { db := setupTestDB(t) populateTestData(t, db) service := NewTodoService(db) // Update a todo title := "Updated Title" completed := true todoUpdate := dto.TodoUpdate{ Title: &title, Completed: &completed, } todo, err := service.UpdateTodo(1, todoUpdate) if err != nil { t.Fatalf("Failed to update todo: %v", err) } if todo.Title != "Updated Title" { t.Errorf("Expected title to be 'Updated Title', got '%s'", todo.Title) } if !todo.Completed { t.Errorf("Expected completed to be true, got %t", todo.Completed) } // Test updating non-existent todo todo, err = service.UpdateTodo(999, todoUpdate) if err != nil { t.Fatalf("Expected no error for non-existent todo, got %v", err) } if todo != nil { t.Errorf("Expected nil for non-existent todo, got %+v", todo) } } func TestDeleteTodo(t *testing.T) { db := setupTestDB(t) populateTestData(t, db) service := NewTodoService(db) // Delete a todo deleted, err := service.DeleteTodo(1) if err != nil { t.Fatalf("Failed to delete todo: %v", err) } if !deleted { t.Errorf("Expected todo to be deleted") } // Try to get the deleted todo todo, err := service.GetTodoByID(1) if err != nil { t.Fatalf("Unexpected error after deletion: %v", err) } if todo != nil { t.Errorf("Expected todo to be nil after deletion, got %+v", todo) } // Test deleting non-existent todo deleted, err = service.DeleteTodo(999) if err != nil { t.Fatalf("Expected no error for non-existent todo, got %v", err) } if deleted { t.Errorf("Expected false for deleting non-existent todo, got %t", deleted) } }