100 lines
3.1 KiB
TypeScript
100 lines
3.1 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
import { DemoMarketDataProvider, IPADS_BASE_URL, IPADS_WIRE_API, IpadsResponsesProvider } from "../src/agent/provider";
|
|
import { loadIpadsConfig } from "../src/server/ipadsConfig";
|
|
import type { WatchStock } from "../src/shared/types";
|
|
|
|
const stock: WatchStock = {
|
|
id: "AAPL",
|
|
symbol: "AAPL",
|
|
display: "AAPL",
|
|
market: "US",
|
|
name: "Apple",
|
|
addedAt: "2026-05-11T00:00:00.000Z"
|
|
};
|
|
|
|
describe("IpadsResponsesProvider", () => {
|
|
it("uses the fixed IPADS Responses API endpoint with IPADS_API_KEY", async () => {
|
|
const fetchImpl = vi.fn(async () => {
|
|
return new Response(
|
|
JSON.stringify({
|
|
output: [
|
|
{
|
|
type: "message",
|
|
role: "assistant",
|
|
content: [
|
|
{
|
|
type: "output_text",
|
|
text: JSON.stringify({
|
|
price: 100,
|
|
currency: "USD",
|
|
pe: 20,
|
|
forwardPe: 18,
|
|
peers: [{ display: "MSFT", pe: 25 }],
|
|
news: [{ title: "Apple earnings preview", url: "https://example.test/news" }]
|
|
})
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}),
|
|
{ status: 200, headers: { "content-type": "application/json" } }
|
|
);
|
|
});
|
|
const provider = new IpadsResponsesProvider("secret", fetchImpl);
|
|
|
|
const snapshot = await provider.snapshot(stock);
|
|
|
|
expect(fetchImpl).toHaveBeenCalledWith(
|
|
`${IPADS_BASE_URL}/${IPADS_WIRE_API}`,
|
|
expect.objectContaining({
|
|
method: "POST",
|
|
headers: expect.objectContaining({
|
|
Authorization: "Bearer secret",
|
|
"Content-Type": "application/json"
|
|
}),
|
|
body: expect.stringContaining("\"model\":\"gpt-5.5\"")
|
|
})
|
|
);
|
|
const calls = fetchImpl.mock.calls as unknown as [string, RequestInit][];
|
|
const requestBody = JSON.parse(String(calls[0]?.[1].body));
|
|
expect(requestBody.input).toContain("\"symbol\":\"AAPL\"");
|
|
expect(typeof requestBody.input).toBe("string");
|
|
expect(requestBody).not.toHaveProperty("metadata");
|
|
expect(snapshot.news[0]?.title).toBe("Apple earnings preview");
|
|
});
|
|
});
|
|
|
|
describe("loadIpadsConfig", () => {
|
|
it("reads IPADS_API_KEY from an env object and keeps fixed URL and wire API", () => {
|
|
expect(loadIpadsConfig({ IPADS_API_KEY: "secret" })).toEqual({
|
|
baseUrl: IPADS_BASE_URL,
|
|
wireApi: IPADS_WIRE_API,
|
|
apiKey: "secret",
|
|
apiKeyConfigured: true
|
|
});
|
|
});
|
|
|
|
it("reports an unconfigured API key when IPADS_API_KEY is blank", () => {
|
|
expect(loadIpadsConfig({ IPADS_API_KEY: " " })).toEqual({
|
|
baseUrl: IPADS_BASE_URL,
|
|
wireApi: IPADS_WIRE_API,
|
|
apiKey: "",
|
|
apiKeyConfigured: false
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("DemoMarketDataProvider", () => {
|
|
it("returns deterministic snapshots when no provider URL is configured", async () => {
|
|
const provider = new DemoMarketDataProvider();
|
|
|
|
await expect(provider.snapshot(stock)).resolves.toEqual(
|
|
expect.objectContaining({
|
|
currency: "USD",
|
|
peers: expect.any(Array),
|
|
news: expect.any(Array)
|
|
})
|
|
);
|
|
});
|
|
});
|