Files
project-inter-server/test/repositories/ApiBasedRepositoryTests.test.ts

348 lines
9.0 KiB
TypeScript

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"
}
},
]
}
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 and cache is empty", async () => {
const repository = new ApiBasedRepository();
const result = await repository.getEtaForShuttleAndStopId("5577", "177666");
expect(result).toEqual(null);
});
});
describe("getEtasForShuttleId", () => {
test("getEtasForShuttleId returns correct ETA data", async () => {
// Because I'm testing updateEtasForSystemIfTTL separately,
// stub it out here
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);
repository.updateEtasForSystemIfTTL = jest.fn(async () => {
});
const result = await repository.getEtasForShuttleId("5577");
expect(result).toEqual(initialCache.etasForShuttleId);
});
test("getEtasForShuttleId returns empty array if no data available", async () => {
const repository = new ApiBasedRepository();
repository.updateEtasForSystemIfTTL = jest.fn(async () => {
});
const result = await repository.getEtasForShuttleId("5577");
expect(result).toEqual([]);
});
});
describe("getEtasForStopId", () => {
test("getEtasForStopId returns correct ETA data", async () => {
// Because I'm testing updateEtasForSystemIfTTL separately,
// stub it out here
updateGlobalFetchMockJson(genericEtaDataByStopId);
const initialCache: ApiBasedRepositoryCache = {
etasForStopId: {
"177666": [
{
secondsRemaining: 587,
shuttleId: "5577",
stopId: "177666",
millisecondsSinceEpoch: Date.now(),
}
]
},
etasForShuttleId: {}
};
const ttls: ApiBasedRepositoryMillisecondTTLs = {
etasForShuttleId: 100000,
etasForStopId: 100000,
};
const repository = new ApiBasedRepository(initialCache, ttls);
repository.updateEtasForSystemIfTTL = jest.fn(async () => {
});
const result = await repository.getEtasForStopId("177666");
expect(result).toEqual(initialCache.etasForShuttleId);
});
test("getEtasForStopId returns empty array if no data available", async () => {
const repository = new ApiBasedRepository();
repository.updateEtasForSystemIfTTL = jest.fn(async () => {
});
const result = await repository.getEtasForShuttleId("5577");
expect(result).toEqual([]);
});
});
describe("updateEtasForSystemIfTTL", () => {
test("updateEtasForSystemIfTTL does nothing if data is not TTL", async () => {
updateGlobalFetchMockJson(genericEtaDataByStopId);
// If ETA data is not TTL, then don't do anything
const expectedEta: IEta = {
secondsRemaining: 587,
shuttleId: "5577",
stopId: "177666",
millisecondsSinceEpoch: Date.now() - 1000,
};
const initialCache: ApiBasedRepositoryCache = {
etasForShuttleId: {
"5577": [
expectedEta,
],
},
etasForStopId: {
"177666": [
expectedEta,
],
},
stopsBySystemId: {
"1": [
{
systemId: "1",
millisecondsSinceEpoch: Date.now() - 1000,
name: "Chapman Court",
id: "177666",
coordinates: {
latitude: 33.796796,
longitude: -117.889293
},
}
],
},
};
const ttls: ApiBasedRepositoryMillisecondTTLs = {
etasForShuttleId: 100000,
etasForStopId: 100000,
};
const repository = new ApiBasedRepository(initialCache, ttls);
await repository.updateEtasForSystemIfTTL("1");
const updatedResult = await repository.getEtaForShuttleAndStopId(
"5577",
"177666",
);
expect(updatedResult?.millisecondsSinceEpoch).toEqual(expectedEta.millisecondsSinceEpoch);
});
test("updateEtasForSystemIfTTL updates all ETA data if data is TTL", async () => {
updateGlobalFetchMockJson(genericEtaDataByStopId);
const repository = new ApiBasedRepository();
repository.getStopsBySystemId = jest.fn(async () => {
return [
{
name: "Chapman Court",
systemId: "1",
id: "177666",
coordinates: {
latitude: 33.796796,
longitude: -117.889293
},
}
];
});
await repository.updateEtasForSystemIfTTL("1");
const updatedResult = await repository.getEtasForStopId("177666");
expect(updatedResult.length).toEqual(2);
});
});
describe("getShuttleById", () => {
test("getShuttleById returns null if unseeded cache", async () => {
});
test("getShuttleById returns old data if not expired", async () => {
});
test("getShuttleById returns fresh data if expired", async () => {
});
});