Files
query-orchestration/internal/client/delete_test.go
T
Jay Brown ad7b21f3a2 Merged in bugfix/delete-client-cascade (pull request #220)
fix cascading delete issue

* test passing
2026-04-08 10:54:32 +00:00

231 lines
6.6 KiB
Go

package client_test
import (
"errors"
"testing"
"queryorchestration/internal/client"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/harddelete"
"queryorchestration/internal/test"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// createDocWithEntryForClient creates a document with an S3 entry in the given folder for a client.
func createDocWithEntryForClient(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)
err = q.AddDocumentEntry(ctx, &repository.AddDocumentEntryParams{
Documentid: docID,
Bucket: "test-bucket",
Key: "clients/" + clientID + "/" + hash,
})
require.NoError(t, err)
return docID
}
func TestHardDeleteClient(t *testing.T) {
ctx := t.Context()
cfg := &TestConfig{}
test.CreateDB(t, cfg)
svc := client.New(cfg)
q := cfg.GetDBQueries()
t.Run("deletes client and all associated data", func(t *testing.T) {
clientID := "test-client-hard-delete"
test.CreateTestClient(t, cfg, clientID, "Test Client Hard Delete")
// Get root folder
rootFolder, err := q.GetFolderByPath(ctx, &repository.GetFolderByPathParams{
Clientid: clientID,
Path: "/",
})
require.NoError(t, err)
// Create documents with S3 entries
doc1ID := createDocWithEntryForClient(t, cfg, clientID, &rootFolder.ID, "client-del-doc1")
doc2ID := createDocWithEntryForClient(t, cfg, clientID, &rootFolder.ID, "client-del-doc2")
// Create collector data
versionID, err := q.AddLatestCollectorVersion(ctx, clientID)
require.NoError(t, err)
err = q.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{
Clientid: clientID,
Versionid: versionID,
})
require.NoError(t, err)
err = q.SetCollectorCleanVersion(ctx, &repository.SetCollectorCleanVersionParams{
Clientid: clientID,
Addedversion: versionID,
Versionid: 1,
})
require.NoError(t, err)
// Create clientCanSync
err = q.AddClientCanSync(ctx, &repository.AddClientCanSyncParams{
Cansync: true,
Clientid: clientID,
})
require.NoError(t, err)
// Delete the client
s3Paths, err := svc.HardDelete(ctx, clientID)
require.NoError(t, err)
// Verify S3 paths returned for both documents
assert.Len(t, s3Paths, 2)
// Verify documents are gone
_, err = q.GetDocumentSummary(ctx, doc1ID)
require.Error(t, err)
_, err = q.GetDocumentSummary(ctx, doc2ID)
require.Error(t, err)
// Verify client is gone
_, err = q.GetClient(ctx, clientID)
require.Error(t, err)
})
t.Run("deletes client with batch outcomes", func(t *testing.T) {
clientID := "test-client-batch-del"
test.CreateTestClient(t, cfg, clientID, "Test Client Batch Del")
// Get root folder
rootFolder, err := q.GetFolderByPath(ctx, &repository.GetFolderByPathParams{
Clientid: clientID,
Path: "/",
})
require.NoError(t, err)
// Create batch upload for client
batchID, err := q.CreateBatchUpload(ctx, &repository.CreateBatchUploadParams{
ClientID: clientID,
OriginalFilename: "test.zip",
TotalDocuments: 1,
})
require.NoError(t, err)
// Create a document linked to the batch
filename := "resolved.pdf"
docID := createDocWithEntryForClient(t, cfg, clientID, &rootFolder.ID, "batch-client-doc")
// Update the document to have the batch_id by creating via params
// (the helper doesn't set batch_id, so create a second doc with batch_id)
docID2, err := q.CreateDocument(ctx, &repository.CreateDocumentParams{
Clientid: clientID,
Hash: "batch-client-doc2",
Filename: &filename,
Folderid: &rootFolder.ID,
BatchID: &batchID,
})
require.NoError(t, err)
_ = docID
// Insert resolved outcome (with document_id set)
err = q.InsertBatchDocumentOutcome(ctx, &repository.InsertBatchDocumentOutcomeParams{
BatchID: batchID,
Filename: "resolved.pdf",
Column3: repository.BatchOutcomeStatusInitComplete,
DocumentID: &docID2,
})
require.NoError(t, err)
// Insert unresolved outcome (document_id NULL)
err = q.InsertBatchDocumentOutcome(ctx, &repository.InsertBatchDocumentOutcomeParams{
BatchID: batchID,
Filename: "unresolved.pdf",
Column3: repository.BatchOutcomeStatusSubmitted,
})
require.NoError(t, err)
// Hard delete the client -- should fail before FK fix
_, err = svc.HardDelete(ctx, clientID)
require.NoError(t, err)
// Verify client is gone
_, err = q.GetClient(ctx, clientID)
require.Error(t, err)
// Verify batch_document_outcomes are gone (cascade from batch_uploads deletion)
rows, err := q.ListBatchDocumentOutcomes(ctx, batchID)
require.NoError(t, err)
assert.Empty(t, rows)
})
t.Run("returns NotFoundError for non-existent client", func(t *testing.T) {
_, err := svc.HardDelete(ctx, "non-existent-client")
require.Error(t, err)
var notFoundErr *harddelete.NotFoundError
assert.True(t, errors.As(err, &notFoundErr))
})
t.Run("deletes client with no documents", func(t *testing.T) {
clientID := "test-client-no-docs-del"
test.CreateTestClient(t, cfg, clientID, "Test Client No Docs Del")
s3Paths, err := svc.HardDelete(ctx, clientID)
require.NoError(t, err)
assert.Empty(t, s3Paths)
// Verify client and root folder are gone
_, err = q.GetClient(ctx, clientID)
require.Error(t, err)
})
t.Run("deletes client with nested folder structure", func(t *testing.T) {
clientID := "test-client-nested-del"
test.CreateTestClient(t, cfg, clientID, "Test Client Nested Del")
rootFolder, err := q.GetFolderByPath(ctx, &repository.GetFolderByPathParams{
Clientid: clientID,
Path: "/",
})
require.NoError(t, err)
// Create subfolder
subFolder, err := q.CreateFolder(ctx, &repository.CreateFolderParams{
Path: "/contracts",
Parentid: &rootFolder.ID,
Clientid: clientID,
Createdby: "testuser",
})
require.NoError(t, err)
// Create document in subfolder
docID := createDocWithEntryForClient(t, cfg, clientID, &subFolder.ID, "nested-del-doc")
s3Paths, err := svc.HardDelete(ctx, clientID)
require.NoError(t, err)
assert.Len(t, s3Paths, 1)
// Verify all gone
_, err = q.GetDocumentSummary(ctx, docID)
require.Error(t, err)
_, err = q.GetFolderByID(ctx, subFolder.ID)
require.Error(t, err)
_, err = q.GetFolderByID(ctx, rootFolder.ID)
require.Error(t, err)
_, err = q.GetClient(ctx, clientID)
require.Error(t, err)
})
}