ad7b21f3a2
fix cascading delete issue * test passing
220 lines
6.2 KiB
Go
220 lines
6.2 KiB
Go
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("deletes document that has batch outcome rows", func(t *testing.T) {
|
|
q := cfg.GetDBQueries()
|
|
|
|
// Use a unique client to avoid collisions with other subtests
|
|
batchClientID := "test-doc-batch-del"
|
|
test.CreateTestClient(t, cfg, batchClientID, "Test Doc Batch Del")
|
|
|
|
rootFolder, err := q.GetFolderByPath(ctx, &repository.GetFolderByPathParams{
|
|
Clientid: batchClientID,
|
|
Path: "/",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Create a batch upload for the client
|
|
batchID, err := q.CreateBatchUpload(ctx, &repository.CreateBatchUploadParams{
|
|
ClientID: batchClientID,
|
|
OriginalFilename: "test.zip",
|
|
TotalDocuments: 1,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Create a document linked to the batch
|
|
filename := "test.pdf"
|
|
docID, err := q.CreateDocument(ctx, &repository.CreateDocumentParams{
|
|
Clientid: batchClientID,
|
|
Hash: "batch-doc-del-test",
|
|
Filename: &filename,
|
|
Folderid: &rootFolder.ID,
|
|
BatchID: &batchID,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Insert a submitted outcome referencing this document
|
|
err = q.InsertBatchDocumentOutcome(ctx, &repository.InsertBatchDocumentOutcomeParams{
|
|
BatchID: batchID,
|
|
Filename: "test.pdf",
|
|
Column3: repository.BatchOutcomeStatusSubmitted,
|
|
DocumentID: &docID,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Hard delete the document -- should fail before FK fix
|
|
s3Paths, err := svc.HardDelete(ctx, docID)
|
|
require.NoError(t, err)
|
|
|
|
// Verify document is gone
|
|
_ = s3Paths
|
|
_, err = q.GetDocumentSummary(ctx, docID)
|
|
require.Error(t, err)
|
|
|
|
// Verify the batch outcome row still exists but document_id is NULL
|
|
// (history preserved via SET NULL on FK)
|
|
rows, err := q.ListBatchDocumentOutcomes(ctx, batchID)
|
|
require.NoError(t, err)
|
|
require.Len(t, rows, 1)
|
|
assert.Nil(t, rows[0].DocumentID)
|
|
})
|
|
|
|
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)
|
|
})
|
|
}
|