Files
OmniRoute/tests/unit/fetch-error-message.test.ts
Diego Rodrigues de Sa e Souza c8031be906 fix(dashboard): surface real analytics error instead of generic placeholder (#3356) (#3361)
The Analytics page discarded the server's error body on a non-OK response and
rendered a generic "An error occurred", so users (and maintainers) could not see
why /api/usage/analytics 500'd after an upgrade. Now the route returns the real
reason via buildErrorBody (sanitized, Hard Rule #12) and the page surfaces it via
a new readFetchErrorMessage helper that handles both the OpenAI-style and legacy
error shapes.

Reported-by: @superti4r
2026-06-07 07:15:42 -03:00

48 lines
1.9 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import { readFetchErrorMessage } from "../../src/shared/utils/fetchError.ts";
const FALLBACK = "An error occurred";
function jsonResponse(body: unknown, status = 500) {
return new Response(JSON.stringify(body), {
status,
headers: { "Content-Type": "application/json" },
});
}
// #3356: the Analytics page rendered a generic "An error occurred" because it
// discarded the server's error body. The page must surface the real (already
// sanitized server-side) message instead.
test("reads the OpenAI-style { error: { message } } shape from buildErrorBody", async () => {
const res = jsonResponse({ error: { message: "Failed to compute analytics", type: "api_error" } });
assert.equal(await readFetchErrorMessage(res, FALLBACK), "Failed to compute analytics");
});
test("reads the legacy { error: '...' } string shape", async () => {
const res = jsonResponse({ error: "no such column: combo_name" });
assert.equal(await readFetchErrorMessage(res, FALLBACK), "no such column: combo_name");
});
test("trims surrounding whitespace from the extracted message", async () => {
const res = jsonResponse({ error: { message: " boom " } });
assert.equal(await readFetchErrorMessage(res, FALLBACK), "boom");
});
test("falls back when the error message is blank", async () => {
const res = jsonResponse({ error: { message: " " } });
assert.equal(await readFetchErrorMessage(res, FALLBACK), FALLBACK);
});
test("falls back when there is no error field", async () => {
const res = jsonResponse({ data: 1 });
assert.equal(await readFetchErrorMessage(res, FALLBACK), FALLBACK);
});
test("falls back on a non-JSON body without throwing", async () => {
const res = new Response("<html>500 Internal Server Error</html>", { status: 500 });
assert.equal(await readFetchErrorMessage(res, FALLBACK), FALLBACK);
});