Something went wrong. Try again.
Browser extension: detect and subscribe to standard.site publications on ATProto
Something went wrong. Try again.
4.3 kB · 108 lines
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs'import { tmpdir } from 'node:os'import { join } from 'node:path'import { afterEach, describe, expect, it } from 'vitest'
import { CAPTURE_DIR, MANIFEST, SHOTS, SITE_DIR, capturePath, storeShots, storeTilePath,} from './shots.mjs'import { syncShots } from './sync-shots.mjs'import { pngSize } from './render-icons.mjs'
const repoRoot = join(import.meta.dirname, '..')
let dirs = []afterEach(() => { for (const dir of dirs) rmSync(dir, { recursive: true, force: true }) dirs = []})
/** A repo-shaped scratch tree with the real captures copied in. */function fixtureRoot(shots) { const root = mkdtempSync(join(tmpdir(), 'sync-shots-')) dirs.push(root) mkdirSync(join(root, CAPTURE_DIR), { recursive: true }) mkdirSync(join(root, SITE_DIR), { recursive: true }) mkdirSync(join(root, MANIFEST, '..'), { recursive: true }) for (const shot of shots) { writeFileSync(join(root, capturePath(shot)), readFileSync(join(repoRoot, capturePath(shot)))) } return root}
describe('sync-shots.mjs', () => { it('copies each capture and records its real pixel size', () => { const root = fixtureRoot(SHOTS) const { manifest } = syncShots({ root })
expect(manifest.map((entry) => entry.name)).toEqual(SHOTS.map((shot) => shot.name)) for (const entry of manifest) { const copied = join(root, SITE_DIR, `${entry.name}.png`) expect(readFileSync(copied)).toEqual(readFileSync(join(repoRoot, `${CAPTURE_DIR}/${entry.name}.png`))) // The page reserves this box before the image lands; a guessed size // would reflow the whole column on load. expect(pngSize(readFileSync(copied))).toEqual({ width: entry.width, height: entry.height }) expect(entry.src).toBe(`/shots/${entry.name}.png`) expect(entry.alt).toBeTruthy() } expect(JSON.parse(readFileSync(join(root, MANIFEST), 'utf8'))).toEqual(manifest) })
it('removes a shot dropped from the list instead of leaving it on the site', () => { const root = fixtureRoot(SHOTS) syncShots({ root }) const { removed } = syncShots({ root, shots: SHOTS.slice(0, 1) })
// Directory order, not list order: compare the sets. expect([...removed].sort()).toEqual(SHOTS.slice(1).map((shot) => `${shot.name}.png`).sort()) expect(readdirSync(join(root, SITE_DIR))).toEqual([`${SHOTS[0].name}.png`]) })
it('fails loudly when a capture is missing rather than writing a manifest for it', () => { const root = fixtureRoot(SHOTS) rmSync(join(root, capturePath(SHOTS[0])))
expect(() => syncShots({ root })).toThrow(/capture-status-docs/) expect(existsSync(join(root, MANIFEST))).toBe(false) })
it('keeps the committed site copies in step with docs/img', () => { // What the prek hook and the deploy both enforce, asserted read-only so // a recapture that skipped the sync fails at `npm test` too. for (const shot of SHOTS) { expect(readFileSync(join(repoRoot, SITE_DIR, `${shot.name}.png`))).toEqual( readFileSync(join(repoRoot, capturePath(shot))), ) } const manifest = JSON.parse(readFileSync(join(repoRoot, MANIFEST), 'utf8')) expect(manifest.map((entry) => entry.name)).toEqual(SHOTS.map((shot) => shot.name)) })})
describe('shots.mjs', () => { it('names at least one store shot, and every shot has a capture', () => { expect(SHOTS.length).toBeGreaterThan(0) expect(storeShots().length).toBeGreaterThan(0) for (const shot of storeShots()) expect(shot.store).toBe(true) for (const shot of SHOTS) expect(existsSync(join(repoRoot, capturePath(shot)))).toBe(true) })
it('refuses a listing with no screenshots, or more than the store takes', () => { expect(() => storeShots([{ name: 'popup-x' }])).toThrow(/1 to 5/) expect(() => storeShots(Array(6).fill({ name: 'popup-x', store: true }))).toThrow(/1 to 5/) })
it('composes a committed listing tile for each store shot', () => { // The tile is what the store listing uploads; a store shot without one // means `npm run cws` has not been run since the list changed. for (const shot of storeShots()) { expect(existsSync(join(repoRoot, storeTilePath(shot)))).toBe(true) } })})