import { SELF } from "cloudflare:test"; import { describe, it, expect } from "vitest"; import { parse } from "node-html-parser"; describe("Cloudflare Docs", () => { describe("html handling", () => { it("responds with index.html at `/`", async () => { const request = new Request("http://fakehost/"); const response = await SELF.fetch(request); expect(response.status).toBe(200); expect(await response.text()).toContain("Cloudflare Docs"); }); it("responds with 404.html at `/non-existent`", async () => { const request = new Request("http://fakehost/non-existent"); const response = await SELF.fetch(request); expect(response.status).toBe(404); expect(await response.text()).toContain("Check the URL,"); }); }); describe("markdown 404 handling", () => { it("responds with markdown 404 for /index.md requests", async () => { const request = new Request("http://fakehost/non-existent/index.md"); const response = await SELF.fetch(request); expect(response.status).toBe(404); expect(response.headers.get("Content-Type")).toContain("text/markdown"); const body = await response.text(); expect(body).toContain("# 404 Page not found"); expect(body).toContain("/llms.txt"); expect(body).toContain("ai-search.developers.cloudflare.com"); }); it("responds with markdown 404 for Accept: text/markdown requests", async () => { const request = new Request("http://fakehost/non-existent", { headers: { Accept: "text/markdown" }, }); const response = await SELF.fetch(request); expect(response.status).toBe(404); expect(response.headers.get("Content-Type")).toContain("text/markdown"); const body = await response.text(); expect(body).toContain("# 404 Page not found"); expect(body).toContain("/llms.txt"); }); it("responds with markdown 404 for parameterized Accept media types", async () => { const request = new Request("http://fakehost/non-existent", { headers: { Accept: "text/markdown; charset=utf-8, text/html;q=1.0" }, }); const response = await SELF.fetch(request); expect(response.status).toBe(404); expect(response.headers.get("Content-Type")).toContain("text/markdown"); const body = await response.text(); expect(body).toContain("# 404 Page not found"); expect(body).toContain("/llms.txt"); }); it("returns html 404 for unrelated Accept media types", async () => { const request = new Request("http://fakehost/non-existent", { headers: { Accept: "text/markdown-extra, application/not-text-markdown", }, }); const response = await SELF.fetch(request); expect(response.status).toBe(404); expect(response.headers.get("Content-Type")).toContain("text/html"); expect(await response.text()).toContain("Check the URL,"); }); }); describe(".well-known", () => { it("api-catalog does not advertise a markdown service-doc yet", async () => { const request = new Request("http://fakehost/.well-known/api-catalog"); const response = await SELF.fetch(request); expect(response.status).toBe(200); expect(response.headers.get("Content-Type")).toContain( "application/linkset+json", ); const catalog: any = await response.json(); const entry = (catalog.linkset as any[]).find( (e) => e.anchor === "https://developers.cloudflare.com/api/", ); expect(entry).toBeDefined(); const serviceDoc = entry["service-doc"] as any[]; expect(serviceDoc.some((d) => d.type === "text/markdown")).toBe(false); expect( serviceDoc.some((d) => String(d.href).endsWith("/api/index.md")), ).toBe(false); expect( serviceDoc.some( (d) => d.type === "text/html" && d.href === "https://developers.cloudflare.com/api/", ), ).toBe(true); }); }); describe("redirects", () => { it("redirects requests with a trailing slash", async () => { const request = new Request("http://fakehost/docs/"); const response = await SELF.fetch(request, { redirect: "manual" }); expect(response.status).toBe(301); expect(response.headers.get("Location")).toBe("/directory/"); }); it("redirects requests without a trailing slash", async () => { const request = new Request("http://fakehost/docs"); const response = await SELF.fetch(request, { redirect: "manual" }); expect(response.status).toBe(301); expect(response.headers.get("Location")).toBe("/directory/"); }); }); describe("json endpoints", () => { it("compatibility flags", async () => { const request = new Request( "http://fakehost/workers/platform/compatibility-flags.json", ); const response = await SELF.fetch(request); expect(response.status).toBe(200); const json: any[] = await response.json(); const urlFlag = json.find((flag) => flag.enable_flag === "url_standard"); const nodeJsFlag = json.find( (flag) => flag.enable_flag === "nodejs_compat", ); expect(urlFlag).toBeDefined(); expect(urlFlag.experimental).toBe(false); expect(nodeJsFlag).toBeDefined(); expect(nodeJsFlag.enable_date).toBe("2026-08-04"); }); it("pages framework configurations", async () => { const request = new Request( "http://fakehost/pages/platform/build-configuration.json", ); const response = await SELF.fetch(request); expect(response.status).toBe(200); const json: any = await response.json(); const analog = json["analog"]; expect(analog).toBeDefined(); expect(analog.icon).toBe("/icons/framework-icons/logo-analog.svg"); }); it("pages build image language and tools", async () => { const request = new Request( "http://fakehost/pages/platform/language-support-and-tools.json", ); const response = await SELF.fetch(request); expect(response.status).toBe(200); const json: any[] = await response.json(); const v1 = json.find((x) => x.major_version === 1); const v2 = json.find((x) => x.major_version === 2); expect(v1).toBeDefined(); expect(v2).toBeDefined(); const v1NodeJs = v1.languages.find((x: any) => x.name === "Node.js"); const v2NodeJs = v2.languages.find((x: any) => x.name === "Node.js"); expect(v1NodeJs).toBeDefined(); expect(v1NodeJs.default).toBe("12.18.0"); expect(v1NodeJs.file).toContain(".nvmrc"); expect(v2NodeJs).toBeDefined(); expect(v2NodeJs.default).toBe("18.17.1"); expect(v2NodeJs.file).toContain(".nvmrc"); }); }); describe("rss endpoints", () => { describe("changelog", () => { it("global", async () => { const request = new Request("http://fakehost/changelog/rss/index.xml"); const response = await SELF.fetch(request); expect(response.status).toBe(200); const xml = await response.text(); expect(xml).toContain("