import { describe, it, expect } from "vitest"; import { createCopilotEndpoint, createCopilotEndpointSingleRoute, } from "../endpoints"; import { CopilotRuntime } from "../core/runtime"; import type { AbstractAgent } from "@ag-ui/client"; const createMockRuntime = (options: { beforeRequestMiddleware?: any } = {}) => { const createMockAgent = () => { const agent: unknown = { execute: async () => ({ events: [] }), }; (agent as { clone: () => unknown }).clone = () => createMockAgent(); return agent as AbstractAgent; }; return new CopilotRuntime({ agents: { default: createMockAgent() }, ...options, }); }; describe("CORS credentials configuration", () => { describe("createCopilotEndpoint", () => { it("sets Access-Control-Allow-Credentials header when credentials is true", async () => { const runtime = createMockRuntime(); const endpoint = createCopilotEndpoint({ runtime, basePath: "/", cors: { origin: "https://myapp.com", credentials: true, }, }); // Make a preflight OPTIONS request const request = new Request("https://example.com/info", { method: "OPTIONS", headers: { Origin: "https://myapp.com", "Access-Control-Request-Method": "GET", }, }); const response = await endpoint.fetch(request); expect(response.headers.get("Access-Control-Allow-Credentials")).toBe( "true", ); expect(response.headers.get("Access-Control-Allow-Origin")).toBe( "https://myapp.com", ); }); it("does not set Access-Control-Allow-Credentials header when credentials is false", async () => { const runtime = createMockRuntime(); const endpoint = createCopilotEndpoint({ runtime, basePath: "/", cors: { origin: "https://myapp.com", credentials: false, }, }); const request = new Request("https://example.com/info", { method: "OPTIONS", headers: { Origin: "https://myapp.com", "Access-Control-Request-Method": "GET", }, }); const response = await endpoint.fetch(request); // When credentials is false, the header should not be present or be "false" const credentialsHeader = response.headers.get( "Access-Control-Allow-Credentials", ); expect(credentialsHeader === null || credentialsHeader === "false").toBe( true, ); }); it("defaults to no credentials when cors config is not provided", async () => { const runtime = createMockRuntime(); const endpoint = createCopilotEndpoint({ runtime, basePath: "/", // No cors config - should default to origin: "*" without credentials }); const request = new Request("https://example.com/info", { method: "OPTIONS", headers: { Origin: "https://somesite.com", "Access-Control-Request-Method": "GET", }, }); const response = await endpoint.fetch(request); // Should allow any origin but not credentials expect(response.headers.get("Access-Control-Allow-Origin")).toBe("*"); const credentialsHeader = response.headers.get( "Access-Control-Allow-Credentials", ); expect(credentialsHeader === null || credentialsHeader === "false").toBe( true, ); }); it("receives cookies in request when client sends them", async () => { const receivedCookies: string[] = []; const runtime = createMockRuntime({ beforeRequestMiddleware: async ({ request }: { request: Request }) => { const cookie = request.headers.get("Cookie"); if (cookie) { receivedCookies.push(cookie); } return undefined; // Don't modify the request }, }); const endpoint = createCopilotEndpoint({ runtime, basePath: "/", cors: { origin: "https://myapp.com", credentials: true, }, }); // Simulate a request with cookies (as a browser would send with credentials: "include") const request = new Request("https://example.com/info", { method: "GET", headers: { Origin: "https://myapp.com", Cookie: "session=abc123; user=john", }, }); const response = await endpoint.fetch(request); expect(response.status).toBe(200); expect(receivedCookies).toContain("session=abc123; user=john"); }); }); describe("createCopilotEndpointSingleRoute", () => { it("sets Access-Control-Allow-Credentials header when credentials is true", async () => { const runtime = createMockRuntime(); const endpoint = createCopilotEndpointSingleRoute({ runtime, basePath: "/api/copilotkit", cors: { origin: "https://myapp.com", credentials: true, }, }); const request = new Request("https://example.com/api/copilotkit", { method: "OPTIONS", headers: { Origin: "https://myapp.com", "Access-Control-Request-Method": "POST", }, }); const response = await endpoint.fetch(request); expect(response.headers.get("Access-Control-Allow-Credentials")).toBe( "true", ); expect(response.headers.get("Access-Control-Allow-Origin")).toBe( "https://myapp.com", ); }); it("receives cookies in POST request body", async () => { const receivedCookies: string[] = []; const runtime = createMockRuntime({ beforeRequestMiddleware: async ({ request }: { request: Request }) => { const cookie = request.headers.get("Cookie"); if (cookie) { receivedCookies.push(cookie); } return undefined; }, }); const endpoint = createCopilotEndpointSingleRoute({ runtime, basePath: "/api/copilotkit", cors: { origin: "https://myapp.com", credentials: true, }, }); const request = new Request("https://example.com/api/copilotkit", { method: "POST", headers: { Origin: "https://myapp.com", "Content-Type": "application/json", Cookie: "auth_token=xyz789", }, body: JSON.stringify({ method: "info" }), }); const response = await endpoint.fetch(request); expect(response.status).toBe(200); expect(receivedCookies).toContain("auth_token=xyz789"); }); }); describe("origin configuration", () => { it("supports string origin", async () => { const runtime = createMockRuntime(); const endpoint = createCopilotEndpoint({ runtime, basePath: "/", cors: { origin: "https://specific-origin.com", credentials: true, }, }); const request = new Request("https://example.com/info", { method: "OPTIONS", headers: { Origin: "https://specific-origin.com", "Access-Control-Request-Method": "GET", }, }); const response = await endpoint.fetch(request); expect(response.headers.get("Access-Control-Allow-Origin")).toBe( "https://specific-origin.com", ); }); it("supports array of origins", async () => { const runtime = createMockRuntime(); const endpoint = createCopilotEndpoint({ runtime, basePath: "/", cors: { origin: ["https://app1.com", "https://app2.com"], credentials: true, }, }); // Request from first allowed origin const request1 = new Request("https://example.com/info", { method: "OPTIONS", headers: { Origin: "https://app1.com", "Access-Control-Request-Method": "GET", }, }); const response1 = await endpoint.fetch(request1); expect(response1.headers.get("Access-Control-Allow-Origin")).toBe( "https://app1.com", ); // Request from second allowed origin const request2 = new Request("https://example.com/info", { method: "OPTIONS", headers: { Origin: "https://app2.com", "Access-Control-Request-Method": "GET", }, }); const response2 = await endpoint.fetch(request2); expect(response2.headers.get("Access-Control-Allow-Origin")).toBe( "https://app2.com", ); }); it("supports function origin for dynamic resolution", async () => { const runtime = createMockRuntime(); const endpoint = createCopilotEndpoint({ runtime, basePath: "/", cors: { origin: (origin: string) => { // Only allow origins ending with .mycompany.com if (origin.endsWith(".mycompany.com")) { return origin; } return null; }, credentials: true, }, }); // Allowed origin const request1 = new Request("https://example.com/info", { method: "OPTIONS", headers: { Origin: "https://app.mycompany.com", "Access-Control-Request-Method": "GET", }, }); const response1 = await endpoint.fetch(request1); expect(response1.headers.get("Access-Control-Allow-Origin")).toBe( "https://app.mycompany.com", ); }); }); });