AUDIT / src /lib /__tests__ /adaptiveSolver.test.ts
Arypulka98's picture
feat(audit): deploy full backend cluster node (part 2)
cc11e77 verified
Raw
History Blame Contribute Delete
6.83 kB
/**
* adaptiveSolver.test.ts — Unit test AdaptiveSolver (S50)
*
* Copre:
* - detectBlockade: 9 tipi di blocco + unknown
* - strategiesFor: listing per kind
* - solve: DI mock, ogni strategia testata in isolamento
*
* Zero vi.mock su Dexie/vfs — usa _setTestDeps() per DI pura.
*/
import { describe, it, expect, beforeEach } from "vitest";
import { detectBlockade, adaptiveSolver, _setTestDeps } from "../adaptiveSolver";
// ─── detectBlockade ───────────────────────────────────────────────────────────
describe("detectBlockade", () => {
it("rileva cors", () => {
expect(detectBlockade("CORS error: blocked by CORS policy").kind).toBe("cors");
});
it("rileva not_found da 404", () => {
expect(detectBlockade("404 not found: /pages/app.html").kind).toBe("not_found");
});
it("rileva not_found da ENOENT", () => {
expect(detectBlockade("ENOENT: no such file or directory").kind).toBe("not_found");
});
it("rileva rate_limit", () => {
expect(detectBlockade("429 Too Many Requests").kind).toBe("rate_limit");
});
it("rileva permission da 403", () => {
expect(detectBlockade("403 Forbidden: access denied").kind).toBe("permission");
});
it("rileva timeout", () => {
expect(detectBlockade("Request timed out after 5000ms").kind).toBe("timeout");
});
it("rileva quota", () => {
expect(detectBlockade("QuotaExceededError: storage full").kind).toBe("quota");
});
it("rileva syntax", () => {
expect(detectBlockade("SyntaxError: Unexpected token {").kind).toBe("syntax");
});
it("rileva network", () => {
expect(detectBlockade("TypeError: Failed to fetch").kind).toBe("network");
});
it("unknown per errori non classificati", () => {
expect(detectBlockade("something weird happened xyz").kind).toBe("unknown");
});
it("include il messaggio originale e hint leggibile", () => {
const b = detectBlockade("CORS blocked by browser");
expect(b.message).toContain("CORS");
expect(b.hint.length).toBeGreaterThan(0);
});
it("tronca messaggi molto lunghi a 300 chars", () => {
const long = "network error " + "x".repeat(500);
expect(detectBlockade(long).message.length).toBeLessThanOrEqual(300);
});
});
// ─── strategiesFor ────────────────────────────────────────────────────────────
describe("adaptiveSolver.strategiesFor", () => {
it("restituisce strategie per cors", () => {
expect(adaptiveSolver.strategiesFor("cors").length).toBeGreaterThan(0);
});
it("restituisce strategie per not_found", () => {
expect(adaptiveSolver.strategiesFor("not_found").length).toBeGreaterThan(0);
});
it("restituisce strategie per permission", () => {
expect(adaptiveSolver.strategiesFor("permission").length).toBeGreaterThan(0);
});
it("restituisce array vuoto per unknown", () => {
expect(adaptiveSolver.strategiesFor("unknown").length).toBe(0);
});
});
// ─── solve ────────────────────────────────────────────────────────────────────
describe("adaptiveSolver.solve", () => {
beforeEach(() => {
_setTestDeps({
vfsListFn: () => [
{ path: "/pages/app.html", content: "<html>test</html>" },
{ path: "/scripts/main.js", content: 'console.log("hello")' },
],
memorySetFn: () => {},
fetchFn: async (url: string) => {
if (url.includes("allorigins")) {
return new Response(
JSON.stringify({ contents: "proxied content ok — risposta dal proxy CORS automatico" }),
{ status: 200 },
);
}
return new Response("ok response from server", { status: 200 });
},
waitFn: async () => {},
});
});
it("unknown error → strategy none, success false", async () => {
const r = await adaptiveSolver.solve("something totally unrecognized xyz 123");
expect(r.success).toBe(false);
expect(r.strategy).toBe("none");
});
it("CORS error → cors_proxy → success true", async () => {
const r = await adaptiveSolver.solve(
"CORS blocked",
'fetch("https://api.example.com/data")',
);
expect(r.strategy).toBe("cors_proxy");
expect(r.success).toBe(true);
expect(r.output).toContain("proxy CORS");
});
it("not_found → file_fuzzy trova file esistente", async () => {
const r = await adaptiveSolver.solve(
"404 not found",
'read_file("/pages/app.html")',
);
expect(r.strategy).toBe("file_fuzzy");
expect(r.output).toContain("trovato");
expect(r.success).toBe(true);
});
it("not_found → file non esistente → elenca disponibili", async () => {
const r = await adaptiveSolver.solve(
"404 not found",
'read_file("/missing/ghost.ts")',
);
expect(r.strategy).toBe("file_fuzzy");
expect(r.output).toContain("File disponibili");
expect(r.success).toBe(false);
});
it("permission + contesto push → permission_rest con hint REST", async () => {
const r = await adaptiveSolver.solve(
"403 Forbidden: access denied",
"push to remote",
"push bloccato",
);
expect(r.strategy).toBe("permission_rest");
expect(r.output).toContain("REST");
});
it("syntax error → syntax_hint con analisi riga", async () => {
const r = await adaptiveSolver.solve(
"SyntaxError: Unexpected token { at line 3",
"line1\nline2\nlet { broken",
);
expect(r.strategy).toBe("syntax_hint");
expect(r.output).toContain("sintattico");
});
it("quota + input piccolo → chunk_payload non applicabile → exhausted", async () => {
const r = await adaptiveSolver.solve("QuotaExceededError: storage full", "small input");
expect(r.strategy).toBe("exhausted");
});
it("quota + input grande → chunk_payload applicabile", async () => {
const bigInput = "x".repeat(6000);
const r = await adaptiveSolver.solve("QuotaExceededError: storage full", bigInput);
expect(r.strategy).toBe("chunk_payload");
expect(r.output).toContain("chunk");
});
it("description sempre leggibile con freccia", async () => {
const r = await adaptiveSolver.solve(
"CORS blocked",
'fetch("https://x.com")',
);
expect(r.description).toContain("→");
expect(r.description.length).toBeGreaterThan(10);
});
it("CORS senza URL → nessun proxy possibile → exhausted", async () => {
const r = await adaptiveSolver.solve("CORS blocked", "nessun url qui");
expect(r.strategy).toBe("exhausted");
});
});