minotor
Version:
A lightweight client-side transit routing library.
104 lines (91 loc) • 3.95 kB
text/typescript
import assert from 'node:assert';
import { beforeEach, describe, it } from 'node:test';
import { timeFromHMS } from '../../timetable/time.js';
import { RouteTypes, TransferTypes } from '../../timetable/timetable.js';
import { StraightLineTransferGenerator } from '../../transfers/straightLineTransferGenerator.js';
import { GtfsParser } from '../parser.js';
describe('GTFS parser', () => {
let parser: GtfsParser;
beforeEach(() => {
const gtfsPath = './src/gtfs/__tests__/resources/sample-feed.zip';
parser = new GtfsParser(gtfsPath);
});
it('should correctly parse stops from GTFS feed', async () => {
const stopsIndex = await parser.parseStops();
assert.strictEqual(stopsIndex.size(), 9);
const stop = stopsIndex.findStopBySourceStopId('FUR_CREEK_RES');
assert(stop);
assert.strictEqual(stop.name, 'Furnace Creek Resort (Demo)');
assert.strictEqual(stop.lat, 36.425288);
assert.strictEqual(stop.lon, -117.133162);
});
it('should correctly parse timetable from GTFS feed', async () => {
const timetable = await parser.parseTimetable(new Date('2007-01-10'));
const stopsIndex = await parser.parseStops();
const furCreekResId =
stopsIndex.findStopBySourceStopId('FUR_CREEK_RES')?.id;
assert(furCreekResId !== undefined);
const transfers = timetable.getTransfers(furCreekResId);
assert.strictEqual(transfers.length, 0);
const route = timetable.getRoute(3);
assert(route);
assert.strictEqual(route.serviceRoute(), 2);
const beattyAirportId =
stopsIndex.findStopBySourceStopId('BEATTY_AIRPORT')?.id;
const bullfrogId = stopsIndex.findStopBySourceStopId('BULLFROG')?.id;
assert(beattyAirportId !== undefined && bullfrogId !== undefined);
assert.strictEqual(route.getNbStops(), 2);
const beattyAirportStopIndex = route.stopRouteIndices(beattyAirportId)[0];
const bullfrogStopIndex = route.stopRouteIndices(bullfrogId)[0];
assert(
beattyAirportStopIndex !== undefined && bullfrogStopIndex !== undefined,
);
assert.strictEqual(
route.arrivalAt(beattyAirportStopIndex, 0),
timeFromHMS(8, 0, 0),
);
assert.strictEqual(
route.departureFrom(beattyAirportStopIndex, 0),
timeFromHMS(8, 0, 0),
);
assert.strictEqual(
route.arrivalAt(bullfrogStopIndex, 0),
timeFromHMS(8, 10, 0),
);
assert.strictEqual(
route.departureFrom(bullfrogStopIndex, 0),
timeFromHMS(8, 15, 0),
);
const routes = timetable.routesPassingThrough(furCreekResId);
assert.strictEqual(routes.length, 2);
assert.strictEqual(routes[0]?.serviceRoute(), 3);
assert.strictEqual(routes[1]?.serviceRoute(), 3);
const serviceRoute = timetable.getServiceRouteInfo(route);
assert(serviceRoute);
assert.strictEqual(serviceRoute.name, '10');
assert.strictEqual(serviceRoute.type, RouteTypes.BUS);
});
it('adds virtual transfers flagged as generated when a generator is supplied', async () => {
// The sample feed has no transfers.txt, so a wide radius connects the
// route-served stops to each other.
const generatorParser = new GtfsParser(
'./src/gtfs/__tests__/resources/sample-feed.zip',
undefined,
new StraightLineTransferGenerator({ maxDistanceMeters: 1_000_000 }),
);
const timetable = await generatorParser.parseTimetable(
new Date('2007-01-10'),
);
const stopsIndex = await generatorParser.parseStops();
const furCreekResId =
stopsIndex.findStopBySourceStopId('FUR_CREEK_RES')?.id;
assert(furCreekResId !== undefined);
const transfers = timetable.getTransfers(furCreekResId);
assert(transfers.length > 0);
assert(
transfers.every((t) => t.type === TransferTypes.REQUIRES_MINIMAL_TIME),
);
// Transfers only point at route-served stops, never at the origin itself.
assert(transfers.every((t) => t.destination !== furCreekResId));
});
});