SPB Git forge
38commits 1branches 0releases
338.7 MBsize
maindefault branch
3 h agolast push
HTML 53.9% TypeScript 44.5% JavaScript 0.6% SQL 0.5%
7.1 KB · 93 lines typescript
Raw Blame History
1import { describe, expect, it } from "vitest";2import type { NormalizedFacility, NormalizedProject } from "@dci/core";3import { fallbackProjectGate, NON_PROJECT_HEADLINE_RE, TITLE_LIKE_NAME_RE, trimSummary, validateEntities, THIRD_PARTY_SUMMARY_MAX } from "./generic.js";45const prov = { sourceId: "s", connectorId: "c", url: "https://x.com/f", firstObserved: "2026-09-01", lastObserved: "2026-09-01", retrievedAt: "2026-09-01", confidence: "high" as const, extractorVersion: "v1" };6function facility(p: Partial<NormalizedFacility>): NormalizedFacility {7  return { entityType: "facility", key: "c:f", name: "DC One", aliases: [], operatorName: "Op", campusName: null, address: null, city: "Ashburn", regionName: null, countryIso2: "US", postalCode: null, geo: null, status: "operational", facilityType: "colocation", tier: null, buildingSqm: null, siteAreaHa: null, itCapacityMw: null, totalPowerMw: null, plannedPowerMw: null, rackCount: null, pue: null, coolingType: null, renewableClaim: null, openedOn: null, constructionStartedOn: null, announcedOn: null, website: null, isAi: null, isHyperscale: null, certifications: [], carriers: [], cloudProviders: [], ixps: [], externalIds: {}, description: null, provenance: prov, ...p };8}9const errors = (r: ReturnType<typeof validateEntities>) => r.issues.filter((i) => i.level === "error").map((i) => i.field);1011describe("validateEntities — facilities", () => {12  it("accepts a plain facility and a sub-MW decimal capacity", () => {13    const r = validateEntities([facility({ itCapacityMw: 0.779 })]);14    expect(r).toMatchObject({ total: 1, valid: 1, rejected: 0 });15  });16  it("rejects title-like and non-facility names", () => {17    expect(errors(validateEntities([facility({ name: "Data Centers in Virginia | Acme" })]))).toContain("name");18    expect(errors(validateEntities([facility({ name: "Our Locations" })]))).toContain("name");19    expect(errors(validateEntities([facility({ name: "How we build data centers" })]))).toContain("name");20    expect(errors(validateEntities([facility({ name: "Joe's Computer Repair Shop" })]))).toContain("name");21    expect(TITLE_LIKE_NAME_RE.test("Ashburn VA1")).toBe(false);22    expect(TITLE_LIKE_NAME_RE.test("Frankfurt FRA5 Data Center")).toBe(false);23  });24  it("rejects > 1 000 MW on a single building unless it is a campus", () => {25    expect(errors(validateEntities([facility({ itCapacityMw: 1200 })]))).toContain("itCapacityMw");26    expect(validateEntities([facility({ name: "Prince William Digital Gateway Campus", totalPowerMw: 1200 })]).rejected).toBe(0);27    expect(validateEntities([facility({ campusName: "Mesa Campus", itCapacityMw: 1500 })]).rejected).toBe(0);28    expect(errors(validateEntities([facility({ itCapacityMw: 20_000 })]))).toContain("itCapacityMw"); // > 10 000 always implausible29  });30  it("rejects impossible figures and coordinates", () => {31    expect(errors(validateEntities([facility({ pue: 0.8 })]))).toContain("pue");32    expect(errors(validateEntities([facility({ geo: { lat: 39, lng: -77, precision: "exact", source: "x" } })]))).toContain("geo");33    expect(errors(validateEntities([facility({ geo: { lat: 99, lng: 0, precision: "city", source: "x" } })]))).toContain("geo");34    expect(errors(validateEntities([facility({ buildingSqm: 600_000 })]))).toContain("buildingSqm");35    expect(errors(validateEntities([facility({ openedOn: "1930" })]))).toContain("openedOn");36    expect(errors(validateEntities([facility({ countryIso2: "USA" })]))).toContain("countryIso2");37  });38  it("warns without rejecting", () => {39    const r = validateEntities([facility({ countryIso2: null, itCapacityMw: 10, totalPowerMw: 8 })]);40    expect(r.rejected).toBe(0);41    expect(r.issues.map((i) => i.field)).toEqual(expect.arrayContaining(["countryIso2", "itCapacityMw"]));42  });43});4445describe("validateEntities — projects, regions, news", () => {46  const project: NormalizedProject = { entityType: "project", key: "c:p", name: "Acme Ohio campus", operatorName: "Acme", countryIso2: "US", status: "announced", announcedOn: "2026-09", plannedMw: 300, investmentUsd: 2e9, description: null, sourceUrl: "https://x.com/n", timeline: [], provenance: prov };47  it("bounds MW and investment", () => {48    expect(validateEntities([project]).rejected).toBe(0);49    expect(errors(validateEntities([{ ...project, plannedMw: 25_000 }]))).toContain("plannedMw");50    expect(errors(validateEntities([{ ...project, investmentUsd: 250e9 }]))).toContain("investmentUsd");51    expect(errors(validateEntities([{ ...project, expectedOpening: "2060" }]))).toContain("expectedOpening");52  });53  it("news events need a real url and title; cloud regions need code+name", () => {54    expect(validateEntities([{ entityType: "news_event", key: "n", title: "", url: "ftp://x", publishedAt: null, summary: null, pageType: "press_release", mentions: { mw: [], operators: [], countriesIso2: [], cities: [] }, provenance: prov }]).rejected).toBe(1);55    expect(validateEntities([{ entityType: "cloud_region", key: "r", providerName: "P", code: "", name: "N", city: null, regionName: null, countryIso2: null, geo: null, availabilityZones: null, launchedOn: null, status: "operational", isSovereign: false, sourceUrl: "https://x", provenance: prov }]).rejected).toBe(1);56  });57});5859describe("fallbackProjectGate", () => {60  it("accepts a build headline with MW + pipeline status", () => {61    expect(fallbackProjectGate("Acme to build 120 MW data center campus in Ohio", null)).toEqual({ mw: 120, status: "announced" });62    expect(fallbackProjectGate("Acme breaks ground on new hyperscale campus", "The 90MW first phase is due in 2027.")).toEqual({ mw: 90, status: "under_construction" });63  });64  it("rejects people / deal / opening / money headlines even with MW in them", () => {65    expect(fallbackProjectGate("Acme appoints Jane Doe as CEO of its 1,400 MW platform", null)).toBeNull();66    expect(fallbackProjectGate("Acme opens 20 MW data center in Paris", null)).toBeNull();67    expect(fallbackProjectGate("Acme signs 50 MW PPA with wind farm", null)).toBeNull();68    expect(fallbackProjectGate("Acme raises $500m to build 100 MW campus", null)).toBeNull();69    expect(NON_PROJECT_HEADLINE_RE.test("Why data centers matter")).toBe(true);70  });71  it("needs a MW figure somewhere up front and a plausible value", () => {72    expect(fallbackProjectGate("Acme plans new campus in Texas", "Details to follow.")).toBeNull();73    expect(fallbackProjectGate("Acme plans 50,000 MW campus", null)).toBeNull();74  });75});7677describe("trimSummary", () => {78  it("cuts at a word boundary with an ellipsis, never above the cap", () => {79    const long = Array.from({ length: 120 }, (_, i) => `word${i}`).join(" ");80    const t = trimSummary(long)!;81    expect(t.length).toBeLessThanOrEqual(THIRD_PARTY_SUMMARY_MAX);82    expect(t.endsWith("…")).toBe(true);83    // the kept text is a prefix of the original and the cut falls on a word boundary (next original char is a space)84    const kept = t.slice(0, -1);85    expect(long.startsWith(kept)).toBe(true);86    expect(long[kept.length]).toBe(" ");87    expect(trimSummary("short")).toBe("short");88    expect(trimSummary(null)).toBeNull();89    expect(trimSummary("abcdef", 4)!.length).toBeLessThanOrEqual(4);90    expect(trimSummary("abcdef", 4)!.endsWith("…")).toBe(true);91  });92});93