import { describe, expect, it } from "@suaveplan/testing/runner"; import * as fc from "fast-check"; import { compressSvg } from "../src/core/compress-svg/compress-svg.js"; import { parseSvg, serializeSvg } from "../src/parser/svg/svg.js"; import { PRESET_DEFAULT } from "../src/presets/index.js"; const SIMPLE_SVGS = [ '', '', '', 'hello', "", ]; describe("property-based: compression idempotency", () => { it("compress(compress(svg)) === compress(svg) for all sample SVGs", { timeout: 30000, }, () => { fc.assert( fc.property(fc.constantFrom(...SIMPLE_SVGS), (svg) => { const first = compressSvg(svg, { plugins: PRESET_DEFAULT }); const second = compressSvg(first.data, { plugins: PRESET_DEFAULT, }); expect(second.data).toBe(first.data); return true; }), { numRuns: 10 } ); }); }); describe("property-based: parse ↔ serialize round-trip", () => { it("serializeSvg(parseSvg(svg)) is re-parseable for sample SVGs", { timeout: 30000, }, () => { fc.assert( fc.property(fc.constantFrom(...SIMPLE_SVGS), (svg) => { const node = parseSvg(svg); const serialized = serializeSvg(node); const reparsed = parseSvg(serialized); expect(reparsed.type).toBe("element"); return true; }), { numRuns: 10 } ); }); it("parse → serialize preserves element names", { timeout: 30000 }, () => { fc.assert( fc.property(fc.constantFrom(...SIMPLE_SVGS), (svg) => { const node = parseSvg(svg); const serialized = serializeSvg(node); const reparsed = parseSvg(serialized); expect(reparsed.name).toBe(node.name); return true; }), { numRuns: 10 } ); }); }); describe("property-based: ratio invariants", () => { it("ratio is always > 0 for valid SVG", { timeout: 30000 }, () => { fc.assert( fc.property(fc.constantFrom(...SIMPLE_SVGS), (svg) => { const result = compressSvg(svg); expect(result.ratio).toBeGreaterThan(0); return true; }), { numRuns: 10 } ); }); it("originalSize matches byte length of input", { timeout: 30000 }, () => { fc.assert( fc.property(fc.constantFrom(...SIMPLE_SVGS), (svg) => { const result = compressSvg(svg); const expected = new TextEncoder().encode(svg).byteLength; expect(result.originalSize).toBe(expected); return true; }), { numRuns: 10 } ); }); it("compressedSize matches byte length of output", { timeout: 30000, }, () => { fc.assert( fc.property(fc.constantFrom(...SIMPLE_SVGS), (svg) => { const result = compressSvg(svg); const expected = new TextEncoder().encode( result.data ).byteLength; expect(result.compressedSize).toBe(expected); return true; }), { numRuns: 10 } ); }); it("ratio equals compressedSize / originalSize", { timeout: 30000 }, () => { fc.assert( fc.property(fc.constantFrom(...SIMPLE_SVGS), (svg) => { const result = compressSvg(svg); expect(result.ratio).toBeCloseTo( result.compressedSize / result.originalSize, 5 ); return true; }), { numRuns: 10 } ); }); }); describe("property-based: passCount invariants", () => { it("passCount >= 1 for all valid SVGs", { timeout: 30000 }, () => { fc.assert( fc.property(fc.constantFrom(...SIMPLE_SVGS), (svg) => { const result = compressSvg(svg); expect(result.passCount).toBeGreaterThanOrEqual(1); return true; }), { numRuns: 10 } ); }); it("passCount === 1 when multipass: false", { timeout: 30000 }, () => { fc.assert( fc.property(fc.constantFrom(...SIMPLE_SVGS), (svg) => { const result = compressSvg(svg, { multipass: false }); expect(result.passCount).toBe(1); return true; }), { numRuns: 10 } ); }); });