feat: tests
This commit is contained in:
parent
3de76916c9
commit
1346abf733
32 changed files with 3772 additions and 11 deletions
195
internal/service/auth_test.go
Normal file
195
internal/service/auth_test.go
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/model"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newTestAuthService(dbi testutil.DBInfo) *AuthService {
|
||||
cfg := testutil.TestConfig()
|
||||
userRepo := repository.NewUserRepository(dbi.DB)
|
||||
profileRepo := repository.NewProfileRepository(dbi.DB)
|
||||
tokenRepo := repository.NewTokenRepository(dbi.DB)
|
||||
spaceRepo := repository.NewSpaceRepository(dbi.DB)
|
||||
spaceSvc := NewSpaceService(spaceRepo)
|
||||
emailSvc := NewEmailService(nil, "test@example.com", "http://localhost:9999", "Budgit Test", false)
|
||||
return NewAuthService(
|
||||
emailSvc,
|
||||
userRepo,
|
||||
profileRepo,
|
||||
tokenRepo,
|
||||
spaceSvc,
|
||||
cfg.JWTSecret,
|
||||
cfg.JWTExpiry,
|
||||
cfg.TokenMagicLinkExpiry,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
func TestAuthService_SendMagicLink(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestAuthService(dbi)
|
||||
|
||||
err := svc.SendMagicLink("newuser@example.com")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify user was created in DB
|
||||
userRepo := repository.NewUserRepository(dbi.DB)
|
||||
user, err := userRepo.ByEmail("newuser@example.com")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "newuser@example.com", user.Email)
|
||||
|
||||
// Verify profile was created in DB
|
||||
profileRepo := repository.NewProfileRepository(dbi.DB)
|
||||
profile, err := profileRepo.ByUserID(user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "", profile.Name)
|
||||
|
||||
// Verify token was created in DB
|
||||
var tokenCount int
|
||||
err = dbi.DB.Get(&tokenCount, `SELECT COUNT(*) FROM tokens WHERE user_id = $1 AND type = $2`, user.ID, model.TokenTypeMagicLink)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, tokenCount)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthService_VerifyMagicLink(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestAuthService(dbi)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "verify@example.com", nil)
|
||||
testutil.CreateTestToken(t, dbi.DB, user.ID, model.TokenTypeMagicLink, "test-token-123", time.Now().Add(10*time.Minute))
|
||||
|
||||
got, err := svc.VerifyMagicLink("test-token-123")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, user.ID, got.ID)
|
||||
assert.Equal(t, user.Email, got.Email)
|
||||
assert.NotNil(t, got.EmailVerifiedAt, "email should be marked as verified")
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthService_LoginWithPassword(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestAuthService(dbi)
|
||||
|
||||
hash, err := svc.HashPassword("testpassword1")
|
||||
require.NoError(t, err)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "login@example.com", &hash)
|
||||
|
||||
got, err := svc.LoginWithPassword("login@example.com", "testpassword1")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, user.ID, got.ID)
|
||||
assert.Equal(t, user.Email, got.Email)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthService_LoginWithPassword_Wrong(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestAuthService(dbi)
|
||||
|
||||
hash, err := svc.HashPassword("testpassword1")
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.CreateTestUser(t, dbi.DB, "wrongpw@example.com", &hash)
|
||||
|
||||
_, err = svc.LoginWithPassword("wrongpw@example.com", "wrongpassword!")
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthService_HashAndComparePassword(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestAuthService(dbi)
|
||||
|
||||
hash, err := svc.HashPassword("testpassword1")
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, hash)
|
||||
|
||||
// Correct password should succeed
|
||||
err = svc.ComparePassword("testpassword1", hash)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Wrong password should fail
|
||||
err = svc.ComparePassword("wrongpassword!", hash)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthService_GenerateAndVerifyJWT(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestAuthService(dbi)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "jwt@example.com", nil)
|
||||
|
||||
tokenString, err := svc.GenerateJWT(user)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, tokenString)
|
||||
|
||||
claims, err := svc.VerifyJWT(tokenString)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, user.ID, claims["user_id"])
|
||||
assert.Equal(t, user.Email, claims["email"])
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthService_SetPassword(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestAuthService(dbi)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "setpw@example.com", nil)
|
||||
assert.False(t, user.HasPassword())
|
||||
|
||||
err := svc.SetPassword(user.ID, "", "newpassword12", "newpassword12")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify user now has a password
|
||||
userRepo := repository.NewUserRepository(dbi.DB)
|
||||
updated, err := userRepo.ByID(user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, updated.HasPassword())
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthService_NeedsOnboarding(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestAuthService(dbi)
|
||||
|
||||
// User with empty name needs onboarding
|
||||
userEmpty, _ := testutil.CreateTestUserWithProfile(t, dbi.DB, "empty@example.com", "")
|
||||
|
||||
needs, err := svc.NeedsOnboarding(userEmpty.ID)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, needs)
|
||||
|
||||
// User with a name does not need onboarding
|
||||
userNamed, _ := testutil.CreateTestUserWithProfile(t, dbi.DB, "named@example.com", "Jane Doe")
|
||||
|
||||
needs, err = svc.NeedsOnboarding(userNamed.ID)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, needs)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthService_CompleteOnboarding(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestAuthService(dbi)
|
||||
|
||||
user, _ := testutil.CreateTestUserWithProfile(t, dbi.DB, "onboard@example.com", "")
|
||||
|
||||
err := svc.CompleteOnboarding(user.ID, "New Name")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify profile name was updated
|
||||
profileRepo := repository.NewProfileRepository(dbi.DB)
|
||||
profile, err := profileRepo.ByUserID(user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "New Name", profile.Name)
|
||||
})
|
||||
}
|
||||
232
internal/service/expense_test.go
Normal file
232
internal/service/expense_test.go
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/model"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestExpenseService_CreateExpense(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
expenseRepo := repository.NewExpenseRepository(dbi.DB)
|
||||
svc := NewExpenseService(expenseRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "exp-svc-create@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Expense Svc Space")
|
||||
tag := testutil.CreateTestTag(t, dbi.DB, space.ID, "Food", nil)
|
||||
|
||||
expense, err := svc.CreateExpense(CreateExpenseDTO{
|
||||
SpaceID: space.ID,
|
||||
UserID: user.ID,
|
||||
Description: "Lunch",
|
||||
Amount: 1500,
|
||||
Type: model.ExpenseTypeExpense,
|
||||
Date: time.Now(),
|
||||
TagIDs: []string{tag.ID},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, expense.ID)
|
||||
assert.Equal(t, "Lunch", expense.Description)
|
||||
assert.Equal(t, 1500, expense.AmountCents)
|
||||
assert.Equal(t, model.ExpenseTypeExpense, expense.Type)
|
||||
})
|
||||
}
|
||||
|
||||
func TestExpenseService_CreateExpense_EmptyDescription(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
expenseRepo := repository.NewExpenseRepository(dbi.DB)
|
||||
svc := NewExpenseService(expenseRepo)
|
||||
|
||||
expense, err := svc.CreateExpense(CreateExpenseDTO{
|
||||
SpaceID: "some-space",
|
||||
UserID: "some-user",
|
||||
Description: "",
|
||||
Amount: 1000,
|
||||
Type: model.ExpenseTypeExpense,
|
||||
Date: time.Now(),
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, expense)
|
||||
})
|
||||
}
|
||||
|
||||
func TestExpenseService_CreateExpense_ZeroAmount(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
expenseRepo := repository.NewExpenseRepository(dbi.DB)
|
||||
svc := NewExpenseService(expenseRepo)
|
||||
|
||||
expense, err := svc.CreateExpense(CreateExpenseDTO{
|
||||
SpaceID: "some-space",
|
||||
UserID: "some-user",
|
||||
Description: "Something",
|
||||
Amount: 0,
|
||||
Type: model.ExpenseTypeExpense,
|
||||
Date: time.Now(),
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, expense)
|
||||
})
|
||||
}
|
||||
|
||||
func TestExpenseService_GetExpensesWithTagsForSpacePaginated(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
expenseRepo := repository.NewExpenseRepository(dbi.DB)
|
||||
svc := NewExpenseService(expenseRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "exp-svc-paginate@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Expense Svc Paginate Space")
|
||||
tag := testutil.CreateTestTag(t, dbi.DB, space.ID, "Transport", nil)
|
||||
|
||||
// Create expense with tag via the service
|
||||
_, err := svc.CreateExpense(CreateExpenseDTO{
|
||||
SpaceID: space.ID,
|
||||
UserID: user.ID,
|
||||
Description: "Bus fare",
|
||||
Amount: 250,
|
||||
Type: model.ExpenseTypeExpense,
|
||||
Date: time.Now(),
|
||||
TagIDs: []string{tag.ID},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create expense without tag
|
||||
_, err = svc.CreateExpense(CreateExpenseDTO{
|
||||
SpaceID: space.ID,
|
||||
UserID: user.ID,
|
||||
Description: "Coffee",
|
||||
Amount: 500,
|
||||
Type: model.ExpenseTypeExpense,
|
||||
Date: time.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
results, totalPages, err := svc.GetExpensesWithTagsForSpacePaginated(space.ID, 1)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, results, 2)
|
||||
assert.Equal(t, 1, totalPages)
|
||||
|
||||
// Verify at least one result has tags and one does not
|
||||
var withTags, withoutTags int
|
||||
for _, r := range results {
|
||||
if len(r.Tags) > 0 {
|
||||
withTags++
|
||||
} else {
|
||||
withoutTags++
|
||||
}
|
||||
}
|
||||
assert.Equal(t, 1, withTags)
|
||||
assert.Equal(t, 1, withoutTags)
|
||||
})
|
||||
}
|
||||
|
||||
func TestExpenseService_GetBalanceForSpace(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
expenseRepo := repository.NewExpenseRepository(dbi.DB)
|
||||
svc := NewExpenseService(expenseRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "exp-svc-balance@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Expense Svc Balance Space")
|
||||
|
||||
testutil.CreateTestExpense(t, dbi.DB, space.ID, user.ID, "Topup", 10000, model.ExpenseTypeTopup)
|
||||
testutil.CreateTestExpense(t, dbi.DB, space.ID, user.ID, "Groceries", 3000, model.ExpenseTypeExpense)
|
||||
|
||||
balance, err := svc.GetBalanceForSpace(space.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 7000, balance)
|
||||
})
|
||||
}
|
||||
|
||||
func TestExpenseService_GetExpensesByTag(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
expenseRepo := repository.NewExpenseRepository(dbi.DB)
|
||||
svc := NewExpenseService(expenseRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "exp-svc-bytag@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Expense Svc ByTag Space")
|
||||
tagColor := "#ff0000"
|
||||
tag := testutil.CreateTestTag(t, dbi.DB, space.ID, "Dining", &tagColor)
|
||||
|
||||
now := time.Now()
|
||||
_, err := svc.CreateExpense(CreateExpenseDTO{
|
||||
SpaceID: space.ID,
|
||||
UserID: user.ID,
|
||||
Description: "Dinner",
|
||||
Amount: 2500,
|
||||
Type: model.ExpenseTypeExpense,
|
||||
Date: now,
|
||||
TagIDs: []string{tag.ID},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
fromDate := now.Add(-24 * time.Hour)
|
||||
toDate := now.Add(24 * time.Hour)
|
||||
summaries, err := svc.GetExpensesByTag(space.ID, fromDate, toDate)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, summaries, 1)
|
||||
assert.Equal(t, tag.ID, summaries[0].TagID)
|
||||
assert.Equal(t, 2500, summaries[0].TotalAmount)
|
||||
})
|
||||
}
|
||||
|
||||
func TestExpenseService_UpdateExpense(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
expenseRepo := repository.NewExpenseRepository(dbi.DB)
|
||||
svc := NewExpenseService(expenseRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "exp-svc-update@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Expense Svc Update Space")
|
||||
|
||||
created, err := svc.CreateExpense(CreateExpenseDTO{
|
||||
SpaceID: space.ID,
|
||||
UserID: user.ID,
|
||||
Description: "Old Description",
|
||||
Amount: 1000,
|
||||
Type: model.ExpenseTypeExpense,
|
||||
Date: time.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
updated, err := svc.UpdateExpense(UpdateExpenseDTO{
|
||||
ID: created.ID,
|
||||
SpaceID: space.ID,
|
||||
Description: "New Description",
|
||||
Amount: 2000,
|
||||
Type: model.ExpenseTypeExpense,
|
||||
Date: time.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "New Description", updated.Description)
|
||||
assert.Equal(t, 2000, updated.AmountCents)
|
||||
})
|
||||
}
|
||||
|
||||
func TestExpenseService_DeleteExpense(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
expenseRepo := repository.NewExpenseRepository(dbi.DB)
|
||||
svc := NewExpenseService(expenseRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "exp-svc-delete@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Expense Svc Delete Space")
|
||||
|
||||
created, err := svc.CreateExpense(CreateExpenseDTO{
|
||||
SpaceID: space.ID,
|
||||
UserID: user.ID,
|
||||
Description: "Doomed Expense",
|
||||
Amount: 500,
|
||||
Type: model.ExpenseTypeExpense,
|
||||
Date: time.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.DeleteExpense(created.ID, space.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = svc.GetExpense(created.ID)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
90
internal/service/invite_test.go
Normal file
90
internal/service/invite_test.go
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newTestInviteService(dbi testutil.DBInfo) *InviteService {
|
||||
inviteRepo := repository.NewInvitationRepository(dbi.DB)
|
||||
spaceRepo := repository.NewSpaceRepository(dbi.DB)
|
||||
userRepo := repository.NewUserRepository(dbi.DB)
|
||||
emailSvc := NewEmailService(nil, "test@example.com", "http://localhost:9999", "Budgit Test", false)
|
||||
return NewInviteService(inviteRepo, spaceRepo, userRepo, emailSvc)
|
||||
}
|
||||
|
||||
func TestInviteService_CreateInvite(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestInviteService(dbi)
|
||||
|
||||
owner := testutil.CreateTestUser(t, dbi.DB, "invite-owner@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, owner.ID, "Invite Space")
|
||||
|
||||
invitation, err := svc.CreateInvite(space.ID, owner.ID, "invitee@example.com")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, space.ID, invitation.SpaceID)
|
||||
assert.Equal(t, owner.ID, invitation.InviterID)
|
||||
assert.Equal(t, "invitee@example.com", invitation.Email)
|
||||
assert.NotEmpty(t, invitation.Token)
|
||||
})
|
||||
}
|
||||
|
||||
func TestInviteService_AcceptInvite(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestInviteService(dbi)
|
||||
|
||||
owner := testutil.CreateTestUser(t, dbi.DB, "accept-owner@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, owner.ID, "Accept Space")
|
||||
invitation := testutil.CreateTestInvitation(t, dbi.DB, space.ID, owner.ID, "acceptee@example.com")
|
||||
|
||||
// Create the user who will accept
|
||||
accepter := testutil.CreateTestUser(t, dbi.DB, "acceptee@example.com", nil)
|
||||
|
||||
spaceID, err := svc.AcceptInvite(invitation.Token, accepter.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, space.ID, spaceID)
|
||||
|
||||
// Verify member was added to space
|
||||
spaceRepo := repository.NewSpaceRepository(dbi.DB)
|
||||
isMember, err := spaceRepo.IsMember(space.ID, accepter.ID)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, isMember)
|
||||
})
|
||||
}
|
||||
|
||||
func TestInviteService_CancelInvite(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestInviteService(dbi)
|
||||
|
||||
owner := testutil.CreateTestUser(t, dbi.DB, "cancel-owner@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, owner.ID, "Cancel Space")
|
||||
invitation := testutil.CreateTestInvitation(t, dbi.DB, space.ID, owner.ID, "cancelee@example.com")
|
||||
|
||||
err := svc.CancelInvite(invitation.Token)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify invitation is gone
|
||||
inviteRepo := repository.NewInvitationRepository(dbi.DB)
|
||||
_, err = inviteRepo.GetByToken(invitation.Token)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestInviteService_GetPendingInvites(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
svc := newTestInviteService(dbi)
|
||||
|
||||
owner := testutil.CreateTestUser(t, dbi.DB, "pending-owner@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, owner.ID, "Pending Space")
|
||||
testutil.CreateTestInvitation(t, dbi.DB, space.ID, owner.ID, "pending1@example.com")
|
||||
testutil.CreateTestInvitation(t, dbi.DB, space.ID, owner.ID, "pending2@example.com")
|
||||
|
||||
pending, err := svc.GetPendingInvites(space.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, pending, 2)
|
||||
})
|
||||
}
|
||||
189
internal/service/money_account_test.go
Normal file
189
internal/service/money_account_test.go
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/model"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMoneyAccountService_CreateAccount(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
accountRepo := repository.NewMoneyAccountRepository(dbi.DB)
|
||||
svc := NewMoneyAccountService(accountRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "acct-svc-create@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Account Svc Space")
|
||||
|
||||
account, err := svc.CreateAccount(CreateMoneyAccountDTO{
|
||||
SpaceID: space.ID,
|
||||
Name: "Savings",
|
||||
CreatedBy: user.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, account.ID)
|
||||
assert.Equal(t, "Savings", account.Name)
|
||||
assert.Equal(t, space.ID, account.SpaceID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMoneyAccountService_CreateAccount_EmptyName(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
accountRepo := repository.NewMoneyAccountRepository(dbi.DB)
|
||||
svc := NewMoneyAccountService(accountRepo)
|
||||
|
||||
account, err := svc.CreateAccount(CreateMoneyAccountDTO{
|
||||
SpaceID: "some-space",
|
||||
Name: "",
|
||||
CreatedBy: "some-user",
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, account)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMoneyAccountService_GetAccountsForSpace(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
accountRepo := repository.NewMoneyAccountRepository(dbi.DB)
|
||||
svc := NewMoneyAccountService(accountRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "acct-svc-list@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Account Svc List Space")
|
||||
account := testutil.CreateTestMoneyAccount(t, dbi.DB, space.ID, "Checking", user.ID)
|
||||
testutil.CreateTestTransfer(t, dbi.DB, account.ID, 5000, model.TransferDirectionDeposit, user.ID)
|
||||
|
||||
accounts, err := svc.GetAccountsForSpace(space.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, accounts, 1)
|
||||
assert.Equal(t, "Checking", accounts[0].Name)
|
||||
assert.Equal(t, 5000, accounts[0].BalanceCents)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMoneyAccountService_CreateTransfer_Deposit(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
accountRepo := repository.NewMoneyAccountRepository(dbi.DB)
|
||||
svc := NewMoneyAccountService(accountRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "acct-svc-deposit@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Account Svc Deposit Space")
|
||||
account := testutil.CreateTestMoneyAccount(t, dbi.DB, space.ID, "Deposit Account", user.ID)
|
||||
|
||||
transfer, err := svc.CreateTransfer(CreateTransferDTO{
|
||||
AccountID: account.ID,
|
||||
Amount: 3000,
|
||||
Direction: model.TransferDirectionDeposit,
|
||||
Note: "Initial deposit",
|
||||
CreatedBy: user.ID,
|
||||
}, 10000)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, transfer.ID)
|
||||
assert.Equal(t, 3000, transfer.AmountCents)
|
||||
assert.Equal(t, model.TransferDirectionDeposit, transfer.Direction)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMoneyAccountService_CreateTransfer_InsufficientBalance(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
accountRepo := repository.NewMoneyAccountRepository(dbi.DB)
|
||||
svc := NewMoneyAccountService(accountRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "acct-svc-insuf@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Account Svc Insuf Space")
|
||||
account := testutil.CreateTestMoneyAccount(t, dbi.DB, space.ID, "Insuf Account", user.ID)
|
||||
|
||||
transfer, err := svc.CreateTransfer(CreateTransferDTO{
|
||||
AccountID: account.ID,
|
||||
Amount: 5000,
|
||||
Direction: model.TransferDirectionDeposit,
|
||||
Note: "Too much",
|
||||
CreatedBy: user.ID,
|
||||
}, 1000)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, transfer)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMoneyAccountService_CreateTransfer_Withdrawal(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
accountRepo := repository.NewMoneyAccountRepository(dbi.DB)
|
||||
svc := NewMoneyAccountService(accountRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "acct-svc-withdraw@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Account Svc Withdraw Space")
|
||||
account := testutil.CreateTestMoneyAccount(t, dbi.DB, space.ID, "Withdraw Account", user.ID)
|
||||
testutil.CreateTestTransfer(t, dbi.DB, account.ID, 5000, model.TransferDirectionDeposit, user.ID)
|
||||
|
||||
transfer, err := svc.CreateTransfer(CreateTransferDTO{
|
||||
AccountID: account.ID,
|
||||
Amount: 2000,
|
||||
Direction: model.TransferDirectionWithdrawal,
|
||||
Note: "Withdrawal",
|
||||
CreatedBy: user.ID,
|
||||
}, 0)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, transfer.ID)
|
||||
assert.Equal(t, 2000, transfer.AmountCents)
|
||||
assert.Equal(t, model.TransferDirectionWithdrawal, transfer.Direction)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMoneyAccountService_GetTotalAllocatedForSpace(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
accountRepo := repository.NewMoneyAccountRepository(dbi.DB)
|
||||
svc := NewMoneyAccountService(accountRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "acct-svc-total@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Account Svc Total Space")
|
||||
|
||||
account1 := testutil.CreateTestMoneyAccount(t, dbi.DB, space.ID, "Account 1", user.ID)
|
||||
testutil.CreateTestTransfer(t, dbi.DB, account1.ID, 3000, model.TransferDirectionDeposit, user.ID)
|
||||
|
||||
account2 := testutil.CreateTestMoneyAccount(t, dbi.DB, space.ID, "Account 2", user.ID)
|
||||
testutil.CreateTestTransfer(t, dbi.DB, account2.ID, 2000, model.TransferDirectionDeposit, user.ID)
|
||||
|
||||
total, err := svc.GetTotalAllocatedForSpace(space.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 5000, total)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMoneyAccountService_DeleteAccount(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
accountRepo := repository.NewMoneyAccountRepository(dbi.DB)
|
||||
svc := NewMoneyAccountService(accountRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "acct-svc-del@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Account Svc Del Space")
|
||||
account := testutil.CreateTestMoneyAccount(t, dbi.DB, space.ID, "Doomed Account", user.ID)
|
||||
|
||||
err := svc.DeleteAccount(account.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
accounts, err := svc.GetAccountsForSpace(space.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, accounts)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMoneyAccountService_DeleteTransfer(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
accountRepo := repository.NewMoneyAccountRepository(dbi.DB)
|
||||
svc := NewMoneyAccountService(accountRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "acct-svc-deltx@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Account Svc DelTx Space")
|
||||
account := testutil.CreateTestMoneyAccount(t, dbi.DB, space.ID, "DelTx Account", user.ID)
|
||||
transfer := testutil.CreateTestTransfer(t, dbi.DB, account.ID, 1000, model.TransferDirectionDeposit, user.ID)
|
||||
|
||||
err := svc.DeleteTransfer(transfer.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
transfers, err := svc.GetTransfersForAccount(account.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, transfers)
|
||||
})
|
||||
}
|
||||
144
internal/service/payment_method_test.go
Normal file
144
internal/service/payment_method_test.go
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/model"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPaymentMethodService_CreateMethod(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
methodRepo := repository.NewPaymentMethodRepository(dbi.DB)
|
||||
svc := NewPaymentMethodService(methodRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "pm-svc-create@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "PM Svc Space")
|
||||
|
||||
method, err := svc.CreateMethod(CreatePaymentMethodDTO{
|
||||
SpaceID: space.ID,
|
||||
Name: "Visa Card",
|
||||
Type: model.PaymentMethodTypeCredit,
|
||||
LastFour: "4242",
|
||||
CreatedBy: user.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, method.ID)
|
||||
assert.Equal(t, "Visa Card", method.Name)
|
||||
assert.Equal(t, model.PaymentMethodTypeCredit, method.Type)
|
||||
require.NotNil(t, method.LastFour)
|
||||
assert.Equal(t, "4242", *method.LastFour)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPaymentMethodService_CreateMethod_EmptyName(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
methodRepo := repository.NewPaymentMethodRepository(dbi.DB)
|
||||
svc := NewPaymentMethodService(methodRepo)
|
||||
|
||||
method, err := svc.CreateMethod(CreatePaymentMethodDTO{
|
||||
SpaceID: "some-space",
|
||||
Name: "",
|
||||
Type: model.PaymentMethodTypeCredit,
|
||||
LastFour: "4242",
|
||||
CreatedBy: "some-user",
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, method)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPaymentMethodService_CreateMethod_InvalidType(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
methodRepo := repository.NewPaymentMethodRepository(dbi.DB)
|
||||
svc := NewPaymentMethodService(methodRepo)
|
||||
|
||||
method, err := svc.CreateMethod(CreatePaymentMethodDTO{
|
||||
SpaceID: "some-space",
|
||||
Name: "Bad Type Card",
|
||||
Type: "invalid",
|
||||
LastFour: "4242",
|
||||
CreatedBy: "some-user",
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, method)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPaymentMethodService_CreateMethod_InvalidLastFour(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
methodRepo := repository.NewPaymentMethodRepository(dbi.DB)
|
||||
svc := NewPaymentMethodService(methodRepo)
|
||||
|
||||
method, err := svc.CreateMethod(CreatePaymentMethodDTO{
|
||||
SpaceID: "some-space",
|
||||
Name: "Short Digits Card",
|
||||
Type: model.PaymentMethodTypeDebit,
|
||||
LastFour: "12",
|
||||
CreatedBy: "some-user",
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, method)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPaymentMethodService_GetMethodsForSpace(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
methodRepo := repository.NewPaymentMethodRepository(dbi.DB)
|
||||
svc := NewPaymentMethodService(methodRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "pm-svc-list@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "PM Svc List Space")
|
||||
|
||||
testutil.CreateTestPaymentMethod(t, dbi.DB, space.ID, "Visa", model.PaymentMethodTypeCredit, user.ID)
|
||||
testutil.CreateTestPaymentMethod(t, dbi.DB, space.ID, "Debit", model.PaymentMethodTypeDebit, user.ID)
|
||||
|
||||
methods, err := svc.GetMethodsForSpace(space.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, methods, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPaymentMethodService_UpdateMethod(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
methodRepo := repository.NewPaymentMethodRepository(dbi.DB)
|
||||
svc := NewPaymentMethodService(methodRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "pm-svc-update@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "PM Svc Update Space")
|
||||
method := testutil.CreateTestPaymentMethod(t, dbi.DB, space.ID, "Old Card", model.PaymentMethodTypeCredit, user.ID)
|
||||
|
||||
updated, err := svc.UpdateMethod(UpdatePaymentMethodDTO{
|
||||
ID: method.ID,
|
||||
Name: "New Card",
|
||||
Type: model.PaymentMethodTypeDebit,
|
||||
LastFour: "9999",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "New Card", updated.Name)
|
||||
assert.Equal(t, model.PaymentMethodTypeDebit, updated.Type)
|
||||
require.NotNil(t, updated.LastFour)
|
||||
assert.Equal(t, "9999", *updated.LastFour)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPaymentMethodService_DeleteMethod(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
methodRepo := repository.NewPaymentMethodRepository(dbi.DB)
|
||||
svc := NewPaymentMethodService(methodRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "pm-svc-delete@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "PM Svc Delete Space")
|
||||
method := testutil.CreateTestPaymentMethod(t, dbi.DB, space.ID, "Doomed Card", model.PaymentMethodTypeCredit, user.ID)
|
||||
|
||||
err := svc.DeleteMethod(method.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
methods, err := svc.GetMethodsForSpace(space.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, methods)
|
||||
})
|
||||
}
|
||||
35
internal/service/profile_test.go
Normal file
35
internal/service/profile_test.go
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestProfileService_ByUserID(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
profileRepo := repository.NewProfileRepository(dbi.DB)
|
||||
svc := NewProfileService(profileRepo)
|
||||
|
||||
user, profile := testutil.CreateTestUserWithProfile(t, dbi.DB, "profile@example.com", "Test User")
|
||||
|
||||
got, err := svc.ByUserID(user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, profile.ID, got.ID)
|
||||
assert.Equal(t, user.ID, got.UserID)
|
||||
assert.Equal(t, "Test User", got.Name)
|
||||
})
|
||||
}
|
||||
|
||||
func TestProfileService_ByUserID_NotFound(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
profileRepo := repository.NewProfileRepository(dbi.DB)
|
||||
svc := NewProfileService(profileRepo)
|
||||
|
||||
_, err := svc.ByUserID("nonexistent-id")
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
204
internal/service/shopping_list_test.go
Normal file
204
internal/service/shopping_list_test.go
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestShoppingListService_CreateList(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
listRepo := repository.NewShoppingListRepository(dbi.DB)
|
||||
itemRepo := repository.NewListItemRepository(dbi.DB)
|
||||
svc := NewShoppingListService(listRepo, itemRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "list-svc-create@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "List Svc Space")
|
||||
|
||||
list, err := svc.CreateList(space.ID, "Weekly Groceries")
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, list.ID)
|
||||
assert.Equal(t, "Weekly Groceries", list.Name)
|
||||
assert.Equal(t, space.ID, list.SpaceID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestShoppingListService_CreateList_EmptyName(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
listRepo := repository.NewShoppingListRepository(dbi.DB)
|
||||
itemRepo := repository.NewListItemRepository(dbi.DB)
|
||||
svc := NewShoppingListService(listRepo, itemRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "list-svc-empty@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "List Svc Empty Space")
|
||||
|
||||
list, err := svc.CreateList(space.ID, "")
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, list)
|
||||
})
|
||||
}
|
||||
|
||||
func TestShoppingListService_GetList(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
listRepo := repository.NewShoppingListRepository(dbi.DB)
|
||||
itemRepo := repository.NewListItemRepository(dbi.DB)
|
||||
svc := NewShoppingListService(listRepo, itemRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "list-svc-get@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "List Svc Get Space")
|
||||
seeded := testutil.CreateTestShoppingList(t, dbi.DB, space.ID, "Seeded List")
|
||||
|
||||
list, err := svc.GetList(seeded.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, seeded.ID, list.ID)
|
||||
assert.Equal(t, "Seeded List", list.Name)
|
||||
})
|
||||
}
|
||||
|
||||
func TestShoppingListService_UpdateList(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
listRepo := repository.NewShoppingListRepository(dbi.DB)
|
||||
itemRepo := repository.NewListItemRepository(dbi.DB)
|
||||
svc := NewShoppingListService(listRepo, itemRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "list-svc-update@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "List Svc Update Space")
|
||||
seeded := testutil.CreateTestShoppingList(t, dbi.DB, space.ID, "Old Name")
|
||||
|
||||
updated, err := svc.UpdateList(seeded.ID, "New Name")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "New Name", updated.Name)
|
||||
})
|
||||
}
|
||||
|
||||
func TestShoppingListService_DeleteList(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
listRepo := repository.NewShoppingListRepository(dbi.DB)
|
||||
itemRepo := repository.NewListItemRepository(dbi.DB)
|
||||
svc := NewShoppingListService(listRepo, itemRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "list-svc-del@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "List Svc Del Space")
|
||||
seeded := testutil.CreateTestShoppingList(t, dbi.DB, space.ID, "Doomed List")
|
||||
testutil.CreateTestListItem(t, dbi.DB, seeded.ID, "Item 1", user.ID)
|
||||
testutil.CreateTestListItem(t, dbi.DB, seeded.ID, "Item 2", user.ID)
|
||||
|
||||
err := svc.DeleteList(seeded.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = svc.GetList(seeded.ID)
|
||||
assert.Error(t, err)
|
||||
|
||||
items, err := itemRepo.GetByListID(seeded.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, items)
|
||||
})
|
||||
}
|
||||
|
||||
func TestShoppingListService_AddItemToList(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
listRepo := repository.NewShoppingListRepository(dbi.DB)
|
||||
itemRepo := repository.NewListItemRepository(dbi.DB)
|
||||
svc := NewShoppingListService(listRepo, itemRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "list-svc-additem@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "List Svc AddItem Space")
|
||||
seeded := testutil.CreateTestShoppingList(t, dbi.DB, space.ID, "Add Item List")
|
||||
|
||||
item, err := svc.AddItemToList(seeded.ID, "Milk", user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, item.ID)
|
||||
assert.Equal(t, "Milk", item.Name)
|
||||
assert.Equal(t, seeded.ID, item.ListID)
|
||||
assert.False(t, item.IsChecked)
|
||||
})
|
||||
}
|
||||
|
||||
func TestShoppingListService_GetItemsForListPaginated(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
listRepo := repository.NewShoppingListRepository(dbi.DB)
|
||||
itemRepo := repository.NewListItemRepository(dbi.DB)
|
||||
svc := NewShoppingListService(listRepo, itemRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "list-svc-paginate@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "List Svc Paginate Space")
|
||||
seeded := testutil.CreateTestShoppingList(t, dbi.DB, space.ID, "Paginate List")
|
||||
|
||||
for i := 0; i < 6; i++ {
|
||||
testutil.CreateTestListItem(t, dbi.DB, seeded.ID, fmt.Sprintf("Item %d", i), user.ID)
|
||||
}
|
||||
|
||||
items, totalPages, err := svc.GetItemsForListPaginated(seeded.ID, 1)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, items, 5)
|
||||
assert.Equal(t, 2, totalPages)
|
||||
})
|
||||
}
|
||||
|
||||
func TestShoppingListService_CheckItem(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
listRepo := repository.NewShoppingListRepository(dbi.DB)
|
||||
itemRepo := repository.NewListItemRepository(dbi.DB)
|
||||
svc := NewShoppingListService(listRepo, itemRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "list-svc-check@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "List Svc Check Space")
|
||||
seeded := testutil.CreateTestShoppingList(t, dbi.DB, space.ID, "Check List")
|
||||
item := testutil.CreateTestListItem(t, dbi.DB, seeded.ID, "Check Me", user.ID)
|
||||
|
||||
err := svc.CheckItem(item.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
fetched, err := svc.GetItem(item.ID)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, fetched.IsChecked)
|
||||
})
|
||||
}
|
||||
|
||||
func TestShoppingListService_GetListsWithUncheckedItems(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
listRepo := repository.NewShoppingListRepository(dbi.DB)
|
||||
itemRepo := repository.NewListItemRepository(dbi.DB)
|
||||
svc := NewShoppingListService(listRepo, itemRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "list-svc-unchecked@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "List Svc Unchecked Space")
|
||||
seeded := testutil.CreateTestShoppingList(t, dbi.DB, space.ID, "Unchecked List")
|
||||
|
||||
checkedItem := testutil.CreateTestListItem(t, dbi.DB, seeded.ID, "Checked Item", user.ID)
|
||||
testutil.CreateTestListItem(t, dbi.DB, seeded.ID, "Unchecked Item", user.ID)
|
||||
|
||||
_, err := dbi.DB.Exec("UPDATE list_items SET is_checked = true WHERE id = $1", checkedItem.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := svc.GetListsWithUncheckedItems(space.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, result, 1)
|
||||
assert.Equal(t, seeded.ID, result[0].List.ID)
|
||||
require.Len(t, result[0].Items, 1)
|
||||
assert.Equal(t, "Unchecked Item", result[0].Items[0].Name)
|
||||
})
|
||||
}
|
||||
|
||||
func TestShoppingListService_DeleteItem(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
listRepo := repository.NewShoppingListRepository(dbi.DB)
|
||||
itemRepo := repository.NewListItemRepository(dbi.DB)
|
||||
svc := NewShoppingListService(listRepo, itemRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "list-svc-delitem@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "List Svc DelItem Space")
|
||||
seeded := testutil.CreateTestShoppingList(t, dbi.DB, space.ID, "DelItem List")
|
||||
item := testutil.CreateTestListItem(t, dbi.DB, seeded.ID, "Doomed Item", user.ID)
|
||||
|
||||
err := svc.DeleteItem(item.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = svc.GetItem(item.ID)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
172
internal/service/space_test.go
Normal file
172
internal/service/space_test.go
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/model"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSpaceService_CreateSpace(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
spaceRepo := repository.NewSpaceRepository(dbi.DB)
|
||||
svc := NewSpaceService(spaceRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "create-space@example.com", nil)
|
||||
|
||||
space, err := svc.CreateSpace("My Space", user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "My Space", space.Name)
|
||||
assert.Equal(t, user.ID, space.OwnerID)
|
||||
assert.NotEmpty(t, space.ID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSpaceService_CreateSpace_EmptyName(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
spaceRepo := repository.NewSpaceRepository(dbi.DB)
|
||||
svc := NewSpaceService(spaceRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "empty-name@example.com", nil)
|
||||
|
||||
_, err := svc.CreateSpace("", user.ID)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSpaceService_EnsurePersonalSpace(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
spaceRepo := repository.NewSpaceRepository(dbi.DB)
|
||||
svc := NewSpaceService(spaceRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "personal@example.com", nil)
|
||||
|
||||
// First call creates the personal space
|
||||
space1, err := svc.EnsurePersonalSpace(user)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, PersonalSpaceName, space1.Name)
|
||||
|
||||
// Second call returns the same space (idempotent)
|
||||
space2, err := svc.EnsurePersonalSpace(user)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, space1.ID, space2.ID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSpaceService_GetSpacesForUser(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
spaceRepo := repository.NewSpaceRepository(dbi.DB)
|
||||
svc := NewSpaceService(spaceRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "getspaces@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Test Space")
|
||||
|
||||
spaces, err := svc.GetSpacesForUser(user.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, spaces, 1)
|
||||
assert.Equal(t, space.ID, spaces[0].ID)
|
||||
assert.Equal(t, "Test Space", spaces[0].Name)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSpaceService_IsMember(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
spaceRepo := repository.NewSpaceRepository(dbi.DB)
|
||||
svc := NewSpaceService(spaceRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "ismember@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Member Check Space")
|
||||
|
||||
// Owner should be a member
|
||||
isMember, err := svc.IsMember(user.ID, space.ID)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, isMember)
|
||||
|
||||
// Random ID should not be a member
|
||||
isMember, err = svc.IsMember("nonexistent-user-id", space.ID)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, isMember)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSpaceService_GetMembers(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
spaceRepo := repository.NewSpaceRepository(dbi.DB)
|
||||
svc := NewSpaceService(spaceRepo)
|
||||
|
||||
owner, _ := testutil.CreateTestUserWithProfile(t, dbi.DB, "owner-members@example.com", "Owner")
|
||||
member, _ := testutil.CreateTestUserWithProfile(t, dbi.DB, "member-members@example.com", "Member")
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, owner.ID, "Members Space")
|
||||
|
||||
// Add second user as a member
|
||||
_, err := dbi.DB.Exec(
|
||||
`INSERT INTO space_members (space_id, user_id, role, joined_at) VALUES ($1, $2, $3, $4)`,
|
||||
space.ID, member.ID, model.RoleMember, time.Now(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
members, err := svc.GetMembers(space.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, members, 2)
|
||||
|
||||
// The query orders by role DESC (owner first), then joined_at ASC
|
||||
assert.Equal(t, model.RoleOwner, members[0].Role)
|
||||
assert.Equal(t, "Owner", members[0].Name)
|
||||
assert.Equal(t, model.RoleMember, members[1].Role)
|
||||
assert.Equal(t, "Member", members[1].Name)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSpaceService_RemoveMember(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
spaceRepo := repository.NewSpaceRepository(dbi.DB)
|
||||
svc := NewSpaceService(spaceRepo)
|
||||
|
||||
owner := testutil.CreateTestUser(t, dbi.DB, "remove-owner@example.com", nil)
|
||||
member := testutil.CreateTestUser(t, dbi.DB, "remove-member@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, owner.ID, "Remove Space")
|
||||
|
||||
// Add member
|
||||
_, err := dbi.DB.Exec(
|
||||
`INSERT INTO space_members (space_id, user_id, role, joined_at) VALUES ($1, $2, $3, $4)`,
|
||||
space.ID, member.ID, model.RoleMember, time.Now(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify member was added
|
||||
isMember, err := svc.IsMember(member.ID, space.ID)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, isMember)
|
||||
|
||||
// Remove member
|
||||
err = svc.RemoveMember(space.ID, member.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify member was removed
|
||||
isMember, err = svc.IsMember(member.ID, space.ID)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, isMember)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSpaceService_UpdateSpaceName(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
spaceRepo := repository.NewSpaceRepository(dbi.DB)
|
||||
svc := NewSpaceService(spaceRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "rename@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Old Name")
|
||||
|
||||
err := svc.UpdateSpaceName(space.ID, "New Name")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify name was updated by fetching the space
|
||||
fetched, err := svc.GetSpace(space.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "New Name", fetched.Name)
|
||||
})
|
||||
}
|
||||
99
internal/service/tag_test.go
Normal file
99
internal/service/tag_test.go
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTagService_CreateTag(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
tagRepo := repository.NewTagRepository(dbi.DB)
|
||||
svc := NewTagService(tagRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "tag-svc-create@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Tag Svc Space")
|
||||
|
||||
color := "#ff0000"
|
||||
tag, err := svc.CreateTag(space.ID, "Groceries", &color)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, tag.ID)
|
||||
assert.Equal(t, "groceries", tag.Name)
|
||||
assert.Equal(t, &color, tag.Color)
|
||||
assert.Equal(t, space.ID, tag.SpaceID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTagService_CreateTag_EmptyName(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
tagRepo := repository.NewTagRepository(dbi.DB)
|
||||
svc := NewTagService(tagRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "tag-svc-empty@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Tag Svc Empty Space")
|
||||
|
||||
tag, err := svc.CreateTag(space.ID, "", nil)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, tag)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTagService_GetTagsForSpace(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
tagRepo := repository.NewTagRepository(dbi.DB)
|
||||
svc := NewTagService(tagRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "tag-svc-list@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Tag Svc List Space")
|
||||
|
||||
testutil.CreateTestTag(t, dbi.DB, space.ID, "Alpha", nil)
|
||||
testutil.CreateTestTag(t, dbi.DB, space.ID, "Beta", nil)
|
||||
|
||||
tags, err := svc.GetTagsForSpace(space.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tags, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTagService_UpdateTag(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
tagRepo := repository.NewTagRepository(dbi.DB)
|
||||
svc := NewTagService(tagRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "tag-svc-update@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Tag Svc Update Space")
|
||||
tag := testutil.CreateTestTag(t, dbi.DB, space.ID, "Old Name", nil)
|
||||
|
||||
newColor := "#00ff00"
|
||||
updated, err := svc.UpdateTag(tag.ID, "New Name", &newColor)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "new name", updated.Name)
|
||||
assert.Equal(t, &newColor, updated.Color)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTagService_DeleteTag(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
tagRepo := repository.NewTagRepository(dbi.DB)
|
||||
svc := NewTagService(tagRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "tag-svc-delete@example.com", nil)
|
||||
space := testutil.CreateTestSpace(t, dbi.DB, user.ID, "Tag Svc Delete Space")
|
||||
tag := testutil.CreateTestTag(t, dbi.DB, space.ID, "Doomed Tag", nil)
|
||||
|
||||
err := svc.DeleteTag(tag.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
tags, err := svc.GetTagsForSpace(space.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, tags)
|
||||
})
|
||||
}
|
||||
|
||||
func TestNormalizeTagName(t *testing.T) {
|
||||
result := NormalizeTagName(" Hello World ")
|
||||
assert.Equal(t, "hello world", result)
|
||||
}
|
||||
34
internal/service/user_test.go
Normal file
34
internal/service/user_test.go
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestUserService_ByID(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
userRepo := repository.NewUserRepository(dbi.DB)
|
||||
svc := NewUserService(userRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "test@example.com", nil)
|
||||
|
||||
got, err := svc.ByID(user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, user.ID, got.ID)
|
||||
assert.Equal(t, user.Email, got.Email)
|
||||
})
|
||||
}
|
||||
|
||||
func TestUserService_ByID_NotFound(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
userRepo := repository.NewUserRepository(dbi.DB)
|
||||
svc := NewUserService(userRepo)
|
||||
|
||||
_, err := svc.ByID("nonexistent-id")
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue