diff --git a/lib/dotcom_web/live/schedule_finder_live.ex b/lib/dotcom_web/live/schedule_finder_live.ex index 8df8bb8656..8d797a9619 100644 --- a/lib/dotcom_web/live/schedule_finder_live.ex +++ b/lib/dotcom_web/live/schedule_finder_live.ex @@ -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) @@ -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}> @@ -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} @@ -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 @@ -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}} @@ -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""" @@ -426,13 +424,13 @@ defmodule DotcomWeb.ScheduleFinderLive do - <%= for service_group <- @service_groups do %> diff --git a/test/dotcom_web/live/schedule_finder_live_test.exs b/test/dotcom_web/live/schedule_finder_live_test.exs index 34882f63d0..3817c42781 100644 --- a/test/dotcom_web/live/schedule_finder_live_test.exs +++ b/test/dotcom_web/live/schedule_finder_live_test.exs @@ -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) @@ -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 _ ->