package repository import ( "context" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/gochat/gochat/internal/model" ) func TestUserRepo_Create(t *testing.T) { db := setupTestDB(t) repo := NewUserRepo(db) user := &model.User{ AccountID: 1, Name: "TestUser", Email: "test@example.com", Password: "hashedpassword", Provider: "email", Role: "agent", Active: true, } err := repo.Create(context.Background(), user) assert.NoError(t, err) assert.NotZero(t, user.ID) } func TestUserRepo_FindByID(t *testing.T) { db := setupTestDB(t) repo := NewUserRepo(db) user := &model.User{ AccountID: 1, Name: "FindByIDUser", Email: "findbyid@example.com", Password: "hashedpassword", Provider: "email", Role: "agent", Active: true, } require.NoError(t, db.Create(user).Error) found, err := repo.FindByID(context.Background(), user.ID) assert.NoError(t, err) assert.Equal(t, "FindByIDUser", found.Name) assert.Equal(t, user.ID, found.ID) assert.Equal(t, "findbyid@example.com", found.Email) } func TestUserRepo_FindByID_NotFound(t *testing.T) { db := setupTestDB(t) repo := NewUserRepo(db) found, err := repo.FindByID(context.Background(), 9999) assert.Error(t, err) assert.Nil(t, found) } func TestUserRepo_FindByEmail(t *testing.T) { db := setupTestDB(t) repo := NewUserRepo(db) user := &model.User{ AccountID: 1, Name: "EmailUser", Email: "emailfind@example.com", Password: "hashedpassword", Provider: "email", Role: "agent", Active: true, } require.NoError(t, db.Create(user).Error) found, err := repo.FindByEmail(context.Background(), "emailfind@example.com") assert.NoError(t, err) assert.Equal(t, user.ID, found.ID) assert.Equal(t, "emailfind@example.com", found.Email) } func TestUserRepo_FindByEmail_NotFound(t *testing.T) { db := setupTestDB(t) repo := NewUserRepo(db) found, err := repo.FindByEmail(context.Background(), "nonexistent@example.com") assert.Error(t, err) assert.Nil(t, found) } func TestUserRepo_Update(t *testing.T) { db := setupTestDB(t) repo := NewUserRepo(db) user := &model.User{ AccountID: 1, Name: "OriginalName", Email: "update@example.com", Password: "hashedpassword", Provider: "email", Role: "agent", Active: true, } require.NoError(t, db.Create(user).Error) user.Name = "UpdatedName" err := repo.Update(context.Background(), user) assert.NoError(t, err) found, err := repo.FindByID(context.Background(), user.ID) assert.NoError(t, err) assert.Equal(t, "UpdatedName", found.Name) } func TestUserRepo_Delete(t *testing.T) { db := setupTestDB(t) repo := NewUserRepo(db) user := &model.User{ AccountID: 1, Name: "DeleteUser", Email: "delete@example.com", Password: "hashedpassword", Provider: "email", Role: "agent", Active: true, } require.NoError(t, db.Create(user).Error) err := repo.Delete(context.Background(), user.ID) assert.NoError(t, err) // After soft-delete, FindByID should return error found, err := repo.FindByID(context.Background(), user.ID) assert.Error(t, err) assert.Nil(t, found) } func TestUserRepo_List(t *testing.T) { db := setupTestDB(t) repo := NewUserRepo(db) for i := 0; i < 5; i++ { user := &model.User{ AccountID: 1, Name: "ListUser" + string(rune('A'+i)), Email: "list" + string(rune('A'+i)) + "@example.com", Password: "hashedpassword", Provider: "email", Role: "agent", Active: true, } require.NoError(t, db.Create(user).Error) } users, total, err := repo.List(context.Background(), 0, 10) assert.NoError(t, err) assert.Equal(t, int64(5), total) assert.Len(t, users, 5) } func TestUserRepo_List_Pagination(t *testing.T) { db := setupTestDB(t) repo := NewUserRepo(db) for i := 0; i < 10; i++ { user := &model.User{ AccountID: 1, Name: "PagUser", Email: "pag" + string(rune('A'+i)) + "@example.com", Password: "hashedpassword", Provider: "email", Role: "agent", Active: true, } require.NoError(t, db.Create(user).Error) } users, total, err := repo.List(context.Background(), 5, 3) assert.NoError(t, err) assert.Equal(t, int64(10), total) assert.Len(t, users, 3) } func TestUserRepo_List_Empty(t *testing.T) { db := setupTestDB(t) repo := NewUserRepo(db) users, total, err := repo.List(context.Background(), 0, 10) assert.NoError(t, err) assert.Equal(t, int64(0), total) assert.Len(t, users, 0) } func TestUserRepo_Count(t *testing.T) { db := setupTestDB(t) repo := NewUserRepo(db) for i := 0; i < 3; i++ { user := &model.User{ AccountID: 1, Name: "CountUser", Email: "count" + string(rune('A'+i)) + "@example.com", Password: "hashedpassword", Provider: "email", Role: "agent", Active: true, } require.NoError(t, db.Create(user).Error) } total, err := repo.Count(context.Background()) assert.NoError(t, err) assert.Equal(t, int64(3), total) } func TestUserRepo_UpdateAvailability(t *testing.T) { db := setupTestDB(t) repo := NewUserRepo(db) user := &model.User{ AccountID: 1, Name: "AvailUser", Email: "avail@example.com", Password: "hashedpassword", Provider: "email", Role: "agent", Active: true, Available: false, } require.NoError(t, db.Create(user).Error) err := repo.UpdateAvailability(context.Background(), user.ID, "online") assert.NoError(t, err) found, err := repo.FindByID(context.Background(), user.ID) assert.NoError(t, err) // Availability is stored in AccountUser, not User directly in GoChat // The repo method updates the users table availability column assert.Equal(t, user.ID, found.ID) } // Search uses ILIKE which SQLite does not support; skip when running SQLite func TestUserRepo_Search(t *testing.T) { skipIfSQLite(t) db := setupTestDB(t) repo := NewUserRepo(db) for i := 0; i < 3; i++ { user := &model.User{ AccountID: 1, Name: "SearchUser" + string(rune('A'+i)), Email: "search" + string(rune('A'+i)) + "@example.com", Password: "hashedpassword", Provider: "email", Role: "agent", Active: true, } require.NoError(t, db.Create(user).Error) } // Search by name users, total, err := repo.Search(context.Background(), "SearchUserA", 0, 10) assert.NoError(t, err) assert.Equal(t, int64(1), total) assert.Len(t, users, 1) assert.Equal(t, "SearchUserA", users[0].Name) // Search by email users, total, err = repo.Search(context.Background(), "searchB", 0, 10) assert.NoError(t, err) assert.Equal(t, int64(1), total) assert.Len(t, users, 1) }