Ctrl K
ComunidadGuías…

src/lib/locations.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { describe, expect, it } from "vitest";
import {
  formatPlaceContext,
  geocodeResultLabel,
  geocodeResultToLocation,
  unrepeated,
} from "./locations";
import type { GeocodeResult } from "@/lib/api/geocoding";

describe("formatPlaceContext", () => {
  it("puts the region before the country", () => {
    expect(formatPlaceContext("Cebu", "Philippines")).toBe("Cebu, Philippines");
  });

  it("says whichever one it has where it has only one", () => {
    expect(formatPlaceContext(null, "Philippines")).toBe("Philippines");
    expect(formatPlaceContext("Cebu", undefined)).toBe("Cebu");
  });

  it("answers null for neither, blanks included", () => {
    // Null rather than "" so a caller can tell "nowhere was named" from a name.
    expect(formatPlaceContext(null, null)).toBeNull();
    expect(formatPlaceContext(" ", "")).toBeNull();
  });
});

describe("unrepeated", () => {
  it("keeps a part the labels do not hold", () => {
    expect(unrepeated("Surat Thani Province", "Ko Tao")).toBe(
      "Surat Thani Province",
    );
  });

  it("drops a part equal to a part of a label, whatever its case", () => {
    expect(unrepeated("Philippines", "Philippines")).toBeNull();
    expect(unrepeated("thailand", "Ko Tao, Thailand")).toBeNull();
    expect(unrepeated("Cebu", "Moalboal", " cebu ")).toBeNull();
  });

  it("compares whole parts, never substrings", () => {
    // "Cebu" is context for a place called Cebu City, not a repeat of it.
    expect(unrepeated("Cebu", "Cebu City, Philippines")).toBe("Cebu");
  });

  it("has nothing to say for a blank or missing part", () => {
    expect(unrepeated(null, "Ko Tao")).toBeNull();
    expect(unrepeated(undefined, "Ko Tao")).toBeNull();
    expect(unrepeated("  ", "Ko Tao")).toBeNull();
  });

  it("ignores a missing label", () => {
    expect(unrepeated("Cebu", null, undefined)).toBe("Cebu");
  });
});

describe("geocodeResultToLocation", () => {
  const DAHAB: GeocodeResult = {
    latitude: 28.4949,
    longitude: 34.5136,
    location: "Dahab, South Sinai Governorate, Egypt",
    name: "Dahab",
    region: "South Sinai Governorate",
    country: "Egypt",
    attribution: "Data © OpenStreetMap contributors, ODbL 1.0.",
    bbox_south: 28.45,
    bbox_north: 28.54,
    bbox_west: 34.47,
    bbox_east: 34.55,
  };

  it("saves the API's composed name unchanged", () => {
    // The place, its region and its country, composed once by the API for a
    // search and a pin alike - so nothing here joins it from the parts.
    expect(geocodeResultToLocation(DAHAB).name).toBe(
      "Dahab, South Sinai Governorate, Egypt",
    );
    expect(
      geocodeResultToLocation({
        ...DAHAB,
        region: "Somewhere Else",
        country: "Nowhere",
      }).name,
    ).toBe("Dahab, South Sinai Governorate, Egypt");
  });

  it("ignores the result's own bare name, which is not what a log records", () => {
    // "Dahab" alone says nothing about which Dahab. It still has a job in the
    // site search, where it is the row's title - but not in the field.
    expect(geocodeResultToLocation({ ...DAHAB, name: "Dahab" }).name).toBe(
      "Dahab, South Sinai Governorate, Egypt",
    );
    expect(geocodeResultToLocation({ ...DAHAB, name: null }).name).toBe(
      "Dahab, South Sinai Governorate, Egypt",
    );
  });

  it("takes the centre and the extent a forward search answered with", () => {
    // These are the *place's*, which is what a search by name returns. A
    // reverse geocode does not come through here, because its coordinates are
    // the host's own pin.
    expect(geocodeResultToLocation(DAHAB)).toEqual({
      name: "Dahab, South Sinai Governorate, Egypt",
      latitude: 28.4949,
      longitude: 34.5136,
      bbox_south: 28.45,
      bbox_north: 28.54,
      bbox_west: 34.47,
      bbox_east: 34.55,
    });
  });

  it("leaves the box out whole when the provider gave none", () => {
    // The API sends all four or nothing, and a half box is refused on the way
    // back in - so an absent one must stay absent rather than become a corner.
    expect(
      geocodeResultToLocation({
        ...DAHAB,
        bbox_south: null,
        bbox_north: null,
        bbox_west: null,
        bbox_east: null,
      }),
    ).toMatchObject({
      bbox_south: null,
      bbox_north: null,
      bbox_west: null,
      bbox_east: null,
    });
  });
});

describe("geocodeResultLabel", () => {
  const MOALBOAL: GeocodeResult = {
    latitude: 9.94,
    longitude: 123.39,
    location: "Moalboal, Cebu, Philippines",
    name: "Moalboal",
    region: "Cebu",
    country: "Philippines",
    attribution: "Data © OpenStreetMap contributors, ODbL 1.0.",
  };

  it("reads, as one line, what picking the row saves", () => {
    const { name, context } = geocodeResultLabel(MOALBOAL);
    expect({ name, context }).toEqual({
      name: "Moalboal",
      context: "Cebu, Philippines",
    });
    expect([name, context].join(", ")).toBe(
      geocodeResultToLocation(MOALBOAL).name,
    );
  });

  it("drops a hint part the name already says", () => {
    expect(
      geocodeResultLabel({
        ...MOALBOAL,
        location: "Philippines",
        name: "Philippines",
        region: null,
      }),
    ).toEqual({ name: "Philippines", context: null });
  });

  it("reads a result with no name of its own as its location alone", () => {
    // An address-only row: the API put its finest address part in the name's
    // place, so every part a hint could add is already in `location`.
    expect(
      geocodeResultLabel({
        ...MOALBOAL,
        location: "Panagsama Road, Cebu, Philippines",
        name: null,
      }),
    ).toEqual({ name: "Panagsama Road, Cebu, Philippines", context: null });
  });
});