mirror of
https://github.com/brendan-ch/project-inter-server.git
synced 2026-04-17 07:50:31 +00:00
272 lines
10 KiB
TypeScript
272 lines
10 KiB
TypeScript
import { beforeEach, describe, expect, it, jest, test } from "@jest/globals";
|
|
import { ApiBasedShuttleRepositoryLoader, ApiResponseError } from "../../src/loaders/ApiBasedShuttleRepositoryLoader";
|
|
import { UnoptimizedInMemoryShuttleRepository } from "../../src/repositories/UnoptimizedInMemoryShuttleRepository";
|
|
import { fetchSystemDataSuccessfulResponse } from "../jsonSnapshots/fetchSystemData/fetchSystemDataSuccessfulResponse";
|
|
import { fetchSystemDataFailedResponse } from "../jsonSnapshots/fetchSystemData/fetchSystemDataFailedResponse";
|
|
import { fetchRouteDataSuccessfulResponse } from "../jsonSnapshots/fetchRouteData/fetchRouteDataSuccessfulResponse";
|
|
import {
|
|
fetchStopAndPolylineDataSuccessfulResponse
|
|
} from "../jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse";
|
|
import { generateMockRoutes, generateMockShuttles, generateMockStops, generateMockPassioSystems } from "../testHelpers/mockDataGenerators";
|
|
import {
|
|
fetchShuttleDataSuccessfulResponse
|
|
} from "../jsonSnapshots/fetchShuttleData/fetchShuttleDataSuccessfulResponse";
|
|
import { fetchEtaDataSuccessfulResponse } from "../jsonSnapshots/fetchEtaData/fetchEtaDataSuccessfulResponse";
|
|
import {
|
|
resetGlobalFetchMockJson,
|
|
updateGlobalFetchMockJson,
|
|
updateGlobalFetchMockJsonToThrowSyntaxError
|
|
} from "../testHelpers/fetchMockHelpers";
|
|
|
|
async function assertAsyncCallbackThrowsApiResponseError(callback: () => Promise<any>) {
|
|
await expect(callback).rejects.toThrow(ApiResponseError);
|
|
}
|
|
|
|
describe("ApiBasedRepositoryLoader", () => {
|
|
let loader: ApiBasedShuttleRepositoryLoader;
|
|
|
|
beforeEach(() => {
|
|
loader = new ApiBasedShuttleRepositoryLoader("1", new UnoptimizedInMemoryShuttleRepository());
|
|
resetGlobalFetchMockJson();
|
|
});
|
|
|
|
describe("fetchAndUpdateSystemData", () => {
|
|
it("updates system data in repository if response received", async () => {
|
|
// Arrange
|
|
const systemsToPrune = generateMockPassioSystems();
|
|
await Promise.all(systemsToPrune.map(async (system) => {
|
|
await loader.repository.updateSystem(system);
|
|
}));
|
|
|
|
const numberOfSystemsInResponse = fetchSystemDataSuccessfulResponse.all.length;
|
|
updateGlobalFetchMockJson(fetchSystemDataSuccessfulResponse);
|
|
|
|
// Act
|
|
await loader.fetchAndUpdateSystemData();
|
|
|
|
// Assert
|
|
const system = await loader.repository.getSystemIfExists();
|
|
expect(system).not.toBeNull();
|
|
});
|
|
|
|
it("throws the correct error if the API response contains no data", async () => {
|
|
updateGlobalFetchMockJson(fetchSystemDataFailedResponse);
|
|
|
|
await assertAsyncCallbackThrowsApiResponseError(async () => {
|
|
await loader.fetchAndUpdateSystemData();
|
|
});
|
|
});
|
|
|
|
it("throws the correct error if HTTP status code is not 200", async () => {
|
|
updateGlobalFetchMockJson(fetchSystemDataFailedResponse, 400);
|
|
|
|
await assertAsyncCallbackThrowsApiResponseError(async () => {
|
|
await loader.fetchAndUpdateSystemData();
|
|
});
|
|
});
|
|
});
|
|
|
|
|
|
describe("fetchAndUpdateRouteDataForExistingSystemsInRepository", () => {
|
|
test("calls fetchAndUpdateRouteDataForSystemId for system in repository", async () => {
|
|
const spy = jest.spyOn(loader, "fetchAndUpdateRouteDataForSystemId");
|
|
|
|
const systems = generateMockPassioSystems();
|
|
|
|
await loader.repository.updateSystem(systems[0]);
|
|
|
|
await loader.fetchAndUpdateRouteDataForExistingSystemInRepository();
|
|
|
|
expect(spy.mock.calls.length).toBe(1);
|
|
expect(spy).toHaveBeenCalledWith(systems[0].id)
|
|
});
|
|
});
|
|
|
|
describe("fetchAndUpdateRouteDataForSystemId", () => {
|
|
const systemId = "263";
|
|
it("updates route data in repository if response received", async () => {
|
|
// Arrange
|
|
// Test pruning
|
|
const routesToPrune = generateMockRoutes();
|
|
await Promise.all(routesToPrune.map(async (route) => {
|
|
route.systemId = systemId;
|
|
await loader.repository.addOrUpdateRoute(route);
|
|
}));
|
|
|
|
updateGlobalFetchMockJson(fetchRouteDataSuccessfulResponse);
|
|
|
|
// Act
|
|
await loader.fetchAndUpdateRouteDataForSystemId(systemId);
|
|
|
|
// Assert
|
|
const routes = await loader.repository.getRoutesBySystemId(systemId);
|
|
|
|
expect(routes.length).toEqual(fetchRouteDataSuccessfulResponse.all.length)
|
|
});
|
|
|
|
it("throws the correct error if the API response contains no data", async () => {
|
|
// The Passio API returns some invalid JSON if there is no data,
|
|
// so simulate a JSON parsing error
|
|
|
|
updateGlobalFetchMockJsonToThrowSyntaxError();
|
|
|
|
await assertAsyncCallbackThrowsApiResponseError(async () => {
|
|
await loader.fetchAndUpdateRouteDataForSystemId(systemId);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository", () => {
|
|
it("calls fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId for system", async () => {
|
|
const spy = jest.spyOn(loader, "fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId");
|
|
|
|
const systems = generateMockPassioSystems();
|
|
|
|
await loader.repository.updateSystem(systems[0]);
|
|
|
|
await loader.fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemInRepository();
|
|
|
|
expect(spy.mock.calls.length).toBe(1);
|
|
expect(spy).toHaveBeenCalledWith(systems[0].id)
|
|
});
|
|
})
|
|
|
|
describe("fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId", () => {
|
|
const systemId = "263";
|
|
it("updates stop and polyline data if response received", async () => {
|
|
// Arrange
|
|
// Test pruning of stops only
|
|
const stopsToPrune = generateMockStops();
|
|
await Promise.all(stopsToPrune.map(async (stop) => {
|
|
stop.systemId = systemId;
|
|
await loader.repository.addOrUpdateStop(stop);
|
|
}));
|
|
|
|
updateGlobalFetchMockJson(fetchStopAndPolylineDataSuccessfulResponse);
|
|
|
|
const stopsArray = Object.values(fetchStopAndPolylineDataSuccessfulResponse.stops);
|
|
|
|
await loader.fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId(systemId);
|
|
|
|
const stops = await loader.repository.getStopsBySystemId(systemId);
|
|
expect(stops.length).toEqual(stopsArray.length);
|
|
|
|
await Promise.all(stops.map(async (stop) => {
|
|
const orderedStops = await loader.repository.getOrderedStopsByStopId(stop.id)
|
|
expect(orderedStops.length).toBeGreaterThan(0);
|
|
}));
|
|
|
|
const routes = await loader.repository.getRoutesBySystemId(systemId);
|
|
routes.forEach((route) => {
|
|
expect(route.polylineCoordinates.length).toBeGreaterThan(0);
|
|
});
|
|
});
|
|
|
|
it("throws the correct error if the API response contains no data", async () => {
|
|
updateGlobalFetchMockJsonToThrowSyntaxError();
|
|
|
|
await assertAsyncCallbackThrowsApiResponseError(async () => {
|
|
await loader.fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId(systemId);
|
|
});
|
|
})
|
|
});
|
|
|
|
describe("fetchAndUpdateShuttleDataForExistingSystemsInRepository", () => {
|
|
it("calls fetchAndUpdateShuttleDataForSystemId for every system", async () => {
|
|
const spy = jest.spyOn(loader, "fetchAndUpdateShuttleDataForSystemId");
|
|
|
|
const systems = generateMockPassioSystems();
|
|
await loader.repository.updateSystem(systems[0]);
|
|
|
|
await loader.fetchAndUpdateShuttleDataForExistingSystemInRepository();
|
|
|
|
expect(spy.mock.calls.length).toBe(1);
|
|
expect(spy).toHaveBeenCalledWith(systems[0].id)
|
|
});
|
|
});
|
|
|
|
describe("fetchAndUpdateShuttleDataForSystemId", () => {
|
|
const systemId = "263";
|
|
it("updates shuttle data in repository if response received", async () => {
|
|
const shuttlesToPrune = generateMockShuttles();
|
|
await Promise.all(shuttlesToPrune.map(async (shuttle) => {
|
|
shuttle.systemId = systemId;
|
|
await loader.repository.addOrUpdateShuttle(shuttle);
|
|
}))
|
|
|
|
updateGlobalFetchMockJson(fetchShuttleDataSuccessfulResponse);
|
|
const busesInResponse = Object.values(fetchShuttleDataSuccessfulResponse.buses);
|
|
|
|
await loader.fetchAndUpdateShuttleDataForSystemId(systemId);
|
|
|
|
const shuttles = await loader.repository.getShuttlesBySystemId(systemId);
|
|
|
|
expect(shuttles.length).toEqual(busesInResponse.length);
|
|
});
|
|
|
|
it("throws the correct error if the API response contains no data", async () => {
|
|
updateGlobalFetchMockJsonToThrowSyntaxError();
|
|
|
|
await assertAsyncCallbackThrowsApiResponseError(async () => {
|
|
await loader.fetchAndUpdateShuttleDataForSystemId(systemId);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository", () => {
|
|
it("calls fetchAndUpdateEtaDataFoExistingStopsForSystemId for every system in repository", async () => {
|
|
const spy = jest.spyOn(loader, "fetchAndUpdateEtaDataForExistingStopsForSystemId");
|
|
|
|
const systems = generateMockPassioSystems();
|
|
await loader.repository.updateSystem(systems[0]);
|
|
|
|
await loader.fetchAndUpdateEtaDataForExistingStopsForSystemInRepository();
|
|
|
|
expect(spy.mock.calls.length).toBe(1);
|
|
expect(spy).toHaveBeenCalledWith(systems[0].id)
|
|
});
|
|
});
|
|
|
|
describe("fetchAndUpdateEtaDataForExistingStopsForSystemId", () => {
|
|
it("calls fetchAndUpdateEtaDataForStopId for every stop in repository", async () => {
|
|
const spy = jest.spyOn(loader, "fetchAndUpdateEtaDataForStopId");
|
|
|
|
const stops = generateMockStops();
|
|
stops.forEach((stop) => {
|
|
stop.systemId = "1";
|
|
});
|
|
|
|
await Promise.all(stops.map(async (stop) => {
|
|
await loader.repository.addOrUpdateStop(stop);
|
|
}));
|
|
|
|
await loader.fetchAndUpdateEtaDataForExistingStopsForSystemId("1");
|
|
|
|
expect(spy.mock.calls.length).toEqual(stops.length);
|
|
});
|
|
});
|
|
|
|
describe("fetchAndUpdateEtaDataForStopId", () => {
|
|
const stopId = "177666";
|
|
it("updates ETA data for stop id if response received", async () => {
|
|
updateGlobalFetchMockJson(fetchEtaDataSuccessfulResponse);
|
|
// @ts-ignore
|
|
const etasFromResponse = fetchEtaDataSuccessfulResponse.ETAs[stopId]
|
|
|
|
await loader.fetchAndUpdateEtaDataForStopId(stopId);
|
|
|
|
const etas = await loader.repository.getEtasForStopId(stopId);
|
|
expect(etas.length).toEqual(etasFromResponse.length);
|
|
});
|
|
|
|
it("throws the correct error if the API response contains no data", async () => {
|
|
updateGlobalFetchMockJsonToThrowSyntaxError();
|
|
|
|
await assertAsyncCallbackThrowsApiResponseError(async () => {
|
|
await loader.fetchAndUpdateEtaDataForStopId("263");
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|