package matching import ( "context" "strings" "testing" "time" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgtype" "github.com/shopspring/decimal" "github.com/missionworkforce/missionmatch/internal/modules/matching/engine" "github.com/missionworkforce/missionmatch/internal/platform/database/dbgen" ) func dec(n int) decimal.Decimal { return decimal.NewFromInt(int64(n)) } func TestProposalReadyGate(t *testing.T) { // Green with all certs held is the only YES. yes := proposalReady(engine.MatchResult{Band: engine.BandGreen, Total: dec(95), Certifications: dec(100)}, false) if yes.Value != "YES" { t.Fatalf("green plus certs must be YES, got %+v", yes) } // Green but a cert gap is REVIEW, and the reason names the missing certification (never a bare NO). certGap := proposalReady(engine.MatchResult{ Band: engine.BandGreen, Total: dec(92), Certifications: dec(66), GapSummary: []string{"Missing required certification: CISSP"}, }, false) if certGap.Value != "REVIEW" || !strings.Contains(certGap.Reason, "CISSP") { t.Fatalf("green with a cert gap must REVIEW citing the cert, got %+v", certGap) } // Below green is REVIEW with a readiness reason. below := proposalReady(engine.MatchResult{Band: engine.BandYellow, Total: dec(80), Certifications: dec(100)}, false) if below.Value != "REVIEW" || below.Reason == "" { t.Fatalf("below green must REVIEW with a reason, got %+v", below) } } func TestClearanceCellRendersStatusAndUnknown(t *testing.T) { asOf := time.Date(2026, 6, 24, 0, 0, 0, 0, time.UTC) date := func(y int) pgtype.Date { return pgtype.Date{Time: time.Date(y, 1, 1, 0, 0, 0, 0, time.UTC), Valid: true} } // Active Secret with a future expiry: shown as Active, SCI not eligible, investigation year present. active := dbgen.Candidate{ ID: uuid.New(), ClearanceLevel: "secret", ClearancePoly: "none", ClearanceStatus: "active", ClearanceGrantedAt: date(2022), ClearanceExpiresAt: date(2030), } a := clearanceCell(active, ClearanceFactsFrom(active, nil), asOf) if !a.SciKnown || a.Status != "Active" || a.SciEligible || a.InvestigationYear != "2022" { t.Fatalf("active Secret rendered wrong: %+v", a) } // A clearance whose expiry has passed must render Expired, never a confident Active. lapsed := dbgen.Candidate{ ID: uuid.New(), ClearanceLevel: "ts_sci", ClearancePoly: "full_scope", ClearanceStatus: "active", ClearanceExpiresAt: date(2024), } l := clearanceCell(lapsed, ClearanceFactsFrom(lapsed, nil), asOf) if l.Status != "Expired" { t.Fatalf("a lapsed clearance must show Expired, got %q", l.Status) } // Unknown clearance (sourced External lead): rendered as Unknown, not SciKnown, never blank. unknown := dbgen.Candidate{ID: uuid.New(), ClearanceLevel: "unknown", ClearancePoly: "none", ClearanceStatus: "unknown"} u := clearanceCell(unknown, ClearanceFactsFrom(unknown, nil), asOf) if u.SciKnown || u.Level != "Unknown" { t.Fatalf("unknown clearance must be Unknown and not SciKnown, got %+v", u) } } func TestBuildCandidateIntelNoRequirements(t *testing.T) { asOf := time.Date(2026, 6, 24, 0, 0, 0, 0, time.UTC) c := dbgen.Candidate{ID: uuid.New(), FullName: "No Reqs Org", ClearanceLevel: "unknown", ClearancePoly: "none", ClearanceStatus: "unknown"} ec := engine.Candidate{ID: c.ID.String()} // Empty reqs and nil maps must not panic (regression for the index out of range crash). v, _ := buildCandidateIntel(context.Background(), c, ec, asOf, nil, nil, nil, nil, nil) if v.MissionReadiness.Status != "No open requirements" || v.BestFit.Name != "" || v.WinImpact.Level != "LOW" { t.Fatalf("a requirement free org must render a clean view, got %+v", v) } } func TestWinImpactCellTiers(t *testing.T) { if got := winImpactCell(3, 6, 12, "Data Scientist"); got.Level != "HIGH" || !strings.Contains(got.Basis, "6 of 12") { t.Fatalf("tier 3 must be HIGH citing the open count, got %+v", got) } if got := winImpactCell(2, 0, 5, "ISSO"); got.Level != "MEDIUM" { t.Fatalf("tier 2 must be MEDIUM, got %+v", got) } if got := winImpactCell(1, 0, 5, "Cyber Engineer"); got.Level != "LOW" { t.Fatalf("tier 1 (redundant depth) must be LOW, got %+v", got) } if got := winImpactCell(0, 0, 0, ""); got.Level != "LOW" { t.Fatalf("tier 0 must be LOW, got %+v", got) } }