Skip to content

Commit 622c16e

Browse files
Fix typed tests after Codex update
1 parent f30ae80 commit 622c16e

2 files changed

Lines changed: 138 additions & 51 deletions

File tree

src/__tests__/CodexACPAgent/CodexAcpClient.test.ts

Lines changed: 34 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,17 @@
33
import {describe, expect, it, vi, beforeEach} from 'vitest';
44
import type {CodexAuthRequest} from "../../CodexAuthMethod";
55
import type * as acp from "@agentclientprotocol/sdk";
6-
import {createTestFixture, createCodexMockTestFixture, createTestSessionState, type TestFixture} from "../acp-test-utils";
6+
import {
7+
createTestFixture,
8+
createCodexMockTestFixture,
9+
createTestModel,
10+
createTestSessionState,
11+
createTestThread,
12+
createTestThreadStartResponse,
13+
createTestTurn,
14+
createTestTurnCompletedNotification,
15+
type TestFixture
16+
} from "../acp-test-utils";
717
import type {ServerNotification} from "../../app-server";
818
import type {SessionState} from "../../CodexAcpServer";
919
import {AgentMode} from "../../AgentMode";
@@ -143,32 +153,13 @@ describe('ACP server test', { timeout: 40_000 }, () => {
143153
const codexAppServerClient = mockFixture.getCodexAppServerClient();
144154

145155
const listSkillsSpy = vi.spyOn(codexAppServerClient, "listSkills").mockResolvedValue({ data: [] });
146-
const threadStartSpy = vi.spyOn(codexAppServerClient, "threadStart").mockResolvedValue({
147-
thread: { id: "thread-id" } as any,
148-
model: "gpt-5",
149-
modelProvider: "openai",
150-
cwd: "/workspace",
151-
approvalPolicy: "on-request",
152-
sandbox: "workspace-write",
153-
reasoningEffort: "medium",
154-
} as any);
156+
const threadStartSpy = vi.spyOn(codexAppServerClient, "threadStart").mockResolvedValue(
157+
createTestThreadStartResponse({
158+
thread: createTestThread({ id: "thread-id" }),
159+
})
160+
);
155161
vi.spyOn(codexAppServerClient, "listModels").mockResolvedValue({
156-
data: [{
157-
id: "gpt-5",
158-
model: "gpt-5",
159-
upgrade: null,
160-
upgradeInfo: null,
161-
availabilityNux: null,
162-
displayName: "gpt-5",
163-
description: "test model",
164-
hidden: false,
165-
supportedReasoningEfforts: [{ reasoningEffort: "medium", description: "balanced" }],
166-
defaultReasoningEffort: "medium",
167-
inputModalities: ["text"],
168-
supportsPersonality: false,
169-
additionalSpeedTiers: [],
170-
isDefault: true
171-
}],
162+
data: [createTestModel({ displayName: "gpt-5" })],
172163
nextCursor: null
173164
});
174165

@@ -233,24 +224,19 @@ describe('ACP server test', { timeout: 40_000 }, () => {
233224
const codexAppServerClient = mockFixture.getCodexAppServerClient();
234225

235226
vi.spyOn(codexAcpAgent, "checkAuthorization").mockResolvedValue(undefined);
236-
vi.spyOn(codexAppServerClient, "threadStart").mockResolvedValue({
237-
thread: { id: "thread-id" } as any,
238-
model: "gpt-5",
239-
reasoningEffort: "medium",
240-
} as any);
227+
vi.spyOn(codexAppServerClient, "threadStart").mockResolvedValue(
228+
createTestThreadStartResponse({
229+
thread: createTestThread({ id: "thread-id" }),
230+
})
231+
);
241232
vi.spyOn(codexAppServerClient, "listModels").mockResolvedValue({
242-
data: [{
243-
id: "gpt-5",
244-
name: "GPT-5",
245-
inputModalities: ["text"],
246-
supportedReasoningEfforts: [],
247-
}],
248-
hasMore: false,
249-
} as any);
233+
data: [createTestModel({ supportedReasoningEfforts: [] })],
234+
nextCursor: null,
235+
});
250236
vi.spyOn(codexAppServerClient, "accountRead").mockResolvedValue({
251237
requiresOpenaiAuth: false,
252238
account: null,
253-
} as any);
239+
});
254240
vi.spyOn(codexAppServerClient, "listSkills").mockResolvedValue({ data: [] });
255241
const mcpServer = {
256242
name: "broken-mcp",
@@ -287,12 +273,14 @@ describe('ACP server test', { timeout: 40_000 }, () => {
287273

288274
const listSkillsSpy = vi.spyOn(codexAppServerClient, "listSkills").mockResolvedValue({ data: [] });
289275
const turnStartSpy = vi.spyOn(codexAppServerClient, "turnStart").mockResolvedValue({
290-
turn: { id: "turn-id", items: [], status: "inProgress", error: null }
291-
} as any);
292-
vi.spyOn(codexAppServerClient, "awaitTurnCompleted").mockResolvedValue({
293-
threadId: "session-id",
294-
turn: { id: "turn-id", items: [], status: "completed", error: null }
295-
} as any);
276+
turn: createTestTurn()
277+
});
278+
vi.spyOn(codexAppServerClient, "awaitTurnCompleted").mockResolvedValue(
279+
createTestTurnCompletedNotification({
280+
threadId: "session-id",
281+
turn: createTestTurn({ status: "completed" })
282+
})
283+
);
296284

297285
vi.spyOn(codexAcpAgent, "getSessionState").mockReturnValue(createTestSessionState({
298286
sessionId: "session-id",

src/__tests__/acp-test-utils.ts

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ import {startCodexConnection} from "../CodexJsonRpcConnection";
44
import {CodexAcpServer, type SessionState} from "../CodexAcpServer";
55
import type {AgentSideConnection, RequestPermissionResponse} from "@agentclientprotocol/sdk";
66
import type {ServerNotification} from "../app-server";
7+
import type {
8+
Model,
9+
Thread,
10+
ThreadStartResponse,
11+
Turn,
12+
TurnCompletedNotification
13+
} from "../app-server/v2";
714
import type {MessageConnection} from "vscode-jsonrpc/node";
815
import path from "node:path";
916
import fs from "node:fs";
@@ -315,6 +322,96 @@ export function createTestSessionState(overrides?: Partial<SessionState>): Sessi
315322
};
316323
}
317324

325+
export function createTestModel(overrides?: Partial<Model>): Model {
326+
return {
327+
id: "gpt-5",
328+
model: "gpt-5",
329+
upgrade: null,
330+
upgradeInfo: null,
331+
availabilityNux: null,
332+
displayName: "GPT-5",
333+
description: "test model",
334+
hidden: false,
335+
supportedReasoningEfforts: [{ reasoningEffort: "medium", description: "balanced" }],
336+
defaultReasoningEffort: "medium",
337+
inputModalities: ["text"],
338+
supportsPersonality: false,
339+
additionalSpeedTiers: [],
340+
isDefault: true,
341+
...overrides,
342+
};
343+
}
344+
345+
export function createTestTurn(overrides?: Partial<Turn>): Turn {
346+
return {
347+
id: "turn-id",
348+
items: [],
349+
status: "inProgress",
350+
error: null,
351+
startedAt: null,
352+
completedAt: null,
353+
durationMs: null,
354+
...overrides,
355+
};
356+
}
357+
358+
export function createTestThread(overrides?: Partial<Thread>): Thread {
359+
return {
360+
id: "thread-id",
361+
forkedFromId: null,
362+
preview: "",
363+
ephemeral: false,
364+
modelProvider: "openai",
365+
createdAt: 0,
366+
updatedAt: 0,
367+
status: { type: "idle" },
368+
path: null,
369+
cwd: "/workspace",
370+
cliVersion: "0.0.0-test",
371+
source: "appServer",
372+
agentNickname: null,
373+
agentRole: null,
374+
gitInfo: null,
375+
name: null,
376+
turns: [],
377+
...overrides,
378+
};
379+
}
380+
381+
export function createTestThreadStartResponse(overrides?: Partial<ThreadStartResponse>): ThreadStartResponse {
382+
return {
383+
thread: createTestThread(),
384+
model: "gpt-5",
385+
modelProvider: "openai",
386+
serviceTier: null,
387+
cwd: "/workspace",
388+
instructionSources: [],
389+
approvalPolicy: "on-request",
390+
approvalsReviewer: "user",
391+
sandbox: {
392+
type: "workspaceWrite",
393+
writableRoots: [],
394+
readOnlyAccess: { type: "fullAccess" },
395+
networkAccess: false,
396+
excludeTmpdirEnvVar: false,
397+
excludeSlashTmp: false,
398+
},
399+
permissionProfile: null,
400+
reasoningEffort: "medium",
401+
...overrides,
402+
};
403+
}
404+
405+
export function createTestTurnCompletedNotification(
406+
overrides?: Partial<TurnCompletedNotification>
407+
): TurnCompletedNotification {
408+
return {
409+
threadId: "session-id",
410+
turn: createTestTurn({ status: "completed" }),
411+
...overrides,
412+
};
413+
}
414+
318415
export async function setupPromptAndSendNotifications(
319416
fixture: CodexMockTestFixture,
320417
sessionId: string,
@@ -323,15 +420,17 @@ export async function setupPromptAndSendNotifications(
323420
): Promise<void> {
324421
const codexAcpAgent = fixture.getCodexAcpAgent();
325422
const codexAppServerClient = fixture.getCodexAppServerClient();
326-
const turn = { id: "turn-id", items: [], status: "inProgress" as const, error: null };
423+
const turn = createTestTurn();
327424

328425
codexAppServerClient.turnStart = vi.fn().mockResolvedValue({
329426
turn,
330427
});
331-
codexAppServerClient.awaitTurnCompleted = vi.fn().mockResolvedValue({
332-
threadId: sessionId,
333-
turn: { ...turn, status: "completed" },
334-
});
428+
codexAppServerClient.awaitTurnCompleted = vi.fn().mockResolvedValue(
429+
createTestTurnCompletedNotification({
430+
threadId: sessionId,
431+
turn: createTestTurn({ ...turn, status: "completed" }),
432+
})
433+
);
335434

336435
vi.spyOn(codexAcpAgent, "getSessionState").mockReturnValue(sessionState);
337436

0 commit comments

Comments
 (0)