+
{formatted_time_range(@itinerary.start, @itinerary.end)}
+ +1
{@duration}
diff --git a/test/dotcom_web/live/trip_planner_live_test.exs b/test/dotcom_web/live/trip_planner_live_test.exs
index 3b6debb782..7a7363c2ea 100644
--- a/test/dotcom_web/live/trip_planner_live_test.exs
+++ b/test/dotcom_web/live/trip_planner_live_test.exs
@@ -3,10 +3,13 @@ defmodule DotcomWeb.TripPlannerLiveTest do
import DotcomWeb.Router.Helpers, only: [live_path: 2, live_path: 3]
import Mox
- import Phoenix.LiveViewTest
import OpenTripPlannerClient.Test.Support.Factory
+ import Phoenix.LiveViewTest
alias Dotcom.TripPlan.AntiCorruptionLayer
+ alias Test.Support.Generators
+
+ @timezone Application.compile_env!(:dotcom, :timezone)
setup :verify_on_exit!
@@ -467,6 +470,137 @@ defmodule DotcomWeb.TripPlannerLiveTest do
assert Floki.find(document, "div[data-test='itinerary_detail:selected:1']") != []
end
+
+ test "renders time range as 'h:mm - h:mm am' if both times are in the morning", %{view: view} do
+ date = Generators.Date.random_date()
+
+ [start_time, end_time] =
+ Faker.Util.sample_uniq(2, fn ->
+ Generators.DateTime.random_time_range_date_time(
+ {DateTime.new!(date, ~T[00:00:00], @timezone),
+ DateTime.new!(date, ~T[11:59:59], @timezone)}
+ )
+ end)
+ |> Enum.sort(DateTime)
+
+ # Setup
+ expect(OpenTripPlannerClient.Mock, :plan, fn _ ->
+ {:ok, [itinerary_group_with_time_range(start_time, end_time)]}
+ end)
+
+ # Exercise
+ view |> element("form") |> render_change(%{"input_form" => @valid_params})
+
+ # Verify
+ assert rendered_time_range(view) ==
+ "#{pretty_time(start_time)}\u2009–\u2009#{pretty_time(end_time)} am"
+ end
+
+ test "renders time range as 'h:mm - h:mm pm' if both times are after noon", %{view: view} do
+ date = Generators.Date.random_date()
+
+ [start_time, end_time] =
+ Faker.Util.sample_uniq(2, fn ->
+ Generators.DateTime.random_time_range_date_time(
+ {DateTime.new!(date, ~T[12:00:00], @timezone),
+ DateTime.new!(date, ~T[23:59:59], @timezone)}
+ )
+ end)
+ |> Enum.sort(DateTime)
+
+ # Setup
+ expect(OpenTripPlannerClient.Mock, :plan, fn _ ->
+ {:ok, [itinerary_group_with_time_range(start_time, end_time)]}
+ end)
+
+ # Exercise
+ view |> element("form") |> render_change(%{"input_form" => @valid_params})
+
+ # Verify
+ assert rendered_time_range(view) ==
+ "#{pretty_time(start_time)}\u2009–\u2009#{pretty_time(end_time)} pm"
+ end
+
+ test "renders time range as 'h:mm am - h:mm pm' if the itinerary crosses noon", %{view: view} do
+ date = Generators.Date.random_date()
+
+ start_time =
+ Generators.DateTime.random_time_range_date_time(
+ {DateTime.new!(date, ~T[00:00:00], @timezone),
+ DateTime.new!(date, ~T[11:59:59], @timezone)}
+ )
+
+ end_time =
+ Generators.DateTime.random_time_range_date_time(
+ {DateTime.new!(date, ~T[12:00:00], @timezone),
+ DateTime.new!(date, ~T[23:59:59], @timezone)}
+ )
+
+ # Setup
+ expect(OpenTripPlannerClient.Mock, :plan, fn _ ->
+ {:ok, [itinerary_group_with_time_range(start_time, end_time)]}
+ end)
+
+ # Exercise
+ view |> element("form") |> render_change(%{"input_form" => @valid_params})
+
+ # Verify
+ assert rendered_time_range(view) ==
+ "#{pretty_time(start_time)} am\u2009–\u2009#{pretty_time(end_time)} pm"
+ end
+
+ test "renders time range as 'h:mm pm - h:mm am +1' if the itinerary crosses a day boundary",
+ %{view: view} do
+ date = Generators.Date.random_date()
+ next_date = date |> Date.shift(day: 1)
+
+ start_time =
+ Generators.DateTime.random_time_range_date_time(
+ {DateTime.new!(date, ~T[12:00:00], @timezone),
+ DateTime.new!(date, ~T[23:59:59], @timezone)}
+ )
+
+ end_time =
+ Generators.DateTime.random_time_range_date_time(
+ {DateTime.new!(next_date, ~T[00:00:00], @timezone),
+ DateTime.new!(next_date, ~T[11:59:59], @timezone)}
+ )
+
+ # Setup
+ expect(OpenTripPlannerClient.Mock, :plan, fn _ ->
+ {:ok, [itinerary_group_with_time_range(start_time, end_time)]}
+ end)
+
+ # Exercise
+ view |> element("form") |> render_change(%{"input_form" => @valid_params})
+
+ # Verify
+ assert rendered_time_range(view) ==
+ "#{pretty_time(start_time)} pm\u2009–\u2009#{pretty_time(end_time)} am +1"
+ end
+ end
+
+ defp itinerary_group_with_time_range(start_time, end_time) do
+ build(:itinerary_group,
+ representative_index: 0,
+ itineraries: [build(:itinerary, start: start_time, end: end_time)]
+ )
+ end
+
+ defp rendered_time_range(view) do
+ view
+ |> render_async()
+ |> Floki.parse_document!()
+ |> Floki.get_by_id("trip-planner-results")
+ |> Floki.find("[data-test=\"itinerary_summary:time_range\"")
+ |> Floki.text()
+ |> String.trim()
+ |> String.split("\n")
+ |> Enum.map_join(" ", &String.trim/1)
+ end
+
+ defp pretty_time(date_time) do
+ date_time |> Cldr.DateTime.to_string!(Dotcom.Cldr, format: "h:mm")
end
# Parse coordinates from data-coordinates.
diff --git a/test/support/generators/date.ex b/test/support/generators/date.ex
new file mode 100644
index 0000000000..44828591ce
--- /dev/null
+++ b/test/support/generators/date.ex
@@ -0,0 +1,23 @@
+defmodule Test.Support.Generators.Date do
+ @moduledoc """
+ Factories to help generate/evaluate dates for testing.
+ """
+
+ @date_time_module Application.compile_env!(:dotcom, :date_time_module)
+
+ @doc "Generate a random date this decade"
+ def random_date() do
+ now = @date_time_module.now()
+
+ beginning_of_year = Date.new!(now.year, 1, 1)
+ end_of_year = Date.new!(now.year + 1, 1, 1)
+
+ date_generator_between({beginning_of_year, end_of_year}) |> Enum.take(1) |> List.first()
+ end
+
+ def date_generator_between({start, stop}) do
+ StreamData.repeatedly(fn ->
+ Faker.Date.between(start, stop)
+ end)
+ end
+end