/** * Abstract Expressionism loft must read as an open painter's loft, not a barred cell. * node --test server/__tests__/abex-loft-interior.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'); const DETAILS = fs.readFileSync(path.join(ROOT, 'client/src/components/hall-details/modernism.tsx'), 'utf8'); function loftStyleBlock() { const start = STYLES.indexOf("'abstract-expressionist-loft'"); assert.ok(start >= 0, 'abstract-expressionist-loft style must exist'); const next = STYLES.indexOf('mk(', start + 1); return STYLES.slice(start, next > start ? next : undefined); } function loftDetailsBlock() { const start = DETAILS.indexOf('export function LoftDetails'); assert.ok(start >= 0, 'LoftDetails must exist'); const next = DETAILS.indexOf('export function ', start + 1); return DETAILS.slice(start, next > start ? next : undefined); } describe('Abstract Expressionism loft — open studio, no prison vibe', () => { it('does not use factory windows (iron-bar grid)', () => { const block = loftStyleBlock(); assert.doesNotMatch(block, /style: 'factory'/); assert.match(block, /style: 'picture'|style: 'clerestory'|style: 'skylight'/); }); it('uses open painted / warm loft surfaces, not dingy cell brick-only', () => { const block = loftStyleBlock(); assert.match(block, /north-light|painter|studio|loft/i); assert.doesNotMatch(block, /north-light factory windows/); }); it('LoftDetails has no cast-iron columns or sprinkler prison pipe', () => { const block = loftDetailsBlock(); assert.doesNotMatch(block, /Cast-iron|Sprinkler main|cast-iron/); assert.match(block, /timber|wood|joist|painter|studio/i); }); });