test: cover captcha env fallback, cache TTLs and public e2e flows
CI / check (push) Successful in 39s
CI / tests-imaging-browsers (push) Successful in 1m46s
CI / tests-unit (push) Successful in 2m16s
CI / tests-integration (push) Successful in 2m12s
CI / tests-ui (push) Failing after 3m45s
CI / preflight (push) Skipped
CI / deploy (push) Skipped
CI / check (push) Successful in 39s
CI / tests-imaging-browsers (push) Successful in 1m46s
CI / tests-unit (push) Successful in 2m16s
CI / tests-integration (push) Successful in 2m12s
CI / tests-ui (push) Failing after 3m45s
CI / preflight (push) Skipped
CI / deploy (push) Skipped
- unit: captcha env fallback/precedence (DB wins, explicit "none") and perf-ttls defaults, overrides and invalid values - e2e: public page render + image health, register form and Turnstile widget consistency, anonymous auth-guard redirects, plus warm latency budgets and cache-control contracts
This commit is contained in:
1 parent
9f024dc6ac
commit
62de3e3a8b
7 files changed
+401
No files matched your search
@@ -0,0 +1,54 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
/**
|
||||
* perf-ttls reads the CMS_* env vars at module load, so each case re-imports
|
||||
* with a freshly stubbed process.env (vitest sets SKIP_ENV_VALIDATION=1, so
|
||||
* @/env is the raw process.env object and vi.stubEnv is visible to it).
|
||||
*/
|
||||
async function loadTtls() {
|
||||
return await import("@/lib/perf-ttls");
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllEnvs();
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
describe("perf-ttls", () => {
|
||||
it("uses the documented defaults when the env is unset", async () => {
|
||||
const mod = await loadTtls();
|
||||
expect(mod.HOME_PAYLOAD_TTL_MS).toBe(15_000);
|
||||
expect(mod.NEWS_LIST_TTL_MS).toBe(300_000);
|
||||
expect(mod.NEWS_ARCHIVE_TTL_MS).toBe(60_000);
|
||||
expect(mod.PUBLIC_SEARCH_TTL_MS).toBe(30_000);
|
||||
expect(mod.ONLINE_COUNT_TTL_MS).toBe(10_000);
|
||||
expect(mod.COUNTERS_TTL_MS).toBe(300_000);
|
||||
expect(mod.SITE_SETTINGS_TTL_MS).toBe(300_000);
|
||||
expect(mod.SITE_SETTINGS_MEMORY_TTL_MS).toBe(60_000);
|
||||
expect(mod.CACHE_WARMUP_ENABLED).toBe(true);
|
||||
});
|
||||
|
||||
it("honours env overrides (seconds → ms)", async () => {
|
||||
vi.stubEnv("CMS_HOME_PAYLOAD_TTL_SEC", "99");
|
||||
vi.stubEnv("CMS_ONLINE_COUNT_TTL_SEC", "3");
|
||||
vi.stubEnv("CMS_WARMUP_ENABLED", "false");
|
||||
const mod = await loadTtls();
|
||||
expect(mod.HOME_PAYLOAD_TTL_MS).toBe(99_000);
|
||||
expect(mod.ONLINE_COUNT_TTL_MS).toBe(3_000);
|
||||
expect(mod.CACHE_WARMUP_ENABLED).toBe(false);
|
||||
// Untouched keys keep their defaults.
|
||||
expect(mod.NEWS_LIST_TTL_MS).toBe(300_000);
|
||||
});
|
||||
|
||||
it("ignores invalid numbers and keeps the default", async () => {
|
||||
vi.stubEnv("CMS_NEWS_ARCHIVE_TTL_SEC", "not-a-number");
|
||||
const mod = await loadTtls();
|
||||
expect(mod.NEWS_ARCHIVE_TTL_MS).toBe(60_000);
|
||||
});
|
||||
|
||||
it("treats zero and negative values as unset", async () => {
|
||||
vi.stubEnv("CMS_SEARCH_TTL_SEC", "0");
|
||||
const mod = await loadTtls();
|
||||
expect(mod.PUBLIC_SEARCH_TTL_MS).toBe(30_000);
|
||||
});
|
||||
});
|
||||
@@ -12,6 +12,7 @@ import { captchaConfig, verifyCaptcha } from "./captcha";
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.unstubAllGlobals();
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
describe("verifyCaptcha", () => {
|
||||
@@ -74,3 +75,63 @@ describe("captchaConfig", () => {
|
||||
expect(cfg.provider).toBe("none");
|
||||
});
|
||||
});
|
||||
|
||||
describe("env fallback", () => {
|
||||
it("enables Turnstile from env when the DB is unconfigured", async () => {
|
||||
mockGet.mockResolvedValue("");
|
||||
vi.stubEnv("CAPTCHA_PROVIDER", "turnstile");
|
||||
vi.stubEnv("TURNSTILE_SITE_KEY", "env-site-key");
|
||||
const cfg = await captchaConfig();
|
||||
expect(cfg.provider).toBe("turnstile");
|
||||
expect(cfg.siteKey).toBe("env-site-key");
|
||||
expect(cfg.field).toBe("cf-turnstile-response");
|
||||
});
|
||||
|
||||
it("lets an explicit DB value — including none — win over env", async () => {
|
||||
mockGet.mockImplementation(async (key: string) => {
|
||||
if (key === "captcha_provider") return "none";
|
||||
return "";
|
||||
});
|
||||
vi.stubEnv("CAPTCHA_PROVIDER", "turnstile");
|
||||
vi.stubEnv("TURNSTILE_SITE_KEY", "env-site-key");
|
||||
const cfg = await captchaConfig();
|
||||
expect(cfg.provider).toBe("none");
|
||||
});
|
||||
|
||||
it("prefers the DB site key over the env one", async () => {
|
||||
mockGet.mockImplementation(async (key: string) => {
|
||||
if (key === "captcha_provider") return "turnstile";
|
||||
if (key === "turnstile_site_key") return "db-site-key";
|
||||
return "";
|
||||
});
|
||||
vi.stubEnv("TURNSTILE_SITE_KEY", "env-site-key");
|
||||
const cfg = await captchaConfig();
|
||||
expect(cfg.siteKey).toBe("db-site-key");
|
||||
});
|
||||
|
||||
it("verifies against the env secret when the DB secret is unset", async () => {
|
||||
mockGet.mockResolvedValue("");
|
||||
vi.stubEnv("CAPTCHA_PROVIDER", "turnstile");
|
||||
vi.stubEnv("TURNSTILE_SITE_KEY", "env-site-key");
|
||||
vi.stubEnv("TURNSTILE_SECRET_KEY", "env-secret");
|
||||
const fetchMock = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
json: async () => ({ success: true }),
|
||||
});
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
expect(await verifyCaptcha("tok", "1.2.3.4")).toBe(true);
|
||||
expect(fetchMock).toHaveBeenCalledOnce();
|
||||
const [, init] = fetchMock.mock.calls[0];
|
||||
expect((init.body as URLSearchParams).get("secret")).toBe("env-secret");
|
||||
expect(fetchMock.mock.calls[0][0]).toBe(
|
||||
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
|
||||
);
|
||||
});
|
||||
|
||||
it("fails closed when the provider comes from env but no secret exists", async () => {
|
||||
mockGet.mockResolvedValue("");
|
||||
vi.stubEnv("CAPTCHA_PROVIDER", "turnstile");
|
||||
vi.stubEnv("TURNSTILE_SITE_KEY", "env-site-key");
|
||||
expect(await verifyCaptcha("tok")).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user