import { describe, expect, it } from "vitest"; import { hasFilters, interpretQuery } from "./interpret.js"; describe("interpretQuery", () => { it("returns empty for blank input", () => { expect(interpretQuery(" ")).toEqual({}); expect(hasFilters(interpretQuery(""))).toBe(false); }); it("extracts a country from a name", () => { const i = interpretQuery("data centers in France"); expect(i.countryIso2).toBe("FR"); expect(i.text).toBeUndefined(); }); it("extracts a bare ISO2 code in caps", () => { expect(interpretQuery("hyperscale US").countryIso2).toBe("US"); expect(interpretQuery("UK colocation").countryIso2).toBe("GB"); }); it("extracts MW thresholds", () => { expect(interpretQuery("over 100 MW").minMw).toBe(100); expect(interpretQuery("1.2 GW campus").minMw).toBe(1200); expect(interpretQuery("at least 50mw germany")).toMatchObject({ minMw: 50, countryIso2: "DE" }); }); it("extracts maximum MW thresholds", () => { expect(interpretQuery("<500 MW")).toMatchObject({ maxMw: 500 }); expect(interpretQuery("under 500 MW announced")).toMatchObject({ maxMw: 500, status: "announced" }); expect(interpretQuery("below 1 GW").maxMw).toBe(1000); expect(interpretQuery("less than 50mw in france")).toMatchObject({ maxMw: 50, countryIso2: "FR" }); expect(interpretQuery("less than 50mw").minMw).toBeUndefined(); expect(interpretQuery(">500 MW announced")).toMatchObject({ minMw: 500, status: "announced" }); expect(interpretQuery("500+ MW").minMw).toBe(500); }); it("extracts status and type words", () => { expect(interpretQuery("under construction data centers")).toMatchObject({ status: "under_construction" }); expect(interpretQuery("planned AI data center")).toMatchObject({ status: "announced", facilityType: "ai" }); expect(interpretQuery("operational colocation in Canada")).toMatchObject({ status: "operational", facilityType: "colocation", countryIso2: "CA" }); }); it("flags AI queries", () => { expect(interpretQuery("ai data centers in texas")).toMatchObject({ ai: true, facilityType: "ai" }); expect(interpretQuery("gpu campus")).toMatchObject({ ai: true }); expect(interpretQuery("colocation in Paris").ai).toBeUndefined(); }); it("switches to projects when the query says projects", () => { const i = interpretQuery("projects over 500 MW in texas"); expect(i).toMatchObject({ entity: "project", minMw: 500 }); expect(i.text).toBe("texas"); expect(interpretQuery("announced data centers").entity).toBeUndefined(); expect(interpretQuery("planned campus in Ohio").entity).toBeUndefined(); }); it("extracts opening year phrases", () => { expect(interpretQuery("projects opening 2028")).toMatchObject({ entity: "project", year: 2028, yearOp: "in" }); expect(interpretQuery("before 2028")).toMatchObject({ year: 2028, yearOp: "before" }); expect(interpretQuery("after 2027 hyperscale")).toMatchObject({ year: 2027, yearOp: "after", facilityType: "hyperscale" }); expect(interpretQuery("opens in 2026").year).toBe(2026); expect(interpretQuery("by 2030")).toMatchObject({ year: 2030, yearOp: "before" }); expect(interpretQuery("500 MW").year).toBeUndefined(); }); it("matches metro names and aliases supplied by the caller", () => { const metros = [{ slug: "northern-virginia", name: "Northern Virginia", aliases: ["NoVA", "Ashburn"] }, { slug: "dallas-fort-worth", name: "Dallas-Fort Worth", aliases: ["DFW"] }]; expect(interpretQuery("hyperscale in Northern Virginia", { metros })).toMatchObject({ metro: "northern-virginia", facilityType: "hyperscale" }); expect(interpretQuery("ashburn colocation", { metros })).toMatchObject({ metro: "northern-virginia" }); expect(interpretQuery("DFW over 50 MW", { metros })).toMatchObject({ metro: "dallas-fort-worth", minMw: 50 }); expect(interpretQuery("virginia", { metros }).metro).toBeUndefined(); }); it("recognises an operator supplied by the caller and keeps the rest as text", () => { const i = interpretQuery("Equinix Paris operational", { operators: [{ slug: "equinix", name: "Equinix", similarity: 0.5 }] }); expect(i.operator).toBe("equinix"); expect(i.status).toBe("operational"); expect(i.text).toBe("Paris"); }); it("uses the countries table names when aliases miss", () => { const i = interpretQuery("Luxembourg City edge", { countries: [{ iso2: "LU", name: "Luxembourg" }] }); expect(i.countryIso2).toBe("LU"); expect(i.facilityType).toBe("edge"); expect(i.text).toBe("City"); }); it("drops generic words from the remaining text", () => { expect(interpretQuery("montreal data center").text).toBe("montreal"); expect(interpretQuery("the campus of Ashburn").text).toBe("Ashburn"); }); it("combines everything", () => { const i = interpretQuery("equinix operational 100 MW in france", { operators: [{ slug: "equinix", name: "Equinix", similarity: 0.4 }] }); expect(i).toEqual({ minMw: 100, operator: "equinix", countryIso2: "FR", status: "operational" }); expect(hasFilters(i)).toBe(true); expect(hasFilters({ entity: "project" })).toBe(true); expect(hasFilters({ year: 2028 })).toBe(true); }); });