Coverage priorities 1-5: test pure functions, extract interfaces, mock-based handler tests
- Priority 1: Test NewSendEmailTask + NewSendPushTask (5 tests) - Priority 2: Test customHTTPErrorHandler — all 15+ branches (21 tests) - Priority 3: Extract Enqueuer interface + payload builders in worker pkg (5 tests) - Priority 4: Extract ClassifyFile/ComputeRelPath in migrate-encrypt (6 tests) - Priority 5: Define Handler interfaces, refactor to accept them, mock-based tests (14 tests) - Fix .gitignore: /worker instead of worker to stop ignoring internal/worker/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
217
internal/repositories/reminder_repo_test.go
Normal file
217
internal/repositories/reminder_repo_test.go
Normal file
@@ -0,0 +1,217 @@
|
||||
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 TestReminderRepository_LogReminder(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
repo := NewReminderRepository(db)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof")
|
||||
|
||||
dueDate := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC)
|
||||
logEntry, err := repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days, nil)
|
||||
require.NoError(t, err)
|
||||
assert.NotZero(t, logEntry.ID)
|
||||
assert.Equal(t, task.ID, logEntry.TaskID)
|
||||
assert.Equal(t, user.ID, logEntry.UserID)
|
||||
assert.Equal(t, models.ReminderStage7Days, logEntry.ReminderStage)
|
||||
}
|
||||
|
||||
func TestReminderRepository_HasSentReminder(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
repo := NewReminderRepository(db)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof")
|
||||
|
||||
dueDate := time.Date(2026, 4, 15, 12, 30, 0, 0, time.UTC) // Has time component
|
||||
|
||||
// Not sent yet
|
||||
sent, err := repo.HasSentReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, sent)
|
||||
|
||||
// Log it
|
||||
_, err = repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Now should be sent
|
||||
sent, err = repo.HasSentReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, sent)
|
||||
|
||||
// Different stage should not be sent
|
||||
sent, err = repo.HasSentReminder(task.ID, user.ID, dueDate, models.ReminderStage3Days)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, sent)
|
||||
}
|
||||
|
||||
func TestReminderRepository_HasSentReminderBatch(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
repo := NewReminderRepository(db)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
task1 := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Task 1")
|
||||
task2 := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Task 2")
|
||||
|
||||
dueDate := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
// Log reminder for task1
|
||||
_, err := repo.LogReminder(task1.ID, user.ID, dueDate, models.ReminderStage7Days, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
keys := []ReminderKey{
|
||||
{TaskID: task1.ID, UserID: user.ID, DueDate: dueDate, Stage: models.ReminderStage7Days},
|
||||
{TaskID: task2.ID, UserID: user.ID, DueDate: dueDate, Stage: models.ReminderStage7Days},
|
||||
}
|
||||
|
||||
result, err := repo.HasSentReminderBatch(keys)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, result[0], "task1 reminder should be sent")
|
||||
assert.False(t, result[1], "task2 reminder should not be sent")
|
||||
}
|
||||
|
||||
func TestReminderRepository_HasSentReminderBatch_Empty(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
repo := NewReminderRepository(db)
|
||||
|
||||
result, err := repo.HasSentReminderBatch([]ReminderKey{})
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, result)
|
||||
}
|
||||
|
||||
func TestReminderRepository_GetSentRemindersForTask(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
repo := NewReminderRepository(db)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof")
|
||||
|
||||
dueDate := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC)
|
||||
_, err := repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days, nil)
|
||||
require.NoError(t, err)
|
||||
_, err = repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage3Days, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
logs, err := repo.GetSentRemindersForTask(task.ID, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, logs, 2)
|
||||
}
|
||||
|
||||
func TestReminderRepository_GetSentRemindersForDueDate(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
repo := NewReminderRepository(db)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof")
|
||||
|
||||
dueDate1 := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC)
|
||||
dueDate2 := time.Date(2026, 5, 15, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
_, err := repo.LogReminder(task.ID, user.ID, dueDate1, models.ReminderStage7Days, nil)
|
||||
require.NoError(t, err)
|
||||
_, err = repo.LogReminder(task.ID, user.ID, dueDate2, models.ReminderStage7Days, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
logs, err := repo.GetSentRemindersForDueDate(task.ID, user.ID, dueDate1)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, logs, 1)
|
||||
}
|
||||
|
||||
func TestReminderRepository_CleanupOldLogs(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
repo := NewReminderRepository(db)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof")
|
||||
|
||||
// Create old log entry (100 days ago)
|
||||
oldLog := &models.TaskReminderLog{
|
||||
TaskID: task.ID,
|
||||
UserID: user.ID,
|
||||
DueDate: time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
ReminderStage: models.ReminderStage7Days,
|
||||
SentAt: time.Now().UTC().AddDate(0, 0, -100),
|
||||
}
|
||||
require.NoError(t, db.Create(oldLog).Error)
|
||||
|
||||
// Create recent log entry
|
||||
recentLog := &models.TaskReminderLog{
|
||||
TaskID: task.ID,
|
||||
UserID: user.ID,
|
||||
DueDate: time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC),
|
||||
ReminderStage: models.ReminderStage3Days,
|
||||
SentAt: time.Now().UTC(),
|
||||
}
|
||||
require.NoError(t, db.Create(recentLog).Error)
|
||||
|
||||
deleted, err := repo.CleanupOldLogs(90)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(1), deleted)
|
||||
|
||||
// Recent log should still exist
|
||||
var count int64
|
||||
db.Model(&models.TaskReminderLog{}).Count(&count)
|
||||
assert.Equal(t, int64(1), count)
|
||||
}
|
||||
|
||||
func TestReminderRepository_GetRecentReminderStats(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
repo := NewReminderRepository(db)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof")
|
||||
|
||||
dueDate := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC)
|
||||
// Create recent reminders
|
||||
_, err := repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days, nil)
|
||||
require.NoError(t, err)
|
||||
_, err = repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage3Days, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
stats, err := repo.GetRecentReminderStats(24) // last 24 hours
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(1), stats[string(models.ReminderStage7Days)])
|
||||
assert.Equal(t, int64(1), stats[string(models.ReminderStage3Days)])
|
||||
}
|
||||
|
||||
func TestReminderRepository_LogReminder_WithNotificationID(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
repo := NewReminderRepository(db)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof")
|
||||
|
||||
// Create a notification
|
||||
notif := &models.Notification{
|
||||
UserID: user.ID,
|
||||
NotificationType: models.NotificationTaskDueSoon,
|
||||
Title: "Test",
|
||||
Body: "Test body",
|
||||
}
|
||||
require.NoError(t, db.Create(notif).Error)
|
||||
|
||||
dueDate := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC)
|
||||
logEntry, err := repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days, ¬if.ID)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, logEntry.NotificationID)
|
||||
assert.Equal(t, notif.ID, *logEntry.NotificationID)
|
||||
}
|
||||
Reference in New Issue
Block a user