import assert from "node:assert/strict"; import { BLUR_AMOUNT_MAX, INVALID_LAYOUT_TEMPLATE_MESSAGE, blurToBoxblur, boxblurFilterSegment, buildArtTrackFilterComplex, clampBlurAmount, clampTextPadding, clampTitleArtistGap, computeLayoutGeometry, normalizeLayoutSettings, requiresArtTrackLayoutEntitlement, } from "../lib/layout"; import { sanitizeDrawtext } from "../lib/watermark"; function testEnumsAndClamp() { assert.equal(clampBlurAmount(150), BLUR_AMOUNT_MAX); assert.equal(clampBlurAmount(-1), 0); assert.equal(clampTextPadding(999), 120); assert.equal(clampTextPadding(1), 16); assert.equal(clampTitleArtistGap(100), 64); assert.equal(clampTitleArtistGap(-5), 0); assert.equal(blurToBoxblur(0), null); const mid = blurToBoxblur(50); assert.ok(mid && mid.radius >= 1 && mid.power >= 1); assert.ok(boxblurFilterSegment(60).includes("boxblur=")); assert.equal(boxblurFilterSegment(0), ""); } function testNormalize() { const classic = normalizeLayoutSettings(null); assert.equal(classic.template, null); assert.equal(classic.titleArtistGap, 10); assert.equal(classic.textOffsetX, 0); assert.equal( normalizeLayoutSettings({ layout_template: "CENTERED_COMPACT", blur_amount: 80, title_artist_gap: 24, text_offset_y: -20, }).titleArtistGap, 24, ); assert.throws( () => normalizeLayoutSettings({ template: "NOT_A_TEMPLATE" }), (err: Error) => err.message === INVALID_LAYOUT_TEMPLATE_MESSAGE, ); assert.throws( () => normalizeLayoutSettings({ template: "COVER_LEFT_TEXT_RIGHT", x: 10 }), (err: Error) => err.message === INVALID_LAYOUT_TEMPLATE_MESSAGE, ); assert.equal( requiresArtTrackLayoutEntitlement(normalizeLayoutSettings({ template: null })), false, ); assert.equal( requiresArtTrackLayoutEntitlement( normalizeLayoutSettings({ template: "COVER_TOP_TEXT_BOTTOM" }), ), true, ); } function testGeometryAndFilter() { const geo = computeLayoutGeometry("COVER_TOP_TEXT_BOTTOM", 1920, 1080, 48, 16, 10, -5); assert.ok(geo.coverMaxW > 1600, "top layout cover should be near full width"); assert.ok(geo.artistY !== geo.titleY); const withGap = computeLayoutGeometry("COVER_LEFT_TEXT_RIGHT", 1280, 720, 40, 40, 0, 0); const tight = computeLayoutGeometry("COVER_LEFT_TEXT_RIGHT", 1280, 720, 40, 0, 0, 0); assert.ok(Number(withGap.artistY) - Number(withGap.titleY) > Number(tight.artistY) - Number(tight.titleY)); const fc = buildArtTrackFilterComplex({ width: 1280, height: 720, layout: { template: "CENTERED_COMPACT", blurAmount: 40, blurOpacity: 70, textPadding: 40, titleArtistGap: 18, textOffsetX: 5, textOffsetY: -8, }, titleEscaped: sanitizeDrawtext("Hello:World"), artistEscaped: sanitizeDrawtext("Artist"), }); assert.ok(fc.includes("split=2")); assert.ok(fc.includes("blend=") || fc.includes("[blurred]")); assert.ok(fc.includes("overlay=")); assert.ok(fc.includes("drawtext=")); assert.ok(fc.endsWith("[laid]")); } testEnumsAndClamp(); testNormalize(); testGeometryAndFilter(); console.log("layout.test.ts: ok");