146 lines
4.3 KiB
TypeScript
146 lines
4.3 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import test from "node:test";
|
|
|
|
const source = async (relativePath: string) => {
|
|
return await readFile(
|
|
join(process.cwd(), ...relativePath.split("/")),
|
|
"utf8",
|
|
);
|
|
};
|
|
|
|
function extractExportSource(sourceText: string, name: string) {
|
|
const marker = `export const ${name} = `;
|
|
const declarationIndex = sourceText.indexOf(marker);
|
|
assert.notEqual(declarationIndex, -1, `Expected declaration for ${name}.`);
|
|
|
|
const openBraceIndex = sourceText.indexOf("{", declarationIndex);
|
|
let depth = 0;
|
|
let end = -1;
|
|
|
|
for (let index = openBraceIndex; index < sourceText.length; index += 1) {
|
|
const char = sourceText[index];
|
|
if (char === "{") {
|
|
depth += 1;
|
|
} else if (char === "}") {
|
|
depth -= 1;
|
|
if (depth === 0) {
|
|
end = index;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
assert.notEqual(end, -1, `Expected balanced braces for ${name}.`);
|
|
return sourceText.slice(openBraceIndex, end + 1);
|
|
}
|
|
|
|
test("audits dashboard query combines final audits with generation runs", async () => {
|
|
const auditsSource = await source("convex/audits.ts");
|
|
const querySource = extractExportSource(auditsSource, "listDashboardRows");
|
|
|
|
assert.match(
|
|
auditsSource,
|
|
/export const listDashboardRows = query/,
|
|
"Dashboard rows should be exposed as a public Convex query.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/requireOperator\(ctx\)/,
|
|
"Dashboard rows should require an authenticated operator.",
|
|
);
|
|
assert.match(
|
|
auditsSource,
|
|
/ctx\.auth\.getUserIdentity\(\)/,
|
|
"Operator checks should derive identity from Convex auth.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/kind:\s*"audit"/,
|
|
"Final audit documents should be returned as audit rows.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/kind:\s*"generation"/,
|
|
"Audit generation runs should be returned as generation rows.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/\.query\("audits"\)/,
|
|
"Dashboard rows should read finalized audits.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/\.query\("agentRuns"\)[\s\S]*\.withIndex\("by_type"/,
|
|
"Dashboard rows should read audit_generation runs through the type index.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/\.query\("auditGenerations"\)[\s\S]*\.withIndex\("by_runId"/,
|
|
"Dashboard rows should load generation stages by run id.",
|
|
);
|
|
});
|
|
|
|
test("audits dashboard query suppresses generation rows once a final audit exists", async () => {
|
|
const auditsSource = await source("convex/audits.ts");
|
|
const querySource = extractExportSource(auditsSource, "listDashboardRows");
|
|
|
|
assert.match(
|
|
querySource,
|
|
/finalAuditRunIds/,
|
|
"Query should track run ids that already have finalized audits.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/finalAuditLeadIds/,
|
|
"Query should track lead ids that already have finalized audits.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/\.query\("audits"\)[\s\S]*\.withIndex\("by_leadId"/,
|
|
"Query should suppress generation rows even when the finalized audit is outside the fetched dashboard page.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/ctx\.db\.get\(run\.auditId\)/,
|
|
"Query should suppress generation rows that directly reference an existing audit.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/continue/,
|
|
"Query should skip duplicate generation rows instead of returning them.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/latestStage/,
|
|
"Generation rows should surface the latest generation stage.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/errorSummary/,
|
|
"Generation rows should surface run or stage errors.",
|
|
);
|
|
});
|
|
|
|
test("audits dashboard query hides child generation rows behind root audit runs", async () => {
|
|
const auditsSource = await source("convex/audits.ts");
|
|
const querySource = extractExportSource(auditsSource, "listDashboardRows");
|
|
|
|
assert.match(
|
|
querySource,
|
|
/rootAuditRunLeadIds/,
|
|
"Query should track lead ids that already have root audit runs.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/run\.type\s*===\s*"audit_generation"[\s\S]*rootAuditRunLeadIds\.has\(run\.leadId\)/,
|
|
"Child audit_generation rows should be skipped when a root audit run for the same lead is already visible.",
|
|
);
|
|
assert.match(
|
|
querySource,
|
|
/continue/,
|
|
"Child generation rows should be skipped instead of rendered as a duplicate card.",
|
|
);
|
|
});
|