diff --git a/config/test.exs b/config/test.exs index 8223d7557..31ccf79b9 100644 --- a/config/test.exs +++ b/config/test.exs @@ -27,6 +27,7 @@ config :screens, blue_bikes_station_status_url: [:no_api_requests_allowed_during_testing], blue_bikes_api_client: Screens.BlueBikes.FakeClient, stops_to_routes_route_mod: Screens.Routes.Route.Mock, + alerts_cache_filter_route_mod: Screens.Routes.Route.Mock, dup_headsign_replacements: %{ "Test 1" => "T1" }, diff --git a/lib/screens/alerts/cache/filter.ex b/lib/screens/alerts/cache/filter.ex index 1d8df5685..ef6e10860 100644 --- a/lib/screens/alerts/cache/filter.ex +++ b/lib/screens/alerts/cache/filter.ex @@ -2,6 +2,8 @@ defmodule Screens.Alerts.Cache.Filter do @moduledoc """ Logic to apply filters to a list of `Screens.Alerts.Alert` structs. """ + alias Screens.Routes.Route + alias Screens.RouteType alias Screens.Stops.StopsToRoutes @default_activities ~w[BOARD EXIT RIDE] @@ -75,7 +77,11 @@ defmodule Screens.Alerts.Cache.Filter do end defp build_matcher({:routes, values}, acc) when is_list(values) do - matchers_for_values(acc, :route, values) + for route_id <- values, + for_route <- matchers_for_route_id(route_id), + matcher <- acc do + Map.merge(matcher, for_route) + end end defp build_matcher({:route_types, values}, acc) when is_list(values) do @@ -114,6 +120,27 @@ defmodule Screens.Alerts.Cache.Filter do end end + defp matchers_for_route_id(nil) do + [%{route: nil}] + end + + defp matchers_for_route_id(route_id) do + route_mod = Application.get_env(:screens, :alerts_cache_filter_route_mod, Route) + + case route_mod.by_id(route_id) do + {:ok, %Route{type: type}} -> + [ + %{ + route_type: RouteType.to_id(type), + route: route_id + } + ] + + _ -> + [%{route: route_id}] + end + end + defp matches?(alert, matchers) when is_list(matchers) do matchers |> Enum.any?(&matches?(alert, &1)) diff --git a/lib/screens/routes/route.ex b/lib/screens/routes/route.ex index c61bdad58..edb220eff 100644 --- a/lib/screens/routes/route.ex +++ b/lib/screens/routes/route.ex @@ -39,6 +39,7 @@ defmodule Screens.Routes.Route do @type color :: name_colors() | :purple | :teal | :yellow @type icon :: name_colors() | :bus | :cr | :ferry | :mattapan + @callback by_id(id()) :: {:ok, t()} | :error @spec by_id(id()) :: {:ok, t()} | :error def by_id(route_id) do case V3Api.get_json("routes/" <> route_id) do diff --git a/test/screens/alerts/alert_test.exs b/test/screens/alerts/alert_test.exs index ba702fecf..09cb1c0fc 100644 --- a/test/screens/alerts/alert_test.exs +++ b/test/screens/alerts/alert_test.exs @@ -202,6 +202,11 @@ defmodule Screens.Alerts.AlertTest do end test "filters by routes", %{get_all_alerts: get_all_alerts} do + stub(Route.Mock, :by_id, fn + "Z" -> {:ok, %Route{id: "Z", type: :rail}} + "Y" -> {:ok, %Route{id: "Y", type: :rail}} + end) + assert {:ok, [%Alert{id: "stop: C, route: Z" <> _}, %Alert{id: "stop: D, route: Y/Z" <> _}]} = Alert.fetch_from_cache([route_ids: ["Z"]], get_all_alerts) @@ -233,6 +238,8 @@ defmodule Screens.Alerts.AlertTest do end test "filters by route and direction_id", %{get_all_alerts: get_all_alerts} do + stub(Route.Mock, :by_id, fn "Z" -> {:ok, %Route{id: "Z", type: :rail}} end) + assert {:ok, [%Alert{id: "stop: D, route: Y/Z, route_type: 2, direction_id: 1"}]} = Alert.fetch_from_cache([route_ids: ["Z"], direction_id: 1], get_all_alerts) end diff --git a/test/screens/alerts/cache/filter_test.exs b/test/screens/alerts/cache/filter_test.exs index 1f9e75208..2c83a037c 100644 --- a/test/screens/alerts/cache/filter_test.exs +++ b/test/screens/alerts/cache/filter_test.exs @@ -53,5 +53,17 @@ defmodule Screens.Alerts.Cache.FilterTest do %{stop: "place-aport"} ] == Filter.build_matchers(%{stops: ["place-aport"]}) end + + test "expands route filters to include route types" do + stub(Route.Mock, :by_id, fn + "Blue" -> {:ok, %Route{id: "Blue", type: :subway}} + "Green-E" -> {:ok, %Route{id: "Green-E", type: :light_rail}} + end) + + assert [ + %{route: "Blue", route_type: 1}, + %{route: "Green-E", route_type: 0} + ] = Filter.build_matchers(%{routes: ["Blue", "Green-E"]}) + end end end