Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
6.5 kB ยท 191 lines
TypeScript
at incident-api
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192import { createMonitor } from "@openstatus/db/src/test/factories";import { expect } from "@std/expect";import { beforeAll, describe, test } from "@std/testing/bdd";
import { createWorkspaceFixture, makeUserCtx } from "../../../test/helpers";import type { ServiceContext } from "../../context";import { agentTools } from "../index";import type { AnyAgentTool } from "../types";
let teamCtx: ServiceContext;let monitorId: number;
beforeAll(async () => { const { workspace, userId } = await createWorkspaceFixture("team"); teamCtx = makeUserCtx(workspace, { userId }); const monitor = await createMonitor(workspace.id); monitorId = monitor.id;});
describe("agent-tool shape equivalence", () => { test("list_status_pages output matches schema", async () => { const tool = agentTools.list_status_pages; const result = await tool.run({ ctx: teamCtx, input: {} }); const parsed = tool.outputSchema.safeParse(result); expect(parsed.success, parsed.error?.message).toBe(true); });
test("list_page_components output matches schema", async () => { const tool = agentTools.list_page_components; const result = await tool.run({ ctx: teamCtx, input: {} }); const parsed = tool.outputSchema.safeParse(result); expect(parsed.success, parsed.error?.message).toBe(true); });
test("list_status_reports output matches schema", async () => { const tool = agentTools.list_status_reports; const result = await tool.run({ ctx: teamCtx, input: { filter: "all", page: 1, perPage: 5 }, }); const parsed = tool.outputSchema.safeParse(result); expect(parsed.success, parsed.error?.message).toBe(true); });
test("list_maintenances output matches schema", async () => { const tool = agentTools.list_maintenances; const result = await tool.run({ ctx: teamCtx, input: { page: 1, perPage: 5 }, }); const parsed = tool.outputSchema.safeParse(result); expect(parsed.success, parsed.error?.message).toBe(true); });
test("list_monitors output matches schema", async () => { const tool = agentTools.list_monitors; const result = await tool.run({ ctx: teamCtx, input: { page: 1, perPage: 5 }, }); const parsed = tool.outputSchema.safeParse(result); expect(parsed.success, parsed.error?.message).toBe(true); });
test("list_notifications output matches schema", async () => { const tool = agentTools.list_notifications; const result = await tool.run({ ctx: teamCtx, input: { page: 1, perPage: 5 }, }); const parsed = tool.outputSchema.safeParse(result); expect(parsed.success, parsed.error?.message).toBe(true); });
test("get_monitor output matches schema", async () => { const tool = agentTools.get_monitor; const result = await tool.run({ ctx: teamCtx, input: { monitorId }, }); const parsed = tool.outputSchema.safeParse(result); expect(parsed.success, parsed.error?.message).toBe(true); });
test("get_monitor_status output matches schema", async () => { const tool = agentTools.get_monitor_status; const result = await tool.run({ ctx: teamCtx, input: { monitorId }, }); const parsed = tool.outputSchema.safeParse(result); expect(parsed.success, parsed.error?.message).toBe(true); });
test("get_monitor_summary output matches schema", async () => { const tool = agentTools.get_monitor_summary; const result = await tool.run({ ctx: teamCtx, input: { monitorId, timeRange: "1d" }, }); const parsed = tool.outputSchema.safeParse(result); expect(parsed.success, parsed.error?.message).toBe(true); });
test("list_response_logs output matches schema", async () => { const tool = agentTools.list_response_logs; const result = await tool.run({ ctx: teamCtx, input: { monitorId, timeRange: "1d", status: ["error"], limit: 10, }, }); const parsed = tool.outputSchema.safeParse(result); expect(parsed.success, parsed.error?.message).toBe(true); });
// get_response_log requires a Tinybird row; covered by RPC handler tests.});
describe("approval metadata contract", () => { const destructiveTools = Object.values(agentTools).filter( (t): t is AnyAgentTool => t.destructive, );
test("every destructive tool declares approval", () => { for (const t of destructiveTools) { expect(t.approval, `${t.name} missing approval`).toBeDefined(); } });
test("extraFlags is capped at one entry", () => { for (const t of destructiveTools) { const flags = t.approval?.extraFlags ?? []; expect(flags.length, `${t.name} extraFlags.length`).toBeLessThanOrEqual( 1, ); } });
test("extraFlags requires applyFlags", () => { for (const t of destructiveTools) { if (t.approval?.extraFlags?.length) { expect( t.approval.applyFlags, `${t.name} extraFlags but no applyFlags`, ).toBeDefined(); } } });
test("applyFlags injects the declared flag id", () => { for (const t of destructiveTools) { const flag = t.approval?.extraFlags?.[0]; if (!flag || !t.approval?.applyFlags) continue; const draft = {} as Record<string, unknown>; const merged = t.approval.applyFlags(draft, { [flag.id]: true, }) as Record<string, unknown>; expect(merged[flag.id], `${t.name} applyFlags(true)`).toBe(true); const merged2 = t.approval.applyFlags(draft, { [flag.id]: false, }) as Record<string, unknown>; expect(merged2[flag.id], `${t.name} applyFlags(false)`).toBe(false); } });
test("summarize returns a non-empty title", () => { for (const t of destructiveTools) { if (!t.approval) continue; // Smoke-call with a synthetic input so we just check shape. // Real inputs are tool-specific; we use minimal placeholders. const placeholder: Record<string, unknown> = { title: "t", message: "m", status: "investigating", pageId: 1, statusReportId: 1, from: new Date().toISOString(), to: new Date(Date.now() + 60000).toISOString(), pageComponentIds: [], content: "c", }; const summary = t.approval.summarize(placeholder); expect(summary.title.length, `${t.name} title empty`).toBeGreaterThan(0); expect(Array.isArray(summary.lines)).toBe(true); } });});