savers.test.js

2.8 kB · javascript · 68 lines

1import { expect, test } from 'bun:test';2import { paints, rng } from './frame.js';3import { fell } from './matrix.js';4import { bounce } from './sleep.js';5import { wayfind } from './fractal.js';6import { SAVERS } from './index.js';7import { DESIGNS, kron, seed, tile } from './tiles.js';8import { light } from '../theme.js';910const take = (rand, n) => Array.from({ length: n }, () => rand());1112test('a seeded xorshift repeats and an unseeded one does not', () => {13  expect(take(rng(7), 5)).toEqual(take(rng(7), 5));14  expect(take(rng(7), 5)).not.toEqual(take(rng(8), 5));15  expect(take(rng(7), 64).every((n) => n >= 0 && n < 1)).toBe(true);16});1718test('the wayfinder keeps the highest escape count that still escapes', () => {19  const feed = [0.95, 0.5, 0.8, 0.5, 0.2, 0.5];20  let i = 0;21  const rand = () => feed[i++ % feed.length];22  const caps = new Set();23  const escape = (x, y, max) => (caps.add(max), x > 0.9 ? max : Math.floor(x * 100));24  const spot = wayfind(escape, { xMin: 0, xMax: 1, yMin: 0, yMax: 1 }, rand);25  expect([...caps]).toEqual([150]);26  expect(spot.x).toBeCloseTo(0.8, 10);27  expect(spot.y).toBeCloseTo(0.5, 10);28});2930test('a matrix column resets past the floor on a rare roll', () => {31  expect(fell(101, 100, 0.98)).toBe(true);32  expect(fell(101, 100, 0.97)).toBe(false);33  expect(fell(99, 100, 0.99)).toBe(false);34});3536test('the sleeper clamps and flips at both walls', () => {37  expect(bounce(-2, -4, 100)).toEqual({ p: 0, v: 4, hit: true });38  expect(bounce(104, 4, 100)).toEqual({ p: 100, v: -4, hit: true });39  expect(bounce(50, 4, 100)).toEqual({ p: 50, v: 4, hit: false });40});4142test('the chrome whitelist is the saver list', async () => {43  const src = await Bun.file(new URL('../chrome.js', import.meta.url)).text();44  const listed = /const SCREENS = \[([^\]]*)\]/.exec(src)?.[1] ?? '';45  expect(listed.split(',').map((one) => one.trim().slice(1, -1))).toEqual(SAVERS);46});4748const lit = (t) => t.cells.reduce((a, b) => a + b, 0);4950test('every design fills its known cells at n=3 and squares them one level up', () => {51  const counts = { carpet: 8, net: 5, htree: 6, vtree: 6, void: 5 };52  for (const design of DESIGNS) {53    const one = tile(design, 3, 1);54    const two = tile(design, 3, 2);55    expect([design, one.size, lit(one)]).toEqual([design, 3, counts[design]]);56    expect([design, two.size, lit(two)]).toEqual([design, 9, counts[design] ** 2]);57  }58  expect([...tile('carpet', 3, 1).cells]).toEqual([1, 1, 1, 1, 0, 1, 1, 1, 1]);59  expect(kron(seed('void', 5), 2).size).toBe(25);60});6162test('a saver reads the tint from --accent and falls back to the palette', () => {63  const canvas = {};64  globalThis.getComputedStyle = () => ({ getPropertyValue: (name) => (name === '--accent' ? ' #00ff00 ' : '') });65  expect(paints(canvas).accent).toBe('#00ff00');66  delete globalThis.getComputedStyle;67  expect(paints(canvas).accent).toBe(light.accent);68});