import assert from 'node:assert/strict' import fs from 'node:fs' import { test } from 'node:test' import { COLORING_PAGES } from '../src/coloring.ts' import { allImagePaths, imageSourceFor, totalImageBytes } from '../src/images.ts' import { PAINTINGS } from '../src/paintings.ts' const CHURCH_PAGE = /^https:\/\/www\.churchofjesuschrist\.org\/media\/image\/[a-z0-9-]+\?lang=eng$/ const CHURCH_IMAGE = /^https:\/\/www\.churchofjesuschrist\.org\/imgs\/[0-9a-f]{40}\/full\/[0-9,!]+\/0\/default\.jpg$/ test('every painting has a unique id, a Church source page and image, a title, and an artist', () => { assert.ok(PAINTINGS.length >= 30 && PAINTINGS.length <= 60) assert.equal(new Set(PAINTINGS.map((p) => p.id)).size, PAINTINGS.length) for (const p of PAINTINGS) { assert.match(p.sourceUrl, CHURCH_PAGE) assert.ok(p.sourceUrl.includes(p.id)) assert.match(p.imageUrl, CHURCH_IMAGE) assert.ok(p.title.trim()) assert.ok(p.artist.trim()) assert.ok(p.bytes > 10_000 && p.bytes < 1_000_000, `${p.id} is ${p.bytes} bytes`) assert.ok(!/\u2014/.test(p.title + p.artist + p.alt), `${p.id} has an em dash`) } }) test('every coloring page has a unique id, a Church source page and image, and a title', () => { assert.ok(COLORING_PAGES.length >= 15 && COLORING_PAGES.length <= 30) assert.equal(new Set(COLORING_PAGES.map((c) => c.id)).size, COLORING_PAGES.length) for (const c of COLORING_PAGES) { assert.match(c.sourceUrl, CHURCH_PAGE) assert.ok(c.sourceUrl.includes(c.id)) assert.match(c.imageUrl, CHURCH_IMAGE) assert.ok(c.title.trim()) assert.ok(Math.max(c.width, c.height) <= 1600) assert.ok(!/\u2014/.test(c.title + c.alt), `${c.id} has an em dash`) } }) test('the image route only serves curated ids', () => { const paths = allImagePaths() assert.equal(paths.length, PAINTINGS.length + COLORING_PAGES.length) for (const path of paths) assert.match(imageSourceFor(path) ?? '', CHURCH_IMAGE) assert.equal(imageSourceFor('/img/p/not-a-painting.jpg'), null) assert.equal(imageSourceFor('/img/x/../../etc.jpg'), null) assert.equal(imageSourceFor(`/img/c/${PAINTINGS[0].id}.jpg`), null) }) test('the offline download stays phone friendly', () => { assert.ok(totalImageBytes() < 18_000_000, `${totalImageBytes()} bytes`) }) test('no em dashes in the source or docs', () => { for (const dir of ['src', 'test']) { for (const file of fs.readdirSync(new URL(`../${dir}/`, import.meta.url))) { const text = fs.readFileSync(new URL(`../${dir}/${file}`, import.meta.url), 'utf8') assert.ok(!text.includes('\u2014'), `${dir}/${file} has an em dash`) } } for (const file of ['README.md', 'AGENTS.md']) { assert.ok(!fs.readFileSync(new URL(`../${file}`, import.meta.url), 'utf8').includes('\u2014'), `${file} has an em dash`) } })