//go:build integration package integration import ( "context" "testing" "github.com/missionworkforce/missionmatch/internal/modules/matching" "github.com/missionworkforce/missionmatch/internal/platform/database/dbgen" ) // TestWhoCanSupportReadsPersistedEvaluations proves the missionMATCH "who can support this mission // today" rollup READS the stored screenMATCH evaluation rather than rescoring: before any screen the // rollup is empty, after a screen persists the qualification the same candidate appears with the SAME // stored total, band, name, and availability. This is the B to D pipeline: screenMATCH persists, the // missionMATCH rollup reads the artifact. func TestWhoCanSupportReadsPersistedEvaluations(t *testing.T) { ctx := context.Background() org := seedOrg(t) req, err := dbgen.New(migrator).CreateRequirement(ctx, dbgen.CreateRequirementParams{ OrganizationID: org, Title: "Mission Role", RequiredLevel: "secret", RequiredPoly: "none", }) if err != nil { t.Fatalf("seed requirement: %v", err) } cand := seedCandidate(t, org, "secret", "active", true) svc := matching.NewService(appDB, nil, nil) // Before any screen the requirement has no stored evaluations, so no one can be shown as supporting. before, err := svc.WhoCanSupport(ctxOrg(org), req.ID) if err != nil { t.Fatalf("WhoCanSupport (before): %v", err) } if len(before) != 0 { t.Fatalf("before any screen want 0 supporters, got %d", len(before)) } // Screen the candidate; this persists the qualification (Workstream B). mr, err := svc.ScreenCandidate(ctxOrg(org), cand.ID, req.ID) if err != nil { t.Fatalf("ScreenCandidate: %v", err) } // The rollup now reads the stored evaluation: same candidate, same frozen score, name, availability. after, err := svc.WhoCanSupport(ctxOrg(org), req.ID) if err != nil { t.Fatalf("WhoCanSupport (after): %v", err) } if len(after) != 1 { t.Fatalf("after a screen want 1 supporter, got %d", len(after)) } s := after[0] if s.CandidateID != cand.ID.String() { t.Fatalf("supporter id = %s, want %s", s.CandidateID, cand.ID) } if s.Total != mr.Total.StringFixed(2) { t.Fatalf("rollup total %s != stored screen total %s (it must read, not rescore)", s.Total, mr.Total.StringFixed(2)) } if s.Band != mr.Band.Code() { t.Fatalf("rollup band %s != stored band %s", s.Band, mr.Band.Code()) } if !s.Available { t.Fatalf("candidate was seeded available, rollup shows unavailable") } if s.FullName == "" { t.Fatalf("rollup must carry the candidate name from the join") } }