Skip to content

Commit

Permalink
fix(Alerts.Disruptions.Subway): add missing service ranges (#2390)
Browse files Browse the repository at this point in the history
  • Loading branch information
thecristen authored Feb 20, 2025
1 parent 7775495 commit 27668d7
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 4 deletions.
16 changes: 13 additions & 3 deletions lib/dotcom/alerts/disruptions/subway.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Dotcom.Alerts.Disruptions.Subway do

import Dotcom.Alerts, only: [service_impacting_alert?: 1]
import Dotcom.Routes, only: [subway_route_ids: 0]
import Dotcom.Utils.ServiceDateTime, only: [service_range: 1]
import Dotcom.Utils.ServiceDateTime, only: [all_service_ranges: 0, service_range: 1]

alias Alerts.Alert
alias Dotcom.Utils
Expand Down Expand Up @@ -50,14 +50,24 @@ defmodule Dotcom.Alerts.Disruptions.Subway do
defp group_alerts(alert, groups) do
alert
|> Map.get(:active_period)
|> Enum.map(fn {start, stop} -> [service_range(start), service_range(stop)] end)
|> List.flatten()
|> Enum.flat_map(&service_range_range/1)
|> Enum.uniq()
|> Enum.reduce(groups, fn service_range, groups ->
Map.update(groups, service_range, [alert], &(&1 ++ [alert]))
end)
end

# An active period can span many ranges from start to stop
# e.g. [:before_today, :today, :later_this_week]
defp service_range_range({start, stop}) do
start_index = Enum.find_index(all_service_ranges(), &(&1 == service_range(start)))
stop_index = Enum.find_index(all_service_ranges(), &(&1 == service_range(stop)))

all_service_ranges()
|> Enum.with_index(&if(&2 in start_index..stop_index, do: &1))
|> Enum.reject(&is_nil/1)
end

# Sorts alerts by the start time of the first active period.
defp sort_alerts_by_start_time(alerts) do
alerts
Expand Down
6 changes: 6 additions & 0 deletions lib/dotcom/utils/service_date_time.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ defmodule Dotcom.Utils.ServiceDateTime do
@service_rollover_time Application.compile_env!(:dotcom, :service_rollover_time)
@timezone Application.compile_env!(:dotcom, :timezone)

@doc """
Returns an ordered list of service ranges, from earliest to latest.
"""
def all_service_ranges,
do: [:before_today, :today, :later_this_week, :next_week, :after_next_week]

@doc """
Returns the time at which service rolls over from 'today' to 'tomorrow'.
"""
Expand Down
65 changes: 64 additions & 1 deletion test/dotcom/alerts/disruptions/subway_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,43 @@ defmodule Dotcom.Alerts.Disruptions.SubwayTest do
after_next_week: [^alert_after_next_week]
} = future_disruptions()
end

test "handles single active_period spanning many service ranges" do
# Setup
{alert_today_start, _} = service_range_day()
{alert_after_next_week_start, _} = service_range_after_next_week()

long_alert =
[{alert_today_start, Timex.shift(alert_after_next_week_start, days: 1)}]
|> disruption_alert()

expect(Alerts.Repo.Mock, :by_route_ids, fn _route_ids, _now ->
[long_alert]
end)

# Exercise/Verify
assert %{
later_this_week: [^long_alert],
next_week: [^long_alert],
after_next_week: [^long_alert]
} = future_disruptions()
end

test "handles alert with more than one active_period" do
# Setup
long_alert =
[service_range_later_this_week(), service_range_next_week()] |> disruption_alert()

expect(Alerts.Repo.Mock, :by_route_ids, fn _route_ids, _now ->
[long_alert]
end)

# Exercise/Verify
assert %{
later_this_week: [^long_alert],
next_week: [^long_alert]
} = future_disruptions()
end
end

describe "todays_disruptions/0" do
Expand All @@ -82,6 +119,30 @@ defmodule Dotcom.Alerts.Disruptions.SubwayTest do
assert %{today: [^alert_today]} = todays_disruptions()
end

test "returns alerts for today when applicable to other service ranges" do
# Setup
{start, _} = service_range_day()
{_, stop} = service_range_next_week()
alert_today_and_beyond = disruption_alert({start, stop})

alert_today_and_other_dates =
[
service_range_day(),
service_range_later_this_week(),
service_range_next_week()
]
|> disruption_alert()

expect(Alerts.Repo.Mock, :by_route_ids, fn _route_ids, _now ->
[alert_today_and_beyond, alert_today_and_other_dates]
end)

# Exercise/Verify
assert %{
today: [^alert_today_and_beyond, ^alert_today_and_other_dates]
} = todays_disruptions()
end

test "sorts alerts by start time" do
# Setup
{start, stop} = service_range_day()
Expand All @@ -100,8 +161,10 @@ defmodule Dotcom.Alerts.Disruptions.SubwayTest do
end

defp disruption_alert(active_period) do
active_period = if(is_list(active_period), do: active_period, else: [active_period])

Factories.Alerts.Alert.build(:alert,
active_period: [active_period],
active_period: active_period,
effect: service_impacting_effects() |> Faker.Util.pick()
)
end
Expand Down

0 comments on commit 27668d7

Please sign in to comment.