test: enhance ai_generate_plan test for structured data validation and normalization

This commit is contained in:
2026-01-16 11:04:28 -06:00
parent e321935286
commit 6c2faa97f1
@@ -45,46 +45,54 @@ async function getAuthedClient(): Promise<
return { client, accessToken }; return { client, accessToken };
} }
Deno.test("ai-generate-plan (JSON body)", async () => { Deno.test("ai_generate_plan creates plan and returns structured data", async () => {
const { client, accessToken } = await getAuthedClient(); const { client, accessToken } = await getAuthedClient();
// Get any carrera
const { data: carrera, error: carreraError } = await client const { data: carrera, error: carreraError } = await client
.from("carreras") .from("carreras")
.select("id").limit(1).single(); .select("id")
if (carreraError) { .limit(1)
throw new Error("Failed to fetch carrera: " + carreraError.message); .single();
} if (carreraError) throw new Error("Failed to fetch carrera: " + carreraError.message);
if (!carrera) throw new Error("No carrera found"); if (!carrera) throw new Error("No carrera found");
// datosBasicos (nombrePlan,carreraId,nivel,tipoCiclo,numCiclos)
const datosBasicos = { const datosBasicos = {
nombrePlan: "Plan de estudios de Ingeniería en Sistemas Computacionales", nombrePlan: "Plan de estudios de Ingeniería en Sistemas Computacionales",
carreraId: carrera.id, carreraId: carrera.id,
nivel: "Licenciatura", nivel: "Licenciatura",
tipoCiclo: "Semestral", tipoCiclo: "Semestre", // important: normalizes to "Semestre"
numCiclos: 8, numCiclos: 8,
}; };
const { data, error } = await client.functions.invoke("ai_generate_plan", { const { data, error } = await client.functions.invoke("ai_generate_plan", {
headers: { headers: {
Authorization: `Bearer ${accessToken}`, // 👈 clave para que tu función pase el authHeader check Authorization: `Bearer ${accessToken}`,
},
body: {
datosBasicos,
}, },
body: { datosBasicos },
}); });
if (error) throw new Error("Invoke failed: " + error.message); if (error) throw new Error("Invoke failed: " + error.message);
assert(data, "Expected data from function"); assert(data, "Expected data from function");
// tu función responde { ok, output, outputText, ... } // Top-level result
assertEquals(data.ok, true); assertEquals(data.ok, true);
assert(data.plan);
assertEquals(data.output.ideas.length, 3); // `plan` (DB record)
for (const it of data.output.ideas) { assert(typeof data.plan?.id === "string");
assert(typeof it.titulo === "string"); assertEquals(data.plan.nombre, datosBasicos.nombrePlan);
assert(typeof it.descripcion === "string"); assertEquals(data.plan.nivel, "Licenciatura");
} assertEquals(data.plan.tipo_ciclo, "Semestre");
assertEquals(data.plan.numero_ciclos, datosBasicos.numCiclos);
// `plan_datos` (normalized structured payload)
assert(typeof data.plan_datos === "object");
assertEquals(data.plan_datos.nombre, datosBasicos.nombrePlan);
assertEquals(data.plan_datos.nivel, "Licenciatura");
assertEquals(
data.plan_datos.total_de_ciclos_del_plan_de_estudios,
String(datosBasicos.numCiclos),
);
assertEquals(data.plan_datos.duracion_del_ciclo_escolar, "16"); // Semestre -> 16
}); });
/* /*
Deno.test("ai-structured (multipart + file)", async () => { Deno.test("ai-structured (multipart + file)", async () => {