mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 14:15:24 +00:00
feat: changelog.md release notes, v tags, plugin release notes and videos
This commit is contained in:
1 parent
b9dd3488a5
commit
9bc2be721b
45 files changed
+1462
-816
No files matched your search
@@ -680,3 +680,40 @@ describe("installing from a file", () => {
|
||||
).rejects.toMatchObject({ code: "UPLOAD_EXPIRED" });
|
||||
});
|
||||
});
|
||||
|
||||
describe("release notes", () => {
|
||||
it("reads an installed plugin's CHANGELOG.md", async () => {
|
||||
createFixturePlugin({ id: "docker", root: bundled });
|
||||
fs.writeFileSync(
|
||||
path.join(bundled, "docker", "CHANGELOG.md"),
|
||||
"# Changelog\n\n## 1.1.0 - 2026-10-06\n\n### Fixed\n- A bug\n\n## 1.0.0\n\n### Added\n- First\n",
|
||||
);
|
||||
await boot();
|
||||
expect(await manage.getPluginChangelog("docker")).toEqual([
|
||||
{
|
||||
version: "1.1.0",
|
||||
date: "2026-10-06",
|
||||
changes: [{ type: "fixed", text: "A bug" }],
|
||||
},
|
||||
{ version: "1.0.0", changes: [{ type: "added", text: "First" }] },
|
||||
]);
|
||||
});
|
||||
|
||||
it("is empty without a changelog and 404s for an unknown plugin", async () => {
|
||||
createFixturePlugin({ id: "docker", root: bundled });
|
||||
await boot();
|
||||
expect(await manage.getPluginChangelog("docker")).toEqual([]);
|
||||
await expect(manage.getPluginChangelog("nope")).rejects.toMatchObject({
|
||||
status: 404,
|
||||
});
|
||||
});
|
||||
|
||||
it("parses registry notes and drops empty ones", () => {
|
||||
expect(manage.readReleaseNotes("Summary.\n\n### Added\n- Thing")).toEqual({
|
||||
summary: "Summary.",
|
||||
changes: [{ type: "added", text: "Thing" }],
|
||||
});
|
||||
expect(manage.readReleaseNotes("")).toBeUndefined();
|
||||
expect(manage.readReleaseNotes(undefined)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
validateManifest,
|
||||
SUPPORTED_PLUGIN_API_VERSION,
|
||||
isTermixCompatible,
|
||||
youtubeVideoId,
|
||||
} from "../../plugins/manifest.js";
|
||||
|
||||
function base(overrides: Record<string, unknown> = {}) {
|
||||
@@ -852,3 +853,47 @@ describe("contributes.protocols", () => {
|
||||
expect(errors.join("\n")).toMatch(/extra/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("manifest video", () => {
|
||||
it("accepts YouTube links", () => {
|
||||
for (const video of [
|
||||
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
||||
"https://youtu.be/dQw4w9WgXcQ",
|
||||
"https://www.youtube.com/embed/dQw4w9WgXcQ",
|
||||
"https://youtube.com/shorts/dQw4w9WgXcQ",
|
||||
]) {
|
||||
expect(validateManifest(base({ video }))).toEqual([]);
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects anything that is not a YouTube video", () => {
|
||||
for (const video of [
|
||||
"https://evil.example/watch?v=dQw4w9WgXcQ",
|
||||
"http://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
||||
"https://www.youtube.com.evil.example/watch?v=dQw4w9WgXcQ",
|
||||
"https://user@www.youtube.com/watch?v=dQw4w9WgXcQ",
|
||||
"https://www.youtube.com/watch?v=short",
|
||||
"https://www.youtube.com/channel/UC123",
|
||||
"javascript:alert(1)",
|
||||
"",
|
||||
42,
|
||||
]) {
|
||||
expect(validateManifest(base({ video }))).toEqual([
|
||||
expect.stringContaining('Field "video" must be a YouTube link'),
|
||||
]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("youtubeVideoId", () => {
|
||||
it("returns only the id", () => {
|
||||
expect(
|
||||
youtubeVideoId("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=42"),
|
||||
).toBe("dQw4w9WgXcQ");
|
||||
expect(youtubeVideoId("https://youtu.be/dQw4w9WgXcQ?si=abc")).toBe(
|
||||
"dQw4w9WgXcQ",
|
||||
);
|
||||
expect(youtubeVideoId("https://youtu.be/../../x")).toBeNull();
|
||||
expect(youtubeVideoId(undefined)).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -121,6 +121,28 @@ describe("parseRegistryIndex", () => {
|
||||
expect(index.plugins.map((p) => p.id)).toEqual(["ok"]);
|
||||
});
|
||||
|
||||
it("keeps release notes and only a YouTube video id", () => {
|
||||
const NOTES = "### Added\n- Thing";
|
||||
const index = parseRegistryIndex({
|
||||
plugins: [
|
||||
{
|
||||
id: "docker",
|
||||
video: "https://youtu.be/dQw4w9WgXcQ",
|
||||
versions: [version({ notes: NOTES })],
|
||||
},
|
||||
{
|
||||
id: "other",
|
||||
video: "https://evil.example/watch?v=dQw4w9WgXcQ",
|
||||
versions: [version({ notes: "x".repeat(30_000) })],
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(index.plugins[0].videoId).toBe("dQw4w9WgXcQ");
|
||||
expect(index.plugins[0].versions[0].notes).toBe(NOTES);
|
||||
expect(index.plugins[1].videoId).toBeUndefined();
|
||||
expect(index.plugins[1].versions[0].notes).toHaveLength(20_000);
|
||||
});
|
||||
|
||||
it("refuses something that is not an index", () => {
|
||||
expect(() => parseRegistryIndex({ nope: true })).toThrow(/no plugins/);
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user