mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-28 21:44:38 +00:00
89 lines
2.9 KiB
JavaScript
89 lines
2.9 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
getMockServerPort,
|
|
resetMockBehavior,
|
|
setMockBehavior,
|
|
startMockServer,
|
|
stopMockServer,
|
|
} from "./index.mjs";
|
|
|
|
// Chaos-toolkit coverage for the mock backend's httpFaultRules engine
|
|
// (plan.md §5.3). Beyond clean HTTP error statuses, authors need to reproduce
|
|
// two real outage shapes: a connection reset mid-response, and a 200 with a
|
|
// non-JSON body. These tests drive the real server over a socket.
|
|
|
|
function base() {
|
|
const port = getMockServerPort();
|
|
assert.ok(port, "mock server must be running");
|
|
return `http://127.0.0.1:${port}`;
|
|
}
|
|
|
|
function setFaultRules(rules) {
|
|
setMockBehavior("httpFaultRules", JSON.stringify(rules));
|
|
}
|
|
|
|
test.beforeEach(async () => {
|
|
await stopMockServer();
|
|
resetMockBehavior();
|
|
await startMockServer();
|
|
});
|
|
|
|
test.afterEach(async () => {
|
|
await stopMockServer();
|
|
});
|
|
|
|
test("mode:reset tears down the connection (client sees a network error)", async () => {
|
|
setFaultRules([{ contains: "/chaos-reset", mode: "reset" }]);
|
|
|
|
await assert.rejects(
|
|
fetch(`${base()}/chaos-reset`),
|
|
(err) => err instanceof TypeError || /reset|hang up|ECONNRESET|fetch failed/i.test(String(err)),
|
|
"a reset rule must surface as a client-side network error, not a clean response",
|
|
);
|
|
});
|
|
|
|
test("mode:malformed returns a 200 with a body that is not valid JSON", async () => {
|
|
setFaultRules([{ contains: "/chaos-malformed", mode: "malformed" }]);
|
|
|
|
const res = await fetch(`${base()}/chaos-malformed`);
|
|
assert.equal(res.status, 200, "malformed mode defaults to a 200 status");
|
|
|
|
const text = await res.text();
|
|
assert.ok(text.length > 0, "malformed body must be non-empty");
|
|
assert.throws(
|
|
() => JSON.parse(text),
|
|
"the malformed body must not parse as JSON (that is the whole point)",
|
|
);
|
|
});
|
|
|
|
test("mode:malformed honours a custom status and body override", async () => {
|
|
setFaultRules([
|
|
{ contains: "/chaos-custom", mode: "malformed", status: 502, body: "upstream said <html>" },
|
|
]);
|
|
|
|
const res = await fetch(`${base()}/chaos-custom`);
|
|
assert.equal(res.status, 502);
|
|
assert.equal(await res.text(), "upstream said <html>");
|
|
});
|
|
|
|
test("default mode still injects a clean HTTP error status + JSON envelope", async () => {
|
|
// Regression guard: adding chaos modes must not change the existing
|
|
// status-injection behaviour when no mode is set.
|
|
setFaultRules([{ contains: "/chaos-status", status: 503, error: "down for maintenance" }]);
|
|
|
|
const res = await fetch(`${base()}/chaos-status`);
|
|
assert.equal(res.status, 503);
|
|
const parsed = await res.json();
|
|
assert.equal(parsed.success, false);
|
|
assert.equal(parsed.error, "down for maintenance");
|
|
});
|
|
|
|
test("a request that matches no fault rule is unaffected", async () => {
|
|
setFaultRules([{ contains: "/chaos-reset", mode: "reset" }]);
|
|
|
|
const res = await fetch(`${base()}/__admin/health`);
|
|
assert.equal(res.status, 200, "unmatched requests must pass through to the real handler");
|
|
});
|