diff --git a/tests/geo.test.ts b/tests/geo.test.ts index f4e4694..d4a399c 100644 --- a/tests/geo.test.ts +++ b/tests/geo.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { countryFromLocation } from "@/lib/geo"; +import { countryForLogin, countryFromLocation } from "@/lib/geo"; // The UK home nations are separate football sides, so a Scottish/Welsh/etc. // profile should fly its own flag instead of being collapsed onto the Union Flag. @@ -57,3 +57,81 @@ describe("countryFromLocation — Georgia (country vs US state)", () => { expect(countryFromLocation("Ohio, USA")).toBe("us"); }); }); + +// The deliberate design decisions the module's own header calls out — a wrong +// guess is worse than no flag, so these are contracts, not incidental behaviour. +describe("countryFromLocation — what it deliberately refuses", () => { + it("skips ambiguous 2-letter abbreviations rather than guessing", () => { + // "DE" is Germany or Delaware, "CA" California or Canada — the module leaves + // both unresolved on purpose (see its header comment). + expect(countryFromLocation("DE")).toBeNull(); + expect(countryFromLocation("CA")).toBeNull(); + }); + + it("still honours the intentional 'uk' alias (not every 2-letter is dropped)", () => { + expect(countryFromLocation("uk")).toBe("gb"); + }); + + it("returns null for empty, blank, or symbol-only input", () => { + expect(countryFromLocation(null)).toBeNull(); + expect(countryFromLocation(undefined)).toBeNull(); + expect(countryFromLocation("")).toBeNull(); + expect(countryFromLocation(" ")).toBeNull(); + expect(countryFromLocation("123 !!!")).toBeNull(); // stripped to nothing + expect(countryFromLocation("nowhere-ville")).toBeNull(); + }); +}); + +describe("countryFromLocation — aliases, accents, and phrases", () => { + it("resolves native-language and colloquial country names", () => { + expect(countryFromLocation("Deutschland")).toBe("de"); + expect(countryFromLocation("España")).toBe("es"); + expect(countryFromLocation("Türkiye")).toBe("tr"); + expect(countryFromLocation("Holland")).toBe("nl"); + }); + + it("resolves accented city names", () => { + expect(countryFromLocation("München")).toBe("de"); + expect(countryFromLocation("Kraków")).toBe("pl"); + }); + + it("resolves non-US cities to their own country", () => { + expect(countryFromLocation("Tokyo")).toBe("jp"); + expect(countryFromLocation("Amsterdam")).toBe("nl"); + expect(countryFromLocation("Toronto")).toBe("ca"); + }); + + it("matches a multi-word term embedded anywhere in the string", () => { + // No comma to split on — the phrase is found inside the free text. + expect(countryFromLocation("currently based in United Kingdom")).toBe("gb"); + expect(countryFromLocation("remote — the netherlands")).toBe("nl"); + }); + + it("takes the first resolving segment, left to right", () => { + // A US state in the first segment wins before "France" is ever considered. + expect(countryFromLocation("California, France")).toBe("us"); + }); +}); + +// countryForLogin is what engine.ts actually calls to set a card's country, and +// it had no tests. It layers a pinned-origin override over countryFromLocation. +describe("countryForLogin", () => { + it("uses the pinned origin for showcased accounts, ignoring their location", () => { + expect(countryForLogin("torvalds", null)).toBe("us"); + expect(countryForLogin("t3dotgg", "somewhere")).toBe("us"); + expect(countryForLogin("pewdiepie-archdaemon", null)).toBe("se"); + }); + + it("matches the pinned login case-insensitively, and the pin wins over location", () => { + expect(countryForLogin("Torvalds", "France")).toBe("us"); // not "fr" + }); + + it("falls back to the location for everyone else", () => { + expect(countryForLogin("some-user", "Berlin, Germany")).toBe("de"); + }); + + it("returns null when a non-pinned account has no resolvable location", () => { + expect(countryForLogin("some-user", null)).toBeNull(); + expect(countryForLogin("some-user", "nowhere-ville")).toBeNull(); + }); +});