font.test.js
1.9 kB · javascript · 46 lines
1import { expect, test } from 'bun:test';2import { animate, cycle, letters, merge, HOLD } from './font.js';3import FONT from './font.json' with { type: 'json' };45const WORDMARK = 'MRLYPROD';67test('the wordmark writes itself in stroke order, one cell a frame', () => {8 const write = animate(WORDMARK, 1);9 expect([write.rows, write.cols, write.fps]).toEqual([7, 49, 25]);10 expect(write.frames[0]).toEqual([]);11 expect(write.frames.length).toBe(104);12 for (let i = 1; i < write.frames.length; i++) expect(write.frames[i].length).toBe(write.frames[i - 1].length + 1);13 expect(write.frames[1]).toEqual([5 * 49 + 1]);14 const grid = letters(WORDMARK).grid;15 const lit = grid.flat().filter(Boolean).length;16 expect(write.frames[103].length).toBe(lit);17});1819test('the eight letters fold into an X in twenty-two frames', () => {20 const folded = merge(WORDMARK, 1);21 expect(folded.length).toBe(22);22 expect(folded[0]).toEqual(animate(WORDMARK, 1).frames[103]);23 const x = [];24 FONT.X.rows.forEach((row, r) => [...row].forEach((ch, c) => ch === '1' && x.push((1 + r) * 49 + 22 + c)));25 expect(folded[21]).toEqual(x);26});2728test('the cycle loops through both halves with a rest after each', () => {29 const anim = cycle(WORDMARK, 1);30 expect(anim.frames.length).toBe(2 * 104 + 2 * 22 + 4 * HOLD);31 expect(anim.frames.length).toBe(352);32 for (const frame of anim.frames) {33 expect(frame.every((v, i) => i === 0 || frame[i - 1] < v)).toBe(true);34 expect(frame.every((v) => v < anim.rows * anim.cols)).toBe(true);35 }36});3738test('any string writes itself and a lone glyph has nothing to merge', () => {39 for (const text of ['a', 'hi', 'mrly.net', '(1)']) {40 const write = animate(text, 2);41 const { rows, cols, grid } = letters(text);42 expect([write.rows, write.cols]).toEqual([rows + 4, cols + 4]);43 expect(write.frames.length).toBe(grid.flat().filter(Boolean).length + 1);44 }45 expect(merge('A', 1).length).toBe(1);46});