+
+ <.itinerary_summary summary={@summary} />
+
- ~H"""
-
-
- <.itinerary_summary summary={@summary} />
+ <.itinerary_detail
+ itineraries={@itineraries}
+ selected_itinerary_detail_index={@itinerary_index}
+ />
-
- <.itinerary_detail
- itineraries={@itineraries}
- selected_itinerary_detail_index={@itinerary_index}
- />
-
- """
+ """
+ end
end
defp itinerary_panel(assigns) do
diff --git a/lib/routes/route.ex b/lib/routes/route.ex
index 9b337e8b67..16097c7349 100644
--- a/lib/routes/route.ex
+++ b/lib/routes/route.ex
@@ -92,6 +92,12 @@ defmodule Routes.Route do
@silver_line ~w(741 742 743 746 749 751)
@silver_line_set MapSet.new(@silver_line)
+ defguard is_external?(route) when not is_nil(route.external_agency_name)
+
+ defguard is_shuttle?(route)
+ when route.type == 3 and route.description == :rail_replacement_bus and
+ not is_external?(route)
+
def logan_express_icon_names, do: @logan_express_icon_names
def massport_icon_names, do: @massport_icon_names
diff --git a/mix.exs b/mix.exs
index 1fc0a88015..d212581ddb 100644
--- a/mix.exs
+++ b/mix.exs
@@ -113,7 +113,7 @@ defmodule DotCom.Mixfile do
{:nebulex_redis_adapter, "2.4.1"},
{
:open_trip_planner_client,
- [github: "mbta/open_trip_planner_client", tag: "v0.11.2"]
+ [github: "mbta/open_trip_planner_client", tag: "v0.11.3"]
},
{:parallel_stream, "1.1.0"},
# latest version 1.7.14
diff --git a/mix.lock b/mix.lock
index d9c6680621..910b127976 100644
--- a/mix.lock
+++ b/mix.lock
@@ -72,7 +72,7 @@
"nimble_ownership": {:hex, :nimble_ownership, "1.0.0", "3f87744d42c21b2042a0aa1d48c83c77e6dd9dd357e425a038dd4b49ba8b79a1", [:mix], [], "hexpm", "7c16cc74f4e952464220a73055b557a273e8b1b7ace8489ec9d86e9ad56cb2cc"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
- "open_trip_planner_client": {:git, "https://github.com/mbta/open_trip_planner_client.git", "3bf74242bda2c4174bbbc48363decd864562d0e9", [tag: "v0.11.2"]},
+ "open_trip_planner_client": {:git, "https://github.com/mbta/open_trip_planner_client.git", "b127ccfcc7cdfc40bc91e30c55d41754426a7cc9", [tag: "v0.11.3"]},
"parallel_stream": {:hex, :parallel_stream, "1.1.0", "f52f73eb344bc22de335992377413138405796e0d0ad99d995d9977ac29f1ca9", [:mix], [], "hexpm", "684fd19191aedfaf387bbabbeb8ff3c752f0220c8112eb907d797f4592d6e871"},
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
"phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"},
diff --git a/test/dotcom/trip_plan/itinerary_row_list_test.exs b/test/dotcom/trip_plan/itinerary_row_list_test.exs
index 42c7ae4bf7..9638bbb5bb 100644
--- a/test/dotcom/trip_plan/itinerary_row_list_test.exs
+++ b/test/dotcom/trip_plan/itinerary_row_list_test.exs
@@ -179,7 +179,7 @@ defmodule Dotcom.TripPlan.ItineraryRowListTest do
to: %NamedPosition{stop: %Stops.Stop{id: "place-pktrm"}, name: "Park Street"},
mode: %TransitDetail{
route: %Routes.Route{id: "Green-C"},
- trip_id: "Green-1",
+ trip: %Schedules.Trip{id: "Green-1"},
intermediate_stops: []
}
}
@@ -248,7 +248,7 @@ defmodule Dotcom.TripPlan.ItineraryRowListTest do
to: %NamedPosition{stop: %Stops.Stop{id: "place-kencl"}, name: "Kenmore"},
mode: %TransitDetail{
route: %Routes.Route{id: "Green-C"},
- trip_id: "Green-1",
+ trip: %Schedules.Trip{id: "Green-1"},
intermediate_stops: []
}
}
diff --git a/test/dotcom/trip_plan/itinerary_test.exs b/test/dotcom/trip_plan/itinerary_test.exs
index 6d642ef9fe..835e0def0c 100644
--- a/test/dotcom/trip_plan/itinerary_test.exs
+++ b/test/dotcom/trip_plan/itinerary_test.exs
@@ -54,7 +54,7 @@ defmodule Dotcom.TripPlan.ItineraryTest do
test_calculated_ids =
Enum.flat_map(itinerary, fn leg ->
case leg.mode do
- %TransitDetail{trip_id: trip_id} -> [trip_id]
+ %TransitDetail{trip: %{id: trip_id}} -> [trip_id]
_ -> []
end
end)
@@ -68,7 +68,7 @@ defmodule Dotcom.TripPlan.ItineraryTest do
test_calculated_ids =
Enum.flat_map(itinerary.legs, fn leg ->
case leg.mode do
- %TransitDetail{} = td -> [{td.route.id, td.trip_id}]
+ %TransitDetail{} = td -> [{td.route.id, td.trip.id}]
_ -> []
end
end)
diff --git a/test/dotcom/trip_plan/leg_test.exs b/test/dotcom/trip_plan/leg_test.exs
index 92ad19195f..ad75bce9dd 100644
--- a/test/dotcom/trip_plan/leg_test.exs
+++ b/test/dotcom/trip_plan/leg_test.exs
@@ -48,7 +48,7 @@ defmodule Dotcom.TripPlan.LegTest do
describe "trip_id/1" do
test "returns {:ok, id} for a transit leg", context do
- trip_id = context.transit_leg.mode.trip_id
+ trip_id = context.transit_leg.mode.trip.id
assert {:ok, ^trip_id} = trip_id(context.transit_leg)
end
diff --git a/test/dotcom/trip_plan/related_link_test.exs b/test/dotcom/trip_plan/related_link_test.exs
index 21f89a5a97..ea5ac96a94 100644
--- a/test/dotcom/trip_plan/related_link_test.exs
+++ b/test/dotcom/trip_plan/related_link_test.exs
@@ -35,10 +35,8 @@ defmodule Dotcom.TripPlan.RelatedLinkTest do
fn id -> %Stops.Stop{id: id} end
)
- [trip_id] = Itinerary.trip_ids(itinerary)
assert [route_link, fare_link] = links_for_itinerary(itinerary)
assert url(route_link) =~ Timex.format!(itinerary.start, "date={ISOdate}")
- assert url(route_link) =~ ~s(trip=#{trip_id}) |> URI.encode()
assert fare_link.text == "View fare information"
if route.type == 3 do
diff --git a/test/dotcom_web/live/trip_planner_test.exs b/test/dotcom_web/live/trip_planner_test.exs
index a27327cbe2..091e2e8607 100644
--- a/test/dotcom_web/live/trip_planner_test.exs
+++ b/test/dotcom_web/live/trip_planner_test.exs
@@ -4,6 +4,7 @@ defmodule DotcomWeb.Live.TripPlannerTest do
import Mox
import Phoenix.LiveViewTest
+ alias OpenTripPlannerClient.Test.Support.Factory
alias Test.Support.Factories.TripPlanner.TripPlanner, as: TripPlannerFactory
setup :verify_on_exit!
@@ -20,19 +21,36 @@ defmodule DotcomWeb.Live.TripPlannerTest do
stub_otp_results(itineraries)
end
- defp update_trip_id(itinerary, trip_id) do
- updated_transit_leg =
- itinerary.legs
- |> Enum.at(1)
- |> update_in([:trip, :gtfs_id], fn _ -> "ma_mbta_us:#{trip_id}" end)
+ # For a list of headsigns, create a bunch of itineraries that would be grouped
+ # by the Trip Planner's logic
+ defp grouped_itineraries_from_headsigns([initial_headsign | _] = headsigns) do
+ # Only MBTA transit legs show the headsigns right now, so ensure the
+ # generated legs are MBTA-only
+ base_leg =
+ Factory.build(:transit_leg, %{
+ agency: Factory.build(:agency, %{name: "MBTA"}),
+ route:
+ Factory.build(:route, %{gtfs_id: "mbta-ma-us:internal", type: Faker.Util.pick(0..4)}),
+ trip:
+ Factory.build(:trip, %{
+ direction_id: Faker.Util.pick(["0", "1"]),
+ trip_headsign: initial_headsign
+ })
+ })
+
+ base_itinerary = Factory.build(:itinerary, legs: [base_leg])
+
+ headsigns
+ |> Enum.with_index()
+ |> Enum.map(fn {headsign, index} ->
+ leg = update_in(base_leg, [:trip, :trip_headsign], fn _ -> headsign end)
- itinerary
- |> Map.update!(:legs, &List.replace_at(&1, 1, updated_transit_leg))
- end
-
- defp update_start_time(itinerary, start_time) do
- itinerary
- |> Map.put(:start, DateTime.new!(Date.utc_today(), start_time, "America/New_York"))
+ %{
+ base_itinerary
+ | legs: [leg],
+ start: Timex.shift(base_itinerary.start, minutes: 10 * index)
+ }
+ end)
end
test "Preview version behind basic auth", %{conn: conn} do
@@ -199,26 +217,15 @@ defmodule DotcomWeb.Live.TripPlannerTest do
conn: conn,
params: params
} do
- trip_datetime_1 = Faker.DateTime.forward(2)
- trip_time_1 = trip_datetime_1 |> DateTime.to_time()
- trip_id_1 = Faker.UUID.v4()
-
- trip_datetime_2 = trip_datetime_1 |> DateTime.shift(hour: 1)
- trip_time_2 = trip_datetime_2 |> DateTime.to_time()
- trip_time_display_2 = trip_time_2 |> Timex.format!("%-I:%M", :strftime)
- trip_id_2 = Faker.UUID.v4()
-
- base_itinerary = TripPlannerFactory.build(:otp_itinerary)
-
- # Right now, the headsign (which is what we actually want to
- # show) is not available from OTP client, but we're rendering
- # the trip ID in its place. Once the headsign is available, we
- # should update these updates and the assertions below to use
- # the headsign instead of the trip ID.
- stub_otp_results([
- base_itinerary |> update_trip_id(trip_id_1) |> update_start_time(trip_time_1),
- base_itinerary |> update_trip_id(trip_id_2) |> update_start_time(trip_time_2)
- ])
+ trip_headsign_1 = "Headsign:#{Faker.App.name()}"
+ trip_headsign_2 = "Headsign:#{Faker.App.name()}"
+
+ expect(OpenTripPlannerClient.Mock, :plan, fn _ ->
+ {:ok,
+ %OpenTripPlannerClient.Plan{
+ itineraries: grouped_itineraries_from_headsigns([trip_headsign_1, trip_headsign_2])
+ }}
+ end)
{:ok, view, _html} = live(conn, ~p"/preview/trip-planner?#{params}")
@@ -226,27 +233,25 @@ defmodule DotcomWeb.Live.TripPlannerTest do
view |> element("button", "Details") |> render_click()
- assert render_async(view) =~ trip_id_1
- refute render_async(view) =~ trip_id_2
+ assert render_async(view) =~ trip_headsign_1
+ refute render_async(view) =~ trip_headsign_2
- view |> element("button", trip_time_display_2) |> render_click()
+ view |> element("#itinerary-detail-departure-times button:last-child") |> render_click()
- assert render_async(view) =~ trip_id_2
- refute render_async(view) =~ trip_id_1
+ assert render_async(view) =~ trip_headsign_2
+ refute render_async(view) =~ trip_headsign_1
end
test "'Depart At' buttons don't appear if there would only be one", %{
conn: conn,
params: params
} do
- trip_time_1 = Faker.DateTime.forward(2) |> DateTime.to_time()
- trip_time_display_1 = trip_time_1 |> Timex.format!("%-I:%M", :strftime)
-
- base_itinerary = TripPlannerFactory.build(:otp_itinerary)
-
- stub_otp_results([
- base_itinerary |> update_start_time(trip_time_1)
- ])
+ expect(OpenTripPlannerClient.Mock, :plan, fn _ ->
+ {:ok,
+ %OpenTripPlannerClient.Plan{
+ itineraries: TripPlannerFactory.build_list(1, :otp_itinerary)
+ }}
+ end)
{:ok, view, _html} = live(conn, ~p"/preview/trip-planner?#{params}")
@@ -254,45 +259,34 @@ defmodule DotcomWeb.Live.TripPlannerTest do
view |> element("button", "Details") |> render_click()
- refute view |> element("button", trip_time_display_1) |> has_element?()
+ refute view |> element("#itinerary-detail-departure-times") |> has_element?()
end
test "'Depart At' button state is not preserved when leaving details view", %{
conn: conn,
params: params
} do
- trip_datetime_1 = Faker.DateTime.forward(2)
- trip_time_1 = trip_datetime_1 |> DateTime.to_time()
- trip_id_1 = Faker.UUID.v4()
-
- trip_datetime_2 = trip_datetime_1 |> DateTime.shift(hour: 1)
- trip_time_2 = trip_datetime_2 |> DateTime.to_time()
- trip_time_display_2 = trip_time_2 |> Timex.format!("%-I:%M", :strftime)
- trip_id_2 = Faker.UUID.v4()
-
- base_itinerary = TripPlannerFactory.build(:otp_itinerary)
-
- # Right now, the headsign (which is what we actually want to
- # show) is not available from OTP client, but we're rendering
- # the trip ID in its place. Once the headsign is available, we
- # should update these updates and the assertions below to use
- # the headsign instead of the trip ID.
- stub_otp_results([
- base_itinerary |> update_trip_id(trip_id_1) |> update_start_time(trip_time_1),
- base_itinerary |> update_trip_id(trip_id_2) |> update_start_time(trip_time_2)
- ])
+ trip_headsign_1 = "Headsign:#{Faker.App.name()}"
+ trip_headsign_2 = "Headsign:#{Faker.App.name()}"
+
+ expect(OpenTripPlannerClient.Mock, :plan, fn _ ->
+ {:ok,
+ %OpenTripPlannerClient.Plan{
+ itineraries: grouped_itineraries_from_headsigns([trip_headsign_1, trip_headsign_2])
+ }}
+ end)
{:ok, view, _html} = live(conn, ~p"/preview/trip-planner?#{params}")
render_async(view)
view |> element("button", "Details") |> render_click()
- view |> element("button", trip_time_display_2) |> render_click()
+ view |> element("#itinerary-detail-departure-times button:last-child") |> render_click()
view |> element("button", "View All Options") |> render_click()
view |> element("button", "Details") |> render_click()
- assert render_async(view) =~ trip_id_1
- refute render_async(view) =~ trip_id_2
+ assert render_async(view) =~ trip_headsign_1
+ refute render_async(view) =~ trip_headsign_2
end
test "displays error message from the Open Trip Planner client", %{conn: conn, params: params} do
diff --git a/test/dotcom_web/views/trip_plan_view_test.exs b/test/dotcom_web/views/trip_plan_view_test.exs
index dbbdabe74c..9018c5c8e2 100644
--- a/test/dotcom_web/views/trip_plan_view_test.exs
+++ b/test/dotcom_web/views/trip_plan_view_test.exs
@@ -925,7 +925,7 @@ closest arrival to 12:00 AM, Thursday, January 1st."
fares: @fares,
intermediate_stops: [%Stops.Stop{id: "70071"}, %Stops.Stop{id: "70073"}],
route: %Routes.Route{id: "Red"},
- trip_id: "43870769C0"
+ trip: %Schedules.Trip{id: "43870769C0"}
},
to: %NamedPosition{
latitude: 42.356395,
@@ -1073,7 +1073,7 @@ closest arrival to 12:00 AM, Thursday, January 1st."
fares: @fares,
intermediate_stops: [%Stops.Stop{id: "70071"}, %Stops.Stop{id: "70073"}],
route: %Routes.Route{id: "Red"},
- trip_id: "43870769C0"
+ trip: %Schedules.Trip{id: "43870769C0"}
},
to: %NamedPosition{
latitude: 42.356395,
@@ -1099,7 +1099,7 @@ closest arrival to 12:00 AM, Thursday, January 1st."
%Stops.Stop{id: "80"}
],
route: %Routes.Route{id: "1"},
- trip_id: "44170977"
+ trip: %Schedules.Trip{id: "44170977"}
},
to: %NamedPosition{
latitude: 42.342478,
@@ -1119,7 +1119,7 @@ closest arrival to 12:00 AM, Thursday, January 1st."
fares: @fares,
intermediate_stops: [%Stops.Stop{id: "70071"}, %Stops.Stop{id: "70073"}],
route: %Routes.Route{id: "Red"},
- trip_id: "43870769C0"
+ trip: %Schedules.Trip{id: "43870769C0"}
},
to: %NamedPosition{
latitude: 42.356395,
@@ -1343,7 +1343,7 @@ closest arrival to 12:00 AM, Thursday, January 1st."
},
intermediate_stops: [%Stops.Stop{id: "70071"}, %Stops.Stop{id: "70073"}],
route: %Routes.Route{id: "Red"},
- trip_id: "43870769C0"
+ trip: %Schedules.Trip{id: "43870769C0"}
},
to: %NamedPosition{
latitude: 42.356395,
@@ -1528,7 +1528,7 @@ closest arrival to 12:00 AM, Thursday, January 1st."
%Stops.Stop{id: "74616"}
],
route: %Routes.Route{id: "741"},
- trip_id: "44812009"
+ trip: %Schedules.Trip{id: "44812009"}
},
to: %NamedPosition{
latitude: 42.352271,
diff --git a/test/fares/fares_test.exs b/test/fares/fares_test.exs
index 5182ac405a..a5605cb76b 100644
--- a/test/fares/fares_test.exs
+++ b/test/fares/fares_test.exs
@@ -245,7 +245,7 @@ defmodule FaresTest do
},
intermediate_stops: [%Stops.Stop{id: "70071"}, %Stops.Stop{id: "70073"}],
route: %Routes.Route{id: "Red"},
- trip_id: "43870769C0"
+ trip: %Schedules.Trip{id: "43870769C0"}
},
to: %NamedPosition{
latitude: 42.356395,