108 lines
3.9 KiB
TypeScript
108 lines
3.9 KiB
TypeScript
import { strict as assert } from "node:assert";
|
|
import { test } from "node:test";
|
|
import {
|
|
adaptLegacyStationNumber,
|
|
formatServiceMinute,
|
|
lookupLegacyStations,
|
|
parseServiceMinute,
|
|
parseWallClockTime,
|
|
physicalStationId,
|
|
serviceDate,
|
|
serviceDateFromCalendarDate,
|
|
serviceMinuteFromWallClock,
|
|
stationStopId,
|
|
trainIdentityKey,
|
|
type StationIdentity,
|
|
type TrainIdentity,
|
|
} from "../lib/domain/railway";
|
|
|
|
const stationFixture = (): StationIdentity[] => [
|
|
{
|
|
physicalStationId: physicalStationId("physical-takamatsu"),
|
|
stationStopId: stationStopId("stop-yosan-takamatsu"),
|
|
stationNumber: "Y00",
|
|
lineId: "yosan",
|
|
},
|
|
{
|
|
physicalStationId: physicalStationId("physical-takamatsu"),
|
|
stationStopId: stationStopId("stop-kotoku-takamatsu"),
|
|
stationNumber: "T28",
|
|
lineId: "kotoku",
|
|
},
|
|
{
|
|
physicalStationId: physicalStationId("physical-muya"),
|
|
stationStopId: stationStopId("stop-tokushima-m12"),
|
|
stationNumber: "M12",
|
|
lineId: "tokushima",
|
|
},
|
|
{
|
|
physicalStationId: physicalStationId("physical-komatsushima"),
|
|
stationStopId: stationStopId("stop-komatsushima-m12"),
|
|
stationNumber: "M12",
|
|
lineId: "komatsushima",
|
|
},
|
|
];
|
|
|
|
test("station identity keeps physical station, stop, and number distinct", () => {
|
|
const stations = stationFixture();
|
|
const takamatsu = lookupLegacyStations(stations, { stationNumber: "Y00" });
|
|
assert.equal(takamatsu.length, 1);
|
|
assert.equal(takamatsu[0].physicalStationId, stations[0].physicalStationId);
|
|
|
|
const samePhysicalStation = stations.filter(
|
|
(station) => station.physicalStationId === stations[0].physicalStationId,
|
|
);
|
|
assert.equal(samePhysicalStation.length, 2);
|
|
assert.notEqual(samePhysicalStation[0].stationNumber, samePhysicalStation[1].stationNumber);
|
|
assert.equal(lookupLegacyStations(stations, { stationNumber: "M12" }).length, 2);
|
|
assert.equal(
|
|
lookupLegacyStations(stations, { stationNumber: "M12", lineId: "tokushima" }).length,
|
|
1,
|
|
);
|
|
});
|
|
|
|
test("legacy adapter does not invent a physical canonical ID", () => {
|
|
assert.deepEqual(adaptLegacyStationNumber("Y00", "yosan"), {
|
|
physicalStationId: null,
|
|
stationNumber: "Y00",
|
|
lineId: "yosan",
|
|
});
|
|
});
|
|
|
|
test("service minute represents extended railway times without Date", () => {
|
|
assert.equal(formatServiceMinute(parseServiceMinute("23:59")), "23:59");
|
|
assert.equal(formatServiceMinute(parseServiceMinute("24:00")), "24:00");
|
|
assert.equal(formatServiceMinute(parseServiceMinute("24:30")), "24:30");
|
|
assert.equal(formatServiceMinute(parseServiceMinute("25:15")), "25:15");
|
|
assert.equal(parseServiceMinute("00:00"), 0);
|
|
assert.equal(parseServiceMinute("24:30"), 1470);
|
|
assert.equal(parseServiceMinute("25:15"), 1515);
|
|
assert.throws(() => parseWallClockTime("24:00"), /between 00:00 and 23:59/);
|
|
});
|
|
|
|
test("service day maps after-midnight wall clock times to the previous service date", () => {
|
|
assert.equal(serviceMinuteFromWallClock("00:30"), 1470);
|
|
assert.equal(serviceMinuteFromWallClock("03:59"), 1679);
|
|
assert.equal(serviceMinuteFromWallClock("04:00"), 240);
|
|
assert.equal(serviceDateFromCalendarDate("2026-08-30", "00:30"), "2026-08-29");
|
|
assert.equal(serviceDateFromCalendarDate("2026-08-30", "03:59"), "2026-08-29");
|
|
assert.equal(serviceDateFromCalendarDate("2026-08-30", "04:00"), "2026-08-30");
|
|
});
|
|
|
|
test("train identity key includes service date, line, and source", () => {
|
|
const base: TrainIdentity = {
|
|
trainNumber: "特急1",
|
|
serviceDate: serviceDate("2026-08-30"),
|
|
lineId: "yosan",
|
|
source: "r2",
|
|
};
|
|
const nextDay = { ...base, serviceDate: serviceDate("2026-08-31") };
|
|
const otherLine = { ...base, lineId: "dosan" };
|
|
const otherSource = { ...base, source: "gas" };
|
|
|
|
assert.notEqual(trainIdentityKey(base), trainIdentityKey(nextDay));
|
|
assert.notEqual(trainIdentityKey(base), trainIdentityKey(otherLine));
|
|
assert.notEqual(trainIdentityKey(base), trainIdentityKey(otherSource));
|
|
assert.equal(trainIdentityKey(base), trainIdentityKey({ ...base }));
|
|
});
|