'use strict'; /** * E10 issue template + E12 archive. * * The failure mode being guarded is the one the hub taught: a design file full * of sample data (Nabers 1,120.5, Nº 128, DAY RECORD 9-4) is a SPEC for what a * live issue renders. Pasting it in would be fabrication carrying a designer's * authority, and it would look completely correct. */ const fs = require('fs'); const path = require('path'); const t = require('../../src/services/report/reportTemplate'); const ROOT = path.join(__dirname, '..', '..'); /** * Strip comments first. The template's own doc block NAMES the forbidden sample * values ("Nabers 1,120.5 ... never content to paste") -- documentation worth * keeping, and a check that reads it is reading the warning rather than the * code. Same bug I made on the offseason hub. */ const stripComments = (s) => s.replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, ''); const ARCHIVE = stripComments(fs.readFileSync(path.join(ROOT, 'web/src/components/vyndr/ReportArchive.tsx'), 'utf8')); const TPL = stripComments(fs.readFileSync(path.join(ROOT, 'src/services/report/reportTemplate.js'), 'utf8')); const ARCHIVE_RAW = fs.readFileSync(path.join(ROOT, 'web/src/components/vyndr/ReportArchive.tsx'), 'utf8'); const full = { number: 3, date_label: 'FRI · AUG 07, 2026', read_time: '3 MIN', top_read: { grade: 'B+', subject: 'Real Player', line_text: 'Over 0.5 Hits', movement: { from: 0.5, to: 0.5, days: 2 }, model: '0.61', best_book: 'DK', note: 'A real note.' }, changed: [{ time: '11:42 AM', tag: 'injury', text: 'Something real happened.' }], record: { line: '9–4', note: 'settled' }, honesty: { graded: 2140, cleared_ceiling: 70, ceiling_letter: 'B+', ceiling_realized: 66, base_rate: 60, unissuable: 'A+, A, A-' }, }; describe('no designer sample data ships', () => { it('the template source contains none of the spec\'s sample values', () => { for (const sample of ['Nabers', '1,120.5', '1,188', 'Skenes', 'Wemby', '12,408']) { expect(TPL).not.toContain(sample); } }); it('the archive contains no sample issues', () => { for (const sample of ['Nabers', 'SKENES', '9–4', 'Nº 128']) { expect(ARCHIVE).not.toContain(sample); } }); }); describe('a section with no data is OMITTED, never filled', () => { it('names every omitted section rather than hiding the gap', () => { const out = t.renderIssue({ number: 1, date_label: 'X' }); expect(out.omitted).toEqual(expect.arrayContaining(['top_read', 'changed', 'record', 'honesty'])); expect(out.html).not.toMatch(/TOP READ OF THE DAY/); }); it('an empty issue still renders a valid, readable shell', () => { const out = t.renderIssue({}); expect(out.html).toMatch(/VYND/); expect(out.html).toMatch(/One email per slate day/); }); it('renders every section when the data is there', () => { const out = t.renderIssue(full); expect(out.omitted).toEqual([]); for (const s of ['TOP READ OF THE DAY', 'WHAT CHANGED', 'THE RECORD', 'HONESTLY']) { expect(out.html).toContain(s); } }); }); describe('the E1 movement law travels into email', () => { it('a flat market says FLAT with its day count, not nothing', () => { // A strip cannot render in email, but its RULE still applies. expect(t.movementText({ from: 1.5, to: 1.5, days: 4 })).toMatchObject({ text: 'FLAT · 4D' }); }); it('green is reserved for a move that FAVOURS the read', () => { const toward = t.movementText({ from: 1.5, to: 1.2, dir: 'toward' }); const against = t.movementText({ from: 1.5, to: 1.8, dir: 'against' }); expect(toward.colour).toBe(t.T.greenOnPaper); expect(against.colour).not.toBe(t.T.greenOnPaper); }); it('an unreadable movement returns null rather than a guess', () => { expect(t.movementText({ from: null, to: 1.2 })).toBeNull(); expect(t.movementText(null)).toBeNull(); }); }); describe('the hybrid shell is an engineering constraint, not a look', () => { it('is 600px and table-based — Gmail strips style blocks, Outlook ignores flex', () => { const out = t.renderIssue(full); expect(out.width).toBe(600); expect(out.html).toMatch(/ { expect(t.T.greenOnPaper).not.toBe(t.T.greenOnDark); }); it('depends on no webfont and no image to be readable', () => { const out = t.renderIssue(full); expect(out.html).not.toMatch(/@font-face|fonts\.googleapis/); expect(out.html).not.toMatch(/ { expect(t.renderIssue(full).html).toContain('{{ UnsubscribeURL }}'); }); it('ships a plain-text alternative', () => { expect(t.renderIssue(full).text).toMatch(/TOP READ/); }); }); describe('E12 — the archive is a ledger too', () => { it('every row renders its own day record', () => { expect(ARCHIVE).toMatch(/DAY RECORD/); }); it('an unknown record says UNSETTLED, not a dash that reads as zero', () => { expect(ARCHIVE).toMatch(/UNSETTLED/); expect(ARCHIVE_RAW).toMatch(/never a dash that reads as zero/); }); it('an empty archive is an honest state, not a broken page', () => { expect(ARCHIVE).toMatch(/No issues published yet/); }); });