42 lines
1.5 KiB
TypeScript
42 lines
1.5 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { createServerIssue, issueFromError } from "../../src/server/issues.ts";
|
|
|
|
test("server issues have stable fingerprints and retain actionable error context", () => {
|
|
const input = {
|
|
ruleId: "server/query",
|
|
category: "server" as const,
|
|
severity: "warning" as const,
|
|
title: "Slow query",
|
|
message: "Query exceeded budget",
|
|
pathname: "/orders",
|
|
source: { file: "app/api/orders.ts", line: 12, column: 4 },
|
|
};
|
|
const first = createServerIssue(input);
|
|
const second = createServerIssue(input);
|
|
expect(first.id).not.toBe(second.id);
|
|
expect(first.fingerprint).toBe(second.fingerprint);
|
|
expect(first.metadata?.pathname).toBe("/orders");
|
|
|
|
const error = issueFromError(new Error("database offline"), { pathname: "/orders" });
|
|
expect(error.severity).toBe("error");
|
|
expect(error.message).toBe("database offline");
|
|
expect(error.metadata?.stack).toContain("database offline");
|
|
expect(error.recommendation).toContain("stack trace");
|
|
});
|
|
|
|
test("non-Error throws are normalized without losing caller context", () => {
|
|
const issue = issueFromError(
|
|
{ reason: "offline" },
|
|
{
|
|
ruleId: "server/dependency",
|
|
title: "Dependency failed",
|
|
pathname: "/health",
|
|
source: { file: "app/api/health.ts", line: 4 },
|
|
},
|
|
);
|
|
expect(issue.ruleId).toBe("server/dependency");
|
|
expect(issue.title).toBe("Dependency failed");
|
|
expect(issue.message).toBe("[object Object]");
|
|
expect(issue.fingerprint).toContain("app/api/health.ts:4:0");
|
|
});
|