mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
Coverage 83.6 to 87.36% lines, 81.63 to 84.14% branches. Mutation testing across five packages: image-engine 85, media-engine 92, doc-engine 87, shared+enterprise 86, apps/api security and jobs slice. Runs all five lanes weekly. Fixes the silently-broken mutation CI (babel pin), a redact-pdf envelope-shape test bug, an untested enterprise license valid-signature path, and an audit test that only exercised a hand-copied reproduction. Test and config only, no product code changes beyond the babel pin and one test-only oidc export. Full suite: 16,712 pass, 0 fail.
69 lines
2.9 KiB
TypeScript
69 lines
2.9 KiB
TypeScript
import { existsSync } from "node:fs";
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
vi.mock("node:fs", () => ({ existsSync: vi.fn() }));
|
|
|
|
const DEJAVU = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf";
|
|
const ARIAL = "/System/Library/Fonts/Supplemental/Arial.ttf";
|
|
const HELVETICA = "/System/Library/Fonts/Helvetica.ttc";
|
|
|
|
describe("resolveFontFile", () => {
|
|
beforeEach(() => {
|
|
vi.resetModules();
|
|
vi.mocked(existsSync).mockReset();
|
|
delete process.env.SNAPOTTER_FONT_FILE;
|
|
delete process.env.SNAPOTTER_FONT_FAMILY;
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
delete process.env.SNAPOTTER_FONT_FILE;
|
|
delete process.env.SNAPOTTER_FONT_FAMILY;
|
|
});
|
|
|
|
it("env override wins without touching the filesystem, default family 'Sans'", async () => {
|
|
process.env.SNAPOTTER_FONT_FILE = "/custom/MyFont.ttf";
|
|
const { resolveFontFile } = await import("../src/fonts.js");
|
|
expect(resolveFontFile()).toEqual({ file: "/custom/MyFont.ttf", family: "Sans" });
|
|
expect(vi.mocked(existsSync)).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("env override uses SNAPOTTER_FONT_FAMILY when set", async () => {
|
|
process.env.SNAPOTTER_FONT_FILE = "/custom/MyFont.ttf";
|
|
process.env.SNAPOTTER_FONT_FAMILY = "My Font";
|
|
const { resolveFontFile } = await import("../src/fonts.js");
|
|
expect(resolveFontFile()).toEqual({ file: "/custom/MyFont.ttf", family: "My Font" });
|
|
});
|
|
|
|
it("returns the first existing candidate (DejaVu) with its exact family", async () => {
|
|
vi.mocked(existsSync).mockImplementation((p) => p === DEJAVU);
|
|
const { resolveFontFile } = await import("../src/fonts.js");
|
|
expect(resolveFontFile()).toEqual({ file: DEJAVU, family: "DejaVu Sans" });
|
|
});
|
|
|
|
it("falls through to Arial when DejaVu is missing", async () => {
|
|
vi.mocked(existsSync).mockImplementation((p) => p === ARIAL);
|
|
const { resolveFontFile } = await import("../src/fonts.js");
|
|
expect(resolveFontFile()).toEqual({ file: ARIAL, family: "Arial" });
|
|
});
|
|
|
|
it("falls through to Helvetica when DejaVu and Arial are missing", async () => {
|
|
vi.mocked(existsSync).mockImplementation((p) => p === HELVETICA);
|
|
const { resolveFontFile } = await import("../src/fonts.js");
|
|
expect(resolveFontFile()).toEqual({ file: HELVETICA, family: "Helvetica" });
|
|
});
|
|
|
|
it("returns the earliest match when several candidates exist (order matters)", async () => {
|
|
// Both Arial and Helvetica present, DejaVu absent: Arial comes first.
|
|
vi.mocked(existsSync).mockImplementation((p) => p === ARIAL || p === HELVETICA);
|
|
const { resolveFontFile } = await import("../src/fonts.js");
|
|
expect(resolveFontFile()).toEqual({ file: ARIAL, family: "Arial" });
|
|
});
|
|
|
|
it("returns null when no candidate file exists", async () => {
|
|
vi.mocked(existsSync).mockReturnValue(false);
|
|
const { resolveFontFile } = await import("../src/fonts.js");
|
|
expect(resolveFontFile()).toBeNull();
|
|
});
|
|
});
|