- 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>
227 lines
5.7 KiB
Go
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)
|
|
}
|
|
}
|