package database_test import ( "testing" "thuanle.me/claw-email-bridge/internal/database" ) // Test matrix #5: Duplicate message_id → không tạo task mới. func TestDuplicateMessageID(t *testing.T) { tdb := database.NewTestDB(t) task1 := &database.Task{ TaskUUID: "uuid-1", ThreadID: "thread-1", MessageID: "msg-duplicate@test.com", Sender: "user@test.com", Subject: "First email", Status: database.StatusReceived, } if err := database.CreateTask(tdb.DB, task1); err != nil { t.Fatalf("create first task: %v", err) } // Lookup should find the existing task. found, err := database.FindByMessageID(tdb.DB, "msg-duplicate@test.com") if err != nil { t.Fatalf("find by message_id: %v", err) } if found == nil { t.Fatal("expected to find existing task") } if found.TaskUUID != "uuid-1" { t.Errorf("expected uuid-1, got %s", found.TaskUUID) } // Attempting to create another task with same task_uuid should fail (unique constraint). task2 := &database.Task{ TaskUUID: "uuid-1", // Same UUID — unique constraint violation. ThreadID: "thread-1", MessageID: "msg-duplicate@test.com", Sender: "user@test.com", Subject: "Duplicate", Status: database.StatusReceived, } err = database.CreateTask(tdb.DB, task2) if err == nil { t.Error("expected error creating duplicate task_uuid, got nil") } } func TestFindByMessageID_NotFound(t *testing.T) { tdb := database.NewTestDB(t) found, err := database.FindByMessageID(tdb.DB, "nonexistent@test.com") if err != nil { t.Fatalf("unexpected error: %v", err) } if found != nil { t.Error("expected nil for nonexistent message_id") } } func TestThreadHistory(t *testing.T) { tdb := database.NewTestDB(t) // Create two completed tasks in same thread. for i, uuid := range []string{"uuid-a", "uuid-b"} { task := &database.Task{ TaskUUID: uuid, ThreadID: "thread-history", MessageID: uuid + "@test.com", Sender: "user@test.com", Subject: "Thread test", BodyPlain: "Message " + uuid, AIResponse: "Reply " + uuid, Status: database.StatusCompleted, } _ = i if err := database.CreateTask(tdb.DB, task); err != nil { t.Fatalf("create task %s: %v", uuid, err) } } // Create one non-completed task — should not appear in history. task3 := &database.Task{ TaskUUID: "uuid-c", ThreadID: "thread-history", MessageID: "uuid-c@test.com", Sender: "user@test.com", Subject: "Pending", Status: database.StatusAIProcessing, } if err := database.CreateTask(tdb.DB, task3); err != nil { t.Fatalf("create task: %v", err) } history, err := database.ThreadHistory(tdb.DB, "thread-history") if err != nil { t.Fatalf("thread history: %v", err) } if len(history) != 2 { t.Errorf("expected 2 completed tasks in history, got %d", len(history)) } }