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%
2.1 KB · 55 lines typescript
Raw Blame History
1// author: simon-pierre boucher <contact@spboucher.ai>2import { describe, expect, it } from "vitest";3import { crawlDelay, isAllowed, parseRobots } from "./robots.js";45describe("parseRobots / isAllowed", () => {6  it("allows everything when robots is empty", () => {7    const r = parseRobots("");8    expect(isAllowed(r, "/anything")).toBe(true);9  });1011  it("honors a wildcard Disallow", () => {12    const r = parseRobots("User-agent: *\nDisallow: /private/");13    expect(isAllowed(r, "/private/x")).toBe(false);14    expect(isAllowed(r, "/public/x")).toBe(true);15  });1617  it("applies longest-match-wins between Allow and Disallow", () => {18    const r = parseRobots("User-agent: *\nDisallow: /a/\nAllow: /a/b");19    expect(isAllowed(r, "/a/b/c")).toBe(true);20    expect(isAllowed(r, "/a/x")).toBe(false);21  });2223  it("supports * and $ wildcards", () => {24    const r = parseRobots("User-agent: *\nDisallow: /*.pdf$");25    expect(isAllowed(r, "/docs/file.pdf")).toBe(false);26    expect(isAllowed(r, "/docs/file.pdf?x=1")).toBe(true);27    expect(isAllowed(r, "/docs/file.html")).toBe(true);28  });2930  it("selects the most specific matching user-agent group", () => {31    const r = parseRobots(32      "User-agent: *\nDisallow: /\n\nUser-agent: Tendril\nAllow: /\nDisallow: /secret",33    );34    expect(isAllowed(r, "/page", "Tendril/1.0")).toBe(true);35    expect(isAllowed(r, "/secret", "Tendril/1.0")).toBe(false);36    expect(isAllowed(r, "/page", "SomeOtherBot")).toBe(false);37  });3839  it("treats an empty Disallow as allow-all", () => {40    const r = parseRobots("User-agent: *\nDisallow:");41    expect(isAllowed(r, "/anything")).toBe(true);42  });4344  it("groups consecutive user-agent lines together", () => {45    const r = parseRobots("User-agent: A\nUser-agent: Tendril\nDisallow: /x");46    expect(isAllowed(r, "/x", "Tendril")).toBe(false);47  });4849  it("collects Sitemap directives and Crawl-delay", () => {50    const r = parseRobots("Sitemap: https://e.com/sitemap.xml\nUser-agent: *\nCrawl-delay: 5\nDisallow: /y");51    expect(r.sitemaps).toEqual(["https://e.com/sitemap.xml"]);52    expect(crawlDelay(r)).toBe(5);53  });54});55