// Unit-Tests für reine Hilfsfunktionen aus pi-coder-judge-extension.ts // // Ausführung (TypeScript): // npx ts-node test-utils.ts // // Ausführung ohne ts-node (schneller): // node --input-type=module < <(sed 's/: string//g; s/: unknown//g; s/: void//g; s/: boolean//g' test-utils.ts) // // Oder: Funktionen aus dieser Datei kopieren und als .js ausführen. // ── Funktionen (aus Extension kopiert, kein pi-API-Import nötig) ───────────── function normalizeForComparison(s: string): string { return s.trim().replace(/\s+/g, " ").replace(/[.,;:!?]+$/g, "").toLowerCase(); } function parseVerdict(text: string): string { const m = text.match(/Urteil:\s*(PASS WITH CONCERNS|PASS|FAIL)/i); return m ? m[1].toUpperCase() : "UNREADABLE"; } function parseBlockers(text: string): string { const m = text.match( /(?:\*\*Blocker\*\*|##\s*Blocker|[-–*]\s*Blocker)[:\n]([\s\S]*?)(?:\n(?:\*\*Major\*\*|##\s*Major|[-–*]\s*Major)|\n(?:\*\*Minor\*\*|##\s*Minor|[-–*]\s*Minor)|$)/i ); return m ? m[1].trim() : ""; } // ── Test-Harness ────────────────────────────────────────────────────────────── let passed = 0; let failed = 0; function expect(actual: unknown, expected: unknown, label: string): void { if (actual === expected) { console.log(` ✅ ${label}`); passed++; } else { console.error(` ❌ ${label}`); console.error(` erwartet: ${JSON.stringify(expected)}`); console.error(` erhalten: ${JSON.stringify(actual)}`); failed++; } } // ── normalizeForComparison ──────────────────────────────────────────────────── console.log("\nnormalizeForComparison()"); expect(normalizeForComparison(" Foo Bar "), "foo bar", "trimmt führende/nachfolgende Leerzeichen"); expect(normalizeForComparison("Foo.\n"), "foo", "entfernt trailing Punkt + Newline"); expect(normalizeForComparison("A B"), "a b", "kollabiert mehrfache Leerzeichen"); expect(normalizeForComparison("Foo:"), "foo", "entfernt trailing Doppelpunkt"); expect(normalizeForComparison("Foo;"), "foo", "entfernt trailing Semikolon"); expect(normalizeForComparison("Foo!"), "foo", "entfernt trailing Ausrufezeichen"); expect(normalizeForComparison("Foo?"), "foo", "entfernt trailing Fragezeichen"); expect(normalizeForComparison("UPPER CASE"), "upper case", "konvertiert zu Kleinbuchstaben"); // Loop-Detection: gleiche Blocker nach Normalisierung erkannt expect( normalizeForComparison("missing error handling.") === normalizeForComparison("missing error handling"), true, "Loop-Detection: trailing Punkt macht keinen Unterschied" ); expect( normalizeForComparison("null check missing\n") === normalizeForComparison("null check missing"), true, "Loop-Detection: Newline am Ende macht keinen Unterschied" ); expect( normalizeForComparison("Fehler bei Import.") === normalizeForComparison("Fehler bei Import"), true, "Loop-Detection: mehrfache Leerzeichen + Punkt machen keinen Unterschied" ); expect( normalizeForComparison("Blocker A") === normalizeForComparison("Blocker B"), false, "Loop-Detection: verschiedene Blocker werden NICHT als gleich erkannt" ); // ── parseVerdict ────────────────────────────────────────────────────────────── console.log("\nparseVerdict()"); expect(parseVerdict("Urteil: PASS"), "PASS", "erkennt PASS"); expect(parseVerdict("Urteil: PASS WITH CONCERNS"), "PASS WITH CONCERNS", "erkennt PASS WITH CONCERNS (vor PASS gematcht)"); expect(parseVerdict("Urteil: FAIL"), "FAIL", "erkennt FAIL"); expect(parseVerdict("kein Urteil hier"), "UNREADABLE", "gibt UNREADABLE zurück wenn kein Urteil"); expect(parseVerdict("urteil: pass"), "PASS", "case-insensitiv: 'urteil: pass'"); expect(parseVerdict("urteil: Pass With Concerns"), "PASS WITH CONCERNS", "case-insensitiv: gemischte Groß-/Kleinschreibung"); expect(parseVerdict("Das ist mein Urteil: PASS — und mehr Text dahinter"), "PASS", "ignoriert Text nach dem Urteil"); expect(parseVerdict("Urteil:PASS"), "PASS", "toleriert fehlenden Leerzeichen nach Doppelpunkt"); expect(parseVerdict(""), "UNREADABLE", "leerer String → UNREADABLE"); // ── parseBlockers ───────────────────────────────────────────────────────────── console.log("\nparseBlockers()"); expect( parseBlockers("**Blocker**:\n- fehlende Validierung\n**Major**:\n- anderes Problem"), "- fehlende Validierung", "erkennt **Blocker** mit Bold-Syntax" ); expect( parseBlockers("## Blocker\nNull-Check fehlt\n## Major\nanderes"), "Null-Check fehlt", "erkennt ## Blocker mit Heading-Syntax" ); expect( parseBlockers("- Blocker:\n- fehlender Import\n- Minor:\n- Stil"), "- fehlender Import", "erkennt - Blocker mit Bullet-Syntax" ); expect( parseBlockers("– Blocker\nKein Logging\n- Minor\nKleinigkeit"), "Kein Logging", "erkennt – Blocker (Gedankenstrich)" ); expect( parseBlockers("Urteil: PASS\n\nAlles ok."), "", "gibt leeren String zurück wenn kein Blocker-Abschnitt" ); expect( parseBlockers("**Blocker**:\nkeine\n**Minor**:\n- Stil"), "keine", "extrahiert 'keine' als Blocker-Text" ); // Mehrzeiliger Blocker const multilineInput = `**Blocker**: - Import fehlt - Funktion nicht definiert **Major**: - weitere Sache`; const multilineResult = parseBlockers(multilineInput); expect( multilineResult.includes("Import fehlt") && multilineResult.includes("Funktion nicht definiert"), true, "extrahiert mehrzeiligen Blocker vollständig" ); // ── Ergebnis ────────────────────────────────────────────────────────────────── console.log(`\n${"─".repeat(50)}`); console.log(`Gesamt: ${passed + failed} Tests — ${passed} bestanden, ${failed} fehlgeschlagen`); if (failed > 0) { process.exit(1); }