// Akzeptanztest der Readiness-Logik (Story B7-1, C9 §1/§2). Reine Logik, kein DB-Zugriff. // Lauf: npx tsx scripts/test-readiness.ts (Exit 1 bei Fehler). import { interpretationBand, averageReifegrad, buildNextSteps, computeReadiness, type ControlAssessment } from "../src/lib/readiness"; let failures = 0; const ok = (cond: boolean, msg: string) => { console.log(`${cond ? "✓" : "✗ FEHLER"} ${msg}`); if (!cond) failures++; }; // — C9 §1: Textbänder je Ø-Reifegrad — ok(interpretationBand(0).band === "Aufbau", "Ø 0 → Aufbau"); ok(interpretationBand(1.49).band === "Aufbau", "Ø 1,49 → Aufbau"); ok(interpretationBand(1.5).band === "Etabliert im Aufbau", "Ø 1,5 → Etabliert im Aufbau"); ok(interpretationBand(2.49).band === "Etabliert im Aufbau", "Ø 2,49 → Etabliert im Aufbau"); ok(interpretationBand(2.5).band === "Assessment-nah", "Ø 2,5 → Assessment-nah"); ok(interpretationBand(2.99).band === "Assessment-nah", "Ø 2,99 → Assessment-nah"); ok(interpretationBand(3.0).band === "Assessment-reif", "Ø 3,0 → Assessment-reif"); // — Ø-Reifegrad: „unbestätigt zählt nicht als erfüllt" (geht mit 0 ein) — { const a: ControlAssessment[] = [ { control: "1.1.1", chapter: "1", reifegrad: 3, bestaetigt: true }, { control: "1.1.2", chapter: "1", reifegrad: 3, bestaetigt: false }, // zählt als 0 ]; ok(averageReifegrad(a) === 1.5, "unbestätigt zählt als 0 → Ø(3,0) = 1,5"); ok(averageReifegrad([]) === null, "keine Assessments → null (A7 ausstehend)"); } // — C9 §2: dynamische nächste Schritte — { const all = buildNextSteps({ openHighCount: 2, unvalidatedCount: 5, prototypeGap: true, evidenceUploadPending: true }); ok(all.some((s) => s.includes("2 Hoch-Punkte")), "Hoch-Punkte → Schritt mit Anzahl"); ok(all.some((s) => s.includes("5 Objekte")), "unvalidierte Objekte → Schritt mit Anzahl"); ok(all.some((s) => s.includes("Prototypen")), "Prototyp-Gap → Prototyp-Schritt"); ok(all.length === 4, "alle vier Regeln greifen"); const none = buildNextSteps({ openHighCount: 0, unvalidatedCount: 0, prototypeGap: false, evidenceUploadPending: false }); ok(none.length === 0, "keine Bedingung → keine Schritte"); } // — computeReadiness: assessmentPending ohne A7-Daten — { const r = computeReadiness({ assessments: [], bestaetigtAnteil: 0, offenJePrioritaet: { hoch: 1, mittel: 2, niedrig: 0 }, pruefzielAbdeckung: [{ pruefziel: "informationssicherheit", anforderungen: 300 }], zielReifegrad: 3, nextSteps: { openHighCount: 1, unvalidatedCount: 0, prototypeGap: false, evidenceUploadPending: false }, }); ok(r.assessmentPending === true && r.avgReifegrad === null && r.band === null, "ohne Assessments → pending, kein Reifegrad/Band"); ok(r.nextSteps.length === 1, "Kennzahlen-basierte Schritte trotzdem berechnet"); } console.log(failures === 0 ? "\nOK — alle Readiness-Tests grün" : `\nPRUEFEN — ${failures} Fehler`); process.exit(failures === 0 ? 0 : 1);