Skip to content

Commit

Permalink
refactor(StopPageRedesign): get route patterns
Browse files Browse the repository at this point in the history
use the router route's `loader` function to fetch the stop's route patterns
  • Loading branch information
thecristen committed Sep 26, 2023
1 parent c4c5aff commit 5feb644
Show file tree
Hide file tree
Showing 16 changed files with 791 additions and 836 deletions.
22 changes: 21 additions & 1 deletion apps/site/assets/ts/helpers/departureInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
import { DirectionId, Route } from "../__v3api";
import DisplayTime from "../stop/components/DisplayTime";
import { getInfoKey } from "../stop/models/displayTimeConfig";
import { RoutePatternWithPolyline } from "../stop/stop-redesign-loader";

export const SUBWAY = "subway";
export const BUS = "bus";
Expand Down Expand Up @@ -186,12 +187,31 @@ const departuresListFromInfos = (
.value();
};

const departureInfoInRoutePatterns = (
departureInfo: DepartureInfo,
routePatterns: RoutePatternWithPolyline[]
): boolean => {
const isMatch = !!routePatterns.find(
rp => rp.id === departureInfo.trip.route_pattern_id
);
// This second case is needed for the edge case where the route pattern is
// canonical but the schedules/predictions are not serving canonical route
// patterns (e.g. due to shuttles or other disruptions)
const isSimilar = !!routePatterns.find(
rp =>
rp.headsign === departureInfo.trip.headsign &&
rp.route_id === departureInfo.route.id
);
return isMatch || isSimilar;
};

export {
mergeIntoDepartureInfo,
departureInfoToTime,
displayInfoContainsPrediction,
getNextUnCancelledDeparture,
isAtDestination,
isCommuterRail,
departuresListFromInfos
departuresListFromInfos,
departureInfoInRoutePatterns
};
132 changes: 32 additions & 100 deletions apps/site/assets/ts/hooks/__tests__/useRouteTest.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { renderHook } from "@testing-library/react-hooks";
import React from "react";
import { SWRConfig } from "swr";
import { RouteWithPolylines, useRoutesByStop } from "../useRoute";
import { useRoutes } from "../useRoute";
import { FetchStatus } from "../../helpers/use-fetch";
import { Route } from "../../__v3api";

const unmockedFetch = global.fetch;
const HookWrapper: React.FC = ({ children }) => (
Expand All @@ -12,85 +13,25 @@ const HookWrapper: React.FC = ({ children }) => (
const testData = [
{
id: "0",
type: 0,
polylines: [
{
id: "0",
"dotted?": false,
weight: 2,
positions: [
[1, 2],
[3, 4]
],
color: "#ABC123"
}
]
type: 0
},
{
id: "1",
type: 1,
polylines: [
{
id: "1",
"dotted?": false,
weight: 2,
positions: [
[5, 2],
[7, 4]
],
color: "#ABC123"
}
]
type: 1
},
{
id: "2",
type: 2,
polylines: [
{
id: "2",
"dotted?": false,
weight: 2,
positions: [
[9, 2],
[3, 4]
],
color: "#ABC123"
}
]
type: 2
},
{
id: "3",
type: 3,
polylines: [
{
id: "3",
"dotted?": false,
weight: 2,
positions: [
[2, 2],
[8, 4]
],
color: "#ABC123"
}
]
type: 3
},
{
id: "4",
type: 4,
polylines: [
{
id: "4",
"dotted?": false,
weight: 2,
positions: [
[9, 2],
[3, 4]
],
color: "#ABC123"
}
]
type: 4
}
] as RouteWithPolylines[];
] as Route[];

describe("useRoute", () => {
beforeEach(() => {
Expand All @@ -108,42 +49,33 @@ describe("useRoute", () => {
);
});

describe("useRoutesByStop", () => {
it("should return an array of routes and lines", async () => {
const { result, waitFor } = renderHook(() => useRoutesByStop("stop-id"), {
wrapper: HookWrapper
});
await waitFor(() =>
expect(result.current.status).toEqual(FetchStatus.Data)
);

await waitFor(() => expect(result.current.data).toEqual(testData));
const routeWithPolylines = result.current.data![0];
expect(typeof routeWithPolylines).toBe("object");
expect(routeWithPolylines.polylines[0]).toHaveProperty("color");
expect(routeWithPolylines.polylines[0]).toHaveProperty("weight");
expect(routeWithPolylines.polylines[0]).toHaveProperty("positions");
it("should return an array of routes", async () => {
const { result, waitFor } = renderHook(() => useRoutes(["stop-id"]), {
wrapper: HookWrapper
});
await waitFor(() =>
expect(result.current.status).toEqual(FetchStatus.Data)
);

await waitFor(() => expect(result.current.data).toEqual(testData));
});

it("returns error status if API returns an error", async () => {
global.fetch = jest.fn(
() =>
new Promise((resolve: Function) =>
resolve({
json: () => [],
ok: false,
status: 500,
statusText: "ERROR"
})
)
);
const { result, waitFor } = renderHook(() => useRoutesByStop("stop-id"), {
wrapper: HookWrapper
});
await waitFor(() =>
expect(result.current.status).toBe(FetchStatus.Error)
);
it("returns error status if API returns an error", async () => {
global.fetch = jest.fn(
() =>
new Promise((resolve: Function) =>
resolve({
json: () => [],
ok: false,
status: 500,
statusText: "ERROR"
})
)
);
const { result, waitFor } = renderHook(() => useRoutes(["stop-id"]), {
wrapper: HookWrapper
});
await waitFor(() => expect(result.current.status).toBe(FetchStatus.Error));
});

afterAll(() => {
Expand Down
17 changes: 8 additions & 9 deletions apps/site/assets/ts/hooks/useRoute.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
import useSWR from "swr";
import { sortBy } from "lodash";
import { fetchJsonOrThrow } from "../helpers/fetch-json";
import { Route } from "../__v3api";
import { Polyline } from "../leaflet/components/__mapdata";
import { FetchState, FetchStatus } from "../helpers/use-fetch";

export type RouteWithPolylines = Route & { polylines: Polyline[] };

const fetchData = async (url: string): Promise<RouteWithPolylines[]> =>
const fetchData = async (url: string): Promise<Route[]> =>
fetchJsonOrThrow(url);

const useRoutesByStop = (stopId: string): FetchState<RouteWithPolylines[]> => {
const { data, error } = useSWR<RouteWithPolylines[]>(
`/api/routes/by-stop/${stopId}`,
const useRoutes = (routeIds: string[]): FetchState<Route[]> => {
const { data, error } = useSWR<Route[]>(
routeIds.length ? `/api/routes/${routeIds.join(",")}` : null,
fetchData
);
if (error) {
return { status: FetchStatus.Error };
}
return { status: FetchStatus.Data, data };
const sortedRoutes = data ? sortBy(data, ["sort_order"]) : data;
return { status: FetchStatus.Data, data: sortedRoutes };
};
// eslint-disable-next-line import/prefer-default-export
export { useRoutesByStop };
export { useRoutes };
Loading

0 comments on commit 5feb644

Please sign in to comment.