Files
fusion/scripts/__tests__/changelog-sync.test.mjs
gsxdsm 7911fdb9b1 fix(release): preserve distilled changelog summaries across releases
syncRootChangelog rewrote every prior release from raw package notes, so only
the latest distilled Highlights view survived. Re-emit already-distilled bodies
on sync, keep the archive pointer outside version sections, and restore wiped
summaries from release history.
2026-07-21 20:29:46 -07:00

158 lines
4.1 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import {
buildRootChangelogLines,
collectDistilledBodies,
isDistilledChangelogBody,
normalizeChangelogLines,
parseChangelog,
stripArchivePointerFromBody,
} from "../lib/changelog-sync.mjs";
const distilledBody = `### Highlights
- Cool feature
### New
- Cool feature details
### Fixed
- Bug fix
`;
const rawPackageBody = `### @runfusion/fusion
#### Minor Changes
- abc1234: summary: Cool feature.
category: feature
`;
test("isDistilledChangelogBody accepts Highlights/category sections", () => {
assert.equal(isDistilledChangelogBody(distilledBody), true);
assert.equal(isDistilledChangelogBody("### New\n\n- Only new."), true);
assert.equal(isDistilledChangelogBody("### Fixed\n\n- Only fix."), true);
});
test("isDistilledChangelogBody rejects raw package aggregates", () => {
assert.equal(isDistilledChangelogBody(rawPackageBody), false);
assert.equal(
isDistilledChangelogBody("### @fusion/core\n\n#### Patch Changes\n\n- dep bump"),
false,
);
});
test("isDistilledChangelogBody rejects empty and non-category prose", () => {
assert.equal(isDistilledChangelogBody(""), false);
assert.equal(isDistilledChangelogBody("Just some notes without headings."), false);
});
test("stripArchivePointerFromBody removes trailing archive pointer", () => {
const withPointer = `${distilledBody}\n\n> Older releases (before 0.60.0) are archived in [\`CHANGELOG-archive.md\`](./CHANGELOG-archive.md).`;
assert.equal(stripArchivePointerFromBody(withPointer), distilledBody.trim());
assert.equal(isDistilledChangelogBody(withPointer), true);
});
test("parseChangelog splits version sections", () => {
const raw = `# Fusion changelog
## 1.1.0
### Highlights
- One
## 1.0.0
### @runfusion/fusion
#### Patch Changes
- Two
`;
const { versions, order } = parseChangelog(raw);
assert.deepEqual(order, ["1.1.0", "1.0.0"]);
assert.match(versions.get("1.1.0"), /### Highlights/);
assert.match(versions.get("1.0.0"), /### @runfusion\/fusion/);
});
test("collectDistilledBodies keeps only distilled sections; first wins", () => {
const current = `# Fusion changelog
## 1.2.0
${distilledBody}
## 1.1.0
${rawPackageBody}
`;
const archive = `# Archive
## 1.2.0
### Highlights
- Stale older summary that must not win
## 0.9.0
### Fixed
- Archive-only distilled fix
`;
const bodies = collectDistilledBodies([current, archive]);
assert.equal(bodies.get("1.2.0"), distilledBody.trim());
assert.equal(bodies.has("1.1.0"), false);
assert.match(bodies.get("0.9.0"), /Archive-only distilled fix/);
});
test("buildRootChangelogLines preserves distilled bodies over package aggregate", () => {
const parsed = [
{
pkgName: "@runfusion/fusion",
versions: new Map([
["1.1.0", "### Minor Changes\n\n- raw entry"],
["1.0.0", "### Patch Changes\n\n- old raw"],
]),
},
];
const preservedBodies = new Map([["1.0.0", distilledBody.trim()]]);
const out = normalizeChangelogLines(
buildRootChangelogLines({
title: "# Fusion changelog",
banner: "banner",
parsed,
versionOrder: ["1.1.0", "1.0.0"],
preservedBodies,
}),
);
// New/raw version still package-aggregated.
assert.match(out, /## 1\.1\.0\n\n### @runfusion\/fusion/);
assert.match(out, /raw entry/);
// Prior distilled version kept summarized form, not package heading.
assert.match(out, /## 1\.0\.0\n\n### Highlights/);
assert.match(out, /Cool feature/);
assert.doesNotMatch(out, /## 1\.0\.0[\s\S]*### @runfusion\/fusion/);
assert.doesNotMatch(out, /old raw/);
});
test("buildRootChangelogLines falls back to package aggregate without preserve", () => {
const parsed = [
{
pkgName: "@fusion/core",
versions: new Map([["2.0.0", "### Patch Changes\n\n- only raw"]]),
},
];
const out = normalizeChangelogLines(
buildRootChangelogLines({
title: "# Changelog",
banner: "b",
parsed,
versionOrder: ["2.0.0"],
}),
);
assert.match(out, /### @fusion\/core/);
assert.match(out, /#### Patch Changes/);
assert.match(out, /only raw/);
});