← back to Homesonspec

packages/shared/src/canonical.test.ts

48 lines

import { describe, expect, it } from "vitest";
import { canonicalKey, normalizeAddress } from "./canonical";

describe("normalizeAddress", () => {
  it("lowercases, strips punctuation, abbreviates street words", () => {
    expect(normalizeAddress("123 Oak Street")).toBe("123 oak st");
    expect(normalizeAddress("123 OAK ST.")).toBe("123 oak st");
    expect(normalizeAddress("456 N. Mesquite Boulevard, #2")).toBe("456 n mesquite blvd 2");
  });
  it("returns empty string for null/undefined", () => {
    expect(normalizeAddress(null)).toBe("");
    expect(normalizeAddress(undefined)).toBe("");
  });
});

describe("canonicalKey", () => {
  const base = {
    builderSlug: "meridian-homes",
    communityName: "Cedar Bend",
    address: "123 Oak Street",
    lotNumber: "42",
    builderInventoryId: "MH-1001",
    lat: 30.312345,
    lon: -97.712345,
    planName: "The Juniper",
  };

  it("is deterministic", () => {
    expect(canonicalKey(base)).toBe(canonicalKey({ ...base }));
  });

  it("collapses cosmetic address differences", () => {
    expect(canonicalKey(base)).toBe(canonicalKey({ ...base, address: "123 oak st." }));
  });

  it("collapses sub-meter GPS jitter (5-decimal rounding)", () => {
    expect(canonicalKey(base)).toBe(canonicalKey({ ...base, lat: 30.312346999 }));
  });

  it("forks identity on a different lot", () => {
    expect(canonicalKey(base)).not.toBe(canonicalKey({ ...base, lotNumber: "43" }));
  });

  it("forks identity on a different builder", () => {
    expect(canonicalKey(base)).not.toBe(canonicalKey({ ...base, builderSlug: "other-builder" }));
  });
});