import { beforeEach, describe, expect, it } from "@jest/globals"; import { setupTestServerContext } from "../testHelpers/apolloTestServerHelpers"; import { IRoute, IStop, ISystem } from "../../src/entities/entities"; import { generateMockOrderedStops, generateMockStops } from "../generators"; import { addMockRouteToRepository, addMockSystemToRepository } from "../testHelpers/repositorySetupHelpers"; import assert = require("node:assert"); describe("OrderedStopResolvers", () => { const context = setupTestServerContext(); let mockSystem: ISystem; let mockRoute: IRoute; let mockStops: IStop[]; beforeEach(async () => { mockSystem = await addMockSystemToRepository(context.repository); mockRoute = await addMockRouteToRepository(context.repository, mockSystem.id); mockStops = generateMockStops(); await Promise.all(mockStops.map(async (mockStop) => { mockStop.systemId = mockSystem.id; await context.repository.addOrUpdateStop(mockStop); })); }); async function setUpOrderedStopsInRepository() { const orderedStops = generateMockOrderedStops(); // Set up IDs and link stops together to work with the test query orderedStops[0].routeId = mockRoute.id; orderedStops[1].routeId = mockRoute.id; // Ensure that there is no duplication orderedStops[0].stopId = mockStops[0].id; orderedStops[1].stopId = mockStops[1].id; // Link the stops together orderedStops[0].nextStop = orderedStops[1]; orderedStops[1].previousStop = orderedStops[0]; await context.repository.addOrUpdateOrderedStop(orderedStops[0]); await context.repository.addOrUpdateOrderedStop(orderedStops[1]); return orderedStops; } describe("nextStop", () => { async function getResponseForNextStopQuery(stopId: string) { const query = ` query GetNextStop($systemId: ID!, $routeId: ID!, $stopId: ID!) { system(id: $systemId) { route(id: $routeId) { orderedStop(forStopId: $stopId) { nextStop { routeId stopId } } } } } `; return await context.testServer.executeOperation({ query, variables: { systemId: mockSystem.id, routeId: mockRoute.id, stopId, }, }, { contextValue: { repository: context.repository, } }); } it("returns the next stop if it exists", async () => { // Arrange const orderedStops = await setUpOrderedStopsInRepository(); // Act const response = await getResponseForNextStopQuery(orderedStops[0].stopId); // Assert assert(response.body.kind === "single"); expect(response.body.singleResult.errors).toBeUndefined(); const nextStop = (response.body.singleResult.data?.system as any).route.orderedStop.nextStop; expect(nextStop.stopId).toEqual(orderedStops[1].stopId); expect(nextStop.routeId).toEqual(orderedStops[1].routeId); }); it("returns null if there is no next stop in the repository", async () => { const orderedStops = await setUpOrderedStopsInRepository(); orderedStops[0].nextStop = undefined; await context.repository.addOrUpdateOrderedStop(orderedStops[0]); const response = await getResponseForNextStopQuery(orderedStops[0].stopId); assert(response.body.kind === "single"); const nonexistentNextStop = (response.body.singleResult.data?.system as any).route.orderedStop.nextStop; expect(nonexistentNextStop).toBeNull(); }); it("returns null if the next stop object no longer exists", async () => { const orderedStops = await setUpOrderedStopsInRepository(); await context.repository.removeStopIfExists(orderedStops[1].stopId); const response = await getResponseForNextStopQuery(orderedStops[0].stopId); assert(response.body.kind === "single"); const nonexistentNextStop = (response.body.singleResult.data?.system as any).route.orderedStop.nextStop; expect(nonexistentNextStop).toBeNull(); }); }); describe("previousStop", () => { async function getResponseForPreviousStopQuery(stopId: string) { const query = ` query GetNextStop($systemId: ID!, $routeId: ID!, $stopId: ID!) { system(id: $systemId) { route(id: $routeId) { orderedStop(forStopId: $stopId) { previousStop { routeId stopId } } } } } `; return await context.testServer.executeOperation({ query, variables: { systemId: mockSystem.id, routeId: mockRoute.id, stopId, }, }, { contextValue: { repository: context.repository, } }); } it("returns the previous stop if it exists", async () => { // Arrange const orderedStops = await setUpOrderedStopsInRepository(); // Act const response = await getResponseForPreviousStopQuery(orderedStops[1].stopId); // Assert assert(response.body.kind === "single"); expect(response.body.singleResult.errors).toBeUndefined(); const previousStop = (response.body.singleResult.data?.system as any).route.orderedStop.previousStop; expect(previousStop.stopId).toEqual(orderedStops[0].stopId); expect(previousStop.routeId).toEqual(orderedStops[0].routeId); }); it("returns null if there is no previous stop in the repository", async () => { const orderedStops = await setUpOrderedStopsInRepository(); orderedStops[1].previousStop = undefined; await context.repository.addOrUpdateOrderedStop(orderedStops[1]); const response = await getResponseForPreviousStopQuery(orderedStops[1].stopId); assert(response.body.kind === "single"); const nonexistentPreviousStop = (response.body.singleResult.data?.system as any).route.orderedStop.previousStop; expect(nonexistentPreviousStop).toBeNull(); }); it("returns null if the current stop no longer exists", async () => { const orderedStops = await setUpOrderedStopsInRepository(); await context.repository.removeStopIfExists(orderedStops[0].stopId); const response = await getResponseForPreviousStopQuery(orderedStops[1].stopId); assert(response.body.kind === "single"); const nonexistentPreviousStop = (response.body.singleResult.data?.system as any).route.orderedStop.previousStop; expect(nonexistentPreviousStop).toBeNull(); }); }); describe("route", () => { // Note that there is no `orderedStop(forRouteId)` resolver, // so fetch all ordered stops for a stop instead. // If we went through the route ID, it would've // relied on the parent data within the route.orderedStop resolver async function getResponseForRouteQuery(stopId: string) { const query = ` query GetNextStop($systemId: ID!, $stopId: ID!) { system(id: $systemId) { stop(id: $stopId) { orderedStops { route { id name } } } } } `; return await context.testServer.executeOperation({ query, variables: { systemId: mockSystem.id, stopId, } }, { contextValue: { repository: context.repository, } }); } it("returns the associated route if it exists", async () => { const orderedStops = generateMockOrderedStops(); orderedStops[0].routeId = mockRoute.id; orderedStops[0].stopId = mockStops[0].id; // Add one stop only await context.repository.addOrUpdateOrderedStop(orderedStops[0]); const response = await getResponseForRouteQuery(orderedStops[1].stopId); assert(response.body.kind === "single"); expect(response.body.singleResult.errors).toBeUndefined(); const route = (response.body.singleResult.data?.system as any).stop.orderedStops[0].route expect(route.id).toEqual(mockRoute.id); expect(route.name).toEqual(mockRoute.name); }); }); describe("stop", () => { async function getResponseForStopQuery(stopId: string) { const query = ` query GetNextStop($systemId: ID!, $routeId: ID!, $stopId: ID!) { system(id: $systemId) { route(id: $routeId) { orderedStop(forStopId: $stopId) { stop { name id } } } } } `; return await context.testServer.executeOperation({ query, variables: { systemId: mockSystem.id, routeId: mockRoute.id, stopId, } }, { contextValue: { repository: context.repository, } }); } it("returns the associated stop if it exists", async () => { const orderedStops = await setUpOrderedStopsInRepository(); orderedStops[0].stopId = mockStops[0].id; await context.repository.addOrUpdateOrderedStop(orderedStops[0]); const response = await getResponseForStopQuery(orderedStops[0].stopId); assert(response.body.kind === "single"); expect(response.body.singleResult.errors).toBeUndefined(); const stop = (response.body.singleResult.data?.system as any).route.orderedStop.stop; expect(stop.name).toEqual(mockStops[0].name); expect(stop.id).toEqual(mockStops[0].id); }); }); });