feat: streamline group dispatch reminders
This commit is contained in:
@@ -11,6 +11,7 @@ let getDispatchPlansRoute: (typeof import("../src/app/api/v1/projects/[projectId
|
||||
let confirmDispatchPlanRoute: (typeof import("../src/app/api/v1/projects/[projectId]/dispatch-plans/[planId]/confirm/route"))["POST"];
|
||||
let rejectDispatchPlanRoute: (typeof import("../src/app/api/v1/projects/[projectId]/dispatch-plans/[planId]/reject/route"))["POST"];
|
||||
let retryDispatchPlanRoute: (typeof import("../src/app/api/v1/projects/[projectId]/dispatch-plans/[planId]/retry/route"))["POST"];
|
||||
let updateDispatchReminderRoute: (typeof import("../src/app/api/v1/projects/[projectId]/dispatch-reminder/route"))["PATCH"];
|
||||
let createAuthSession: (typeof import("../src/lib/boss-data"))["createAuthSession"];
|
||||
let createProjectGroupChat: (typeof import("../src/lib/boss-data"))["createProjectGroupChat"];
|
||||
let isDispatchableThreadProject: (typeof import("../src/lib/boss-data"))["isDispatchableThreadProject"];
|
||||
@@ -28,12 +29,13 @@ async function setup() {
|
||||
process.env.BOSS_RUNTIME_ROOT = runtimeRoot;
|
||||
process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json");
|
||||
|
||||
const [messageModule, plansModule, confirmModule, rejectModule, retryModule, data, auth] = await Promise.all([
|
||||
const [messageModule, plansModule, confirmModule, rejectModule, retryModule, reminderModule, data, auth] = await Promise.all([
|
||||
import("../src/app/api/v1/projects/[projectId]/messages/route.ts"),
|
||||
import("../src/app/api/v1/projects/[projectId]/dispatch-plans/route.ts"),
|
||||
import("../src/app/api/v1/projects/[projectId]/dispatch-plans/[planId]/confirm/route.ts"),
|
||||
import("../src/app/api/v1/projects/[projectId]/dispatch-plans/[planId]/reject/route.ts"),
|
||||
import("../src/app/api/v1/projects/[projectId]/dispatch-plans/[planId]/retry/route.ts"),
|
||||
import("../src/app/api/v1/projects/[projectId]/dispatch-reminder/route.ts"),
|
||||
import("../src/lib/boss-data.ts"),
|
||||
import("../src/lib/boss-auth.ts"),
|
||||
]);
|
||||
@@ -43,6 +45,7 @@ async function setup() {
|
||||
confirmDispatchPlanRoute = confirmModule.POST;
|
||||
rejectDispatchPlanRoute = rejectModule.POST;
|
||||
retryDispatchPlanRoute = retryModule.POST;
|
||||
updateDispatchReminderRoute = reminderModule.PATCH;
|
||||
createAuthSession = data.createAuthSession;
|
||||
createProjectGroupChat = data.createProjectGroupChat;
|
||||
isDispatchableThreadProject = data.isDispatchableThreadProject;
|
||||
@@ -63,7 +66,7 @@ test.beforeEach(async () => {
|
||||
await writeState(structuredClone(baseState));
|
||||
});
|
||||
|
||||
async function createAuthedRequest(url: string, method: "GET" | "POST", body?: unknown) {
|
||||
async function createAuthedRequest(url: string, method: "GET" | "POST" | "PATCH", body?: unknown) {
|
||||
const session = await createAuthSession({
|
||||
account: "17600003315",
|
||||
role: "highest_admin",
|
||||
@@ -299,6 +302,39 @@ test("POST /api/v1/projects/[projectId]/dispatch-plans/[planId]/confirm confirms
|
||||
assert.equal(executionTask?.orchestrationBackendLabel, "Boss Native Orchestrator");
|
||||
});
|
||||
|
||||
test("confirming a dispatch plan with rememberLightReminder persists the group reminder preference", async () => {
|
||||
const { groupProject, dispatchPlan } = await createDispatchPlanForTest();
|
||||
const approvedTargetProjectId = dispatchPlan.targets[0]?.projectId;
|
||||
assert.ok(approvedTargetProjectId, "expected a recommended target project");
|
||||
|
||||
const response = await confirmDispatchPlanRoute(
|
||||
await createAuthedRequest(
|
||||
`http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-plans/${dispatchPlan.planId}/confirm`,
|
||||
"POST",
|
||||
{
|
||||
approvedTargetProjectIds: [approvedTargetProjectId],
|
||||
rememberLightReminder: true,
|
||||
},
|
||||
),
|
||||
{ params: Promise.resolve({ projectId: groupProject.id, planId: dispatchPlan.planId }) },
|
||||
);
|
||||
assert.equal(response.status, 200);
|
||||
|
||||
const payload = (await response.json()) as {
|
||||
ok: boolean;
|
||||
collaborationGate: {
|
||||
lightDispatchReminderEnabled?: boolean;
|
||||
};
|
||||
};
|
||||
assert.equal(payload.ok, true);
|
||||
assert.equal(payload.collaborationGate.lightDispatchReminderEnabled, true);
|
||||
|
||||
const nextState = await readState();
|
||||
const nextGroupProject = nextState.projects.find((project) => project.id === groupProject.id);
|
||||
assert.ok(nextGroupProject, "expected group project to remain present");
|
||||
assert.equal(nextGroupProject?.lightDispatchReminderEnabled, true);
|
||||
});
|
||||
|
||||
test("master-agent dispatch plans can also be confirmed and create queued executions", async () => {
|
||||
const { dispatchPlan } = await createMasterAgentDispatchPlanForTest();
|
||||
const approvedTargetProjectId = dispatchPlan.targets[0]?.projectId;
|
||||
@@ -523,3 +559,56 @@ test("retrying a rejected dispatch plan creates a fresh pending recommendation a
|
||||
const nextGroupProject = nextState.projects.find((project) => project.id === groupProject.id);
|
||||
assert.equal(nextGroupProject?.approvalState, "pending_user");
|
||||
});
|
||||
|
||||
test("PATCH /api/v1/projects/[projectId]/dispatch-reminder updates the per-group light reminder preference", async () => {
|
||||
const { groupProject } = await createDispatchPlanForTest();
|
||||
|
||||
const enableResponse = await updateDispatchReminderRoute(
|
||||
await createAuthedRequest(
|
||||
`http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-reminder`,
|
||||
"PATCH",
|
||||
{ lightDispatchReminderEnabled: true },
|
||||
),
|
||||
{ params: Promise.resolve({ projectId: groupProject.id }) },
|
||||
);
|
||||
assert.equal(enableResponse.status, 200);
|
||||
const enablePayload = (await enableResponse.json()) as {
|
||||
ok: boolean;
|
||||
project: {
|
||||
id: string;
|
||||
lightDispatchReminderEnabled?: boolean;
|
||||
};
|
||||
};
|
||||
assert.equal(enablePayload.ok, true);
|
||||
assert.equal(enablePayload.project.id, groupProject.id);
|
||||
assert.equal(enablePayload.project.lightDispatchReminderEnabled, true);
|
||||
|
||||
const disableResponse = await updateDispatchReminderRoute(
|
||||
await createAuthedRequest(
|
||||
`http://127.0.0.1:3000/api/v1/projects/${groupProject.id}/dispatch-reminder`,
|
||||
"PATCH",
|
||||
{ lightDispatchReminderEnabled: false },
|
||||
),
|
||||
{ params: Promise.resolve({ projectId: groupProject.id }) },
|
||||
);
|
||||
assert.equal(disableResponse.status, 200);
|
||||
const disablePayload = (await disableResponse.json()) as {
|
||||
ok: boolean;
|
||||
project: {
|
||||
id: string;
|
||||
lightDispatchReminderEnabled?: boolean;
|
||||
};
|
||||
collaborationGate: {
|
||||
lightDispatchReminderEnabled?: boolean;
|
||||
};
|
||||
};
|
||||
assert.equal(disablePayload.ok, true);
|
||||
assert.equal(disablePayload.project.id, groupProject.id);
|
||||
assert.equal(disablePayload.project.lightDispatchReminderEnabled, false);
|
||||
assert.equal(disablePayload.collaborationGate.lightDispatchReminderEnabled, false);
|
||||
|
||||
const nextState = await readState();
|
||||
const nextGroupProject = nextState.projects.find((project) => project.id === groupProject.id);
|
||||
assert.ok(nextGroupProject, "expected group project to remain present");
|
||||
assert.equal(nextGroupProject?.lightDispatchReminderEnabled, false);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user