import { describe, expect, it } from "vitest"; import { classifyPage, eventTypeFor, isDataCenterRelevant } from "./classify.js"; import { projectMwFigures } from "./mw-figures.js"; describe("classifyPage — URL rules win", () => { it("a facility page mentioning an acquisition stays facility_page", () => { const c = classifyPage("https://op.com/data-centers/ashburn-va1/", "VA1 Ashburn", "VA1 was acquired in 2019 as part of the acquisition of Acme. 36 MW critical load, N+1, 2N power."); expect(c.pageType).toBe("facility_page"); expect(c.eventType).toBe("facility_updated"); expect(c.mw).toEqual([36]); }); it("facility index, newsroom index, press release, cloud region, financial, planning by URL", () => { expect(classifyPage("https://op.com/data-centers/", null, "").pageType).toBe("facility_index"); expect(classifyPage("https://op.com/newsroom/", null, "").pageType).toBe("news_index"); expect(classifyPage("https://op.com/news/2026/big-campus", null, "").pageType).toBe("press_release"); expect(classifyPage("https://cloud.com/global-infrastructure/regions/", null, "").pageType).toBe("cloud_region"); expect(classifyPage("https://op.com/investors/annual-report", null, "").pageType).toBe("financial_disclosure"); expect(classifyPage("https://county.gov/planning/applications/2026-001", null, "").pageType).toBe("planning_document"); expect(classifyPage("https://op.de/rechenzentren/frankfurt-1/", null, "").pageType).toBe("facility_page"); }); it("PDFs are planning documents only with planning vocabulary in URL or title, otherwise unknown", () => { expect(classifyPage("https://county.gov/files/rezoning-application-2026.pdf", null, "").pageType).toBe("planning_document"); expect(classifyPage("https://county.gov/files/ZMAP-2026-0001.pdf", "Planning Commission agenda", "")).toMatchObject({ pageType: "planning_document", rule: "url:pdf+planning" }); expect(classifyPage("https://op.com/files/brochure.pdf", "Campus brochure", "We announce a new 100 MW data center")).toMatchObject({ pageType: "unknown", rule: "url:pdf" }); expect(classifyPage("https://op.com/news/release.pdf", null, "").pageType).toBe("unknown"); // the news parser decides }); }); describe("classifyPage — text rules", () => { it("first matching text rule wins", () => { expect(classifyPage("https://x.com/p/1", "Acme completes acquisition of Beta", "").pageType).toBe("acquisition"); expect(classifyPage("https://x.com/p/2", "Acme expands Dallas campus", "adds 40 MW").pageType).toBe("expansion"); expect(classifyPage("https://x.com/p/3", "Acme breaks ground in Ohio", "").pageType).toBe("construction_update"); expect(classifyPage("https://x.com/p/4", "Acme signs power purchase agreement", "").pageType).toBe("power_infrastructure"); expect(classifyPage("https://x.com/p/5", "Acme launches new region in Madrid", "availability zones").pageType).toBe("cloud_region"); expect(classifyPage("https://x.com/p/6", "Acme announces $2 billion campus", "").pageType).toBe("project_announcement"); expect(classifyPage("https://x.com/p/7", "Quarterly newsletter", "nothing here").pageType).toBe("unknown"); }); it("understands German, French, Spanish, Portuguese and Dutch announcements", () => { expect(classifyPage("https://x.de/p/1", "Acme baut neues Rechenzentrum in Frankfurt", "").pageType).toBe("project_announcement"); expect(classifyPage("https://x.fr/p/1", "Acme annonce un nouveau centre de données à Marseille", "communiqué de presse").pageType).toBe("project_announcement"); expect(classifyPage("https://x.es/p/1", "Acme construirá un nuevo centro de datos en Madrid", "").pageType).toBe("project_announcement"); expect(classifyPage("https://x.pt/p/1", "Acme anuncia novo centro de dados em Sines", "").pageType).toBe("project_announcement"); expect(classifyPage("https://x.nl/p/1", "Acme bouwt nieuw datacentrum in Groningen", "").pageType).toBe("project_announcement"); }); it("filters portfolio totals out of the MW list", () => { const c = classifyPage("https://x.com/p/8", "Acme announces 60 MW data center in Lisbon", "The new facility brings the company's total capacity to 1.4 GW across Europe. The 60MW site opens in 2028."); expect(c.mw).toEqual([60]); }); }); describe("eventTypeFor", () => { it("maps page types to event types with text refinements", () => { expect(eventTypeFor("construction_update", "Acme breaks ground")).toBe("construction_started"); expect(eventTypeFor("construction_update", "construction progress update")).toBe("project_status_changed"); expect(eventTypeFor("planning_document", "the board approved the application")).toBe("planning_approved"); expect(eventTypeFor("planning_document", "application filed")).toBe("planning_filed"); expect(eventTypeFor("cloud_region", "Acme announces upcoming region")).toBe("cloud_region_announced"); expect(eventTypeFor("cloud_region", "region is now available")).toBe("cloud_region_launched"); expect(eventTypeFor("project_announcement", "to invest $5 billion in the state")).toBe("investment_announced"); expect(eventTypeFor("project_announcement", "to invest $5 billion in a 300 MW campus")).toBe("project_announced"); expect(eventTypeFor("project_announcement", "Acme investiert 1 Mrd. in ein neues Rechenzentrum")).toBe("project_announced"); expect(eventTypeFor("press_release", "")).toBe("news"); expect(eventTypeFor("unknown", "")).toBeUndefined(); }); }); describe("isDataCenterRelevant", () => { it("accepts data-center vocabulary in every indexed language", () => { for (const t of ["new data center in Ohio", "colocation provider", "50 MW campus", "Rechenzentrum in Frankfurt", "centre de données à Paris", "centro de datos en Madrid", "centro de dados em Lisboa", "datacentrum in Amsterdam", "nytt datasenter i Oslo", "nytt datacenter i Stockholm", "serverhall i Luleå"]) expect(isDataCenterRelevant(t), t).toBe(true); }); it("rejects unrelated text", () => { expect(isDataCenterRelevant("Quarterly dividend declared by the board")).toBe(false); expect(isDataCenterRelevant("Acme names Jane Doe as CFO")).toBe(false); }); }); describe("projectMwFigures", () => { it("keeps site figures, drops portfolio/company-wide figures, dedupes, sorts descending, bounds 0–20 000", () => { expect(projectMwFigures("a 100 MW campus with a first 20MW phase and 20 MW later; portfolio of 2 GW across Asia; 30,000 MW pipeline")).toEqual([100, 20]); expect(projectMwFigures("brings the total capacity to 500 MW")).toEqual([]); expect(projectMwFigures("now operates 800 MW globally")).toEqual([]); expect(projectMwFigures("1.5 GW of contracted capacity")).toEqual([]); expect(projectMwFigures("no figures here")).toEqual([]); }); });