Refactor comment handling logic into performAction for improved testability

This commit is contained in:
Mario Campos
2026-10-09 17:35:09 -05:00
parent f1419b8c76
commit e7dadca872
2 changed files with 109 additions and 9 deletions

View File

@@ -10,7 +10,9 @@ import { describe, it } from "node:test";
import { type ApiClient } from "./api-client";
import {
findExistingComment,
type Options,
parseOptions,
performAction,
resolveToken,
} from "./post-comment";
@@ -211,3 +213,87 @@ describe("findExistingComment", async () => {
assert.equal(id, undefined);
});
});
/** A baseline set of `Options`, for use in `performAction` tests. */
const baseOptions: Options = {
body: "hello",
marker: "<!-- marker -->",
actionCondition: true,
actionIfTrue: "insert",
actionIfFalse: "delete",
issueId: 42,
repository: { owner: "owner", repo: "repo" },
};
describe("performAction", async () => {
await it("does nothing for 'none'", async () => {
const { client, calls } = fakeClient([]);
await performAction(client, "none", baseOptions);
assert.deepEqual(calls, {
createComment: [],
updateComment: [],
deleteComment: [],
});
});
await it("creates a new comment for 'insert', with the marker prepended", async () => {
const { client, calls } = fakeClient([]);
await performAction(client, "insert", baseOptions);
assert.deepEqual(calls.createComment, [
{
owner: "owner",
repo: "repo",
issue_number: 42,
body: "<!-- marker -->\nhello",
},
]);
assert.deepEqual(calls.updateComment, []);
assert.deepEqual(calls.deleteComment, []);
});
await it("creates a new comment for 'upsert' when no existing comment is found", async () => {
const { client, calls } = fakeClient([{ id: 1, body: "unrelated" }]);
await performAction(client, "upsert", 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 for 'upsert' when one is found", async () => {
const { client, calls } = fakeClient([
{ id: 7, body: "<!-- marker -->\nold" },
]);
await performAction(client, "upsert", baseOptions);
assert.deepEqual(calls.updateComment, [
{
owner: "owner",
repo: "repo",
comment_id: 7,
body: "<!-- marker -->\nhello",
},
]);
assert.deepEqual(calls.createComment, []);
});
await it("does nothing for 'delete' when no existing comment is found", async () => {
const { client, calls } = fakeClient([{ id: 1, body: "unrelated" }]);
await performAction(client, "delete", baseOptions);
assert.deepEqual(calls.deleteComment, []);
});
await it("deletes the existing comment for 'delete' when one is found", async () => {
const { client, calls } = fakeClient([
{ id: 9, body: "<!-- marker -->\nold" },
]);
await performAction(client, "delete", baseOptions);
assert.deepEqual(calls.deleteComment, [
{ owner: "owner", repo: "repo", comment_id: 9 },
]);
});
});

View File

@@ -172,16 +172,17 @@ export async function findExistingComment(
return comments.find((comment) => comment.body?.startsWith(marker))?.id;
}
async function main(): Promise<number> {
const options = parseOptions();
const action = options.actionCondition
? options.actionIfTrue
: options.actionIfFalse;
console.info(`Resolved action: ${action}`);
const token = resolveToken(process.env);
/**
* Performs the resolved `action` against a (possibly pre-existing) marked comment, using
* `client` to talk to the GitHub API. This is the core dispatch logic of this script, extracted
* from `main` so it can be unit-tested with an injected (fake) `client`.
*/
export async function performAction(
client: ApiClient,
action: Action,
options: Options,
): Promise<void> {
const { issueId, marker, repository } = options;
const client = getApiClient(token);
const body = `${marker}\n${options.body}`;
let existingCommentId: number | undefined;
@@ -235,6 +236,19 @@ async function main(): Promise<number> {
}
break;
}
}
async function main(): Promise<number> {
const options = parseOptions();
const action = options.actionCondition
? options.actionIfTrue
: options.actionIfFalse;
console.info(`Resolved action: ${action}`);
const token = resolveToken(process.env);
const client = getApiClient(token);
await performAction(client, action, options);
return 0;
}