mirror of
https://github.com/brendan-ch/project-inter-server.git
synced 2026-04-17 07:50:31 +00:00
Merge pull request #38 from brendan-ch/chore/reorganize-classes-for-multiple-systems
[INT-58] chore/reorganize-classes-for-multiple-systems
This commit is contained in:
@@ -13,6 +13,7 @@ type System {
|
||||
type Route {
|
||||
name: String!
|
||||
id: ID!
|
||||
systemId: ID!
|
||||
orderedStop(forStopId: ID): OrderedStop
|
||||
shuttles: [Shuttle!]
|
||||
polylineCoordinates: [Coordinates!]!
|
||||
@@ -26,10 +27,12 @@ type OrderedStop {
|
||||
routeId: ID!
|
||||
stop: Stop
|
||||
stopId: ID!
|
||||
systemId: ID!
|
||||
}
|
||||
|
||||
type Stop {
|
||||
id: ID!
|
||||
systemId: ID!
|
||||
name: String!
|
||||
coordinates: Coordinates!
|
||||
etas: [ETA!]
|
||||
@@ -47,10 +50,12 @@ type ETA {
|
||||
shuttle: Shuttle
|
||||
shuttleId: ID!
|
||||
secondsRemaining: Float!
|
||||
systemId: ID!
|
||||
}
|
||||
|
||||
type Shuttle {
|
||||
name: String!
|
||||
systemId: ID!
|
||||
id: ID!,
|
||||
coordinates: Coordinates!
|
||||
route: Route
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { ETANotificationScheduler } from "./notifications/schedulers/ETANotificationScheduler";
|
||||
import { ShuttleGetterSetterRepository } from "./repositories/ShuttleGetterSetterRepository";
|
||||
import { NotificationRepository } from "./repositories/NotificationRepository";
|
||||
import { InterchangeSystem } from "./entities/InterchangeSystem";
|
||||
|
||||
export interface ServerContext {
|
||||
shuttleRepository: ShuttleGetterSetterRepository;
|
||||
notificationRepository: NotificationRepository;
|
||||
systems: InterchangeSystem[];
|
||||
findSystemById: (id: string) => InterchangeSystem | null;
|
||||
}
|
||||
|
||||
105
src/entities/InterchangeSystem.ts
Normal file
105
src/entities/InterchangeSystem.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import { ShuttleRepositoryLoader } from "../loaders/ShuttleRepositoryLoader";
|
||||
import { ETANotificationScheduler } from "../notifications/schedulers/ETANotificationScheduler";
|
||||
import { TimedApiBasedShuttleRepositoryLoader } from "../loaders/TimedApiBasedShuttleRepositoryLoader";
|
||||
import { UnoptimizedInMemoryShuttleRepository } from "../repositories/UnoptimizedInMemoryShuttleRepository";
|
||||
import { RedisNotificationRepository } from "../repositories/RedisNotificationRepository";
|
||||
import { NotificationRepository } from "../repositories/NotificationRepository";
|
||||
import { ShuttleGetterSetterRepository } from "../repositories/ShuttleGetterSetterRepository";
|
||||
import { InMemoryNotificationRepository } from "../repositories/InMemoryNotificationRepository";
|
||||
import { AppleNotificationSender } from "../notifications/senders/AppleNotificationSender";
|
||||
import { ApiBasedShuttleRepositoryLoader } from "../loaders/ApiBasedShuttleRepositoryLoader";
|
||||
|
||||
export interface InterchangeSystemBuilderArguments {
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* ID to identify the system internally and in the API.
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* ID for fetching shuttle data from the Passio GO! system.
|
||||
*/
|
||||
passioSystemId: string;
|
||||
}
|
||||
|
||||
export class InterchangeSystem {
|
||||
constructor(
|
||||
public name: string,
|
||||
public id: string,
|
||||
public shuttleDataLoader: ShuttleRepositoryLoader,
|
||||
public shuttleRepository: ShuttleGetterSetterRepository,
|
||||
public notificationScheduler: ETANotificationScheduler,
|
||||
public notificationRepository: NotificationRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance of the class where all composited
|
||||
* classes are correctly linked, meant for use in development and production.
|
||||
* @param args
|
||||
*/
|
||||
static async build(
|
||||
args: InterchangeSystemBuilderArguments,
|
||||
) {
|
||||
const shuttleRepository = new UnoptimizedInMemoryShuttleRepository();
|
||||
const shuttleDataLoader = new TimedApiBasedShuttleRepositoryLoader(
|
||||
args.passioSystemId,
|
||||
args.id,
|
||||
shuttleRepository
|
||||
);
|
||||
await shuttleDataLoader.start();
|
||||
|
||||
const notificationRepository = new RedisNotificationRepository();
|
||||
await notificationRepository.connect();
|
||||
const notificationScheduler = new ETANotificationScheduler(
|
||||
shuttleRepository,
|
||||
notificationRepository,
|
||||
new AppleNotificationSender(),
|
||||
);
|
||||
notificationScheduler.startListeningForUpdates();
|
||||
|
||||
return new InterchangeSystem(
|
||||
args.name,
|
||||
args.id,
|
||||
shuttleDataLoader,
|
||||
shuttleRepository,
|
||||
notificationScheduler,
|
||||
notificationRepository,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance of the class where all composited
|
||||
* classes are correctly linked, meant for unit tests, and server/app
|
||||
* integration tests.
|
||||
* @param args
|
||||
*/
|
||||
static buildForTesting(
|
||||
args: InterchangeSystemBuilderArguments,
|
||||
) {
|
||||
const shuttleRepository = new UnoptimizedInMemoryShuttleRepository();
|
||||
const shuttleDataLoader = new ApiBasedShuttleRepositoryLoader(
|
||||
args.passioSystemId,
|
||||
args.id,
|
||||
shuttleRepository
|
||||
);
|
||||
|
||||
const notificationRepository = new InMemoryNotificationRepository();
|
||||
const notificationScheduler = new ETANotificationScheduler(
|
||||
shuttleRepository,
|
||||
notificationRepository,
|
||||
new AppleNotificationSender(false),
|
||||
);
|
||||
notificationScheduler.startListeningForUpdates();
|
||||
|
||||
return new InterchangeSystem(
|
||||
args.name,
|
||||
args.id,
|
||||
shuttleDataLoader,
|
||||
shuttleRepository,
|
||||
notificationScheduler,
|
||||
notificationRepository,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ export interface IEntityWithId {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface ISystem extends IEntityWithId, IEntityWithOptionalTimestamp {
|
||||
export interface IPassioSystem extends IEntityWithId, IEntityWithOptionalTimestamp {
|
||||
name: string;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ export interface IEta extends IEntityWithOptionalTimestamp {
|
||||
secondsRemaining: number;
|
||||
shuttleId: string;
|
||||
stopId: string;
|
||||
systemId: string;
|
||||
}
|
||||
|
||||
export interface IOrderedStop extends IEntityWithOptionalTimestamp {
|
||||
@@ -48,5 +49,6 @@ export interface IOrderedStop extends IEntityWithOptionalTimestamp {
|
||||
routeId: string;
|
||||
stopId: string;
|
||||
position: number;
|
||||
systemId: string;
|
||||
}
|
||||
|
||||
|
||||
71
src/index.ts
71
src/index.ts
@@ -3,17 +3,20 @@ import { ApolloServer } from "@apollo/server";
|
||||
import { startStandaloneServer } from "@apollo/server/standalone";
|
||||
import { MergedResolvers } from "./MergedResolvers";
|
||||
import { ServerContext } from "./ServerContext";
|
||||
import { UnoptimizedInMemoryShuttleRepository } from "./repositories/UnoptimizedInMemoryShuttleRepository";
|
||||
import { TimedApiBasedShuttleRepositoryLoader } from "./loaders/TimedApiBasedShuttleRepositoryLoader";
|
||||
import { ETANotificationScheduler } from "./notifications/schedulers/ETANotificationScheduler";
|
||||
import { loadShuttleTestData } from "./loaders/loadShuttleTestData";
|
||||
import { AppleNotificationSender } from "./notifications/senders/AppleNotificationSender";
|
||||
import { InMemoryNotificationRepository } from "./repositories/InMemoryNotificationRepository";
|
||||
import { NotificationRepository } from "./repositories/NotificationRepository";
|
||||
import { RedisNotificationRepository } from "./repositories/RedisNotificationRepository";
|
||||
import { loadShuttleTestData, supportedIntegrationTestSystems } from "./loaders/loadShuttleTestData";
|
||||
import { InterchangeSystem, InterchangeSystemBuilderArguments } from "./entities/InterchangeSystem";
|
||||
|
||||
const typeDefs = readFileSync("./schema.graphqls", "utf8");
|
||||
|
||||
// In the future this can be stored as a separate file
|
||||
const supportedSystems: InterchangeSystemBuilderArguments[] = [
|
||||
{
|
||||
id: "1",
|
||||
passioSystemId: "263",
|
||||
name: "Chapman University",
|
||||
}
|
||||
]
|
||||
|
||||
async function main() {
|
||||
const server = new ApolloServer<ServerContext>({
|
||||
typeDefs,
|
||||
@@ -21,39 +24,27 @@ async function main() {
|
||||
introspection: process.env.NODE_ENV !== "production",
|
||||
});
|
||||
|
||||
const shuttleRepository = new UnoptimizedInMemoryShuttleRepository();
|
||||
|
||||
let notificationRepository: NotificationRepository;
|
||||
let notificationService: ETANotificationScheduler;
|
||||
let systems: InterchangeSystem[];
|
||||
|
||||
if (process.argv.length > 2 && process.argv[2] == "integration-testing") {
|
||||
console.log("Using integration testing setup")
|
||||
await loadShuttleTestData(shuttleRepository);
|
||||
|
||||
const appleNotificationSender = new AppleNotificationSender(false);
|
||||
notificationRepository = new InMemoryNotificationRepository();
|
||||
systems = await Promise.all(supportedIntegrationTestSystems.map(
|
||||
async (systemArguments) => {
|
||||
const system = InterchangeSystem.buildForTesting(systemArguments);
|
||||
|
||||
notificationService = new ETANotificationScheduler(
|
||||
shuttleRepository,
|
||||
notificationRepository,
|
||||
appleNotificationSender
|
||||
);
|
||||
notificationService.startListeningForUpdates();
|
||||
// TODO: Have loading of different data for different systems in the future
|
||||
await loadShuttleTestData(system.shuttleRepository);
|
||||
|
||||
return system;
|
||||
}
|
||||
));
|
||||
} else {
|
||||
const repositoryDataUpdater = new TimedApiBasedShuttleRepositoryLoader(
|
||||
shuttleRepository,
|
||||
);
|
||||
await repositoryDataUpdater.start();
|
||||
|
||||
const redisNotificationRepository = new RedisNotificationRepository();
|
||||
await redisNotificationRepository.connect();
|
||||
|
||||
notificationRepository = redisNotificationRepository;
|
||||
notificationService = new ETANotificationScheduler(
|
||||
shuttleRepository,
|
||||
notificationRepository
|
||||
);
|
||||
notificationService.startListeningForUpdates();
|
||||
systems = await Promise.all(supportedSystems.map(
|
||||
async (systemArguments) => {
|
||||
return await InterchangeSystem.build(systemArguments);
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
const { url } = await startStandaloneServer(server, {
|
||||
@@ -62,8 +53,14 @@ async function main() {
|
||||
},
|
||||
context: async () => {
|
||||
return {
|
||||
shuttleRepository,
|
||||
notificationRepository,
|
||||
systems,
|
||||
findSystemById: (id: string) => {
|
||||
const system = systems.find((system) => system.id === id);
|
||||
if (!system) {
|
||||
return null;
|
||||
}
|
||||
return system;
|
||||
},
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ShuttleGetterSetterRepository } from "../repositories/ShuttleGetterSetterRepository";
|
||||
import { IEntityWithId, IEta, IRoute, IShuttle, IStop, ISystem } from "../entities/entities";
|
||||
import { IEntityWithId, IEta, IRoute, IShuttle, IStop } from "../entities/entities";
|
||||
import { ShuttleRepositoryLoader } from "./ShuttleRepositoryLoader";
|
||||
|
||||
export class ApiResponseError extends Error {
|
||||
@@ -15,10 +15,11 @@ export class ApiResponseError extends Error {
|
||||
* which inherit from `IEntityWithId`.
|
||||
*/
|
||||
export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader {
|
||||
supportedSystemIds = ["263"];
|
||||
baseUrl = "https://passiogo.com/mapGetData.php";
|
||||
|
||||
constructor(
|
||||
public passioSystemId: string,
|
||||
public systemIdForConstructedData: string,
|
||||
public repository: ShuttleGetterSetterRepository,
|
||||
) {
|
||||
}
|
||||
@@ -32,59 +33,10 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
return ids;
|
||||
}
|
||||
|
||||
public async fetchAndUpdateSystemData() {
|
||||
const params = {
|
||||
getSystems: "2",
|
||||
};
|
||||
const query = new URLSearchParams(params).toString();
|
||||
|
||||
const systemIds = await this.constructExistingEntityIdSet(async () => {
|
||||
return await this.repository.getSystems();
|
||||
})
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.baseUrl}?${query}`);
|
||||
const json = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error with status ${response.status}`)
|
||||
}
|
||||
|
||||
if (typeof json.all === "object") {
|
||||
// filter down to supported systems
|
||||
const filteredSystems = json.all.filter((jsonSystem: any) => this.supportedSystemIds.includes(jsonSystem.id));
|
||||
await Promise.all(filteredSystems.map(async (system: any) => {
|
||||
const constructedSystem: ISystem = {
|
||||
id: system.id,
|
||||
name: system.fullname,
|
||||
};
|
||||
|
||||
await this.repository.addOrUpdateSystem(constructedSystem);
|
||||
systemIds.delete(constructedSystem.id);
|
||||
}));
|
||||
} else {
|
||||
throw new Error("Received JSON object does not contain `all` field")
|
||||
}
|
||||
|
||||
// Prune systems
|
||||
await Promise.all(Array.from(systemIds).map(async (systemId) => {
|
||||
await this.repository.removeSystemIfExists(systemId);
|
||||
}));
|
||||
} catch(e: any) {
|
||||
throw new ApiResponseError(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
public async fetchAndUpdateRouteDataForExistingSystemsInRepository() {
|
||||
const systems = await this.repository.getSystems();
|
||||
await Promise.all(systems.map(async (system) => {
|
||||
await this.fetchAndUpdateRouteDataForSystemId(system.id);
|
||||
}));
|
||||
}
|
||||
|
||||
public async fetchAndUpdateRouteDataForSystemId(systemId: string) {
|
||||
public async fetchAndUpdateRouteDataForSystem() {
|
||||
const systemId = this.passioSystemId;
|
||||
const routeIdsToPrune = await this.constructExistingEntityIdSet(async () => {
|
||||
return await this.repository.getRoutesBySystemId(systemId);
|
||||
return await this.repository.getRoutes();
|
||||
});
|
||||
|
||||
const params = {
|
||||
@@ -114,7 +66,7 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
color: jsonRoute.color,
|
||||
id: jsonRoute.myid,
|
||||
polylineCoordinates: [],
|
||||
systemId: systemId,
|
||||
systemId: this.systemIdForConstructedData,
|
||||
};
|
||||
|
||||
await this.repository.addOrUpdateRoute(constructedRoute);
|
||||
@@ -131,18 +83,13 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
}
|
||||
}
|
||||
|
||||
public async fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository() {
|
||||
const systems = await this.repository.getSystems();
|
||||
await Promise.all(systems.map(async (system: ISystem) => {
|
||||
await this.fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId(system.id);
|
||||
}));
|
||||
}
|
||||
public async fetchAndUpdateStopAndPolylineDataForRoutesInSystem() {
|
||||
const passioSystemId = this.passioSystemId;
|
||||
|
||||
public async fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId(systemId: string) {
|
||||
// Fetch from the API
|
||||
// Pass JSON output into two different methods to update repository
|
||||
const stopIdsToPrune = await this.constructExistingEntityIdSet(async () => {
|
||||
return await this.repository.getStopsBySystemId(systemId);
|
||||
return await this.repository.getStops();
|
||||
});
|
||||
|
||||
const params = {
|
||||
@@ -150,7 +97,7 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
};
|
||||
|
||||
const formDataJsonObject = {
|
||||
"s0": systemId,
|
||||
"s0": passioSystemId,
|
||||
"sA": 1
|
||||
};
|
||||
const formData = new FormData();
|
||||
@@ -165,7 +112,7 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
});
|
||||
const json = await response.json();
|
||||
|
||||
await this.updateStopDataForSystemAndApiResponse(systemId, json, stopIdsToPrune);
|
||||
await this.updateStopDataForSystemAndApiResponse(json, stopIdsToPrune);
|
||||
await this.updateOrderedStopDataForExistingStops(json);
|
||||
await this.updatePolylineDataForExistingRoutesAndApiResponse(json);
|
||||
|
||||
@@ -177,17 +124,10 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
}
|
||||
}
|
||||
|
||||
public async fetchAndUpdateShuttleDataForExistingSystemsInRepository() {
|
||||
const systems = await this.repository.getSystems();
|
||||
await Promise.all(systems.map(async (system: ISystem) => {
|
||||
const systemId = system.id;
|
||||
await this.fetchAndUpdateShuttleDataForSystemId(systemId);
|
||||
}));
|
||||
}
|
||||
|
||||
public async fetchAndUpdateShuttleDataForSystemId(systemId: string) {
|
||||
public async fetchAndUpdateShuttleDataForSystem() {
|
||||
const systemId = this.passioSystemId;
|
||||
const shuttleIdsToPrune = await this.constructExistingEntityIdSet(async () => {
|
||||
return await this.repository.getShuttlesBySystemId(systemId);
|
||||
return await this.repository.getShuttles();
|
||||
});
|
||||
|
||||
const params = {
|
||||
@@ -224,7 +164,7 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
longitude: parseFloat(jsonBus.longitude),
|
||||
},
|
||||
routeId: jsonBus.routeId,
|
||||
systemId: systemId,
|
||||
systemId: this.systemIdForConstructedData,
|
||||
id: `${jsonBus.busId}`,
|
||||
orientationInDegrees: parseFloat(jsonBus.calculatedCourse)
|
||||
}
|
||||
@@ -243,16 +183,8 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
}
|
||||
}
|
||||
|
||||
public async fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository() {
|
||||
const systems = await this.repository.getSystems()
|
||||
await Promise.all(systems.map(async (system: ISystem) => {
|
||||
const systemId = system.id;
|
||||
await this.fetchAndUpdateEtaDataForExistingStopsForSystemId(systemId);
|
||||
}))
|
||||
}
|
||||
|
||||
public async fetchAndUpdateEtaDataForExistingStopsForSystemId(systemId: string) {
|
||||
const stops = await this.repository.getStopsBySystemId(systemId);
|
||||
public async fetchAndUpdateEtaDataForExistingStopsForSystem() {
|
||||
const stops = await this.repository.getStops();
|
||||
await Promise.all(stops.map(async (stop) => {
|
||||
let stopId = stop.id;
|
||||
await this.fetchAndUpdateEtaDataForStopId(stopId);
|
||||
@@ -284,6 +216,7 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
shuttleId: `${shuttleId}`,
|
||||
stopId: stopId,
|
||||
millisecondsSinceEpoch: Date.now(),
|
||||
systemId: this.systemIdForConstructedData,
|
||||
};
|
||||
|
||||
this.repository.addOrUpdateEta(eta);
|
||||
@@ -295,7 +228,6 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
}
|
||||
|
||||
protected async updateStopDataForSystemAndApiResponse(
|
||||
systemId: string,
|
||||
json: any,
|
||||
setOfIdsToPrune: Set<string> = new Set(),
|
||||
) {
|
||||
@@ -306,7 +238,7 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
const constructedStop: IStop = {
|
||||
name: stop.name,
|
||||
id: stop.id,
|
||||
systemId,
|
||||
systemId: this.systemIdForConstructedData,
|
||||
coordinates: {
|
||||
latitude: parseFloat(stop.latitude),
|
||||
longitude: parseFloat(stop.longitude),
|
||||
@@ -341,6 +273,7 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
routeId,
|
||||
stopId,
|
||||
position: index + 1,
|
||||
systemId: this.systemIdForConstructedData,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -349,6 +282,7 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
routeId,
|
||||
stopId: jsonOrderedStopData[index - 1][1],
|
||||
position: index,
|
||||
systemId: this.systemIdForConstructedData,
|
||||
};
|
||||
}
|
||||
if (index < jsonOrderedStopData.length - 1) {
|
||||
@@ -356,6 +290,7 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
|
||||
routeId,
|
||||
stopId: jsonOrderedStopData[index + 1][1],
|
||||
position: index + 2,
|
||||
systemId: this.systemIdForConstructedData,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
export interface ShuttleRepositoryLoader {
|
||||
fetchAndUpdateSystemData(): Promise<void>;
|
||||
fetchAndUpdateRouteDataForExistingSystemsInRepository(): Promise<void>;
|
||||
fetchAndUpdateRouteDataForSystemId(systemId: string): Promise<void>;
|
||||
fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository(): Promise<void>;
|
||||
fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId(systemId: string): Promise<void>;
|
||||
fetchAndUpdateShuttleDataForExistingSystemsInRepository(): Promise<void>;
|
||||
fetchAndUpdateShuttleDataForSystemId(systemId: string): Promise<void>;
|
||||
fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository(): Promise<void>;
|
||||
fetchAndUpdateEtaDataForExistingStopsForSystemId(systemId: string): Promise<void>;
|
||||
fetchAndUpdateRouteDataForSystem(): Promise<void>;
|
||||
fetchAndUpdateStopAndPolylineDataForRoutesInSystem(): Promise<void>;
|
||||
fetchAndUpdateShuttleDataForSystem(): Promise<void>;
|
||||
fetchAndUpdateEtaDataForExistingStopsForSystem(): Promise<void>;
|
||||
fetchAndUpdateEtaDataForStopId(stopId: string): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -22,9 +22,11 @@ export class TimedApiBasedShuttleRepositoryLoader extends ApiBasedShuttleReposit
|
||||
readonly timeout = 10000;
|
||||
|
||||
constructor(
|
||||
public passioSystemId: string,
|
||||
public systemIdForConstructedData: string,
|
||||
repository: ShuttleGetterSetterRepository,
|
||||
) {
|
||||
super(repository);
|
||||
super(passioSystemId, systemIdForConstructedData, repository);
|
||||
this.startFetchDataAndUpdate = this.startFetchDataAndUpdate.bind(this);
|
||||
}
|
||||
|
||||
@@ -46,15 +48,14 @@ export class TimedApiBasedShuttleRepositoryLoader extends ApiBasedShuttleReposit
|
||||
if (!this.shouldBeRunning) return;
|
||||
|
||||
try {
|
||||
await this.fetchAndUpdateSystemData();
|
||||
await this.fetchAndUpdateRouteDataForExistingSystemsInRepository();
|
||||
await this.fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository();
|
||||
await this.fetchAndUpdateShuttleDataForExistingSystemsInRepository();
|
||||
await this.fetchAndUpdateRouteDataForSystem();
|
||||
await this.fetchAndUpdateStopAndPolylineDataForRoutesInSystem();
|
||||
await this.fetchAndUpdateShuttleDataForSystem();
|
||||
|
||||
// Because ETA method doesn't support pruning yet,
|
||||
// add a call to the clear method here
|
||||
await this.repository.clearEtaData();
|
||||
await this.fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository();
|
||||
await this.fetchAndUpdateEtaDataForExistingStopsForSystem();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// Mock data
|
||||
import { IEta, IOrderedStop, IRoute, IShuttle, IStop, ISystem } from "../entities/entities";
|
||||
import { IEta, IOrderedStop, IRoute, IShuttle, IStop, IPassioSystem } from "../entities/entities";
|
||||
import { ShuttleGetterSetterRepository } from "../repositories/ShuttleGetterSetterRepository";
|
||||
import { InterchangeSystemBuilderArguments } from "../entities/InterchangeSystem";
|
||||
|
||||
const systems: ISystem[] = [
|
||||
export const supportedIntegrationTestSystems: InterchangeSystemBuilderArguments[] = [
|
||||
{
|
||||
id: "1",
|
||||
name: "Chapman University",
|
||||
passioSystemId: "263",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -4327,14 +4329,14 @@ const routes: IRoute[] = [
|
||||
{
|
||||
name: "Red Route",
|
||||
id: "1",
|
||||
systemId: systems[0].id,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
polylineCoordinates: redRoutePolylineCoordinates,
|
||||
color: "#db2316",
|
||||
},
|
||||
{
|
||||
name: "Teal Route",
|
||||
id: "2",
|
||||
systemId: systems[0].id,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
polylineCoordinates: tealRoutePolylineCoordinates,
|
||||
color: "#21bdd1",
|
||||
},
|
||||
@@ -4348,7 +4350,7 @@ const stops: IStop[] = [
|
||||
latitude: 33.796001,
|
||||
longitude: -117.8892805,
|
||||
},
|
||||
systemId: systems[0].id,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
@@ -4357,7 +4359,7 @@ const stops: IStop[] = [
|
||||
latitude: 33.804433,
|
||||
longitude: -117.895966,
|
||||
},
|
||||
systemId: systems[0].id,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
@@ -4366,7 +4368,7 @@ const stops: IStop[] = [
|
||||
"latitude": 33.793325,
|
||||
"longitude": -117.85281
|
||||
},
|
||||
systemId: systems[0].id,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
}
|
||||
];
|
||||
|
||||
@@ -4375,11 +4377,13 @@ const orderedStopsForRedRoute: IOrderedStop[] = [
|
||||
routeId: routes[0].id,
|
||||
stopId: stops[0].id,
|
||||
position: 1,
|
||||
systemId: "1",
|
||||
},
|
||||
{
|
||||
routeId: routes[0].id,
|
||||
stopId: stops[2].id,
|
||||
position: 2,
|
||||
systemId: "1",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -4388,16 +4392,19 @@ const orderedStopsForTealRoute: IOrderedStop[] = [
|
||||
routeId: routes[1].id,
|
||||
stopId: stops[0].id,
|
||||
position: 1,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
},
|
||||
{
|
||||
routeId: routes[1].id,
|
||||
stopId: stops[1].id,
|
||||
position: 2,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
},
|
||||
{
|
||||
routeId: routes[1].id,
|
||||
stopId: stops[2].id,
|
||||
position: 2,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -4415,7 +4422,7 @@ const shuttles: IShuttle[] = [
|
||||
longitude: -117.883698,
|
||||
},
|
||||
routeId: routes[0].id,
|
||||
systemId: systems[0].id,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
orientationInDegrees: 45.91,
|
||||
},
|
||||
{
|
||||
@@ -4426,7 +4433,7 @@ const shuttles: IShuttle[] = [
|
||||
longitude: -117.862825,
|
||||
},
|
||||
routeId: routes[0].id,
|
||||
systemId: systems[0].id,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
orientationInDegrees: 90.24,
|
||||
}
|
||||
];
|
||||
@@ -4436,28 +4443,29 @@ const etas: IEta[] = [
|
||||
stopId: stops[0].id,
|
||||
shuttleId: shuttles[0].id,
|
||||
secondsRemaining: 12.023,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
},
|
||||
{
|
||||
stopId: stops[2].id,
|
||||
shuttleId: shuttles[0].id,
|
||||
secondsRemaining: 600.123,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
},
|
||||
{
|
||||
stopId: stops[2].id,
|
||||
shuttleId: shuttles[1].id,
|
||||
secondsRemaining: 172.015,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
},
|
||||
{
|
||||
stopId: stops[0].id,
|
||||
shuttleId: shuttles[1].id,
|
||||
secondsRemaining: 710.152,
|
||||
systemId: supportedIntegrationTestSystems[0].id,
|
||||
}
|
||||
];
|
||||
|
||||
export async function loadShuttleTestData(repository: ShuttleGetterSetterRepository) {
|
||||
await Promise.all(systems.map(async (system) => {
|
||||
await repository.addOrUpdateSystem(system);
|
||||
}));
|
||||
await Promise.all(routes.map(async (route) => {
|
||||
await repository.addOrUpdateRoute(route);
|
||||
}));
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { IEta, IOrderedStop, IRoute, IShuttle, IStop, ISystem } from "../entities/entities";
|
||||
import { IEta, IOrderedStop, IRoute, IShuttle, IStop } from "../entities/entities";
|
||||
|
||||
/**
|
||||
* Shuttle getter repository to be linked to a system.
|
||||
*/
|
||||
export interface ShuttleGetterRepository {
|
||||
getSystems(): Promise<ISystem[]>;
|
||||
getSystemById(systemId: string): Promise<ISystem | null>;
|
||||
|
||||
getStopsBySystemId(systemId: string): Promise<IStop[]>;
|
||||
getStops(): Promise<IStop[]>;
|
||||
getStopById(stopId: string): Promise<IStop | null>;
|
||||
|
||||
getRoutesBySystemId(systemId: string): Promise<IRoute[]>;
|
||||
getRoutes(): Promise<IRoute[]>;
|
||||
getRouteById(routeId: string): Promise<IRoute | null>;
|
||||
|
||||
getShuttlesBySystemId(systemId: string): Promise<IShuttle[]>;
|
||||
getShuttles(): Promise<IShuttle[]>;
|
||||
getShuttleById(shuttleId: string): Promise<IShuttle | null>;
|
||||
getShuttlesByRouteId(routeId: string): Promise<IShuttle[]>;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// to convert from data repo to GraphQL schema
|
||||
|
||||
import { ShuttleGetterRepository } from "./ShuttleGetterRepository";
|
||||
import { IEta, IOrderedStop, IRoute, IShuttle, IStop, ISystem } from "../entities/entities";
|
||||
import { IEta, IOrderedStop, IRoute, IShuttle, IStop } from "../entities/entities";
|
||||
|
||||
/**
|
||||
* ShuttleGetterRepository interface for data derived from Passio API.
|
||||
@@ -12,21 +12,18 @@ import { IEta, IOrderedStop, IRoute, IShuttle, IStop, ISystem } from "../entitie
|
||||
*/
|
||||
export interface ShuttleGetterSetterRepository extends ShuttleGetterRepository {
|
||||
// Setter methods
|
||||
addOrUpdateSystem(system: ISystem): Promise<void>;
|
||||
addOrUpdateRoute(route: IRoute): Promise<void>;
|
||||
addOrUpdateShuttle(shuttle: IShuttle): Promise<void>;
|
||||
addOrUpdateStop(stop: IStop): Promise<void>;
|
||||
addOrUpdateOrderedStop(orderedStop: IOrderedStop): Promise<void>;
|
||||
addOrUpdateEta(eta: IEta): Promise<void>;
|
||||
|
||||
removeSystemIfExists(systemId: string): Promise<ISystem | null>;
|
||||
removeRouteIfExists(routeId: string): Promise<IRoute | null>;
|
||||
removeShuttleIfExists(shuttleId: string): Promise<IShuttle | null>;
|
||||
removeStopIfExists(stopId: string): Promise<IStop | null>;
|
||||
removeOrderedStopIfExists(stopId: string, routeId: string): Promise<IOrderedStop | null>;
|
||||
removeEtaIfExists(shuttleId: string, stopId: string): Promise<IEta | null>;
|
||||
|
||||
clearSystemData(): Promise<void>;
|
||||
clearRouteData(): Promise<void>;
|
||||
clearShuttleData(): Promise<void>;
|
||||
clearStopData(): Promise<void>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ShuttleGetterSetterRepository } from "./ShuttleGetterSetterRepository";
|
||||
import { IEntityWithId, IEta, IOrderedStop, IRoute, IShuttle, IStop, ISystem } from "../entities/entities";
|
||||
import { IEntityWithId, IEta, IOrderedStop, IRoute, IShuttle, IStop } from "../entities/entities";
|
||||
|
||||
/**
|
||||
* An unoptimized in memory repository.
|
||||
@@ -7,7 +7,6 @@ import { IEntityWithId, IEta, IOrderedStop, IRoute, IShuttle, IStop, ISystem } f
|
||||
* switching to another data store later anyways)
|
||||
*/
|
||||
export class UnoptimizedInMemoryShuttleRepository implements ShuttleGetterSetterRepository {
|
||||
private systems: ISystem[] = [];
|
||||
private stops: IStop[] = [];
|
||||
private routes: IRoute[] = [];
|
||||
private shuttles: IShuttle[] = [];
|
||||
@@ -16,32 +15,24 @@ export class UnoptimizedInMemoryShuttleRepository implements ShuttleGetterSetter
|
||||
|
||||
private subscribers: ((eta: IEta) => void)[] = [];
|
||||
|
||||
public async getSystems() {
|
||||
return this.systems;
|
||||
}
|
||||
|
||||
public async getSystemById(systemId: string) {
|
||||
return this.findEntityById(systemId, this.systems);
|
||||
}
|
||||
|
||||
public async getStopsBySystemId(systemId: string) {
|
||||
return this.stops.filter(stop => stop.systemId === systemId);
|
||||
public async getStops(): Promise<IStop[]> {
|
||||
return this.stops;
|
||||
}
|
||||
|
||||
public async getStopById(stopId: string) {
|
||||
return this.findEntityById(stopId, this.stops);
|
||||
}
|
||||
|
||||
public async getRoutesBySystemId(systemId: string) {
|
||||
return this.routes.filter(route => route.systemId === systemId);
|
||||
public async getRoutes(): Promise<IRoute[]> {
|
||||
return this.routes;
|
||||
}
|
||||
|
||||
public async getRouteById(routeId: string) {
|
||||
return this.findEntityById(routeId, this.routes);
|
||||
}
|
||||
|
||||
public async getShuttlesBySystemId(systemId: string) {
|
||||
return this.shuttles.filter(shuttle => shuttle.systemId === systemId);
|
||||
public async getShuttles(): Promise<IShuttle[]> {
|
||||
return this.shuttles;
|
||||
}
|
||||
|
||||
public async getShuttlesByRouteId(routeId: string) {
|
||||
@@ -52,7 +43,7 @@ export class UnoptimizedInMemoryShuttleRepository implements ShuttleGetterSetter
|
||||
return this.findEntityById(shuttleId, this.shuttles);
|
||||
}
|
||||
|
||||
public async getEtasForShuttleId(shuttleId: string) {
|
||||
public async getEtasForShuttleId(shuttleId: string): Promise<IEta[]> {
|
||||
return this.etas.filter(eta => eta.shuttleId === shuttleId);
|
||||
}
|
||||
|
||||
@@ -99,15 +90,6 @@ export class UnoptimizedInMemoryShuttleRepository implements ShuttleGetterSetter
|
||||
return entity;
|
||||
}
|
||||
|
||||
public async addOrUpdateSystem(system: ISystem): Promise<void> {
|
||||
const index = this.systems.findIndex((s) => s.id === system.id);
|
||||
if (index !== -1) {
|
||||
this.systems[index] = system; // Update existing
|
||||
} else {
|
||||
this.systems.push(system); // Add new
|
||||
}
|
||||
}
|
||||
|
||||
public async addOrUpdateRoute(route: IRoute): Promise<void> {
|
||||
const index = this.routes.findIndex((r) => r.id === route.id);
|
||||
if (index !== -1) {
|
||||
@@ -175,10 +157,6 @@ export class UnoptimizedInMemoryShuttleRepository implements ShuttleGetterSetter
|
||||
return await this.removeEntityByMatcherIfExists((value) => value.id === entityId, arrayToSearchIn);
|
||||
}
|
||||
|
||||
public async removeSystemIfExists(systemId: string): Promise<ISystem | null> {
|
||||
return await this.removeEntityByIdIfExists(systemId, this.systems);
|
||||
}
|
||||
|
||||
public async removeRouteIfExists(routeId: string): Promise<IRoute | null> {
|
||||
return await this.removeEntityByIdIfExists(routeId, this.routes);
|
||||
}
|
||||
@@ -205,10 +183,6 @@ export class UnoptimizedInMemoryShuttleRepository implements ShuttleGetterSetter
|
||||
}, this.etas);
|
||||
}
|
||||
|
||||
public async clearSystemData() {
|
||||
this.systems = [];
|
||||
}
|
||||
|
||||
public async clearShuttleData(): Promise<void> {
|
||||
this.shuttles = [];
|
||||
}
|
||||
|
||||
@@ -4,10 +4,16 @@ import { ServerContext } from "../ServerContext";
|
||||
export const EtaResolvers: Resolvers<ServerContext> = {
|
||||
ETA: {
|
||||
stop: async (parent, args, contextValue, info) => {
|
||||
return await contextValue.shuttleRepository.getStopById(parent.stopId);
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) return null;
|
||||
|
||||
return await system.shuttleRepository.getStopById(parent.stopId);
|
||||
},
|
||||
shuttle: async (parent, args, contextValue, info) => {
|
||||
return await contextValue.shuttleRepository.getShuttleById(parent.shuttleId);
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) return null;
|
||||
|
||||
return await system.shuttleRepository.getShuttleById(parent.shuttleId);
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,21 +1,47 @@
|
||||
import { NotificationResponse, Resolvers } from "../generated/graphql";
|
||||
import { MutationScheduleNotificationArgs, NotificationResponse, Resolvers } from "../generated/graphql";
|
||||
import { ServerContext } from "../ServerContext";
|
||||
import {
|
||||
ETANotificationScheduler,
|
||||
} from "../notifications/schedulers/ETANotificationScheduler";
|
||||
import { ScheduledNotification } from "../repositories/NotificationRepository";
|
||||
import { InterchangeSystem } from "../entities/InterchangeSystem";
|
||||
|
||||
async function temp_findMatchingSystemBasedOnShuttleId(context: ServerContext, args: Omit<MutationScheduleNotificationArgs, "input"> & {
|
||||
input: NonNullable<MutationScheduleNotificationArgs["input"]>
|
||||
}) {
|
||||
let matchingSystem: InterchangeSystem | undefined;
|
||||
await Promise.all(context.systems.map(async (system) => {
|
||||
const shuttle = await system.shuttleRepository.getShuttleById(args.input.shuttleId);
|
||||
// Theoretically, there should only be one
|
||||
if (shuttle !== null) {
|
||||
matchingSystem = system;
|
||||
}
|
||||
return shuttle;
|
||||
}));
|
||||
return matchingSystem;
|
||||
}
|
||||
|
||||
export const MutationResolvers: Resolvers<ServerContext> = {
|
||||
// TODO: Require system ID on these endpoints
|
||||
Mutation: {
|
||||
scheduleNotification: async (_parent, args, context, _info) => {
|
||||
const shuttle = await context.shuttleRepository.getShuttleById(args.input.shuttleId);
|
||||
let matchingSystem = await temp_findMatchingSystemBasedOnShuttleId(context, args);
|
||||
|
||||
if (!matchingSystem) {
|
||||
return {
|
||||
message: "Shuttle ID doesn't exist",
|
||||
success: false,
|
||||
}
|
||||
}
|
||||
|
||||
const shuttle = await matchingSystem.shuttleRepository.getShuttleById(args.input.shuttleId);
|
||||
if (!shuttle) {
|
||||
return {
|
||||
message: "Shuttle ID doesn't exist",
|
||||
success: false,
|
||||
}
|
||||
}
|
||||
const stop = await context.shuttleRepository.getStopById(args.input.stopId);
|
||||
const stop = await matchingSystem.shuttleRepository.getStopById(args.input.stopId);
|
||||
if (!stop) {
|
||||
return {
|
||||
message: "Stop ID doesn't exist",
|
||||
@@ -30,7 +56,7 @@ export const MutationResolvers: Resolvers<ServerContext> = {
|
||||
: ETANotificationScheduler.defaultSecondsThresholdForNotificationToFire,
|
||||
}
|
||||
|
||||
await context.notificationRepository.addOrUpdateNotification(notificationData);
|
||||
await matchingSystem.notificationRepository.addOrUpdateNotification(notificationData);
|
||||
|
||||
const response: NotificationResponse = {
|
||||
message: "Notification scheduled",
|
||||
@@ -40,9 +66,18 @@ export const MutationResolvers: Resolvers<ServerContext> = {
|
||||
return response;
|
||||
},
|
||||
cancelNotification: async (_parent, args, context, _info) => {
|
||||
const isScheduled = await context.notificationRepository.isNotificationScheduled(args.input)
|
||||
const matchingSystem = await temp_findMatchingSystemBasedOnShuttleId(context, args);
|
||||
if (!matchingSystem) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Unable to find correct system",
|
||||
data: args.input,
|
||||
}
|
||||
}
|
||||
|
||||
const isScheduled = await matchingSystem.notificationRepository.isNotificationScheduled(args.input)
|
||||
if (isScheduled) {
|
||||
await context.notificationRepository.deleteNotificationIfExists(args.input);
|
||||
await matchingSystem.notificationRepository.deleteNotificationIfExists(args.input);
|
||||
return {
|
||||
success: true,
|
||||
message: "Notification cancelled",
|
||||
|
||||
@@ -3,49 +3,63 @@ import { ServerContext } from "../ServerContext";
|
||||
|
||||
export const OrderedStopResolvers: Resolvers<ServerContext> = {
|
||||
OrderedStop: {
|
||||
nextStop: async (parent, args, contextValue, info): Promise<OrderedStop | null> => {
|
||||
nextStop: async (parent, args, contextValue, _info): Promise<OrderedStop | null> => {
|
||||
const routeId = parent.routeId;
|
||||
const stopId = parent.stopId;
|
||||
|
||||
const currentOrderedStop = await contextValue.shuttleRepository.getOrderedStopByRouteAndStopId(routeId, stopId);
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) return null;
|
||||
|
||||
const currentOrderedStop = await system.shuttleRepository.getOrderedStopByRouteAndStopId(routeId, stopId);
|
||||
if (!currentOrderedStop) return null;
|
||||
|
||||
const nextOrderedStop = currentOrderedStop.nextStop;
|
||||
if (!nextOrderedStop) return null;
|
||||
|
||||
const nextOrderedStopObject = await contextValue.shuttleRepository.getStopById(nextOrderedStop.stopId);
|
||||
const nextOrderedStopObject = await system.shuttleRepository.getStopById(nextOrderedStop.stopId);
|
||||
if (!nextOrderedStopObject) return null;
|
||||
|
||||
return {
|
||||
route: parent.route,
|
||||
routeId: parent.routeId,
|
||||
stopId: nextOrderedStopObject.id,
|
||||
systemId: system.id,
|
||||
}
|
||||
},
|
||||
previousStop: async (parent, args, contextValue, info): Promise<OrderedStop | null> => {
|
||||
previousStop: async (parent, args, contextValue, _info): Promise<OrderedStop | null> => {
|
||||
const routeId = parent.routeId;
|
||||
const stopId = parent.stopId;
|
||||
|
||||
const currentOrderedStop = await contextValue.shuttleRepository.getOrderedStopByRouteAndStopId(routeId, stopId);
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) return null;
|
||||
|
||||
const currentOrderedStop = await system.shuttleRepository.getOrderedStopByRouteAndStopId(routeId, stopId);
|
||||
if (!currentOrderedStop) return null;
|
||||
|
||||
const previousOrderedStop = currentOrderedStop.previousStop;
|
||||
if (!previousOrderedStop) return null;
|
||||
|
||||
const previousOrderedStopObject = await contextValue.shuttleRepository.getStopById(previousOrderedStop.stopId);
|
||||
const previousOrderedStopObject = await system.shuttleRepository.getStopById(previousOrderedStop.stopId);
|
||||
if (!previousOrderedStopObject) return null;
|
||||
|
||||
return {
|
||||
route: parent.route,
|
||||
routeId: parent.routeId,
|
||||
stopId: previousOrderedStopObject.id,
|
||||
systemId: system.id,
|
||||
}
|
||||
},
|
||||
stop: async (parent, args, contextValue, info) => {
|
||||
return await contextValue.shuttleRepository.getStopById(parent.stopId);
|
||||
stop: async (parent, args, contextValue, _info) => {
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) return null;
|
||||
|
||||
return await system.shuttleRepository.getStopById(parent.stopId);
|
||||
},
|
||||
route: async (parent, args, contextValue, info) => {
|
||||
return await contextValue.shuttleRepository.getRouteById(parent.routeId);
|
||||
route: async (parent, args, contextValue, _info) => {
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) return null;
|
||||
|
||||
return await system.shuttleRepository.getRouteById(parent.routeId);
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -4,11 +4,16 @@ import { Resolvers } from "../generated/graphql";
|
||||
export const QueryResolvers: Resolvers<ServerContext> = {
|
||||
Query: {
|
||||
systems: async (_parent, args, contextValue, _info) => {
|
||||
return await contextValue.shuttleRepository.getSystems();
|
||||
return contextValue.systems.map((system) => {
|
||||
return {
|
||||
name: system.name,
|
||||
id: system.id,
|
||||
};
|
||||
})
|
||||
},
|
||||
system: async (_parent, args, contextValue, _info) => {
|
||||
if (!args.id) return null;
|
||||
const system = await contextValue.shuttleRepository.getSystemById(args.id);
|
||||
const system = contextValue.findSystemById(args.id);
|
||||
if (system === null) return null;
|
||||
|
||||
return {
|
||||
@@ -16,13 +21,30 @@ export const QueryResolvers: Resolvers<ServerContext> = {
|
||||
id: system.id,
|
||||
};
|
||||
},
|
||||
// TODO: Update the GraphQL schema to require a system ID
|
||||
isNotificationScheduled: async (_parent, args, contextValue, _info) => {
|
||||
const notificationData = args.input;
|
||||
return await contextValue.notificationRepository.isNotificationScheduled(notificationData);
|
||||
|
||||
for (let system of contextValue.systems) {
|
||||
const isScheduled = await system.notificationRepository.isNotificationScheduled(notificationData);
|
||||
if (isScheduled) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
secondsThresholdForNotification: async (_parent, args, contextValue, _info) => {
|
||||
const notificationData = args.input;
|
||||
return await contextValue.notificationRepository.getSecondsThresholdForNotificationIfExists(notificationData);
|
||||
|
||||
for (let system of contextValue.systems) {
|
||||
const isScheduled = await system.notificationRepository.isNotificationScheduled(notificationData);
|
||||
if (isScheduled) {
|
||||
return await system.notificationRepository.getSecondsThresholdForNotificationIfExists(args.input);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@ import { ServerContext } from "../ServerContext";
|
||||
export const RouteResolvers: Resolvers<ServerContext> = {
|
||||
Route: {
|
||||
shuttles: async (parent, args, contextValue, info) => {
|
||||
const shuttles = await contextValue.shuttleRepository.getShuttlesByRouteId(parent.id);
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) return null;
|
||||
|
||||
const shuttles = await system.shuttleRepository.getShuttlesByRouteId(parent.id);
|
||||
|
||||
return shuttles.map(({
|
||||
coordinates,
|
||||
@@ -17,21 +20,27 @@ export const RouteResolvers: Resolvers<ServerContext> = {
|
||||
route: parent,
|
||||
routeId: parent.id,
|
||||
id,
|
||||
orientationInDegrees
|
||||
orientationInDegrees,
|
||||
systemId: parent.systemId,
|
||||
}));
|
||||
},
|
||||
orderedStop: async (parent, args, contextValue, info) => {
|
||||
if (!args.forStopId) return null;
|
||||
const orderedStop = await contextValue.shuttleRepository.getOrderedStopByRouteAndStopId(parent.id, args.forStopId);
|
||||
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) return null;
|
||||
|
||||
const orderedStop = await system.shuttleRepository.getOrderedStopByRouteAndStopId(parent.id, args.forStopId);
|
||||
if (!orderedStop) return null;
|
||||
|
||||
const stop = await contextValue.shuttleRepository.getStopById(orderedStop.stopId);
|
||||
const stop = await system.shuttleRepository.getStopById(orderedStop.stopId);
|
||||
if (!stop) return null;
|
||||
|
||||
return {
|
||||
stopId: args.forStopId,
|
||||
routeId: parent.id,
|
||||
route: parent,
|
||||
systemId: system.id,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -5,7 +5,11 @@ export const ShuttleResolvers: Resolvers<ServerContext> = {
|
||||
Shuttle: {
|
||||
eta: async (parent, args, contextValue, info) => {
|
||||
if (!args.forStopId) return null;
|
||||
const etaForStopId = await contextValue.shuttleRepository.getEtaForShuttleAndStopId(parent.id, args.forStopId);
|
||||
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) return null;
|
||||
|
||||
const etaForStopId = await system.shuttleRepository.getEtaForShuttleAndStopId(parent.id, args.forStopId);
|
||||
if (etaForStopId === null) return null;
|
||||
|
||||
return {
|
||||
@@ -13,10 +17,14 @@ export const ShuttleResolvers: Resolvers<ServerContext> = {
|
||||
secondsRemaining: etaForStopId.secondsRemaining,
|
||||
shuttleId: parent.id,
|
||||
shuttle: parent,
|
||||
systemId: system.id,
|
||||
};
|
||||
},
|
||||
etas: async (parent, args, contextValue, info) => {
|
||||
const etasForShuttle = await contextValue.shuttleRepository.getEtasForShuttleId(parent.id);
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) return null;
|
||||
|
||||
const etasForShuttle = await system.shuttleRepository.getEtasForShuttleId(parent.id);
|
||||
if (!etasForShuttle) return null;
|
||||
|
||||
const computedEtas = await Promise.all(etasForShuttle.map(async ({
|
||||
@@ -28,6 +36,7 @@ export const ShuttleResolvers: Resolvers<ServerContext> = {
|
||||
stopId,
|
||||
shuttle: parent,
|
||||
shuttleId: parent.id,
|
||||
systemId: system.id,
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -38,7 +47,10 @@ export const ShuttleResolvers: Resolvers<ServerContext> = {
|
||||
return [];
|
||||
},
|
||||
route: async (parent, args, contextValue, info) => {
|
||||
const route = await contextValue.shuttleRepository.getRouteById(parent.routeId);
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) return null;
|
||||
|
||||
const route = await system.shuttleRepository.getRouteById(parent.routeId);
|
||||
if (route === null) return null;
|
||||
|
||||
return {
|
||||
@@ -46,6 +58,7 @@ export const ShuttleResolvers: Resolvers<ServerContext> = {
|
||||
id: route.id,
|
||||
name: route.name,
|
||||
polylineCoordinates: route.polylineCoordinates,
|
||||
systemId: system.id,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -3,11 +3,19 @@ import { ServerContext } from "../ServerContext";
|
||||
|
||||
export const StopResolvers: Resolvers<ServerContext> = {
|
||||
Stop: {
|
||||
orderedStops: async (parent, args, contextValue, info) => {
|
||||
return await contextValue.shuttleRepository.getOrderedStopsByStopId(parent.id);
|
||||
orderedStops: async (parent, args, contextValue, _info) => {
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) {
|
||||
return [];
|
||||
}
|
||||
return await system.shuttleRepository.getOrderedStopsByStopId(parent.id);
|
||||
},
|
||||
etas: async (parent, args, contextValue, info) => {
|
||||
return await contextValue.shuttleRepository.getEtasForStopId(parent.id);
|
||||
etas: async (parent, args, contextValue, _info) => {
|
||||
const system = contextValue.findSystemById(parent.systemId);
|
||||
if (!system) {
|
||||
return [];
|
||||
}
|
||||
return await system.shuttleRepository.getEtasForStopId(parent.id);
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -3,15 +3,30 @@ import { ServerContext } from "../ServerContext";
|
||||
|
||||
export const SystemResolvers: Resolvers<ServerContext> = {
|
||||
System: {
|
||||
routes: async (parent, args, contextValue, info) => {
|
||||
return await contextValue.shuttleRepository.getRoutesBySystemId(parent.id);
|
||||
routes: async (parent, _args, contextValue, _info) => {
|
||||
const system = contextValue.findSystemById(parent.id);
|
||||
if (!system) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return await system.shuttleRepository.getRoutes();
|
||||
},
|
||||
stops: async (parent, args, contextValue, info) => {
|
||||
return await contextValue.shuttleRepository.getStopsBySystemId(parent.id);
|
||||
stops: async (parent, _args, contextValue, _info) => {
|
||||
const system = contextValue.findSystemById(parent.id);
|
||||
if (!system) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return await system.shuttleRepository.getStops();
|
||||
},
|
||||
stop: async (parent, args, contextValue, info) => {
|
||||
stop: async (parent, args, contextValue, _info) => {
|
||||
if (!args.id) return null;
|
||||
const stop = await contextValue.shuttleRepository.getStopById(args.id);
|
||||
const system = contextValue.findSystemById(parent.id);
|
||||
if (!system) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const stop = await system.shuttleRepository.getStopById(args.id);
|
||||
if (stop === null) return null;
|
||||
|
||||
if (stop.systemId !== parent.id) return null;
|
||||
@@ -20,11 +35,16 @@ export const SystemResolvers: Resolvers<ServerContext> = {
|
||||
id: stop.id,
|
||||
name: stop.name,
|
||||
coordinates: stop.coordinates as Coordinates,
|
||||
systemId: parent.id,
|
||||
};
|
||||
},
|
||||
route: async (parent, args, contextValue, info) => {
|
||||
route: async (parent, args, contextValue, _info) => {
|
||||
if (!args.id) return null;
|
||||
const route = await contextValue.shuttleRepository.getRouteById(args.id);
|
||||
const system = contextValue.findSystemById(parent.id);
|
||||
if (!system) {
|
||||
return null;
|
||||
}
|
||||
const route = await system.shuttleRepository.getRouteById(args.id);
|
||||
if (route === null) return null;
|
||||
|
||||
if (route.systemId !== parent.id) return null;
|
||||
@@ -34,19 +54,29 @@ export const SystemResolvers: Resolvers<ServerContext> = {
|
||||
id: route.id,
|
||||
name: route.name,
|
||||
polylineCoordinates: route.polylineCoordinates as Coordinates[],
|
||||
systemId: parent.id,
|
||||
};
|
||||
},
|
||||
shuttle: async (parent, args, contextValue, info) => {
|
||||
shuttle: async (parent, args, contextValue, _info) => {
|
||||
if (!args.id) return null;
|
||||
const shuttle = await contextValue.shuttleRepository.getShuttleById(args.id);
|
||||
const system = contextValue.findSystemById(parent.id);
|
||||
if (!system) {
|
||||
return null;
|
||||
}
|
||||
const shuttle = await system.shuttleRepository.getShuttleById(args.id);
|
||||
if (shuttle === null) return null;
|
||||
|
||||
if (shuttle.systemId !== parent.id) return null;
|
||||
|
||||
return shuttle;
|
||||
},
|
||||
shuttles: async (parent, args, contextValue, info) => {
|
||||
return await contextValue.shuttleRepository.getShuttlesBySystemId(parent.id);
|
||||
shuttles: async (parent, args, contextValue, _info) => {
|
||||
const system = contextValue.findSystemById(parent.id);
|
||||
if (!system) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return await system.shuttleRepository.getShuttles();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import { beforeEach, describe, expect, it, jest, test } from "@jest/globals";
|
||||
import { beforeEach, describe, expect, it, jest } 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, generateMockSystems } from "../testHelpers/mockDataGenerators";
|
||||
import { generateMockRoutes, generateMockShuttles, generateMockStops } from "../testHelpers/mockDataGenerators";
|
||||
import {
|
||||
fetchShuttleDataSuccessfulResponse
|
||||
} from "../jsonSnapshots/fetchShuttleData/fetchShuttleDataSuccessfulResponse";
|
||||
@@ -26,69 +24,12 @@ describe("ApiBasedRepositoryLoader", () => {
|
||||
let loader: ApiBasedShuttleRepositoryLoader;
|
||||
|
||||
beforeEach(() => {
|
||||
loader = new ApiBasedShuttleRepositoryLoader(new UnoptimizedInMemoryShuttleRepository());
|
||||
loader = new ApiBasedShuttleRepositoryLoader("263", "1", new UnoptimizedInMemoryShuttleRepository());
|
||||
resetGlobalFetchMockJson();
|
||||
});
|
||||
|
||||
describe("fetchAndUpdateSystemData", () => {
|
||||
it("updates system data in repository if response received", async () => {
|
||||
// Arrange
|
||||
const systemsToPrune = generateMockSystems();
|
||||
await Promise.all(systemsToPrune.map(async (system) => {
|
||||
await loader.repository.addOrUpdateSystem(system);
|
||||
}));
|
||||
|
||||
const numberOfSystemsInResponse = fetchSystemDataSuccessfulResponse.all.length;
|
||||
updateGlobalFetchMockJson(fetchSystemDataSuccessfulResponse);
|
||||
|
||||
// Act
|
||||
await loader.fetchAndUpdateSystemData();
|
||||
|
||||
// Assert
|
||||
const systems = await loader.repository.getSystems();
|
||||
if (loader.supportedSystemIds.length < numberOfSystemsInResponse) {
|
||||
expect(systems).toHaveLength(loader.supportedSystemIds.length);
|
||||
} else {
|
||||
expect(systems).toHaveLength(numberOfSystemsInResponse);
|
||||
}
|
||||
});
|
||||
|
||||
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 all systems in repository", async () => {
|
||||
const spy = jest.spyOn(loader, "fetchAndUpdateRouteDataForSystemId");
|
||||
|
||||
const systems = generateMockSystems();
|
||||
|
||||
await Promise.all(systems.map(async (system) => {
|
||||
await loader.repository.addOrUpdateSystem(system);
|
||||
}));
|
||||
|
||||
await loader.fetchAndUpdateRouteDataForExistingSystemsInRepository();
|
||||
|
||||
expect(spy.mock.calls.length).toBe(systems.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe("fetchAndUpdateRouteDataForSystemId", () => {
|
||||
const systemId = "263";
|
||||
const systemId = "1";
|
||||
describe("fetchAndUpdateRouteDataForSystem", () => {
|
||||
it("updates route data in repository if response received", async () => {
|
||||
// Arrange
|
||||
// Test pruning
|
||||
@@ -101,10 +42,10 @@ describe("ApiBasedRepositoryLoader", () => {
|
||||
updateGlobalFetchMockJson(fetchRouteDataSuccessfulResponse);
|
||||
|
||||
// Act
|
||||
await loader.fetchAndUpdateRouteDataForSystemId(systemId);
|
||||
await loader.fetchAndUpdateRouteDataForSystem();
|
||||
|
||||
// Assert
|
||||
const routes = await loader.repository.getRoutesBySystemId(systemId);
|
||||
const routes = await loader.repository.getRoutes();
|
||||
|
||||
expect(routes.length).toEqual(fetchRouteDataSuccessfulResponse.all.length)
|
||||
});
|
||||
@@ -116,29 +57,12 @@ describe("ApiBasedRepositoryLoader", () => {
|
||||
updateGlobalFetchMockJsonToThrowSyntaxError();
|
||||
|
||||
await assertAsyncCallbackThrowsApiResponseError(async () => {
|
||||
await loader.fetchAndUpdateRouteDataForSystemId(systemId);
|
||||
await loader.fetchAndUpdateRouteDataForSystem();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository", () => {
|
||||
it("calls fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId for every system", async () => {
|
||||
const spy = jest.spyOn(loader, "fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId");
|
||||
|
||||
const systems = generateMockSystems();
|
||||
|
||||
await Promise.all(systems.map(async (system) => {
|
||||
await loader.repository.addOrUpdateSystem(system);
|
||||
}));
|
||||
|
||||
await loader.fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository();
|
||||
|
||||
expect(spy.mock.calls.length).toBe(systems.length);
|
||||
});
|
||||
})
|
||||
|
||||
describe("fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId", () => {
|
||||
const systemId = "263";
|
||||
it("updates stop and polyline data if response received", async () => {
|
||||
// Arrange
|
||||
// Test pruning of stops only
|
||||
@@ -152,9 +76,9 @@ describe("ApiBasedRepositoryLoader", () => {
|
||||
|
||||
const stopsArray = Object.values(fetchStopAndPolylineDataSuccessfulResponse.stops);
|
||||
|
||||
await loader.fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId(systemId);
|
||||
await loader.fetchAndUpdateStopAndPolylineDataForRoutesInSystem();
|
||||
|
||||
const stops = await loader.repository.getStopsBySystemId(systemId);
|
||||
const stops = await loader.repository.getStops();
|
||||
expect(stops.length).toEqual(stopsArray.length);
|
||||
|
||||
await Promise.all(stops.map(async (stop) => {
|
||||
@@ -162,7 +86,7 @@ describe("ApiBasedRepositoryLoader", () => {
|
||||
expect(orderedStops.length).toBeGreaterThan(0);
|
||||
}));
|
||||
|
||||
const routes = await loader.repository.getRoutesBySystemId(systemId);
|
||||
const routes = await loader.repository.getRoutes();
|
||||
routes.forEach((route) => {
|
||||
expect(route.polylineCoordinates.length).toBeGreaterThan(0);
|
||||
});
|
||||
@@ -172,28 +96,12 @@ describe("ApiBasedRepositoryLoader", () => {
|
||||
updateGlobalFetchMockJsonToThrowSyntaxError();
|
||||
|
||||
await assertAsyncCallbackThrowsApiResponseError(async () => {
|
||||
await loader.fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId(systemId);
|
||||
await loader.fetchAndUpdateStopAndPolylineDataForRoutesInSystem();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe("fetchAndUpdateShuttleDataForExistingSystemsInRepository", () => {
|
||||
it("calls fetchAndUpdateShuttleDataForSystemId for every system", async () => {
|
||||
const spy = jest.spyOn(loader, "fetchAndUpdateShuttleDataForSystemId");
|
||||
|
||||
const systems = generateMockSystems();
|
||||
await Promise.all(systems.map(async (system) => {
|
||||
await loader.repository.addOrUpdateSystem(system);
|
||||
}))
|
||||
|
||||
await loader.fetchAndUpdateShuttleDataForExistingSystemsInRepository();
|
||||
|
||||
expect(spy.mock.calls.length).toBe(systems.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe("fetchAndUpdateShuttleDataForSystemId", () => {
|
||||
const systemId = "263";
|
||||
describe("fetchAndUpdateShuttleDataForSystem", () => {
|
||||
it("updates shuttle data in repository if response received", async () => {
|
||||
const shuttlesToPrune = generateMockShuttles();
|
||||
await Promise.all(shuttlesToPrune.map(async (shuttle) => {
|
||||
@@ -204,9 +112,9 @@ describe("ApiBasedRepositoryLoader", () => {
|
||||
updateGlobalFetchMockJson(fetchShuttleDataSuccessfulResponse);
|
||||
const busesInResponse = Object.values(fetchShuttleDataSuccessfulResponse.buses);
|
||||
|
||||
await loader.fetchAndUpdateShuttleDataForSystemId(systemId);
|
||||
await loader.fetchAndUpdateShuttleDataForSystem();
|
||||
|
||||
const shuttles = await loader.repository.getShuttlesBySystemId(systemId);
|
||||
const shuttles = await loader.repository.getShuttles();
|
||||
|
||||
expect(shuttles.length).toEqual(busesInResponse.length);
|
||||
});
|
||||
@@ -215,27 +123,12 @@ describe("ApiBasedRepositoryLoader", () => {
|
||||
updateGlobalFetchMockJsonToThrowSyntaxError();
|
||||
|
||||
await assertAsyncCallbackThrowsApiResponseError(async () => {
|
||||
await loader.fetchAndUpdateShuttleDataForSystemId(systemId);
|
||||
await loader.fetchAndUpdateShuttleDataForSystem();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository", () => {
|
||||
it("calls fetchAndUpdateEtaDataFoExistingStopsForSystemId for every system in repository", async () => {
|
||||
const spy = jest.spyOn(loader, "fetchAndUpdateEtaDataForExistingStopsForSystemId");
|
||||
|
||||
const systems = generateMockSystems();
|
||||
await Promise.all(systems.map(async (system) => {
|
||||
await loader.repository.addOrUpdateSystem(system);
|
||||
}));
|
||||
|
||||
await loader.fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository();
|
||||
|
||||
expect(spy.mock.calls.length).toBe(systems.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe("fetchAndUpdateEtaDataForExistingStopsForSystemId", () => {
|
||||
describe("fetchAndUpdateEtaDataForExistingStopsForSystem", () => {
|
||||
it("calls fetchAndUpdateEtaDataForStopId for every stop in repository", async () => {
|
||||
const spy = jest.spyOn(loader, "fetchAndUpdateEtaDataForStopId");
|
||||
|
||||
@@ -248,7 +141,7 @@ describe("ApiBasedRepositoryLoader", () => {
|
||||
await loader.repository.addOrUpdateStop(stop);
|
||||
}));
|
||||
|
||||
await loader.fetchAndUpdateEtaDataForExistingStopsForSystemId("1");
|
||||
await loader.fetchAndUpdateEtaDataForExistingStopsForSystem();
|
||||
|
||||
expect(spy.mock.calls.length).toEqual(stops.length);
|
||||
});
|
||||
|
||||
@@ -15,14 +15,17 @@ describe("TimedApiBasedRepositoryLoader", () => {
|
||||
beforeEach(() => {
|
||||
resetGlobalFetchMockJson();
|
||||
|
||||
loader = new TimedApiBasedShuttleRepositoryLoader(new UnoptimizedInMemoryShuttleRepository());
|
||||
loader = new TimedApiBasedShuttleRepositoryLoader(
|
||||
"1",
|
||||
"1",
|
||||
new UnoptimizedInMemoryShuttleRepository()
|
||||
);
|
||||
|
||||
spies = {
|
||||
fetchAndUpdateSystemData: jest.spyOn(loader, 'fetchAndUpdateSystemData'),
|
||||
fetchAndUpdateRouteDataForExistingSystemsInRepository: jest.spyOn(loader, 'fetchAndUpdateRouteDataForExistingSystemsInRepository'),
|
||||
fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository: jest.spyOn(loader, 'fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository'),
|
||||
fetchAndUpdateShuttleDataForExistingSystemsInRepository: jest.spyOn(loader, 'fetchAndUpdateShuttleDataForExistingSystemsInRepository'),
|
||||
fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository: jest.spyOn(loader, 'fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository')
|
||||
fetchAndUpdateRouteDataForSystem: jest.spyOn(loader, 'fetchAndUpdateRouteDataForSystem'),
|
||||
fetchAndUpdateStopAndPolylineDataForRoutesInSystem: jest.spyOn(loader, 'fetchAndUpdateStopAndPolylineDataForRoutesInSystem'),
|
||||
fetchAndUpdateShuttleDataForSystem: jest.spyOn(loader, 'fetchAndUpdateShuttleDataForSystem'),
|
||||
fetchAndUpdateEtaDataForExistingStopsForSystem: jest.spyOn(loader, 'fetchAndUpdateEtaDataForExistingStopsForSystem')
|
||||
};
|
||||
|
||||
Object.values(spies).forEach((spy: any) => {
|
||||
|
||||
@@ -50,6 +50,7 @@ describe("ETANotificationScheduler", () => {
|
||||
shuttleId: shuttle.id,
|
||||
stopId: stop.id,
|
||||
secondsRemaining: 120,
|
||||
systemId: "1",
|
||||
};
|
||||
|
||||
const notificationData1 = {
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
generateMockRoutes,
|
||||
generateMockShuttles,
|
||||
generateMockStops,
|
||||
generateMockSystems
|
||||
} from "../testHelpers/mockDataGenerators";
|
||||
|
||||
// For repositories created in the future, reuse core testing
|
||||
@@ -21,57 +20,19 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
repository = new UnoptimizedInMemoryShuttleRepository();
|
||||
});
|
||||
|
||||
describe("getSystems", () => {
|
||||
test("gets the systems stored in the repository", async () => {
|
||||
const mockSystems = generateMockSystems();
|
||||
for (const system of mockSystems) {
|
||||
await repository.addOrUpdateSystem(system);
|
||||
}
|
||||
|
||||
const result = await repository.getSystems();
|
||||
|
||||
expect(result).toEqual(mockSystems);
|
||||
});
|
||||
|
||||
test("gets an empty list if there are no systems stored", async () => {
|
||||
const result = await repository.getSystems();
|
||||
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getSystemById", () => {
|
||||
test("gets a system by the ID if it exists", async () => {
|
||||
const mockSystems = generateMockSystems();
|
||||
for (const system of mockSystems) {
|
||||
await repository.addOrUpdateSystem(system);
|
||||
}
|
||||
|
||||
const result = await repository.getSystemById("2");
|
||||
|
||||
expect(result).toEqual(mockSystems[1]); // Ensure it retrieves the correct system
|
||||
});
|
||||
|
||||
test("returns null if the system doesn't exist", async () => {
|
||||
const result = await repository.getSystemById("nonexistent-id");
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getStopsBySystemId", () => {
|
||||
test("gets stops by system ID", async () => {
|
||||
describe("getStops", () => {
|
||||
test("gets all stops in the repository", async () => {
|
||||
const mockStops = generateMockStops();
|
||||
for (const stop of mockStops) {
|
||||
await repository.addOrUpdateStop(stop);
|
||||
}
|
||||
|
||||
const result = await repository.getStopsBySystemId("sys1");
|
||||
expect(result).toEqual(mockStops.filter((stop) => stop.systemId === "sys1"));
|
||||
const result = await repository.getStops();
|
||||
expect(result).toEqual(mockStops);
|
||||
});
|
||||
|
||||
test("returns an empty list if there are no stops for the given system ID", async () => {
|
||||
const result = await repository.getStopsBySystemId("nonexistent-system");
|
||||
const result = await repository.getStops();
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -92,19 +53,19 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("getRoutesBySystemId", () => {
|
||||
describe("getRoutes", () => {
|
||||
test("gets all routes for a specific system ID", async () => {
|
||||
const mockRoutes = generateMockRoutes();
|
||||
for (const route of mockRoutes) {
|
||||
await repository.addOrUpdateRoute(route);
|
||||
}
|
||||
|
||||
const result = await repository.getRoutesBySystemId("sys1");
|
||||
expect(result).toEqual(mockRoutes.filter((route) => route.systemId === "sys1"));
|
||||
const result = await repository.getRoutes();
|
||||
expect(result).toEqual(mockRoutes);
|
||||
});
|
||||
|
||||
test("returns an empty list if there are no routes for the system ID", async () => {
|
||||
const result = await repository.getRoutesBySystemId("nonexistent-system");
|
||||
const result = await repository.getRoutes();
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -124,19 +85,19 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
describe("getShuttlesBySystemId", () => {
|
||||
describe("getShuttles", () => {
|
||||
test("gets all shuttles for a specific system ID", async () => {
|
||||
const mockShuttles = generateMockShuttles();
|
||||
for (const shuttle of mockShuttles) {
|
||||
await repository.addOrUpdateShuttle(shuttle);
|
||||
}
|
||||
|
||||
const result = await repository.getShuttlesBySystemId("sys1");
|
||||
expect(result).toEqual(mockShuttles.filter((sh) => sh.systemId === "sys1"));
|
||||
const result = await repository.getShuttles();
|
||||
expect(result).toEqual(mockShuttles);
|
||||
});
|
||||
|
||||
test("returns an empty list if there are no shuttles for the system ID", async () => {
|
||||
const result = await repository.getShuttlesBySystemId("nonexistent-system");
|
||||
const result = await repository.getShuttles();
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -324,31 +285,6 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("addOrUpdateSystem", () => {
|
||||
test("adds a new system if nonexistent", async () => {
|
||||
const mockSystems = generateMockSystems();
|
||||
const newSystem = mockSystems[0];
|
||||
|
||||
await repository.addOrUpdateSystem(newSystem);
|
||||
|
||||
const result = await repository.getSystems();
|
||||
expect(result).toEqual([newSystem]);
|
||||
});
|
||||
|
||||
test("updates an existing system if it exists", async () => {
|
||||
const mockSystems = generateMockSystems();
|
||||
const existingSystem = mockSystems[0];
|
||||
const updatedSystem = structuredClone(existingSystem);
|
||||
updatedSystem.name = "Updated System";
|
||||
|
||||
await repository.addOrUpdateSystem(existingSystem);
|
||||
await repository.addOrUpdateSystem(updatedSystem);
|
||||
|
||||
const result = await repository.getSystems();
|
||||
expect(result).toEqual([updatedSystem]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("addOrUpdateRoute", () => {
|
||||
test("adds a new route if nonexistent", async () => {
|
||||
const mockRoutes = generateMockRoutes();
|
||||
@@ -356,7 +292,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
|
||||
await repository.addOrUpdateRoute(newRoute);
|
||||
|
||||
const result = await repository.getRoutesBySystemId("sys1");
|
||||
const result = await repository.getRoutes();
|
||||
expect(result).toEqual([newRoute]);
|
||||
});
|
||||
|
||||
@@ -369,7 +305,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
await repository.addOrUpdateRoute(existingRoute);
|
||||
await repository.addOrUpdateRoute(updatedRoute);
|
||||
|
||||
const result = await repository.getRoutesBySystemId("sys1");
|
||||
const result = await repository.getRoutes();
|
||||
expect(result).toEqual([updatedRoute]);
|
||||
});
|
||||
});
|
||||
@@ -381,7 +317,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
|
||||
await repository.addOrUpdateShuttle(newShuttle);
|
||||
|
||||
const result = await repository.getShuttlesBySystemId("sys1");
|
||||
const result = await repository.getShuttles();
|
||||
expect(result).toEqual([newShuttle]);
|
||||
});
|
||||
|
||||
@@ -394,7 +330,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
await repository.addOrUpdateShuttle(existingShuttle);
|
||||
await repository.addOrUpdateShuttle(updatedShuttle);
|
||||
|
||||
const result = await repository.getShuttlesBySystemId("sys1");
|
||||
const result = await repository.getShuttles();
|
||||
expect(result).toEqual([updatedShuttle]);
|
||||
});
|
||||
});
|
||||
@@ -406,7 +342,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
|
||||
await repository.addOrUpdateStop(newStop);
|
||||
|
||||
const result = await repository.getStopsBySystemId("sys1");
|
||||
const result = await repository.getStops();
|
||||
expect(result).toEqual([newStop]);
|
||||
});
|
||||
|
||||
@@ -419,7 +355,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
await repository.addOrUpdateStop(existingStop);
|
||||
await repository.addOrUpdateStop(updatedStop);
|
||||
|
||||
const result = await repository.getStopsBySystemId("sys1");
|
||||
const result = await repository.getStops();
|
||||
expect(result).toEqual([updatedStop]);
|
||||
});
|
||||
});
|
||||
@@ -474,33 +410,6 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("removeSystemIfExists", () => {
|
||||
test("removes system given ID", async () => {
|
||||
const mockSystems = generateMockSystems();
|
||||
await Promise.all(mockSystems.map(async (system) => {
|
||||
await repository.addOrUpdateSystem(system);
|
||||
}));
|
||||
|
||||
const systemToRemove = mockSystems[0];
|
||||
await repository.removeSystemIfExists(systemToRemove.id);
|
||||
|
||||
const remainingSystems = await repository.getSystems();
|
||||
expect(remainingSystems).toHaveLength(mockSystems.length - 1);
|
||||
});
|
||||
|
||||
test("does nothing if system doesn't exist", async () => {
|
||||
const mockSystems = generateMockSystems();
|
||||
await Promise.all(mockSystems.map(async (system) => {
|
||||
await repository.addOrUpdateSystem(system);
|
||||
}));
|
||||
|
||||
await repository.removeSystemIfExists("nonexistent-id");
|
||||
|
||||
const remainingSystems = await repository.getSystems();
|
||||
expect(remainingSystems).toHaveLength(mockSystems.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe("removeRouteIfExists", () => {
|
||||
test("removes route given ID", async () => {
|
||||
const systemId = "1";
|
||||
@@ -513,7 +422,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
const routeToRemove = mockRoutes[0];
|
||||
await repository.removeRouteIfExists(routeToRemove.id);
|
||||
|
||||
const remainingRoutes = await repository.getRoutesBySystemId(systemId);
|
||||
const remainingRoutes = await repository.getRoutes();
|
||||
expect(remainingRoutes).toHaveLength(mockRoutes.length - 1);
|
||||
});
|
||||
|
||||
@@ -527,7 +436,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
|
||||
await repository.removeRouteIfExists("nonexistent-id");
|
||||
|
||||
const remainingRoutes = await repository.getRoutesBySystemId(systemId);
|
||||
const remainingRoutes = await repository.getRoutes();
|
||||
expect(remainingRoutes).toHaveLength(mockRoutes.length);
|
||||
});
|
||||
});
|
||||
@@ -544,7 +453,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
const shuttleToRemove = mockShuttles[0];
|
||||
await repository.removeShuttleIfExists(shuttleToRemove.id);
|
||||
|
||||
const remainingShuttles = await repository.getShuttlesBySystemId(systemId);
|
||||
const remainingShuttles = await repository.getShuttles();
|
||||
expect(remainingShuttles).toHaveLength(mockShuttles.length - 1);
|
||||
});
|
||||
|
||||
@@ -558,7 +467,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
|
||||
await repository.removeShuttleIfExists("nonexistent-id");
|
||||
|
||||
const remainingShuttles = await repository.getShuttlesBySystemId(systemId);
|
||||
const remainingShuttles = await repository.getShuttles();
|
||||
expect(remainingShuttles).toHaveLength(mockShuttles.length);
|
||||
});
|
||||
});
|
||||
@@ -575,7 +484,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
const stopToRemove = mockStops[0];
|
||||
await repository.removeStopIfExists(stopToRemove.id);
|
||||
|
||||
const remainingStops = await repository.getStopsBySystemId(systemId);
|
||||
const remainingStops = await repository.getStops();
|
||||
expect(remainingStops).toHaveLength(mockStops.length - 1);
|
||||
});
|
||||
|
||||
@@ -589,7 +498,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
|
||||
await repository.removeStopIfExists("nonexistent-id");
|
||||
|
||||
const remainingStops = await repository.getStopsBySystemId(systemId);
|
||||
const remainingStops = await repository.getStops();
|
||||
expect(remainingStops).toHaveLength(mockStops.length);
|
||||
});
|
||||
});
|
||||
@@ -662,31 +571,6 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("clearSystemData", () => {
|
||||
test("clears all systems from the repository", async () => {
|
||||
const mockSystems = generateMockSystems();
|
||||
for (const system of mockSystems) {
|
||||
await repository.addOrUpdateSystem(system);
|
||||
}
|
||||
|
||||
await repository.clearSystemData();
|
||||
|
||||
const result = await repository.getSystems();
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
test("clears system data when the repository has data", async () => {
|
||||
const mockSystems = generateMockSystems();
|
||||
const system = mockSystems[0];
|
||||
await repository.addOrUpdateSystem(system);
|
||||
|
||||
await repository.clearSystemData();
|
||||
|
||||
const result = await repository.getSystems();
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("clearShuttleData", () => {
|
||||
test("clears all shuttles from the repository", async () => {
|
||||
const mockShuttles = generateMockShuttles();
|
||||
@@ -696,7 +580,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
|
||||
await repository.clearShuttleData();
|
||||
|
||||
const result = await repository.getShuttlesBySystemId("sys1");
|
||||
const result = await repository.getShuttles();
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -738,7 +622,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
|
||||
await repository.clearRouteData();
|
||||
|
||||
const result = await repository.getRoutesBySystemId("sys1");
|
||||
const result = await repository.getRoutes();
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -752,7 +636,7 @@ describe("UnoptimizedInMemoryRepository", () => {
|
||||
|
||||
await repository.clearStopData();
|
||||
|
||||
const result = await repository.getStopsBySystemId("sys1");
|
||||
const result = await repository.getStops();
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { beforeEach, describe, expect, it } from "@jest/globals";
|
||||
import { setupTestServerContext, setupTestServerHolder } from "../testHelpers/apolloTestServerHelpers";
|
||||
import { IEta, IShuttle, IStop, ISystem } from "../../src/entities/entities";
|
||||
import { IEta, IShuttle, IStop, IPassioSystem } from "../../src/entities/entities";
|
||||
import {
|
||||
addMockEtaToRepository, addMockShuttleToRepository,
|
||||
addMockStopToRepository,
|
||||
addMockSystemToRepository
|
||||
} from "../testHelpers/repositorySetupHelpers";
|
||||
import assert = require("node:assert");
|
||||
|
||||
@@ -12,23 +11,21 @@ describe("EtaResolvers", () => {
|
||||
const holder = setupTestServerHolder();
|
||||
const context = setupTestServerContext();
|
||||
|
||||
let mockSystem: ISystem;
|
||||
let mockShuttle: IShuttle;
|
||||
let mockStop: IStop;
|
||||
let expectedEta: IEta;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockSystem = await addMockSystemToRepository(context.shuttleRepository);
|
||||
mockShuttle = await addMockShuttleToRepository(context.shuttleRepository, mockSystem.id);
|
||||
mockStop = await addMockStopToRepository(context.shuttleRepository, mockSystem.id);
|
||||
expectedEta = await addMockEtaToRepository(context.shuttleRepository, mockStop.id, mockShuttle.id);
|
||||
mockShuttle = await addMockShuttleToRepository(context.systems[0].shuttleRepository, context.systems[0].id);
|
||||
mockStop = await addMockStopToRepository(context.systems[0].shuttleRepository, context.systems[0].id);
|
||||
expectedEta = await addMockEtaToRepository(context.systems[0].shuttleRepository, mockStop.id, mockShuttle.id);
|
||||
});
|
||||
|
||||
async function getResponseForEtaQuery(query: string) {
|
||||
const response = await holder.testServer.executeOperation({
|
||||
query,
|
||||
variables: {
|
||||
systemId: mockSystem.id,
|
||||
systemId: context.systems[0].id,
|
||||
shuttleId: mockShuttle.id,
|
||||
},
|
||||
}, {
|
||||
|
||||
@@ -3,7 +3,6 @@ import { setupTestServerContext, setupTestServerHolder } from "../testHelpers/ap
|
||||
import {
|
||||
addMockShuttleToRepository,
|
||||
addMockStopToRepository,
|
||||
addMockSystemToRepository
|
||||
} from "../testHelpers/repositorySetupHelpers";
|
||||
import assert = require("node:assert");
|
||||
import { NotificationInput } from "../../src/generated/graphql";
|
||||
@@ -44,14 +43,14 @@ describe("MutationResolvers", () => {
|
||||
const notificationResponse = response.body.singleResult.data?.scheduleNotification as any;
|
||||
expect(notificationResponse.success).toBe(false);
|
||||
|
||||
expect(await context.notificationRepository.isNotificationScheduled(notificationInput)).toBe(false);
|
||||
expect(await context.systems[0].notificationRepository.isNotificationScheduled(notificationInput)).toBe(false);
|
||||
}
|
||||
|
||||
|
||||
it("adds a notification to the notification service", async () => {
|
||||
const system = await addMockSystemToRepository(context.shuttleRepository);
|
||||
const shuttle = await addMockShuttleToRepository(context.shuttleRepository, system.id);
|
||||
const stop = await addMockStopToRepository(context.shuttleRepository, system.id);
|
||||
const system = context.systems[0];
|
||||
const shuttle = await addMockShuttleToRepository(context.systems[0].shuttleRepository, system.id);
|
||||
const stop = await addMockStopToRepository(context.systems[0].shuttleRepository, system.id);
|
||||
|
||||
const notificationInput = {
|
||||
deviceId: "1",
|
||||
@@ -72,13 +71,13 @@ describe("MutationResolvers", () => {
|
||||
expect(notificationResponse?.success).toBe(true);
|
||||
expect(notificationResponse?.data).toEqual(expectedNotificationData);
|
||||
|
||||
expect(await context.notificationRepository.getSecondsThresholdForNotificationIfExists(expectedNotificationData)).toBe(240);
|
||||
expect(await context.systems[0].notificationRepository.getSecondsThresholdForNotificationIfExists(expectedNotificationData)).toBe(240);
|
||||
});
|
||||
|
||||
it("adds a notification with the default seconds threshold if none is provided", async () => {
|
||||
const system = await addMockSystemToRepository(context.shuttleRepository);
|
||||
const shuttle = await addMockShuttleToRepository(context.shuttleRepository, system.id);
|
||||
const stop = await addMockStopToRepository(context.shuttleRepository, system.id);
|
||||
const system = context.systems[0];
|
||||
const shuttle = await addMockShuttleToRepository(context.systems[0].shuttleRepository, system.id);
|
||||
const stop = await addMockStopToRepository(context.systems[0].shuttleRepository, system.id);
|
||||
|
||||
const notificationInput = {
|
||||
deviceId: "1",
|
||||
@@ -93,12 +92,12 @@ describe("MutationResolvers", () => {
|
||||
const notificationResponse = response.body.singleResult.data?.scheduleNotification as any;
|
||||
expect(notificationResponse?.success).toBe(true);
|
||||
|
||||
expect(await context.notificationRepository.getSecondsThresholdForNotificationIfExists(notificationInput)).toBe(180);
|
||||
expect(await context.systems[0].notificationRepository.getSecondsThresholdForNotificationIfExists(notificationInput)).toBe(180);
|
||||
});
|
||||
|
||||
it("fails if the shuttle ID doesn't exist", async () => {
|
||||
const system = await addMockSystemToRepository(context.shuttleRepository);
|
||||
const stop = await addMockStopToRepository(context.shuttleRepository, system.id);
|
||||
const system = context.systems[0];
|
||||
const stop = await addMockStopToRepository(context.systems[0].shuttleRepository, system.id);
|
||||
|
||||
const notificationInput = {
|
||||
deviceId: "1",
|
||||
@@ -110,8 +109,8 @@ describe("MutationResolvers", () => {
|
||||
});
|
||||
|
||||
it("fails if the stop ID doesn't exist", async () => {
|
||||
const system = await addMockSystemToRepository(context.shuttleRepository);
|
||||
const shuttle = await addMockShuttleToRepository(context.shuttleRepository, system.id);
|
||||
const system = context.systems[0];
|
||||
const shuttle = await addMockShuttleToRepository(context.systems[0].shuttleRepository, system.id);
|
||||
|
||||
const notificationInput = {
|
||||
deviceId: "1",
|
||||
@@ -140,9 +139,9 @@ describe("MutationResolvers", () => {
|
||||
`
|
||||
|
||||
it("removes the notification from the notification service", async () => {
|
||||
const system = await addMockSystemToRepository(context.shuttleRepository);
|
||||
const shuttle = await addMockShuttleToRepository(context.shuttleRepository, system.id);
|
||||
const stop = await addMockStopToRepository(context.shuttleRepository, system.id);
|
||||
const system = context.systems[0];
|
||||
const shuttle = await addMockShuttleToRepository(context.systems[0].shuttleRepository, system.id);
|
||||
const stop = await addMockStopToRepository(context.systems[0].shuttleRepository, system.id);
|
||||
|
||||
const notificationInput: any = {
|
||||
deviceId: "1",
|
||||
@@ -150,7 +149,7 @@ describe("MutationResolvers", () => {
|
||||
stopId: stop.id,
|
||||
secondsThreshold: 180,
|
||||
}
|
||||
await context.notificationRepository.addOrUpdateNotification(notificationInput);
|
||||
await context.systems[0].notificationRepository.addOrUpdateNotification(notificationInput);
|
||||
|
||||
const notificationLookup = {
|
||||
...notificationInput
|
||||
@@ -166,7 +165,7 @@ describe("MutationResolvers", () => {
|
||||
expect(notificationResponse.success).toBe(true);
|
||||
expect(notificationResponse.data).toEqual(notificationLookup);
|
||||
|
||||
expect(await context.notificationRepository.isNotificationScheduled(notificationLookup)).toBe(false);
|
||||
expect(await context.systems[0].notificationRepository.isNotificationScheduled(notificationLookup)).toBe(false);
|
||||
});
|
||||
|
||||
it("fails if the notification doesn't exist", async () => {
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
import { beforeEach, describe, expect, it } from "@jest/globals";
|
||||
import { setupTestServerContext, setupTestServerHolder } from "../testHelpers/apolloTestServerHelpers";
|
||||
import { IRoute, IStop, ISystem } from "../../src/entities/entities";
|
||||
import { IRoute, IStop, IPassioSystem } from "../../src/entities/entities";
|
||||
import { generateMockOrderedStops, generateMockStops } from "../testHelpers/mockDataGenerators";
|
||||
import { addMockRouteToRepository, addMockSystemToRepository } from "../testHelpers/repositorySetupHelpers";
|
||||
import { addMockRouteToRepository } from "../testHelpers/repositorySetupHelpers";
|
||||
import assert = require("node:assert");
|
||||
|
||||
describe("OrderedStopResolvers", () => {
|
||||
const holder = setupTestServerHolder();
|
||||
const context = setupTestServerContext();
|
||||
|
||||
let mockSystem: ISystem;
|
||||
let mockRoute: IRoute;
|
||||
let mockStops: IStop[];
|
||||
|
||||
beforeEach(async () => {
|
||||
mockSystem = await addMockSystemToRepository(context.shuttleRepository);
|
||||
mockRoute = await addMockRouteToRepository(context.shuttleRepository, mockSystem.id);
|
||||
mockRoute = await addMockRouteToRepository(context.systems[0].shuttleRepository, context.systems[0].id);
|
||||
|
||||
mockStops = generateMockStops();
|
||||
await Promise.all(mockStops.map(async (mockStop) => {
|
||||
mockStop.systemId = mockSystem.id;
|
||||
await context.shuttleRepository.addOrUpdateStop(mockStop);
|
||||
mockStop.systemId = context.systems[0].id;
|
||||
await context.systems[0].shuttleRepository.addOrUpdateStop(mockStop);
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -38,8 +36,8 @@ describe("OrderedStopResolvers", () => {
|
||||
// Link the stops together
|
||||
orderedStops[0].nextStop = orderedStops[1];
|
||||
orderedStops[1].previousStop = orderedStops[0];
|
||||
await context.shuttleRepository.addOrUpdateOrderedStop(orderedStops[0]);
|
||||
await context.shuttleRepository.addOrUpdateOrderedStop(orderedStops[1]);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateOrderedStop(orderedStops[0]);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateOrderedStop(orderedStops[1]);
|
||||
return orderedStops;
|
||||
}
|
||||
|
||||
@@ -63,7 +61,7 @@ describe("OrderedStopResolvers", () => {
|
||||
return await holder.testServer.executeOperation({
|
||||
query,
|
||||
variables: {
|
||||
systemId: mockSystem.id,
|
||||
systemId: context.systems[0].id,
|
||||
routeId: mockRoute.id,
|
||||
stopId,
|
||||
},
|
||||
@@ -93,7 +91,7 @@ describe("OrderedStopResolvers", () => {
|
||||
it("returns null if there is no next stop in the repository", async () => {
|
||||
const orderedStops = await setUpOrderedStopsInRepository();
|
||||
orderedStops[0].nextStop = undefined;
|
||||
await context.shuttleRepository.addOrUpdateOrderedStop(orderedStops[0]);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateOrderedStop(orderedStops[0]);
|
||||
|
||||
const response = await getResponseForNextStopQuery(orderedStops[0].stopId);
|
||||
|
||||
@@ -104,7 +102,7 @@ describe("OrderedStopResolvers", () => {
|
||||
|
||||
it("returns null if the next stop object no longer exists", async () => {
|
||||
const orderedStops = await setUpOrderedStopsInRepository();
|
||||
await context.shuttleRepository.removeStopIfExists(orderedStops[1].stopId);
|
||||
await context.systems[0].shuttleRepository.removeStopIfExists(orderedStops[1].stopId);
|
||||
|
||||
const response = await getResponseForNextStopQuery(orderedStops[0].stopId);
|
||||
|
||||
@@ -134,7 +132,7 @@ describe("OrderedStopResolvers", () => {
|
||||
return await holder.testServer.executeOperation({
|
||||
query,
|
||||
variables: {
|
||||
systemId: mockSystem.id,
|
||||
systemId: context.systems[0].id,
|
||||
routeId: mockRoute.id,
|
||||
stopId,
|
||||
},
|
||||
@@ -163,7 +161,7 @@ describe("OrderedStopResolvers", () => {
|
||||
it("returns null if there is no previous stop in the repository", async () => {
|
||||
const orderedStops = await setUpOrderedStopsInRepository();
|
||||
orderedStops[1].previousStop = undefined;
|
||||
await context.shuttleRepository.addOrUpdateOrderedStop(orderedStops[1]);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateOrderedStop(orderedStops[1]);
|
||||
|
||||
const response = await getResponseForPreviousStopQuery(orderedStops[1].stopId);
|
||||
|
||||
@@ -174,7 +172,7 @@ describe("OrderedStopResolvers", () => {
|
||||
|
||||
it("returns null if the current stop no longer exists", async () => {
|
||||
const orderedStops = await setUpOrderedStopsInRepository();
|
||||
await context.shuttleRepository.removeStopIfExists(orderedStops[0].stopId);
|
||||
await context.systems[0].shuttleRepository.removeStopIfExists(orderedStops[0].stopId);
|
||||
|
||||
const response = await getResponseForPreviousStopQuery(orderedStops[1].stopId);
|
||||
|
||||
@@ -208,7 +206,7 @@ describe("OrderedStopResolvers", () => {
|
||||
return await holder.testServer.executeOperation({
|
||||
query,
|
||||
variables: {
|
||||
systemId: mockSystem.id,
|
||||
systemId: context.systems[0].id,
|
||||
stopId,
|
||||
}
|
||||
}, {
|
||||
@@ -223,7 +221,7 @@ describe("OrderedStopResolvers", () => {
|
||||
orderedStops[0].stopId = mockStops[0].id;
|
||||
|
||||
// Add one stop only
|
||||
await context.shuttleRepository.addOrUpdateOrderedStop(orderedStops[0]);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateOrderedStop(orderedStops[0]);
|
||||
|
||||
const response = await getResponseForRouteQuery(orderedStops[1].stopId);
|
||||
|
||||
@@ -257,7 +255,7 @@ describe("OrderedStopResolvers", () => {
|
||||
return await holder.testServer.executeOperation({
|
||||
query,
|
||||
variables: {
|
||||
systemId: mockSystem.id,
|
||||
systemId: context.systems[0].id,
|
||||
routeId: mockRoute.id,
|
||||
stopId,
|
||||
}
|
||||
@@ -270,7 +268,7 @@ describe("OrderedStopResolvers", () => {
|
||||
it("returns the associated stop if it exists", async () => {
|
||||
const orderedStops = await setUpOrderedStopsInRepository();
|
||||
orderedStops[0].stopId = mockStops[0].id;
|
||||
await context.shuttleRepository.addOrUpdateOrderedStop(orderedStops[0]);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateOrderedStop(orderedStops[0]);
|
||||
|
||||
const response = await getResponseForStopQuery(orderedStops[0].stopId);
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { describe, expect, it } from "@jest/globals";
|
||||
import { generateMockSystems } from "../testHelpers/mockDataGenerators";
|
||||
import { setupTestServerContext, setupTestServerHolder } from "../testHelpers/apolloTestServerHelpers";
|
||||
import { generateMockPassioSystems } from "../testHelpers/mockDataGenerators";
|
||||
import {
|
||||
buildSystemForTesting,
|
||||
setupTestServerContext,
|
||||
setupTestServerHolder
|
||||
} from "../testHelpers/apolloTestServerHelpers";
|
||||
import assert = require("node:assert");
|
||||
import { addMockShuttleToRepository, addMockStopToRepository } from "../testHelpers/repositorySetupHelpers";
|
||||
import { ScheduledNotification } from "../../src/repositories/NotificationRepository";
|
||||
@@ -12,17 +16,9 @@ describe("QueryResolvers", () => {
|
||||
const holder = setupTestServerHolder();
|
||||
const context = setupTestServerContext();
|
||||
|
||||
async function addMockSystems() {
|
||||
const systems = generateMockSystems();
|
||||
await Promise.all(systems.map(async (system) => {
|
||||
await context.shuttleRepository.addOrUpdateSystem(system);
|
||||
}));
|
||||
return systems;
|
||||
}
|
||||
|
||||
describe("systems", () => {
|
||||
it("returns systems from the repository", async () => {
|
||||
const systems = await addMockSystems();
|
||||
const systems = context.systems;
|
||||
|
||||
const query = `
|
||||
query GetSystems
|
||||
@@ -58,7 +54,14 @@ describe("QueryResolvers", () => {
|
||||
`;
|
||||
|
||||
it("returns a system for an ID from the repository", async () => {
|
||||
const systems = await addMockSystems();
|
||||
context.systems = [
|
||||
buildSystemForTesting(),
|
||||
buildSystemForTesting(),
|
||||
];
|
||||
context.findSystemById = (_: string) => context.systems[1];
|
||||
context.systems[1].id = "test-id";
|
||||
|
||||
const systems = context.systems;
|
||||
const systemToGet = systems[1];
|
||||
|
||||
const response = await holder.testServer.executeOperation({
|
||||
@@ -77,6 +80,8 @@ describe("QueryResolvers", () => {
|
||||
});
|
||||
|
||||
it("returns null if there is no system", async () => {
|
||||
context.findSystemById = (_: string) => null;
|
||||
|
||||
const response = await holder.testServer.executeOperation({
|
||||
query,
|
||||
variables: {
|
||||
@@ -103,8 +108,8 @@ describe("QueryResolvers", () => {
|
||||
|
||||
it("returns correct data if the notification is scheduled", async () => {
|
||||
// Arrange
|
||||
const shuttle = await addMockShuttleToRepository(context.shuttleRepository, "1");
|
||||
const stop = await addMockStopToRepository(context.shuttleRepository, "1")
|
||||
const shuttle = await addMockShuttleToRepository(context.systems[0].shuttleRepository, "1");
|
||||
const stop = await addMockStopToRepository(context.systems[0].shuttleRepository, "1")
|
||||
|
||||
const notification: ScheduledNotification = {
|
||||
shuttleId: shuttle.id,
|
||||
@@ -112,7 +117,7 @@ describe("QueryResolvers", () => {
|
||||
deviceId: "1",
|
||||
secondsThreshold: 240,
|
||||
};
|
||||
await context.notificationRepository.addOrUpdateNotification(notification);
|
||||
await context.systems[0].notificationRepository.addOrUpdateNotification(notification);
|
||||
|
||||
const notificationLookup: any = {
|
||||
...notification,
|
||||
|
||||
@@ -2,27 +2,26 @@ import { beforeEach, describe, expect, it } from "@jest/globals";
|
||||
import { setupTestServerContext, setupTestServerHolder } from "../testHelpers/apolloTestServerHelpers";
|
||||
import {
|
||||
addMockRouteToRepository,
|
||||
addMockStopToRepository,
|
||||
addMockSystemToRepository
|
||||
addMockStopToRepository
|
||||
} from "../testHelpers/repositorySetupHelpers";
|
||||
import { generateMockOrderedStops, generateMockShuttles } from "../testHelpers/mockDataGenerators";
|
||||
import { IRoute, IStop, ISystem } from "../../src/entities/entities";
|
||||
import { IRoute, IStop, IPassioSystem } from "../../src/entities/entities";
|
||||
import assert = require("node:assert");
|
||||
|
||||
describe("RouteResolvers", () => {
|
||||
const holder = setupTestServerHolder();
|
||||
const context = setupTestServerContext();
|
||||
|
||||
let mockSystem: ISystem;
|
||||
let mockSystem: IPassioSystem;
|
||||
let mockRoute: IRoute;
|
||||
let mockStop: IStop;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockSystem = await addMockSystemToRepository(context.shuttleRepository);
|
||||
mockSystem = context.systems[0];
|
||||
const systemId = mockSystem.id;
|
||||
|
||||
mockRoute = await addMockRouteToRepository(context.shuttleRepository, systemId);
|
||||
mockStop = await addMockStopToRepository(context.shuttleRepository, systemId);
|
||||
mockRoute = await addMockRouteToRepository(context.systems[0].shuttleRepository, systemId);
|
||||
mockStop = await addMockStopToRepository(context.systems[0].shuttleRepository, systemId);
|
||||
});
|
||||
|
||||
|
||||
@@ -58,7 +57,7 @@ describe("RouteResolvers", () => {
|
||||
const expectedShuttle = expectedShuttles[0];
|
||||
expectedShuttle.systemId = mockSystem.id;
|
||||
expectedShuttle.routeId = mockRoute.id;
|
||||
await context.shuttleRepository.addOrUpdateShuttle(expectedShuttle);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateShuttle(expectedShuttle);
|
||||
|
||||
const response = await getResponseForShuttlesQuery();
|
||||
|
||||
@@ -113,7 +112,7 @@ describe("RouteResolvers", () => {
|
||||
const expectedOrderedStop = orderedStops[0];
|
||||
expectedOrderedStop.stopId = mockStop.id;
|
||||
expectedOrderedStop.routeId = mockRoute.id;
|
||||
await context.shuttleRepository.addOrUpdateOrderedStop(expectedOrderedStop);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateOrderedStop(expectedOrderedStop);
|
||||
|
||||
const response = await getResponseForOrderedStopQuery();
|
||||
|
||||
@@ -130,9 +129,9 @@ describe("RouteResolvers", () => {
|
||||
const expectedOrderedStop = orderedStops[0];
|
||||
expectedOrderedStop.stopId = mockStop.id;
|
||||
expectedOrderedStop.routeId = mockRoute.id;
|
||||
await context.shuttleRepository.addOrUpdateOrderedStop(expectedOrderedStop);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateOrderedStop(expectedOrderedStop);
|
||||
|
||||
await context.shuttleRepository.removeStopIfExists(mockStop.id);
|
||||
await context.systems[0].shuttleRepository.removeStopIfExists(mockStop.id);
|
||||
|
||||
const response = await getResponseForOrderedStopQuery();
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { beforeEach, describe, expect, it } from "@jest/globals";
|
||||
import { generateMockEtas, generateMockRoutes } from "../testHelpers/mockDataGenerators";
|
||||
import { IShuttle, ISystem } from "../../src/entities/entities";
|
||||
import { IShuttle, IPassioSystem } from "../../src/entities/entities";
|
||||
import { setupTestServerContext, setupTestServerHolder } from "../testHelpers/apolloTestServerHelpers";
|
||||
import { addMockShuttleToRepository, addMockSystemToRepository } from "../testHelpers/repositorySetupHelpers";
|
||||
import { addMockShuttleToRepository } from "../testHelpers/repositorySetupHelpers";
|
||||
import assert = require("node:assert");
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ describe("ShuttleResolvers", () => {
|
||||
const holder = setupTestServerHolder();
|
||||
const context = setupTestServerContext();
|
||||
|
||||
let mockSystem: ISystem;
|
||||
let mockSystem: IPassioSystem;
|
||||
let mockShuttle: IShuttle;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockSystem = await addMockSystemToRepository(context.shuttleRepository);
|
||||
mockShuttle = await addMockShuttleToRepository(context.shuttleRepository,
|
||||
mockSystem = context.systems[0];
|
||||
mockShuttle = await addMockShuttleToRepository(context.systems[0].shuttleRepository,
|
||||
mockSystem.id);
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ describe("ShuttleResolvers", () => {
|
||||
const etas = generateMockEtas();
|
||||
await Promise.all(etas.map(async (eta) => {
|
||||
eta.shuttleId = shuttleId;
|
||||
await context.shuttleRepository.addOrUpdateEta(eta);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateEta(eta);
|
||||
}));
|
||||
return etas;
|
||||
}
|
||||
@@ -175,7 +175,7 @@ describe("ShuttleResolvers", () => {
|
||||
|
||||
it("returns the route if it exists", async () => {
|
||||
const mockRoute = generateMockRoutes()[0];
|
||||
await context.shuttleRepository.addOrUpdateRoute(mockRoute);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateRoute(mockRoute);
|
||||
|
||||
const response = await getResponseForQuery();
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { beforeEach, describe, expect, it } from "@jest/globals";
|
||||
import { setupTestServerContext, setupTestServerHolder } from "../testHelpers/apolloTestServerHelpers";
|
||||
import {
|
||||
setupTestServerContext,
|
||||
setupTestServerHolder
|
||||
} from "../testHelpers/apolloTestServerHelpers";
|
||||
import { generateMockEtas, generateMockOrderedStops } from "../testHelpers/mockDataGenerators";
|
||||
import { IStop, ISystem } from "../../src/entities/entities";
|
||||
import { addMockStopToRepository, addMockSystemToRepository } from "../testHelpers/repositorySetupHelpers";
|
||||
import { IStop } from "../../src/entities/entities";
|
||||
import { addMockStopToRepository } from "../testHelpers/repositorySetupHelpers";
|
||||
import assert = require("node:assert");
|
||||
|
||||
describe("StopResolvers", () => {
|
||||
@@ -10,18 +13,16 @@ describe("StopResolvers", () => {
|
||||
const context = setupTestServerContext();
|
||||
|
||||
let mockStop: IStop;
|
||||
let mockSystem: ISystem;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockSystem = await addMockSystemToRepository(context.shuttleRepository);
|
||||
mockStop = await addMockStopToRepository(context.shuttleRepository, mockSystem.id);
|
||||
mockStop = await addMockStopToRepository(context.systems[0].shuttleRepository, context.systems[0].id);
|
||||
})
|
||||
|
||||
async function getResponseForQuery(query: string) {
|
||||
return await holder.testServer.executeOperation({
|
||||
query,
|
||||
variables: {
|
||||
systemId: mockSystem.id,
|
||||
systemId: context.systems[0].id,
|
||||
stopId: mockStop.id,
|
||||
},
|
||||
}, {
|
||||
@@ -49,7 +50,7 @@ describe("StopResolvers", () => {
|
||||
mockOrderedStops = mockOrderedStops.filter((orderedStop) => orderedStop.stopId === mockOrderedStops[0].stopId);
|
||||
await Promise.all(mockOrderedStops.map(async orderedStop => {
|
||||
orderedStop.stopId = mockStop.id;
|
||||
await context.shuttleRepository.addOrUpdateOrderedStop(orderedStop);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateOrderedStop(orderedStop);
|
||||
}));
|
||||
|
||||
const response = await getResponseForQuery(query);
|
||||
@@ -86,7 +87,7 @@ describe("StopResolvers", () => {
|
||||
mockEtas = mockEtas.filter((eta) => eta.stopId === mockEtas[0].stopId);
|
||||
await Promise.all(mockEtas.map(async eta => {
|
||||
eta.stopId = mockStop.id;
|
||||
await context.shuttleRepository.addOrUpdateEta(eta);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateEta(eta);
|
||||
}));
|
||||
|
||||
const response = await getResponseForQuery(query);
|
||||
|
||||
@@ -5,19 +5,18 @@ import {
|
||||
addMockRouteToRepository,
|
||||
addMockShuttleToRepository,
|
||||
addMockStopToRepository,
|
||||
addMockSystemToRepository
|
||||
} from "../testHelpers/repositorySetupHelpers";
|
||||
import { ISystem } from "../../src/entities/entities";
|
||||
import { IPassioSystem } from "../../src/entities/entities";
|
||||
import assert = require("node:assert");
|
||||
|
||||
describe("SystemResolvers", () => {
|
||||
const holder = setupTestServerHolder();
|
||||
const context = setupTestServerContext();
|
||||
|
||||
let mockSystem: ISystem;
|
||||
let mockSystem: IPassioSystem;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockSystem = await addMockSystemToRepository(context.shuttleRepository);
|
||||
mockSystem = context.systems[0];
|
||||
});
|
||||
|
||||
// TODO: Consolidate these into one single method taking an object
|
||||
@@ -28,9 +27,7 @@ describe("SystemResolvers", () => {
|
||||
systemId: mockSystem.id,
|
||||
},
|
||||
}, {
|
||||
contextValue: {
|
||||
shuttleRepository: context.shuttleRepository
|
||||
},
|
||||
contextValue: context,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -50,7 +47,7 @@ describe("SystemResolvers", () => {
|
||||
const expectedRoutes = generateMockRoutes();
|
||||
await Promise.all(expectedRoutes.map(async (route) => {
|
||||
route.systemId = mockSystem.id;
|
||||
await context.shuttleRepository.addOrUpdateRoute(route);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateRoute(route);
|
||||
}));
|
||||
|
||||
const response = await getResponseFromQueryNeedingSystemId(query);
|
||||
@@ -78,7 +75,7 @@ describe("SystemResolvers", () => {
|
||||
const expectedStops = generateMockStops();
|
||||
await Promise.all(expectedStops.map(async (stop) => {
|
||||
stop.systemId = mockSystem.id;
|
||||
await context.shuttleRepository.addOrUpdateStop(stop);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateStop(stop);
|
||||
}));
|
||||
|
||||
const response = await getResponseFromQueryNeedingSystemId(query);
|
||||
@@ -110,14 +107,12 @@ describe("SystemResolvers", () => {
|
||||
stopId: stopId,
|
||||
},
|
||||
}, {
|
||||
contextValue: {
|
||||
shuttleRepository: context.shuttleRepository,
|
||||
}
|
||||
contextValue: context,
|
||||
});
|
||||
}
|
||||
|
||||
it("gets the stop with the correct id", async () => {
|
||||
const mockStop = await addMockStopToRepository(context.shuttleRepository, mockSystem.id);
|
||||
const mockStop = await addMockStopToRepository(context.systems[0].shuttleRepository, mockSystem.id);
|
||||
|
||||
const response = await getResponseForStopQuery(mockStop.id);
|
||||
|
||||
@@ -133,9 +128,8 @@ describe("SystemResolvers", () => {
|
||||
...mockSystem,
|
||||
id: "2",
|
||||
}
|
||||
await context.shuttleRepository.addOrUpdateSystem(updatedSystem);
|
||||
|
||||
const mockStop = await addMockStopToRepository(context.shuttleRepository, updatedSystem.id);
|
||||
const mockStop = await addMockStopToRepository(context.systems[0].shuttleRepository, updatedSystem.id);
|
||||
|
||||
const response = await getResponseForStopQuery(mockStop.id);
|
||||
|
||||
@@ -182,7 +176,7 @@ describe("SystemResolvers", () => {
|
||||
}
|
||||
|
||||
it("gets the route with the correct id", async () => {
|
||||
const mockRoute = await addMockRouteToRepository(context.shuttleRepository, mockSystem.id);
|
||||
const mockRoute = await addMockRouteToRepository(context.systems[0].shuttleRepository, mockSystem.id);
|
||||
|
||||
const response = await getResponseForRouteQuery(mockRoute.id);
|
||||
|
||||
@@ -199,9 +193,8 @@ describe("SystemResolvers", () => {
|
||||
...mockSystem,
|
||||
id: "2",
|
||||
}
|
||||
await context.shuttleRepository.addOrUpdateSystem(updatedSystem);
|
||||
|
||||
const mockRoute = await addMockRouteToRepository(context.shuttleRepository, updatedSystem.id);
|
||||
const mockRoute = await addMockRouteToRepository(context.systems[0].shuttleRepository, updatedSystem.id);
|
||||
|
||||
const response = await getResponseForRouteQuery(mockRoute.id);
|
||||
|
||||
@@ -249,7 +242,7 @@ describe("SystemResolvers", () => {
|
||||
}
|
||||
|
||||
it("gets the shuttle with the correct id", async () => {
|
||||
const mockShuttle = await addMockShuttleToRepository(context.shuttleRepository, mockSystem.id);
|
||||
const mockShuttle = await addMockShuttleToRepository(context.systems[0].shuttleRepository, mockSystem.id);
|
||||
|
||||
const response = await getResponseForShuttleQuery(mockShuttle.id);
|
||||
|
||||
@@ -265,9 +258,8 @@ describe("SystemResolvers", () => {
|
||||
...mockSystem,
|
||||
id: "2",
|
||||
}
|
||||
await context.shuttleRepository.addOrUpdateSystem(updatedSystem);
|
||||
|
||||
const mockShuttle = await addMockShuttleToRepository(context.shuttleRepository, updatedSystem.id);
|
||||
const mockShuttle = await addMockShuttleToRepository(context.systems[0].shuttleRepository, updatedSystem.id);
|
||||
|
||||
const response = await getResponseForShuttleQuery(mockShuttle.id);
|
||||
|
||||
@@ -305,7 +297,7 @@ describe("SystemResolvers", () => {
|
||||
const expectedShuttles = generateMockShuttles();
|
||||
await Promise.all(expectedShuttles.map(async (shuttle) => {
|
||||
shuttle.systemId = mockSystem.id;
|
||||
await context.shuttleRepository.addOrUpdateShuttle(shuttle);
|
||||
await context.systems[0].shuttleRepository.addOrUpdateShuttle(shuttle);
|
||||
}));
|
||||
|
||||
const response = await getResponseFromQueryNeedingSystemId(query);
|
||||
|
||||
@@ -6,6 +6,7 @@ import { beforeEach } from "@jest/globals";
|
||||
import { ServerContext } from "../../src/ServerContext";
|
||||
import { ETANotificationScheduler } from "../../src/notifications/schedulers/ETANotificationScheduler";
|
||||
import { InMemoryNotificationRepository } from "../../src/repositories/InMemoryNotificationRepository";
|
||||
import { InterchangeSystem } from "../../src/entities/InterchangeSystem";
|
||||
|
||||
|
||||
function setUpTestServer() {
|
||||
@@ -18,6 +19,16 @@ function setUpTestServer() {
|
||||
});
|
||||
}
|
||||
|
||||
const systemInfoForTesting = {
|
||||
id: "1", name: "Chapman University", passioSystemId: "263"
|
||||
};
|
||||
|
||||
export function buildSystemForTesting() {
|
||||
return InterchangeSystem.buildForTesting(
|
||||
systemInfoForTesting,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a `ServerContext` object which can be passed to requests
|
||||
* for testing.
|
||||
@@ -26,8 +37,10 @@ export function setupTestServerContext() {
|
||||
const context: { [key: string] : any } = {};
|
||||
|
||||
beforeEach(() => {
|
||||
context.shuttleRepository = new UnoptimizedInMemoryShuttleRepository();
|
||||
context.notificationRepository = new InMemoryNotificationRepository();
|
||||
context.systems = [
|
||||
buildSystemForTesting(),
|
||||
];
|
||||
context.findSystemById = (_: string) => context.systems[0];
|
||||
});
|
||||
|
||||
return context as ServerContext;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { IEta, IOrderedStop, IRoute, IShuttle, IStop, ISystem } from "../../src/entities/entities";
|
||||
import { IEta, IOrderedStop, IRoute, IShuttle, IStop, IPassioSystem } from "../../src/entities/entities";
|
||||
|
||||
// Use a single set of generators in case any of the
|
||||
// interfaces change in the future
|
||||
|
||||
export function generateMockSystems(): ISystem[] {
|
||||
export function generateMockPassioSystems(): IPassioSystem[] {
|
||||
return [
|
||||
{ id: "1", name: "System A" },
|
||||
{ id: "2", name: "System B" },
|
||||
@@ -67,17 +67,17 @@ export function generateMockStops(): IStop[] {
|
||||
|
||||
export function generateMockOrderedStops(): IOrderedStop[] {
|
||||
return [
|
||||
{ stopId: "st1", routeId: "r1", position: 1 },
|
||||
{ stopId: "st1", routeId: "r2", position: 2 },
|
||||
{ stopId: "st2", routeId: "r1", position: 3 },
|
||||
{ stopId: "st2", routeId: "r2", position: 4 },
|
||||
{ stopId: "st1", routeId: "r1", position: 1, systemId: "sys1" },
|
||||
{ stopId: "st1", routeId: "r2", position: 2, systemId: "sys1" },
|
||||
{ stopId: "st2", routeId: "r1", position: 3, systemId: "sys1" },
|
||||
{ stopId: "st2", routeId: "r2", position: 4, systemId: "sys1" },
|
||||
];
|
||||
}
|
||||
|
||||
export function generateMockEtas(): IEta[] {
|
||||
return [
|
||||
{ shuttleId: "sh1", stopId: "st1", secondsRemaining: 120 },
|
||||
{ shuttleId: "sh1", stopId: "st2", secondsRemaining: 180 },
|
||||
{ shuttleId: "sh2", stopId: "st3", secondsRemaining: 240 },
|
||||
{ shuttleId: "sh1", stopId: "st1", secondsRemaining: 120, systemId: "sys1" },
|
||||
{ shuttleId: "sh1", stopId: "st2", secondsRemaining: 180, systemId: "sys1" },
|
||||
{ shuttleId: "sh2", stopId: "st3", secondsRemaining: 240, systemId: "sys1" },
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,19 +3,9 @@ import {
|
||||
generateMockRoutes,
|
||||
generateMockShuttles,
|
||||
generateMockStops,
|
||||
generateMockSystems
|
||||
} from "./mockDataGenerators";
|
||||
import { ShuttleGetterSetterRepository } from "../../src/repositories/ShuttleGetterSetterRepository";
|
||||
|
||||
export async function addMockSystemToRepository(repository: ShuttleGetterSetterRepository) {
|
||||
const mockSystems = generateMockSystems();
|
||||
const mockSystem = mockSystems[0];
|
||||
mockSystem.id = "1";
|
||||
await repository.addOrUpdateSystem(mockSystem);
|
||||
|
||||
return mockSystem;
|
||||
}
|
||||
|
||||
export async function addMockRouteToRepository(repository: ShuttleGetterSetterRepository, systemId: string) {
|
||||
const mockRoutes = generateMockRoutes();
|
||||
const mockRoute = mockRoutes[0];
|
||||
|
||||
Reference in New Issue
Block a user