/** * daemon-notes.test.mjs — `releasedSections()` 的演練(D95 第三輪) * * 這支存在的理由:`releasedSections()` 的產出**會直接變成使用者讀的那一頁** * (`rag.arcrun.dev/docs/help/changelog/`)。它多切一段、少切一段、或把給維護者看的 * preamble 漏出去,都是使用者當場看得到的錯,而建置不會報任何錯。 * * 跑法:node --test collector/cmd/arcrun-app/daemon-notes.test.mjs */ import { test } from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { releasedSections, releasedSectionsFromFile, CHANGELOG_PATH } from './daemon-notes.mjs'; const FIXTURE = [ '# Arcrun 桌面版(daemon)版本說明', '', '> 給維護者看的說明,不該出現在網站上。', '', '## 怎麼出新版(不要手打版本號)', '', '在本檔最上面加一個二級標題:', '', ' <二級標題> 下一版(未發佈)', '', '---', '', '## 下一版(未發佈)', '', '- 🔑 **還沒戳版號的東西**:不該出現在網站上。', '', '## v0.18.29(2026-08-16)', '', '**建議更新**', '', '- 🔑 **甲**:內文甲。', '', '### 小標題也要留著', '', '- 乙', '', '## v0.18.28(2026-08-16)', '', '- 丙', '', ].join('\n'); test('只留已發佈段落:preamble 與「下一版(未發佈)」都不會被投影出去', () => { const { markdown, versions } = releasedSections(FIXTURE); assert.deepEqual(versions, ['v0.18.29', 'v0.18.28']); for (const forbidden of ['給維護者看的說明', '怎麼出新版', '<二級標題>', '下一版(未發佈)', '還沒戳版號']) { assert.ok(!markdown.includes(forbidden), `不該出現在使用者眼前:${forbidden}`); } assert.ok(markdown.startsWith('## v0.18.29(2026-08-16)'), '第一行就該是最新的已發佈版本'); }); test('段落內文原樣保留,`###` 小標題不會被當成段落結束', () => { const { markdown } = releasedSections(FIXTURE); assert.ok(markdown.includes('### 小標題也要留著')); assert.ok(markdown.includes('- 乙'), '`###` 之後的內容仍屬於同一個版本段'); assert.ok(markdown.includes('**建議更新**') && markdown.includes('- 丙')); }); test('一段都沒有就 throw——不准安靜回空字串(那會建出一頁少一半的東西)', () => { assert.throws( () => releasedSectionsFromFile('/nonexistent/CHANGELOG.md'), /找不到 daemon 的版本說明檔/); // 只有未發佈段落時同樣要停 const onlyUnreleased = '# 標題\n\n## 下一版(未發佈)\n\n- 甲\n'; assert.deepEqual(releasedSections(onlyUnreleased).versions, []); }); test('對真的 collector/CHANGELOG.md 跑一次:段數=檔案裡 `## vX.Y.Z` 的行數', () => { const raw = readFileSync(CHANGELOG_PATH, 'utf8'); const expected = raw.split('\n').filter((l) => /^##\s+v\d+\.\d+\.\d+/.test(l)).length; const { versions, markdown } = releasedSectionsFromFile(); assert.equal(versions.length, expected); assert.ok(expected > 0, '真檔裡至少要有一個已發佈版本'); assert.ok(!markdown.includes('單一真相源'), '檔頭那段維護者說明不該被投影出去'); });