- Implemented StopsMap component to display bus stops on a map using MapLibre GL. - Integrated walking directions feature in WalkingDirections component to calculate routes from user location to selected bus stop. - Added geo utility functions for coordinate validation and distance calculation. - Created route grouping and stop filtering logic in routeGroups module. - Developed custom hooks for managing stop routes with React Query. - Added tests for routing and stop functionalities to ensure reliability.
56 lines
3.6 KiB
JavaScript
56 lines
3.6 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { coordinates } from '../server/coordinates.mjs';
|
|
import { createRideBusClient, normalizeCities, normalizeStop, normalizeStops, parseRequest } from '../server/ridebus.mjs';
|
|
import { distanceMeters, hasCoordinates, walkingLink } from '../src/lib/geo.ts';
|
|
|
|
test('map coordinates accept numeric strings and preserve missing/invalid pairs as missing', () => {
|
|
assert.deepEqual(coordinates('55.517553', 28.776448), { latitude: 55.517553, longitude: 28.776448 });
|
|
assert.deepEqual(coordinates(0, 0), { latitude: 0, longitude: 0 });
|
|
for (const [lat, lon] of [[null, 28], ['', 28], [55, undefined], [91, 28], [55, -181], [true, 28], ['bad', 28], [NaN, 28]]) {
|
|
assert.deepEqual(coordinates(lat, lon), {});
|
|
assert.equal(hasCoordinates({ latitude: lat, longitude: lon }), false);
|
|
}
|
|
assert.equal(hasCoordinates({ latitude: 0, longitude: 0 }), true);
|
|
assert.deepEqual(normalizeCities([{ id: 1, name: 'Полоцк', center_lat: '55.4869', center_lon: '28.7856' }])[0].latitude, 55.4869);
|
|
});
|
|
|
|
test('stop catalog retains platform coordinates and detail exposes only active distinct routes', () => {
|
|
const raw = { id: 95, name: '11 Июля', latitude: 55.517553, longitude: 28.776448, address: ' улица Ленина ', description: ' на Лозовку ', routes_count: '4' };
|
|
assert.equal(normalizeStops([raw])[0].address, 'улица Ленина');
|
|
assert.equal(normalizeStops([raw])[0].longitude, 28.776448);
|
|
const detail = normalizeStop({ ...raw, secret: 'hidden', routes: [
|
|
{ id: 2, route_number: '12', name: 'Центр', is_active: true },
|
|
{ id: 1, route_number: '4', name: 'Вокзал' },
|
|
{ id: 1, route_number: '4', name: 'Вокзал' },
|
|
{ id: 3, route_number: '2', name: 'Больница', is_active: false },
|
|
] });
|
|
assert.deepEqual(detail.routes.map(route => route.number), ['4', '12']);
|
|
assert.equal(detail.routesCount, 2);
|
|
assert.equal('secret' in detail, false);
|
|
assert.throws(() => normalizeStop({ ...raw, routes: null }), error => error.status === 502);
|
|
});
|
|
|
|
test('stop details validate identifiers, coalesce loads and isolate city caches', async () => {
|
|
assert.deepEqual(parseRequest(new URLSearchParams('resource=stop&cityId=1&stopId=95')), { resource: 'stop', cityId: 1, stopId: 95 });
|
|
for (const input of ['resource=stop&cityId=1', 'resource=stop&cityId=1&stopId=-1', 'resource=stop&cityId=1&stopId=../1']) assert.throws(() => parseRequest(new URLSearchParams(input)), error => error.status === 400);
|
|
const calls = [];
|
|
const client = createRideBusClient({ apiKey: 'private-key', fetchData: async (url, options) => {
|
|
calls.push([url.pathname, options.headers['X-City-Id']]);
|
|
return { ok: true, json: async () => ({ id: 95, name: '11 Июля', routes: [] }) };
|
|
} });
|
|
const input = { resource: 'stop', cityId: 1, stopId: 95 };
|
|
await Promise.all([client.get(input), client.get(input)]); await client.get(input); await client.get({ ...input, cityId: 2 });
|
|
assert.deepEqual(calls, [['/api/v1/stops/95', '1'], ['/api/v1/stops/95', '2']]);
|
|
});
|
|
|
|
test('nearby distances use geographic coordinates and walking links use the selected platform', () => {
|
|
const a = { latitude: 55.4849, longitude: 28.7685 }, b = { latitude: 55.4852, longitude: 28.7691 };
|
|
assert.equal(distanceMeters(a, a), 0);
|
|
assert.ok(distanceMeters(a, b) > 40 && distanceMeters(a, b) < 60);
|
|
assert.equal(distanceMeters(a, b), distanceMeters(b, a));
|
|
const link = new URL(walkingLink(b));
|
|
assert.equal(link.searchParams.get('destination'), '55.4852,28.7691');
|
|
assert.equal(link.searchParams.get('travelmode'), 'walking');
|
|
});
|