Files
codeql-action/pr-checks/post-comment.test.ts
2026-10-28 16:00:37 -05:00

252 lines
6.8 KiB
TypeScript

#!/usr/bin/env npx tsx
/*
Tests for post-comment.ts.
*/
import * as assert from "node:assert/strict";
import { describe, it } from "node:test";
import { type ApiClient } from "./api-client";
import {
findExistingComment,
type Options,
parseOptions,
resolveToken,
setComment,
} from "./post-comment";
/** A baseline set of valid CLI flags, as an array, for use in parseOptions tests. */
const validFlags = [
"--body",
"hello",
"--marker",
"<!-- marker -->",
"--issue-id",
"42",
"--repository",
"github/codeql-action",
];
/** Returns a copy of `validFlags` with the value following `flag` replaced by `value`. */
function withFlag(flag: string, value: string): string[] {
const flags = [...validFlags];
const index = flags.indexOf(flag);
flags[index + 1] = value;
return flags;
}
/** Returns a copy of `validFlags` with `flag` (and its value) removed entirely. */
function withoutFlag(flag: string): string[] {
const flags = [...validFlags];
const index = flags.indexOf(flag);
flags.splice(index, 2);
return flags;
}
describe("parseOptions", async () => {
await it("parses valid flags", () => {
const options = parseOptions(validFlags);
assert.deepEqual(options, {
body: "hello",
marker: "<!-- marker -->",
issueId: 42,
repository: { owner: "github", repo: "codeql-action" },
});
});
await it("rejects a missing --marker", () => {
assert.throws(
() => parseOptions(withoutFlag("--marker")),
/Missing required flag --marker/,
);
});
await it("rejects an empty --marker", () => {
assert.throws(
() => parseOptions(withFlag("--marker", "")),
/Missing required flag --marker/,
);
});
await it("rejects a whitespace-only --marker", () => {
assert.throws(
() => parseOptions(withFlag("--marker", " \t\n")),
/Missing required flag --marker/,
);
});
await it("rejects unknown flags using parseArgs", () => {
assert.throws(() => parseOptions([...validFlags, "--unknown", "value"]), {
code: "ERR_PARSE_ARGS_UNKNOWN_OPTION",
});
});
await it("rejects flags without a value using parseArgs", () => {
assert.throws(() => parseOptions([...validFlags, "--body"]), {
code: "ERR_PARSE_ARGS_INVALID_OPTION_VALUE",
});
});
});
describe("resolveToken", async () => {
await it("reads the token from GH_TOKEN", () => {
assert.equal(
resolveToken({ GH_TOKEN: "gh-token", GITHUB_TOKEN: "gha-token" }),
"gh-token",
);
});
await it("falls back to GITHUB_TOKEN", () => {
assert.equal(resolveToken({ GITHUB_TOKEN: "gha-token" }), "gha-token");
});
await it("throws when no token is set", () => {
assert.throws(() => resolveToken({}), /Missing authentication token/);
});
});
/** A minimal fake of the subset of `ApiClient` used by post-comment.ts. */
function fakeClient(existingComments: Array<{ id: number; body?: string }>) {
const calls: {
createComment: unknown[];
updateComment: unknown[];
} = { createComment: [], updateComment: [] };
const client = {
paginate: async () => existingComments,
rest: {
issues: {
listComments: () => {},
createComment: async (params: unknown) => {
calls.createComment.push(params);
},
updateComment: async (params: unknown) => {
calls.updateComment.push(params);
},
},
},
};
return { client: client as unknown as ApiClient, calls };
}
describe("findExistingComment", async () => {
await it("finds the id of the first comment containing the marker", async () => {
const { client } = fakeClient([
{ id: 1, body: "unrelated" },
{ id: 2, body: "<!-- marker -->\nhello" },
{ id: 3, body: "<!-- marker -->\nanother" },
]);
const id = await findExistingComment(
client,
{ owner: "owner", repo: "repo" },
1,
"<!-- marker -->",
);
assert.equal(id, 2);
});
await it("returns undefined when no comment matches", async () => {
const { client } = fakeClient([{ id: 1, body: "unrelated" }]);
const id = await findExistingComment(
client,
{ owner: "owner", repo: "repo" },
1,
"<!-- marker -->",
);
assert.equal(id, undefined);
});
});
/** A baseline set of `Options`, for use in `setComment` tests. */
const baseOptions: Options = {
body: "hello",
marker: "<!-- marker -->",
issueId: 42,
repository: { owner: "owner", repo: "repo" },
};
describe("setComment", async () => {
await it("uses the supplied marker without affecting other comments", async () => {
const marker = "<!-- custom-warning -->";
const { client, calls } = fakeClient([
{ id: 1, body: "<!-- marker -->\nunrelated warning" },
{ id: 2, body: `${marker}\nold warning` },
]);
const options = parseOptions(withFlag("--marker", marker));
await setComment(client, options);
assert.deepEqual(calls, {
createComment: [],
updateComment: [
{
...options.repository,
comment_id: 2,
body: `${marker}\nhello`,
},
],
});
});
await it("creates a new comment with the marker prepended", async () => {
const { client, calls } = fakeClient([]);
await setComment(client, baseOptions);
assert.deepEqual(calls.createComment, [
{
owner: "owner",
repo: "repo",
issue_number: 42,
body: "<!-- marker -->\nhello",
},
]);
assert.deepEqual(calls.updateComment, []);
});
await it("creates a new comment when no existing comment matches", async () => {
const { client, calls } = fakeClient([{ id: 1, body: "unrelated" }]);
await setComment(client, baseOptions);
assert.deepEqual(calls.createComment, [
{
owner: "owner",
repo: "repo",
issue_number: 42,
body: "<!-- marker -->\nhello",
},
]);
assert.deepEqual(calls.updateComment, []);
});
await it("updates the existing comment when one is found", async () => {
const { client, calls } = fakeClient([
{ id: 7, body: "<!-- marker -->\nold" },
]);
await setComment(client, baseOptions);
assert.deepEqual(calls.updateComment, [
{
owner: "owner",
repo: "repo",
comment_id: 7,
body: "<!-- marker -->\nhello",
},
]);
assert.deepEqual(calls.createComment, []);
});
await it("replaces a warning with the resolved state using the same marker", async () => {
const { client, calls } = fakeClient([
{ id: 9, body: "<!-- marker -->\nold" },
]);
const body =
"`CHANGELOG.md` is not modified in this PR. No changelog action is needed.";
await setComment(client, { ...baseOptions, body });
assert.deepEqual(calls.updateComment, [
{
...baseOptions.repository,
comment_id: 9,
body: `${baseOptions.marker}\n${body}`,
},
]);
assert.deepEqual(calls.createComment, []);
});
});