mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 06:57:10 +00:00
Parameterize repeated test cases
This commit is contained in:
parent
beb7497b5c
commit
b148ada1d0
7 changed files with 164 additions and 162 deletions
|
|
@ -19,11 +19,13 @@ describe("app-server thread settings", () => {
|
|||
expect(update).toEqual({ model: "gpt-5.5", effort: null });
|
||||
});
|
||||
|
||||
it("parses supported approvals reviewer values", () => {
|
||||
expect(approvalsReviewerOrNull("user")).toBe("user");
|
||||
expect(approvalsReviewerOrNull("auto_review")).toBe("auto_review");
|
||||
expect(approvalsReviewerOrNull("guardian_subagent")).toBe("guardian_subagent");
|
||||
expect(approvalsReviewerOrNull("unknown")).toBeNull();
|
||||
it.each([
|
||||
["user", "user"],
|
||||
["auto_review", "auto_review"],
|
||||
["guardian_subagent", "guardian_subagent"],
|
||||
["unknown", null],
|
||||
] as const)("parses approvals reviewer value %s", (value, expected) => {
|
||||
expect(approvalsReviewerOrNull(value)).toBe(expected);
|
||||
});
|
||||
|
||||
it("builds collaboration mode payloads with built-in instructions", () => {
|
||||
|
|
@ -54,18 +56,14 @@ describe("app-server thread settings", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("accepts non-empty service tier ids from config and app-server reports", () => {
|
||||
expect(parseServiceTier("fast")).toBe("fast");
|
||||
expect(parseServiceTier("standard")).toBe("standard");
|
||||
expect(parseServiceTier("priority")).toBe("priority");
|
||||
expect(parseServiceTier("default")).toBe("default");
|
||||
expect(parseServiceTier("flex")).toBe("flex");
|
||||
expect(parseServiceTier("auto")).toBe("auto");
|
||||
expect(parseServiceTier("catalog-tier")).toBe("catalog-tier");
|
||||
});
|
||||
it.each(["fast", "standard", "priority", "default", "flex", "auto", "catalog-tier"])(
|
||||
"accepts non-empty service tier id %s from config and app-server reports",
|
||||
(serviceTier) => {
|
||||
expect(parseServiceTier(serviceTier)).toBe(serviceTier);
|
||||
},
|
||||
);
|
||||
|
||||
it("ignores absent service tier values", () => {
|
||||
expect(parseServiceTier("")).toBeNull();
|
||||
expect(parseServiceTier(null)).toBeNull();
|
||||
it.each(["", null])("ignores absent service tier value %s", (serviceTier) => {
|
||||
expect(parseServiceTier(serviceTier)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,20 +12,26 @@ const baseEvent: ComposerSendKeyEvent = {
|
|||
};
|
||||
|
||||
describe("composer send keys", () => {
|
||||
it("sends on plain Enter in Enter mode", () => {
|
||||
expect(isComposerSendKey(baseEvent, "enter")).toBe(true);
|
||||
expect(isComposerSendKey({ ...baseEvent, shiftKey: true }, "enter")).toBe(false);
|
||||
expect(isComposerSendKey({ ...baseEvent, metaKey: true }, "enter")).toBe(false);
|
||||
it.each([
|
||||
{ name: "plain Enter", event: baseEvent, shortcut: "enter", expected: true },
|
||||
{ name: "Shift+Enter", event: { ...baseEvent, shiftKey: true }, shortcut: "enter", expected: false },
|
||||
{ name: "Meta+Enter", event: { ...baseEvent, metaKey: true }, shortcut: "enter", expected: false },
|
||||
] as const)("checks $name in Enter mode", ({ event, shortcut, expected }) => {
|
||||
expect(isComposerSendKey(event, shortcut)).toBe(expected);
|
||||
});
|
||||
|
||||
it("sends on Cmd/Ctrl+Enter in mod-enter mode", () => {
|
||||
expect(isComposerSendKey({ ...baseEvent, metaKey: true }, "mod-enter")).toBe(true);
|
||||
expect(isComposerSendKey({ ...baseEvent, ctrlKey: true }, "mod-enter")).toBe(true);
|
||||
expect(isComposerSendKey(baseEvent, "mod-enter")).toBe(false);
|
||||
it.each([
|
||||
{ name: "Meta+Enter", event: { ...baseEvent, metaKey: true }, shortcut: "mod-enter", expected: true },
|
||||
{ name: "Ctrl+Enter", event: { ...baseEvent, ctrlKey: true }, shortcut: "mod-enter", expected: true },
|
||||
{ name: "plain Enter", event: baseEvent, shortcut: "mod-enter", expected: false },
|
||||
] as const)("checks $name in Cmd/Ctrl+Enter mode", ({ event, shortcut, expected }) => {
|
||||
expect(isComposerSendKey(event, shortcut)).toBe(expected);
|
||||
});
|
||||
|
||||
it("does not send during composition", () => {
|
||||
expect(isComposerSendKey({ ...baseEvent, isComposing: true }, "enter")).toBe(false);
|
||||
expect(isComposerSendKey({ ...baseEvent, metaKey: true, isComposing: true }, "mod-enter")).toBe(false);
|
||||
it.each([
|
||||
{ name: "Enter mode", event: { ...baseEvent, isComposing: true }, shortcut: "enter" },
|
||||
{ name: "Cmd/Ctrl+Enter mode", event: { ...baseEvent, metaKey: true, isComposing: true }, shortcut: "mod-enter" },
|
||||
] as const)("does not send during composition in $name", ({ event, shortcut }) => {
|
||||
expect(isComposerSendKey(event, shortcut)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -112,22 +112,24 @@ describe("composer suggestions", () => {
|
|||
},
|
||||
];
|
||||
|
||||
it("parses supported slash commands only", () => {
|
||||
expect(parseSlashCommand("/status")).toEqual({ command: "status", args: "" });
|
||||
expect(parseSlashCommand("/clear")).toEqual({ command: "clear", args: "" });
|
||||
expect(parseSlashCommand("/resume thread-1")).toEqual({ command: "resume", args: "thread-1" });
|
||||
expect(parseSlashCommand("/refer thread-1 続きです")).toEqual({ command: "refer", args: "thread-1 続きです" });
|
||||
expect(parseSlashCommand("/fork")).toEqual({ command: "fork", args: "" });
|
||||
expect(parseSlashCommand("/archive thread-1")).toEqual({ command: "archive", args: "thread-1" });
|
||||
expect(parseSlashCommand("/rename thread-1 New name")).toEqual({ command: "rename", args: "thread-1 New name" });
|
||||
expect(parseSlashCommand("/doctor")).toEqual({ command: "doctor", args: "" });
|
||||
expect(parseSlashCommand("/fast now")).toEqual({ command: "fast", args: "now" });
|
||||
expect(parseSlashCommand("/plan")).toEqual({ command: "plan", args: "" });
|
||||
expect(parseSlashCommand("/plan OK、実装してください")).toEqual({ command: "plan", args: "OK、実装してください" });
|
||||
expect(parseSlashCommand("/model gpt-5.5")).toEqual({ command: "model", args: "gpt-5.5" });
|
||||
expect(parseSlashCommand("/reasoning high")).toEqual({ command: "reasoning", args: "high" });
|
||||
expect(parseSlashCommand("/new")).toBeNull();
|
||||
expect(parseSlashCommand("/unknown")).toBeNull();
|
||||
it.each([
|
||||
{ input: "/status", expected: { command: "status", args: "" } },
|
||||
{ input: "/clear", expected: { command: "clear", args: "" } },
|
||||
{ input: "/resume thread-1", expected: { command: "resume", args: "thread-1" } },
|
||||
{ input: "/refer thread-1 続きです", expected: { command: "refer", args: "thread-1 続きです" } },
|
||||
{ input: "/fork", expected: { command: "fork", args: "" } },
|
||||
{ input: "/archive thread-1", expected: { command: "archive", args: "thread-1" } },
|
||||
{ input: "/rename thread-1 New name", expected: { command: "rename", args: "thread-1 New name" } },
|
||||
{ input: "/doctor", expected: { command: "doctor", args: "" } },
|
||||
{ input: "/fast now", expected: { command: "fast", args: "now" } },
|
||||
{ input: "/plan", expected: { command: "plan", args: "" } },
|
||||
{ input: "/plan OK、実装してください", expected: { command: "plan", args: "OK、実装してください" } },
|
||||
{ input: "/model gpt-5.5", expected: { command: "model", args: "gpt-5.5" } },
|
||||
{ input: "/reasoning high", expected: { command: "reasoning", args: "high" } },
|
||||
{ input: "/new", expected: null },
|
||||
{ input: "/unknown", expected: null },
|
||||
])("parses slash command input $input", ({ input, expected }) => {
|
||||
expect(parseSlashCommand(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
it("ranks wikilinks with Obsidian fuzzy search and uses Obsidian linktext", () => {
|
||||
|
|
|
|||
|
|
@ -651,16 +651,14 @@ describe("slash commands", () => {
|
|||
expect(ctx.addSystemMessage).toHaveBeenCalledWith("Reasoning effort reset to default for subsequent turns.");
|
||||
});
|
||||
|
||||
it("routes runtime reset aliases through reset commands", async () => {
|
||||
it.each(["reset", "clear", "off"])("routes runtime reset alias %s through reset commands", async (alias) => {
|
||||
const ctx = context();
|
||||
|
||||
for (const alias of ["reset", "clear", "off"]) {
|
||||
await executeSlashCommand("model", alias, ctx);
|
||||
await executeSlashCommand("reasoning", alias, ctx);
|
||||
}
|
||||
await executeSlashCommand("model", alias, ctx);
|
||||
await executeSlashCommand("reasoning", alias, ctx);
|
||||
|
||||
expect(ctx.runtimeSettings.resetModelToConfig).toHaveBeenCalledTimes(3);
|
||||
expect(ctx.runtimeSettings.resetReasoningEffortToConfig).toHaveBeenCalledTimes(3);
|
||||
expect(ctx.runtimeSettings.resetModelToConfig).toHaveBeenCalledOnce();
|
||||
expect(ctx.runtimeSettings.resetReasoningEffortToConfig).toHaveBeenCalledOnce();
|
||||
expect(ctx.runtimeSettings.requestModel).not.toHaveBeenCalled();
|
||||
expect(ctx.runtimeSettings.requestReasoningEffort).not.toHaveBeenCalled();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -56,28 +56,24 @@ describe("chat inbound routing", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("classifies every active-thread server request method and extracts its scope", () => {
|
||||
const requests = [
|
||||
{ request: commandApprovalRequest(), kind: "approval" },
|
||||
{ request: fileChangeApprovalRequest(), kind: "approval" },
|
||||
{ request: permissionsApprovalRequest(), kind: "approval" },
|
||||
{ request: userInputRequest({ threadId: "thread-active" }), kind: "userInput" },
|
||||
{ request: mcpElicitationRequest(), kind: "mcpElicitation" },
|
||||
{ request: currentTimeRequest("thread-active"), kind: "currentTime" },
|
||||
{ request: dynamicToolCallRequest(), kind: "unsupported" },
|
||||
] as const;
|
||||
|
||||
for (const { request, kind } of requests) {
|
||||
expect(routeServerRequest(request, activeScope).kind).toBe(kind);
|
||||
if ("turnId" in request.params) {
|
||||
expect(
|
||||
routeServerRequest({ ...request, params: { ...request.params, turnId: "turn-other" } } as ServerRequest, activeScope).kind,
|
||||
).toBe("inactive");
|
||||
}
|
||||
it.each([
|
||||
{ name: "command approval", request: commandApprovalRequest(), kind: "approval" },
|
||||
{ name: "file change approval", request: fileChangeApprovalRequest(), kind: "approval" },
|
||||
{ name: "permissions approval", request: permissionsApprovalRequest(), kind: "approval" },
|
||||
{ name: "user input", request: userInputRequest({ threadId: "thread-active" }), kind: "userInput" },
|
||||
{ name: "MCP elicitation", request: mcpElicitationRequest(), kind: "mcpElicitation" },
|
||||
{ name: "current time", request: currentTimeRequest("thread-active"), kind: "currentTime" },
|
||||
{ name: "dynamic tool call", request: dynamicToolCallRequest(), kind: "unsupported" },
|
||||
])("classifies $name server requests and extracts scope", ({ request, kind }) => {
|
||||
expect(routeServerRequest(request, activeScope).kind).toBe(kind);
|
||||
if ("turnId" in request.params) {
|
||||
expect(
|
||||
routeServerRequest({ ...request, params: { ...request.params, threadId: "thread-other" } } as ServerRequest, activeScope).kind,
|
||||
routeServerRequest({ ...request, params: { ...request.params, turnId: "turn-other" } } as ServerRequest, activeScope).kind,
|
||||
).toBe("inactive");
|
||||
}
|
||||
expect(
|
||||
routeServerRequest({ ...request, params: { ...request.params, threadId: "thread-other" } } as ServerRequest, activeScope).kind,
|
||||
).toBe("inactive");
|
||||
});
|
||||
|
||||
it("marks scoped messages inactive when the thread or turn does not match", () => {
|
||||
|
|
@ -149,11 +145,13 @@ describe("chat inbound routing", () => {
|
|||
).toBe("inactive");
|
||||
});
|
||||
|
||||
it("classifies supported server request families before unsupported requests", () => {
|
||||
expect(routeServerRequest(commandApprovalRequest(), { activeThreadId: null, activeTurnId: null }).kind).toBe("approval");
|
||||
expect(routeServerRequest(userInputRequest(), { activeThreadId: null, activeTurnId: null }).kind).toBe("userInput");
|
||||
expect(routeServerRequest(mcpElicitationRequest(), { activeThreadId: null, activeTurnId: null }).kind).toBe("mcpElicitation");
|
||||
expect(routeServerRequest(currentTimeRequest("thread-active"), { activeThreadId: null, activeTurnId: null }).kind).toBe("currentTime");
|
||||
it.each([
|
||||
{ name: "command approval", request: commandApprovalRequest(), kind: "approval" },
|
||||
{ name: "user input", request: userInputRequest(), kind: "userInput" },
|
||||
{ name: "MCP elicitation", request: mcpElicitationRequest(), kind: "mcpElicitation" },
|
||||
{ name: "current time", request: currentTimeRequest("thread-active"), kind: "currentTime" },
|
||||
])("classifies $name before unsupported requests", ({ request, kind }) => {
|
||||
expect(routeServerRequest(request, { activeThreadId: null, activeTurnId: null }).kind).toBe(kind);
|
||||
});
|
||||
|
||||
it("classifies inactive requests before request-family handling", () => {
|
||||
|
|
@ -162,10 +160,13 @@ describe("chat inbound routing", () => {
|
|||
expect(route.kind).toBe("inactive");
|
||||
});
|
||||
|
||||
it("keeps unscoped unsupported requests out of active-turn routing", () => {
|
||||
for (const request of unscopedUnsupportedRequests()) {
|
||||
expect(routeServerRequest(request, activeScope).kind).toBe("unsupported");
|
||||
}
|
||||
it.each(
|
||||
unscopedUnsupportedRequests().map((request) => ({
|
||||
name: request.method,
|
||||
request,
|
||||
})),
|
||||
)("keeps unscoped unsupported request $name out of active-turn routing", ({ request }) => {
|
||||
expect(routeServerRequest(request, activeScope).kind).toBe("unsupported");
|
||||
});
|
||||
|
||||
it("routes unknown runtime server requests to the unknown fallback", () => {
|
||||
|
|
@ -187,15 +188,17 @@ describe("chat inbound routing", () => {
|
|||
).toBe("inactive");
|
||||
});
|
||||
|
||||
it("classifies notification categories without mutating state", () => {
|
||||
expect(routeServerNotification(agentDeltaNotification(), activeScope).kind).toBe("streamUpdate");
|
||||
expect(routeServerNotification(turnStartedNotification(), activeScope).kind).toBe("turnLifecycle");
|
||||
expect(routeServerNotification(threadArchivedNotification(), activeScope).kind).toBe("threadLifecycle");
|
||||
expect(routeServerNotification(threadSettingsUpdatedNotification(), activeScope).kind).toBe("threadLifecycle");
|
||||
expect(routeServerNotification(threadGoalUpdatedNotification(), activeScope).kind).toBe("threadLifecycle");
|
||||
expect(routeServerNotification(serverRequestResolvedNotification(), activeScope).kind).toBe("requestResolved");
|
||||
expect(routeServerNotification(mcpStartupStatusNotification(), activeScope).kind).toBe("diagnosticStatus");
|
||||
expect(routeServerNotification(warningNotification(), activeScope).kind).toBe("userVisibleNotice");
|
||||
it.each([
|
||||
{ name: "agent delta", notification: agentDeltaNotification(), kind: "streamUpdate" },
|
||||
{ name: "turn started", notification: turnStartedNotification(), kind: "turnLifecycle" },
|
||||
{ name: "thread archived", notification: threadArchivedNotification(), kind: "threadLifecycle" },
|
||||
{ name: "thread settings updated", notification: threadSettingsUpdatedNotification(), kind: "threadLifecycle" },
|
||||
{ name: "thread goal updated", notification: threadGoalUpdatedNotification(), kind: "threadLifecycle" },
|
||||
{ name: "server request resolved", notification: serverRequestResolvedNotification(), kind: "requestResolved" },
|
||||
{ name: "MCP startup status", notification: mcpStartupStatusNotification(), kind: "diagnosticStatus" },
|
||||
{ name: "warning", notification: warningNotification(), kind: "userVisibleNotice" },
|
||||
])("classifies $name notifications without mutating state", ({ notification, kind }) => {
|
||||
expect(routeServerNotification(notification, activeScope).kind).toBe(kind);
|
||||
});
|
||||
|
||||
it("leaves unhandled app-server notifications explicit", () => {
|
||||
|
|
@ -240,31 +243,23 @@ describe("chat inbound routing", () => {
|
|||
expect(planChatNotification(state, notification, (prefix) => `${prefix}-1`)).toEqual({ actions: [], effects: [] });
|
||||
});
|
||||
|
||||
it("still scopes app-server notifications that Codex Panel does not handle", () => {
|
||||
expect(routeServerNotification(rawResponseItemCompletedNotification("thread-active", "turn-active"), activeScope).kind).toBe(
|
||||
"unhandled",
|
||||
);
|
||||
expect(routeServerNotification(rawResponseItemCompletedNotification("thread-other", "turn-active"), activeScope).kind).toBe("inactive");
|
||||
expect(routeServerNotification(rawResponseItemCompletedNotification("thread-active", "turn-other"), activeScope).kind).toBe("inactive");
|
||||
|
||||
expect(routeServerNotification(turnModerationMetadataNotification("thread-active", "turn-active"), activeScope).kind).toBe("unhandled");
|
||||
expect(routeServerNotification(turnModerationMetadataNotification("thread-other", "turn-active"), activeScope).kind).toBe("inactive");
|
||||
expect(routeServerNotification(turnModerationMetadataNotification("thread-active", "turn-other"), activeScope).kind).toBe("inactive");
|
||||
|
||||
expect(routeServerNotification(terminalInteractionNotification("thread-active", "turn-active"), activeScope).kind).toBe("unhandled");
|
||||
expect(routeServerNotification(terminalInteractionNotification("thread-other", "turn-active"), activeScope).kind).toBe("inactive");
|
||||
expect(routeServerNotification(terminalInteractionNotification("thread-active", "turn-other"), activeScope).kind).toBe("inactive");
|
||||
|
||||
expect(routeServerNotification(modelVerificationNotification("thread-active", "turn-active"), activeScope).kind).toBe("unhandled");
|
||||
expect(routeServerNotification(modelVerificationNotification("thread-other", "turn-active"), activeScope).kind).toBe("inactive");
|
||||
expect(routeServerNotification(modelVerificationNotification("thread-active", "turn-other"), activeScope).kind).toBe("inactive");
|
||||
it.each([
|
||||
{ name: "raw response item completed", notification: rawResponseItemCompletedNotification },
|
||||
{ name: "turn moderation metadata", notification: turnModerationMetadataNotification },
|
||||
{ name: "terminal interaction", notification: terminalInteractionNotification },
|
||||
{ name: "model verification", notification: modelVerificationNotification },
|
||||
])("still scopes unhandled turn notification $name", ({ notification }) => {
|
||||
expect(routeServerNotification(notification("thread-active", "turn-active"), activeScope).kind).toBe("unhandled");
|
||||
expect(routeServerNotification(notification("thread-other", "turn-active"), activeScope).kind).toBe("inactive");
|
||||
expect(routeServerNotification(notification("thread-active", "turn-other"), activeScope).kind).toBe("inactive");
|
||||
});
|
||||
|
||||
it("still scopes unhandled thread lifecycle notifications", () => {
|
||||
expect(routeServerNotification(threadStatusChangedNotification("thread-active"), activeScope).kind).toBe("unhandled");
|
||||
expect(routeServerNotification(threadStatusChangedNotification("thread-other"), activeScope).kind).toBe("inactive");
|
||||
expect(routeServerNotification(threadClosedNotification("thread-active"), activeScope).kind).toBe("unhandled");
|
||||
expect(routeServerNotification(threadClosedNotification("thread-other"), activeScope).kind).toBe("inactive");
|
||||
it.each([
|
||||
{ name: "thread status changed", notification: threadStatusChangedNotification },
|
||||
{ name: "thread closed", notification: threadClosedNotification },
|
||||
])("still scopes unhandled thread lifecycle notification $name", ({ notification }) => {
|
||||
expect(routeServerNotification(notification("thread-active"), activeScope).kind).toBe("unhandled");
|
||||
expect(routeServerNotification(notification("thread-other"), activeScope).kind).toBe("inactive");
|
||||
});
|
||||
|
||||
it("scopes MCP startup status notifications when app-server provides a thread id", () => {
|
||||
|
|
|
|||
|
|
@ -385,60 +385,61 @@ describe("approval model", () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it("builds action responses for current approval families", () => {
|
||||
const requests: { request: ServerRequest; acceptSession: unknown; cancel: unknown }[] = [
|
||||
{
|
||||
request: {
|
||||
id: 3,
|
||||
method: "item/commandExecution/requestApproval",
|
||||
params: {
|
||||
command: "npm test",
|
||||
cwd: "/tmp/project",
|
||||
threadId: "thread",
|
||||
turnId: "turn",
|
||||
itemId: "command",
|
||||
environmentId: null,
|
||||
startedAtMs: 1,
|
||||
reason: null,
|
||||
commandActions: [],
|
||||
proposedExecpolicyAmendment: null,
|
||||
proposedNetworkPolicyAmendments: [],
|
||||
availableDecisions: ["acceptForSession", "cancel", "decline"],
|
||||
},
|
||||
it.each([
|
||||
{
|
||||
name: "command approval",
|
||||
request: {
|
||||
id: 3,
|
||||
method: "item/commandExecution/requestApproval",
|
||||
params: {
|
||||
command: "npm test",
|
||||
cwd: "/tmp/project",
|
||||
threadId: "thread",
|
||||
turnId: "turn",
|
||||
itemId: "command",
|
||||
environmentId: null,
|
||||
startedAtMs: 1,
|
||||
reason: null,
|
||||
commandActions: [],
|
||||
proposedExecpolicyAmendment: null,
|
||||
proposedNetworkPolicyAmendments: [],
|
||||
availableDecisions: ["acceptForSession", "cancel", "decline"],
|
||||
},
|
||||
acceptSession: { decision: "acceptForSession" },
|
||||
cancel: { decision: "cancel" },
|
||||
},
|
||||
{
|
||||
request: {
|
||||
id: 4,
|
||||
method: "item/fileChange/requestApproval",
|
||||
params: {
|
||||
threadId: "thread",
|
||||
turnId: "turn",
|
||||
itemId: "file",
|
||||
startedAtMs: 1,
|
||||
reason: "write",
|
||||
grantRoot: "/tmp/project",
|
||||
},
|
||||
acceptSession: { decision: "acceptForSession" },
|
||||
cancel: { decision: "cancel" },
|
||||
},
|
||||
{
|
||||
name: "file change approval",
|
||||
request: {
|
||||
id: 4,
|
||||
method: "item/fileChange/requestApproval",
|
||||
params: {
|
||||
threadId: "thread",
|
||||
turnId: "turn",
|
||||
itemId: "file",
|
||||
startedAtMs: 1,
|
||||
reason: "write",
|
||||
grantRoot: "/tmp/project",
|
||||
},
|
||||
acceptSession: { decision: "acceptForSession" },
|
||||
cancel: { decision: "cancel" },
|
||||
},
|
||||
];
|
||||
|
||||
for (const { request, acceptSession, cancel } of requests) {
|
||||
acceptSession: { decision: "acceptForSession" },
|
||||
cancel: { decision: "cancel" },
|
||||
},
|
||||
] satisfies { name: string; request: ServerRequest; acceptSession: unknown; cancel: unknown }[])(
|
||||
"builds action responses for $name",
|
||||
({ request, acceptSession, cancel }) => {
|
||||
const approval = expectPresent(toPendingApproval(request));
|
||||
if (approval.kind === "command") {
|
||||
const options = approvalActionOptions(approval);
|
||||
expect(approvalResponse(approval, expectPresent(options[0]).action)).toEqual(acceptSession);
|
||||
expect(approvalResponse(approval, expectPresent(options[1]).action)).toEqual(cancel);
|
||||
expect(approvalResponse(approval, expectPresent(options[2]).action)).toEqual({ decision: "decline" });
|
||||
} else {
|
||||
expect(approvalResponse(approval, "accept-session")).toEqual(acceptSession);
|
||||
expect(approvalResponse(approval, "cancel")).toEqual(cancel);
|
||||
expect(approvalResponse(approval, "decline")).toEqual({ decision: "decline" });
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
expect(approvalResponse(approval, "accept-session")).toEqual(acceptSession);
|
||||
expect(approvalResponse(approval, "cancel")).toEqual(cancel);
|
||||
expect(approvalResponse(approval, "decline")).toEqual({ decision: "decline" });
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@ import { fastModeActive } from "../../src/features/chat/domain/runtime/effective
|
|||
import type { RuntimeSnapshot } from "../../src/features/chat/domain/runtime/snapshot";
|
||||
|
||||
describe("service tier runtime state", () => {
|
||||
it("recognizes Codex fast tier aliases without rejecting other tier ids", () => {
|
||||
expect(fastMode("fast")).toBe(true);
|
||||
expect(fastMode("priority")).toBe(true);
|
||||
expect(fastMode("catalog-fast", [{ id: "catalog-fast", name: "Fast" }])).toBe(true);
|
||||
expect(fastMode("priority", [{ id: "priority", name: "Priority" }])).toBe(false);
|
||||
expect(fastMode("flex", [{ id: "flex", name: "Flex" }])).toBe(false);
|
||||
it.each([
|
||||
{ name: "built-in fast", serviceTier: "fast", serviceTiers: [], expected: true },
|
||||
{ name: "built-in priority", serviceTier: "priority", serviceTiers: [], expected: true },
|
||||
{ name: "catalog Fast tier", serviceTier: "catalog-fast", serviceTiers: [{ id: "catalog-fast", name: "Fast" }], expected: true },
|
||||
{ name: "catalog Priority tier", serviceTier: "priority", serviceTiers: [{ id: "priority", name: "Priority" }], expected: false },
|
||||
{ name: "catalog Flex tier", serviceTier: "flex", serviceTiers: [{ id: "flex", name: "Flex" }], expected: false },
|
||||
])("recognizes $name without rejecting other tier ids", ({ serviceTier, serviceTiers, expected }) => {
|
||||
expect(fastMode(serviceTier, serviceTiers)).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue