diff --git a/internal/mail/resolve_thread_test.go b/internal/mail/resolve_thread_test.go new file mode 100644 index 0000000..9e52251 --- /dev/null +++ b/internal/mail/resolve_thread_test.go @@ -0,0 +1,86 @@ +package mail + +import ( + "errors" + "testing" + + "thuanle.me/claw-email-bridge/internal/database" +) + +func TestResolveThreadID_NoHeaders_ReturnsMessageID(t *testing.T) { + got := resolveThreadID("msg-1", "", "", nilLookup) + if got != "msg-1" { + t.Fatalf("expected msg-1, got %s", got) + } +} + +func TestResolveThreadID_InReplyToMatches_ReturnsParentThreadID(t *testing.T) { + lookup := func(messageID string) (*database.Task, error) { + if messageID == "" { + return &database.Task{ThreadID: "thread-abc"}, nil + } + return nil, nil + } + got := resolveThreadID("msg-2", "", "", lookup) + if got != "thread-abc" { + t.Fatalf("expected thread-abc, got %s", got) + } +} + +func TestResolveThreadID_ReferencesOnly_LastIDMatches(t *testing.T) { + lookup := func(messageID string) (*database.Task, error) { + if messageID == "" { + return &database.Task{ThreadID: "thread-c"}, nil + } + return nil, nil + } + got := resolveThreadID("msg-3", "", " ", lookup) + if got != "thread-c" { + t.Fatalf("expected thread-c, got %s", got) + } +} + +func TestResolveThreadID_ReferencesOnly_MiddleIDMatches(t *testing.T) { + lookup := func(messageID string) (*database.Task, error) { + if messageID == "" { + return &database.Task{ThreadID: "thread-b"}, nil + } + return nil, nil + } + got := resolveThreadID("msg-4", "", " ", lookup) + if got != "thread-b" { + t.Fatalf("expected thread-b, got %s", got) + } +} + +func TestResolveThreadID_ReferencesOnly_NoMatch_ReturnsMessageID(t *testing.T) { + got := resolveThreadID("msg-5", "", " ", nilLookup) + if got != "msg-5" { + t.Fatalf("expected msg-5, got %s", got) + } +} + +func TestResolveThreadID_InReplyToMiss_ReferencesMatches(t *testing.T) { + lookup := func(messageID string) (*database.Task, error) { + if messageID == "" { + return &database.Task{ThreadID: "thread-ref"}, nil + } + return nil, nil + } + got := resolveThreadID("msg-6", "", "", lookup) + if got != "thread-ref" { + t.Fatalf("expected thread-ref, got %s", got) + } +} + +func TestResolveThreadID_LookupError_ReturnsMessageID(t *testing.T) { + lookup := func(messageID string) (*database.Task, error) { + return nil, errors.New("db error") + } + got := resolveThreadID("msg-7", "", "", lookup) + if got != "msg-7" { + t.Fatalf("expected msg-7, got %s", got) + } +} + +var nilLookup = func(string) (*database.Task, error) { return nil, nil } \ No newline at end of file