193 lines
6.2 KiB
TypeScript
193 lines
6.2 KiB
TypeScript
|
|
// 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);
|
|||
|
|
}
|