Skip to content

Commit 4852718

Browse files
committed
Add e2e tests for session modes and refactor status checks
1 parent 885e028 commit 4852718

2 files changed

Lines changed: 56 additions & 5 deletions

File tree

src/__tests__/CodexACPAgent/e2e/acp-e2e-test-utils.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import fs from "node:fs";
44
import os from "node:os";
55
import path from "node:path";
66
import {Readable, Writable} from "node:stream";
7-
import {describe, vi} from "vitest";
7+
import {describe, expect, vi} from "vitest";
88
import {removeDirectoryWithRetry} from "../../acp-test-utils";
99

1010
export const RUN_E2E_TESTS = process.env["RUN_E2E_TESTS"] === "true";
@@ -25,6 +25,17 @@ export function describeE2E(name: string, factory: () => void, timeoutMs = DEFAU
2525
describe.skipIf(!RUN_E2E_TESTS)(name, {timeout: timeoutMs}, factory);
2626
}
2727

28+
export async function expectStatus(
29+
session: SpawnedSessionFixture,
30+
fields: Record<string, unknown>,
31+
): Promise<void> {
32+
await session.expectPromptText("/status", (text) => {
33+
for (const [field, value] of Object.entries(fields)) {
34+
expect(text).toContain(`**${field}:** ${String(value)}`);
35+
}
36+
});
37+
}
38+
2839
interface TestSkill {
2940
readonly name: string;
3041
readonly description: string;
@@ -68,7 +79,8 @@ export async function createFixtureWithSkill(skill: TestSkill): Promise<SpawnedA
6879
}
6980

7081
export async function createAuthenticatedFixture(
71-
runtimePaths = createTemporaryRuntimePaths()
82+
runtimePaths = createTemporaryRuntimePaths(),
83+
extraEnv?: NodeJS.ProcessEnv,
7284
): Promise<SpawnedAgentFixture> {
7385
const apiKey = requireLiveApiKey();
7486
return await createSpawnedFixture(async (connection, authMethods) => {
@@ -89,7 +101,7 @@ export async function createAuthenticatedFixture(
89101
if (authenticationStatus["type"] !== "api-key") {
90102
throw new Error(`Unexpected authentication status: ${JSON.stringify(authenticationStatus)}`);
91103
}
92-
}, runtimePaths);
104+
}, runtimePaths, extraEnv);
93105
}
94106

95107
export interface GatewayFixtureOptions {
@@ -128,13 +140,15 @@ type Authenticator = (connection: acp.ClientSideConnection, authMethods: acp.Aut
128140
async function createSpawnedFixture(
129141
authenticate: Authenticator,
130142
runtimePaths: RuntimePaths,
143+
extraEnv?: NodeJS.ProcessEnv,
131144
): Promise<SpawnedAgentFixture> {
132145
const agentProcess = spawn("npm", ["run", "--silent", "start"], {
133146
cwd: process.cwd(),
134147
env: {
135148
...process.env,
136149
CODEX_HOME: runtimePaths.codexHome,
137150
APP_SERVER_LOGS: runtimePaths.appServerLogsDir,
151+
...extraEnv,
138152
},
139153
stdio: ["pipe", "pipe", "pipe"],
140154
});

src/__tests__/CodexACPAgent/e2e/acp-e2e.test.ts

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import {afterEach, expect, it} from "vitest";
2+
import {AgentMode} from "../../../AgentMode";
23
import {
34
createAuthenticatedFixture,
45
createFixtureWithSkill,
56
createGatewayFixture,
67
describeE2E,
8+
expectStatus,
79
requireLiveApiKey,
810
type SpawnedAgentFixture,
911
} from "./acp-e2e-test-utils";
@@ -60,8 +62,43 @@ describeE2E("E2E tests", () => {
6062
sessionId: session.response.sessionId,
6163
modelId: selectedModelId,
6264
});
63-
await session.expectPromptText("/status", (text) => {
64-
expect(text).toContain(`**Model:** ${selectedModelId}`);
65+
await expectStatus(session, {Model: selectedModelId});
66+
});
67+
68+
it("changes session mode via setSessionMode and reflects it in /status", async () => {
69+
fixture = await createAuthenticatedFixture();
70+
const session = await fixture.createSession();
71+
72+
const modes = session.response.modes;
73+
expect(modes?.currentModeId).toBe(AgentMode.DEFAULT_AGENT_MODE.id);
74+
expect(modes?.availableModes.map((mode) => mode.id)).toEqual(
75+
AgentMode.all().map((mode) => mode.id),
76+
);
77+
78+
const targetMode = AgentMode.AgentFullAccess;
79+
await fixture.connection.setSessionMode({
80+
sessionId: session.response.sessionId,
81+
modeId: targetMode.id,
82+
});
83+
84+
await expectStatus(session, {
85+
Approval: targetMode.approvalPolicy,
86+
Sandbox: targetMode.sandboxMode,
87+
});
88+
});
89+
90+
it("respects INITIAL_AGENT_MODE when seeding the initial session mode", async () => {
91+
const initialMode = AgentMode.ReadOnly;
92+
fixture = await createAuthenticatedFixture(undefined, {
93+
INITIAL_AGENT_MODE: initialMode.id,
94+
});
95+
const session = await fixture.createSession();
96+
97+
expect(session.response.modes?.currentModeId).toBe(initialMode.id);
98+
99+
await expectStatus(session, {
100+
Approval: initialMode.approvalPolicy,
101+
Sandbox: initialMode.sandboxMode,
65102
});
66103
});
67104

0 commit comments

Comments
 (0)