Files
honeyDueAPI/internal/worker/jobs/handler_helpers_test.go
Trey T bec880886b 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>
2026-04-01 20:30:09 -05:00

227 lines
5.7 KiB
Go

package jobs
import (
"encoding/json"
"testing"
"github.com/treytartt/honeydue-api/internal/models"
)
// --- BuildDigestMessage ---
func TestBuildDigestMessage_BothCounts(t *testing.T) {
title, body := BuildDigestMessage(3, 5)
if title != "Daily Task Summary" {
t.Errorf("title = %q, want %q", title, "Daily Task Summary")
}
want := "You have 3 overdue task(s) and 5 task(s) due this week"
if body != want {
t.Errorf("body = %q, want %q", body, want)
}
}
func TestBuildDigestMessage_OnlyOverdue(t *testing.T) {
_, body := BuildDigestMessage(2, 0)
want := "You have 2 overdue task(s) that need attention"
if body != want {
t.Errorf("body = %q, want %q", body, want)
}
}
func TestBuildDigestMessage_OnlyDueSoon(t *testing.T) {
_, body := BuildDigestMessage(0, 4)
want := "You have 4 task(s) due this week"
if body != want {
t.Errorf("body = %q, want %q", body, want)
}
}
func TestBuildDigestMessage_Title_AlwaysDailyTaskSummary(t *testing.T) {
cases := [][2]int{{1, 1}, {0, 1}, {1, 0}}
for _, c := range cases {
title, _ := BuildDigestMessage(c[0], c[1])
if title != "Daily Task Summary" {
t.Errorf("BuildDigestMessage(%d,%d) title = %q", c[0], c[1], title)
}
}
}
// --- IsOverdueStage ---
func TestIsOverdueStage_Overdue1_True(t *testing.T) {
if !IsOverdueStage("overdue_1") {
t.Error("expected true for overdue_1")
}
}
func TestIsOverdueStage_Overdue14_True(t *testing.T) {
if !IsOverdueStage("overdue_14") {
t.Error("expected true for overdue_14")
}
}
func TestIsOverdueStage_Reminder7d_False(t *testing.T) {
if IsOverdueStage("reminder_7d") {
t.Error("expected false for reminder_7d")
}
}
func TestIsOverdueStage_DayOf_False(t *testing.T) {
if IsOverdueStage("day_of") {
t.Error("expected false for day_of")
}
}
func TestIsOverdueStage_Empty_False(t *testing.T) {
if IsOverdueStage("") {
t.Error("expected false for empty string")
}
}
// --- ExtractFrequencyDays ---
func TestExtractFrequencyDays_WithFrequency(t *testing.T) {
days := 7
task := &models.Task{
Frequency: &models.TaskFrequency{Days: &days},
}
got := ExtractFrequencyDays(task)
if got == nil || *got != 7 {
t.Errorf("got %v, want 7", got)
}
}
func TestExtractFrequencyDays_WithCustomInterval(t *testing.T) {
custom := 14
task := &models.Task{
CustomIntervalDays: &custom,
}
got := ExtractFrequencyDays(task)
if got == nil || *got != 14 {
t.Errorf("got %v, want 14", got)
}
}
func TestExtractFrequencyDays_NilFrequency(t *testing.T) {
task := &models.Task{}
got := ExtractFrequencyDays(task)
if got != nil {
t.Errorf("got %v, want nil", got)
}
}
func TestExtractFrequencyDays_NilDays(t *testing.T) {
task := &models.Task{
Frequency: &models.TaskFrequency{},
}
got := ExtractFrequencyDays(task)
if got != nil {
t.Errorf("got %v, want nil", got)
}
}
// --- Email payload tests ---
func TestEmailPayload_Unmarshal_Valid(t *testing.T) {
data := []byte(`{"to":"a@b.com","subject":"hi","html_body":"<b>hi</b>","text_body":"hi"}`)
var p EmailPayload
if err := json.Unmarshal(data, &p); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if p.To != "a@b.com" || p.Subject != "hi" {
t.Errorf("got %+v", p)
}
}
func TestEmailPayload_Unmarshal_Invalid(t *testing.T) {
var p EmailPayload
if err := json.Unmarshal([]byte(`{invalid}`), &p); err == nil {
t.Error("expected error for invalid JSON")
}
}
// --- NewSendEmailTask ---
func TestNewSendEmailTask_ReturnsTask(t *testing.T) {
task, err := NewSendEmailTask("a@b.com", "Subject", "<b>hi</b>", "hi")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if task.Type() != TypeSendEmail {
t.Errorf("task type = %q, want %q", task.Type(), TypeSendEmail)
}
}
func TestNewSendEmailTask_PayloadFields(t *testing.T) {
task, err := NewSendEmailTask("user@example.com", "Welcome", "<h1>Hello</h1>", "Hello")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
var p EmailPayload
if err := json.Unmarshal(task.Payload(), &p); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if p.To != "user@example.com" {
t.Errorf("To = %q, want %q", p.To, "user@example.com")
}
if p.Subject != "Welcome" {
t.Errorf("Subject = %q, want %q", p.Subject, "Welcome")
}
if p.HTMLBody != "<h1>Hello</h1>" {
t.Errorf("HTMLBody = %q, want %q", p.HTMLBody, "<h1>Hello</h1>")
}
if p.TextBody != "Hello" {
t.Errorf("TextBody = %q, want %q", p.TextBody, "Hello")
}
}
// --- NewSendPushTask ---
func TestNewSendPushTask_ReturnsTask(t *testing.T) {
task, err := NewSendPushTask(42, "Title", "Body", map[string]string{"key": "val"})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if task.Type() != TypeSendPush {
t.Errorf("task type = %q, want %q", task.Type(), TypeSendPush)
}
}
func TestNewSendPushTask_PayloadFields(t *testing.T) {
data := map[string]string{"action": "open", "id": "123"}
task, err := NewSendPushTask(7, "Alert", "Something happened", data)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
var p PushPayload
if err := json.Unmarshal(task.Payload(), &p); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if p.UserID != 7 {
t.Errorf("UserID = %d, want 7", p.UserID)
}
if p.Title != "Alert" {
t.Errorf("Title = %q, want %q", p.Title, "Alert")
}
if p.Message != "Something happened" {
t.Errorf("Message = %q, want %q", p.Message, "Something happened")
}
if p.Data["action"] != "open" || p.Data["id"] != "123" {
t.Errorf("Data = %v, want map with action=open, id=123", p.Data)
}
}
func TestNewSendPushTask_NilData(t *testing.T) {
task, err := NewSendPushTask(1, "T", "M", nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
var p PushPayload
if err := json.Unmarshal(task.Payload(), &p); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if p.Data != nil {
t.Errorf("Data = %v, want nil", p.Data)
}
}