test(server): support locked review policy updates

Keep terminal-update route harnesses aligned with the transactional issue service contract.

Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
Dotta 2026-08-15 01:31:45 +00:00
parent 991f40bb2e
commit 3a87b143a2
6 changed files with 20 additions and 1 deletions

View File

@ -7,6 +7,7 @@ import { normalizeIssueExecutionPolicy } from "../services/issue-execution-polic
const mockIssueService = vi.hoisted(() => ({
getById: vi.fn(),
getByIdForUpdate: vi.fn(),
assertCheckoutOwner: vi.fn(),
update: vi.fn(),
addComment: vi.fn(),
@ -200,6 +201,7 @@ describe("issue activity event routes", () => {
registerModuleMocks();
vi.clearAllMocks();
mockIssueService.assertCheckoutOwner.mockResolvedValue({ adoptedFromRunId: null });
mockIssueService.getByIdForUpdate.mockImplementation(async () => mockIssueService.getById());
mockIssueService.findMentionedAgents.mockResolvedValue([]);
mockIssueService.getRelationSummaries.mockResolvedValue({ blockedBy: [], blocks: [] });
mockIssueService.listWakeableBlockedDependents.mockResolvedValue([]);
@ -555,6 +557,7 @@ describe("issue activity event routes", () => {
createdAt: new Date("2026-05-01T00:00:00.000Z"),
};
const dbMock = {
transaction: async (callback: (tx: unknown) => Promise<unknown>) => callback({}),
select: () => ({
from: () => ({
where: () => ({

View File

@ -20,6 +20,7 @@ const mockIssueService = vi.hoisted(() => ({
getAttachmentById: vi.fn(),
getByIdentifier: vi.fn(),
getById: vi.fn(),
getByIdForUpdate: vi.fn(),
getComment: vi.fn(),
getDependencyReadiness: vi.fn(),
getRelationSummaries: vi.fn(),
@ -433,6 +434,7 @@ describe("agent issue mutation checkout ownership", () => {
mockIssueService.getAttachmentById.mockReset();
mockIssueService.getByIdentifier.mockReset();
mockIssueService.getById.mockReset();
mockIssueService.getByIdForUpdate.mockReset();
mockIssueService.getComment.mockReset();
mockIssueService.getDependencyReadiness.mockReset();
mockIssueService.getDependencyReadiness.mockResolvedValue({
@ -558,6 +560,7 @@ describe("agent issue mutation checkout ownership", () => {
mockAgentService.resolveByReference.mockResolvedValue({ ambiguous: false, agent: null });
mockCompanyService.getById.mockResolvedValue({ id: companyId, issuePrefix: "PAP" });
mockIssueService.getById.mockResolvedValue(makeIssue());
mockIssueService.getByIdForUpdate.mockImplementation(async () => mockIssueService.getById());
mockIssueService.getByIdentifier.mockResolvedValue(null);
mockIssueService.getComment.mockResolvedValue({
id: "comment-1",
@ -976,6 +979,7 @@ describe("agent issue mutation checkout ownership", () => {
expect(mockIssueService.update).toHaveBeenCalledWith(
issueId,
expect.objectContaining({ status: "done" }),
expect.anything(),
);
});

View File

@ -5,6 +5,7 @@ import { HttpError } from "../errors.js";
const mockIssueService = vi.hoisted(() => ({
getById: vi.fn(),
getByIdForUpdate: vi.fn(),
assertCheckoutOwner: vi.fn(),
update: vi.fn(),
addComment: vi.fn(),
@ -265,6 +266,7 @@ describe.sequential("issue comment reopen routes", () => {
beforeEach(() => {
vi.clearAllMocks();
mockIssueService.getById.mockReset();
mockIssueService.getByIdForUpdate.mockReset();
mockIssueService.assertCheckoutOwner.mockReset();
mockIssueService.update.mockReset();
mockIssueService.addComment.mockReset();
@ -316,6 +318,7 @@ describe.sequential("issue comment reopen routes", () => {
mockDbSelectFrom.mockImplementation(() => ({ where: mockDbSelectWhere }));
mockDbSelect.mockImplementation(() => ({ from: mockDbSelectFrom }));
mockDb.transaction.mockImplementation(async (fn: (tx: typeof mockTx) => Promise<unknown>) => fn(mockTx));
mockIssueService.getByIdForUpdate.mockImplementation(async () => mockIssueService.getById());
mockHeartbeatService.wakeup.mockResolvedValue(undefined);
mockHeartbeatService.reportRunActivity.mockResolvedValue(undefined);
mockHeartbeatService.getRun.mockResolvedValue(null);

View File

@ -7,6 +7,7 @@ const mockFindExistingIssueBlockersResolvedWake = vi.hoisted(() => vi.fn(async (
const mockIssueService = vi.hoisted(() => ({
getAncestors: vi.fn(),
getById: vi.fn(),
getByIdForUpdate: vi.fn(),
getByIdentifier: vi.fn(async () => null),
getComment: vi.fn(),
getCommentCursor: vi.fn(),
@ -114,6 +115,7 @@ async function createApp() {
select: vi.fn(() => ({
from: vi.fn(() => query),
})),
transaction: async (callback: (tx: Record<string, never>) => Promise<unknown>) => callback({}),
};
const [{ issueRoutes }, { errorHandler }] = await Promise.all([
vi.importActual<typeof import("../routes/issues.js")>("../routes/issues.js"),
@ -145,6 +147,7 @@ describe("issue dependency wakeups in issue routes", () => {
vi.clearAllMocks();
mockFindExistingIssueBlockersResolvedWake.mockResolvedValue(null);
mockIssueService.getAncestors.mockResolvedValue([]);
mockIssueService.getByIdForUpdate.mockImplementation(async () => mockIssueService.getById());
mockIssueService.getComment.mockResolvedValue(null);
mockIssueService.getCommentCursor.mockResolvedValue({
totalComments: 0,

View File

@ -4,6 +4,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
const mockIssueService = vi.hoisted(() => ({
getById: vi.fn(),
getByIdForUpdate: vi.fn(),
getWakeableParentAfterChildCompletion: vi.fn(),
listWakeableBlockedDependents: vi.fn(),
update: vi.fn(),
@ -157,6 +158,7 @@ describe("issue telemetry routes", () => {
vi.clearAllMocks();
mockGetTelemetryClient.mockReturnValue({ track: vi.fn() });
mockIssueService.getById.mockResolvedValue(makeIssue("todo"));
mockIssueService.getByIdForUpdate.mockImplementation(async () => mockIssueService.getById());
mockIssueService.getWakeableParentAfterChildCompletion.mockResolvedValue(null);
mockIssueService.listWakeableBlockedDependents.mockResolvedValue([]);
mockIssueService.update.mockImplementation(async (_id: string, patch: Record<string, unknown>) => ({

View File

@ -8,6 +8,7 @@ const MENTIONED_AGENT_ID = "33333333-3333-4333-8333-333333333333";
const mockIssueService = vi.hoisted(() => ({
getById: vi.fn(),
getByIdForUpdate: vi.fn(),
update: vi.fn(),
addComment: vi.fn(),
findMentionedAgents: vi.fn(),
@ -192,7 +193,9 @@ async function createApp() {
};
next();
});
app.use("/api", issueRoutes({} as any, {} as any));
app.use("/api", issueRoutes({
transaction: async (callback: (tx: Record<string, never>) => Promise<unknown>) => callback({}),
} as any, {} as any));
app.use(errorHandler);
return app;
}
@ -227,6 +230,7 @@ describe("issue update comment wakeups", () => {
registerModuleMocks();
vi.clearAllMocks();
mockIssueService.findMentionedAgents.mockResolvedValue([]);
mockIssueService.getByIdForUpdate.mockImplementation(async () => mockIssueService.getById());
mockIssueService.getRelationSummaries.mockResolvedValue({ blockedBy: [], blocks: [] });
mockIssueService.listWakeableBlockedDependents.mockResolvedValue([]);
mockIssueService.getWakeableParentAfterChildCompletion.mockResolvedValue(null);