package services import ( "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/treytartt/honeydue-api/internal/dto/requests" "github.com/treytartt/honeydue-api/internal/models" "github.com/treytartt/honeydue-api/internal/repositories" "github.com/treytartt/honeydue-api/internal/testutil" ) func setupDocumentService(t *testing.T) (*DocumentService, *repositories.DocumentRepository, *repositories.ResidenceRepository) { db := testutil.SetupTestDB(t) testutil.SeedLookupData(t, db) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) return service, documentRepo, residenceRepo } // === CreateDocument === func TestDocumentService_CreateDocument(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") req := &requests.CreateDocumentRequest{ ResidenceID: residence.ID, Title: "Furnace Manual", Description: "Installation manual for the furnace", DocumentType: models.DocumentTypeManual, FileURL: "https://example.com/manual.pdf", FileName: "manual.pdf", } resp, err := service.CreateDocument(req, user.ID) require.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, "Furnace Manual", resp.Title) assert.Equal(t, models.DocumentTypeManual, resp.DocumentType) } func TestDocumentService_CreateDocument_DefaultType(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") req := &requests.CreateDocumentRequest{ ResidenceID: residence.ID, Title: "Some Document", // DocumentType not set — should default to "general" } resp, err := service.CreateDocument(req, user.ID) require.NoError(t, err) assert.Equal(t, models.DocumentTypeGeneral, resp.DocumentType) } func TestDocumentService_CreateDocument_WithImages(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") req := &requests.CreateDocumentRequest{ ResidenceID: residence.ID, Title: "Receipt with photos", ImageURLs: []string{"https://example.com/img1.jpg", "https://example.com/img2.jpg"}, } resp, err := service.CreateDocument(req, user.ID) require.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, "Receipt with photos", resp.Title) } func TestDocumentService_CreateDocument_AccessDenied(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) 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") req := &requests.CreateDocumentRequest{ ResidenceID: residence.ID, Title: "Unauthorized Doc", } _, err := service.CreateDocument(req, other.ID) testutil.AssertAppError(t, err, http.StatusForbidden, "error.residence_access_denied") } // === GetDocument === func TestDocumentService_GetDocument(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Test Doc") resp, err := service.GetDocument(doc.ID, user.ID) require.NoError(t, err) assert.Equal(t, doc.ID, resp.ID) assert.Equal(t, "Test Doc", resp.Title) } func TestDocumentService_GetDocument_NotFound(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") _, err := service.GetDocument(9999, user.ID) testutil.AssertAppError(t, err, http.StatusNotFound, "error.document_not_found") } func TestDocumentService_GetDocument_AccessDenied(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) 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") doc := testutil.CreateTestDocument(t, db, residence.ID, owner.ID, "Private Doc") _, err := service.GetDocument(doc.ID, other.ID) testutil.AssertAppError(t, err, http.StatusForbidden, "error.document_access_denied") } // === UpdateDocument === func TestDocumentService_UpdateDocument(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Original Title") newTitle := "Updated Title" newDesc := "Updated description" req := &requests.UpdateDocumentRequest{ Title: &newTitle, Description: &newDesc, } resp, err := service.UpdateDocument(doc.ID, user.ID, req) require.NoError(t, err) assert.Equal(t, "Updated Title", resp.Title) assert.Equal(t, "Updated description", resp.Description) } func TestDocumentService_UpdateDocument_NotFound(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") newTitle := "Won't Work" req := &requests.UpdateDocumentRequest{Title: &newTitle} _, err := service.UpdateDocument(9999, user.ID, req) testutil.AssertAppError(t, err, http.StatusNotFound, "error.document_not_found") } func TestDocumentService_UpdateDocument_AccessDenied(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) 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") doc := testutil.CreateTestDocument(t, db, residence.ID, owner.ID, "Private Doc") newTitle := "Hacked" req := &requests.UpdateDocumentRequest{Title: &newTitle} _, err := service.UpdateDocument(doc.ID, other.ID, req) testutil.AssertAppError(t, err, http.StatusForbidden, "error.document_access_denied") } func TestDocumentService_UpdateDocument_ChangeType(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "My Receipt") newType := models.DocumentTypeWarranty req := &requests.UpdateDocumentRequest{DocumentType: &newType} resp, err := service.UpdateDocument(doc.ID, user.ID, req) require.NoError(t, err) assert.Equal(t, models.DocumentTypeWarranty, resp.DocumentType) } // === DeleteDocument === func TestDocumentService_DeleteDocument(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "To Delete") err := service.DeleteDocument(doc.ID, user.ID) require.NoError(t, err) // Should not be found after deletion _, err = service.GetDocument(doc.ID, user.ID) assert.Error(t, err) } func TestDocumentService_DeleteDocument_NotFound(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") err := service.DeleteDocument(9999, user.ID) testutil.AssertAppError(t, err, http.StatusNotFound, "error.document_not_found") } func TestDocumentService_DeleteDocument_AccessDenied(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) 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") doc := testutil.CreateTestDocument(t, db, residence.ID, owner.ID, "Private Doc") err := service.DeleteDocument(doc.ID, other.ID) testutil.AssertAppError(t, err, http.StatusForbidden, "error.document_access_denied") } // === ListDocuments === func TestDocumentService_ListDocuments(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc 1") testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc 2") resp, err := service.ListDocuments(user.ID, nil) require.NoError(t, err) assert.Len(t, resp, 2) } func TestDocumentService_ListDocuments_NoResidences(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "loner", "loner@test.com", "Password123") resp, err := service.ListDocuments(user.ID, nil) require.NoError(t, err) assert.Empty(t, resp) } func TestDocumentService_ListDocuments_FilterByResidence(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence1 := testutil.CreateTestResidence(t, db, user.ID, "House 1") residence2 := testutil.CreateTestResidence(t, db, user.ID, "House 2") testutil.CreateTestDocument(t, db, residence1.ID, user.ID, "Doc A") testutil.CreateTestDocument(t, db, residence2.ID, user.ID, "Doc B") filter := &repositories.DocumentFilter{ResidenceID: &residence1.ID} resp, err := service.ListDocuments(user.ID, filter) require.NoError(t, err) assert.Len(t, resp, 1) assert.Equal(t, "Doc A", resp[0].Title) } func TestDocumentService_ListDocuments_FilterByResidence_AccessDenied(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) 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, "Owner House") // other has their own residence so they have at least one testutil.CreateTestResidence(t, db, other.ID, "Other House") filter := &repositories.DocumentFilter{ResidenceID: &residence.ID} _, err := service.ListDocuments(other.ID, filter) testutil.AssertAppError(t, err, http.StatusForbidden, "error.residence_access_denied") } // === ListWarranties === func TestDocumentService_ListWarranties(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") // Create a warranty doc directly warrantyDoc := &models.Document{ ResidenceID: residence.ID, CreatedByID: user.ID, Title: "HVAC Warranty", DocumentType: "warranty", FileURL: "https://example.com/warranty.pdf", } err := db.Create(warrantyDoc).Error require.NoError(t, err) // Create a general doc testutil.CreateTestDocument(t, db, residence.ID, user.ID, "General Doc") resp, err := service.ListWarranties(user.ID) require.NoError(t, err) assert.Len(t, resp, 1) assert.Equal(t, "HVAC Warranty", resp[0].Title) } func TestDocumentService_ListWarranties_NoResidences(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "loner", "loner@test.com", "Password123") resp, err := service.ListWarranties(user.ID) require.NoError(t, err) assert.Empty(t, resp) } // === DeactivateDocument === func TestDocumentService_DeactivateDocument(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "To Deactivate") resp, err := service.DeactivateDocument(doc.ID, user.ID) require.NoError(t, err) assert.False(t, resp.IsActive) } func TestDocumentService_DeactivateDocument_NotFound(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") _, err := service.DeactivateDocument(9999, user.ID) testutil.AssertAppError(t, err, http.StatusNotFound, "error.document_not_found") } func TestDocumentService_DeactivateDocument_AccessDenied(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) 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") doc := testutil.CreateTestDocument(t, db, residence.ID, owner.ID, "Private Doc") _, err := service.DeactivateDocument(doc.ID, other.ID) testutil.AssertAppError(t, err, http.StatusForbidden, "error.document_access_denied") } // === UploadDocumentImage === func TestDocumentService_UploadDocumentImage(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Test Doc") resp, err := service.UploadDocumentImage(doc.ID, user.ID, "https://example.com/photo.jpg", "Front view") require.NoError(t, err) assert.NotNil(t, resp) } func TestDocumentService_UploadDocumentImage_NotFound(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") _, err := service.UploadDocumentImage(9999, user.ID, "https://example.com/photo.jpg", "") testutil.AssertAppError(t, err, http.StatusNotFound, "error.document_not_found") } func TestDocumentService_UploadDocumentImage_AccessDenied(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) 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") doc := testutil.CreateTestDocument(t, db, residence.ID, owner.ID, "Private Doc") _, err := service.UploadDocumentImage(doc.ID, other.ID, "https://example.com/photo.jpg", "") testutil.AssertAppError(t, err, http.StatusForbidden, "error.document_access_denied") } // === DeleteDocumentImage === func TestDocumentService_DeleteDocumentImage(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Test Doc") // Create an image img := &models.DocumentImage{ DocumentID: doc.ID, ImageURL: "https://example.com/photo.jpg", } err := db.Create(img).Error require.NoError(t, err) resp, err := service.DeleteDocumentImage(doc.ID, img.ID, user.ID) require.NoError(t, err) assert.NotNil(t, resp) } func TestDocumentService_DeleteDocumentImage_NotFound(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Test Doc") _, err := service.DeleteDocumentImage(doc.ID, 9999, user.ID) testutil.AssertAppError(t, err, http.StatusNotFound, "error.document_image_not_found") } func TestDocumentService_DeleteDocumentImage_WrongDocument(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc1 := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc 1") doc2 := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc 2") // Create an image on doc1 img := &models.DocumentImage{ DocumentID: doc1.ID, ImageURL: "https://example.com/photo.jpg", } err := db.Create(img).Error require.NoError(t, err) // Try to delete the image specifying doc2 _, err = service.DeleteDocumentImage(doc2.ID, img.ID, user.ID) testutil.AssertAppError(t, err, http.StatusNotFound, "error.document_image_not_found") } func TestDocumentService_DeleteDocumentImage_AccessDenied(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) 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") doc := testutil.CreateTestDocument(t, db, residence.ID, owner.ID, "Private Doc") img := &models.DocumentImage{ DocumentID: doc.ID, ImageURL: "https://example.com/photo.jpg", } err := db.Create(img).Error require.NoError(t, err) _, err = service.DeleteDocumentImage(doc.ID, img.ID, other.ID) testutil.AssertAppError(t, err, http.StatusForbidden, "error.document_access_denied") } // === SharedUser access === func TestDocumentService_GetDocument_SharedUserHasAccess(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) 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) doc := testutil.CreateTestDocument(t, db, residence.ID, owner.ID, "Shared Doc") resp, err := service.GetDocument(doc.ID, shared.ID) require.NoError(t, err) assert.Equal(t, "Shared Doc", resp.Title) } // === ActivateDocument === func TestDocumentService_ActivateDocument(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "To Activate") // Deactivate first _, err := service.DeactivateDocument(doc.ID, user.ID) require.NoError(t, err) // Now activate resp, err := service.ActivateDocument(doc.ID, user.ID) require.NoError(t, err) assert.True(t, resp.IsActive) } func TestDocumentService_ActivateDocument_NotFound(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") _, err := service.ActivateDocument(9999, user.ID) testutil.AssertAppError(t, err, http.StatusNotFound, "error.document_not_found") } func TestDocumentService_ActivateDocument_AccessDenied(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) 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") doc := testutil.CreateTestDocument(t, db, residence.ID, owner.ID, "Private Doc") _, err := service.ActivateDocument(doc.ID, other.ID) testutil.AssertAppError(t, err, http.StatusForbidden, "error.document_access_denied") } // === CreateDocument — with empty image URL in array (should skip) === func TestDocumentService_CreateDocument_WithEmptyImageURL(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") req := &requests.CreateDocumentRequest{ ResidenceID: residence.ID, Title: "Doc with empty images", ImageURLs: []string{"", "https://example.com/img.jpg", ""}, } resp, err := service.CreateDocument(req, user.ID) require.NoError(t, err) assert.NotNil(t, resp) } // === UpdateDocument — all optional fields === func TestDocumentService_UpdateDocument_AllFields(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Original") newTitle := "Updated" newDesc := "New description" newType := models.DocumentTypeWarranty newFileURL := "https://example.com/new.pdf" newFileName := "new.pdf" newMimeType := "application/pdf" newVendor := "HVAC Corp" newSerial := "SN12345" newModel := "Model X" size := int64(1024) req := &requests.UpdateDocumentRequest{ Title: &newTitle, Description: &newDesc, DocumentType: &newType, FileURL: &newFileURL, FileName: &newFileName, FileSize: &size, MimeType: &newMimeType, Vendor: &newVendor, SerialNumber: &newSerial, ModelNumber: &newModel, } resp, err := service.UpdateDocument(doc.ID, user.ID, req) require.NoError(t, err) assert.Equal(t, "Updated", resp.Title) assert.Equal(t, "New description", resp.Description) assert.Equal(t, models.DocumentTypeWarranty, resp.DocumentType) } // === ListDocuments — filter by document type === func TestDocumentService_ListDocuments_FilterByType(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") // Create a warranty doc warrantyDoc := &models.Document{ ResidenceID: residence.ID, CreatedByID: user.ID, Title: "Warranty Doc", DocumentType: models.DocumentTypeWarranty, FileURL: "https://example.com/w.pdf", } err := db.Create(warrantyDoc).Error require.NoError(t, err) // Create a general doc testutil.CreateTestDocument(t, db, residence.ID, user.ID, "General Doc") filter := &repositories.DocumentFilter{DocumentType: string(models.DocumentTypeWarranty)} resp, err := service.ListDocuments(user.ID, filter) require.NoError(t, err) assert.Len(t, resp, 1) assert.Equal(t, "Warranty Doc", resp[0].Title) } // === Shared user can update/delete documents === func TestDocumentService_SharedUser_CanUpdate(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) 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) doc := testutil.CreateTestDocument(t, db, residence.ID, owner.ID, "Shared Doc") newTitle := "Updated by shared user" req := &requests.UpdateDocumentRequest{Title: &newTitle} resp, err := service.UpdateDocument(doc.ID, shared.ID, req) require.NoError(t, err) assert.Equal(t, "Updated by shared user", resp.Title) } func TestDocumentService_SharedUser_CanDelete(t *testing.T) { db := testutil.SetupTestDB(t) documentRepo := repositories.NewDocumentRepository(db) residenceRepo := repositories.NewResidenceRepository(db) service := NewDocumentService(documentRepo, residenceRepo) 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) doc := testutil.CreateTestDocument(t, db, residence.ID, owner.ID, "Shared Doc") err := service.DeleteDocument(doc.ID, shared.ID) require.NoError(t, err) }