package repositories import ( "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/treytartt/honeydue-api/internal/models" "github.com/treytartt/honeydue-api/internal/testutil" ) func TestGetCompletionSummary_EmptyResidence(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewTaskRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") now := time.Date(2026, 3, 15, 0, 0, 0, 0, time.UTC) summary, err := repo.GetCompletionSummary(residence.ID, now, 10) require.NoError(t, err) assert.Equal(t, 0, summary.TotalAllTime) assert.Equal(t, 0, summary.TotalLast12Months) assert.Len(t, summary.Months, 12) // First month should be March 2025 assert.Equal(t, "2025-03", summary.Months[0].Month) // Last month should be February 2026 assert.Equal(t, "2026-02", summary.Months[11].Month) } func TestGetCompletionSummary_CountsByMonthAndColumn(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewTaskRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix roof") now := time.Date(2026, 3, 15, 0, 0, 0, 0, time.UTC) completions := []models.TaskCompletion{ {TaskID: task.ID, CompletedByID: user.ID, CompletedAt: time.Date(2026, 1, 10, 12, 0, 0, 0, time.UTC), CompletedFromColumn: "overdue_tasks"}, {TaskID: task.ID, CompletedByID: user.ID, CompletedAt: time.Date(2026, 1, 20, 12, 0, 0, 0, time.UTC), CompletedFromColumn: "completed_tasks"}, {TaskID: task.ID, CompletedByID: user.ID, CompletedAt: time.Date(2026, 2, 5, 12, 0, 0, 0, time.UTC), CompletedFromColumn: "due_soon_tasks"}, {TaskID: task.ID, CompletedByID: user.ID, CompletedAt: time.Date(2025, 6, 1, 12, 0, 0, 0, time.UTC), CompletedFromColumn: "upcoming_tasks"}, } for i := range completions { require.NoError(t, db.Create(&completions[i]).Error) } summary, err := repo.GetCompletionSummary(residence.ID, now, 10) require.NoError(t, err) assert.Equal(t, 4, summary.TotalAllTime) assert.Equal(t, 4, summary.TotalLast12Months) for _, m := range summary.Months { switch m.Month { case "2026-01": assert.Equal(t, 2, m.Total, "January should have 2 completions") assert.Len(t, m.Completions, 2, "January should have 2 column entries") case "2026-02": assert.Equal(t, 1, m.Total, "February should have 1 completion") case "2025-06": assert.Equal(t, 1, m.Total, "June 2025 should have 1 completion") } } } func TestGetCompletionSummary_Overflow(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewTaskRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := testutil.CreateTestResidence(t, db, user.ID, "Busy House") task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Lots of tasks") now := time.Date(2026, 3, 15, 0, 0, 0, 0, time.UTC) for i := 0; i < 15; i++ { c := models.TaskCompletion{ TaskID: task.ID, CompletedByID: user.ID, CompletedAt: time.Date(2026, 2, 1+i, 12, 0, 0, 0, time.UTC), CompletedFromColumn: "completed_tasks", } require.NoError(t, db.Create(&c).Error) } summary, err := repo.GetCompletionSummary(residence.ID, now, 10) require.NoError(t, err) for _, m := range summary.Months { if m.Month == "2026-02" { assert.Equal(t, 15, m.Total) assert.Equal(t, 5, m.Overflow) return } } t.Fatal("February 2026 not found") } func TestGetCompletionSummary_OldCompletionsExcludedFromMonths(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewTaskRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := testutil.CreateTestResidence(t, db, user.ID, "Old House") task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Old task") now := time.Date(2026, 3, 15, 0, 0, 0, 0, time.UTC) old := models.TaskCompletion{ TaskID: task.ID, CompletedByID: user.ID, CompletedAt: time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC), CompletedFromColumn: "completed_tasks", } require.NoError(t, db.Create(&old).Error) recent := models.TaskCompletion{ TaskID: task.ID, CompletedByID: user.ID, CompletedAt: time.Date(2026, 2, 1, 12, 0, 0, 0, time.UTC), CompletedFromColumn: "completed_tasks", } require.NoError(t, db.Create(&recent).Error) summary, err := repo.GetCompletionSummary(residence.ID, now, 10) require.NoError(t, err) assert.Equal(t, 2, summary.TotalAllTime) assert.Equal(t, 1, summary.TotalLast12Months) } func TestGetCompletionSummary_CompletionColors(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewTaskRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := testutil.CreateTestResidence(t, db, user.ID, "Color House") task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Color task") now := time.Date(2026, 3, 15, 0, 0, 0, 0, time.UTC) c := models.TaskCompletion{ TaskID: task.ID, CompletedByID: user.ID, CompletedAt: time.Date(2026, 1, 5, 12, 0, 0, 0, time.UTC), CompletedFromColumn: "overdue_tasks", } require.NoError(t, db.Create(&c).Error) summary, err := repo.GetCompletionSummary(residence.ID, now, 10) require.NoError(t, err) for _, m := range summary.Months { if m.Month == "2026-01" { require.Len(t, m.Completions, 1) assert.Equal(t, "overdue_tasks", m.Completions[0].Column) assert.Equal(t, "#FF3B30", m.Completions[0].Color) assert.Equal(t, 1, m.Completions[0].Count) return } } t.Fatal("January 2026 not found") } func TestKanbanColumnColor(t *testing.T) { tests := []struct { column string expected string }{ {"overdue_tasks", "#FF3B30"}, {"in_progress_tasks", "#5856D6"}, {"due_soon_tasks", "#FF9500"}, {"upcoming_tasks", "#007AFF"}, {"completed_tasks", "#34C759"}, {"cancelled_tasks", "#8E8E93"}, {"unknown_column", "#34C759"}, } for _, tt := range tests { t.Run(tt.column, func(t *testing.T) { assert.Equal(t, tt.expected, KanbanColumnColor(tt.column)) }) } }