package document_test import ( "errors" "testing" "queryorchestration/internal/database/repository" "queryorchestration/internal/document" "queryorchestration/internal/fieldextraction" "queryorchestration/internal/harddelete" "queryorchestration/internal/test" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // createTestDocumentWithDeps creates a document with entries, cleans, and field extractions. // Returns the document ID for use in delete tests. func createTestDocumentWithDeps(t *testing.T, cfg *TestConfig, clientID string, folderID *uuid.UUID, hash string) uuid.UUID { t.Helper() ctx := t.Context() q := cfg.GetDBQueries() filename := hash + ".pdf" docID, err := q.CreateDocument(ctx, &repository.CreateDocumentParams{ Clientid: clientID, Hash: hash, Filename: &filename, Folderid: folderID, }) require.NoError(t, err) // Add a document entry (S3 reference) err = q.AddDocumentEntry(ctx, &repository.AddDocumentEntryParams{ Documentid: docID, Bucket: "test-bucket", Key: "test-key/" + hash, }) require.NoError(t, err) // Add a document clean (must satisfy location_xor_fail constraint) cleanBucket := "clean-bucket" cleanKey := "clean-key/" + hash cleanHash := "cleanhash-" + hash cleanID, err := q.AddDocumentClean(ctx, &repository.AddDocumentCleanParams{ Documentid: docID, Bucket: &cleanBucket, Key: &cleanKey, Hash: &cleanHash, Mimetype: repository.NullCleanmimetype{ Cleanmimetype: repository.CleanmimetypeApplicationPdf, Valid: true, }, }) require.NoError(t, err) // Add a clean entry err = q.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ Cleanid: cleanID, Version: 1, }) require.NoError(t, err) // Add field extraction fieldSvc := fieldextraction.New(cfg) contractTitle := "Test Contract " + hash input := &fieldextraction.CreateFieldExtractionInput{ DocumentID: docID, SingleFields: &repository.AddFieldExtractionParams{ Documentid: docID, Filename: &filename, Contracttitle: &contractTitle, Createdby: "testuser", }, ArrayFields: []*repository.AddFieldExtractionArrayFieldParams{}, } _, err = fieldSvc.CreateFieldExtraction(ctx, input) require.NoError(t, err) return docID } func TestHardDeleteDocument(t *testing.T) { ctx := t.Context() cfg := &TestConfig{} test.CreateDB(t, cfg) clientID := "test-doc-delete" test.CreateTestClient(t, cfg, clientID, "Test Doc Delete") svc := document.New(cfg) t.Run("deletes document and all dependent rows", func(t *testing.T) { q := cfg.GetDBQueries() rootFolder, err := q.GetFolderByPath(ctx, &repository.GetFolderByPathParams{ Clientid: clientID, Path: "/", }) require.NoError(t, err) docID := createTestDocumentWithDeps(t, cfg, clientID, &rootFolder.ID, "delete-cascade-test") // Verify document and deps exist before delete _, err = q.GetDocumentSummary(ctx, docID) require.NoError(t, err) s3Rows, err := q.CollectDocumentS3Paths(ctx, docID) require.NoError(t, err) assert.Len(t, s3Rows, 1) // Delete the document s3Paths, err := svc.HardDelete(ctx, docID) require.NoError(t, err) // Verify S3 paths returned assert.Len(t, s3Paths, 1) assert.Equal(t, "test-bucket", s3Paths[0].Bucket) assert.Equal(t, "test-key/delete-cascade-test", s3Paths[0].Key) assert.Equal(t, docID, s3Paths[0].DocumentID) // Verify document is gone _, err = q.GetDocumentSummary(ctx, docID) require.Error(t, err) // Verify document entries are gone s3Rows, err = q.CollectDocumentS3Paths(ctx, docID) require.NoError(t, err) assert.Empty(t, s3Rows) // Verify field extractions are gone extractions, err := q.GetFieldExtractionsByDocumentID(ctx, docID) require.NoError(t, err) assert.Empty(t, extractions) }) t.Run("returns NotFoundError for non-existent document", func(t *testing.T) { fakeID := uuid.New() _, err := svc.HardDelete(ctx, fakeID) require.Error(t, err) var notFoundErr *harddelete.NotFoundError assert.True(t, errors.As(err, ¬FoundErr)) }) t.Run("returns empty S3 paths when document has no entries", func(t *testing.T) { q := cfg.GetDBQueries() // Create a document with no entries docID, err := q.CreateDocument(ctx, &repository.CreateDocumentParams{ Clientid: clientID, Hash: "no-entries-test", }) require.NoError(t, err) s3Paths, err := svc.HardDelete(ctx, docID) require.NoError(t, err) assert.Empty(t, s3Paths) }) }