8c218f162b
enrich doc responses * enrich doc responses
531 lines
15 KiB
Go
531 lines
15 KiB
Go
package folder_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"queryorchestration/internal/database/repository"
|
|
"queryorchestration/internal/fieldextraction"
|
|
"queryorchestration/internal/folder"
|
|
"queryorchestration/internal/serviceconfig"
|
|
"queryorchestration/internal/test"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type TestConfig struct {
|
|
serviceconfig.BaseConfig
|
|
}
|
|
|
|
func TestCreateFolder(t *testing.T) {
|
|
ctx := t.Context()
|
|
cfg := &TestConfig{}
|
|
test.CreateDB(t, cfg)
|
|
svc := folder.New(cfg)
|
|
|
|
// Create test client first
|
|
clientID := "test-client-folders"
|
|
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
|
Clientid: clientID,
|
|
Name: "Test Client Folders",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
t.Run("create root folder successfully", func(t *testing.T) {
|
|
path := "/documents"
|
|
createdBy := "user123"
|
|
|
|
result, err := svc.CreateFolder(ctx, path, nil, clientID, createdBy)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, result)
|
|
assert.Equal(t, path, result.Path)
|
|
assert.Nil(t, result.Parentid)
|
|
assert.Equal(t, clientID, result.Clientid)
|
|
assert.Equal(t, createdBy, result.Createdby)
|
|
})
|
|
|
|
t.Run("create subfolder with valid parent", func(t *testing.T) {
|
|
// Create parent folder
|
|
parentPath := "/contracts"
|
|
parentResult, err := svc.CreateFolder(ctx, parentPath, nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
parentID := parentResult.ID
|
|
|
|
// Create subfolder
|
|
subPath := "/contracts/2025"
|
|
result, err := svc.CreateFolder(ctx, subPath, &parentID, clientID, "user123")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, result)
|
|
assert.Equal(t, subPath, result.Path)
|
|
require.NotNil(t, result.Parentid)
|
|
assert.Equal(t, parentID, *result.Parentid)
|
|
})
|
|
|
|
t.Run("reject empty path", func(t *testing.T) {
|
|
_, err := svc.CreateFolder(ctx, "", nil, clientID, "user123")
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "must start with /")
|
|
})
|
|
|
|
t.Run("reject empty clientID", func(t *testing.T) {
|
|
_, err := svc.CreateFolder(ctx, "/test", nil, "", "user123")
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "clientID cannot be empty")
|
|
})
|
|
|
|
t.Run("reject empty createdBy", func(t *testing.T) {
|
|
_, err := svc.CreateFolder(ctx, "/test", nil, clientID, "")
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "createdBy cannot be empty")
|
|
})
|
|
|
|
t.Run("reject parent from different client", func(t *testing.T) {
|
|
// Create another client
|
|
otherClientID := "other-client"
|
|
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
|
Clientid: otherClientID,
|
|
Name: "Other Client",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Create parent folder for other client
|
|
parentResult, err := svc.CreateFolder(ctx, "/other", nil, otherClientID, "user123")
|
|
require.NoError(t, err)
|
|
parentID := parentResult.ID
|
|
|
|
// Try to create subfolder with parent from different client
|
|
_, err = svc.CreateFolder(ctx, "/test", &parentID, clientID, "user123")
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "different client")
|
|
})
|
|
}
|
|
|
|
func TestGetFolder(t *testing.T) {
|
|
ctx := t.Context()
|
|
cfg := &TestConfig{}
|
|
test.CreateDB(t, cfg)
|
|
svc := folder.New(cfg)
|
|
|
|
clientID := "test-client-get"
|
|
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
|
Clientid: clientID,
|
|
Name: "Test Client Get",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Create a folder
|
|
path := "/documents"
|
|
created, err := svc.CreateFolder(ctx, path, nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
// Get the folder
|
|
result, err := svc.GetFolder(ctx, created.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, created.ID, result.ID)
|
|
assert.Equal(t, path, result.Path)
|
|
}
|
|
|
|
func TestGetFolderByPath(t *testing.T) {
|
|
ctx := t.Context()
|
|
cfg := &TestConfig{}
|
|
test.CreateDB(t, cfg)
|
|
svc := folder.New(cfg)
|
|
|
|
clientID := "test-client-path"
|
|
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
|
Clientid: clientID,
|
|
Name: "Test Client Path",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Create a folder
|
|
path := "/documents/2025"
|
|
created, err := svc.CreateFolder(ctx, path, nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
// Get by path
|
|
result, err := svc.GetFolderByPath(ctx, clientID, path)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, created.ID, result.ID)
|
|
assert.Equal(t, path, result.Path)
|
|
assert.Equal(t, clientID, result.Clientid)
|
|
}
|
|
|
|
func TestRenameFolder(t *testing.T) {
|
|
ctx := t.Context()
|
|
cfg := &TestConfig{}
|
|
test.CreateDB(t, cfg)
|
|
svc := folder.New(cfg)
|
|
|
|
clientID := "test-client-rename"
|
|
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
|
Clientid: clientID,
|
|
Name: "Test Client Rename",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
t.Run("rename successfully", func(t *testing.T) {
|
|
oldPath := "/old-path"
|
|
created, err := svc.CreateFolder(ctx, oldPath, nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
newPath := "/new-path"
|
|
err = svc.RenameFolder(ctx, created.ID, newPath)
|
|
require.NoError(t, err)
|
|
|
|
// Verify rename
|
|
result, err := svc.GetFolder(ctx, created.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, newPath, result.Path)
|
|
})
|
|
|
|
t.Run("reject empty path", func(t *testing.T) {
|
|
err := svc.RenameFolder(ctx, uuid.New(), "")
|
|
require.Error(t, err)
|
|
// The folder won't be found, so we can't test path validation
|
|
assert.Contains(t, err.Error(), "folder not found")
|
|
})
|
|
|
|
t.Run("reject invalid path characters", func(t *testing.T) {
|
|
path := "/test-rename-invalid"
|
|
created, err := svc.CreateFolder(ctx, path, nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
err = svc.RenameFolder(ctx, created.ID, "/invalid@path")
|
|
require.Error(t, err)
|
|
assert.True(t, folder.IsPathValidationError(err))
|
|
})
|
|
|
|
t.Run("reject root folder rename", func(t *testing.T) {
|
|
// Create root folder
|
|
rootPath := "/"
|
|
rootFolder, err := svc.CreateFolder(ctx, rootPath, nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
// Try to rename root folder
|
|
err = svc.RenameFolder(ctx, rootFolder.ID, "/renamed-root")
|
|
require.Error(t, err)
|
|
assert.True(t, folder.IsPathValidationError(err))
|
|
assert.Contains(t, err.Error(), "root folder cannot be renamed")
|
|
})
|
|
}
|
|
|
|
func TestGetFolderTree(t *testing.T) {
|
|
ctx := t.Context()
|
|
cfg := &TestConfig{}
|
|
test.CreateDB(t, cfg)
|
|
svc := folder.New(cfg)
|
|
|
|
clientID := "test-client-tree"
|
|
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
|
Clientid: clientID,
|
|
Name: "Test Client Tree",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Create folder hierarchy
|
|
root, err := svc.CreateFolder(ctx, "/documents", nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
child1, err := svc.CreateFolder(ctx, "/documents/2025", &root.ID, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
_, err = svc.CreateFolder(ctx, "/documents/2025/january", &child1.ID, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
// Get tree
|
|
result, err := svc.GetFolderTree(ctx, root.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, result, 3) // root + 2 descendants
|
|
assert.Equal(t, root.ID, result[0].ID)
|
|
}
|
|
|
|
func TestGetFoldersByClient(t *testing.T) {
|
|
ctx := t.Context()
|
|
cfg := &TestConfig{}
|
|
test.CreateDB(t, cfg)
|
|
svc := folder.New(cfg)
|
|
|
|
clientID := "test-client-list"
|
|
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
|
Clientid: clientID,
|
|
Name: "Test Client List",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Create multiple folders
|
|
_, err = svc.CreateFolder(ctx, "/documents", nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
_, err = svc.CreateFolder(ctx, "/contracts", nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
result, err := svc.GetFoldersByClient(ctx, clientID)
|
|
require.NoError(t, err)
|
|
assert.GreaterOrEqual(t, len(result), 2)
|
|
}
|
|
|
|
func TestGetRootFolders(t *testing.T) {
|
|
ctx := t.Context()
|
|
cfg := &TestConfig{}
|
|
test.CreateDB(t, cfg)
|
|
svc := folder.New(cfg)
|
|
|
|
clientID := "test-client-roots"
|
|
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
|
Clientid: clientID,
|
|
Name: "Test Client Roots",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Create root folder
|
|
root, err := svc.CreateFolder(ctx, "/documents", nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
// Create child folder
|
|
_, err = svc.CreateFolder(ctx, "/documents/sub", &root.ID, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
// Get only root folders
|
|
result, err := svc.GetRootFolders(ctx, clientID)
|
|
require.NoError(t, err)
|
|
|
|
// Filter to only this test's root
|
|
var foundRoot *repository.Folder
|
|
for _, f := range result {
|
|
if f.ID == root.ID {
|
|
foundRoot = f
|
|
break
|
|
}
|
|
}
|
|
require.NotNil(t, foundRoot)
|
|
assert.Nil(t, foundRoot.Parentid)
|
|
}
|
|
|
|
func TestGetSubfolders(t *testing.T) {
|
|
ctx := t.Context()
|
|
cfg := &TestConfig{}
|
|
test.CreateDB(t, cfg)
|
|
svc := folder.New(cfg)
|
|
|
|
clientID := "test-client-subs"
|
|
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
|
Clientid: clientID,
|
|
Name: "Test Client Subs",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Create parent
|
|
parent, err := svc.CreateFolder(ctx, "/documents", nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
// Create child
|
|
child, err := svc.CreateFolder(ctx, "/documents/2025", &parent.ID, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
// Get subfolders
|
|
result, err := svc.GetSubfolders(ctx, parent.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, result, 1)
|
|
assert.Equal(t, child.ID, result[0].ID)
|
|
assert.Equal(t, parent.ID, *result[0].Parentid)
|
|
}
|
|
|
|
func TestGetDocumentsByFolder(t *testing.T) {
|
|
ctx := t.Context()
|
|
cfg := &TestConfig{}
|
|
test.CreateDB(t, cfg)
|
|
svc := folder.New(cfg)
|
|
|
|
clientID := "test-client-docs-by-folder"
|
|
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
|
Clientid: clientID,
|
|
Name: "Test Client Docs By Folder",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
t.Run("get documents in folder", func(t *testing.T) {
|
|
// Create folder
|
|
folderResult, err := svc.CreateFolder(ctx, "/contracts", nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
// Create documents in folder
|
|
filename1 := "contract1.pdf"
|
|
doc1ID, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
|
|
Clientid: clientID,
|
|
Hash: "foldertest1",
|
|
Filename: &filename1,
|
|
Folderid: &folderResult.ID,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
filename2 := "contract2.pdf"
|
|
doc2ID, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
|
|
Clientid: clientID,
|
|
Hash: "foldertest2",
|
|
Filename: &filename2,
|
|
Folderid: &folderResult.ID,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Get documents by folder
|
|
docs, err := svc.GetDocumentsByFolder(ctx, folderResult.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, docs, 2)
|
|
|
|
// Verify both documents are returned
|
|
docIDs := make(map[uuid.UUID]bool)
|
|
for _, doc := range docs {
|
|
docIDs[doc.ID] = true
|
|
}
|
|
assert.True(t, docIDs[doc1ID])
|
|
assert.True(t, docIDs[doc2ID])
|
|
})
|
|
|
|
t.Run("return empty for folder with no documents", func(t *testing.T) {
|
|
// Create folder with no documents
|
|
emptyFolder, err := svc.CreateFolder(ctx, "/empty", nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
docs, err := svc.GetDocumentsByFolder(ctx, emptyFolder.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, docs, 0)
|
|
})
|
|
}
|
|
|
|
func TestGetDocumentsEnriched(t *testing.T) {
|
|
ctx := t.Context()
|
|
cfg := &TestConfig{}
|
|
test.CreateDB(t, cfg)
|
|
svc := folder.New(cfg)
|
|
|
|
clientID := "test-client-docs-enriched"
|
|
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
|
Clientid: clientID,
|
|
Name: "Test Client Docs Enriched",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
t.Run("get enriched documents without text record", func(t *testing.T) {
|
|
// Create folder
|
|
folderResult, err := svc.CreateFolder(ctx, "/enriched-no-text", nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
// Create document in folder
|
|
filename := "enriched1.pdf"
|
|
originalPath := "/uploads/enriched1.pdf"
|
|
docID, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
|
|
Clientid: clientID,
|
|
Hash: "enrichedtest1",
|
|
Filename: &filename,
|
|
Originalpath: &originalPath,
|
|
Folderid: &folderResult.ID,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Get enriched documents
|
|
docs, err := svc.GetDocumentsEnriched(ctx, folderResult.ID, false)
|
|
require.NoError(t, err)
|
|
assert.Len(t, docs, 1)
|
|
assert.Equal(t, docID, docs[0].ID)
|
|
assert.Equal(t, "enrichedtest1", docs[0].Hash)
|
|
assert.Equal(t, filename, *docs[0].Filename)
|
|
assert.Equal(t, originalPath, *docs[0].OriginalPath)
|
|
assert.False(t, docs[0].HasTextRecord)
|
|
assert.Nil(t, docs[0].TextRecord)
|
|
assert.Empty(t, docs[0].Labels)
|
|
})
|
|
|
|
t.Run("get enriched documents with text record", func(t *testing.T) {
|
|
// Create folder
|
|
folderResult, err := svc.CreateFolder(ctx, "/enriched-with-text", nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
// Create document in folder
|
|
filename := "enriched2.pdf"
|
|
docID, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
|
|
Clientid: clientID,
|
|
Hash: "enrichedtest2",
|
|
Filename: &filename,
|
|
Folderid: &folderResult.ID,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Create field extraction for this document
|
|
fieldSvc := fieldextraction.New(cfg)
|
|
contractTitle := "Enriched Test Contract"
|
|
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)
|
|
|
|
// Get enriched documents with text record
|
|
docs, err := svc.GetDocumentsEnriched(ctx, folderResult.ID, true)
|
|
require.NoError(t, err)
|
|
assert.Len(t, docs, 1)
|
|
assert.Equal(t, docID, docs[0].ID)
|
|
assert.True(t, docs[0].HasTextRecord)
|
|
assert.NotNil(t, docs[0].TextRecord)
|
|
assert.Equal(t, docID, docs[0].TextRecord.DocumentID)
|
|
assert.Equal(t, int32(1), docs[0].TextRecord.Version)
|
|
assert.Equal(t, "testuser", docs[0].TextRecord.CreatedBy)
|
|
})
|
|
|
|
t.Run("get enriched documents with text record but not requesting it", func(t *testing.T) {
|
|
// Create folder
|
|
folderResult, err := svc.CreateFolder(ctx, "/enriched-skip-text", nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
// Create document in folder
|
|
filename := "enriched3.pdf"
|
|
docID, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
|
|
Clientid: clientID,
|
|
Hash: "enrichedtest3",
|
|
Filename: &filename,
|
|
Folderid: &folderResult.ID,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Create field extraction
|
|
fieldSvc := fieldextraction.New(cfg)
|
|
contractTitle := "Skip Text Contract"
|
|
input := &fieldextraction.CreateFieldExtractionInput{
|
|
DocumentID: docID,
|
|
SingleFields: &repository.AddFieldExtractionParams{
|
|
Documentid: docID,
|
|
Filename: &filename,
|
|
Contracttitle: &contractTitle,
|
|
Createdby: "skipuser",
|
|
},
|
|
ArrayFields: []*repository.AddFieldExtractionArrayFieldParams{},
|
|
}
|
|
_, err = fieldSvc.CreateFieldExtraction(ctx, input)
|
|
require.NoError(t, err)
|
|
|
|
// Get enriched documents without requesting text record
|
|
docs, err := svc.GetDocumentsEnriched(ctx, folderResult.ID, false)
|
|
require.NoError(t, err)
|
|
assert.Len(t, docs, 1)
|
|
assert.True(t, docs[0].HasTextRecord) // Has text record
|
|
assert.Nil(t, docs[0].TextRecord) // But not fetched
|
|
})
|
|
|
|
t.Run("return empty for empty folder", func(t *testing.T) {
|
|
// Create folder with no documents
|
|
emptyFolder, err := svc.CreateFolder(ctx, "/enriched-empty", nil, clientID, "user123")
|
|
require.NoError(t, err)
|
|
|
|
docs, err := svc.GetDocumentsEnriched(ctx, emptyFolder.ID, false)
|
|
require.NoError(t, err)
|
|
assert.Len(t, docs, 0)
|
|
})
|
|
}
|