import { beforeEach, describe, expect, jest, test } from "@jest/globals"; import { ApiBasedRepository, ApiBasedRepositoryCache, ApiBasedRepositoryMillisecondTTLs } from "../../src/repositories/ApiBasedRepository"; import { IEta } from "../../src/entities/entities"; /** * Update the global fetch function to return a specific object. * @param obj */ function updateGlobalFetchMockJson(obj: any) { // @ts-ignore global.fetch = jest.fn(() => { return Promise.resolve({ json: () => Promise.resolve(obj) }) }) as jest.Mock; } /** * Reset the global fetch function mock's JSON to return an empty object. * @param obj */ function resetGlobalFetchMockJson() { updateGlobalFetchMockJson({}) } beforeEach(() => { resetGlobalFetchMockJson(); }) // Snapshot taken from the Passio GO! API const genericEtaDataByStopId = { "177666": [ { "OOS": 0, "busName": "08", "distance": 1, "speed": 10.028535400123669, "routeBlockId": "142270", "actualRouteBlockId": "142270", "arrived": null, "eta": "10 min ", "color": "#000000", "bg": "#ffea3f", "order": 0, "dwell": null, "stopsAmount": 2, "secondsSpent": 587, "etaR": "10", "error": null, "outdated": 0, "routeId": "53966", "serviceTime": "", "scheduleTimes": [], "goShowSchedule": 0, "looping": "1", "routeGroupId": "6703", "busId": 5577, "tripId": 751430, "deviceId": 402840, "created": "2025-01-07 15:00:09", "routePointPosition": 6, "routeStopPosition": 1, "stopRoutePointPosition": 217, "timezoneOffset": -10800, "busLatLng": [ 33.7933406, -117.8539321 ], "busProjectionLatlng": { "lat": 33.79331052666975, "lng": -117.85392945849208 }, "busProjectionError": 3, "stopId": "177666", "theStop": { "name": "Chapman Court", "position": 3, "userId": "263", "routeStopId": "1348785", "busId": 5577, "routeName": "Red Route", "shortName": null, "routeId": "53966", "stopId": "177666" } }, { "OOS": 0, "busName": "07", "distance": 1, "speed": 12.160256921380398, "routeBlockId": "142270", "actualRouteBlockId": "142270", "arrived": null, "eta": "11 min ", "color": "#000000", "bg": "#ffea3f", "order": 0, "dwell": null, "stopsAmount": 2, "secondsSpent": 635, "etaR": "11", "error": null, "outdated": 0, "routeId": "53966", "serviceTime": "", "scheduleTimes": [], "goShowSchedule": 0, "looping": "1", "routeGroupId": "6703", "busId": 5576, "tripId": 751430, "deviceId": 441065, "created": "2025-01-07 15:00:10", "routePointPosition": 448, "routeStopPosition": 4, "stopRoutePointPosition": 217, "timezoneOffset": -10800, "busLatLng": [ 33.7933284, -117.855132 ], "busProjectionLatlng": { "lat": 33.79332033922653, "lng": -117.85513217762522 }, "busProjectionError": 1, "stopId": "177666", "theStop": { "name": "Chapman Court", "position": 3, "userId": "263", "routeStopId": "1348785", "busId": 5576, "routeName": "Red Route", "shortName": null, "routeId": "53966", "stopId": "177666" } }, { "OOS": 0, "busName": "10", "distance": 1, "speed": 11.085164763991688, "routeBlockId": "142270", "actualRouteBlockId": "142270", "arrived": null, "eta": "19 min ", "color": "#000000", "bg": "#ffea3f", "order": 0, "dwell": null, "stopsAmount": 2, "secondsSpent": 1150, "etaR": "19", "error": null, "outdated": 0, "routeId": "53966", "serviceTime": "", "scheduleTimes": [], "goShowSchedule": 0, "looping": "1", "routeGroupId": "6703", "busId": 7105, "tripId": 751430, "deviceId": 404873, "created": "2025-01-07 15:00:08", "routePointPosition": 254, "routeStopPosition": 3, "stopRoutePointPosition": 217, "timezoneOffset": -10800, "busLatLng": [ 33.7917895, -117.8901868 ], "busProjectionLatlng": { "lat": 33.79179583075815, "lng": -117.8902164019431 }, "busProjectionError": 3, "stopId": "177666", "theStop": { "name": "Chapman Court", "position": 3, "userId": "263", "routeStopId": "1348785", "busId": 7105, "routeName": "Red Route", "shortName": null, "routeId": "53966", "stopId": "177666" } } ] } describe("getEtaForShuttleAndStopId", () => { test("getEtaForShuttleAndStopId returns correct ETA data", async () => { updateGlobalFetchMockJson(genericEtaDataByStopId); const repository = new ApiBasedRepository(); const result = await repository.getEtaForShuttleAndStopId("5577", "177666"); expect(result?.secondsRemaining).toEqual(587); expect(result?.millisecondsSinceEpoch).toBeDefined(); }); test("getEtaForShuttleAndStopId returns null if API call is invalid", async () => { const repository = new ApiBasedRepository(); const result = await repository.getEtaForShuttleAndStopId("5577", "177666"); expect(result).toEqual(null); }); test("getEtasForShuttleAndStopId returns old data if not expired", async () => { updateGlobalFetchMockJson(genericEtaDataByStopId); const expectedEta: IEta = { secondsRemaining: 587, shuttleId: "5577", stopId: "177666", millisecondsSinceEpoch: Date.now(), }; const initialCache: ApiBasedRepositoryCache = { etasForShuttleId: { "5577": [ expectedEta, ], }, etasForStopId: { "177666": [ expectedEta, ], }, }; const ttls: ApiBasedRepositoryMillisecondTTLs = { etasForShuttleId: 100000, etasForStopId: 100000, } const repository = new ApiBasedRepository(initialCache, ttls); const result = repository.getEtaForShuttleAndStopId("5577", "177666"); expect(result).toEqual(expectedEta); }); }); describe("getEtasForShuttleId", () => { test("getEtasForShuttleId returns correct ETA data", async () => { // Because I'm testing updateEtasForSystemIfTTL separately, force it to hit // the cache for the stops }); test("getEtasForShuttleId returns empty array if no data available", async () => { }); test("getEtasForShuttleId returns old data if not expired", async () => { updateGlobalFetchMockJson(genericEtaDataByStopId); const initialCache: ApiBasedRepositoryCache = { etasForStopId: {}, etasForShuttleId: { "5577": [ { secondsRemaining: 587, shuttleId: "5577", stopId: "177666", millisecondsSinceEpoch: Date.now(), } ] }, }; const ttls: ApiBasedRepositoryMillisecondTTLs = { etasForShuttleId: 100000, etasForStopId: 100000, }; const repository = new ApiBasedRepository(initialCache, ttls); const result = await repository.getEtasForShuttleId("5577"); expect(result).toEqual(initialCache.etasForShuttleId); }); }); describe("getEtasForStopId", () => { test("getEtasForStopId returns correct ETA data", async () => { }); test("getEtasForStopId returns empty array if no data available", async () => { }); test("getEtasForStopId returns old data if not expired", async () => { }); });