import { rm, writeFile, readFile, mkdtemp } from 'node:fs/promises'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; import { tap, expect } from '@git.zone/tstest/tapbundle'; import { appendPendingChangelogEntry, movePendingToVersion, readPendingChangelog, } from './ts/helpers.changelog.js'; const withChangelogFile = async ( initialContent: string, testFunction: (filePath: string) => Promise, ) => { const testDir = await mkdtemp(join(tmpdir(), 'gitzone-changelog-')); const changelogPath = join(testDir, 'changelog.md'); try { await writeFile(changelogPath, initialContent); await testFunction(changelogPath); } finally { await rm(testDir, { recursive: true, force: true }); } }; tap.test('readPendingChangelog should not create a missing Pending section', async () => { await withChangelogFile('# Changelog\n\n## 2026-01-01 - 1.0.0\n\n### Fixes\n\n- existing\n', async (filePath) => { const pending = await readPendingChangelog(filePath, 'Pending'); const changelogContent = await readFile(filePath, 'utf8'); expect(pending.isEmpty).toBeTrue(); expect(pending.block).toEqual(''); expect(changelogContent).not.toInclude('## Pending'); }); }); tap.test('movePendingToVersion should fail when Pending is missing', async () => { await withChangelogFile('# Changelog\n\n## 2026-01-01 - 1.0.0\n\n### Fixes\n\n- existing\n', async (filePath) => { let errorMessage = ''; try { await movePendingToVersion(filePath, 'Pending', '## {{date}} - {{version}}', '1.0.1', '2026-01-02'); } catch (error) { errorMessage = error instanceof Error ? error.message : String(error); } expect(errorMessage).toEqual('No pending changelog entries. Nothing to release.'); const changelogContent = await readFile(filePath, 'utf8'); expect(changelogContent).not.toInclude('## Pending'); }); }); tap.test('movePendingToVersion should remove the consumed Pending section', async () => { await withChangelogFile('# Changelog\n\n## Pending\n\n### Fixes\n\n- pending fix\n\n## 2026-01-01 - 1.0.0\n\n### Fixes\n\n- existing\n', async (filePath) => { await movePendingToVersion(filePath, 'Pending', '## {{date}} - {{version}}', '1.0.1', '2026-01-02'); const changelogContent = await readFile(filePath, 'utf8'); expect(changelogContent).not.toInclude('## Pending'); expect(changelogContent).toInclude('## 2026-01-02 - 1.0.1\n\n### Fixes\n\n- pending fix'); expect(changelogContent).toInclude('## 2026-01-01 - 1.0.0\n\n### Fixes\n\n- existing'); }); }); tap.test('appendPendingChangelogEntry should recreate Pending when needed', async () => { await withChangelogFile('# Changelog\n\n## 2026-01-01 - 1.0.0\n\n### Fixes\n\n- existing\n', async (filePath) => { await appendPendingChangelogEntry(filePath, 'Pending', { type: 'fix', scope: 'changelog', message: 'record pending changes', }); const changelogContent = await readFile(filePath, 'utf8'); expect(changelogContent).toInclude('## Pending\n\n### Fixes\n\n- record pending changes (changelog)'); expect(changelogContent).toInclude('## 2026-01-01 - 1.0.0'); }); }); export default tap.start();