Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 19 additions & 21 deletions lib/dotcom_web/live/schedule_finder_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ defmodule DotcomWeb.ScheduleFinderLive do
|> assign_new(:service_groups, fn -> service_groups end)
|> assign_new(:loaded_trips, fn -> %{} end)
|> assign_new(:selected_service_name, fn -> Map.get(selected_service, :label, "") end)
|> assign_new(:selected_service_key, fn -> service_key(selected_service) end)
|> assign_new(:service_today?, fn ->
Enum.any?(all_services, &(!is_nil(&1.now_date)))
end)
Expand Down Expand Up @@ -131,6 +132,7 @@ defmodule DotcomWeb.ScheduleFinderLive do
<.service_picker
id={"service-picker-#{@route.id}"}
selected_service_name={@selected_service_name}
selected_service_key={@selected_service_key}
service_groups={@service_groups}
/>
<.async_result :let={departures} assign={@departures}>
Expand Down Expand Up @@ -197,12 +199,11 @@ defmodule DotcomWeb.ScheduleFinderLive do
end
end

def handle_event("select_service", %{"selected_service" => selected_service_label}, socket) do
send(self(), %{selected_service: selected_service_label})

def handle_event("select_service", %{"selected_service" => selected_service_key}, socket) do
{:noreply,
socket
|> assign(:departures, AsyncResult.loading())}
|> assign_service(selected_service_key)
|> assign_departures()}
end

def handle_event(_, _, socket), do: {:noreply, socket}
Expand All @@ -227,13 +228,6 @@ defmodule DotcomWeb.ScheduleFinderLive do
{:noreply, assign_alerts(socket)}
end

def handle_info(%{selected_service: selected_service_label}, socket) do
{:noreply,
socket
|> assign_service(selected_service_label)
|> assign_departures()}
end

def handle_info(_, socket), do: {:noreply, socket}

defp subscribe_to_alerts(socket) do
Expand Down Expand Up @@ -320,20 +314,23 @@ defmodule DotcomWeb.ScheduleFinderLive do
end
end

defp assign_service(socket, selected_service_label) do
defp assign_service(socket, selected_service_key) do
selected_dated_service =
socket.assigns.service_groups
|> Enum.flat_map(& &1.services)
|> Enum.find(&(&1.label == selected_service_label))

daily_schedule_date =
selected_dated_service.last_service_date
|> Enum.find(&(service_key(&1) == selected_service_key))

socket
|> assign(:selected_service_name, selected_service_label)
|> assign(:daily_schedule_date, daily_schedule_date)
|> assign(:selected_service_name, selected_dated_service.label)
|> assign(:selected_service_key, selected_service_key)
|> assign(:daily_schedule_date, selected_dated_service.last_service_date)
end

defp service_key(%{label: label, last_service_date: date}),
do: "#{Date.to_iso8601(date)}:#{label}"

defp service_key(_), do: ""

defp get_departures(route_id, direction_id, stop_id, date) do
case @schedule_finder.daily_departures(route_id, direction_id, stop_id, date) do
{:ok, departures} -> {:ok, %{departures: departures}}
Expand Down Expand Up @@ -414,6 +411,7 @@ defmodule DotcomWeb.ScheduleFinderLive do
attr :id, :string, required: true
attr :service_groups, :list, required: true
attr :selected_service_name, :string, default: ""
attr :selected_service_key, :string, default: ""

