Skip to content

Commit

Permalink
Merge branch 'hp/skate-detours-channel' into hp/hook-for-loading-sing…
Browse files Browse the repository at this point in the history
…le-detour
  • Loading branch information
hannahpurcell committed Jan 6, 2025
2 parents f7ee64c + 071dcb2 commit 01404bb
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 71 deletions.
39 changes: 28 additions & 11 deletions assets/src/hooks/useDetours.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Channel, Socket } from "phoenix"
import { SimpleDetour } from "../models/detoursList"
import {
SimpleDetour,
SimpleDetourData,
simpleDetourFromData,
} from "../models/detoursList"
import { useEffect, useState } from "react"
import { reload } from "../models/browser"
import { userUuid } from "../util/userUuid"
Expand All @@ -21,17 +25,25 @@ const subscribe = (
const channel = socket.channel(topic)

handleDrafted &&
channel.on("drafted", ({ data: data }) => handleDrafted(data))
channel.on("drafted", ({ data: data }: { data: SimpleDetourData }) =>
handleDrafted(simpleDetourFromData(data))
)
handleActivated &&
channel.on("activated", ({ data: data }) => handleActivated(data))
channel.on("activated", ({ data: data }: { data: SimpleDetourData }) =>
handleActivated(simpleDetourFromData(data))
)
handleDeactivated &&
channel.on("deactivated", ({ data: data }) => handleDeactivated(data))
channel.on("deactivated", ({ data: data }: { data: SimpleDetourData }) =>
handleDeactivated(simpleDetourFromData(data))
)
channel.on("auth_expired", reload)

channel
.join()
.receive("ok", ({ data: data }: { data: SimpleDetour[] }) => {
const detoursMap = Object.fromEntries(data.map((v) => [v.id, v]))
.receive("ok", ({ data: data }: { data: SimpleDetourData[] }) => {
const detoursMap = Object.fromEntries(
data.map((v) => [v.id, simpleDetourFromData(v)])
)
initializeChannel(detoursMap)
})

Expand Down Expand Up @@ -166,13 +178,16 @@ const subscribeByRoute = (
): Channel => {
const channel = socket.channel(topic + routeId)

channel.on("activated", ({ data: data }) => {
channel.on("activated", ({ data: data }: { data: SimpleDetourData }) => {
setDetours((activeDetours) => ({
...activeDetours,
[routeId]: { ...activeDetours[routeId], [data.id]: data },
[routeId]: {
...activeDetours[routeId],
[data.id]: simpleDetourFromData(data),
},
}))
})
channel.on("deactivated", ({ data: data }) => {
channel.on("deactivated", ({ data: data }: { data: SimpleDetourData }) => {
setDetours((activeDetours) => {
delete activeDetours[routeId][data.id]
return activeDetours
Expand All @@ -182,8 +197,10 @@ const subscribeByRoute = (

channel
.join()
.receive("ok", ({ data: data }: { data: SimpleDetour[] }) => {
const detoursMap = Object.fromEntries(data.map((v) => [v.id, v]))
.receive("ok", ({ data: data }: { data: SimpleDetourData[] }) => {
const detoursMap = Object.fromEntries(
data.map((v) => [v.id, simpleDetourFromData(v)])
)
setDetours((detoursByRouteId) => ({
...detoursByRouteId,
[routeId]: detoursMap,
Expand Down
19 changes: 13 additions & 6 deletions assets/tests/factories/detourListFactory.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
import { Factory } from "fishery"
import {
GroupedSimpleDetours,
SimpleDetour,
SimpleDetourData,
simpleDetourFromData,
} from "../../src/models/detoursList"

export const detourListFactory = Factory.define<GroupedSimpleDetours>(() => {
return {
active: [
simpleDetourFactory.build(),
simpleDetourFactory.build({ direction: "Outbound" }),
simpleDetourFromData(simpleDetourDataFactory.build()),
simpleDetourFromData(
simpleDetourDataFactory.build({ direction: "Outbound" })
),
],
draft: undefined,
past: [simpleDetourFactory.build({ name: "Headsign Z" })],
past: [
simpleDetourFromData(
simpleDetourDataFactory.build({ name: "Headsign Z" })
),
],
}
})

export const simpleDetourFactory = Factory.define<SimpleDetour>(
export const simpleDetourDataFactory = Factory.define<SimpleDetourData>(
({ sequence }) => ({
id: sequence,
route: `${sequence}`,
direction: "Inbound",
name: `Headsign ${sequence}`,
intersection: `Street A${sequence} & Avenue B${sequence}`,
updatedAt: 1724866392,
updated_at: 1724866392,
})
)
88 changes: 48 additions & 40 deletions assets/tests/hooks/useDetours.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import { describe, expect, test } from "@jest/globals"
import { makeMockChannel, makeMockSocket } from "../testHelpers/socketHelpers"
import { act, renderHook } from "@testing-library/react"
import { simpleDetourFactory } from "../factories/detourListFactory"
import { simpleDetourDataFactory } from "../factories/detourListFactory"
import {
useActiveDetours,
useActiveDetoursByRoute,
useDraftDetours,
usePastDetours,
} from "../../src/hooks/useDetours"
import { SimpleDetour } from "../../src/models/detoursList"
import {
SimpleDetourData,
simpleDetourFromData,
} from "../../src/models/detoursList"
import { RouteId } from "../../src/schedule"

const detourA = simpleDetourFactory.build()
const detourB = simpleDetourFactory.build()
const detourC = simpleDetourFactory.build()
const detourD = simpleDetourFactory.build()
const detourA = simpleDetourDataFactory.build()
const detourB = simpleDetourDataFactory.build()
const detourC = simpleDetourDataFactory.build()
const detourD = simpleDetourDataFactory.build()

const parsedDetourA = simpleDetourFromData(detourA)
const parsedDetourB = simpleDetourFromData(detourB)
const parsedDetourC = simpleDetourFromData(detourC)
const parsedDetourD = simpleDetourFromData(detourD)

const detours = [detourA, detourB, detourC]

Expand All @@ -26,9 +34,9 @@ describe("useActiveDetours", () => {
const { result } = renderHook(() => useActiveDetours(mockSocket))

expect(result.current).toStrictEqual({
[detourA.id]: detourA,
[detourB.id]: detourB,
[detourC.id]: detourC,
[detourA.id]: parsedDetourA,
[detourB.id]: parsedDetourB,
[detourC.id]: parsedDetourC,
})
})

Expand All @@ -38,7 +46,7 @@ describe("useActiveDetours", () => {

const mockEvents: Record<
string,
undefined | ((data: { data: SimpleDetour }) => void)
undefined | ((data: { data: SimpleDetourData }) => void)
> = {
activated: undefined,
}
Expand All @@ -54,10 +62,10 @@ describe("useActiveDetours", () => {
act(() => mockEvents["activated"]?.({ data: detourD }))

expect(result.current).toStrictEqual({
[detourA.id]: detourA,
[detourB.id]: detourB,
[detourC.id]: detourC,
[detourD.id]: detourD,
[detourA.id]: parsedDetourA,
[detourB.id]: parsedDetourB,
[detourC.id]: parsedDetourC,
[detourD.id]: parsedDetourD,
})
})

Expand All @@ -67,7 +75,7 @@ describe("useActiveDetours", () => {

const mockEvents: Record<
string,
undefined | ((data: { data: SimpleDetour }) => void)
undefined | ((data: { data: SimpleDetourData }) => void)
> = {
deactivated: undefined,
}
Expand All @@ -83,8 +91,8 @@ describe("useActiveDetours", () => {
act(() => mockEvents["deactivated"]?.({ data: detourA }))

expect(result.current).toStrictEqual({
[detourB.id]: detourB,
[detourC.id]: detourC,
[detourB.id]: parsedDetourB,
[detourC.id]: parsedDetourC,
})
})
})
Expand All @@ -97,9 +105,9 @@ describe("usePastDetours", () => {
const { result } = renderHook(() => usePastDetours(mockSocket))

expect(result.current).toStrictEqual({
[detourA.id]: detourA,
[detourB.id]: detourB,
[detourC.id]: detourC,
[detourA.id]: parsedDetourA,
[detourB.id]: parsedDetourB,
[detourC.id]: parsedDetourC,
})
})

Expand All @@ -109,7 +117,7 @@ describe("usePastDetours", () => {

const mockEvents: Record<
string,
undefined | ((data: { data: SimpleDetour }) => void)
undefined | ((data: { data: SimpleDetourData }) => void)
> = {
deactivated: undefined,
}
Expand All @@ -125,10 +133,10 @@ describe("usePastDetours", () => {
act(() => mockEvents["deactivated"]?.({ data: detourD }))

expect(result.current).toStrictEqual({
[detourA.id]: detourA,
[detourB.id]: detourB,
[detourC.id]: detourC,
[detourD.id]: detourD,
[detourA.id]: parsedDetourA,
[detourB.id]: parsedDetourB,
[detourC.id]: parsedDetourC,
[detourD.id]: parsedDetourD,
})
})
})
Expand All @@ -141,9 +149,9 @@ describe("useDraftDetours", () => {
const { result } = renderHook(() => useDraftDetours(mockSocket))

expect(result.current).toStrictEqual({
[detourA.id]: detourA,
[detourB.id]: detourB,
[detourC.id]: detourC,
[detourA.id]: parsedDetourA,
[detourB.id]: parsedDetourB,
[detourC.id]: parsedDetourC,
})
})

Expand All @@ -153,7 +161,7 @@ describe("useDraftDetours", () => {

const mockEvents: Record<
string,
undefined | ((data: { data: SimpleDetour }) => void)
undefined | ((data: { data: SimpleDetourData }) => void)
> = {
drafted: undefined,
}
Expand All @@ -169,10 +177,10 @@ describe("useDraftDetours", () => {
act(() => mockEvents["drafted"]?.({ data: detourD }))

expect(result.current).toStrictEqual({
[detourA.id]: detourA,
[detourB.id]: detourB,
[detourC.id]: detourC,
[detourD.id]: detourD,
[detourA.id]: parsedDetourA,
[detourB.id]: parsedDetourB,
[detourC.id]: parsedDetourC,
[detourD.id]: parsedDetourD,
})
})

Expand All @@ -182,7 +190,7 @@ describe("useDraftDetours", () => {

const mockEvents: Record<
string,
undefined | ((data: { data: SimpleDetour }) => void)
undefined | ((data: { data: SimpleDetourData }) => void)
> = {
activated: undefined,
}
Expand All @@ -198,8 +206,8 @@ describe("useDraftDetours", () => {
act(() => mockEvents["activated"]?.({ data: detourA }))

expect(result.current).toStrictEqual({
[detourB.id]: detourB,
[detourC.id]: detourC,
[detourB.id]: parsedDetourB,
[detourC.id]: parsedDetourC,
})
})
})
Expand Down Expand Up @@ -257,9 +265,9 @@ describe("useActiveDetoursByRoute", () => {

expect(result.current).toEqual({
"1": {
[detourA.id]: detourA,
[detourB.id]: detourB,
[detourC.id]: detourC,
[detourA.id]: parsedDetourA,
[detourB.id]: parsedDetourB,
[detourC.id]: parsedDetourC,
},
})
})
Expand All @@ -281,7 +289,7 @@ describe("useActiveDetoursByRoute", () => {

expect(result.current).toEqual({
"1": {
[detourD.id]: detourD,
[detourD.id]: parsedDetourD,
},
})
})
Expand Down
16 changes: 8 additions & 8 deletions lib/skate/detours/detours.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ defmodule Skate.Detours.Detours do
def active_detours_by_route(route_id) do
list_detours()
|> Enum.filter(fn detour ->
categorize_detour(detour) == :active and get_detour_route(detour) == route_id
categorize_detour(detour) == :active and get_detour_route_id(detour) == route_id
end)
|> Enum.map(fn detour -> db_detour_to_detour(detour) end)
end
Expand Down Expand Up @@ -131,9 +131,9 @@ defmodule Skate.Detours.Detours do

def categorize_detour(_detour_context), do: :draft

@spec get_detour_route(detour :: map()) :: String.t()
defp get_detour_route(%{state: %{"context" => %{"route" => %{"name" => route_name}}}}),
do: route_name
@spec get_detour_route_id(detour :: map()) :: String.t()
defp get_detour_route_id(%{state: %{"context" => %{"route" => %{"id" => route_id}}}}),
do: route_id

@doc """
Gets a single detour.
Expand Down Expand Up @@ -264,7 +264,7 @@ defmodule Skate.Detours.Detours do
|> User.get_by_id!()
|> Map.get(:uuid)

route_id = get_detour_route(detour)
route_id = get_detour_route_id(detour)

Phoenix.PubSub.broadcast(
Skate.PubSub,
Expand All @@ -274,7 +274,7 @@ defmodule Skate.Detours.Detours do

Phoenix.PubSub.broadcast(
Skate.PubSub,
"detours:active" <> route_id,
"detours:active:" <> route_id,
{:detour_activated, db_detour_to_detour(detour)}
)

Expand All @@ -286,11 +286,11 @@ defmodule Skate.Detours.Detours do
end

defp broadcast_detour(:past, detour, _author_id) do
route_id = get_detour_route(detour)
route_id = get_detour_route_id(detour)

Phoenix.PubSub.broadcast(
Skate.PubSub,
"detours:active" <> route_id,
"detours:active:" <> route_id,
{:detour_deactivated, db_detour_to_detour(detour)}
)

Expand Down
4 changes: 2 additions & 2 deletions test/skate_web/channels/detours_channel_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ defmodule SkateWeb.DetoursChannelTest do
draft_detour = :detour_snapshot |> build() |> with_id(1)

active_detour_one =
:detour_snapshot |> build() |> activated |> with_id(2) |> with_route_name("57")
:detour_snapshot |> build() |> activated |> with_id(2) |> with_route("57")

active_detour_two =
:detour_snapshot |> build() |> activated |> with_id(3) |> with_route_name("66")
:detour_snapshot |> build() |> activated |> with_id(3) |> with_route("66")

past_detour = :detour_snapshot |> build() |> deactivated |> with_id(4)

Expand Down
Loading

0 comments on commit 01404bb

Please sign in to comment.