Files
clean-architecture-frontend…/tests/runtime-schema/runtime-config.test.js

89 lines
2.8 KiB
JavaScript

import { describe, expect, it } from "vitest";
import { loadRuntimeConfig } from "../../src/bootstrap/load-runtime-config.js";
import { validateRuntimeConfig } from "../../src/bootstrap/runtime-config-schema.js";
import { assertSafeConfigNames } from "../../src/contracts/env.js";
const validConfig = {
APP_ENV: "local",
API_BASE_URL: "http://localhost:8080",
REQUEST_TIMEOUT_MS: 10_000,
MAX_RETRY_ATTEMPTS: 2,
TELEMETRY_ENABLED: false,
AUTH_MODE: "external",
CONFIG_SCHEMA_VERSION: "1",
API_CONTRACT_VERSION: "1",
RELEASE_MANIFEST_URL: "/release-manifest.json",
BUILD_ID: "build-a",
};
describe("runtime configuration boundary", () => {
it.each([
[{ ...validConfig, API_BASE_URL: undefined }, "required key"],
[{ ...validConfig, REQUEST_TIMEOUT_MS: 0 }, "integer range"],
[{ ...validConfig, MAX_RETRY_ATTEMPTS: 3 }, "retry cap"],
[{ ...validConfig, TELEMETRY_ENABLED: "false" }, "ambiguous boolean"],
[{ ...validConfig, CONFIG_SCHEMA_VERSION: "next" }, "version"],
[{ ...validConfig, UNKNOWN_KEY: true }, "unknown key"],
])("rejects invalid config: %s (%s)", (candidate, _reason) => {
void _reason;
expect(validateRuntimeConfig(candidate).success).toBe(false);
});
it("rejects secret-like names before schema validation", () => {
expect(() => assertSafeConfigNames({ CLIENT_SECRET: "not-safe" })).toThrow(
"Forbidden client configuration key",
);
});
it("allows demo authentication only for local runtime configuration", () => {
expect(
validateRuntimeConfig({ ...validConfig, AUTH_MODE: "demo" }).success,
).toBe(true);
expect(
validateRuntimeConfig({
...validConfig,
APP_ENV: "production",
API_BASE_URL: "https://api.example.test",
AUTH_MODE: "demo",
}).success,
).toBe(false);
});
it("validates a fetched config under the 500ms budget excluding network", async () => {
let current = 100;
const result = await loadRuntimeConfig({
buildConfig: {
buildId: "build-a",
commitSha: "local",
routerBasePath: "/",
runtimeConfigUrl: "/config.json",
},
fetcher: async () => new Response(JSON.stringify(validConfig)),
now: () => (current += 2),
});
expect(result.validationDurationMs).toBeLessThanOrEqual(500);
expect(result.config.API_BASE_URL).toBe("http://localhost:8080");
});
it("returns only safe boot fields on failure", async () => {
await expect(
loadRuntimeConfig({
buildConfig: {
buildId: "build-a",
commitSha: "local",
routerBasePath: "/",
runtimeConfigUrl: "/config.json",
},
fetcher: async () => new Response("{"),
}),
).rejects.toMatchObject({
safe: {
kind: "BOOT_CONFIG_FAILURE",
buildId: "build-a",
},
});
});
});