import { expect, test } from "bun:test"; import { SCORING_MODEL } from "./scoring-model"; import { calculateScoringResult, deriveTrafficLight, type LlmScoringAssessment } from "./scoring"; function assessmentWithColor(farbe: "gruen" | "gelb" | "rot" | "unbewertbar"): LlmScoringAssessment { return { ausschlussgruende: [], dimensionen: SCORING_MODEL.map((dimension) => ({ id: dimension.id, subcriteria: dimension.subcriteria.map((subcriterion) => ({ id: subcriterion.id, farbe, evidence: farbe === "unbewertbar" ? "" : "Test evidence", begruendung: "Test begruendung", confidence: 0.9, missingReason: farbe === "unbewertbar" ? "Keine belastbaren Angaben" : "", })), })), }; } test("calculates a green weighted score when all criteria are green", () => { const scoring = calculateScoringResult(SCORING_MODEL, assessmentWithColor("gruen")); expect(scoring.gesamtScore).toBe(100); expect(scoring.farbe).toBe("gruen"); expect(scoring.unbewertbareKriterien).toBe(0); }); test("scores against the maximum achievable by assessable dimensions", () => { const assessment = assessmentWithColor("gruen"); for (const subcriterion of assessment.dimensionen[4]!.subcriteria) { subcriterion.farbe = "unbewertbar"; subcriterion.evidence = ""; subcriterion.missingReason = "Keine belastbaren Angaben"; } const scoring = calculateScoringResult(SCORING_MODEL, assessment); expect(scoring.gesamtScore).toBe(100); expect(scoring.farbe).toBe("gruen"); expect(scoring.dimensionen[4]!.score).toBe(0); expect(scoring.dimensionen[4]!.scorableWeight).toBe(0); expect(scoring.unbewertbareKriterien).toBeGreaterThan(0); }); test("normalizes a partially assessable dimension by answered criterion weight", () => { const assessment = assessmentWithColor("gruen"); const innovation = assessment.dimensionen.find((dimension) => dimension.id === "innovation")!; for (const subcriterion of innovation.subcriteria) { if (subcriterion.id === "innovation_output") { subcriterion.farbe = "unbewertbar"; subcriterion.evidence = ""; subcriterion.missingReason = "Keine belastbaren Angaben"; } } const scoring = calculateScoringResult(SCORING_MODEL, assessment); const innovationScore = scoring.dimensionen.find((dimension) => dimension.id === "innovation")!; expect(innovationScore.scorableWeight).toBe(75); expect(innovationScore.score).toBe(100); expect(scoring.gesamtScore).toBe(100); expect(scoring.farbe).toBe("gruen"); }); test("derives red when automatic exclusion reasons are present", () => { const scoring = calculateScoringResult(SCORING_MODEL, assessmentWithColor("gruen")); expect(deriveTrafficLight(scoring, ["Stiftung als Bewerber"])).toBe("rot"); }); test("keeps low-scoring non-excluded applications yellow rather than discarded", () => { const scoring = calculateScoringResult(SCORING_MODEL, assessmentWithColor("rot")); expect(scoring.gesamtScore).toBe(0); expect(scoring.farbe).toBe("gelb"); expect(deriveTrafficLight(scoring, [])).toBe("gelb"); });