Coverage priorities 1-5: test pure functions, extract interfaces, mock-based handler tests
- Priority 1: Test NewSendEmailTask + NewSendPushTask (5 tests) - Priority 2: Test customHTTPErrorHandler — all 15+ branches (21 tests) - Priority 3: Extract Enqueuer interface + payload builders in worker pkg (5 tests) - Priority 4: Extract ClassifyFile/ComputeRelPath in migrate-encrypt (6 tests) - Priority 5: Define Handler interfaces, refactor to accept them, mock-based tests (14 tests) - Fix .gitignore: /worker instead of worker to stop ignoring internal/worker/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -456,3 +456,631 @@ func TestCreateResidence_ProTier_AllowsMore(t *testing.T) {
|
||||
func ptrTime(t time.Time) *time.Time {
|
||||
return &t
|
||||
}
|
||||
|
||||
// === GetMyResidences ===
|
||||
|
||||
func TestResidenceService_GetMyResidences(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
testutil.CreateTestResidence(t, db, user.ID, "House 1")
|
||||
testutil.CreateTestResidence(t, db, user.ID, "House 2")
|
||||
|
||||
resp, err := service.GetMyResidences(user.ID, time.Now())
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, resp.Residences, 2)
|
||||
}
|
||||
|
||||
func TestResidenceService_GetMyResidences_NoResidences(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "loner", "loner@test.com", "Password123")
|
||||
|
||||
resp, err := service.GetMyResidences(user.ID, time.Now())
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, resp.Residences)
|
||||
}
|
||||
|
||||
// === GetSummary ===
|
||||
|
||||
func TestResidenceService_GetSummary(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
testutil.CreateTestResidence(t, db, user.ID, "House 1")
|
||||
testutil.CreateTestResidence(t, db, user.ID, "House 2")
|
||||
|
||||
resp, err := service.GetSummary(user.ID, time.Now())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, resp.TotalResidences)
|
||||
}
|
||||
|
||||
func TestResidenceService_GetSummary_NoResidences(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "loner", "loner@test.com", "Password123")
|
||||
|
||||
resp, err := service.GetSummary(user.ID, time.Now())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 0, resp.TotalResidences)
|
||||
}
|
||||
|
||||
// === GetShareCode ===
|
||||
|
||||
func TestResidenceService_GetShareCode_NoActiveCode(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
|
||||
resp, err := service.GetShareCode(residence.ID, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Nil(t, resp) // No active code
|
||||
}
|
||||
|
||||
func TestResidenceService_GetShareCode_AccessDenied(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
other := testutil.CreateTestUser(t, db, "other", "other@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House")
|
||||
|
||||
_, err := service.GetShareCode(residence.ID, other.ID)
|
||||
testutil.AssertAppError(t, err, http.StatusForbidden, "error.residence_access_denied")
|
||||
}
|
||||
|
||||
// === GenerateShareCode ===
|
||||
|
||||
func TestResidenceService_GenerateShareCode_NotOwner(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
shared := testutil.CreateTestUser(t, db, "shared", "shared@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House")
|
||||
residenceRepo.AddUser(residence.ID, shared.ID)
|
||||
|
||||
_, err := service.GenerateShareCode(residence.ID, shared.ID, 24)
|
||||
testutil.AssertAppError(t, err, http.StatusForbidden, "error.not_residence_owner")
|
||||
}
|
||||
|
||||
func TestResidenceService_GenerateShareCode_DefaultExpiry(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
|
||||
// Pass 0 hours — should default to 24
|
||||
resp, err := service.GenerateShareCode(residence.ID, user.ID, 0)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, resp.ShareCode.Code)
|
||||
}
|
||||
|
||||
// === GenerateSharePackage ===
|
||||
|
||||
func TestResidenceService_GenerateSharePackage(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
|
||||
resp, err := service.GenerateSharePackage(residence.ID, user.ID, 48)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, resp.ShareCode)
|
||||
assert.Equal(t, "Test House", resp.ResidenceName)
|
||||
assert.Equal(t, "owner@test.com", resp.SharedBy)
|
||||
}
|
||||
|
||||
func TestResidenceService_GenerateSharePackage_NotOwner(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
shared := testutil.CreateTestUser(t, db, "shared", "shared@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House")
|
||||
residenceRepo.AddUser(residence.ID, shared.ID)
|
||||
|
||||
_, err := service.GenerateSharePackage(residence.ID, shared.ID, 24)
|
||||
testutil.AssertAppError(t, err, http.StatusForbidden, "error.not_residence_owner")
|
||||
}
|
||||
|
||||
// === JoinWithCode ===
|
||||
|
||||
func TestResidenceService_JoinWithCode_InvalidCode(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "user", "user@test.com", "Password123")
|
||||
|
||||
_, err := service.JoinWithCode("BADCODE", user.ID)
|
||||
testutil.AssertAppError(t, err, http.StatusNotFound, "error.share_code_invalid")
|
||||
}
|
||||
|
||||
// === RemoveUser ===
|
||||
|
||||
func TestResidenceService_RemoveUser_NotOwner(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
shared := testutil.CreateTestUser(t, db, "shared", "shared@test.com", "Password123")
|
||||
other := testutil.CreateTestUser(t, db, "other", "other@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House")
|
||||
residenceRepo.AddUser(residence.ID, shared.ID)
|
||||
|
||||
// shared user tries to remove other — should fail because shared is not owner
|
||||
err := service.RemoveUser(residence.ID, other.ID, shared.ID)
|
||||
testutil.AssertAppError(t, err, http.StatusForbidden, "error.not_residence_owner")
|
||||
}
|
||||
|
||||
// === GetResidenceUsers ===
|
||||
|
||||
func TestResidenceService_GetResidenceUsers_AccessDenied(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
other := testutil.CreateTestUser(t, db, "other", "other@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House")
|
||||
|
||||
_, err := service.GetResidenceUsers(residence.ID, other.ID)
|
||||
testutil.AssertAppError(t, err, http.StatusForbidden, "error.residence_access_denied")
|
||||
}
|
||||
|
||||
// === GetResidenceTypes ===
|
||||
|
||||
func TestResidenceService_GetResidenceTypes(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
testutil.SeedLookupData(t, db)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
resp, err := service.GetResidenceTypes()
|
||||
require.NoError(t, err)
|
||||
// SeedLookupData creates 4 residence types
|
||||
assert.Len(t, resp, 4)
|
||||
}
|
||||
|
||||
// === UpdateResidence with home profile fields ===
|
||||
|
||||
func TestResidenceService_UpdateResidence_HomeProfileFields(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
|
||||
hasPool := true
|
||||
hasGarage := true
|
||||
heatingType := "Forced Air"
|
||||
req := &requests.UpdateResidenceRequest{
|
||||
HasPool: &hasPool,
|
||||
HasGarage: &hasGarage,
|
||||
HeatingType: &heatingType,
|
||||
}
|
||||
|
||||
resp, err := service.UpdateResidence(residence.ID, user.ID, req)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, resp.Data.HasPool)
|
||||
assert.True(t, resp.Data.HasGarage)
|
||||
}
|
||||
|
||||
// === CreateResidence with home profile fields ===
|
||||
|
||||
func TestResidenceService_CreateResidence_HomeProfileFields(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
|
||||
hasPool := true
|
||||
hasSeptic := true
|
||||
req := &requests.CreateResidenceRequest{
|
||||
Name: "New House",
|
||||
StreetAddress: "456 Oak St",
|
||||
City: "Dallas",
|
||||
StateProvince: "TX",
|
||||
PostalCode: "75201",
|
||||
HasPool: &hasPool,
|
||||
HasSeptic: &hasSeptic,
|
||||
}
|
||||
|
||||
resp, err := service.CreateResidence(req, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, resp.Data.HasPool)
|
||||
assert.True(t, resp.Data.HasSeptic)
|
||||
}
|
||||
|
||||
// === Shared user GetResidence ===
|
||||
|
||||
func TestResidenceService_GetResidence_SharedUser(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
shared := testutil.CreateTestUser(t, db, "shared", "shared@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House")
|
||||
residenceRepo.AddUser(residence.ID, shared.ID)
|
||||
|
||||
resp, err := service.GetResidence(residence.ID, shared.ID, time.Now())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Test House", resp.Name)
|
||||
}
|
||||
|
||||
// === GetMyResidences with task repo (overdue counts + completion summaries) ===
|
||||
|
||||
func TestResidenceService_GetMyResidences_WithTaskRepo(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
taskRepo := repositories.NewTaskRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
service.SetTaskRepository(taskRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
testutil.CreateTestResidence(t, db, user.ID, "House 1")
|
||||
testutil.CreateTestResidence(t, db, user.ID, "House 2")
|
||||
|
||||
resp, err := service.GetMyResidences(user.ID, time.Now())
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, resp.Residences, 2)
|
||||
}
|
||||
|
||||
// === GetResidence with task repo (completion summary) ===
|
||||
|
||||
func TestResidenceService_GetResidence_WithTaskRepo(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
taskRepo := repositories.NewTaskRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
service.SetTaskRepository(taskRepo)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
|
||||
resp, err := service.GetResidence(residence.ID, user.ID, time.Now())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Test House", resp.Name)
|
||||
}
|
||||
|
||||
// === GenerateShareCode with negative expiry defaults to 24 ===
|
||||
|
||||
func TestResidenceService_GenerateShareCode_NegativeExpiry(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
|
||||
resp, err := service.GenerateShareCode(residence.ID, user.ID, -5)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, resp.ShareCode.Code)
|
||||
}
|
||||
|
||||
// === GenerateSharePackage with default expiry ===
|
||||
|
||||
func TestResidenceService_GenerateSharePackage_DefaultExpiry(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
|
||||
// Pass 0 hours — should default to 24
|
||||
resp, err := service.GenerateSharePackage(residence.ID, user.ID, 0)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, resp.ShareCode)
|
||||
assert.Equal(t, "Test House", resp.ResidenceName)
|
||||
}
|
||||
|
||||
// === RemoveUser — trying to remove the owner by a different owner ID ===
|
||||
|
||||
func TestResidenceService_RemoveUser_OwnerViaResidenceOwnerID(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
sharedUser := testutil.CreateTestUser(t, db, "shared", "shared@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House")
|
||||
residenceRepo.AddUser(residence.ID, sharedUser.ID)
|
||||
|
||||
// Try removing the owner (by residence.OwnerID) — even though requestingUserID != userIDToRemove
|
||||
// The second check (userIDToRemove == residence.OwnerID) should catch this
|
||||
err := service.RemoveUser(residence.ID, owner.ID, owner.ID)
|
||||
testutil.AssertAppError(t, err, http.StatusBadRequest, "error.cannot_remove_owner")
|
||||
}
|
||||
|
||||
// === GenerateTasksReport ===
|
||||
|
||||
func TestResidenceService_GenerateTasksReport(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
testutil.SeedLookupData(t, db)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
|
||||
// Create some tasks
|
||||
testutil.CreateTestTask(t, db, residence.ID, user.ID, "Task 1")
|
||||
testutil.CreateTestTask(t, db, residence.ID, user.ID, "Task 2")
|
||||
|
||||
report, err := service.GenerateTasksReport(residence.ID, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, residence.ID, report.ResidenceID)
|
||||
assert.Equal(t, "Test House", report.ResidenceName)
|
||||
assert.Equal(t, 2, report.TotalTasks)
|
||||
}
|
||||
|
||||
func TestResidenceService_GenerateTasksReport_AccessDenied(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
other := testutil.CreateTestUser(t, db, "other", "other@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House")
|
||||
|
||||
_, err := service.GenerateTasksReport(residence.ID, other.ID)
|
||||
testutil.AssertAppError(t, err, http.StatusForbidden, "error.residence_access_denied")
|
||||
}
|
||||
|
||||
func TestResidenceService_GenerateTasksReport_NotFound(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
|
||||
// Non-existent residence — user has no access
|
||||
_, err := service.GenerateTasksReport(9999, user.ID)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
// === GetShareCode with active code ===
|
||||
|
||||
func TestResidenceService_GetShareCode_WithActiveCode(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
|
||||
// Generate a share code first
|
||||
_, err := service.GenerateShareCode(residence.ID, user.ID, 24)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Now get the active code
|
||||
resp, err := service.GetShareCode(residence.ID, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
assert.NotEmpty(t, resp.Code)
|
||||
}
|
||||
|
||||
// === CreateResidence with all boolean fields ===
|
||||
|
||||
func TestResidenceService_CreateResidence_AllBooleanFields(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
|
||||
hasPool := true
|
||||
hasSprinkler := true
|
||||
hasSeptic := true
|
||||
hasFireplace := true
|
||||
hasGarage := true
|
||||
hasBasement := true
|
||||
hasAttic := true
|
||||
|
||||
req := &requests.CreateResidenceRequest{
|
||||
Name: "Full Feature House",
|
||||
StreetAddress: "789 Full St",
|
||||
City: "Austin",
|
||||
StateProvince: "TX",
|
||||
PostalCode: "78701",
|
||||
HasPool: &hasPool,
|
||||
HasSprinklerSystem: &hasSprinkler,
|
||||
HasSeptic: &hasSeptic,
|
||||
HasFireplace: &hasFireplace,
|
||||
HasGarage: &hasGarage,
|
||||
HasBasement: &hasBasement,
|
||||
HasAttic: &hasAttic,
|
||||
}
|
||||
|
||||
resp, err := service.CreateResidence(req, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, resp.Data.HasPool)
|
||||
assert.True(t, resp.Data.HasSprinklerSystem)
|
||||
assert.True(t, resp.Data.HasSeptic)
|
||||
assert.True(t, resp.Data.HasFireplace)
|
||||
assert.True(t, resp.Data.HasGarage)
|
||||
assert.True(t, resp.Data.HasBasement)
|
||||
assert.True(t, resp.Data.HasAttic)
|
||||
}
|
||||
|
||||
// === UpdateResidence with all optional fields ===
|
||||
|
||||
func TestResidenceService_UpdateResidence_AllOptionalFields(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Original Name")
|
||||
|
||||
newStreet := "456 New St"
|
||||
newApt := "Apt 2B"
|
||||
newState := "CA"
|
||||
newPostal := "90210"
|
||||
newCountry := "Canada"
|
||||
bedrooms := 4
|
||||
bathrooms := decimal.NewFromFloat(3.0)
|
||||
sqft := 3000
|
||||
lotSize := decimal.NewFromFloat(0.5)
|
||||
yearBuilt := 2020
|
||||
newDesc := "Nice house"
|
||||
isPrimary := false
|
||||
hasPool := true
|
||||
hasSprinkler := true
|
||||
hasSeptic := false
|
||||
hasFireplace := true
|
||||
hasGarage := true
|
||||
hasBasement := false
|
||||
hasAttic := true
|
||||
coolingType := "Central AC"
|
||||
waterHeaterType := "Tankless"
|
||||
roofType := "Shingle"
|
||||
exteriorType := "Brick"
|
||||
flooringPrimary := "Hardwood"
|
||||
landscapingType := "Xeriscape"
|
||||
|
||||
req := &requests.UpdateResidenceRequest{
|
||||
StreetAddress: &newStreet,
|
||||
ApartmentUnit: &newApt,
|
||||
StateProvince: &newState,
|
||||
PostalCode: &newPostal,
|
||||
Country: &newCountry,
|
||||
Bedrooms: &bedrooms,
|
||||
Bathrooms: &bathrooms,
|
||||
SquareFootage: &sqft,
|
||||
LotSize: &lotSize,
|
||||
YearBuilt: &yearBuilt,
|
||||
Description: &newDesc,
|
||||
IsPrimary: &isPrimary,
|
||||
HasPool: &hasPool,
|
||||
HasSprinklerSystem: &hasSprinkler,
|
||||
HasSeptic: &hasSeptic,
|
||||
HasFireplace: &hasFireplace,
|
||||
HasGarage: &hasGarage,
|
||||
HasBasement: &hasBasement,
|
||||
HasAttic: &hasAttic,
|
||||
CoolingType: &coolingType,
|
||||
WaterHeaterType: &waterHeaterType,
|
||||
RoofType: &roofType,
|
||||
ExteriorType: &exteriorType,
|
||||
FlooringPrimary: &flooringPrimary,
|
||||
LandscapingType: &landscapingType,
|
||||
}
|
||||
|
||||
resp, err := service.UpdateResidence(residence.ID, user.ID, req)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "456 New St", resp.Data.StreetAddress)
|
||||
assert.Equal(t, "CA", resp.Data.StateProvince)
|
||||
assert.True(t, resp.Data.HasPool)
|
||||
assert.True(t, resp.Data.HasFireplace)
|
||||
assert.True(t, resp.Data.HasAttic)
|
||||
}
|
||||
|
||||
// === ListResidences with no residences ===
|
||||
|
||||
func TestResidenceService_ListResidences_NoResidences(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
user := testutil.CreateTestUser(t, db, "loner", "loner@test.com", "Password123")
|
||||
|
||||
resp, err := service.ListResidences(user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, resp)
|
||||
}
|
||||
|
||||
// === getSummaryForUser returns empty summary ===
|
||||
|
||||
func TestResidenceService_getSummaryForUser_ReturnsEmpty(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
cfg := &config.Config{}
|
||||
service := NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
|
||||
summary := service.getSummaryForUser(999)
|
||||
assert.Equal(t, 0, summary.TotalResidences)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user