package repositories import ( "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/treytartt/honeydue-api/internal/models" "github.com/treytartt/honeydue-api/internal/testutil" ) func TestResidenceRepository_Create(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := &models.Residence{ OwnerID: user.ID, Name: "Test House", StreetAddress: "123 Main St", City: "Austin", StateProvince: "TX", PostalCode: "78701", Country: "USA", IsActive: true, IsPrimary: true, } err := repo.Create(residence) require.NoError(t, err) assert.NotZero(t, residence.ID) } func TestResidenceRepository_FindByID(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") found, err := repo.FindByID(residence.ID) require.NoError(t, err) assert.Equal(t, residence.ID, found.ID) assert.Equal(t, "Test House", found.Name) assert.Equal(t, user.ID, found.OwnerID) } func TestResidenceRepository_FindByID_NotFound(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) _, err := repo.FindByID(9999) assert.Error(t, err) } func TestResidenceRepository_FindByID_InactiveNotFound(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") // Deactivate db.Model(residence).Update("is_active", false) _, err := repo.FindByID(residence.ID) assert.Error(t, err) // Should not find inactive residences } func TestResidenceRepository_FindByUser(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") sharedUser := testutil.CreateTestUser(t, db, "shared", "shared@test.com", "password") // Create residences r1 := testutil.CreateTestResidence(t, db, owner.ID, "House 1") r2 := testutil.CreateTestResidence(t, db, owner.ID, "House 2") // Share r1 with sharedUser repo.AddUser(r1.ID, sharedUser.ID) // Owner should see both ownerResidences, err := repo.FindByUser(owner.ID) require.NoError(t, err) assert.Len(t, ownerResidences, 2) // Shared user should see only r1 sharedResidences, err := repo.FindByUser(sharedUser.ID) require.NoError(t, err) assert.Len(t, sharedResidences, 1) assert.Equal(t, r1.ID, sharedResidences[0].ID) // Another user should see nothing otherUser := testutil.CreateTestUser(t, db, "other", "other@test.com", "password") otherResidences, err := repo.FindByUser(otherUser.ID) require.NoError(t, err) assert.Len(t, otherResidences, 0) _ = r2 // suppress unused } func TestResidenceRepository_FindOwnedByUser(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") otherOwner := testutil.CreateTestUser(t, db, "other", "other@test.com", "password") testutil.CreateTestResidence(t, db, owner.ID, "House 1") testutil.CreateTestResidence(t, db, owner.ID, "House 2") testutil.CreateTestResidence(t, db, otherOwner.ID, "Other House") residences, err := repo.FindOwnedByUser(owner.ID) require.NoError(t, err) assert.Len(t, residences, 2) } func TestResidenceRepository_Update(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") residence.Name = "Updated House" residence.City = "Dallas" err := repo.Update(residence) require.NoError(t, err) found, err := repo.FindByID(residence.ID) require.NoError(t, err) assert.Equal(t, "Updated House", found.Name) assert.Equal(t, "Dallas", found.City) } func TestResidenceRepository_Delete(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") err := repo.Delete(residence.ID) require.NoError(t, err) // Should not be found (soft delete sets is_active = false) _, err = repo.FindByID(residence.ID) assert.Error(t, err) } func TestResidenceRepository_HasAccess(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") sharedUser := testutil.CreateTestUser(t, db, "shared", "shared@test.com", "password") otherUser := testutil.CreateTestUser(t, db, "other", "other@test.com", "password") residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House") repo.AddUser(residence.ID, sharedUser.ID) tests := []struct { name string userID uint expected bool }{ {"owner has access", owner.ID, true}, {"shared user has access", sharedUser.ID, true}, {"other user no access", otherUser.ID, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { hasAccess, err := repo.HasAccess(residence.ID, tt.userID) require.NoError(t, err) assert.Equal(t, tt.expected, hasAccess) }) } } func TestResidenceRepository_IsOwner(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") sharedUser := testutil.CreateTestUser(t, db, "shared", "shared@test.com", "password") residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House") repo.AddUser(residence.ID, sharedUser.ID) // Owner should be owner isOwner, err := repo.IsOwner(residence.ID, owner.ID) require.NoError(t, err) assert.True(t, isOwner) // Shared user should not be owner isOwner, err = repo.IsOwner(residence.ID, sharedUser.ID) require.NoError(t, err) assert.False(t, isOwner) } func TestResidenceRepository_AddAndRemoveUser(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") sharedUser := testutil.CreateTestUser(t, db, "shared", "shared@test.com", "password") residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House") // Initially no access hasAccess, _ := repo.HasAccess(residence.ID, sharedUser.ID) assert.False(t, hasAccess) // Add user err := repo.AddUser(residence.ID, sharedUser.ID) require.NoError(t, err) hasAccess, _ = repo.HasAccess(residence.ID, sharedUser.ID) assert.True(t, hasAccess) // Remove user err = repo.RemoveUser(residence.ID, sharedUser.ID) require.NoError(t, err) hasAccess, _ = repo.HasAccess(residence.ID, sharedUser.ID) assert.False(t, hasAccess) } func TestResidenceRepository_GetResidenceUsers(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") user1 := testutil.CreateTestUser(t, db, "user1", "user1@test.com", "password") user2 := testutil.CreateTestUser(t, db, "user2", "user2@test.com", "password") residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House") repo.AddUser(residence.ID, user1.ID) repo.AddUser(residence.ID, user2.ID) users, err := repo.GetResidenceUsers(residence.ID) require.NoError(t, err) assert.Len(t, users, 3) // owner + 2 shared users } func TestResidenceRepository_CountByOwner(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") testutil.CreateTestResidence(t, db, owner.ID, "House 1") testutil.CreateTestResidence(t, db, owner.ID, "House 2") testutil.CreateTestResidence(t, db, owner.ID, "House 3") count, err := repo.CountByOwner(owner.ID) require.NoError(t, err) assert.Equal(t, int64(3), count) } func TestResidenceRepository_CreateShareCode(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House") shareCode, err := repo.CreateShareCode(residence.ID, owner.ID, 24*time.Hour) require.NoError(t, err) assert.NotEmpty(t, shareCode.Code) assert.Len(t, shareCode.Code, 6) assert.True(t, shareCode.IsActive) assert.NotNil(t, shareCode.ExpiresAt) } func TestResidenceRepository_FindShareCodeByCode(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House") created, err := repo.CreateShareCode(residence.ID, owner.ID, 24*time.Hour) require.NoError(t, err) found, err := repo.FindShareCodeByCode(created.Code) require.NoError(t, err) assert.Equal(t, created.ID, found.ID) assert.Equal(t, residence.ID, found.ResidenceID) } func TestResidenceRepository_FindShareCodeByCode_Expired(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) owner := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password") residence := testutil.CreateTestResidence(t, db, owner.ID, "Test House") // Create expired code created, err := repo.CreateShareCode(residence.ID, owner.ID, -1*time.Hour) // Already expired require.NoError(t, err) _, err = repo.FindShareCodeByCode(created.Code) assert.Error(t, err) // Should fail for expired code } func TestResidenceRepository_GetAllResidenceTypes(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewResidenceRepository(db) // Create residence types types := []models.ResidenceType{ {Name: "House"}, {Name: "Apartment"}, {Name: "Condo"}, } for _, rt := range types { db.Create(&rt) } result, err := repo.GetAllResidenceTypes() require.NoError(t, err) assert.Len(t, result, 3) }