Spaces:
Sleeping
Sleeping
| /** | |
| * confidenceEngine.test.ts — Unit test S39 ConfidenceEngine | |
| * | |
| * Copertura (12 test): | |
| * 1. score iniziale 0.5 → level=medium | |
| * 2. recordSignal tool_success → score aumenta | |
| * 3. recordSignal tool_failure → score diminuisce | |
| * 4. build_ok → grande aumento score | |
| * 5. build_fail_serious → grande calo score | |
| * 6. shouldEscalate: true sotto soglia 0.35 | |
| * 7. shouldClose: true sopra soglia 0.72 | |
| * 8. reset: ritorna a score iniziale | |
| * 9. summary: stringa leggibile con score e conteggi | |
| * 10. classifyBuildFailure: "cannot find module" → serious | |
| * 11. classifyBuildFailure: singolo TS error → trivial | |
| * 12. buildFailureSignal mappa correttamente a kind | |
| * 13. DI _setTestDeps: now() mock | |
| * 14. score clampato tra 0 e 1 | |
| * | |
| * SESSIONE: S39 — TaskClassifier + ConfidenceEngine + RequestEnhancer | |
| */ | |
| import { describe, it, expect, beforeEach, afterEach } from "vitest"; | |
| import { | |
| ConfidenceSession, | |
| createConfidenceSession, | |
| classifyBuildFailure, | |
| buildFailureSignal, | |
| getThresholds, | |
| _setTestDeps, | |
| _resetDeps, | |
| } from "@/lib/confidenceEngine"; | |
| afterEach(() => { | |
| _resetDeps(); | |
| }); | |
| // ─── ConfidenceSession ──────────────────────────────────────────────────────── | |
| describe("ConfidenceSession", () => { | |
| it("1. score iniziale 0.5 → level=medium", () => { | |
| const s = createConfidenceSession("task-1"); | |
| expect(s.getScore()).toBeCloseTo(0.5); | |
| expect(s.getLevel()).toBe("medium"); | |
| }); | |
| it("2. tool_success → score aumenta", () => { | |
| const s = createConfidenceSession("task-2"); | |
| const before = s.getScore(); | |
| s.recordSignal("tool_success"); | |
| expect(s.getScore()).toBeGreaterThan(before); | |
| }); | |
| it("3. tool_failure → score diminuisce", () => { | |
| const s = createConfidenceSession("task-3"); | |
| const before = s.getScore(); | |
| s.recordSignal("tool_failure"); | |
| expect(s.getScore()).toBeLessThan(before); | |
| }); | |
| it("4. build_ok → aumento significativo score", () => { | |
| const s = createConfidenceSession("task-4", 0.4); | |
| s.recordSignal("build_ok"); | |
| expect(s.getScore()).toBeGreaterThan(0.55); | |
| }); | |
| it("5. build_fail_serious → calo drastico score", () => { | |
| const s = createConfidenceSession("task-5", 0.7); | |
| s.recordSignal("build_fail_serious"); | |
| expect(s.getScore()).toBeLessThan(0.45); | |
| }); | |
| it("6. shouldEscalate: true dopo segnali negativi gravi", () => { | |
| const s = createConfidenceSession("task-6", 0.5); | |
| s.recordSignal("build_fail_serious"); | |
| s.recordSignal("llm_refusal"); | |
| expect(s.shouldEscalate()).toBe(true); | |
| }); | |
| it("7. shouldClose: true dopo segnali positivi", () => { | |
| const s = createConfidenceSession("task-7", 0.6); | |
| s.recordSignal("build_ok"); | |
| s.recordSignal("user_confirm"); | |
| expect(s.shouldClose()).toBe(true); | |
| }); | |
| it("8. reset: ritorna allo score iniziale e svuota segnali", () => { | |
| const s = createConfidenceSession("task-8", 0.5); | |
| s.recordSignal("build_fail_serious"); | |
| s.recordSignal("tool_failure"); | |
| s.reset(); | |
| expect(s.getScore()).toBeCloseTo(0.5); | |
| expect(s.getState().signals).toHaveLength(0); | |
| }); | |
| it("9. summary: stringa che include score e conteggi segnali", () => { | |
| const s = createConfidenceSession("task-9"); | |
| s.recordSignal("tool_success"); | |
| s.recordSignal("tool_failure"); | |
| const sum = s.summary(); | |
| expect(sum).toContain("%"); | |
| expect(sum).toContain("+1"); | |
| expect(sum).toContain("-1"); | |
| }); | |
| it("14. score clampato tra 0 e 1 anche con molti segnali negativi", () => { | |
| const s = createConfidenceSession("task-14", 0.1); | |
| for (let i = 0; i < 10; i++) s.recordSignal("build_fail_serious"); | |
| expect(s.getScore()).toBeGreaterThanOrEqual(0); | |
| expect(s.getScore()).toBeLessThanOrEqual(1); | |
| }); | |
| it("14b. score clampato tra 0 e 1 anche con molti segnali positivi", () => { | |
| const s = createConfidenceSession("task-14b", 0.9); | |
| for (let i = 0; i < 10; i++) s.recordSignal("build_ok"); | |
| expect(s.getScore()).toBeGreaterThanOrEqual(0); | |
| expect(s.getScore()).toBeLessThanOrEqual(1); | |
| }); | |
| }); | |
| // ─── classifyBuildFailure ───────────────────────────────────────────────────── | |
| describe("classifyBuildFailure", () => { | |
| it("10. 'cannot find module' → serious", () => { | |
| expect(classifyBuildFailure("Error: Cannot find module './foo'")).toBe("serious"); | |
| }); | |
| it("10b. molti errori → serious", () => { | |
| expect(classifyBuildFailure("27 errors found in build")).toBe("serious"); | |
| }); | |
| it("10c. dipendenza mancante → serious", () => { | |
| expect(classifyBuildFailure("Failed to resolve import 'react' from 'src/main.tsx'")).toBe("serious"); | |
| }); | |
| it("11. singolo errore TypeScript banale → trivial", () => { | |
| expect(classifyBuildFailure("TS2345: Argument of type 'string' is not assignable to 'number'")).toBe("trivial"); | |
| }); | |
| it("11b. errore di variabile non usata → trivial", () => { | |
| expect(classifyBuildFailure("warning: unused variable 'foo'")).toBe("trivial"); | |
| }); | |
| }); | |
| // ─── buildFailureSignal ─────────────────────────────────────────────────────── | |
| describe("buildFailureSignal", () => { | |
| it("12. errore serio → 'build_fail_serious'", () => { | |
| expect(buildFailureSignal("Cannot find module './auth'")).toBe("build_fail_serious"); | |
| }); | |
| it("12b. errore banale → 'build_fail_trivial'", () => { | |
| expect(buildFailureSignal("TS1005: ';' expected")).toBe("build_fail_trivial"); | |
| }); | |
| }); | |
| // ─── DI _setTestDeps ───────────────────────────────────────────────────────── | |
| describe("DI _setTestDeps", () => { | |
| it("13. now() mock è usato in recordSignal", () => { | |
| let t = 1000; | |
| _setTestDeps({ now: () => t }); | |
| const s = createConfidenceSession("task-di"); | |
| s.recordSignal("tool_success"); | |
| const sig = s.getState().signals[0]; | |
| expect(sig.at).toBe(1000); | |
| }); | |
| }); | |
| // ─── getThresholds ──────────────────────────────────────────────────────────── | |
| describe("getThresholds", () => { | |
| it("ritorna tutte le soglie operative", () => { | |
| const t = getThresholds(); | |
| expect(t.high).toBeGreaterThan(t.medium); | |
| expect(t.medium).toBeGreaterThan(t.low); | |
| expect(t.escalate).toBeGreaterThan(0); | |
| expect(t.close).toBeGreaterThan(t.escalate); | |
| }); | |
| }); | |