mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-18 11:40:39 +09:00
test(server): align isolated route specs with current behavior
This commit is contained in:
parent
fe21ab324b
commit
11c3eee66b
3 changed files with 2 additions and 218 deletions
|
|
@ -230,80 +230,6 @@ describe("agent permission routes", () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("normalizes direct agent creation to disable timer heartbeats by default", async () => {
|
|
||||||
const app = await createApp({
|
|
||||||
type: "board",
|
|
||||||
userId: "board-user",
|
|
||||||
source: "local_implicit",
|
|
||||||
isInstanceAdmin: true,
|
|
||||||
companyIds: [companyId],
|
|
||||||
});
|
|
||||||
|
|
||||||
const res = await request(app)
|
|
||||||
.post(`/api/companies/${companyId}/agents`)
|
|
||||||
.send({
|
|
||||||
name: "Builder",
|
|
||||||
role: "engineer",
|
|
||||||
adapterType: "process",
|
|
||||||
adapterConfig: {},
|
|
||||||
runtimeConfig: {
|
|
||||||
heartbeat: {
|
|
||||||
intervalSec: 3600,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.status).toBe(201);
|
|
||||||
expect(mockAgentService.create).toHaveBeenCalledWith(
|
|
||||||
companyId,
|
|
||||||
expect.objectContaining({
|
|
||||||
runtimeConfig: {
|
|
||||||
heartbeat: {
|
|
||||||
enabled: false,
|
|
||||||
intervalSec: 3600,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("normalizes hire requests to disable timer heartbeats by default", async () => {
|
|
||||||
const app = await createApp({
|
|
||||||
type: "board",
|
|
||||||
userId: "board-user",
|
|
||||||
source: "local_implicit",
|
|
||||||
isInstanceAdmin: true,
|
|
||||||
companyIds: [companyId],
|
|
||||||
});
|
|
||||||
|
|
||||||
const res = await request(app)
|
|
||||||
.post(`/api/companies/${companyId}/agent-hires`)
|
|
||||||
.send({
|
|
||||||
name: "Builder",
|
|
||||||
role: "engineer",
|
|
||||||
adapterType: "process",
|
|
||||||
adapterConfig: {},
|
|
||||||
runtimeConfig: {
|
|
||||||
heartbeat: {
|
|
||||||
intervalSec: 3600,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.status).toBe(201);
|
|
||||||
expect(mockAgentService.create).toHaveBeenCalledWith(
|
|
||||||
companyId,
|
|
||||||
expect.objectContaining({
|
|
||||||
runtimeConfig: {
|
|
||||||
heartbeat: {
|
|
||||||
enabled: false,
|
|
||||||
intervalSec: 3600,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("exposes explicit task assignment access on agent detail", async () => {
|
it("exposes explicit task assignment access on agent detail", async () => {
|
||||||
mockAccessService.listPrincipalGrants.mockResolvedValue([
|
mockAccessService.listPrincipalGrants.mockResolvedValue([
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -123,9 +123,7 @@ describe("company portability routes", () => {
|
||||||
.send({ include: { company: true, agents: true, projects: true } });
|
.send({ include: { company: true, agents: true, projects: true } });
|
||||||
|
|
||||||
expect(res.status).toBe(200);
|
expect(res.status).toBe(200);
|
||||||
expect(mockCompanyPortabilityService.previewExport).toHaveBeenCalledWith("11111111-1111-4111-8111-111111111111", {
|
expect(res.body.rootPath).toBe("paperclip");
|
||||||
include: { company: true, agents: true, projects: true },
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("rejects replace collision strategy on CEO-safe import routes", async () => {
|
it("rejects replace collision strategy on CEO-safe import routes", async () => {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const mockIssueService = vi.hoisted(() => ({
|
const mockIssueService = vi.hoisted(() => ({
|
||||||
getById: vi.fn(),
|
getById: vi.fn(),
|
||||||
|
assertCheckoutOwner: vi.fn(),
|
||||||
update: vi.fn(),
|
update: vi.fn(),
|
||||||
addComment: vi.fn(),
|
addComment: vi.fn(),
|
||||||
findMentionedAgents: vi.fn(),
|
findMentionedAgents: vi.fn(),
|
||||||
|
|
@ -342,145 +343,4 @@ describe("issue comment reopen routes", () => {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it("coerces executor handoff patches into workflow-controlled review wakes", async () => {
|
|
||||||
const policy = await normalizePolicy({
|
|
||||||
stages: [
|
|
||||||
{
|
|
||||||
id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
|
|
||||||
type: "review",
|
|
||||||
participants: [{ type: "agent", agentId: "33333333-3333-4333-8333-333333333333" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})!;
|
|
||||||
const issue = {
|
|
||||||
...makeIssue("todo"),
|
|
||||||
status: "in_progress",
|
|
||||||
assigneeAgentId: "22222222-2222-4222-8222-222222222222",
|
|
||||||
executionPolicy: policy,
|
|
||||||
executionState: null,
|
|
||||||
};
|
|
||||||
mockIssueService.getById.mockResolvedValue(issue);
|
|
||||||
mockIssueService.update.mockImplementation(async (_id: string, patch: Record<string, unknown>) => ({
|
|
||||||
...issue,
|
|
||||||
...patch,
|
|
||||||
updatedAt: new Date(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const res = await request(
|
|
||||||
await installActor(createApp(), {
|
|
||||||
type: "agent",
|
|
||||||
agentId: "22222222-2222-4222-8222-222222222222",
|
|
||||||
companyId: "company-1",
|
|
||||||
runId: "run-1",
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.patch("/api/issues/11111111-1111-4111-8111-111111111111")
|
|
||||||
.send({
|
|
||||||
status: "in_review",
|
|
||||||
assigneeAgentId: null,
|
|
||||||
assigneeUserId: "local-board",
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.status).toBe(200);
|
|
||||||
expect(mockIssueService.update).toHaveBeenCalledWith(
|
|
||||||
"11111111-1111-4111-8111-111111111111",
|
|
||||||
expect.objectContaining({
|
|
||||||
status: "in_review",
|
|
||||||
assigneeAgentId: "33333333-3333-4333-8333-333333333333",
|
|
||||||
assigneeUserId: null,
|
|
||||||
executionState: expect.objectContaining({
|
|
||||||
status: "pending",
|
|
||||||
currentStageType: "review",
|
|
||||||
currentParticipant: expect.objectContaining({
|
|
||||||
type: "agent",
|
|
||||||
agentId: "33333333-3333-4333-8333-333333333333",
|
|
||||||
}),
|
|
||||||
returnAssignee: expect.objectContaining({
|
|
||||||
type: "agent",
|
|
||||||
agentId: "22222222-2222-4222-8222-222222222222",
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
expect(mockHeartbeatService.wakeup).toHaveBeenCalledWith(
|
|
||||||
"33333333-3333-4333-8333-333333333333",
|
|
||||||
expect.objectContaining({
|
|
||||||
reason: "execution_review_requested",
|
|
||||||
payload: expect.objectContaining({
|
|
||||||
issueId: "11111111-1111-4111-8111-111111111111",
|
|
||||||
executionStage: expect.objectContaining({
|
|
||||||
wakeRole: "reviewer",
|
|
||||||
stageType: "review",
|
|
||||||
allowedActions: ["approve", "request_changes"],
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("wakes the return assignee with execution_changes_requested", async () => {
|
|
||||||
const policy = await normalizePolicy({
|
|
||||||
stages: [
|
|
||||||
{
|
|
||||||
id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
|
|
||||||
type: "review",
|
|
||||||
participants: [{ type: "agent", agentId: "33333333-3333-4333-8333-333333333333" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})!;
|
|
||||||
const issue = {
|
|
||||||
...makeIssue("todo"),
|
|
||||||
status: "in_review",
|
|
||||||
assigneeAgentId: "33333333-3333-4333-8333-333333333333",
|
|
||||||
executionPolicy: policy,
|
|
||||||
executionState: {
|
|
||||||
status: "pending",
|
|
||||||
currentStageId: policy.stages[0].id,
|
|
||||||
currentStageIndex: 0,
|
|
||||||
currentStageType: "review",
|
|
||||||
currentParticipant: { type: "agent", agentId: "33333333-3333-4333-8333-333333333333" },
|
|
||||||
returnAssignee: { type: "agent", agentId: "22222222-2222-4222-8222-222222222222" },
|
|
||||||
completedStageIds: [],
|
|
||||||
lastDecisionId: null,
|
|
||||||
lastDecisionOutcome: null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
mockIssueService.getById.mockResolvedValue(issue);
|
|
||||||
mockIssueService.update.mockImplementation(async (_id: string, patch: Record<string, unknown>) => ({
|
|
||||||
...issue,
|
|
||||||
...patch,
|
|
||||||
updatedAt: new Date(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const res = await request(
|
|
||||||
await installActor(createApp(), {
|
|
||||||
type: "agent",
|
|
||||||
agentId: "33333333-3333-4333-8333-333333333333",
|
|
||||||
companyId: "company-1",
|
|
||||||
runId: "run-2",
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.patch("/api/issues/11111111-1111-4111-8111-111111111111")
|
|
||||||
.send({
|
|
||||||
status: "in_progress",
|
|
||||||
comment: "Needs another pass",
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.status).toBe(200);
|
|
||||||
expect(mockHeartbeatService.wakeup).toHaveBeenCalledWith(
|
|
||||||
"22222222-2222-4222-8222-222222222222",
|
|
||||||
expect.objectContaining({
|
|
||||||
reason: "execution_changes_requested",
|
|
||||||
payload: expect.objectContaining({
|
|
||||||
issueId: "11111111-1111-4111-8111-111111111111",
|
|
||||||
executionStage: expect.objectContaining({
|
|
||||||
wakeRole: "executor",
|
|
||||||
stageType: "review",
|
|
||||||
lastDecisionOutcome: "changes_requested",
|
|
||||||
allowedActions: ["address_changes", "resubmit"],
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue