testReleasesInEditor
releases in the editor: packages, the next release and why, drafting, releasing, the changelog, packing
import { plainEnv, tcmBin, tempDir, withChildren } from "#codebase/tcmts/cli/test/e2e/harness"; import { client } from "#codebase/tcmts/cli/test/e2e/lsp"; import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; export const testReleasesInEditor = () => withChildren(async (keep) => { const dir6 = tempDir("lsp releases"); const tcm = (...args: string[]) => spawnSync(process.execPath, [tcmBin(), ...args], { cwd: dir6, env: plainEnv(), encoding: "utf8" }); tcm("init"); fs.writeFileSync(path.join(dir6, "scratch.ts"), `// tcm: namespace geo\n/** Plane geometry. */\nexport const manifest = { name: "geo" };\nexport interface Point { x: number; y: number }\n/** The distance between two points. */\nexport const distance = (a: Point, b: Point): number => Math.hypot(a.x - b.x, a.y - b.y);\n`); assert.equal(tcm("add").status, 0); assert.equal(tcm("release").status, 0); fs.writeFileSync(path.join(dir6, "scratch.ts"), `// tcm: namespace geo\nexport interface Point { x: number; y: number; label: string }\n`); assert.equal(tcm("update").status, 0); const c = client(keep); await c.request("initialize", { processId: null, rootUri: pathToFileURL(dir6).href, capabilities: {}, clientInfo: { name: "Visual Studio Code" } }); c.notify("initialized", {}); const list = await c.request("tcm/publishing", {}); assert.deepEqual(list.map((p: { name: string; namespace: string; latest: { version: string } }) => [p.name, p.namespace, p.latest.version]), [["geo", "geo", "0.1.0"]]); assert.equal(list[0].description, "Plane geometry."); // the next release, and every finding behind it, with the definition each is about const check = await c.request("tcm/releaseCheck", { name: "geo" }); assert.equal(check.version, "0.2.0"); assert.equal(check.reason, "breaking changes"); const f = check.findings.find((x: { lint: string }) => x.lint === "type_required_property_added"); assert.deepEqual([f.path, f.level, f.detail], ["geo.Point", "major", "label"]); assert.match(f.why, /values written for the old type lack it/); assert.ok(f.hash, "a finding links to its definition"); assert.match(check.notes, /### Breaking changes\n\n- `geo\.Point` has a new required property: `label`/); // drafting writes the scratch file the editor opens; releasing takes its words const draft = await c.request("workspace/executeCommand", { command: "tcm.releaseDraft", arguments: ["geo"] }); const file = fileURLToPath(draft); assert.equal(path.basename(file), "release-geo.md"); fs.writeFileSync(file, fs.readFileSync(file, "utf8").replace("<!-- what this release is about, for the people who use it -->", "Points have labels.")); assert.deepEqual(await c.request("workspace/executeCommand", { command: "tcm.release", arguments: ["geo"] }), { package: "geo", version: "0.2.0" }); await c.waitFor(() => c.notes.find((n) => n.method === "window/showMessage" && /released geo@0\.2\.0: breaking changes/.test(n.params.message))); assert.ok(!fs.existsSync(file)); // the page: the manifest, the next release, the changelog const page = await c.request("tcm/releasePage", { name: "geo" }); assert.deepEqual(page.exports, [{ subpath: ".", count: 2 }]); assert.deepEqual(page.releases.map((r: { version: string }) => r.version), ["0.2.0", "0.1.0"]); assert.equal(page.releases[0].summary, "Points have labels."); assert.equal(page.next.upToDate, true, "nothing new since the release"); assert.deepEqual((await c.request("tcm/releaseList", { name: "geo" })).map((r: { version: string }) => r.version), ["0.2.0", "0.1.0"]); assert.match((await c.request("tcm/releaseList", { name: "geo" }))[0].body, /^Points have labels\.\n\n### Breaking changes/); assert.match((await c.request("tcm/changelog", { name: "geo" })).markdown, /^# Changelog\n\n## 0\.2\.0 .*\n\nPoints have labels\./); const dir = await c.request("workspace/executeCommand", { command: "tcm.pack", arguments: ["geo", "0.2.0"] }); assert.equal(JSON.parse(fs.readFileSync(path.join(dir, "package.json"), "utf8")).version, "0.2.0"); assert.ok(fs.existsSync(path.join(dir, "CHANGELOG.md"))); await assert.rejects(c.request("tcm/releasePage", { name: "nope" }), /no package nope/); await c.request("shutdown", null); })