All checks were successful
Deploy MineGeo to Dokploy / deploy (push) Successful in 5m17s
154 lines
5.0 KiB
TypeScript
154 lines
5.0 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
import { createElement } from "react";
|
|
import {
|
|
parseReleasePost,
|
|
RELEASE_NEWS_CHANNEL,
|
|
RELEASE_WEBHOOK_ID,
|
|
} from "../shared/changelog";
|
|
import { readChangelogFeed } from "../lib/changelog-feed";
|
|
import { ReleaseNotes } from "../components/ReleaseNotes";
|
|
|
|
const post = (content: string) => ({
|
|
id: "1561021045211660402",
|
|
channel_id: RELEASE_NEWS_CHANNEL,
|
|
webhook_id: RELEASE_WEBHOOK_ID,
|
|
timestamp: "2026-10-20T08:00:00Z",
|
|
content,
|
|
});
|
|
|
|
test("release posts remove roles, punctuation and each published footer format", () => {
|
|
for (const kind of ["Alpha", "Beta", "Production", "Bug fix"]) {
|
|
for (const footer of [
|
|
"<https://minegeo.site>",
|
|
"<https://minegeo.site/>",
|
|
'[https://minegeo.site/](https://minegeo.site/ "https://minegeo.site/")',
|
|
]) {
|
|
const entry = parseReleasePost(
|
|
post(
|
|
`<@&1558052962817933322>, <@&1558053208008433705>.\n## MineGeo 1.0.4.1 ${kind}\n\nA new release. 😄\n\n- **Fixed:** Shared timers.\n\nPLAY THE MINEGEO AT: ${footer}`,
|
|
),
|
|
);
|
|
assert.equal(entry?.kind, kind);
|
|
assert.equal(
|
|
entry?.body,
|
|
"A new release. 😄\n\n- **Fixed:** Shared timers.",
|
|
);
|
|
assert.equal(entry?.version, "1.0.4.1");
|
|
}
|
|
}
|
|
});
|
|
|
|
test("only the release webhook's complete release posts appear", () => {
|
|
const valid = post("## MineGeo 1.0.4 Beta\nHello");
|
|
assert.equal(
|
|
parseReleasePost({ ...valid, webhook_id: "111111111111111111" }),
|
|
null,
|
|
);
|
|
assert.equal(parseReleasePost({ ...valid, webhook_id: undefined }), null);
|
|
assert.equal(parseReleasePost({ ...valid, timestamp: "invalid" }), null);
|
|
assert.equal(
|
|
parseReleasePost(post("## Community tournament\nStarts soon")),
|
|
null,
|
|
);
|
|
assert.equal(parseReleasePost(post("## MineGeo 1.0.4 Beta\n")), null);
|
|
});
|
|
|
|
test("release headings can include a descriptive subtitle", () => {
|
|
const entry = parseReleasePost(
|
|
post(
|
|
"## MineGeo 1.0.5 Beta — Changelog Update\n\nA new release.\n\nPLAY THE MINEGEO AT: <https://minegeo.site/>",
|
|
),
|
|
);
|
|
assert.equal(entry?.title, "MineGeo 1.0.5 Beta — Changelog Update");
|
|
assert.equal(entry?.body, "A new release.");
|
|
});
|
|
|
|
test("feed uses only GET, preserves older pagination through non-release posts", async () => {
|
|
let calls = 0;
|
|
const request: typeof fetch = async (url, options) => {
|
|
calls++;
|
|
assert.equal(options?.method, "GET");
|
|
assert.equal(
|
|
new URL(String(url)).searchParams.get("before"),
|
|
"1661021045211660402",
|
|
);
|
|
assert.equal(
|
|
new Headers(options?.headers).get("Authorization"),
|
|
"Bot test-token",
|
|
);
|
|
const posts = Array.from({ length: 100 }, (_, i) => ({
|
|
...post("Tournament news"),
|
|
id: String(1561021045211660500n - BigInt(i)),
|
|
}));
|
|
posts[0].content = "## MineGeo 1.0.4 Beta\n- **New:** Void";
|
|
return Response.json(posts);
|
|
};
|
|
const feed = await readChangelogFeed({
|
|
token: "test-token",
|
|
request,
|
|
before: "1661021045211660402",
|
|
});
|
|
assert.equal(calls, 1);
|
|
assert.equal(feed.entries.length, 1);
|
|
assert.equal(feed.before, "1561021045211660401");
|
|
});
|
|
|
|
test("feed fails cleanly on denied access, rate limits and wrong channel data", async () => {
|
|
for (const status of [401, 403, 429, 500]) {
|
|
await assert.rejects(
|
|
readChangelogFeed({
|
|
token: "test",
|
|
request: async () => new Response("", { status }),
|
|
}),
|
|
);
|
|
}
|
|
await assert.rejects(
|
|
readChangelogFeed({
|
|
token: "test",
|
|
request: async () =>
|
|
Response.json([{ ...post("test"), channel_id: "other" }]),
|
|
}),
|
|
);
|
|
});
|
|
|
|
test("redacted webhook messages are unavailable rather than an empty release history", async () => {
|
|
await assert.rejects(
|
|
readChangelogFeed({
|
|
token: "test",
|
|
request: async () => Response.json([post("")]),
|
|
}),
|
|
/Message Content/,
|
|
);
|
|
});
|
|
|
|
test("release Markdown renders emphasis and safe links, escaping executable HTML", () => {
|
|
const html = renderToStaticMarkup(
|
|
createElement(ReleaseNotes, {
|
|
body: "- **New:** Void\n- <script>alert(1)</script>\n\n[Guide](https://minegeo.site/docs) [bad](javascript:alert)",
|
|
}),
|
|
);
|
|
assert.match(html, /<strong>New:<\/strong>/);
|
|
assert.match(html, /<script>/);
|
|
assert.match(html, /href="https:\/\/minegeo.site\/docs"/);
|
|
assert.doesNotMatch(html, /href="javascript:/);
|
|
});
|
|
|
|
test("release lists directly after a paragraph and wrapped bullet text remain lists", () => {
|
|
const html = renderToStaticMarkup(
|
|
createElement(ReleaseNotes, {
|
|
body: "This release improves:\n- **Controls:** Keyboard access\n and fixed map gestures.\n- Changelog lists.\nMore updates soon.",
|
|
}),
|
|
);
|
|
assert.match(html, /<p>This release improves:<\/p><ul>/);
|
|
assert.match(
|
|
html,
|
|
/<li><strong>Controls:<\/strong> Keyboard access and fixed map gestures\.<\/li>/,
|
|
);
|
|
assert.match(
|
|
html,
|
|
/<li>Changelog lists\.<\/li><\/ul><p>More updates soon\.<\/p>/,
|
|
);
|
|
});
|