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.9 kB ยท 203 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204import { expect } from "@std/expect";import { afterEach, describe, test } from "@std/testing/bdd";import { assertSpyCalls, spy } from "@std/testing/mock";
import type { ServiceContext } from "../../context";import { getContentPageTool, searchContentTool } from "../content";
// Both tools ignore ctx โ public content, workspace-independent.const ctx = {} as ServiceContext;
const originalFetch = globalThis.fetch;
afterEach(() => { globalThis.fetch = originalFetch;});
function mockFetch(response: Response) { const fn = spy(async () => response); globalThis.fetch = fn as unknown as typeof fetch; return fn;}
function searchFixture(i: number, type = "product") { return { metadata: { title: `Result ${i}`, description: `Description ${i}`, publishedAt: "2018-10-20T01:46:40.000Z", author: "openstatus", }, type, content: `...snippet for result ${i}...`, slug: `page-${i}`, href: `/page-${i}?q=pricing#some-heading`, filePath: `/var/task/apps/web/src/content/pages/product/page-${i}.mdx`, };}
describe("search_content", () => { test("defaults to the `all` corpus", async () => { const fn = mockFetch(Response.json([])); await searchContentTool.run({ ctx, input: searchContentTool.inputSchema.parse({ query: "pricing" }), }); assertSpyCalls(fn, 1); const url = String((fn.calls[0] as { args: unknown[] }).args[0]); expect(url).toContain("/api/search?p=all&q=pricing"); });
test("passes a narrowed type through", async () => { const fn = mockFetch(Response.json([])); await searchContentTool.run({ ctx, input: { query: "pricing", type: "compare" }, }); const url = String((fn.calls[0] as { args: unknown[] }).args[0]); expect(url).toContain("/api/search?p=compare&q=pricing"); });
test("maps live response shape incl. type, strips query/hash/filePath", async () => { mockFetch(Response.json([searchFixture(1), searchFixture(2, "blog")])); const result = await searchContentTool.run({ ctx, input: { query: "pricing", type: "all" }, }); const parsed = searchContentTool.outputSchema.safeParse(result); expect(parsed.success, parsed.error?.message).toBe(true); expect(result.results).toHaveLength(2); const first = result.results[0]; expect(first.title).toBe("Result 1"); expect(first.type).toBe("product"); expect(first.path).toBe("page-1"); expect(first.url).toBe( "https://www.openstatus.dev/page-1?q=pricing#some-heading", ); expect(result.results[1].type).toBe("blog"); expect(JSON.stringify(result)).not.toContain("filePath"); });
test("drops the homepage โ get_content_page has no path for it", async () => { mockFetch( Response.json([ { ...searchFixture(0), href: "/" }, { ...searchFixture(1), href: "/?ref=search" }, searchFixture(2), ]), ); const result = await searchContentTool.run({ ctx, input: { query: "what is openstatus", type: "all" }, }); expect(result.results.map((r) => r.path)).toEqual(["page-2"]); });
test("returns error shape on non-OK response without throwing", async () => { mockFetch(new Response("oops", { status: 500 })); const result = await searchContentTool.run({ ctx, input: { query: "pricing", type: "all" }, }); expect(result.results).toEqual([]); expect(result.error).toBe("search unavailable (HTTP 500)"); expect(searchContentTool.outputSchema.safeParse(result).success).toBe(true); });
test("returns error shape when fetch throws", async () => { globalThis.fetch = (async () => { throw new Error("ECONNREFUSED"); }) as unknown as typeof fetch; const result = await searchContentTool.run({ ctx, input: { query: "pricing", type: "all" }, }); expect(result.results).toEqual([]); expect(result.error).toBe("search unavailable (network error)"); });
test("caps results at 8", async () => { mockFetch( Response.json(Array.from({ length: 12 }, (_, i) => searchFixture(i))), ); const result = await searchContentTool.run({ ctx, input: { query: "pricing", type: "all" }, }); expect(result.results).toHaveLength(8); });});
describe("get_content_page", () => { test("fetches any site page, not only docs", async () => { const fn = mockFetch(new Response("# Pricing\n\nPlans.")); const result = await getContentPageTool.run({ ctx, input: { path: "/pricing" }, }); const parsed = getContentPageTool.outputSchema.safeParse(result); expect(parsed.success, parsed.error?.message).toBe(true); expect(result.markdown).toBe("# Pricing\n\nPlans."); expect(result.truncated).toBe(false); expect(result.url).toBe("https://www.openstatus.dev/pricing"); const url = String((fn.calls[0] as { args: unknown[] }).args[0]); expect(url).toBe("https://www.openstatus.dev/api/markdown/pricing"); });
test("truncates long pages with a marker", async () => { mockFetch(new Response("x".repeat(30_000))); const result = await getContentPageTool.run({ ctx, input: { path: "blog/some-post" }, }); expect(result.truncated).toBe(true); expect(result.markdown.length).toBeLessThan(24_200); expect( result.markdown.endsWith( "[truncated โ content continues at https://www.openstatus.dev/blog/some-post]", ), ).toBe(true); });
test("returns error shape on 404", async () => { mockFetch(new Response("Not Found", { status: 404 })); const result = await getContentPageTool.run({ ctx, input: { path: "compare/does-not-exist" }, }); expect(result.markdown).toBe(""); expect(result.error).toBe("page not found (HTTP 404)"); });
test("reports non-404 failures as unavailable, not missing", async () => { mockFetch(new Response("oops", { status: 500 })); const result = await getContentPageTool.run({ ctx, input: { path: "pricing" }, }); expect(result.markdown).toBe(""); expect(result.error).toBe("page unavailable (HTTP 500)"); });
test("rejects traversal, absolute urls and odd characters without fetching", async () => { const fn = mockFetch(new Response("should not be called")); for (const path of [ "../etc", "docs/../../etc", "https://evil.example/x", "//evil.example/x", "pricing?x=1", "api/markdown/pricing#frag", ]) { const result = await getContentPageTool.run({ ctx, input: { path } }); expect(result.markdown).toBe(""); expect(result.error).toBe( "path must be a site-relative page path like docs/concept/monitor", ); expect(getContentPageTool.outputSchema.safeParse(result).success).toBe( true, ); } assertSpyCalls(fn, 0); });});