src/lib/trip-parts.test.ts
Rama main · réplica de lectura del repositorio original.
import { describe, expect, it } from "vitest";
import {
formatTripPartDates,
formatTripSpan,
tripPartLocations,
tripSpan,
} from "./trip-parts";
describe("tripSpan", () => {
it("has nothing to say about a trip with no parts", () => {
// A state the app has never had before: every caller answers for it rather
// than formatting an absence.
expect(tripSpan([])).toEqual({ start: undefined, end: undefined });
expect(tripSpan(undefined)).toEqual({ start: undefined, end: undefined });
});
it("has nothing to say about parts that carry no dates", () => {
expect(tripSpan([{ location: { name: "Dahab" } }])).toEqual({
start: undefined,
end: undefined,
});
});
it("takes the earliest start and the latest end", () => {
expect(
tripSpan([
{ start_date: "2026-04-22", end_date: "2026-04-25" },
{ start_date: "2026-04-18", end_date: "2026-04-22" },
]),
).toEqual({ start: "2026-04-18", end: "2026-04-25" });
});
it("ignores the parts that carry no dates", () => {
expect(
tripSpan([
{ location: { name: "Dahab" } },
{ start_date: "2026-04-18", end_date: "2026-04-22" },
{ location: { name: "Sharm" } },
]),
).toEqual({ start: "2026-04-18", end: "2026-04-22" });
});
it("takes each end independently", () => {
// A trip whose only dated part carries an end and no start has an end and
// no start - what the data says, rather than an invented range. The API
// derives it the same way.
expect(tripSpan([{ end_date: "2026-04-25" }])).toEqual({
start: undefined,
end: "2026-04-25",
});
expect(
tripSpan([{ start_date: "2026-04-18" }, { end_date: "2026-04-25" }]),
).toEqual({ start: "2026-04-18", end: "2026-04-25" });
});
it("reads null the way the API writes it", () => {
expect(
tripSpan([{ start_date: null, end_date: null, location: null }]),
).toEqual({ start: undefined, end: undefined });
});
});
describe("formatTripSpan", () => {
it("formats the span of the parts, not of any one of them", () => {
expect(
formatTripSpan([
{ start_date: "2026-04-18", end_date: "2026-04-22" },
{ start_date: "2026-04-22", end_date: "2026-04-25" },
]),
).toBe("Apr 18 - Apr 25, 2026");
});
it("answers undefined when no part carries a date", () => {
// So a table can show "-" and a subtitle can disappear.
expect(formatTripSpan([{ location: { name: "Dahab" } }])).toBeUndefined();
expect(formatTripSpan([])).toBeUndefined();
});
it("shows the one date a half-dated trip has", () => {
expect(formatTripSpan([{ start_date: "2026-04-18" }])).toBe("Apr 18, 2026");
});
});
describe("tripPartLocations", () => {
it("keeps the diver's order and drops the parts with no place", () => {
expect(
tripPartLocations([
{ location: { name: "Dahab" } },
{ start_date: "2026-04-22" },
{ location: { name: "Sharm" } },
]),
).toEqual([{ name: "Dahab" }, { name: "Sharm" }]);
});
it("keeps a place named twice", () => {
// A trip that returns to one is the shape this change exists to record, and
// a label reading "Dahab, Sharm +1" is the honest one.
expect(
tripPartLocations([
{ location: { name: "Dahab" } },
{ location: { name: "Sharm" } },
{ location: { name: "Dahab" } },
]).map((location) => location.name),
).toEqual(["Dahab", "Sharm", "Dahab"]);
});
it("answers an absent list with an empty one", () => {
expect(tripPartLocations(undefined)).toEqual([]);
expect(tripPartLocations([{ location: null }])).toEqual([]);
});
});
describe("formatTripPartDates", () => {
it("reads a part with one date as running from or to it", () => {
expect(formatTripPartDates({ start_date: "2026-09-01" })).toBe(
"From Sep 1, 2026",
);
expect(
formatTripPartDates({ end_date: "2021-04-06", start_date: null }),
).toBe("Until Apr 6, 2021");
});
it("formats a part with both dates as a range, and one with none as nothing", () => {
expect(
formatTripPartDates({ start_date: "2026-04-03", end_date: "2026-04-08" }),
).toBe("Apr 3 - Apr 8, 2026");
expect(
formatTripPartDates({ location: { name: "Dahab" } }),
).toBeUndefined();
});
});