import { describe, expect, it } from "vitest"; import { decidePageview, type IncomingPageviewRequest, } from "./pageview-decision"; const humanRequest = ( overrides: Partial = {}, ): IncomingPageviewRequest => ({ method: "GET", secFetchDest: "document", pathname: "/", search: "", hostname: "mintel.me", referrer: "", language: "de-DE", userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/131.0.0.0", clientIp: "84.117.2.55", ...overrides, }); describe("decidePageview", () => { it("tracks a browser navigation for the homepage", () => { const decision = decidePageview(humanRequest()); expect(decision).toEqual({ track: true, facts: { url: "/", hostname: "mintel.me", referrer: "", language: "de-DE", userAgent: humanRequest().userAgent, clientIp: "84.117.2.55", }, }); }); it("keeps the query string in the tracked url", () => { const decision = decidePageview( humanRequest({ pathname: "/imprint", search: "?from=footer" }), ); expect(decision).toMatchObject({ track: true, facts: { url: "/imprint?from=footer" }, }); }); it("tracks a blog-style slug that merely contains a file-like segment", () => { const decision = decidePageview( humanRequest({ pathname: "/blog/next.js-vs-remix" }), ); expect(decision).toMatchObject({ track: true }); }); it("tracks a slug that merely starts like a metadata image route", () => { const decision = decidePageview( humanRequest({ pathname: "/notes/opengraph-image-deep-dive" }), ); expect(decision).toMatchObject({ track: true }); }); it("accepts the method in lower case", () => { const decision = decidePageview(humanRequest({ method: "get" })); expect(decision).toMatchObject({ track: true }); }); it.each([ ["a form submission", { method: "POST" }], ["a head request", { method: "HEAD" }], ["an options probe", { method: "OPTIONS" }], ])("skips %s", (_label, overrides) => { const decision = decidePageview(humanRequest(overrides)); expect(decision).toEqual({ track: false, reason: "non-get-method" }); }); it.each([ ["a router prefetch payload", "empty"], ["a script subresource", "script"], ["an image subresource", "image"], ["a request without fetch metadata", ""], ])("skips %s", (_label, secFetchDest) => { const decision = decidePageview(humanRequest({ secFetchDest })); expect(decision).toEqual({ track: false, reason: "non-navigation-request", }); }); it.each([ ["a next build chunk", "/_next/static/chunks/main-abc123.js"], ["a next image request", "/_next/image"], ["a public image", "/images/portrait.webp"], ["a jpeg photo", "/images/photo.jpg"], ["a woff font", "/fonts/inter.woff"], ["a font", "/fonts/inter.woff2"], ["a feed document", "/rss.xml"], ["the sitemap", "/sitemap.xml"], ["the robots file", "/robots.txt"], ["the web manifest", "/manifest.webmanifest"], ["an open graph image route", "/opengraph-image"], ["a twitter image route", "/twitter-image"], ["a favicon", "/favicon.ico"], ])("skips %s at %s", (_label, pathname) => { const decision = decidePageview(humanRequest({ pathname })); expect(decision).toEqual({ track: false, reason: "static-asset" }); }); it.each([ ["the analytics proxy", "/stats/api/send"], ["the error relay", "/errors/api/relay"], ["an api route", "/api/contact"], ["the api health check", "/api/health"], ["the health check", "/health"], ["the gatekeeper", "/gatekeeper/api/verify"], ["a well-known challenge", "/.well-known/acme-challenge/token"], ])("skips %s at %s", (_label, pathname) => { const decision = decidePageview(humanRequest({ pathname })); expect(decision).toEqual({ track: false, reason: "infrastructure-path" }); }); it.each([ ["curl", "curl/8.1.2"], ["wget", "Wget/1.21"], ["python requests", "python-requests/2.31"], ["go http", "Go-http-client/2.0"], ["uptime kuma", "Uptime-Kuma/1.23.11"], ["a crawler", "Googlebot/2.1 (+http://www.google.com/bot.html)"], ["a link preview", "WhatsApp/2.23.20.0"], ])("skips the %s user agent", (_label, userAgent) => { const decision = decidePageview(humanRequest({ userAgent })); expect(decision).toEqual({ track: false, reason: "bot-user-agent" }); }); it("skips a bot even when its request looks like a navigation", () => { const decision = decidePageview( humanRequest({ userAgent: "curl/8.1.2", secFetchDest: "document" }), ); expect(decision).toEqual({ track: false, reason: "bot-user-agent" }); }); });