From 8be785cd8b1c19616d1901af1f178337101e69b7 Mon Sep 17 00:00:00 2001 From: ari melody Date: Fri, 31 Jul 2026 04:46:32 +0100 Subject: [PATCH] 100% test coverage on account service! --- main.go | 10 +----- repository/account/interface.go | 3 +- repository/account/memory.go | 13 +++++++ service/account/account.go | 20 ----------- service/account/account_test.go | 61 +++++++++++++++++++++++++++++++++ 5 files changed, 76 insertions(+), 31 deletions(-) diff --git a/main.go b/main.go index e3055c1..b662cc8 100644 --- a/main.go +++ b/main.go @@ -306,15 +306,7 @@ func main() { } account.Password = string(hashedPassword) - var email *string = nil - if account.Email.Valid { email = &account.Email.String } - var avatarURL *string = nil - if account.AvatarURL.Valid { email = &account.AvatarURL.String } - if err = app.AccountService.Update( - account.ID, - username, string(hashedPassword), - email, avatarURL, - ); err != nil { + if err = app.AccountService.ChangePassword(account.ID, string(hashedPassword)); err != nil { logger.Fatalf("FATAL: Failed to update password: %v\n", err) } diff --git a/repository/account/interface.go b/repository/account/interface.go index f715511..fda2b1a 100644 --- a/repository/account/interface.go +++ b/repository/account/interface.go @@ -16,8 +16,7 @@ type AccountRepository interface { // Create an account, returning the new account ID. Create(username string, password string, email *string, avatarURL *string) (string, error) - // Intended for large profile updates. For smaller adjusments, - // more specialised Change* and Remove* functions should be used. + // Deprecated in favour of more specialised Change* and Remove* functions. Update(id string, username string, password string, email *string, avatarUrl *string) error ChangeUsername(id string, username string) error ChangePassword(id string, password string) error diff --git a/repository/account/memory.go b/repository/account/memory.go index 3f4ff2b..1b94167 100644 --- a/repository/account/memory.go +++ b/repository/account/memory.go @@ -99,20 +99,27 @@ func (repo *AccountRepositoryMemory) ChangeUsername(id string, username string) } else if account != nil && account.ID != id { return errors.New("Account with this username already exists") } + account, err := repo.GetByID(id) if err != nil { return err } + if account == nil { return errors.New("Account does not exist") } + account.Username = username return nil } func (repo *AccountRepositoryMemory) ChangePassword(id string, password string) error { account, err := repo.GetByID(id) if err != nil { return err } + if account == nil { return errors.New("Account does not exist") } + account.Password = password return nil } func (repo *AccountRepositoryMemory) ChangeEmail(id string, email string) error { account, err := repo.GetByID(id) if err != nil { return err } + if account == nil { return errors.New("Account does not exist") } + account.Email.Valid = true account.Email.String = email return nil @@ -120,6 +127,8 @@ func (repo *AccountRepositoryMemory) ChangeEmail(id string, email string) error func (repo *AccountRepositoryMemory) RemoveEmail(id string) error { account, err := repo.GetByID(id) if err != nil { return err } + if account == nil { return errors.New("Account does not exist") } + account.Email.Valid = false account.Email.String = "" return nil @@ -127,6 +136,8 @@ func (repo *AccountRepositoryMemory) RemoveEmail(id string) error { func (repo *AccountRepositoryMemory) ChangeAvatarURL(id string, avatarURL string) error { account, err := repo.GetByID(id) if err != nil { return err } + if account == nil { return errors.New("Account does not exist") } + account.AvatarURL.Valid = true account.AvatarURL.String = avatarURL return nil @@ -134,6 +145,8 @@ func (repo *AccountRepositoryMemory) ChangeAvatarURL(id string, avatarURL string func (repo *AccountRepositoryMemory) RemoveAvatar(id string) error { account, err := repo.GetByID(id) if err != nil { return err } + if account == nil { return errors.New("Account does not exist") } + account.AvatarURL.Valid = false account.AvatarURL.String = "" return nil diff --git a/service/account/account.go b/service/account/account.go index 88b06f9..730fc8b 100644 --- a/service/account/account.go +++ b/service/account/account.go @@ -60,26 +60,6 @@ func (s *AccountService) Create( return id, nil } -// Intended for large profile updates. For smaller adjusments, -// more specialised Change* and Remove* functions should be used. -func (s *AccountService) Update( - id string, - username string, - password string, - email *string, - avatarUrl *string, -) error { - if len(username) == 0 { return errors.New("Username cannot be empty") } - if len(password) == 0 { return errors.New("Password cannot be empty") } - if email != nil && len(*email) == 0 { return errors.New("Email cannot be empty") } - - if err := s.repo.Update(id, username, password, email, avatarUrl); err != nil { - return err - } - - s.log.Printf("Updated account '%s' (%s)", username, id) - return nil -} func (s *AccountService) ChangeUsername(id string, username string) error { if len(username) == 0 { return errors.New("Username cannot be empty") } if err := s.repo.ChangeUsername(id, username); err != nil { diff --git a/service/account/account_test.go b/service/account/account_test.go index dc5c78d..6487d64 100644 --- a/service/account/account_test.go +++ b/service/account/account_test.go @@ -149,6 +149,12 @@ func Test_Account(t *testing.T) { } else if account.Username != testUsername { t.Error("Username did not update") } + + t.Run("but not to an invalid value", func(t *testing.T) { + if err := service.ChangeUsername(id, ""); err == nil { + t.Error("Could change username to invalid value") + } + }) }) t.Run("can change password", func(t *testing.T) { @@ -164,6 +170,12 @@ func Test_Account(t *testing.T) { } else if account.Password != testPassword { t.Error("Password did not update") } + + t.Run("but not to an invalid value", func(t *testing.T) { + if err := service.ChangePassword(id, ""); err == nil { + t.Error("Could change password to invalid value") + } + }) }) t.Run("can change email", func(t *testing.T) { @@ -294,6 +306,55 @@ func Test_Account(t *testing.T) { } }) + t.Run("can't create an account with invalid", func(t *testing.T) { + t.Run("username", func(t *testing.T) { + if _, err := service.Create("", password, &email, &avatarURL); err == nil { + t.Error("Could create account with empty username") + } + }) + + t.Run("password", func(t *testing.T) { + if _, err := service.Create(username, "", &email, &avatarURL); err == nil { + t.Error("Could create account with empty password") + } + }) + + t.Run("email", func(t *testing.T) { + testEmail := "" + if _, err := service.Create(username, password, &testEmail, &avatarURL); err == nil { + t.Error("Could create account with empty (non-nil) email") + } + }) + }) + + t.Run("can't update account that doesn't exist", func(t *testing.T) { + garbageAccountID := "adsginh534g9405gmb40i9bm" + + t.Run("username", func(t *testing.T) { + if err := service.ChangeUsername(garbageAccountID, "some-username"); err == nil { + t.Error("Could update non-existent account's username") + } + }) + + t.Run("password", func(t *testing.T) { + if err := service.ChangePassword(garbageAccountID, "some-password"); err == nil { + t.Error("Could update non-existent account's password") + } + }) + + t.Run("email", func(t *testing.T) { + if err := service.ChangeEmail(garbageAccountID, "some-email@real.gov"); err == nil { + t.Error("Could update non-existent account's email") + } + }) + + t.Run("avatar URL", func(t *testing.T) { + if err := service.ChangeAvatarURL(garbageAccountID, "/img/null.webp"); err == nil { + t.Error("Could update non-existent account's avatar URL") + } + }) + }) + t.Cleanup(func() { if err := service.Delete(id); err != nil { t.Errorf("Failed to clean up test case: %v", err)