test(ui): feed the Decisions playground integration test /model/info deployments

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
mateo 2026-10-10 22:41:54 +00:00
parent 09660f73e8
commit 00cb4d0f01

View file

@ -15,15 +15,15 @@ import SystemOneUI, { NOUL_HELP } from "./SystemOneUI";
import type { SystemOneResponse } from "./lib/schemas";
import type { OpenAIDecisionsResponse } from "./lib/openAIDecisions";
interface ModelGroupInfo {
model_group: string;
interface Deployment {
model_name: string;
mode: string;
}
const DECISION_AND_CHAT_MODELS: ModelGroupInfo[] = [
{ model_group: "gpt-5.5", mode: "chat" },
{ model_group: "jev-latest", mode: "evaluation" },
{ model_group: "pplx-decider", mode: "evaluation" },
const DECISION_AND_CHAT_MODELS: Deployment[] = [
{ model_name: "gpt-5.5", mode: "chat" },
{ model_name: "jev-latest", mode: "evaluation" },
{ model_name: "pplx-decider", mode: "evaluation" },
];
const responseBody: SystemOneResponse = {
@ -45,8 +45,19 @@ const render = (ui: ReactElement) =>
</QueryClientProvider>,
);
const modelGroupInfoResponse = (groups: ModelGroupInfo[]) =>
({ ok: true, status: 200, text: async () => JSON.stringify({ data: groups }) }) as Response;
const modelInfoResponse = (deployments: Deployment[]) =>
({
ok: true,
status: 200,
text: async () =>
JSON.stringify({
data: deployments.map(({ model_name, mode }) => ({
model_name,
litellm_params: { model: `openai/${model_name}` },
model_info: { id: model_name, mode },
})),
}),
}) as Response;
const EXPIRED_KEY_RESPONSE = {
ok: false,
@ -55,7 +66,7 @@ const EXPIRED_KEY_RESPONSE = {
JSON.stringify({ error: { message: "Authentication Error - Expired Key.", type: "expired_key", code: "401" } }),
} as Response;
const isModelLookup = (input: RequestInfo | URL) => String(input).endsWith("/model_group/info");
const isModelLookup = (input: RequestInfo | URL) => String(input).endsWith("/model/info");
const lookupAuthHeaders = (calls: Parameters<typeof fetch>[]) =>
calls.map(([, init]) => Object.values((init?.headers ?? {}) as Record<string, string>));
@ -96,7 +107,7 @@ describe("SystemOneUI integration", () => {
isModelLookup(input) ? mockModelLookup(input, init) : mockFetch(input, init),
);
mockFetch.mockResolvedValue(createResponse(responseBody));
mockModelLookup.mockResolvedValue(modelGroupInfoResponse([]));
mockModelLookup.mockResolvedValue(modelInfoResponse([]));
});
afterEach(() => {
@ -143,7 +154,7 @@ describe("SystemOneUI integration", () => {
});
it("keeps the preset label after picking a model and leaves an omitted model out when clearing", async () => {
mockModelLookup.mockResolvedValue(modelGroupInfoResponse(DECISION_AND_CHAT_MODELS));
mockModelLookup.mockResolvedValue(modelInfoResponse(DECISION_AND_CHAT_MODELS));
render(<SystemOneUI accessToken="session-key" />);
await waitFor(() => expect(screen.getByRole("combobox", { name: "Decision model" })).toHaveValue("jev-latest"));
const picker = screen.getByRole("combobox", { name: "Example" });
@ -210,7 +221,7 @@ describe("SystemOneUI integration", () => {
it("opens on /v1/systemone with the first decision model the key can call", async () => {
const user = userEvent.setup();
mockModelLookup.mockResolvedValue(modelGroupInfoResponse(DECISION_AND_CHAT_MODELS));
mockModelLookup.mockResolvedValue(modelInfoResponse(DECISION_AND_CHAT_MODELS));
render(<SystemOneUI accessToken="session-key" />);
await waitFor(() => expect(screen.getByRole("combobox", { name: "Decision model" })).toHaveValue("jev-latest"));
@ -228,7 +239,7 @@ describe("SystemOneUI integration", () => {
it("sends each endpoint's real shape and switches existing responses between cards and JSON without resending", async () => {
const user = userEvent.setup();
mockModelLookup.mockResolvedValue(modelGroupInfoResponse(DECISION_AND_CHAT_MODELS));
mockModelLookup.mockResolvedValue(modelInfoResponse(DECISION_AND_CHAT_MODELS));
render(<SystemOneUI accessToken="session-key" />);
await waitFor(() => expect(screen.getByRole("combobox", { name: "Decision model" })).toHaveValue("jev-latest"));
const systemOneEditor = await openJsonEditor();
@ -519,7 +530,7 @@ describe("SystemOneUI integration", () => {
it("offers only decision models and writes the picked one into the request", async () => {
const user = userEvent.setup();
mockModelLookup.mockResolvedValue(modelGroupInfoResponse(DECISION_AND_CHAT_MODELS));
mockModelLookup.mockResolvedValue(modelInfoResponse(DECISION_AND_CHAT_MODELS));
render(<SystemOneUI accessToken="session-key" />);
const picker = await screen.findByRole("combobox", { name: "Decision model" });
@ -542,9 +553,7 @@ describe("SystemOneUI integration", () => {
it("routes a configured TypeSafe model through the same proxy endpoint", async () => {
const user = userEvent.setup();
mockModelLookup.mockResolvedValue(
modelGroupInfoResponse([{ model_group: "typesafe/jev-latest", mode: "evaluation" }]),
);
mockModelLookup.mockResolvedValue(modelInfoResponse([{ model_name: "typesafe/jev-latest", mode: "evaluation" }]));
render(<SystemOneUI accessToken="session-key" />);
await waitFor(() =>
expect(screen.getByRole("combobox", { name: "Decision model" })).toHaveValue("typesafe/jev-latest"),
@ -573,7 +582,7 @@ describe("SystemOneUI integration", () => {
it("looks up a typed virtual key's decision models once, after typing settles", async () => {
const user = userEvent.setup();
mockModelLookup.mockResolvedValue(modelGroupInfoResponse(DECISION_AND_CHAT_MODELS));
mockModelLookup.mockResolvedValue(modelInfoResponse(DECISION_AND_CHAT_MODELS));
render(<SystemOneUI accessToken={null} disabledPersonalKeyCreation />);
await user.type(screen.getByLabelText("Virtual Key", { exact: true }), "sk-typed-key");
@ -606,7 +615,7 @@ describe("SystemOneUI integration", () => {
fireEvent.change(editor, { target: { value: draft } });
await act(async () => {
models.resolve(modelGroupInfoResponse(DECISION_AND_CHAT_MODELS));
models.resolve(modelInfoResponse(DECISION_AND_CHAT_MODELS));
await new Promise((resolve) => setTimeout(resolve, 0));
});
@ -635,7 +644,7 @@ describe("SystemOneUI integration", () => {
expect(mockFetch.mock.calls[0]?.[0]).toMatch(new RegExp(`${endpoint}$`));
expect(JSON.parse(mockFetch.mock.calls[0]?.[1]?.body as string)).not.toHaveProperty("model");
await act(async () => {
models.resolve(modelGroupInfoResponse(DECISION_AND_CHAT_MODELS));
models.resolve(modelInfoResponse(DECISION_AND_CHAT_MODELS));
await models.promise;
});
expect(screen.getByRole("combobox", { name: "Decision model" })).toHaveValue("");
@ -676,7 +685,7 @@ describe("SystemOneUI integration", () => {
it("uses the requested model when the response omits it", async () => {
const user = userEvent.setup();
mockModelLookup.mockResolvedValue(modelGroupInfoResponse(DECISION_AND_CHAT_MODELS));
mockModelLookup.mockResolvedValue(modelInfoResponse(DECISION_AND_CHAT_MODELS));
mockFetch.mockResolvedValueOnce(
createResponse({
answers: responseBody.answers,
@ -984,7 +993,7 @@ describe("SystemOneUI integration", () => {
it("edits score levels and keeps instructions when a question changes type", async () => {
const user = userEvent.setup();
mockModelLookup.mockResolvedValue(modelGroupInfoResponse(DECISION_AND_CHAT_MODELS));
mockModelLookup.mockResolvedValue(modelInfoResponse(DECISION_AND_CHAT_MODELS));
render(<SystemOneUI accessToken="session-key" />);
await waitFor(() => expect(screen.getByRole("combobox", { name: "Decision model" })).toHaveValue("jev-latest"));