package user import ( "errors" "log/slog" "os" "testing" "golang.org/x/crypto/bcrypt" ) func TestMain(m *testing.M) { slog.SetDefault(slog.New(slog.DiscardHandler)) os.Exit(m.Run()) } func newTestUserService(t *testing.T) *Service { t.Helper() return &Service{repository: newEmptyRepository(), bcryptCost: bcrypt.MinCost} } func TestRegisterInputValidateFaultyData(t *testing.T) { badInputs := getInvalidRegisterInputs() for name, in := range badInputs { t.Run(name, func(t *testing.T) { err := in.validate() if err == nil { t.Errorf("bad input got through: %+v", in) } if !errors.Is(err, ErrInvalidInput) { t.Errorf("unexpected error: got %v, want ErrInvalidInput", err) } }) } } func TestRegisterBadInput(t *testing.T) { in := &RegisterInput{} s := newTestUserService(t) _, err := s.Register(in) if err == nil { t.Error("no error when registering with faulty input") } } func TestRegisterExistingUser(t *testing.T) { r := newEmptyRepository() r.fill() badInputs := map[string]RegisterInput{ "existing username": { Username: r.users[0].Username, Email: "thisemaildoesnt@exist.com", Phone: "123321", Password: "22332233", }, "existing email": { Username: "thisusernamedoesntexist", Email: r.users[0].Email, Phone: "123321", Password: "22332233", }, } for name, in := range badInputs { t.Run(name, func(t *testing.T) { s := &Service{repository: r, bcryptCost: bcrypt.MinCost} _, err := s.Register(&in) if err == nil { t.Error("existing user registered") } if !errors.Is(err, ErrUserExists) { t.Errorf("unexpected error: got %v, want ErrUserExists", err) } }) } } func TestRegisterRepositoryError(t *testing.T) { s := &Service{ repository: &RepositoryMock{err: errors.New("db down")}, bcryptCost: bcrypt.MinCost, } in := &RegisterInput{Username: "bob", Email: "b@b.com", Password: "thisissecure"} _, err := s.Register(in) if err == nil { t.Error("register swallowed repository error") } if errors.Is(err, ErrUserExists) { t.Error("repository failure reported as ErrUserExists") } } func TestSuccessfulRegister(t *testing.T) { s := newTestUserService(t) in := &RegisterInput{ Username: "happyuser123", Email: "happyuser@email.com", Phone: "+381233232", Password: "supersecretpassword1234", } usr, err := s.Register(in) if err != nil { t.Errorf("register with good input failed: %+v", in) } err = bcrypt.CompareHashAndPassword([]byte(usr.passwordHash), []byte(in.Password)) if err != nil { t.Errorf("hash and password compare error: %v", err) } } func TestRegisterSameUserTwice(t *testing.T) { s := newTestUserService(t) in := &RegisterInput{ Username: "happyuser123", Email: "happyuser@email.com", Phone: "+381233232", Password: "supersecretpassword1234", } s.Register(in) _, err := s.Register(in) if err == nil { t.Errorf("registered same user twice: %+v", in) } if !errors.Is(err, ErrUserExists) { t.Errorf("unexpected error: got %v, want ErrUserExists", err) } }