package services_test import ( "testing" "code.tczkiot.com/wlw/ai-agent/internal/models" "code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/request" "code.tczkiot.com/wlw/ai-agent/internal/services" "github.com/glebarez/sqlite" "github.com/mlogclub/simple/sqls" "gorm.io/gorm" "gorm.io/gorm/schema" ) func TestNotificationServiceCreateAndUnreadCount(t *testing.T) { setupNotificationTestDB(t) item, err := services.NotificationService.Create(request.CreateNotificationRequest{ RecipientUserID: 101, Title: "会话分配提醒", Content: "会话 #1 已分配给你", NotificationType: "conversation_assigned", BizType: "conversation", BizID: 1, ActionURL: "/dashboard/conversations?conversationId=1", }) if err != nil { t.Fatalf("Create() error = %v", err) } if item.ID == 0 { t.Fatalf("expected notification id to be assigned") } if item.RecipientUserID != 101 || item.ReadAt != nil { t.Fatalf("unexpected notification: %+v", item) } if got := services.NotificationService.CountUnread(101); got != 1 { t.Fatalf("expected unread count 1, got %d", got) } if got := services.NotificationService.CountUnread(102); got != 0 { t.Fatalf("expected unread count 0 for another user, got %d", got) } } func TestNotificationServiceMarkReadRequiresOwner(t *testing.T) { setupNotificationTestDB(t) item, err := services.NotificationService.Create(request.CreateNotificationRequest{ RecipientUserID: 201, Title: "会话分配提醒", Content: "会话 #9 已分配给你", NotificationType: "conversation_assigned", BizType: "conversation", BizID: 9, ActionURL: "/dashboard/conversations?conversationId=9", }) if err != nil { t.Fatalf("Create() error = %v", err) } if err := services.NotificationService.MarkRead(item.ID, 202); err == nil { t.Fatalf("expected foreign user mark read to fail") } if got := services.NotificationService.CountUnread(201); got != 1 { t.Fatalf("expected notification to remain unread, got %d", got) } if err := services.NotificationService.MarkRead(item.ID, 201); err != nil { t.Fatalf("MarkRead() owner error = %v", err) } if got := services.NotificationService.CountUnread(201); got != 0 { t.Fatalf("expected unread count 0 after mark read, got %d", got) } } func TestNotificationServiceMarkAllReadOnlyCurrentUser(t *testing.T) { setupNotificationTestDB(t) for _, userID := range []int64{301, 301, 302} { if _, err := services.NotificationService.Create(request.CreateNotificationRequest{ RecipientUserID: userID, Title: "会话分配提醒", Content: "会话已分配给你", NotificationType: "conversation_assigned", BizType: "conversation", BizID: userID, ActionURL: "/dashboard/conversations?conversationId=1", }); err != nil { t.Fatalf("Create() error = %v", err) } } if err := services.NotificationService.MarkAllRead(301); err != nil { t.Fatalf("MarkAllRead() error = %v", err) } if got := services.NotificationService.CountUnread(301); got != 0 { t.Fatalf("expected user 301 unread count 0, got %d", got) } if got := services.NotificationService.CountUnread(302); got != 1 { t.Fatalf("expected user 302 unread count 1, got %d", got) } } func setupNotificationTestDB(t *testing.T) *gorm.DB { t.Helper() db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{ NamingStrategy: schema.NamingStrategy{ TablePrefix: "t_", SingularTable: true, }, }) if err != nil { t.Fatalf("open sqlite error = %v", err) } t.Cleanup(func() { sqlDB, err := db.DB() if err == nil { _ = sqlDB.Close() } }) if err := db.AutoMigrate(&models.Notification{}); err != nil { t.Fatalf("auto migrate error = %v", err) } sqls.SetDB(db) return db }