Files
EpicNext-Cms/src/lib/imager.test.ts
T
openhands fe5a7a6185
Gitea Actions Runner Test / test-job (push) Successful in 0s
CI / check (push) Successful in 30s
CI / tests-integration (push) Successful in 1m40s
CI / tests-unit (push) Successful in 1m51s
CI / tests-ui (push) Successful in 2m43s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 2m10s
fix(imaging): keep avatars rendering, cacheable and reliably timed
Effect renders need a little over 4s, which the 4s primary timeout cut off,
so every avatar with the default effect fell through to an unreachable
public fallback and rendered as a placeholder. Raise the primary budget
above the observed render cost and shorten the fallback budget.

Also stop the proxy from stamping no-store over the avatar and media
responses, so browsers keep the long-lived Cache-Control the route already
sends, and recreate the imaging cache directories with the container user
on every deploy, since root ownership made those cache writes fail
silently.
2026-09-24 23:22:28 +02:00

76 lines
2.2 KiB
TypeScript

// @ts-nocheck
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { getAvatarUrl } from "./imager";
import { FALLBACK_TIMEOUT_MS, PRIMARY_TIMEOUT_MS } from "./imager-upstream";
afterEach(() => {
vi.unstubAllEnvs();
});
describe("getAvatarUrl", () => {
beforeEach(() => {
vi.stubEnv("NEXT_PUBLIC_IMAGER_URL", "https://img.example.com");
});
it("builds a query string with defaults (omits default params)", () => {
const url = getAvatarUrl("hd-180-1");
expect(url.startsWith("/api/imaging/avatar?")).toBe(true);
expect(url).toContain("figure=hd-180-1");
expect(url).not.toContain("direction=2");
expect(url).not.toContain("head_direction=3");
expect(url).not.toContain("size=m");
expect(url).toContain("img_format=apng");
expect(url).toContain("effect=14");
});
it("honors custom options", () => {
const url = getAvatarUrl("hd-180-1", {
size: "l",
direction: 1,
headDirection: 2,
headOnly: true,
gesture: "sml",
action: "sit",
});
expect(url).toContain("size=l");
expect(url).toContain("direction=1");
expect(url).toContain("head_direction=2");
expect(url).toContain("headonly=1");
expect(url).toContain("gesture=sml");
expect(url).toContain("action=sit");
});
it("escapes figure values in the query string", () => {
const url = getAvatarUrl("hd-180-1&x=1");
expect(url).not.toContain("&x=1");
});
it("allows custom img_format", () => {
const url = getAvatarUrl("hd-180-1", { img_format: "png" });
expect(url).toContain("img_format=png");
});
it("allows custom effect", () => {
const url = getAvatarUrl("hd-180-1", { effect: 0 });
expect(url).toContain("effect=0");
});
it("uses the local runtime proxy when no env var is set", () => {
vi.stubEnv("NEXT_PUBLIC_IMAGER_URL", "");
const url = getAvatarUrl("hd-180-1");
expect(url.startsWith("/api/imaging/avatar?")).toBe(true);
expect(url).toContain("img_format=apng");
expect(url).toContain("effect=14");
});
});
describe("upstream render budgets", () => {
it("keeps enough headroom for APNG effect renders", () => {
expect(PRIMARY_TIMEOUT_MS).toBeGreaterThanOrEqual(8_000);
});
it("does not stack a long fallback wait on a slow primary", () => {
expect(FALLBACK_TIMEOUT_MS).toBeLessThan(PRIMARY_TIMEOUT_MS);
});
});