CI (SIAX Cloud) / integration (push) Skipped
CI (SIAX Cloud) / sonar (push) Skipped
masterplan-lock / check (push) Successful in 10s
CI (SIAX Cloud) / sonar (pull_request) Skipped
Security Scan (SIAX Cloud) / security (push) Successful in 13s
masterplan-lock / check (pull_request) Successful in 7s
CI (SIAX Cloud) / security (push) Successful in 26s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 17s
CI (SIAX Cloud) / security (pull_request) Successful in 19s
CI (SIAX Cloud) / quality (push) Successful in 1m9s
CI (SIAX Cloud) / quality (pull_request) Successful in 2m26s
CI (SIAX Cloud) / integration (pull_request) Successful in 2m33s
- POST /api/0pt/documents/upload: real multipart bytes into DOC0 through the durable attempt journal and the existing coordinator; verified tenant/actor only, project authorization fail-closed. - POST /api/0pt/documents/structure: DOC0 segments -> INF0 -> evidence-bound validation -> optional JSON/CSV export, with credit reserve/settle. - Credits: balance, server-owned price book, Stripe Checkout and idempotent webhook reconciliation via a Stripe re-read of session + payment intent. - /portal/dokument and /portal/krediter: SIAX-styled workspace. - @siax/access: universal, framework-neutral OpenFGA project relationship primitive reusable by DOC0/N0D/other products. - Readiness: real Redis PING probe instead of presence-only; queue is now a live dependency when configured. - Dockerfile: copy every workspace manifest so --frozen-lockfile works. - Format/build hygiene: .prettierignore, .worktrees ignored, valid manifest YAML.
70 lines
2.6 KiB
TypeScript
70 lines
2.6 KiB
TypeScript
/**
|
|
* Route-level regression test for GET /api/health (BACKLOG P0-3): the old
|
|
* handler hardcoded `ok: true` regardless of dependency state. These tests
|
|
* cover the default (nothing configured) baseline against the real route
|
|
* handler; per-dependency ok/error branching is covered at the unit level in
|
|
* tests/lib/health-checks.test.ts (dependency-injected, no network/DB
|
|
* needed).
|
|
*/
|
|
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
import { GET as healthGET } from "@/app/api/health/route";
|
|
|
|
describe("GET /api/health", () => {
|
|
const savedEnv = {
|
|
DATABASE_URL: process.env.DATABASE_URL,
|
|
POSTGRES_URL: process.env.POSTGRES_URL,
|
|
ENGINE_URL: process.env.ENGINE_URL,
|
|
STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
|
|
REDIS_URL: process.env.REDIS_URL,
|
|
};
|
|
|
|
beforeEach(() => {
|
|
delete process.env.DATABASE_URL;
|
|
delete process.env.POSTGRES_URL;
|
|
delete process.env.ENGINE_URL;
|
|
delete process.env.STRIPE_SECRET_KEY;
|
|
delete process.env.REDIS_URL;
|
|
});
|
|
|
|
afterEach(() => {
|
|
for (const [k, v] of Object.entries(savedEnv)) {
|
|
if (v === undefined) delete process.env[k];
|
|
else process.env[k] = v;
|
|
}
|
|
});
|
|
|
|
it("REGRESSION: always returns HTTP 200 (liveness), but `ok` now reflects a real per-dependency check rather than a hardcoded true", async () => {
|
|
const res = await healthGET();
|
|
expect(res.status).toBe(200);
|
|
const body = await res.json();
|
|
// With nothing configured, nothing can be degraded -- ok:true here is
|
|
// now an honest conclusion, not a hardcoded literal.
|
|
expect(body.ok).toBe(true);
|
|
expect(body.service).toBe("0pt-web");
|
|
});
|
|
|
|
it("reports not_configured (not the old flat 'configured'/'not_configured' guess) for every unset dependency", async () => {
|
|
const res = await healthGET();
|
|
const body = await res.json();
|
|
expect(body.db).toBe("not_configured");
|
|
expect(body.engine).toBe("not_configured");
|
|
expect(body.stripe).toBe("not_configured");
|
|
expect(body.queue).toBe("not_configured");
|
|
});
|
|
|
|
it("reports a configured but unreachable queue as error (never a fabricated ok)", async () => {
|
|
process.env.REDIS_URL = "redis://127.0.0.1:1";
|
|
const res = await healthGET();
|
|
const body = await res.json();
|
|
expect(body.queue).toBe("error");
|
|
// Liveness stays 200; readiness is what fails closed on a broken dependency.
|
|
expect(res.status).toBe(200);
|
|
});
|
|
|
|
it("response includes a ts timestamp", async () => {
|
|
const res = await healthGET();
|
|
const body = await res.json();
|
|
expect(new Date(body.ts).toString()).not.toBe("Invalid Date");
|
|
});
|
|
});
|