test(plugins): mirror checkbox selection rules

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Michael NguyenandPaperclip committed 2026-07-24 01:10:47 -07:00
1 parent 942a2fe768
commit 963ece7848
2 files changed
+63 -12

No files matched your search

+27 -11
View File
@@ -1,5 +1,5 @@
import { randomUUID } from "node:crypto";
import { pluginOperationIssueOriginKind } from "@paperclipai/shared";
import { acceptIssueThreadInteractionSchema, pluginOperationIssueOriginKind } from "@paperclipai/shared";
import type {
PaperclipPluginManifestV1,
PluginCapability,
@@ -1807,19 +1807,35 @@ export function createTestHarness(options: TestHarnessOptions): TestHarness {
if (current.status !== "pending") {
return { interaction: current, applied: false };
}
let checkboxResult: { version: 1; outcome: "accepted"; selectedOptionIds: string[] } | undefined;
if (input.action === "accept" && current.kind === "request_checkbox_confirmation") {
const parsed = acceptIssueThreadInteractionSchema.parse(input);
const optionIds = new Set(current.payload.options.map((option) => option.id));
const selectedOptionIds = parsed.selectedOptionIds
?? current.payload.defaultSelectedOptionIds
?? [];
for (const optionId of selectedOptionIds) {
if (!optionIds.has(optionId)) {
throw new Error(`Unknown checkbox confirmation optionId: ${optionId}`);
}
}
const selected = current.payload.options
.filter((option) => selectedOptionIds.includes(option.id))
.map((option) => option.id);
const minSelected = current.payload.minSelected ?? 0;
const maxSelected = current.payload.maxSelected ?? null;
if (selected.length < minSelected) {
throw new Error(`Select at least ${minSelected} checkbox confirmation option(s)`);
}
if (maxSelected != null && selected.length > maxSelected) {
throw new Error(`Select no more than ${maxSelected} checkbox confirmation option(s)`);
}
checkboxResult = { version: 1, outcome: "accepted", selectedOptionIds: selected };
}
const resolved: IssueThreadInteraction = {
...current,
status: input.action === "accept" ? "accepted" : "rejected",
...(input.action === "accept"
&& current.kind === "request_checkbox_confirmation"
&& input.selectedOptionIds !== undefined
? {
result: {
outcome: "accepted",
selectedOptionIds: input.selectedOptionIds,
},
}
: {}),
...(checkboxResult ? { result: checkboxResult } : {}),
updatedAt: new Date(),
} as IssueThreadInteraction;
const index = list.indexOf(current);
@@ -77,7 +77,21 @@ describe("createTestHarness issue interactions", () => {
it("creates request_checkbox_confirmation interactions through the typed host helper", async () => {
const harness = createTestHarness({
manifest,
capabilities: ["issues.create", "issue.interactions.create"],
capabilities: ["issues.create", "issue.interactions.create", "issue.interactions.respond"],
});
const now = new Date().toISOString();
harness.seed({
accessMembers: [{
id: "member-1",
companyId: "company-1",
principalType: "user",
principalId: "user-1",
status: "active",
membershipRole: "operator",
grants: [],
createdAt: now,
updatedAt: now,
}],
});
const issue = await harness.ctx.issues.create({
companyId: "company-1",
@@ -126,5 +140,26 @@ describe("createTestHarness issue interactions", () => {
maxSelected: 2,
},
});
const accepted = await harness.ctx.issues.respondInteraction(
issue.id,
interaction.id,
{
action: "accept",
actorUserId: "user-1",
selectedOptionIds: ["file-b"],
},
"company-1",
);
expect(accepted).toMatchObject({
applied: true,
interaction: {
status: "accepted",
result: {
outcome: "accepted",
selectedOptionIds: ["file-b"],
},
},
});
});
});