Files
query-orchestration/api/queryAPI/fieldextractions_test.go
T
Jay Brown 3bdc27f4de Merged in feature/textExtractionsPart2 (pull request #193)
Continue finishing the parts of the text extraction plan

* add missing fields
2025-12-02 19:13:08 +00:00

833 lines
27 KiB
Go

package queryapi_test
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"time"
queryapi "queryorchestration/api/queryAPI"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/fieldextraction"
"queryorchestration/internal/serviceconfig"
"queryorchestration/internal/test"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/labstack/echo/v4"
openapi_types "github.com/oapi-codegen/runtime/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type FieldExtractionsTestConfig struct {
serviceconfig.BaseConfig
}
func (c *FieldExtractionsTestConfig) GetBackgroundRunner() any { return nil }
func setupFieldExtractionsTestController(t *testing.T) (*queryapi.Controllers, *FieldExtractionsTestConfig, uuid.UUID, string) {
t.Helper()
cfg := &FieldExtractionsTestConfig{}
test.CreateDB(t, cfg)
// Create services
fieldExtractionSvc := fieldextraction.New(cfg)
services := &queryapi.Services{
FieldExtraction: fieldExtractionSvc,
}
// Create test client and document with unique IDs
ctx := t.Context()
uniqueID := uuid.New().String()[:8]
clientID := fmt.Sprintf("test-client-%s", uniqueID)
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
Clientid: clientID,
Name: "Test Client",
})
require.NoError(t, err)
filename := "test.pdf"
documentID, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
Clientid: clientID,
Hash: fmt.Sprintf("testhash-%s", uniqueID), // Unique hash per test
Filename: &filename,
})
require.NoError(t, err)
ctrl := queryapi.NewControllers(services, nil)
return ctrl, cfg, documentID, clientID
}
func TestCreateFieldExtraction_Success(t *testing.T) {
ctrl, _, documentID, _ := setupFieldExtractionsTestController(t)
// Create request body
reqBody := queryapi.FieldExtractionRequest{
DocumentId: queryapi.DocumentID(documentID),
CreatedBy: openapi_types.Email("test@example.com"),
SingleFields: queryapi.SingleFields{
FileName: ptr("test.pdf"),
ContractTitle: ptr("Test Contract"),
ClientName: ptr("Test Client Inc"),
},
ArrayFields: []queryapi.ArrayFieldItem{
{
ExhibitTitle: ptr("Exhibit A"),
ExhibitPage: ptr("1"),
ReimbProvTin: ptr("123456789"),
},
{
ExhibitTitle: ptr("Exhibit B"),
ExhibitPage: ptr("2"),
ReimbProvTin: ptr("987654321"),
},
},
}
body, err := json.Marshal(reqBody)
require.NoError(t, err)
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/field-extractions", bytes.NewReader(body))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err = ctrl.CreateFieldExtraction(c)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec.Code)
// Parse response
var resp queryapi.FieldExtractionResponse
err = json.Unmarshal(rec.Body.Bytes(), &resp)
require.NoError(t, err)
assert.Equal(t, documentID, uuid.UUID(resp.DocumentId))
assert.Equal(t, int32(1), resp.Version) // First version is 1
assert.Equal(t, "test@example.com", string(resp.CreatedBy))
assert.Equal(t, "test.pdf", *resp.SingleFields.FileName)
assert.Equal(t, "Test Contract", *resp.SingleFields.ContractTitle)
assert.Len(t, resp.ArrayFields, 2)
assert.Equal(t, "Exhibit A", *resp.ArrayFields[0].ExhibitTitle)
assert.Equal(t, "Exhibit B", *resp.ArrayFields[1].ExhibitTitle)
}
func TestCreateFieldExtraction_InvalidRequest(t *testing.T) {
ctrl, _, _, _ := setupFieldExtractionsTestController(t)
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/field-extractions", bytes.NewReader([]byte("invalid json")))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err := ctrl.CreateFieldExtraction(c)
// Handler returns an echo.HTTPError which should be treated as an error
require.Error(t, err)
httpErr, ok := err.(*echo.HTTPError)
require.True(t, ok)
assert.Equal(t, http.StatusBadRequest, httpErr.Code)
}
func TestCreateFieldExtraction_MissingDocumentID(t *testing.T) {
ctrl, _, _, _ := setupFieldExtractionsTestController(t)
reqBody := queryapi.FieldExtractionRequest{
DocumentId: queryapi.DocumentID(uuid.Nil),
CreatedBy: openapi_types.Email("test@example.com"),
SingleFields: queryapi.SingleFields{
FileName: ptr("test.pdf"),
},
ArrayFields: []queryapi.ArrayFieldItem{},
}
body, err := json.Marshal(reqBody)
require.NoError(t, err)
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/field-extractions", bytes.NewReader(body))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err = ctrl.CreateFieldExtraction(c)
require.Error(t, err)
httpErr, ok := err.(*echo.HTTPError)
require.True(t, ok)
assert.Equal(t, http.StatusBadRequest, httpErr.Code)
}
func TestCreateFieldExtraction_MissingCreatedBy(t *testing.T) {
// Use a simple controller without database since we're just testing validation
ctrl := &queryapi.Controllers{}
// Use a valid document ID but empty createdBy
documentID := uuid.New()
body := []byte(fmt.Sprintf(`{
"documentId": "%s",
"createdBy": "",
"singleFields": {"fileName": "test.pdf"},
"arrayFields": []
}`, documentID))
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/field-extractions", bytes.NewReader(body))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err := ctrl.CreateFieldExtraction(c)
require.Error(t, err)
httpErr, ok := err.(*echo.HTTPError)
require.True(t, ok)
assert.Equal(t, http.StatusBadRequest, httpErr.Code)
}
func TestGetCurrentFieldExtraction_Success(t *testing.T) {
ctrl, cfg, documentID, _ := setupFieldExtractionsTestController(t)
ctx := t.Context()
// First create a field extraction using the service directly
svc := fieldextraction.New(cfg)
filename := "test.pdf"
contractTitle := "Test Contract"
_, err := svc.CreateFieldExtraction(ctx, &fieldextraction.CreateFieldExtractionInput{
DocumentID: documentID,
SingleFields: &repository.AddFieldExtractionParams{
Documentid: documentID,
Filename: &filename,
Contracttitle: &contractTitle,
Createdby: "user@example.com",
},
ArrayFields: []*repository.AddFieldExtractionArrayFieldParams{},
})
require.NoError(t, err)
// Now test the API
e := echo.New()
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/field-extractions?documentId=%s", documentID), nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
params := queryapi.GetCurrentFieldExtractionParams{
DocumentId: queryapi.DocumentID(documentID),
}
err = ctrl.GetCurrentFieldExtraction(c, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
// Parse response
var resp queryapi.FieldExtractionResponse
err = json.Unmarshal(rec.Body.Bytes(), &resp)
require.NoError(t, err)
assert.Equal(t, documentID, uuid.UUID(resp.DocumentId))
assert.Equal(t, int32(1), resp.Version)
assert.Equal(t, "user@example.com", string(resp.CreatedBy))
assert.Equal(t, "Test Contract", *resp.SingleFields.ContractTitle)
}
func TestGetCurrentFieldExtraction_NotFound(t *testing.T) {
ctrl, _, _, _ := setupFieldExtractionsTestController(t)
// Use a random document ID that doesn't have any extractions
randomDocID := uuid.New()
e := echo.New()
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/field-extractions?documentId=%s", randomDocID), nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
params := queryapi.GetCurrentFieldExtractionParams{
DocumentId: queryapi.DocumentID(randomDocID),
}
err := ctrl.GetCurrentFieldExtraction(c, params)
require.Error(t, err)
httpErr, ok := err.(*echo.HTTPError)
require.True(t, ok)
assert.Equal(t, http.StatusNotFound, httpErr.Code)
}
func TestGetCurrentFieldExtraction_InvalidDocumentID(t *testing.T) {
ctrl, _, _, _ := setupFieldExtractionsTestController(t)
e := echo.New()
req := httptest.NewRequest(http.MethodGet, "/field-extractions?documentId=", nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
params := queryapi.GetCurrentFieldExtractionParams{
DocumentId: queryapi.DocumentID(uuid.Nil),
}
err := ctrl.GetCurrentFieldExtraction(c, params)
require.Error(t, err)
httpErr, ok := err.(*echo.HTTPError)
require.True(t, ok)
assert.Equal(t, http.StatusBadRequest, httpErr.Code)
}
func TestGetFieldExtractionHistory_Success(t *testing.T) {
ctrl, cfg, documentID, _ := setupFieldExtractionsTestController(t)
ctx := t.Context()
// Create multiple versions
svc := fieldextraction.New(cfg)
filename := "test.pdf"
for i := 1; i <= 3; i++ {
contractTitle := fmt.Sprintf("Contract Version %d", i)
_, err := svc.CreateFieldExtraction(ctx, &fieldextraction.CreateFieldExtractionInput{
DocumentID: documentID,
SingleFields: &repository.AddFieldExtractionParams{
Documentid: documentID,
Filename: &filename,
Contracttitle: &contractTitle,
Createdby: fmt.Sprintf("user%d@example.com", i),
},
ArrayFields: []*repository.AddFieldExtractionArrayFieldParams{},
})
require.NoError(t, err)
}
// Now test the API
e := echo.New()
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/field-extractions/history?documentId=%s", documentID), nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
params := queryapi.GetFieldExtractionHistoryParams{
DocumentId: queryapi.DocumentID(documentID),
}
err := ctrl.GetFieldExtractionHistory(c, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
// Parse response
var resp struct {
Versions []queryapi.FieldExtractionVersion `json:"versions"`
}
err = json.Unmarshal(rec.Body.Bytes(), &resp)
require.NoError(t, err)
// Should have 3 versions, most recent first
assert.Len(t, resp.Versions, 3)
assert.Equal(t, int32(3), resp.Versions[0].Version)
assert.Equal(t, "user3@example.com", string(resp.Versions[0].CreatedBy))
assert.Equal(t, int32(2), resp.Versions[1].Version)
assert.Equal(t, "user2@example.com", string(resp.Versions[1].CreatedBy))
assert.Equal(t, int32(1), resp.Versions[2].Version)
assert.Equal(t, "user1@example.com", string(resp.Versions[2].CreatedBy))
}
func TestGetFieldExtractionHistory_NoHistory(t *testing.T) {
ctrl, cfg, _, clientID := setupFieldExtractionsTestController(t)
ctx := t.Context()
// Create a new document with no extractions
filename := "nohistory.pdf"
newDocID, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
Clientid: clientID,
Hash: "nohistoryhash",
Filename: &filename,
})
require.NoError(t, err)
e := echo.New()
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/field-extractions/history?documentId=%s", newDocID), nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
params := queryapi.GetFieldExtractionHistoryParams{
DocumentId: queryapi.DocumentID(newDocID),
}
err = ctrl.GetFieldExtractionHistory(c, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
// Parse response
var resp struct {
Versions []queryapi.FieldExtractionVersion `json:"versions"`
}
err = json.Unmarshal(rec.Body.Bytes(), &resp)
require.NoError(t, err)
assert.Len(t, resp.Versions, 0)
}
func TestGetFieldExtractionHistory_InvalidDocumentID(t *testing.T) {
ctrl, _, _, _ := setupFieldExtractionsTestController(t)
e := echo.New()
req := httptest.NewRequest(http.MethodGet, "/field-extractions/history?documentId=", nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
params := queryapi.GetFieldExtractionHistoryParams{
DocumentId: queryapi.DocumentID(uuid.Nil),
}
err := ctrl.GetFieldExtractionHistory(c, params)
require.Error(t, err)
httpErr, ok := err.(*echo.HTTPError)
require.True(t, ok)
assert.Equal(t, http.StatusBadRequest, httpErr.Code)
}
func TestCreateFieldExtraction_WithDates(t *testing.T) {
ctrl, _, documentID, _ := setupFieldExtractionsTestController(t)
effectiveDate := openapi_types.Date{Time: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)}
terminationDate := openapi_types.Date{Time: time.Date(2025, 12, 31, 0, 0, 0, 0, time.UTC)}
reimbEffectiveDate := openapi_types.Date{Time: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC)}
reqBody := queryapi.FieldExtractionRequest{
DocumentId: queryapi.DocumentID(documentID),
CreatedBy: openapi_types.Email("test@example.com"),
SingleFields: queryapi.SingleFields{
FileName: ptr("contract.pdf"),
ContractTitle: ptr("Test Contract with Dates"),
AareteDerivedEffectiveDt: &effectiveDate,
AareteDerivedTerminationDt: &terminationDate,
},
ArrayFields: []queryapi.ArrayFieldItem{
{
ExhibitTitle: ptr("Exhibit A"),
ReimbEffectiveDt: &reimbEffectiveDate,
},
},
}
body, err := json.Marshal(reqBody)
require.NoError(t, err)
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/field-extractions", bytes.NewReader(body))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err = ctrl.CreateFieldExtraction(c)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec.Code)
// Parse response
var resp queryapi.FieldExtractionResponse
err = json.Unmarshal(rec.Body.Bytes(), &resp)
require.NoError(t, err)
// Verify dates are returned correctly
require.NotNil(t, resp.SingleFields.AareteDerivedEffectiveDt)
assert.Equal(t, 2024, resp.SingleFields.AareteDerivedEffectiveDt.Year())
assert.Equal(t, time.January, resp.SingleFields.AareteDerivedEffectiveDt.Month())
assert.Equal(t, 1, resp.SingleFields.AareteDerivedEffectiveDt.Day())
require.NotNil(t, resp.SingleFields.AareteDerivedTerminationDt)
assert.Equal(t, 2025, resp.SingleFields.AareteDerivedTerminationDt.Year())
assert.Equal(t, time.December, resp.SingleFields.AareteDerivedTerminationDt.Month())
assert.Equal(t, 31, resp.SingleFields.AareteDerivedTerminationDt.Day())
require.NotNil(t, resp.ArrayFields[0].ReimbEffectiveDt)
assert.Equal(t, 2024, resp.ArrayFields[0].ReimbEffectiveDt.Year())
assert.Equal(t, time.June, resp.ArrayFields[0].ReimbEffectiveDt.Month())
}
func TestCreateFieldExtraction_WithNumericFields(t *testing.T) {
ctrl, _, documentID, _ := setupFieldExtractionsTestController(t)
reimbPctRate := 10.5
reimbFeeRate := 150.75
grouperBaseRate := 1000.00
reqBody := queryapi.FieldExtractionRequest{
DocumentId: queryapi.DocumentID(documentID),
CreatedBy: openapi_types.Email("test@example.com"),
SingleFields: queryapi.SingleFields{
FileName: ptr("numeric_test.pdf"),
},
ArrayFields: []queryapi.ArrayFieldItem{
{
ExhibitTitle: ptr("Exhibit A"),
ReimbPctRate: &reimbPctRate,
ReimbFeeRate: &reimbFeeRate,
GrouperBaseRate: &grouperBaseRate,
},
},
}
body, err := json.Marshal(reqBody)
require.NoError(t, err)
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/field-extractions", bytes.NewReader(body))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err = ctrl.CreateFieldExtraction(c)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec.Code)
// Parse response
var resp queryapi.FieldExtractionResponse
err = json.Unmarshal(rec.Body.Bytes(), &resp)
require.NoError(t, err)
// Verify numeric fields
require.Len(t, resp.ArrayFields, 1)
require.NotNil(t, resp.ArrayFields[0].ReimbPctRate)
assert.InDelta(t, 10.5, *resp.ArrayFields[0].ReimbPctRate, 0.001)
require.NotNil(t, resp.ArrayFields[0].ReimbFeeRate)
assert.InDelta(t, 150.75, *resp.ArrayFields[0].ReimbFeeRate, 0.001)
require.NotNil(t, resp.ArrayFields[0].GrouperBaseRate)
assert.InDelta(t, 1000.00, *resp.ArrayFields[0].GrouperBaseRate, 0.001)
}
func TestCreateFieldExtraction_EmptyArrayFields(t *testing.T) {
ctrl, _, documentID, _ := setupFieldExtractionsTestController(t)
reqBody := queryapi.FieldExtractionRequest{
DocumentId: queryapi.DocumentID(documentID),
CreatedBy: openapi_types.Email("test@example.com"),
SingleFields: queryapi.SingleFields{
FileName: ptr("simple.pdf"),
ContractTitle: ptr("Simple Contract"),
},
ArrayFields: []queryapi.ArrayFieldItem{},
}
body, err := json.Marshal(reqBody)
require.NoError(t, err)
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/field-extractions", bytes.NewReader(body))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err = ctrl.CreateFieldExtraction(c)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec.Code)
// Parse response
var resp queryapi.FieldExtractionResponse
err = json.Unmarshal(rec.Body.Bytes(), &resp)
require.NoError(t, err)
assert.Len(t, resp.ArrayFields, 0)
}
func TestCreateFieldExtraction_LargeArrayFields(t *testing.T) {
ctrl, _, documentID, _ := setupFieldExtractionsTestController(t)
// Create 100 array field items
arrayFields := make([]queryapi.ArrayFieldItem, 100)
for i := range arrayFields {
title := fmt.Sprintf("Exhibit %d", i)
page := fmt.Sprintf("%d", i+1)
arrayFields[i] = queryapi.ArrayFieldItem{
ExhibitTitle: &title,
ExhibitPage: &page,
}
}
reqBody := queryapi.FieldExtractionRequest{
DocumentId: queryapi.DocumentID(documentID),
CreatedBy: openapi_types.Email("test@example.com"),
SingleFields: queryapi.SingleFields{
FileName: ptr("large_array.pdf"),
ContractTitle: ptr("Large Array Contract"),
},
ArrayFields: arrayFields,
}
body, err := json.Marshal(reqBody)
require.NoError(t, err)
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/field-extractions", bytes.NewReader(body))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err = ctrl.CreateFieldExtraction(c)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec.Code)
// Parse response
var resp queryapi.FieldExtractionResponse
err = json.Unmarshal(rec.Body.Bytes(), &resp)
require.NoError(t, err)
assert.Len(t, resp.ArrayFields, 100)
assert.Equal(t, "Exhibit 0", *resp.ArrayFields[0].ExhibitTitle)
assert.Equal(t, "Exhibit 99", *resp.ArrayFields[99].ExhibitTitle)
}
func TestCreateFieldExtraction_VersionIncrement(t *testing.T) {
ctrl, cfg, documentID, _ := setupFieldExtractionsTestController(t)
// Create first version via API
reqBody := queryapi.FieldExtractionRequest{
DocumentId: queryapi.DocumentID(documentID),
CreatedBy: openapi_types.Email("user1@example.com"),
SingleFields: queryapi.SingleFields{
ContractTitle: ptr("Version 1"),
},
ArrayFields: []queryapi.ArrayFieldItem{},
}
body, _ := json.Marshal(reqBody)
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/field-extractions", bytes.NewReader(body))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err := ctrl.CreateFieldExtraction(c)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec.Code)
var resp1 queryapi.FieldExtractionResponse
_ = json.Unmarshal(rec.Body.Bytes(), &resp1)
assert.Equal(t, int32(1), resp1.Version)
// Create second version
reqBody.CreatedBy = openapi_types.Email("user2@example.com")
reqBody.SingleFields.ContractTitle = ptr("Version 2")
body, _ = json.Marshal(reqBody)
req = httptest.NewRequest(http.MethodPost, "/field-extractions", bytes.NewReader(body))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec = httptest.NewRecorder()
c = e.NewContext(req, rec)
err = ctrl.CreateFieldExtraction(c)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec.Code)
var resp2 queryapi.FieldExtractionResponse
_ = json.Unmarshal(rec.Body.Bytes(), &resp2)
assert.Equal(t, int32(2), resp2.Version)
// GetCurrentFieldExtraction should return version 2
req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("/field-extractions?documentId=%s", documentID), nil)
rec = httptest.NewRecorder()
c = e.NewContext(req, rec)
_ = cfg // Keep cfg used for test context
params := queryapi.GetCurrentFieldExtractionParams{
DocumentId: queryapi.DocumentID(documentID),
}
err = ctrl.GetCurrentFieldExtraction(c, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
var currentResp queryapi.FieldExtractionResponse
_ = json.Unmarshal(rec.Body.Bytes(), &currentResp)
assert.Equal(t, int32(2), currentResp.Version)
assert.Equal(t, "Version 2", *currentResp.SingleFields.ContractTitle)
}
func TestGetFieldExtractionByVersion_Success(t *testing.T) {
ctrl, cfg, documentID, _ := setupFieldExtractionsTestController(t)
ctx := t.Context()
// Create multiple versions with dates for coverage
svc := fieldextraction.New(cfg)
filename := "test.pdf"
for i := 1; i <= 3; i++ {
contractTitle := fmt.Sprintf("Contract Version %d", i)
clientName := fmt.Sprintf("Client %d", i)
// Include dates to test date conversion coverage
effectiveDate := pgtype.Date{Time: time.Date(2024, 1, i, 0, 0, 0, 0, time.UTC), Valid: true}
terminationDate := pgtype.Date{Time: time.Date(2024, 12, i, 0, 0, 0, 0, time.UTC), Valid: true}
_, err := svc.CreateFieldExtraction(ctx, &fieldextraction.CreateFieldExtractionInput{
DocumentID: documentID,
SingleFields: &repository.AddFieldExtractionParams{
Documentid: documentID,
Filename: &filename,
Contracttitle: &contractTitle,
Clientname: &clientName,
Aaretederivedeffectivedt: effectiveDate,
Aaretederivedterminationdt: terminationDate,
Createdby: fmt.Sprintf("user%d@example.com", i),
},
ArrayFields: []*repository.AddFieldExtractionArrayFieldParams{
{
Exhibittitle: ptr(fmt.Sprintf("Exhibit V%d", i)),
},
},
})
require.NoError(t, err)
}
// Test retrieving version 2
e := echo.New()
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/field-extractions/version?documentId=%s&version=2", documentID), nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
params := queryapi.GetFieldExtractionByVersionParams{
DocumentId: queryapi.DocumentID(documentID),
Version: 2,
}
err := ctrl.GetFieldExtractionByVersion(c, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
// Parse response
var resp queryapi.FieldExtractionResponse
err = json.Unmarshal(rec.Body.Bytes(), &resp)
require.NoError(t, err)
// Verify we got version 2
assert.Equal(t, documentID, uuid.UUID(resp.DocumentId))
assert.Equal(t, int32(2), resp.Version)
assert.Equal(t, "user2@example.com", string(resp.CreatedBy))
assert.Equal(t, "Contract Version 2", *resp.SingleFields.ContractTitle)
assert.Equal(t, "Client 2", *resp.SingleFields.ClientName)
// Verify dates are returned correctly
require.NotNil(t, resp.SingleFields.AareteDerivedEffectiveDt, "Expected effective date in response")
require.NotNil(t, resp.SingleFields.AareteDerivedTerminationDt, "Expected termination date in response")
assert.Equal(t, 2024, resp.SingleFields.AareteDerivedEffectiveDt.Year())
assert.Equal(t, time.January, resp.SingleFields.AareteDerivedEffectiveDt.Month())
assert.Equal(t, 2, resp.SingleFields.AareteDerivedEffectiveDt.Day())
require.Len(t, resp.ArrayFields, 1)
assert.Equal(t, "Exhibit V2", *resp.ArrayFields[0].ExhibitTitle)
// Also test retrieving version 1
req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("/field-extractions/version?documentId=%s&version=1", documentID), nil)
rec = httptest.NewRecorder()
c = e.NewContext(req, rec)
params.Version = 1
err = ctrl.GetFieldExtractionByVersion(c, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
err = json.Unmarshal(rec.Body.Bytes(), &resp)
require.NoError(t, err)
assert.Equal(t, int32(1), resp.Version)
assert.Equal(t, "Contract Version 1", *resp.SingleFields.ContractTitle)
assert.Equal(t, "Exhibit V1", *resp.ArrayFields[0].ExhibitTitle)
}
func TestGetFieldExtractionByVersion_NotFound(t *testing.T) {
ctrl, cfg, documentID, _ := setupFieldExtractionsTestController(t)
ctx := t.Context()
// Create only one version
svc := fieldextraction.New(cfg)
filename := "test.pdf"
contractTitle := "Test Contract"
_, err := svc.CreateFieldExtraction(ctx, &fieldextraction.CreateFieldExtractionInput{
DocumentID: documentID,
SingleFields: &repository.AddFieldExtractionParams{
Documentid: documentID,
Filename: &filename,
Contracttitle: &contractTitle,
Createdby: "user@example.com",
},
ArrayFields: []*repository.AddFieldExtractionArrayFieldParams{},
})
require.NoError(t, err)
// Try to get version 5 (which doesn't exist)
e := echo.New()
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/field-extractions/version?documentId=%s&version=5", documentID), nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
params := queryapi.GetFieldExtractionByVersionParams{
DocumentId: queryapi.DocumentID(documentID),
Version: 5,
}
err = ctrl.GetFieldExtractionByVersion(c, params)
require.Error(t, err)
httpErr, ok := err.(*echo.HTTPError)
require.True(t, ok)
assert.Equal(t, http.StatusNotFound, httpErr.Code)
}
func TestGetFieldExtractionByVersion_InvalidDocumentID(t *testing.T) {
ctrl, _, _, _ := setupFieldExtractionsTestController(t)
e := echo.New()
req := httptest.NewRequest(http.MethodGet, "/field-extractions/version?documentId=&version=1", nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
params := queryapi.GetFieldExtractionByVersionParams{
DocumentId: queryapi.DocumentID(uuid.Nil),
Version: 1,
}
err := ctrl.GetFieldExtractionByVersion(c, params)
require.Error(t, err)
httpErr, ok := err.(*echo.HTTPError)
require.True(t, ok)
assert.Equal(t, http.StatusBadRequest, httpErr.Code)
}
func TestGetFieldExtractionByVersion_InvalidVersion(t *testing.T) {
ctrl, _, documentID, _ := setupFieldExtractionsTestController(t)
e := echo.New()
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/field-extractions/version?documentId=%s&version=0", documentID), nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
params := queryapi.GetFieldExtractionByVersionParams{
DocumentId: queryapi.DocumentID(documentID),
Version: 0, // Invalid: version must be >= 1
}
err := ctrl.GetFieldExtractionByVersion(c, params)
require.Error(t, err)
httpErr, ok := err.(*echo.HTTPError)
require.True(t, ok)
assert.Equal(t, http.StatusBadRequest, httpErr.Code)
}
func TestGetFieldExtractionByVersion_NoExtractions(t *testing.T) {
ctrl, _, documentID, _ := setupFieldExtractionsTestController(t)
// Document exists but has no field extractions
e := echo.New()
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/field-extractions/version?documentId=%s&version=1", documentID), nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
params := queryapi.GetFieldExtractionByVersionParams{
DocumentId: queryapi.DocumentID(documentID),
Version: 1,
}
err := ctrl.GetFieldExtractionByVersion(c, params)
require.Error(t, err)
httpErr, ok := err.(*echo.HTTPError)
require.True(t, ok)
assert.Equal(t, http.StatusNotFound, httpErr.Code)
}
// Helper function to create string pointer
func ptr(s string) *string {
return &s
}