SPB Git forge

spb/ka-maps

Public
6commits 1branches 0releases
448.0 KBsize
maindefault branch
29 days agolast push
TypeScript 87.7% CSS 12.3%
2.1 KB · 73 lines typescript
Raw Blame History
1/**2 * Author: Simon-Pierre Boucher3 * Contact: contact@spboucher.ai4 * Project: Groupe Ka / Ka Maps5 */67import { describe, expect, it } from "vitest";8import {9  computeLensStats,10  propertiesInBBox,11  propertiesInPolygon,12} from "../src/utils/lens.js";13import type { MapProperty } from "../src/types/index.js";1415function prop(over: Partial<MapProperty>): MapProperty {16  return {17    id: over.id ?? Math.random().toString(36),18    appSource: "lou-ka",19    latitude: 46.8,20    longitude: -71.2,21    kind: "listing",22    ...over,23  };24}2526describe("computeLensStats", () => {27  it("computes medians and type mix from real fields only", () => {28    const stats = computeLensStats([29      prop({ price: 300_000, propertyType: "Maison", daysOnMarket: 10 }),30      prop({ price: 500_000, propertyType: "Maison", daysOnMarket: 100 }),31      prop({ price: 700_000, propertyType: "Condo", priceChange: -0.05 }),32    ]);33    expect(stats.count).toBe(3);34    expect(stats.medianPrice).toBe(500_000);35    expect(stats.medianDaysOnMarket).toBe(55);36    expect(stats.stale90dShare).toBe(0.5);37    expect(stats.priceCutShare).toBeCloseTo(1 / 3);38    expect(stats.typeMix?.["Maison"]).toBeCloseTo(2 / 3);39    // pas de valeurs estimées dans les données → pas de médiane inventée40    expect(stats.medianEstimatedValue).toBeUndefined();41  });4243  it("returns bare count on empty/opaque data", () => {44    const stats = computeLensStats([]);45    expect(stats).toEqual({ count: 0 });46  });47});4849describe("geographic selection", () => {50  const items = [51    prop({ id: "in", latitude: 46.8, longitude: -71.2 }),52    prop({ id: "out", latitude: 45.5, longitude: -73.6 }),53  ];5455  it("filters by bbox", () => {56    const sel = propertiesInBBox(items, {57      west: -71.4,58      south: 46.7,59      east: -71.0,60      north: 46.9,61    });62    expect(sel.map((p) => p.id)).toEqual(["in"]);63  });6465  it("filters by polygon (ray casting)", () => {66    const sel = propertiesInPolygon(items, {67      type: "Polygon",68      coordinates: [[[-71.4, 46.7], [-71.0, 46.7], [-71.0, 46.9], [-71.4, 46.9], [-71.4, 46.7]]],69    });70    expect(sel.map((p) => p.id)).toEqual(["in"]);71  });72});73