// The town-crier leg's own tests, moved out of core's announceJobs.test.js in // Phase 3 (MODULE_SYSTEM.md §2.7.1). // // Core keeps what it owns there — the backoff schedule, the parent-status rollup // and the Discord leg — because those are the announce PIPELINE. What is here is // this module's LEG: how a post becomes town-crier lines, and how the sidecar's // answers classify into done / retry / terminal. The split is the same one the // registry makes. const { test } = require('node:test') const assert = require('node:assert/strict') const { fakeCtx } = require('./_fakes') require('../core').init(fakeCtx()) const townCrier = require('../utils/shardAnnounce') // ── buildTownCrierText ─────────────────────────────────────────────────────── test('buildTownCrierText produces title, excerpt, and URL lines', () => { const lines = townCrier.buildTownCrierText( { id: 7, title: 'Server Update', excerpt: 'Big things afoot.', body: null }, { baseUrl: 'https://uom.example' }, ) assert.deepEqual(lines, ['Server Update', 'Big things afoot.', 'https://uom.example/site/news']) }) test('buildTownCrierText falls back to a stripped body when excerpt is empty', () => { const lines = townCrier.buildTownCrierText( { id: 1, title: 'T', excerpt: '', body: '

Hello world

' }, { baseUrl: 'https://uom.example' }, ) assert.equal(lines[1], 'Hello world') }) test('buildTownCrierText clamps each line to the sidecar per-line cap', () => { const longTitle = 'x'.repeat(500) const lines = townCrier.buildTownCrierText( { id: 1, title: longTitle, excerpt: 'y'.repeat(500), body: null }, { baseUrl: 'https://uom.example' }, ) for (const line of lines) assert.ok(line.length <= townCrier.MAX_LINE_LEN, `line too long: ${line.length}`) assert.ok(lines[0].endsWith('…')) assert.ok(lines.length <= townCrier.MAX_LINES) }) test('buildTownCrierText omits the excerpt line when there is no excerpt or body', () => { const lines = townCrier.buildTownCrierText( { id: 1, title: 'Only a title', excerpt: null, body: null }, { baseUrl: 'https://uom.example' }, ) assert.deepEqual(lines, ['Only a title', 'https://uom.example/site/news']) }) // ── classifyTownCrier ──────────────────────────────────────────────────────── test('town crier classify: 2xx is done', () => { assert.equal(townCrier.classify({ ok: true, status: 200 }).outcome, 'done') }) test('town crier classify: over-cap / auth / protocol errors are terminal (no retry)', () => { for (const status of [400, 401, 409]) { assert.equal(townCrier.classify({ ok: false, status }).outcome, 'terminal', `status ${status}`) } }) test('town crier classify: shard-transient and network errors retry', () => { for (const status of [503, 504, 500, 0]) { assert.equal(townCrier.classify({ ok: false, status }).outcome, 'retry', `status ${status}`) } })