Skip to content

Commit

Permalink
feat(TripPlanner): display backend error message (#2243)
Browse files Browse the repository at this point in the history
* deps: update open_trip_planner_client

* feat: OTP fallback error message

* feat(TripPlanner): display backend error message

* deps: update mbta_metro

to hopefully fix datepicker and possibly other input errors

* wip: shaded error container component

* chore: use shaded error component

* fix: show error message for locations
  • Loading branch information
thecristen authored Dec 5, 2024
1 parent 040b0bb commit 282a294
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 23 deletions.
3 changes: 2 additions & 1 deletion config/deps/deps.exs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ if config_env() == :test do
end

config :open_trip_planner_client,
timezone: "America/New_York"
timezone: "America/New_York",
fallback_error_message: "Please try again or send us feedback at mbta.com/customer-support"
16 changes: 16 additions & 0 deletions lib/dotcom_web/components/components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,20 @@ defmodule DotcomWeb.Components do
</div>
"""
end

def error_container(assigns) do
assigns =
assigns
|> assign_new(:title, fn -> nil end)
|> assign_new(:padding_class, fn %{title: title} ->
if(title, do: "p-6", else: "px-4 py-2")
end)

~H"""
<div class={"error-container rounded #{@padding_class}"}>
<p :if={@title} class="font-bold mb-2"><%= @title %></p>
<%= render_slot(@inner_block) %>
</div>
"""
end
end
25 changes: 10 additions & 15 deletions lib/dotcom_web/components/live_components/trip_planner_form.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do
"""
use DotcomWeb, :live_component

import MbtaMetro.Components.{Feedback, InputGroup}
import MbtaMetro.Components.InputGroup
import Phoenix.HTML.Form, only: [input_value: 2]

alias Dotcom.TripPlan.{InputForm, InputForm.Modes}
Expand Down Expand Up @@ -56,7 +56,7 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do
phx-change="handle_change"
phx-target={@myself}
>
<div :for={field <- [:from, :to]} class="mb-1" id="trip-planner-locations" phx-update="ignore">
<div :for={field <- [:from, :to]} class="mb-1" id="trip-planner-locations">
<.algolia_autocomplete
config_type="trip-planner"
placeholder="Enter a location"
Expand All @@ -72,9 +72,9 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do
name={location_f[subfield].name}
/>
</.inputs_for>
<.feedback :for={{msg, _} <- f[field].errors} :if={used_input?(f[field])} kind={:error}>
<.error_container :for={{msg, _} <- f[field].errors} :if={used_input?(f[field])}>
<%= msg %>
</.feedback>
</.error_container>
</.algolia_autocomplete>
</div>
<div>
Expand All @@ -89,27 +89,22 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do
phx-change="toggle_datepicker"
phx-update="ignore"
/>
<.feedback
<.error_container
:for={{msg, _} <- f[:datetime_type].errors}
:if={used_input?(f[:datetime_type])}
kind={:error}
>
<%= msg %>
</.feedback>
</.error_container>
<.live_component
:if={@show_datepicker}
module={DatePicker}
config={datepicker_config()}
field={f[:datetime]}
id={:datepicker}
/>
<.feedback
:for={{msg, _} <- f[:datetime].errors}
:if={used_input?(f[:datetime])}
kind={:error}
>
<.error_container :for={{msg, _} <- f[:datetime].errors} :if={used_input?(f[:datetime])}>
<%= msg %>
</.feedback>
</.error_container>
</div>
<div>
<.fieldset id="modes" legend="Modes">
Expand All @@ -130,9 +125,9 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do
</div>
</:content>
<:extra :if={used_input?(f[:modes])}>
<.feedback :for={{msg, _} <- f[:modes].errors} kind={:error}>
<.error_container :for={{msg, _} <- f[:modes].errors}>
<%= msg %>
</.feedback>
</.error_container>
</:extra>
</.accordion>
</.fieldset>
Expand Down
8 changes: 6 additions & 2 deletions lib/dotcom_web/live/trip_planner.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,12 @@ defmodule DotcomWeb.Live.TripPlanner do
<p class="text-lg font-semibold mb-0"><%= submission_summary(@submitted_values) %></p>
<p><%= time_summary(@submitted_values) %></p>
<.async_result :let={results} assign={@results}>
<:failed :let={{:error, _reason}}>
<.feedback kind={:error}>Something else went wrong.</.feedback>
<:failed :let={{:error, errors}}>
<.error_container title="Unable to plan your trip">
<p :for={%OpenTripPlannerClient.Error{message: message} <- errors} class="last:mb-0">
<%= message %>
</p>
</.error_container>
</:failed>
<:loading>
<.spinner aria_label="Waiting for results" /> Waiting for results...
Expand Down
5 changes: 3 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
defmodule DotCom.Mixfile do
@moduledoc false
use Mix.Project

def project do
Expand Down Expand Up @@ -107,14 +108,14 @@ defmodule DotCom.Mixfile do
# Mail kept at 0.3.1 as we experienced inconsistent photo attachment and
# email encoding success with later version
{:mail, "0.3.1"},
{:mbta_metro, "0.0.58"},
{:mbta_metro, "0.0.60"},
{:mock, "0.3.8", [only: :test]},
{:mox, "1.2.0", [only: :test]},
{:nebulex, "2.6.4"},
{:nebulex_redis_adapter, "2.4.1"},
{
:open_trip_planner_client,
[github: "thecristen/open_trip_planner_client", tag: "v0.10.6"]
[github: "mbta/open_trip_planner_client", tag: "v0.11.1"]
},
{:parallel_stream, "1.1.0"},
# latest version 1.7.14
Expand Down
4 changes: 2 additions & 2 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"makeup_elixir": {:hex, :makeup_elixir, "1.0.0", "74bb8348c9b3a51d5c589bf5aebb0466a84b33274150e3b6ece1da45584afc82", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "49159b7d7d999e836bedaf09dcf35ca18b312230cf901b725a64f3f42e407983"},
"makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"},
"makeup_html": {:hex, :makeup_html, "0.1.2", "19d4050c0978a4f1618ffe43054c0049f91fe5feeb9ae8d845b5dc79c6008ae5", [:mix], [{:makeup, "~> 1.2", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "b7fb9afedd617d167e6644a0430e49c1279764bfd3153da716d4d2459b0998c5"},
"mbta_metro": {:hex, :mbta_metro, "0.0.58", "874fde95c254dd430ee395f505df985a8526a9caa95e9dc9005e4ec39fd1e821", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: false]}, {:heroicons, "0.5.6", [hex: :heroicons, repo: "hexpm", optional: true]}, {:jason, "1.4.4", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, "1.7.14", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_live_view, "1.0.0-rc.6", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_storybook, "0.6.4", [hex: :phoenix_storybook, repo: "hexpm", optional: false]}, {:timex, "3.7.11", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm", "bef9d84e431f1f7c29159b0289e7b7e3e5e7aec74ea3192a597996c5f430c642"},
"mbta_metro": {:hex, :mbta_metro, "0.0.60", "59ec399f631ff521d978c3316028c3eb0e9255503138055d166ce0df20e366ff", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: false]}, {:heroicons, "0.5.6", [hex: :heroicons, repo: "hexpm", optional: true]}, {:jason, "1.4.4", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, "1.7.14", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_live_view, "1.0.0-rc.6", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_storybook, "0.6.4", [hex: :phoenix_storybook, repo: "hexpm", optional: false]}, {:timex, "3.7.11", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm", "d962eb850f64fc82331ede365046311926dd86cb2274f21e63b8ecc85dbb2843"},
"meck": {:hex, :meck, "0.9.2", "85ccbab053f1db86c7ca240e9fc718170ee5bda03810a6292b5306bf31bae5f5", [:rebar3], [], "hexpm", "81344f561357dc40a8344afa53767c32669153355b626ea9fcbc8da6b3045826"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
Expand All @@ -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/thecristen/open_trip_planner_client.git", "ca4112f6b2133404b3f99afbf9eaeea6d42c0c21", [tag: "v0.10.6"]},
"open_trip_planner_client": {:git, "https://github.com/mbta/open_trip_planner_client.git", "da20df3ba39314487b4ab050b42131cb01f21826", [tag: "v0.11.1"]},
"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"},
Expand Down
25 changes: 25 additions & 0 deletions test/dotcom_web/components_test.exs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
defmodule DotcomWeb.ComponentsTest do
@moduledoc false
use ExUnit.Case

import Phoenix.Component
import Phoenix.LiveViewTest
import DotcomWeb.Components

Expand Down Expand Up @@ -30,4 +32,27 @@ defmodule DotcomWeb.ComponentsTest do
assert html =~ ~s(<div id="#{id}" phx-hook="AlgoliaAutocomplete" phx-update="ignore">)
end
end

describe "error_container" do
test "optionally shows a title" do
assigns = %{
title: Faker.Lorem.sentence(2),
content: Faker.Lorem.sentence(4)
}

str =
rendered_to_string(~H"""
<.error_container title={assigns.title}>
<%= assigns.content %>
</.error_container>
""")

assert str =~ assigns.title
assert str =~ assigns.content

assert rendered_to_string(~H"""
<.error_container><%= assigns.content %></.error_container>
""") =~ assigns.content
end
end
end
14 changes: 13 additions & 1 deletion test/dotcom_web/live/trip_planner_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ defmodule DotcomWeb.Live.TripPlannerTest do
end)
end

defp stub_populated_otp_results() do
defp stub_populated_otp_results do
itineraries = TripPlannerFactory.build_list(3, :otp_itinerary)

stub_otp_results(itineraries)
Expand Down Expand Up @@ -268,5 +268,17 @@ defmodule DotcomWeb.Live.TripPlannerTest do
assert render_async(view) =~ trip_id_1
refute render_async(view) =~ trip_id_2
end

test "displays error message from the Open Trip Planner client", %{conn: conn, params: params} do
error_message = Faker.Lorem.sentence()

expect(OpenTripPlannerClient.Mock, :plan, fn _ ->
{:error, [%OpenTripPlannerClient.Error{message: error_message}]}
end)

{:ok, view, _html} = live(conn, ~p"/preview/trip-planner?#{params}")

assert render_async(view) =~ error_message
end
end
end

0 comments on commit 282a294

Please sign in to comment.