$ node --test --test-reporter=spec "test/*.test.mjs"   (Node v24.11.0, Windows 11, 1 October 2026)

✔ default profile (0.9814ms)
✔ good (0.1247ms)
✔ js-shell (0.0671ms)
✔ canonical-wrong (0.1224ms)
✔ canonical-conflict (0.0774ms)
✔ canonical-in-body (0.0625ms)
✔ noindex-meta (0.0475ms)
✔ noindex-header (0.0412ms)
✔ jsonld-malformed (0.0853ms)
✔ redirect-loop (0.1339ms)
✔ blocked (0.0589ms)
✔ not-in-sitemap (0.043ms)
✔ temporary-redirect (0.0789ms)
✔ server-error (0.1086ms)
✔ timeout (0.0564ms)
✔ oversized (0.0277ms)
✔ redirect-to-private (0.0227ms)
✔ edge-drift profile (0.033ms)
✔ edge-drift (0.035ms)
✔ robots-503 profile (0.0499ms)
✔ robots-503 (0.0243ms)
✔ no-robots profile (0.0244ms)
✔ no-robots (0.0204ms)
✔ robots-html profile (0.0186ms)
✔ robots-html (0.0203ms)
▶ path matching: Google's URL-matching table
  ✔ / (1.6951ms)
  ✔ /* (0.3612ms)
  ✔ /$ (0.2949ms)
  ✔ /fish (0.3334ms)
  ✔ /fish* (0.913ms)
  ✔ /fish/ (0.1158ms)
  ✔ /*.php (0.1256ms)
  ✔ /*.php$ (0.0936ms)
  ✔ /fish*.php (0.1331ms)
✔ path matching: Google's URL-matching table (5.5491ms)
▶ rule precedence: Google's sample situations
  ✔ /page with allow: /p + disallow: / (0.3477ms)
  ✔ /folder/page with allow: /folder + disallow: /folder (0.1026ms)
  ✔ /page.htm with allow: /page + disallow: /*.htm (0.0918ms)
  ✔ /page.php5 with allow: /page + disallow: /*.ph (0.0614ms)
  ✔ / with allow: /$ + disallow: / (0.0517ms)
  ✔ /page.htm with allow: /$ + disallow: / (0.068ms)
✔ rule precedence: Google's sample situations (1.0165ms)
▶ groups: RFC 9309
  ✔ a crawler named in a group obeys only that group, not * (0.2087ms)
  ✔ a crawler with no group of its own falls back to * (0.0871ms)
  ✔ user-agent matching is case-insensitive (0.1945ms)
  ✔ consecutive User-agent lines share a group; comments and blank lines do not end it (0.138ms)
  ✔ groups naming the same crawler are combined (0.0956ms)
  ✔ paths are case-sensitive (0.0591ms)
  ✔ /robots.txt is always allowed (0.0412ms)
  ✔ Sitemap lines are read (0.8989ms)
  ✔ with no group for the crawler and no * group, everything is allowed (0.1566ms)
  ✔ an empty Disallow matches nothing (0.1059ms)
  ✔ a product token with a version still names the crawler (0.1654ms)
✔ groups: RFC 9309 (2.531ms)
▶ encoding
  ✔ non-ASCII paths match their percent-encoded form (0.3779ms)
  ✔ escaped unreserved characters match their plain form (0.1126ms)
✔ encoding (0.5875ms)
▶ comparing the live file with the source file
  ✔ identical files (0.4954ms)
  ✔ comment-only differences keep the same rules (0.1546ms)
  ✔ lines added at the edge are reported (0.2013ms)
✔ comparing the live file with the source file (0.9723ms)
▶ request guard
  ✔ addresses are classified (4.4215ms)
  ✔ localhost is refused unless allowed, and answers when it is (17.2835ms)
  ✔ private addresses are refused even with --allow-localhost (0.5217ms)
  ✔ a name that resolves to loopback is refused like the address (3.6882ms)
  ✔ credentials in the URL and other schemes are refused (0.2125ms)
✔ request guard (27.1343ms)
▶ sitemap reader
  ✔ a sitemap over the byte limit is reported as over the limit, not as a broken file (20.352ms)
✔ sitemap reader (20.5001ms)
▶ HTML reader
  ✔ an element that cannot be in <head> moves what follows it into <body> (4.6942ms)
  ✔ JSON-LD scripts are not counted as scripts that build the page (0.5741ms)
  ✔ text inside script, style and template is not page text (0.7874ms)
✔ HTML reader (6.2599ms)
▶ JSON-LD checks
  ✔ a block without a schema.org @context is a finding (0.6815ms)
  ✔ a page node naming another URL of the same site is a finding (0.2016ms)
  ✔ list items pointing at other pages are not mistaken for the page itself (1.0042ms)
  ✔ a FAQ question missing from the page text is a finding (0.6093ms)
  ✔ a reference to an entity described elsewhere is left for review (0.386ms)
✔ JSON-LD checks (3.075ms)
ℹ tests 70
ℹ suites 9
ℹ pass 70
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 4255.8112
