add in-memory DB for accounts, with tests!
This commit is contained in:
parent
49e14b5bc5
commit
5a540184c9
9 changed files with 534 additions and 45 deletions
|
|
@ -19,7 +19,7 @@ func NewAccountService(repo repository.AccountRepository, logger *log.Logger) (*
|
|||
}
|
||||
}
|
||||
|
||||
func (s *AccountService) GetAll() ([]model.Account, error) {
|
||||
func (s *AccountService) GetAll() ([]*model.Account, error) {
|
||||
return s.repo.GetAll()
|
||||
}
|
||||
|
||||
|
|
@ -39,12 +39,6 @@ func (s *AccountService) GetByEmail(email string) (*model.Account, error) {
|
|||
return s.repo.GetByEmail(email)
|
||||
}
|
||||
|
||||
func (s *AccountService) GetBySession(sessionToken string) (*model.Account, error) {
|
||||
if sessionToken == "" { return nil, nil }
|
||||
|
||||
return s.repo.GetBySession(sessionToken)
|
||||
}
|
||||
|
||||
func (s *AccountService) Create(
|
||||
username string,
|
||||
password string,
|
||||
|
|
@ -131,6 +125,10 @@ func (s *AccountService) IncrementFails(accountID string) (int, error) {
|
|||
return s.repo.IncrementFails(accountID)
|
||||
}
|
||||
|
||||
func (s *AccountService) ResetFails(accountID string) (error) {
|
||||
return s.repo.ResetFails(accountID)
|
||||
}
|
||||
|
||||
func (s *AccountService) Lock(accountID string) error {
|
||||
return s.repo.Lock(accountID)
|
||||
}
|
||||
|
|
|
|||
302
service/account/account_test.go
Normal file
302
service/account/account_test.go
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
package account
|
||||
|
||||
import (
|
||||
"arimelody-web/model"
|
||||
accountRepo "arimelody-web/repository/account"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
service *AccountService
|
||||
)
|
||||
|
||||
func init() {
|
||||
devNullFile, err := os.OpenFile(os.DevNull, os.O_RDWR, 0666)
|
||||
if err != nil { panic(err) }
|
||||
defer devNullFile.Close()
|
||||
|
||||
repo := accountRepo.NewAccountRepositoryMemory()
|
||||
service = NewAccountService(
|
||||
repo,
|
||||
log.New(devNullFile, "", model.DEFAULT_LOG_FLAGS),
|
||||
)
|
||||
}
|
||||
|
||||
// Tests the account lifecycle. Users:
|
||||
// - [x] can create account
|
||||
// - [x] can't create duplicate account
|
||||
// - [x] can change username
|
||||
// - [x] can change password
|
||||
// - [x] can change email
|
||||
// - [x] can change avatar URL
|
||||
// - [x] can increment auth failures
|
||||
// - [x] can reset auth failures
|
||||
// - [x] can lock account
|
||||
// - [x] can unlock account
|
||||
// - [x] can delete account
|
||||
func Test_Account(t *testing.T) {
|
||||
username := "testificate"
|
||||
password := "the amazing digital data breach"
|
||||
email := "goober@arimelody.space"
|
||||
avatarURL := "/img/default-avatar.webp"
|
||||
|
||||
var id string
|
||||
var err error
|
||||
|
||||
t.Run("accounts should start empty", func(t *testing.T) {
|
||||
t.Run("count is zero", func(t *testing.T) {
|
||||
if num, err := service.GetCount(); err != nil {
|
||||
t.Errorf("Failed to get number of accounts: %v", err)
|
||||
} else {
|
||||
assert.Equal(t, num, 0)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("service returns empty array", func(t *testing.T) {
|
||||
if accounts, err := service.GetAll(); err != nil {
|
||||
t.Errorf("Failed to get number of accounts: %v", err)
|
||||
} else {
|
||||
assert.Equal(t, len(accounts), 0)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("can create account", func(t *testing.T) {
|
||||
id, err = service.Create(username, password, &email, &avatarURL)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to create account: %v", err)
|
||||
}
|
||||
|
||||
t.Run("and fetch by ID", func(t *testing.T) {
|
||||
account, err := service.GetByID(id)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to get account after creation: %v", err)
|
||||
}
|
||||
|
||||
assert.Equal(t, account.Username, username)
|
||||
assert.Equal(t, account.Password, password)
|
||||
assert.Equal(t, account.Email.String, email)
|
||||
assert.Equal(t, account.AvatarURL.String, avatarURL)
|
||||
assert.Equal(t, account.FailAttempts, 0)
|
||||
assert.Equal(t, account.Locked, false)
|
||||
})
|
||||
t.Run("and fetch by username", func(t *testing.T) {
|
||||
account, err := service.GetByUsername(username)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to get account after creation: %v", err)
|
||||
}
|
||||
|
||||
assert.Equal(t, account.ID, id)
|
||||
assert.Equal(t, account.Password, password)
|
||||
assert.Equal(t, account.Email.String, email)
|
||||
assert.Equal(t, account.AvatarURL.String, avatarURL)
|
||||
assert.Equal(t, account.FailAttempts, 0)
|
||||
assert.Equal(t, account.Locked, false)
|
||||
})
|
||||
t.Run("and fetch by email", func(t *testing.T) {
|
||||
account, err := service.GetByEmail(email)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to get account after creation: %v", err)
|
||||
}
|
||||
|
||||
assert.Equal(t, account.ID, id)
|
||||
assert.Equal(t, account.Username, username)
|
||||
assert.Equal(t, account.Password, password)
|
||||
assert.Equal(t, account.AvatarURL.String, avatarURL)
|
||||
assert.Equal(t, account.FailAttempts, 0)
|
||||
assert.Equal(t, account.Locked, false)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("number of accounts should increment", func(t *testing.T) {
|
||||
t.Run("count is one", func(t *testing.T) {
|
||||
if num, err := service.GetCount(); err != nil {
|
||||
t.Errorf("Failed to get number of accounts: %v", err)
|
||||
} else {
|
||||
assert.Equal(t, num, 1)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("service returns array with one account", func(t *testing.T) {
|
||||
if accounts, err := service.GetAll(); err != nil {
|
||||
t.Errorf("Failed to get number of accounts: %v", err)
|
||||
} else {
|
||||
assert.Equal(t, len(accounts), 1)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("can't create duplicate account", func(t *testing.T) {
|
||||
_, err := service.Create(username, password, &email, &avatarURL)
|
||||
if err == nil {
|
||||
t.Error("Duplicate account was created")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can change username", func(t *testing.T) {
|
||||
testUsername := "some_other_name"
|
||||
if err := service.ChangeUsername(id, testUsername); err != nil {
|
||||
t.Errorf("Failed to change username: %v", err)
|
||||
}
|
||||
|
||||
if account, err := service.GetByID(id); err != nil {
|
||||
t.Errorf("Failed to get account: %v", err)
|
||||
} else if account == nil {
|
||||
t.Error("Account is nil after update")
|
||||
} else if account.Username != testUsername {
|
||||
t.Error("Username did not update")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can change password", func(t *testing.T) {
|
||||
testPassword := "other more different password"
|
||||
if err := service.ChangePassword(id, testPassword); err != nil {
|
||||
t.Errorf("Failed to change password: %v", err)
|
||||
}
|
||||
|
||||
if account, err := service.GetByID(id); err != nil {
|
||||
t.Errorf("Failed to get account: %v", err)
|
||||
} else if account == nil {
|
||||
t.Error("Account is nil after update")
|
||||
} else if account.Password != testPassword {
|
||||
t.Error("Password did not update")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can change email", func(t *testing.T) {
|
||||
testEmail := "brandnewemail@for.me"
|
||||
if err := service.ChangeEmail(id, testEmail); err != nil {
|
||||
t.Errorf("Failed to change email: %v", err)
|
||||
}
|
||||
|
||||
if account, err := service.GetByID(id); err != nil {
|
||||
t.Errorf("Failed to get account: %v", err)
|
||||
} else if account == nil {
|
||||
t.Error("Account is nil after update")
|
||||
} else if !account.Email.Valid || account.Email.String != testEmail {
|
||||
t.Error("Email did not update")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can remove email", func(t *testing.T) {
|
||||
if err := service.ChangeEmail(id, ""); err != nil {
|
||||
t.Errorf("Failed to change email: %v", err)
|
||||
}
|
||||
|
||||
if account, err := service.GetByID(id); err != nil {
|
||||
t.Errorf("Failed to get account: %v", err)
|
||||
} else if account == nil {
|
||||
t.Error("Account is nil after update")
|
||||
} else if account.Email.Valid || len(account.Email.String) > 0 {
|
||||
t.Error("Email did not update")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can change avatar URL", func(t *testing.T) {
|
||||
testAvatarURL := "/img/some-other-avatar.webp"
|
||||
if err := service.ChangeAvatarURL(id, testAvatarURL); err != nil {
|
||||
t.Errorf("Failed to change avatar URL: %v", err)
|
||||
}
|
||||
|
||||
if account, err := service.GetByID(id); err != nil {
|
||||
t.Errorf("Failed to get account: %v", err)
|
||||
} else if account == nil {
|
||||
t.Error("Account is nil after update")
|
||||
} else if !account.AvatarURL.Valid || account.AvatarURL.String != testAvatarURL {
|
||||
t.Error("Avatar URL did not update")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can remove avatar URL", func(t *testing.T) {
|
||||
if err := service.ChangeAvatarURL(id, ""); err != nil {
|
||||
t.Errorf("Failed to change avatar URL: %v", err)
|
||||
}
|
||||
|
||||
if account, err := service.GetByID(id); err != nil {
|
||||
t.Errorf("Failed to get account: %v", err)
|
||||
} else if account == nil {
|
||||
t.Error("Account is nil after update")
|
||||
} else if account.AvatarURL.Valid || len(account.AvatarURL.String) > 0 {
|
||||
t.Error("Avatar URL did not update")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can increment auth failures", func(t *testing.T) {
|
||||
if num, err := service.IncrementFails(id); err != nil {
|
||||
t.Errorf("Failed to increment account auth failures: %v", err)
|
||||
} else {
|
||||
assert.Equal(t, num, 1)
|
||||
}
|
||||
|
||||
if account, err := service.GetByID(id); err != nil {
|
||||
t.Errorf("Failed to get account: %v", err)
|
||||
} else if account == nil {
|
||||
t.Error("Account is nil after update")
|
||||
} else {
|
||||
assert.Equal(t, account.FailAttempts, 1)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can reset auth failures", func(t *testing.T) {
|
||||
if err := service.ResetFails(id); err != nil {
|
||||
t.Errorf("Failed to reset account auth failures: %v", err)
|
||||
}
|
||||
|
||||
if account, err := service.GetByID(id); err != nil {
|
||||
t.Errorf("Failed to get account: %v", err)
|
||||
} else if account == nil {
|
||||
t.Error("Account is nil after update")
|
||||
} else {
|
||||
assert.Equal(t, account.FailAttempts, 0)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can lock account", func(t *testing.T) {
|
||||
if err := service.Lock(id); err != nil {
|
||||
t.Errorf("Failed to lock account: %v", err)
|
||||
}
|
||||
|
||||
if account, err := service.GetByID(id); err != nil {
|
||||
t.Errorf("Failed to get account: %v", err)
|
||||
} else if account == nil {
|
||||
t.Error("Account is nil after update")
|
||||
} else {
|
||||
assert.Equal(t, account.Locked, true)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can unlock account", func(t *testing.T) {
|
||||
if err := service.Unlock(id); err != nil {
|
||||
t.Errorf("Failed to unlock account: %v", err)
|
||||
}
|
||||
|
||||
if account, err := service.GetByID(id); err != nil {
|
||||
t.Errorf("Failed to get account: %v", err)
|
||||
} else if account == nil {
|
||||
t.Error("Account is nil after update")
|
||||
} else {
|
||||
assert.Equal(t, account.Locked, false)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can delete account", func(t *testing.T) {
|
||||
if err = service.Delete(id); err != nil {
|
||||
t.Errorf("Failed to delete account: %v", err)
|
||||
}
|
||||
|
||||
if account, err := service.GetByID(id); err != nil {
|
||||
t.Errorf("Failed to get account after deletion: %v", err)
|
||||
} else if account != nil {
|
||||
t.Error("Account still exists after deletion")
|
||||
}
|
||||
})
|
||||
|
||||
t.Cleanup(func() {
|
||||
if err := service.Delete(id); err != nil {
|
||||
t.Errorf("Failed to clean up test case: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue