408 lines
12 KiB
Go
408 lines
12 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
|
|
"veza-backend-api/internal/database"
|
|
)
|
|
|
|
func setupTestNotificationService(t *testing.T) (*NotificationService, *gorm.DB, *database.Database) {
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
require.NoError(t, err)
|
|
db.Exec("PRAGMA foreign_keys = ON")
|
|
|
|
// Create notifications table manually
|
|
err = db.Exec(`
|
|
CREATE TABLE notifications (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
type TEXT NOT NULL,
|
|
title TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
link TEXT NOT NULL,
|
|
read INTEGER NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)
|
|
`).Error
|
|
require.NoError(t, err)
|
|
|
|
sqlDB, err := db.DB()
|
|
require.NoError(t, err)
|
|
|
|
testDB := &database.Database{
|
|
DB: sqlDB,
|
|
}
|
|
|
|
logger := zap.NewNop()
|
|
service := NewNotificationService(testDB, logger)
|
|
|
|
return service, db, testDB
|
|
}
|
|
|
|
func TestNotificationService_CreateNotification_Success(t *testing.T) {
|
|
service, _, _ := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
notificationType := "test_type"
|
|
title := "Test Title"
|
|
content := "Test Content"
|
|
link := "https://example.com"
|
|
|
|
err := service.CreateNotification(userID, notificationType, title, content, link)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestNotificationService_CreateNotification_EmptyFields(t *testing.T) {
|
|
service, _, _ := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
notificationType := ""
|
|
title := ""
|
|
content := ""
|
|
link := ""
|
|
|
|
// SQLite allows empty strings, so this should not error
|
|
err := service.CreateNotification(userID, notificationType, title, content, link)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestNotificationService_GetNotifications_AllNotifications(t *testing.T) {
|
|
service, _, testDB := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
ctx := context.Background()
|
|
|
|
// Create test notifications
|
|
for i := 0; i < 3; i++ {
|
|
notificationID := uuid.New()
|
|
_, err := testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, notificationID.String(), userID.String(), "test_type", "Title", "Content", "", false)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
result, err := service.GetNotifications(userID, GetNotificationsParams{Page: 1, Limit: 20})
|
|
assert.NoError(t, err)
|
|
require.NotNil(t, result)
|
|
assert.Len(t, result.Notifications, 3)
|
|
assert.Equal(t, userID, result.Notifications[0].UserID)
|
|
assert.Equal(t, 3, result.Total)
|
|
}
|
|
|
|
func TestNotificationService_GetNotifications_UnreadOnly(t *testing.T) {
|
|
service, _, testDB := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
ctx := context.Background()
|
|
|
|
// Create read notification
|
|
readID := uuid.New()
|
|
_, err := testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, readID.String(), userID.String(), "test_type", "Read Title", "Content", "", true)
|
|
require.NoError(t, err)
|
|
|
|
// Create unread notification
|
|
unreadID := uuid.New()
|
|
_, err = testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, unreadID.String(), userID.String(), "test_type", "Unread Title", "Content", "", false)
|
|
require.NoError(t, err)
|
|
|
|
// Get all notifications
|
|
allResult, err := service.GetNotifications(userID, GetNotificationsParams{Page: 1, Limit: 20})
|
|
assert.NoError(t, err)
|
|
require.NotNil(t, allResult)
|
|
assert.Len(t, allResult.Notifications, 2)
|
|
|
|
// Get unread only
|
|
unreadResult, err := service.GetNotifications(userID, GetNotificationsParams{UnreadOnly: true, Page: 1, Limit: 20})
|
|
assert.NoError(t, err)
|
|
require.NotNil(t, unreadResult)
|
|
assert.Len(t, unreadResult.Notifications, 1)
|
|
assert.False(t, unreadResult.Notifications[0].Read)
|
|
}
|
|
|
|
func TestNotificationService_GetNotifications_NoNotifications(t *testing.T) {
|
|
service, _, _ := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
|
|
result, err := service.GetNotifications(userID, GetNotificationsParams{Page: 1, Limit: 20})
|
|
assert.NoError(t, err)
|
|
require.NotNil(t, result)
|
|
assert.Len(t, result.Notifications, 0)
|
|
assert.Equal(t, 0, result.Total)
|
|
}
|
|
|
|
func TestNotificationService_GetNotifications_DifferentUsers(t *testing.T) {
|
|
service, _, testDB := setupTestNotificationService(t)
|
|
|
|
userID1 := uuid.New()
|
|
userID2 := uuid.New()
|
|
ctx := context.Background()
|
|
|
|
// Create notification for user1
|
|
notificationID1 := uuid.New()
|
|
_, err := testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, notificationID1.String(), userID1.String(), "test_type", "Title", "Content", "", false)
|
|
require.NoError(t, err)
|
|
|
|
// Create notification for user2
|
|
notificationID2 := uuid.New()
|
|
_, err = testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, notificationID2.String(), userID2.String(), "test_type", "Title", "Content", "", false)
|
|
require.NoError(t, err)
|
|
|
|
// Get notifications for user1
|
|
result1, err := service.GetNotifications(userID1, GetNotificationsParams{Page: 1, Limit: 20})
|
|
assert.NoError(t, err)
|
|
require.NotNil(t, result1)
|
|
assert.Len(t, result1.Notifications, 1)
|
|
assert.Equal(t, userID1, result1.Notifications[0].UserID)
|
|
|
|
// Get notifications for user2
|
|
result2, err := service.GetNotifications(userID2, GetNotificationsParams{Page: 1, Limit: 20})
|
|
assert.NoError(t, err)
|
|
require.NotNil(t, result2)
|
|
assert.Len(t, result2.Notifications, 1)
|
|
assert.Equal(t, userID2, result2.Notifications[0].UserID)
|
|
}
|
|
|
|
func TestNotificationService_MarkAsRead_Success(t *testing.T) {
|
|
service, _, testDB := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
notificationID := uuid.New()
|
|
ctx := context.Background()
|
|
|
|
// Create unread notification
|
|
_, err := testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, notificationID.String(), userID.String(), "test_type", "Title", "Content", "", false)
|
|
require.NoError(t, err)
|
|
|
|
// Mark as read
|
|
err = service.MarkAsRead(userID, notificationID)
|
|
assert.NoError(t, err)
|
|
|
|
// Verify it's marked as read
|
|
var read bool
|
|
err = testDB.QueryRowContext(ctx, `
|
|
SELECT read FROM notifications WHERE id = $1
|
|
`, notificationID.String()).Scan(&read)
|
|
assert.NoError(t, err)
|
|
assert.True(t, read)
|
|
}
|
|
|
|
func TestNotificationService_MarkAsRead_WrongUser(t *testing.T) {
|
|
service, _, testDB := setupTestNotificationService(t)
|
|
|
|
userID1 := uuid.New()
|
|
userID2 := uuid.New()
|
|
notificationID := uuid.New()
|
|
ctx := context.Background()
|
|
|
|
// Create notification for user1
|
|
_, err := testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, notificationID.String(), userID1.String(), "test_type", "Title", "Content", "", false)
|
|
require.NoError(t, err)
|
|
|
|
// Try to mark as read with wrong user (should not error, but won't update)
|
|
err = service.MarkAsRead(userID2, notificationID)
|
|
assert.NoError(t, err)
|
|
|
|
// Verify it's still unread (because user_id didn't match)
|
|
var read bool
|
|
err = testDB.QueryRowContext(ctx, `
|
|
SELECT read FROM notifications WHERE id = $1
|
|
`, notificationID.String()).Scan(&read)
|
|
assert.NoError(t, err)
|
|
assert.False(t, read)
|
|
}
|
|
|
|
func TestNotificationService_MarkAsRead_NonExistent(t *testing.T) {
|
|
service, _, _ := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
notificationID := uuid.New()
|
|
|
|
// Try to mark non-existent notification as read (should not error)
|
|
err := service.MarkAsRead(userID, notificationID)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestNotificationService_MarkAllAsRead_Success(t *testing.T) {
|
|
service, _, testDB := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
ctx := context.Background()
|
|
|
|
// Create multiple unread notifications
|
|
for i := 0; i < 3; i++ {
|
|
notificationID := uuid.New()
|
|
_, err := testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, notificationID.String(), userID.String(), "test_type", "Title", "Content", "", false)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Mark all as read
|
|
err := service.MarkAllAsRead(userID)
|
|
assert.NoError(t, err)
|
|
|
|
// Verify all are marked as read
|
|
var count int
|
|
err = testDB.QueryRowContext(ctx, `
|
|
SELECT COUNT(*) FROM notifications WHERE user_id = $1 AND read = FALSE
|
|
`, userID.String()).Scan(&count)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 0, count)
|
|
}
|
|
|
|
func TestNotificationService_MarkAllAsRead_NoUnread(t *testing.T) {
|
|
service, _, testDB := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
ctx := context.Background()
|
|
|
|
// Create read notification
|
|
notificationID := uuid.New()
|
|
_, err := testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, notificationID.String(), userID.String(), "test_type", "Title", "Content", "", true)
|
|
require.NoError(t, err)
|
|
|
|
// Mark all as read (should not error even if none are unread)
|
|
err = service.MarkAllAsRead(userID)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestNotificationService_MarkAllAsRead_NoNotifications(t *testing.T) {
|
|
service, _, _ := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
|
|
// Mark all as read when user has no notifications (should not error)
|
|
err := service.MarkAllAsRead(userID)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestNotificationService_GetUnreadCount_Success(t *testing.T) {
|
|
service, _, testDB := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
ctx := context.Background()
|
|
|
|
// Create unread notifications
|
|
for i := 0; i < 3; i++ {
|
|
notificationID := uuid.New()
|
|
_, err := testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, notificationID.String(), userID.String(), "test_type", "Title", "Content", "", false)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Create read notification
|
|
readID := uuid.New()
|
|
_, err := testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, readID.String(), userID.String(), "test_type", "Title", "Content", "", true)
|
|
require.NoError(t, err)
|
|
|
|
count, err := service.GetUnreadCount(userID)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 3, count)
|
|
}
|
|
|
|
func TestNotificationService_GetUnreadCount_Zero(t *testing.T) {
|
|
service, _, _ := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
|
|
count, err := service.GetUnreadCount(userID)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 0, count)
|
|
}
|
|
|
|
func TestNotificationService_GetUnreadCount_AfterMarkAllAsRead(t *testing.T) {
|
|
service, _, testDB := setupTestNotificationService(t)
|
|
|
|
userID := uuid.New()
|
|
ctx := context.Background()
|
|
|
|
// Create unread notifications
|
|
for i := 0; i < 2; i++ {
|
|
notificationID := uuid.New()
|
|
_, err := testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, notificationID.String(), userID.String(), "test_type", "Title", "Content", "", false)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Mark all as read
|
|
err := service.MarkAllAsRead(userID)
|
|
assert.NoError(t, err)
|
|
|
|
// Verify unread count is 0
|
|
count, err := service.GetUnreadCount(userID)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 0, count)
|
|
}
|
|
|
|
func TestNotificationService_GetUnreadCount_DifferentUsers(t *testing.T) {
|
|
service, _, testDB := setupTestNotificationService(t)
|
|
|
|
userID1 := uuid.New()
|
|
userID2 := uuid.New()
|
|
ctx := context.Background()
|
|
|
|
// Create unread notification for user1
|
|
notificationID1 := uuid.New()
|
|
_, err := testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, notificationID1.String(), userID1.String(), "test_type", "Title", "Content", "", false)
|
|
require.NoError(t, err)
|
|
|
|
// Create unread notification for user2
|
|
notificationID2 := uuid.New()
|
|
_, err = testDB.ExecContext(ctx, `
|
|
INSERT INTO notifications (id, user_id, type, title, content, link, read)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
`, notificationID2.String(), userID2.String(), "test_type", "Title", "Content", "", false)
|
|
require.NoError(t, err)
|
|
|
|
// Get unread count for user1
|
|
count1, err := service.GetUnreadCount(userID1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, count1)
|
|
|
|
// Get unread count for user2
|
|
count2, err := service.GetUnreadCount(userID2)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, count2)
|
|
}
|