Files
0pt/tests/api/health.test.ts
admin b3239487b7
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
feat(document-workbench): wire customer upload, structuring, credits and readiness
- 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.
2026-11-02 14:46:10 +01:00

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");
});
});