68 lines
3.0 KiB
TypeScript
68 lines
3.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|||
|
|
import { campuses, getCampus, openCampuses } from "@/config/campuses";
|
||
|
|
import { FAR_AWAY_MILES, formatDistance, haversineMiles, isValidLatLng, nearestCampus, normalizeZip, rankCampuses } from "@/lib/geo";
|
||
|
|
|
||
|
|
describe("haversineMiles", () => {
|
||
|
|
it("returns 0 for identical points", () => {
|
||
|
|
expect(haversineMiles({ lat: 42, lng: -71 }, { lat: 42, lng: -71 })).toBe(0);
|
||
|
|
});
|
||
|
|
it("matches a known distance (Boston → Providence ≈ 41 mi)", () => {
|
||
|
|
const d = haversineMiles({ lat: 42.3601, lng: -71.0589 }, { lat: 41.824, lng: -71.4128 });
|
||
|
|
expect(d).toBeGreaterThan(39);
|
||
|
|
expect(d).toBeLessThan(43);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("nearestCampus", () => {
|
||
|
|
it("recommends North Attleboro from Attleboro Falls", () => {
|
||
|
|
const r = nearestCampus({ lat: 41.97, lng: -71.3 }, campuses)!;
|
||
|
|
expect(r.campus.id).toBe("north-attleboro");
|
||
|
|
expect(r.distanceMiles).toBeLessThan(1);
|
||
|
|
});
|
||
|
|
it("recommends Norwood from Dedham", () => {
|
||
|
|
expect(nearestCampus({ lat: 42.2436, lng: -71.166 }, campuses)!.campus.id).toBe("norwood");
|
||
|
|
});
|
||
|
|
it("recommends Woonsocket from Cumberland RI", () => {
|
||
|
|
expect(nearestCampus({ lat: 41.9668, lng: -71.4328 }, campuses)!.campus.id).toBe("woonsocket");
|
||
|
|
});
|
||
|
|
it("recommends Southcoast from Fall River", () => {
|
||
|
|
expect(nearestCampus({ lat: 41.7015, lng: -71.155 }, campuses)!.campus.id).toBe("southcoast");
|
||
|
|
});
|
||
|
|
it("recommends Apollo Beach from Tampa", () => {
|
||
|
|
expect(nearestCampus({ lat: 27.9506, lng: -82.4572 }, campuses)!.campus.id).toBe("apollo-beach");
|
||
|
|
});
|
||
|
|
it("never recommends a launching campus, even when it is closest", () => {
|
||
|
|
// Winter Park FL is 0 mi from the Orlando launch location
|
||
|
|
const r = nearestCampus({ lat: 28.59213, lng: -81.37501 }, campuses)!;
|
||
|
|
expect(getCampus("orlando")?.status).toBe("launching");
|
||
|
|
expect(r.campus.id).toBe("apollo-beach");
|
||
|
|
expect(r.distanceMiles).toBeGreaterThan(FAR_AWAY_MILES);
|
||
|
|
});
|
||
|
|
it("ranks every open campus and sorts ascending", () => {
|
||
|
|
const ranked = rankCampuses({ lat: 42.0, lng: -71.4 }, campuses);
|
||
|
|
expect(ranked).toHaveLength(openCampuses.length);
|
||
|
|
for (let i = 1; i < ranked.length; i++) expect(ranked[i].distanceMiles).toBeGreaterThanOrEqual(ranked[i - 1].distanceMiles);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("helpers", () => {
|
||
|
|
it("formats distances for humans", () => {
|
||
|
|
expect(formatDistance(0.4)).toBe("under a mile");
|
||
|
|
expect(formatDistance(3.26)).toBe("3.3 mi");
|
||
|
|
expect(formatDistance(47.6)).toBe("48 mi");
|
||
|
|
});
|
||
|
|
it("validates coordinates and rejects null island", () => {
|
||
|
|
expect(isValidLatLng({ lat: 41.9, lng: -71.3 })).toBe(true);
|
||
|
|
expect(isValidLatLng({ lat: 0, lng: 0 })).toBe(false);
|
||
|
|
expect(isValidLatLng({ lat: 91, lng: 0 })).toBe(false);
|
||
|
|
expect(isValidLatLng({ lat: "41", lng: -71 })).toBe(false);
|
||
|
|
expect(isValidLatLng(null)).toBe(false);
|
||
|
|
});
|
||
|
|
it("normalizes ZIP codes", () => {
|
||
|
|
expect(normalizeZip(" 02763 ")).toBe("02763");
|
||
|
|
expect(normalizeZip("02763-1234")).toBe("02763");
|
||
|
|
expect(normalizeZip("2763")).toBeNull();
|
||
|
|
expect(normalizeZip("abcde")).toBeNull();
|
||
|
|
});
|
||
|
|
});
|