96 lines
3.9 KiB
TypeScript
96 lines
3.9 KiB
TypeScript
import { readFileSync } from "node:fs";
|
||
import { describe, expect, it } from "vitest";
|
||
import { parse } from "yaml";
|
||
|
||
/**
|
||
* Die Datenbank im Betriebsstand ist absichtlich von aussen nicht erreichbar.
|
||
* Diese Tests halten das fest, damit ein ports:-Mapping nicht versehentlich
|
||
* zurueckkommt. Siehe docs/betrieb/inbetriebnahme.md.
|
||
*/
|
||
function compose(datei: string): Record<string, never> {
|
||
return parse(readFileSync(datei, "utf8")) as Record<string, never>;
|
||
}
|
||
|
||
describe("Betriebsstand: docker-compose.yml", () => {
|
||
const stand = compose("docker-compose.yml") as unknown as {
|
||
services: Record<string, { ports?: unknown[]; networks?: string[] }>;
|
||
networks: Record<string, { internal?: boolean } | null>;
|
||
};
|
||
|
||
it("veroeffentlicht keinen Port der Datenbank", () => {
|
||
expect(stand.services["postgres"]?.ports).toBeUndefined();
|
||
});
|
||
|
||
it("haengt die Datenbank nur in das interne Netz", () => {
|
||
expect(stand.services["postgres"]?.networks).toEqual(["intern"]);
|
||
});
|
||
|
||
it("hat das interne Netz ohne Gateway", () => {
|
||
expect(stand.networks["intern"]?.internal).toBe(true);
|
||
});
|
||
|
||
it("laesst nur den Webdienst in das externe Netz", () => {
|
||
const aussen = Object.entries(stand.services)
|
||
.filter(([, dienst]) => dienst.networks?.includes("extern"))
|
||
.map(([name]) => name);
|
||
expect(aussen).toEqual(["web"]);
|
||
});
|
||
|
||
it("bindet den Webdienst standardmaessig nur auf localhost", () => {
|
||
expect(stand.services["web"]?.ports).toEqual(["${BIND_ADDR:-127.0.0.1}:${APP_PORT:-3000}:3000"]);
|
||
});
|
||
|
||
it("prueft die Gesundheit des Webdienstes ueber IPv4, nicht ueber localhost", () => {
|
||
// busybox-wget loest localhost zuerst nach ::1 auf, Next lauscht nur auf
|
||
// 0.0.0.0:3000. Mit localhost stand web dauerhaft auf (unhealthy), obwohl
|
||
// die App antwortete (#019).
|
||
const probe = (stand.services["web"] as unknown as { healthcheck?: { test?: string[] } }).healthcheck
|
||
?.test;
|
||
expect(probe).toEqual(["CMD", "wget", "-qO-", "http://127.0.0.1:3000/api/gesundheit"]);
|
||
});
|
||
|
||
it("hat ein Volume für die Anhänge – sonst sind sie beim nächsten Neuaufbau weg", () => {
|
||
/*
|
||
* Die Dateien der Anhaenge liegen im Dateisystem, in der Datenbank stehen
|
||
* nur die Metadaten (#032). Ohne Volume lebten sie im Container: ein
|
||
* `docker compose up --build` waere Datenverlust, und die Zeilen zeigten auf
|
||
* Dateien, die es nicht mehr gibt.
|
||
*/
|
||
const web = stand.services["web"] as unknown as {
|
||
volumes?: string[];
|
||
environment?: Record<string, string>;
|
||
};
|
||
expect(web.volumes).toContain("anhaenge:/daten/anhaenge");
|
||
expect(web.environment?.["ANHAENGE_PFAD"]).toBe("/daten/anhaenge");
|
||
expect(Object.keys((stand as unknown as { volumes: Record<string, unknown> }).volumes)).toContain(
|
||
"anhaenge",
|
||
);
|
||
});
|
||
|
||
it("nennt das Anhang-Volume in der Sicherungsanleitung", () => {
|
||
// Eine Sicherung, die nur `pg_dump` macht, verliert ab #032 Daten. Dass die
|
||
// Anleitung das sagt, ist Teil der Zusage – nicht nur das Volume selbst.
|
||
const sicherung = readFileSync("docs/betrieb/sicherung.md", "utf8");
|
||
expect(sicherung).toContain("anhaenge");
|
||
expect(sicherung).toMatch(/ANHAENGE_PFAD/);
|
||
});
|
||
|
||
it("bricht ohne Geheimnisse ab, statt mit Standardwerten zu starten", () => {
|
||
const roh = readFileSync("docker-compose.yml", "utf8");
|
||
expect(roh).toContain("${APP_SECRET:?");
|
||
expect(roh).toContain("${POSTGRES_PASSWORD:?");
|
||
expect(roh).toContain("${APP_URL:?");
|
||
});
|
||
});
|
||
|
||
describe("Betriebsstand: Entwicklungsdatenbank", () => {
|
||
it("bindet nur auf localhost und auf einen eigenen, umstellbaren Port", () => {
|
||
const stand = compose("docker-compose.dev.yml") as unknown as {
|
||
services: Record<string, { ports?: string[] }>;
|
||
};
|
||
// Der Standard ist 5434, weil 5432 lokal und 5433 von einem anderen Projekt
|
||
// belegt sein koennen. Umstellbar ueber DEV_DB_PORT.
|
||
expect(stand.services["postgres"]?.ports).toEqual(["127.0.0.1:${DEV_DB_PORT:-5434}:5432"]);
|
||
});
|
||
});
|