defp service_picker(assigns) do
~H"""
Expand All @@ -426,13 +424,13 @@ defmodule DotcomWeb.ScheduleFinderLive do
<label for={@id} class="sr-only">
{~t(Choose a schedule type from the available options)}
</label>
<select id={@id} class="mbta-input w-full" name="selected_service" phx-update="ignore">
<select id={@id} class="mbta-input w-full" name="selected_service">
<%= for service_group <- @service_groups do %>
<optgroup label={service_group.group_label}>
<option
:for={service <- service_group.services}
value={service.label}
selected={service.now_date || service.next_date}
value={service_key(service)}
selected={service_key(service) == @selected_service_key}
>
{service.label} {if(service.now_date, do: " (#{~t(Now)})")}
</option>
Expand Down
97 changes: 95 additions & 2 deletions test/dotcom_web/live/schedule_finder_live_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,98 @@ defmodule DotcomWeb.ScheduleFinderLiveTest do
end

describe "Daily Departures" do
test "selects the requested schedule when service labels repeat across ratings", %{conn: conn} do
today = Dotcom.Utils.ServiceDateTime.service_date()
current_end_date = Date.shift(today, day: 7)
future_start_date = Date.shift(today, day: 14)
future_end_date = Date.shift(today, day: 21)

current_service =
Factories.Services.Service.build(:service,
start_date: Date.shift(today, day: -7),
end_date: current_end_date,
rating_start_date: Date.shift(today, day: -7),
rating_end_date: current_end_date,
rating_description: "Current",
type: :weekday,
typicality: :typical_service,
valid_days: [1, 2, 3, 4, 5, 6, 7]
)

future_service =
Factories.Services.Service.build(:service,
start_date: future_start_date,
end_date: future_end_date,
rating_start_date: future_start_date,
rating_end_date: future_end_date,
rating_description: "Future",
type: :weekday,
typicality: :typical_service,
valid_days: [1, 2, 3, 4, 5, 6, 7]
)

current_departure =
Factories.ScheduleFinder.build(:daily_departure, trip_id: "current-departure")

future_departure =
Factories.ScheduleFinder.build(:daily_departure, trip_id: "future-departure")

expect(Dotcom.ScheduleFinder.Mock, :daily_departures, 2, fn _, _, _, date ->
case date do
^today -> {:ok, [current_departure]}
^future_end_date -> {:ok, [future_departure]}
end
end)

route_id = FactoryHelpers.build(:id)
direction_id = FactoryHelpers.build(:direction_id)
stop_id = FactoryHelpers.build(:id)

assert {:ok, view, _html} =
visit_with_set_params(
conn,
route_id,
direction_id,
stop_id,
[2],
[current_service, future_service]
)

render_async(view)

current_service_key = "#{current_end_date}:Weekday schedules"
future_service_key = "#{future_end_date}:Weekday schedules"

assert has_element?(
view,
"[id='service-picker-#{route_id}'] option[value='#{current_service_key}'][selected]"
)

refute has_element?(
view,
"[id='service-picker-#{route_id}'] option[value='#{future_service_key}'][selected]"
)

loading_html =
view
|> form("#service-picker-form", selected_service: future_service_key)
|> render_change()

assert loading_html
|> Floki.parse_fragment!()
|> Floki.find("[data-test=\"departures_loading\"]") != []

render_async(view)

assert has_element?(
view,
"[id='service-picker-#{route_id}'] option[value='#{future_service_key}'][selected]"
)

assert has_element?(view, "[phx-value-trip='future-departure']")
refute has_element?(view, "[phx-value-trip='current-departure']")
end

test "indicates no service", %{conn: conn} do
expect(Services.Repo.Mock, :by_route_id, 2, fn _ -> [] end)
expect(Dotcom.ScheduleFinder.Mock, :daily_departures, fn _, _, _, _ -> {:ok, []} end)
Expand Down Expand Up @@ -434,14 +526,15 @@ defmodule DotcomWeb.ScheduleFinderLiveTest do
route_id,
direction_id,
stop_id,
route_types \\ [0, 1, 2, 3, 4]
route_types \\ [0, 1, 2, 3, 4],
services \\ nil
) do
stub(Routes.Repo.Mock, :get, fn _ ->
Factories.Routes.Route.build(:route, %{id: route_id, type: Faker.Util.pick(route_types)})
end)

stub(Services.Repo.Mock, :by_route_id, fn _ ->
Factories.Services.Service.build_list(15, :service)
services || Factories.Services.Service.build_list(15, :service)
end)

stub(Stops.Repo.Mock, :get, fn _ ->
Expand Down
Loading