49 lines
2.1 KiB
TypeScript
49 lines
2.1 KiB
TypeScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import { fileURLToPath } from "node:url";
|
|
import { dirname, resolve } from "node:path";
|
|
|
|
// Regression guard for #5991 — clicking "Update now" showed an "Internal Server
|
|
// Error" screen (Minified React error #31). The handler POSTs /api/system/version
|
|
// (a loopback-only auto-update endpoint) and, on a non-OK JSON response, did:
|
|
// notify.error(data.error || "Failed to start update.");
|
|
// OmniRoute's error envelope is `{ error: { code, message, correlation_id } }`, so
|
|
// `data.error` is an OBJECT. notify.error rendered that object as a React child →
|
|
// React #31 crash. The fix funnels the body through extractApiErrorMessage() (the
|
|
// same helper introduced in #5340) so a string always reaches the toast.
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
const source = readFileSync(
|
|
resolve(here, "../../../src/app/(dashboard)/dashboard/HomePageClient.tsx"),
|
|
"utf8"
|
|
);
|
|
|
|
test("HomePageClient imports the safe API error extractor", () => {
|
|
assert.match(
|
|
source,
|
|
/import\s*\{\s*extractApiErrorMessage\s*\}\s*from\s*["']@\/shared\/http\/apiErrorMessage["']/,
|
|
"HomePageClient must import extractApiErrorMessage to render API errors safely (#5991)"
|
|
);
|
|
});
|
|
|
|
test("the update-error handler funnels the body through extractApiErrorMessage (#5991)", () => {
|
|
// The update failure path must extract a string, not hand the raw envelope object
|
|
// (which triggers React #31) to notify.error.
|
|
assert.match(
|
|
source,
|
|
/notify\.error\(\s*extractApiErrorMessage\(\s*data\s*,/,
|
|
"the update-error notify.error must use extractApiErrorMessage(data, …) (#5991)"
|
|
);
|
|
});
|
|
|
|
test("the update-error handler never passes the raw error object to notify.error (#5991)", () => {
|
|
// The pre-fix pattern `notify.error(data.error || …)` rendered an object as a React
|
|
// child. It must not come back.
|
|
assert.doesNotMatch(
|
|
source,
|
|
/notify\.error\(\s*data\.error\b/,
|
|
"notify.error(data.error …) renders the error envelope object as a React child → React #31 (#5991)"
|
|
);
|
|
});
|