Files
cfw-autumn/apps/leaf/tests/unit/agent/agent.test.ts
2026-06-06 21:15:25 +01:00

169 lines
4.5 KiB
TypeScript

import { afterEach, describe, expect, test } from "bun:test";
import { AppEnv } from "@autumn/shared";
process.env.DATABASE_URL ??=
"postgresql://postgres:postgres@localhost:5432/postgres";
process.env.ENCRYPTION_PASSWORD ??= "test";
process.env.SLACK_CLIENT_ID ??= "test";
process.env.SLACK_CLIENT_SECRET ??= "test";
process.env.SLACK_SIGNING_SECRET ??= "test";
process.env.FIRECRAWL_API_KEY ??= "fc_test";
const { agentDocUris, getDefaultChatEnv, selectChatEnv } = await import(
"../../../src/agent/agent.js"
);
const { createFirecrawlTools } = await import(
"../../../src/agent/firecrawl.js"
);
const execute = async (
tool: { execute?: (...args: never[]) => Promise<unknown> } | undefined,
input: unknown,
) => {
if (!tool?.execute) throw new Error("Tool is not executable");
return tool.execute(input as never, {} as never);
};
const originalNodeEnv = process.env.NODE_ENV;
afterEach(() => {
if (originalNodeEnv === undefined) {
delete process.env.NODE_ENV;
} else {
process.env.NODE_ENV = originalNodeEnv;
}
});
describe("chat environment selection", () => {
test("loads feature catalog MCP guidance", () => {
expect(agentDocUris).toContain("autumn://docs/feature-catalog");
});
test("loads request-log MCP guidance", () => {
expect(agentDocUris).toContain("autumn://docs/request-logs");
expect(agentDocUris).toContain("autumn://docs/request-log-customers");
expect(agentDocUris).toContain("autumn://docs/request-log-balances");
expect(agentDocUris).toContain("autumn://docs/request-log-billing");
expect(agentDocUris).toContain("autumn://docs/request-log-stripe-webhooks");
expect(agentDocUris).toContain("autumn://docs/request-log-analytics");
});
test("defaults to sandbox outside production", () => {
delete process.env.NODE_ENV;
expect(getDefaultChatEnv()).toBe(AppEnv.Sandbox);
process.env.NODE_ENV = "development";
expect(getDefaultChatEnv()).toBe(AppEnv.Sandbox);
});
test("defaults to live in production", () => {
process.env.NODE_ENV = "production";
expect(getDefaultChatEnv()).toBe(AppEnv.Live);
});
test("uses live from structured model output", async () => {
await expect(
selectChatEnv({
message: "list customers",
select: () => ({ env: AppEnv.Live }),
}),
).resolves.toBe(AppEnv.Live);
});
test("uses sandbox from structured model output", async () => {
await expect(
selectChatEnv({
message: "try this in the sandbox first",
select: () => ({ env: AppEnv.Sandbox }),
}),
).resolves.toBe(AppEnv.Sandbox);
});
test("rejects malformed model output", async () => {
await expect(
selectChatEnv({
message: "test mode",
select: () => ({ env: "test" }),
}),
).rejects.toThrow();
});
});
describe("Firecrawl tools", () => {
test("registers search and scrape tools", () => {
const tools = createFirecrawlTools({
apiKey: "fc_test",
client: {
search: async () => ({ web: [] }),
scrape: async () => ({}),
},
});
expect(Object.keys(tools).sort()).toEqual(["scrapeUrl", "searchWeb"]);
});
test("maps search results into compact output", async () => {
const tools = createFirecrawlTools({
apiKey: "fc_test",
client: {
search: async (query, options) => {
expect(query).toBe("autumn billing docs");
expect(options).toEqual({ limit: 2, sources: ["web"] });
return {
web: [
{
title: "Autumn Docs",
url: "https://docs.useautumn.com",
description: "Billing docs",
},
],
};
},
scrape: async () => ({}),
},
});
await expect(
execute(tools.searchWeb, { query: "autumn billing docs", limit: 2 }),
).resolves.toEqual({
results: [
{
title: "Autumn Docs",
url: "https://docs.useautumn.com",
description: "Billing docs",
},
],
});
});
test("scrapes one URL and bounds returned markdown", async () => {
const tools = createFirecrawlTools({
apiKey: "fc_test",
client: {
search: async () => ({ web: [] }),
scrape: async (url, options) => {
expect(url).toBe("https://example.com");
expect(options).toEqual({ formats: ["markdown"] });
return {
markdown: `${"a".repeat(13_000)}\n\n\nextra`,
metadata: {
title: "Example",
sourceURL: "https://example.com",
},
};
},
},
});
const result = await execute(tools.scrapeUrl, {
url: "https://example.com",
});
expect(result).toMatchObject({
title: "Example",
url: "https://example.com",
});
expect((result as { markdown: string }).markdown.length).toBe(12_000);
});
});