package dashboard import ( "context" "errors" "testing" "tm/pkg/ai_summarizer" "go.mongodb.org/mongo-driver/v2/bson" ) type mockProcedureDocumentsLister struct { procedures []ai_summarizer.ProcedureDocumentsSummary err error } func (m *mockProcedureDocumentsLister) ListProceduresWithDocuments(context.Context) ([]ai_summarizer.ProcedureDocumentsSummary, error) { if m.err != nil { return nil, m.err } return m.procedures, nil } func TestScrapedDocumentsFolderIDsUsesMinIOProcedures(t *testing.T) { repo := &repository{ procedureLister: &mockProcedureDocumentsLister{ procedures: []ai_summarizer.ProcedureDocumentsSummary{ {ContractFolderID: "PROC-1", DocumentCount: 3}, {ContractFolderID: "PROC-2", DocumentCount: 0}, {ContractFolderID: " PROC-3 ", DocumentCount: 1}, {ContractFolderID: "PROC-1", DocumentCount: 2}, }, }, } got, err := repo.scrapedDocumentsFolderIDs(context.Background()) if err != nil { t.Fatalf("unexpected error: %v", err) } want := []string{"PROC-1", "PROC-3"} if len(got) != len(want) { t.Fatalf("expected %d folder IDs, got %d: %v", len(want), len(got), got) } for i, id := range want { if got[i] != id { t.Fatalf("expected folder ID %q at index %d, got %q", id, i, got[i]) } } } func TestScrapedDocumentsFolderIDsWithoutLister(t *testing.T) { repo := &repository{} got, err := repo.scrapedDocumentsFolderIDs(context.Background()) if err != nil { t.Fatalf("unexpected error: %v", err) } if got != nil { t.Fatalf("expected nil folder IDs without lister, got %v", got) } } func TestScrapedDocumentsFolderIDsPropagatesError(t *testing.T) { repo := &repository{ procedureLister: &mockProcedureDocumentsLister{ err: errors.New("minio unavailable"), }, } _, err := repo.scrapedDocumentsFolderIDs(context.Background()) if err == nil { t.Fatal("expected error") } } func TestResolveScrapedTendersScopeUsesMinIOFolders(t *testing.T) { repo := &repository{ procedureLister: &mockProcedureDocumentsLister{ procedures: []ai_summarizer.ProcedureDocumentsSummary{ {ContractFolderID: "PROC-1", DocumentCount: 2}, }, }, } scope, err := repo.resolveScrapedTendersScope(context.Background()) if err != nil { t.Fatalf("unexpected error: %v", err) } if scope.zero { t.Fatal("expected non-zero scope") } in, ok := scope.match["contract_folder_id"].(bson.M) if !ok { t.Fatalf("expected contract_folder_id filter, got %#v", scope.match) } ids, ok := in["$in"].([]string) if !ok || len(ids) != 1 || ids[0] != "PROC-1" { t.Fatalf("unexpected folder IDs: %#v", in["$in"]) } } func TestResolveScrapedTendersScopeMongoFallbackWhenMinIOEmpty(t *testing.T) { repo := &repository{ procedureLister: &mockProcedureDocumentsLister{}, } scope, err := repo.resolveScrapedTendersScope(context.Background()) if err != nil { t.Fatalf("unexpected error: %v", err) } if scope.zero { t.Fatal("expected mongo fallback scope, not zero scope") } if scope.match["processing_metadata.documents_scraped"] != true { t.Fatalf("expected mongo fallback filter, got %#v", scope.match) } } func TestResolveScrapedTendersScopeMongoFallbackWithoutLister(t *testing.T) { repo := &repository{} scope, err := repo.resolveScrapedTendersScope(context.Background()) if err != nil { t.Fatalf("unexpected error: %v", err) } if scope.zero { t.Fatal("expected mongo fallback scope") } if scope.match["processing_metadata.documents_scraped"] != true { t.Fatalf("expected mongo fallback filter, got %#v", scope.match) } } func TestMongoScrapedTendersScopeMatchesStatisticsFilter(t *testing.T) { scope := mongoScrapedTendersScope() if scope.zero { t.Fatal("expected non-zero mongo statistics scope") } if scope.match["processing_metadata.documents_scraped"] != true { t.Fatalf("expected documents_scraped filter, got %#v", scope.match) } }