import { BinaryFontPacker } from "@suaveplan/font-compress"; import type { TypefaceFont } from "@suaveplan/font-convert"; import { describe, it } from "@suaveplan/testing/runner"; import fc from "fast-check"; import { BinaryFontUnpacker } from "../src/index.js"; const packer = new BinaryFontPacker(); const unpacker = new BinaryFontUnpacker(); // Restrict coordinates to Int16 range (BTF dict uses Int16Array) const coordArb = fc.integer({ min: -32768, max: 32767 }); const glyphArb = fc.record({ ha: coordArb, x_min: coordArb, x_max: coordArb, o: fc.constant("m 0 0 z "), }); const fontArb: fc.Arbitrary = fc.record({ familyName: fc.string({ minLength: 1, maxLength: 30 }), cssFontWeight: fc.constantFrom("100", "400", "700", "bold", "normal"), cssFontStyle: fc.constantFrom("normal", "italic", "oblique"), reversed: fc.boolean(), ascender: coordArb, descender: coordArb, underlinePosition: coordArb, underlineThickness: coordArb, resolution: coordArb, boundingBox: fc.record({ yMin: coordArb, xMin: coordArb, yMax: coordArb, xMax: coordArb, }), original_font_information: fc.constant({}), glyphs: fc.dictionary( fc .string({ minLength: 1, maxLength: 1 }) .filter((s) => s.charCodeAt(0) < 65536), glyphArb, { minKeys: 0, maxKeys: 20 } ), }); describe("property tests: pack/unpack roundtrip", () => { it("familyName round-trips for all valid inputs", { timeout: 30000, }, () => { fc.assert( fc.property(fontArb, (font) => { const result = unpacker.unpack(packer.pack(font)); return result.familyName === font.familyName; }), { numRuns: 100 } ); }); it("metrics round-trip for all valid inputs", { timeout: 30000 }, () => { fc.assert( fc.property(fontArb, (font) => { const result = unpacker.unpack(packer.pack(font)); return ( result.ascender === font.ascender && result.descender === font.descender && result.resolution === font.resolution && result.reversed === font.reversed ); }), { numRuns: 100 } ); }); it("glyph count round-trips for all valid inputs", { timeout: 30000, }, () => { fc.assert( fc.property(fontArb, (font) => { const result = unpacker.unpack(packer.pack(font)); return ( Object.keys(result.glyphs).length === Object.keys(font.glyphs).length ); }), { numRuns: 100 } ); }); });