From 544cab53246770821cf99ffd9f60f950c350ce6a Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 16 Apr 2025 17:01:41 -0700 Subject: [PATCH] move parking structures to a sub-field of system --- schema.graphqls | 6 +- src/MergedResolvers.ts | 2 + src/resolvers/ParkingSystemResolvers.ts | 29 ++++ src/resolvers/SystemResolvers.ts | 22 --- .../ParkingSystemResolverTests.test.ts | 151 ++++++++++++++++++ test/resolvers/SystemResolverTests.test.ts | 118 -------------- 6 files changed, 187 insertions(+), 141 deletions(-) create mode 100644 src/resolvers/ParkingSystemResolvers.ts create mode 100644 test/resolvers/ParkingSystemResolverTests.test.ts diff --git a/schema.graphqls b/schema.graphqls index 59915e2..60a3d63 100644 --- a/schema.graphqls +++ b/schema.graphqls @@ -11,7 +11,11 @@ type System { shuttles: [Shuttle!] shuttle(id: ID): Shuttle - # TODO: Implement these in system resolvers + parkingSystem: ParkingSystem +} + +type ParkingSystem { + systemId: ID! parkingStructures: [ParkingStructure!] parkingStructure(id: ID): ParkingStructure } diff --git a/src/MergedResolvers.ts b/src/MergedResolvers.ts index 3c0caad..795ec38 100644 --- a/src/MergedResolvers.ts +++ b/src/MergedResolvers.ts @@ -8,9 +8,11 @@ import { StopResolvers } from "./resolvers/StopResolvers"; import { ShuttleResolvers } from "./resolvers/ShuttleResolvers"; import { RouteResolvers } from "./resolvers/RouteResolvers"; import { MutationResolvers } from "./resolvers/MutationResolvers"; +import { ParkingSystemResolvers } from "./resolvers/ParkingSystemResolvers"; export const MergedResolvers: Resolvers = { ...QueryResolvers, + ...ParkingSystemResolvers, ...SystemResolvers, ...RouteResolvers, ...ShuttleResolvers, diff --git a/src/resolvers/ParkingSystemResolvers.ts b/src/resolvers/ParkingSystemResolvers.ts new file mode 100644 index 0000000..73a5303 --- /dev/null +++ b/src/resolvers/ParkingSystemResolvers.ts @@ -0,0 +1,29 @@ +import { Resolvers } from "../generated/graphql"; +import { ServerContext } from "../ServerContext"; + +export const ParkingSystemResolvers: Resolvers = { + ParkingSystem: { + parkingStructures: async (parent, _args, contextValue, _info) => { + const system = contextValue.findSystemById(parent.systemId); + if (!system) { + return []; + } + const parkingRepository = system.parkingRepository; + if (!parkingRepository) return []; + + return await parkingRepository.getParkingStructures(); + }, + parkingStructure: async (parent, args, contextValue, info) => { + if (!args.id) return null; + + const system = contextValue.findSystemById(parent.systemId); + if (!system) { + return null; + } + const parkingRepository = system.parkingRepository; + if (!parkingRepository) return null; + + return await parkingRepository.getParkingStructureById(args.id); + }, + } +} diff --git a/src/resolvers/SystemResolvers.ts b/src/resolvers/SystemResolvers.ts index 0dc568d..54cd305 100644 --- a/src/resolvers/SystemResolvers.ts +++ b/src/resolvers/SystemResolvers.ts @@ -78,27 +78,5 @@ export const SystemResolvers: Resolvers = { return await system.shuttleRepository.getShuttles(); }, - parkingStructures: async (parent, _args, contextValue, _info) => { - const system = contextValue.findSystemById(parent.id); - if (!system) { - return []; - } - const parkingRepository = system.parkingRepository; - if (!parkingRepository) return []; - - return await parkingRepository.getParkingStructures(); - }, - parkingStructure: async (parent, args, contextValue, info) => { - if (!args.id) return null; - - const system = contextValue.findSystemById(parent.id); - if (!system) { - return null; - } - const parkingRepository = system.parkingRepository; - if (!parkingRepository) return null; - - return await parkingRepository.getParkingStructureById(args.id); - }, }, } diff --git a/test/resolvers/ParkingSystemResolverTests.test.ts b/test/resolvers/ParkingSystemResolverTests.test.ts new file mode 100644 index 0000000..02b5510 --- /dev/null +++ b/test/resolvers/ParkingSystemResolverTests.test.ts @@ -0,0 +1,151 @@ +import { beforeEach, describe, expect, it } from "@jest/globals"; +import { generateParkingStructures } from "../testHelpers/mockDataGenerators"; +import { setupTestServerContext, setupTestServerHolder } from "../testHelpers/apolloTestServerHelpers"; +import { InterchangeSystem } from "../../src/entities/InterchangeSystem"; +import assert = require("node:assert"); + +describe("ParkingSystemResolver", () => { + const holder = setupTestServerHolder(); + const context = setupTestServerContext(); + + let mockSystem: InterchangeSystem; + + beforeEach(async () => { + mockSystem = context.systems[0]; + }); + + async function getResponseFromQueryNeedingSystemId(query: string) { + return await holder.testServer.executeOperation({ + query, + variables: { + systemId: mockSystem.id, + }, + }, { + contextValue: context, + }); + } + + describe("parkingStructures", () => { + const query = ` + query GetParkingStructuresBySystem($systemId: ID!) { + system(id: $systemId) { + parkingSystem { + parkingStructures { + name + id + capacity + spotsAvailable + coordinates { + latitude + longitude + } + address + } + } + } + } + ` + + it("gets parking structures associated with the system id", async () => { + const expectedParkingStructures = generateParkingStructures(); + await Promise.all(expectedParkingStructures.map(async (structure) => { + await context.systems[0].parkingRepository?.addOrUpdateParkingStructure(structure); + })); + + const response = await getResponseFromQueryNeedingSystemId(query); + + assert(response.body.kind === "single"); + expect(response.body.singleResult.errors).toBeUndefined(); + const parkingStructures = (response.body.singleResult.data as any).system.parkingSystem.parkingStructures; + expect(parkingStructures).toEqual(expectedParkingStructures); + }); + + it("returns a blank array if there are no parking structures", async () => { + const response = await getResponseFromQueryNeedingSystemId(query); + + assert(response.body.kind === "single"); + expect(response.body.singleResult.errors).toBeUndefined(); + const parkingStructures = (response.body.singleResult.data as any).system.parkingSystem.parkingStructures; + expect(parkingStructures).toHaveLength(0); + }); + + it("returns a blank array if there is no parking data available", async () => { + context.systems[0].parkingTimedDataLoader = null; + context.systems[0].parkingRepository = null; + + const response = await getResponseFromQueryNeedingSystemId(query); + + assert(response.body.kind === "single"); + expect(response.body.singleResult.errors).toBeUndefined(); + const parkingStructures = (response.body.singleResult.data as any).system.parkingSystem.parkingStructures; + expect(parkingStructures).toHaveLength(0); + }); + }); + + + describe("parkingStructure", () => { + async function getResponseForParkingStructureQuery(parkingStructureId: string) { + const query = ` + query GetParkingStructureBySystem($systemId: ID!, $parkingStructureId: ID!) { + system(id: $systemId) { + parkingSystem { + parkingStructure(id: $parkingStructureId) { + name + id + capacity + spotsAvailable + coordinates { + latitude + longitude + } + address + } + } + } + } + `; + + return await holder.testServer.executeOperation({ + query, + variables: { + systemId: mockSystem.id, + parkingStructureId, + } + }, { + contextValue: context + + }); + } + + it("returns the correct parking structure given the id", async () => { + const generatedParkingStructures = generateParkingStructures(); + await Promise.all(generatedParkingStructures.map(async (structure) => { + await context.systems[0].parkingRepository?.addOrUpdateParkingStructure(structure); + })); + const expectedParkingStructure = generatedParkingStructures[1]; + + const response = await getResponseForParkingStructureQuery(expectedParkingStructure.id); + + assert(response.body.kind === "single"); + expect(response.body.singleResult.errors).toBeUndefined(); + const parkingStructure = (response.body.singleResult.data as any).system.parkingSystem.parkingStructure; + expect(parkingStructure).toEqual(expectedParkingStructure); + }); + + it("returns null if there is no matching parking structure", async () => { + const generatedParkingStructures = generateParkingStructures(); + await Promise.all(generatedParkingStructures.map(async (structure) => { + await context.systems[0].parkingRepository?.addOrUpdateParkingStructure(structure); + })); + + const nonexistentId = generatedParkingStructures[0].id + "12345"; + + const response = await getResponseForParkingStructureQuery(nonexistentId); + + assert(response.body.kind === "single"); + expect(response.body.singleResult.errors).toBeUndefined(); + const parkingStructure = (response.body.singleResult.data as any).system.parkingSystem.parkingStructure; + expect(parkingStructure).toBeNull(); + }); + }); +}); diff --git a/test/resolvers/SystemResolverTests.test.ts b/test/resolvers/SystemResolverTests.test.ts index 29ff221..6c0e7aa 100644 --- a/test/resolvers/SystemResolverTests.test.ts +++ b/test/resolvers/SystemResolverTests.test.ts @@ -314,122 +314,4 @@ describe("SystemResolvers", () => { }); }); - describe("parkingStructures", () => { - const query = ` - query GetParkingStructuresBySystem($systemId: ID!) { - system(id: $systemId) { - parkingStructures { - name - id - capacity - spotsAvailable - coordinates { - latitude - longitude - } - address - } - } - } - ` - - it("gets parking structures associated with the system id", async () => { - const expectedParkingStructures = generateParkingStructures(); - await Promise.all(expectedParkingStructures.map(async (structure) => { - await context.systems[0].parkingRepository?.addOrUpdateParkingStructure(structure); - })); - - const response = await getResponseFromQueryNeedingSystemId(query); - - assert(response.body.kind === "single"); - expect(response.body.singleResult.errors).toBeUndefined(); - const parkingStructures = (response.body.singleResult.data as any).system.parkingStructures; - expect(parkingStructures).toEqual(expectedParkingStructures); - }); - - it("returns a blank array if there are no parking structures", async () => { - const response = await getResponseFromQueryNeedingSystemId(query); - - assert(response.body.kind === "single"); - expect(response.body.singleResult.errors).toBeUndefined(); - const parkingStructures = (response.body.singleResult.data as any).system.parkingStructures; - expect(parkingStructures).toHaveLength(0); - }); - - it("returns a blank array if there is no parking data available", async () => { - context.systems[0].parkingTimedDataLoader = null; - context.systems[0].parkingRepository = null; - - const response = await getResponseFromQueryNeedingSystemId(query); - - assert(response.body.kind === "single"); - expect(response.body.singleResult.errors).toBeUndefined(); - const parkingStructures = (response.body.singleResult.data as any).system.parkingStructures; - expect(parkingStructures).toHaveLength(0); - }); - }); - - describe("parkingStructure", () => { - async function getResponseForParkingStructureQuery(parkingStructureId: string) { - const query = ` - query GetParkingStructureBySystem($systemId: ID!, $parkingStructureId: ID!) { - system(id: $systemId) { - parkingStructure(id: $parkingStructureId) { - name - id - capacity - spotsAvailable - coordinates { - latitude - longitude - } - address - } - } - } - `; - - return await holder.testServer.executeOperation({ - query, - variables: { - systemId: mockSystem.id, - parkingStructureId, - } - }, { - contextValue: context - - }); - } - - it("returns the correct parking structure given the id", async () => { - const generatedParkingStructures = generateParkingStructures(); - await Promise.all(generatedParkingStructures.map(async (structure) => { - await context.systems[0].parkingRepository?.addOrUpdateParkingStructure(structure); - })); - const expectedParkingStructure = generatedParkingStructures[1]; - - const response = await getResponseForParkingStructureQuery(expectedParkingStructure.id); - - assert(response.body.kind === "single"); - expect(response.body.singleResult.errors).toBeUndefined(); - const parkingStructure = (response.body.singleResult.data as any).system.parkingStructure; - expect(parkingStructure).toEqual(expectedParkingStructure); - }); - - it("returns null if there is no matching parking structure", async () => { - const generatedParkingStructures = generateParkingStructures(); - await Promise.all(generatedParkingStructures.map(async (structure) => { - await context.systems[0].parkingRepository?.addOrUpdateParkingStructure(structure); - })); - - const nonexistentId = generatedParkingStructures[0].id + "12345"; - - const response = await getResponseForParkingStructureQuery(nonexistentId); - - assert(response.body.kind === "single"); - expect(response.body.singleResult.errors).toBeUndefined(); - const parkingStructure = (response.body.singleResult.data as any).system.parkingStructure; - expect(parkingStructure).toBeNull(); - }); - }); });