package repository import ( "context" "testing" "gorm.io/driver/sqlite" "gorm.io/gorm" "github.com/dhao2001/mygo/internal/model" ) func setupUserRepo(t *testing.T) UserRepository { t.Helper() db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) if err != nil { t.Fatalf("open db: %v", err) } if err := db.AutoMigrate(&model.User{}); err != nil { t.Fatalf("migrate: %v", err) } return NewUserRepository(db) } func TestUserRepository_Create(t *testing.T) { repo := setupUserRepo(t) ctx := context.Background() user := &model.User{ ID: "user-1", Username: "alice", Email: "alice@example.com", PasswordHash: "hash", } if err := repo.Create(ctx, user); err != nil { t.Fatalf("Create = %v", err) } } func TestUserRepository_CreateDuplicateUsername(t *testing.T) { repo := setupUserRepo(t) ctx := context.Background() u1 := &model.User{ID: "user-1", Username: "alice", Email: "alice@example.com", PasswordHash: "hash"} u2 := &model.User{ID: "user-2", Username: "alice", Email: "alice2@example.com", PasswordHash: "hash"} if err := repo.Create(ctx, u1); err != nil { t.Fatalf("Create = %v", err) } err := repo.Create(ctx, u2) if err != model.ErrDuplicate { t.Fatalf("expected ErrDuplicate, got %v", err) } } func TestUserRepository_FindByID(t *testing.T) { repo := setupUserRepo(t) ctx := context.Background() user := &model.User{ID: "user-1", Username: "alice", Email: "alice@example.com", PasswordHash: "hash"} if err := repo.Create(ctx, user); err != nil { t.Fatalf("Create = %v", err) } found, err := repo.FindByID(ctx, "user-1") if err != nil { t.Fatalf("FindByID = %v", err) } if found.Username != "alice" { t.Errorf("username = %q, want %q", found.Username, "alice") } } func TestUserRepository_FindByIDNotFound(t *testing.T) { repo := setupUserRepo(t) ctx := context.Background() _, err := repo.FindByID(ctx, "nonexistent") if err != model.ErrNotFound { t.Fatalf("expected ErrNotFound, got %v", err) } } func TestUserRepository_FindByEmail(t *testing.T) { repo := setupUserRepo(t) ctx := context.Background() user := &model.User{ID: "user-1", Username: "alice", Email: "alice@example.com", PasswordHash: "hash"} if err := repo.Create(ctx, user); err != nil { t.Fatalf("Create = %v", err) } found, err := repo.FindByEmail(ctx, "alice@example.com") if err != nil { t.Fatalf("FindByEmail = %v", err) } if found.ID != "user-1" { t.Errorf("id = %q, want %q", found.ID, "user-1") } } func TestUserRepository_FindByUsername(t *testing.T) { repo := setupUserRepo(t) ctx := context.Background() user := &model.User{ID: "user-1", Username: "alice", Email: "alice@example.com", PasswordHash: "hash"} if err := repo.Create(ctx, user); err != nil { t.Fatalf("Create = %v", err) } found, err := repo.FindByUsername(ctx, "alice") if err != nil { t.Fatalf("FindByUsername = %v", err) } if found.Email != "alice@example.com" { t.Errorf("email = %q, want %q", found.Email, "alice@example.com") } } func TestUserRepository_Update(t *testing.T) { repo := setupUserRepo(t) ctx := context.Background() user := &model.User{ID: "user-1", Username: "alice", Email: "alice@example.com", PasswordHash: "hash"} if err := repo.Create(ctx, user); err != nil { t.Fatalf("Create = %v", err) } user.Username = "alice2" if err := repo.Update(ctx, user); err != nil { t.Fatalf("Update = %v", err) } found, err := repo.FindByID(ctx, "user-1") if err != nil { t.Fatalf("FindByID = %v", err) } if found.Username != "alice2" { t.Errorf("username = %q, want %q", found.Username, "alice2") } } func TestUserRepository_Delete(t *testing.T) { repo := setupUserRepo(t) ctx := context.Background() user := &model.User{ID: "user-1", Username: "alice", Email: "alice@example.com", PasswordHash: "hash"} if err := repo.Create(ctx, user); err != nil { t.Fatalf("Create = %v", err) } if err := repo.Delete(ctx, "user-1"); err != nil { t.Fatalf("Delete = %v", err) } _, err := repo.FindByID(ctx, "user-1") if err != model.ErrNotFound { t.Fatalf("expected ErrNotFound after delete, got %v", err) } } func TestUserRepository_List(t *testing.T) { repo := setupUserRepo(t) ctx := context.Background() for i := range 5 { user := &model.User{ ID: "user-" + string(rune('0'+i)), Username: "user" + string(rune('0'+i)), Email: "user" + string(rune('0'+i)) + "@example.com", PasswordHash: "hash", } if err := repo.Create(ctx, user); err != nil { t.Fatalf("Create = %v", err) } } users, total, err := repo.List(ctx, 0, 3) if err != nil { t.Fatalf("List = %v", err) } if len(users) != 3 { t.Errorf("len(users) = %d, want %d", len(users), 3) } if total != 5 { t.Errorf("total = %d, want %d", total, 5) } }