Files
Codeman/test/whats-new.test.ts
T
Codeman maintainer 02ea9251f8 fix(#618): keep the release commit green when a release has no bold lead-ins
The shipped-json test asserted at least one highlight. Many releases are
written without bold lead-ins (1.32.1, 1.29.1 and 1.24.7 here, and every
changesets-bot release whose changesets are plain sentences, this PR's own
changeset included), and the generator handles that on purpose: it warns
and writes an empty list, and the client then stays quiet. Running
`npm run version-packages` in a scratch copy with only this PR's changeset
produced `{"version":"1.42.0","highlights":[]}` and turned the gate red
on exactly the release commit. The version check, which is what keeps a
hand bump from shipping the previous release's notes, stays.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:27:26 +02:00

77 lines
2.8 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
// @ts-expect-error plain .mjs helper shared with scripts/generate-whats-new.mjs
import { extractHighlights, versionSection, buildWhatsNew } from '../scripts/lib/whats-new.mjs';
const root = resolve(import.meta.dirname, '..');
const CHANGELOG = `# aicodeman
## 1.2.0
### Minor Changes
- ### Thanks
- @someone for a fix
**The tile grid: six sessions side by side.** Body text with **inline bold** later.
- **Split view (#560).** More text.
- A bullet with no bold lead.
**Behaviour change: \`Ctrl+W\` no longer closes a session.** Details.
## 1.1.0
- **Old feature.** Not for 1.2.0.
`;
describe('whats-new extraction', () => {
it('limits itself to the requested version section', () => {
const section = versionSection(CHANGELOG, '1.2.0');
expect(section).toContain('tile grid');
expect(section).not.toContain('Old feature');
expect(versionSection(CHANGELOG, '9.9.9')).toBe('');
});
it('takes bold lead-ins only, cleaned, and skips the Thanks block', () => {
expect(extractHighlights(versionSection(CHANGELOG, '1.2.0'))).toEqual([
'The tile grid: six sessions side by side',
'Split view (#560)',
'Behaviour change: `Ctrl+W` no longer closes a session',
]);
});
it('caps the list', () => {
const many = Array.from({ length: 20 }, (_, i) => `**Feature number ${i}.** text`).join('\n\n');
expect(extractHighlights(many)).toHaveLength(8);
});
it('builds the payload the client reads', () => {
expect(buildWhatsNew(CHANGELOG, '1.2.0').version).toBe('1.2.0');
});
});
describe('shipped whats-new.json', () => {
it("matches the package version, so a release cannot ship the previous release's notes", () => {
const pkg = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8'));
const notes = JSON.parse(readFileSync(resolve(root, 'src/web/public/whats-new.json'), 'utf8'));
expect(notes.version).toBe(pkg.version);
// A release written without bold lead-ins legitimately has none (the client then stays
// quiet), so an empty list must not turn the release commit's CI red.
expect(Array.isArray(notes.highlights)).toBe(true);
});
it('is regenerated by the release script and consumed once per version by the client', () => {
const pkg = readFileSync(resolve(root, 'package.json'), 'utf8');
expect(pkg).toMatch(/"version-packages": "changeset version && node scripts\/generate-whats-new\.mjs/);
const ui = readFileSync(resolve(root, 'src/web/public/settings-ui.js'), 'utf8');
expect(ui).toContain("'codeman-whats-new-seen'");
expect(ui).toContain("fetch('/whats-new.json'");
expect(readFileSync(resolve(root, 'src/web/public/app.js'), 'utf8')).toContain(
'this.checkWhatsNew?.(data.version)'
);
});
});