SPB Git

spb/tendril Public

Tendril — web ingestion platform (scrape/crawl/map/search) on macOS Apple Silicon: WebKit fidelity, authenticated pages, deterministic testable extraction. A self-hosted Firecrawl alternative.

JavaScript 82.6% TypeScript 11.8% HTML 5.3%
1.7 KB · 45 lines typescript
Raw Blame History
1// author: simon-pierre boucher <contact@spboucher.ai>2import { describe, expect, it } from "vitest";3import { ERROR_TAXONOMY, httpStatusFor, isRetryable, tendrilError } from "./errors.js";45describe("error taxonomy", () => {6  it("maps every code to a valid HTTP status", () => {7    for (const [code, spec] of Object.entries(ERROR_TAXONOMY)) {8      expect(spec.http, code).toBeGreaterThanOrEqual(400);9      expect(spec.http, code).toBeLessThan(600);10      expect(spec.message.length, code).toBeGreaterThan(0);11    }12  });1314  it("marks non-retryable terminal codes correctly", () => {15    expect(isRetryable("ERR_ROBOTS_DENIED")).toBe(false);16    expect(isRetryable("ERR_SSRF_BLOCKED")).toBe(false);17    expect(isRetryable("ERR_UNSUPPORTED_TYPE")).toBe(false);18    expect(isRetryable("ERR_TARGET_4XX")).toBe(false);19  });2021  it("marks transient codes as retryable", () => {22    expect(isRetryable("ERR_TIER_TIMEOUT")).toBe(true);23    expect(isRetryable("ERR_POOL_EXHAUSTED")).toBe(true);24    expect(isRetryable("ERR_DAEMON_DOWN")).toBe(true);25  });2627  it("builds errors with default and custom messages", () => {28    expect(tendrilError("ERR_INVALID_URL").message).toBe(ERROR_TAXONOMY.ERR_INVALID_URL.message);29    const e = tendrilError("ERR_TOO_LARGE", { message: "custom", details: { size: 42 } });30    expect(e.message).toBe("custom");31    expect(e.details).toEqual({ size: 42 });32  });3334  it("omits optional fields when not provided (exactOptionalPropertyTypes)", () => {35    const e = tendrilError("ERR_INTERNAL");36    expect("details" in e).toBe(false);37    expect("cause" in e).toBe(false);38  });3940  it("exposes HTTP status via helper", () => {41    expect(httpStatusFor("ERR_UNAUTHORIZED")).toBe(401);42    expect(httpStatusFor("ERR_RATE_LIMITED")).toBe(429);43  });44});45