import { describe, test } from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { TARGETS, DEFAULT_TOKENS, deriveDimensions, loadBrandTokens, tokensToCss, wrapSvg, injectTokens, parseSvgMeta, validateFigure, resolveChrome, parseArgs, renderFigure, } from '../build-figur.mjs'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const FIXTURE_SVG = path.join(__dirname, 'fixtures', 'demo-figur.svg'); function tmpdir() { return fs.mkdtempSync(path.join(os.tmpdir(), 'build-figur-test-')); } // Leser bredde/høyde fra PNG-IHDR (byte 16–23, big-endian). function pngDimensions(file) { const buf = fs.readFileSync(file); return { width: buf.readUInt32BE(16), height: buf.readUInt32BE(20) }; } describe('TARGETS + deriveDimensions', () => { test('carousel er 1080×1350 (fast)', () => { assert.equal(TARGETS.carousel.width, 1080); assert.equal(TARGETS.carousel.height, 1350); }); test('article er 1200 bred med innholdsstyrt høyde', () => { assert.equal(TARGETS.article.width, 1200); assert.equal(TARGETS.article.height, null); }); test('single er kvadratisk 1200×1200', () => { assert.equal(TARGETS.single.width, 1200); assert.equal(TARGETS.single.height, 1200); }); test('article + aspekt 16:9 gir avledet høyde 675', () => { const d = deriveDimensions('article', 1200 / 675, {}); assert.equal(d.width, 1200); assert.equal(d.height, 675); assert.equal(d.warnings.length, 0); }); test('article uten aspekt gir fallback-høyde med warning', () => { const d = deriveDimensions('article', null, {}); assert.equal(d.width, 1200); assert.ok(d.height > 0); assert.ok(d.warnings.some((w) => /høyde/i.test(w))); }); test('--width/--height-overstyringer vinner over målet', () => { const d = deriveDimensions('carousel', null, { width: 800, height: 600 }); assert.equal(d.width, 800); assert.equal(d.height, 600); }); test('ukjent mål kaster med gyldige mål i meldingen', () => { assert.throws(() => deriveDimensions('poster', null, {}), /article/); }); }); describe('loadBrandTokens — token-seam (brukerdata, aldri hardkodet)', () => { test('uten brand-tokens.json: nøytrale defaults, source=default', () => { const dir = tmpdir(); const r = loadBrandTokens(dir); assert.equal(r.source, 'default'); assert.deepEqual(r.tokens, DEFAULT_TOKENS); assert.equal(r.warnings.length, 0); }); test('gyldig fil merges over defaults, source=user', () => { const dir = tmpdir(); fs.mkdirSync(path.join(dir, 'profile'), { recursive: true }); fs.writeFileSync( path.join(dir, 'profile', 'brand-tokens.json'), JSON.stringify({ accent: '#123456' }), 'utf8' ); const r = loadBrandTokens(dir); assert.equal(r.source, 'user'); assert.equal(r.tokens.accent, '#123456'); // umerkede felter beholder defaults assert.equal(r.tokens.background, DEFAULT_TOKENS.background); }); test('ugyldig JSON: defaults + warning, kaster aldri', () => { const dir = tmpdir(); fs.mkdirSync(path.join(dir, 'profile'), { recursive: true }); fs.writeFileSync(path.join(dir, 'profile', 'brand-tokens.json'), '{not json', 'utf8'); let r; assert.doesNotThrow(() => { r = loadBrandTokens(dir); }); assert.equal(r.source, 'default'); assert.ok(r.warnings.some((w) => /brand-tokens\.json/.test(w))); }); }); describe('tokensToCss + wrapSvg + injectTokens — CSS-injeksjon', () => { test('tokensToCss produserer --figur-variabler for alle tokens', () => { const css = tokensToCss(DEFAULT_TOKENS); assert.match(css, /:root\{/); for (const key of Object.keys(DEFAULT_TOKENS)) { assert.ok(css.includes(`--figur-${key}`), `mangler --figur-${key}`); } }); test('egendefinerte tokenverdier reflekteres i CSS-en', () => { const css = tokensToCss({ ...DEFAULT_TOKENS, accent: '#ABCDEF' }); assert.match(css, /--figur-accent:\s*#ABCDEF/); }); test('wrapSvg bygger komplett HTML med svg + tokens + mål-dimensjoner', () => { const html = wrapSvg('', { width: 1080, height: 1350 }, DEFAULT_TOKENS); assert.match(html, //i); assert.match(html, //); assert.match(html, /--figur-accent/); assert.match(html, /width:\s*1080px/); assert.match(html, /height:\s*1350px/); }); test('injectTokens legger style rett etter når den finnes', () => { const out = injectTokens('x', DEFAULT_TOKENS); assert.match(out, /\s*