/** * No movement hall may use factory (iron-bar grid) windows — they read as prison cells. * node --test server/__tests__/no-factory-windows.test.js */ const { describe, it } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const ROOT = path.join(__dirname, '..', '..'); const STYLES = fs.readFileSync(path.join(ROOT, 'client/src/data/movement-interior-styles.ts'), 'utf8'); function styleBlock(id) { const start = STYLES.indexOf(`'${id}'`); assert.ok(start >= 0, `${id} must exist`); const next = STYLES.indexOf('mk(', start + 1); return STYLES.slice(start, next > start ? next : undefined); } describe('Movement interiors — no factory / iron-bar windows', () => { it('no authored movement style uses factory windows', () => { // Only count style: 'factory' assignments inside BY_MOVEMENT_ID mk() blocks, // not the GalleryWindowStyle union member. const uses = [...STYLES.matchAll(/style:\s*'factory'/g)]; assert.equal(uses.length, 0, `found ${uses.length} factory window assignment(s)`); }); it('Futurism uses open picture or clerestory daylight, not bars', () => { const block = styleBlock('futurist-loft'); assert.doesNotMatch(block, /style: 'factory'/); assert.match(block, /style: 'picture'|style: 'ribbon'|style: 'clerestory'|style: 'skylight'/); assert.match(block, /open|ribbon|picture|glass/i); }); });