40467-vm/backend/test/readOnlyDemo.test.js
2026-07-22 16:45:10 +00:00

77 lines
2.2 KiB
JavaScript

const assert = require("node:assert/strict");
const test = require("node:test");
const { enforceReadOnlyDemo } = require("../src/security/readOnlyDemo");
function response() {
return {
body: null,
statusCode: null,
status(code) {
this.statusCode = code;
return this;
},
send(body) {
this.body = body;
return this;
},
};
}
function run(request) {
const res = response();
let nextCalled = false;
enforceReadOnlyDemo(request, res, () => {
nextCalled = true;
});
return { nextCalled, res };
}
test("demo mode allows reads and login", () => {
const previous = process.env.DEMO_MODE;
process.env.DEMO_MODE = "true";
try {
assert.equal(run({ method: "GET", path: "/api/coaching/clients" }).nextCalled, true);
assert.equal(run({ method: "POST", path: "/api/auth/signin/local" }).nextCalled, true);
assert.equal(run({ method: "POST", path: "/api/auth/signin/demo" }).nextCalled, true);
} finally {
process.env.DEMO_MODE = previous;
}
});
test("demo mode blocks persistent and costly operations", () => {
const previous = process.env.DEMO_MODE;
process.env.DEMO_MODE = "true";
try {
for (const request of [
{ method: "POST", path: "/api/coaching/clients" },
{ method: "PATCH", path: "/api/coaching/sessions/id/share" },
{ method: "DELETE", path: "/api/coaching/sessions/id" },
{ method: "POST", path: "/api/ai/response" },
{ method: "POST", path: "/api/coaching/session-memory/transcribe" },
{ method: "PUT", path: "/api/auth/password-update" },
]) {
const result = run(request);
assert.equal(result.nextCalled, false, `${request.method} ${request.path}`);
assert.equal(result.res.statusCode, 403, `${request.method} ${request.path}`);
assert.equal(result.res.body.error, "demo_read_only", `${request.method} ${request.path}`);
}
} finally {
process.env.DEMO_MODE = previous;
}
});
test("writes remain available outside demo mode", () => {
const previous = process.env.DEMO_MODE;
process.env.DEMO_MODE = "false";
try {
assert.equal(run({ method: "POST", path: "/api/coaching/clients" }).nextCalled, true);
} finally {
process.env.DEMO_MODE = previous;
}
});