111 lines
4.0 KiB
TypeScript
111 lines
4.0 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
const mod = await import("../../scripts/release/gen-contributors.mjs");
|
|
const {
|
|
extractVersionSection,
|
|
parseContributors,
|
|
renderContributors,
|
|
injectContributors,
|
|
NOISE_HANDLES,
|
|
} = mod;
|
|
|
|
const FIXTURE = `# Changelog
|
|
|
|
## [Unreleased]
|
|
|
|
---
|
|
|
|
## [3.9.0] — 2026-08-01
|
|
|
|
### ✨ New Features
|
|
|
|
- **feat(a):** thing one. ([#100](https://github.com/x/y/pull/100) — thanks @alice)
|
|
- **feat(b):** uses \`@toon-format/toon\` and \`@dnd-kit\`. ([#101](https://github.com/x/y/pull/101) — thanks @bob)
|
|
|
|
### 🔧 Bug Fixes
|
|
|
|
- **fix(c):** direct commit fix. (thanks @carol)
|
|
- **fix(d):** extracted. Extracted from [#102](https://github.com/x/y/pull/102) by [@dave](https://github.com/dave).
|
|
|
|
### 📝 Maintenance
|
|
|
|
- **refactor(rollup):** god-file split ([#200](https://github.com/x/y/pull/200), [#201](https://github.com/x/y/pull/201) — thanks @erin); editorconfig ([#202](https://github.com/x/y/pull/202) — thanks @frank). — thanks @diegosouzapw
|
|
|
|
---
|
|
|
|
## [3.8.99] — 2026-07-31
|
|
|
|
### 🔧 Bug Fixes
|
|
|
|
- **fix(z):** other version, must not leak. ([#999](https://github.com/x/y/pull/999) — thanks @zoe)
|
|
|
|
---
|
|
`;
|
|
|
|
test("extractVersionSection returns only the target version body (not the next section)", () => {
|
|
const sec = extractVersionSection(FIXTURE, "3.9.0");
|
|
assert.ok(sec.includes("thing one"), "includes 3.9.0 content");
|
|
assert.ok(!sec.includes("must not leak"), "excludes 3.8.99 content");
|
|
assert.ok(!sec.includes("#999"), "does not bleed into next version");
|
|
});
|
|
|
|
test("parseContributors credits per parenthetical group, not a flat scan", () => {
|
|
const agg = parseContributors(extractVersionSection(FIXTURE, "3.9.0"));
|
|
// rollup: erin gets 200+201, frank gets 202 — NOT both getting all three
|
|
assert.deepEqual(
|
|
[...agg.get("erin")].sort((a, b) => a - b),
|
|
[200, 201]
|
|
);
|
|
assert.deepEqual([...agg.get("frank")], [202]);
|
|
// simple bullets
|
|
assert.deepEqual([...agg.get("alice")], [100]);
|
|
// direct-commit credit with no PR ref
|
|
assert.ok(agg.has("carol") && agg.get("carol").size === 0);
|
|
// "Extracted from #N by @X"
|
|
assert.deepEqual([...agg.get("dave")], [102]);
|
|
});
|
|
|
|
test("noise handles and the maintainer are excluded from the contributor map", () => {
|
|
const agg = parseContributors(extractVersionSection(FIXTURE, "3.9.0"));
|
|
assert.ok(!agg.has("toon-format"), "package scope is not a contributor");
|
|
assert.ok(!agg.has("dnd-kit"), "package scope is not a contributor");
|
|
assert.ok(!agg.has("diegosouzapw"), "maintainer is rendered separately, not in the map");
|
|
assert.ok(NOISE_HANDLES.has("toon-format"));
|
|
});
|
|
|
|
test("renderContributors emits an alphabetical table with maintainer last", () => {
|
|
const agg = parseContributors(extractVersionSection(FIXTURE, "3.9.0"));
|
|
const table = renderContributors("3.9.0", agg);
|
|
assert.ok(table.startsWith("### 🙌 Contributors"));
|
|
const rows = table.split("\n").filter((l) => l.startsWith("| [@"));
|
|
const handles = rows.map((r) => r.match(/@([A-Za-z0-9_-]+)/)[1]);
|
|
assert.equal(handles[handles.length - 1], "diegosouzapw", "maintainer is last");
|
|
const external = handles.slice(0, -1);
|
|
assert.deepEqual(
|
|
external,
|
|
[...external].sort((a, b) => a.localeCompare(b)),
|
|
"external sorted"
|
|
);
|
|
assert.ok(table.includes("| [@carol](https://github.com/carol) | direct commit / report |"));
|
|
});
|
|
|
|
test("injectContributors inserts before the closing --- and is idempotent", () => {
|
|
const once = injectContributors(
|
|
FIXTURE,
|
|
"3.9.0",
|
|
renderContributors("3.9.0", parseContributors(extractVersionSection(FIXTURE, "3.9.0")))
|
|
);
|
|
assert.ok(once.includes("### 🙌 Contributors"), "section injected");
|
|
// 3.8.99 untouched
|
|
assert.ok(once.includes("must not leak"));
|
|
// idempotent: injecting again does not duplicate
|
|
const twice = injectContributors(
|
|
once,
|
|
"3.9.0",
|
|
renderContributors("3.9.0", parseContributors(extractVersionSection(once, "3.9.0")))
|
|
);
|
|
const count = (twice.match(/### 🙌 Contributors/g) || []).length;
|
|
assert.equal(count, 1, "no duplicate Contributors section on re-run");
|
|
});
|