136 lines · 4.7 KB · TypeScript
RawDownload
// Parse / extract / preview coverage against a big real-world spec.// DB-touching behaviour (addSpec, removeSpec, tool registration) moved// to apps/cloud/src/services/sources-api.node.test.ts — those run// through the real postgres + drizzle adapter so adapter regressions// (e.g. a per-row createMany fallback) surface automatically instead// of needing a dedicated budget assertion. import { describe, expect, it } from "@effect/vitest";import { Effect, Option } from "effect";import { FetchHttpClient } from "effect/unstable/http";import { readFileSync } from "node:fs";import { resolve } from "node:path"; import type { ParsedDocument } from "./parse";import { parse } from "./parse";import { extract } from "./extract";import { previewSpec as previewSpecRaw } from "./preview";import type { ExtractionResult } from "./types"; const previewSpec = (input: string) =>  previewSpecRaw(input).pipe(Effect.provide(FetchHttpClient.layer)); // ---------------------------------------------------------------------------// Load + parse once, share across tests// --------------------------------------------------------------------------- const specPath = resolve(__dirname, "../../fixtures/cloudflare.json");const specText = readFileSync(specPath, "utf-8"); let cachedDoc: ParsedDocument | null = null;let cachedResult: ExtractionResult | null = null; const getDoc = () =>  Effect.gen(function* () {    if (!cachedDoc) cachedDoc = yield* parse(specText);    return cachedDoc;  }); const getResult = () =>  Effect.gen(function* () {    if (!cachedResult) {      const doc = yield* getDoc();      cachedResult = yield* extract(doc);    }    return cachedResult;  }); describe("Real specs: Cloudflare API", { timeout: 60_000 }, () => {  it.effect("parses the full Cloudflare spec", () =>    Effect.gen(function* () {      const doc = yield* getDoc();      expect(doc).toBeDefined();    }),  );   it.effect("extracts operations from the Cloudflare spec", () =>    Effect.gen(function* () {      const result = yield* getResult();       expect(Option.getOrElse(result.title, () => "")).toBe("Cloudflare API");      expect(Option.getOrElse(result.version, () => "")).toBe("4.0.0");      expect(result.operations.length).toBeGreaterThan(1000);       for (const op of result.operations) {        expect(op.operationId).toBeTruthy();      }       const validMethods = new Set([        "get",        "post",        "put",        "delete",        "patch",        "head",        "options",        "trace",      ]);      for (const op of result.operations) {        expect(validMethods.has(op.method)).toBe(true);      }       const zoneOps = result.operations.filter((op) => op.pathTemplate.includes("/zones"));      expect(zoneOps.length).toBeGreaterThan(0);       const dnsOps = result.operations.filter((op) => op.pathTemplate.includes("/dns_records"));      expect(dnsOps.length).toBeGreaterThan(0);    }),  );   it.effect("operations have input schemas", () =>    Effect.gen(function* () {      const result = yield* getResult();       const opsWithInput = result.operations.filter((op) => Option.isSome(op.inputSchema));      expect(opsWithInput.length).toBeGreaterThan(500);    }),  );   it.effect("operations have output schemas", () =>    Effect.gen(function* () {      const result = yield* getResult();       const getOps = result.operations.filter((op) => op.method === "get");      const getOpsWithOutput = getOps.filter((op) => Option.isSome(op.outputSchema));      expect(getOpsWithOutput.length).toBeGreaterThan(getOps.length / 2);    }),  );   it.effect("previewSpec returns security schemes and header presets", () =>    Effect.gen(function* () {      const preview = yield* previewSpec(specText);       expect(preview.operationCount).toBeGreaterThan(1000);      expect(Option.isSome(preview.title)).toBe(true);      expect(preview.servers.length).toBeGreaterThan(0);       expect(preview.securitySchemes.length).toBe(4);      const schemeNames = preview.securitySchemes.map((s) => s.name);      expect(schemeNames).toContain("api_token");      expect(schemeNames).toContain("api_key");      expect(schemeNames).toContain("api_email");       expect(preview.headerPresets.length).toBeGreaterThan(0);       const bearerPreset = preview.headerPresets.find((p) => p.label.includes("Bearer"));      expect(bearerPreset).toBeDefined();      expect(bearerPreset!.headers["Authorization"]).toBeNull();      expect(bearerPreset!.secretHeaders).toContain("Authorization");       const keyEmailPreset = preview.headerPresets.find((p) => p.label.includes("api_email"));      expect(keyEmailPreset).toBeDefined();      expect(keyEmailPreset!.headers["X-Auth-Email"]).toBeNull();      expect(keyEmailPreset!.headers["X-Auth-Key"]).toBeNull();    }),  );});