diff --git a/assets/js/alert-item.js b/assets/js/alert-item.js index 75e04e79ff..76aee4ebbf 100644 --- a/assets/js/alert-item.js +++ b/assets/js/alert-item.js @@ -10,6 +10,10 @@ export const addAlertItemEventHandlers = () => { [...document.querySelectorAll(`.${ITEM_SELECTOR}`)].forEach(alertItem => { alertItem.addEventListener("click", handleAlertItemClick); alertItem.addEventListener("keydown", handleAlertItemKeyPress); + + if (document.querySelector(".diversions-template") && alertItem.querySelector("img")) { + alertItem.click(); + } }); } }; diff --git a/lib/alerts/alert.ex b/lib/alerts/alert.ex index 8d7204ba5f..8d09ef5f97 100644 --- a/lib/alerts/alert.ex +++ b/lib/alerts/alert.ex @@ -1,21 +1,28 @@ defmodule Alerts.Alert do - @moduledoc "Module for representation of an alert, including information such as description, severity or additional URL to learn more" - alias Alerts.Priority - alias Alerts.InformedEntitySet, as: IESet + @moduledoc """ + Module for representation of an alert, including information such as description, severity or additional URL to learn more + """ + + use Timex + + alias Alerts.{InformedEntitySet, Priority} defstruct id: "", - header: "", - informed_entity: %IESet{}, active_period: [], - effect: :unknown, - severity: 5, - lifecycle: :unknown, + banner: "", cause: "", - updated_at: Timex.now(), + created_at: nil, description: "", + effect: :unknown, + header: "", + image_alternative_text: nil, + image: nil, + informed_entity: %InformedEntitySet{}, + lifecycle: :unknown, priority: :low, - url: "", - banner: "" + severity: 5, + updated_at: Timex.now(), + url: "" @type period_pair :: {DateTime.t() | nil, DateTime.t() | nil} @@ -51,30 +58,31 @@ defmodule Alerts.Alert do | :unknown @type severity :: 0..10 + @type lifecycle :: :ongoing | :upcoming | :ongoing_upcoming | :new | :unknown + @type id_t :: String.t() + @type t :: %Alerts.Alert{ id: id_t(), - header: String.t(), - informed_entity: IESet.t(), active_period: [period_pair], + banner: String.t() | nil, cause: String.t(), + description: String.t() | nil, effect: effect, - severity: severity, + header: String.t(), + image: String.t() | nil, + image_alternative_text: String.t() | nil, + informed_entity: InformedEntitySet.t(), lifecycle: lifecycle, - updated_at: DateTime.t(), - description: String.t() | nil, priority: Priority.priority_level(), - url: String.t() | nil, - banner: String.t() | nil + severity: severity, + updated_at: DateTime.t(), + url: String.t() | nil } @type icon_type :: :alert | :cancel | :none | :shuttle | :snow - use Timex - - @stops_repo Application.compile_env!(:dotcom, :repo_modules)[:stops] - @ongoing_effects [ :cancellation, :detour, @@ -107,12 +115,17 @@ defmodule Alerts.Alert do ] @diversion_effects [ + :detour, :shuttle, - :stop_closure, :station_closure, - :detour + :stop_closure, + :suspension ] + @lifecycles [:ongoing, :upcoming, :ongoing_upcoming, :new, :unknown] + + @stops_repo Application.compile_env!(:dotcom, :repo_modules)[:stops] + @spec new(Keyword.t()) :: t() def new(keywords \\ []) @@ -145,7 +158,7 @@ defmodule Alerts.Alert do @spec ensure_entity_set(map) :: t() defp ensure_entity_set(alert) do - %__MODULE__{alert | informed_entity: IESet.new(alert.informed_entity)} + %__MODULE__{alert | informed_entity: InformedEntitySet.new(alert.informed_entity)} end @spec all_types :: [effect] @@ -154,13 +167,24 @@ defmodule Alerts.Alert do @spec ongoing_effects :: [effect] def ongoing_effects, do: @ongoing_effects + @spec lifecycles :: [lifecycle] + def lifecycles, do: @lifecycles + @spec get_entity(t, :route | :stop | :route_type | :trip | :direction_id) :: Enumerable.t() @doc "Helper function for retrieving InformedEntity values for an alert" - def get_entity(%__MODULE__{informed_entity: %IESet{route: set}}, :route), do: set - def get_entity(%__MODULE__{informed_entity: %IESet{stop: set}}, :stop), do: set - def get_entity(%__MODULE__{informed_entity: %IESet{route_type: set}}, :route_type), do: set - def get_entity(%__MODULE__{informed_entity: %IESet{trip: set}}, :trip), do: set - def get_entity(%__MODULE__{informed_entity: %IESet{direction_id: set}}, :direction_id), do: set + def get_entity(%__MODULE__{informed_entity: %InformedEntitySet{route: set}}, :route), do: set + def get_entity(%__MODULE__{informed_entity: %InformedEntitySet{stop: set}}, :stop), do: set + + def get_entity(%__MODULE__{informed_entity: %InformedEntitySet{route_type: set}}, :route_type), + do: set + + def get_entity(%__MODULE__{informed_entity: %InformedEntitySet{trip: set}}, :trip), do: set + + def get_entity( + %__MODULE__{informed_entity: %InformedEntitySet{direction_id: set}}, + :direction_id + ), + do: set def access_alert_types do [elevator_closure: "Elevator", escalator_closure: "Escalator", access_issue: "Other"] @@ -232,8 +256,13 @@ defmodule Alerts.Alert do def high_severity_or_high_priority?(_), do: false @spec diversion?(t) :: boolean() - def diversion?(%{effect: effect}), - do: effect in @diversion_effects + def diversion?(alert) do + alert.effect in @diversion_effects && + alert.active_period + |> List.first() + |> Kernel.elem(0) + |> Timex.after?(alert.created_at) + end @spec municipality(t) :: String.t() | nil def municipality(alert) do diff --git a/lib/alerts/informed_entity.ex b/lib/alerts/informed_entity.ex index cefd2fab51..fc9fc535c1 100644 --- a/lib/alerts/informed_entity.ex +++ b/lib/alerts/informed_entity.ex @@ -1,43 +1,51 @@ defmodule Alerts.InformedEntity do - @fields [:route, :route_type, :stop, :trip, :direction_id, :facility, :activities] - @empty_activities MapSet.new() - defstruct route: nil, - route_type: nil, - stop: nil, - trip: nil, + defstruct activities: MapSet.new(), direction_id: nil, facility: nil, - activities: @empty_activities + route: nil, + route_type: nil, + stop: nil, + trip: nil @type t :: %Alerts.InformedEntity{ + activities: MapSet.t(activity), + direction_id: 0 | 1 | nil, + facility: String.t() | nil, route: String.t() | nil, route_type: String.t() | nil, stop: String.t() | nil, - trip: String.t() | nil, - direction_id: 0 | 1 | nil, - facility: String.t() | nil, - activities: MapSet.t(activity_type) + trip: String.t() | nil } - @type activity_type :: + @type activity :: :board + | :bringing_bike | :exit - | :ride | :park_car - | :bringing_bike + | :ride | :store_bike - | :using_wheelchair | :using_escalator + | :using_wheelchair - alias __MODULE__, as: IE + @activities [ + :board, + :bringing_bike, + :exit, + :park_car, + :ride, + :store_bike, + :using_escalator, + :using_wheelchair + ] - @doc """ + @spec activities() :: list(activity) + def activities(), do: @activities + @doc """ Given a keyword list (with keys matching our fields), returns a new InformedEntity. Additional keys are ignored. - """ - @spec from_keywords(list) :: IE.t() + @spec from_keywords(list) :: Alerts.InformedEntity.t() def from_keywords(options) do options |> Enum.map(&ensure_value_type/1) @@ -60,13 +68,14 @@ defmodule Alerts.InformedEntity do Otherwise the nil can match any value in the other InformedEntity. """ - @spec match?(IE.t(), IE.t()) :: boolean - def match?(%IE{} = first, %IE{} = second) do + @spec match?(Alerts.InformedEntity.t(), Alerts.InformedEntity.t()) :: boolean + def match?(%__MODULE__{} = first, %__MODULE__{} = second) do share_a_key?(first, second) && do_match?(first, second) end + @spec mapsets_match?(MapSet.t(), MapSet.t()) :: boolean() def mapsets_match?(%MapSet{} = a, %MapSet{} = b) - when a == @empty_activities or b == @empty_activities, + when a == %MapSet{} or b == %MapSet{}, do: true def mapsets_match?(%MapSet{} = a, %MapSet{} = b), do: has_intersect?(a, b) @@ -74,7 +83,9 @@ defmodule Alerts.InformedEntity do defp has_intersect?(a, b), do: Enum.any?(a, &(&1 in b)) defp do_match?(f, s) do - @fields + __MODULE__.__struct__() + |> Map.keys() + |> List.delete(:__struct__) |> Enum.all?(&key_match(Map.get(f, &1), Map.get(s, &1))) end @@ -85,7 +96,9 @@ defmodule Alerts.InformedEntity do defp key_match(_, _), do: false defp share_a_key?(first, second) do - @fields + __MODULE__.__struct__() + |> Map.keys() + |> List.delete(:__struct__) |> Enum.any?(&shared_key(Map.get(first, &1), Map.get(second, &1))) end diff --git a/lib/alerts/informed_entity_set.ex b/lib/alerts/informed_entity_set.ex index 83954bc6cb..68640fec68 100644 --- a/lib/alerts/informed_entity_set.ex +++ b/lib/alerts/informed_entity_set.ex @@ -6,30 +6,31 @@ defmodule Alerts.InformedEntitySet do it's present in the InformedEntitySet. If it's not, there's no way for it to match any of the InformedEntities inside. """ - alias Alerts.InformedEntity, as: IE - defstruct route: MapSet.new(), - route_type: MapSet.new(), - stop: MapSet.new(), - trip: MapSet.new(), + alias Alerts.InformedEntity + + defstruct activities: MapSet.new(), direction_id: MapSet.new(), + entities: [], facility: MapSet.new(), - activities: MapSet.new(), - entities: [] + route: MapSet.new(), + route_type: MapSet.new(), + stop: MapSet.new(), + trip: MapSet.new() @type t :: %__MODULE__{ + activities: MapSet.t(), + direction_id: MapSet.t(), + entities: [InformedEntity.t()], + facility: MapSet.t(), route: MapSet.t(), route_type: MapSet.t(), stop: MapSet.t(), - trip: MapSet.t(), - direction_id: MapSet.t(), - facility: MapSet.t(), - activities: MapSet.t(), - entities: [IE.t()] + trip: MapSet.t() } @doc "Create a new InformedEntitySet from a list of InformedEntitys" - @spec new([IE.t()]) :: t + @spec new([InformedEntity.t()]) :: t def new(%__MODULE__{} = entity_set) do entity_set end @@ -40,8 +41,8 @@ defmodule Alerts.InformedEntitySet do end @doc "Returns whether the given entity matches the set" - @spec match?(t, IE.t()) :: boolean - def match?(%__MODULE__{} = set, %IE{} = entity) do + @spec match?(t, InformedEntity.t()) :: boolean + def match?(%__MODULE__{} = set, %InformedEntity{} = entity) do entity |> Map.from_struct() |> Enum.all?(&field_in_set?(set, &1)) @@ -73,7 +74,7 @@ defmodule Alerts.InformedEntitySet do end defp field_in_set?(set, {:activities, %MapSet{} = value}) do - IE.mapsets_match?(set.activities, value) + InformedEntity.mapsets_match?(set.activities, value) end defp field_in_set?(set, {key, value}) do @@ -89,7 +90,7 @@ defmodule Alerts.InformedEntitySet do defp try_all_entity_match(true, set, entity) do # we only try matching against the whole set when the MapSets overlapped - Enum.any?(set, &IE.match?(&1, entity)) + Enum.any?(set, &InformedEntity.match?(&1, entity)) end end diff --git a/lib/alerts/parser.ex b/lib/alerts/parser.ex index 425583fbdc..8da9406420 100644 --- a/lib/alerts/parser.ex +++ b/lib/alerts/parser.ex @@ -10,17 +10,20 @@ defmodule Alerts.Parser do def parse(%JsonApi.Item{type: "alert", id: id, attributes: attributes}) do Alerts.Alert.new( id: id, - header: attributes["header"], - informed_entity: parse_informed_entity(attributes["informed_entity"]), active_period: Enum.map(attributes["active_period"], &active_period/1), - effect: effect(attributes), + banner: description(attributes["banner"]), cause: cause(attributes["cause"]), - severity: severity(attributes["severity"]), + created_at: parse_time(attributes["created_at"]), + description: description(attributes["description"]), + effect: effect(attributes), + header: attributes["header"], + image_alternative_text: attributes["image_alternative_text"], + image: attributes["image"], + informed_entity: parse_informed_entity(attributes["informed_entity"]), lifecycle: lifecycle(attributes["lifecycle"]), + severity: severity(attributes["severity"]), updated_at: parse_time(attributes["updated_at"]), - description: description(attributes["description"]), - url: description(attributes["url"]), - banner: description(attributes["banner"]) + url: description(attributes["url"]) ) end diff --git a/lib/alerts/priority.ex b/lib/alerts/priority.ex index 80821b6927..94631533ab 100644 --- a/lib/alerts/priority.ex +++ b/lib/alerts/priority.ex @@ -8,6 +8,11 @@ defmodule Alerts.Priority do @type priority_level :: :high | :low | :system @ongoing_effects Alerts.Alert.ongoing_effects() + @priority_levels [:high, :low, :system] + + @spec priority_levels() :: [priority_level] + def priority_levels, do: @priority_levels + @spec priority(map, DateTime.t()) :: priority_level def priority(map, now \\ Util.now()) diff --git a/lib/alerts/repo.ex b/lib/alerts/repo.ex index a712b11550..684c8eadfd 100644 --- a/lib/alerts/repo.ex +++ b/lib/alerts/repo.ex @@ -28,6 +28,21 @@ defmodule Alerts.Repo do |> Store.alerts(now) end + @doc """ + Get alerts that are diversion types: shuttle, station_closure, suspension. + + We sort them so that earlier alerts are displaed first. + """ + @spec diversions_by_route_ids([String.t()], DateTime.t()) :: [Alert.t()] + def diversions_by_route_ids(route_ids, now) do + route_ids + |> by_route_ids(now) + |> Enum.filter(&Alert.diversion?/1) + |> Enum.sort(fn a, b -> + a.active_period |> List.first() |> elem(0) < b.active_period |> List.first() |> elem(0) + end) + end + @spec by_route_types(Enumerable.t(), DateTime.t()) :: [Alert.t()] def by_route_types(types, now) do types diff --git a/lib/cms/helpers.ex b/lib/cms/helpers.ex index 421077ad79..3022960b29 100644 --- a/lib/cms/helpers.ex +++ b/lib/cms/helpers.ex @@ -69,6 +69,22 @@ defmodule CMS.Helpers do |> Enum.map(&File.from_api/1) end + @spec parse_page_types(map) :: list(String.t()) + def parse_page_types(%{} = data) do + data + |> Map.get("field_page_type", []) + |> Enum.map(&Map.get(&1, "name")) + |> Enum.filter(&(!is_nil(&1))) + end + + @spec parse_related_transit(map) :: list(String.t()) + def parse_related_transit(%{} = data) do + data + |> Map.get("field_related_transit", []) + |> Enum.map(&Map.get(&1, "name")) + |> Enum.filter(&(!is_nil(&1))) + end + @spec path_alias(map) :: String.t() | nil def path_alias(data) do data diff --git a/lib/cms/page.ex b/lib/cms/page.ex index a44b402f44..d0579768a5 100644 --- a/lib/cms/page.ex +++ b/lib/cms/page.ex @@ -10,6 +10,7 @@ defmodule CMS.Page do alias CMS.Page.{ Basic, + Diversions, Event, EventAgenda, Landing, @@ -73,6 +74,10 @@ defmodule CMS.Page do Redirect.from_api(api_data) end + defp parse(%{"field_page_type" => [%{"name" => "Diversions"}]} = api_data, preview_opts) do + Diversions.from_api(api_data, preview_opts) + end + # For all other node/content types from the CMS, use a common struct/template defp parse(%{"type" => [%{"target_type" => "node_type"}]} = api_data, preview_opts) do Basic.from_api(api_data, preview_opts) diff --git a/lib/cms/page/diversions.ex b/lib/cms/page/diversions.ex new file mode 100644 index 0000000000..7a1c8ab298 --- /dev/null +++ b/lib/cms/page/diversions.ex @@ -0,0 +1,64 @@ +defmodule CMS.Page.Diversions do + @moduledoc """ + Represents a basic "page" type in the Drupal CMS. Multiple + content types can use this struct, as defined in CMS.Page.Basic + """ + + alias CMS.Breadcrumbs + alias CMS.Partial.{MenuLinks, Paragraph} + alias Phoenix.HTML + + import CMS.Helpers, + only: [ + field_value: 2, + int_or_string_to_int: 1, + parse_body: 1, + parse_page_types: 1, + parse_paragraphs: 2, + parse_related_transit: 1 + ] + + defstruct id: nil, + body: HTML.raw(""), + breadcrumbs: [], + page_types: [], + paragraphs: [], + related_transit: [], + sidebar_menu: nil, + title: "" + + @type t :: %__MODULE__{ + id: integer | nil, + body: HTML.safe(), + breadcrumbs: [Util.Breadcrumb.t()], + page_types: [String.t()], + paragraphs: [Paragraph.t()], + related_transit: [String.t()], + sidebar_menu: MenuLinks.t() | nil, + title: String.t() + } + + @spec from_api(map, Keyword.t()) :: t + def from_api(%{} = data, preview_opts \\ []) do + %__MODULE__{ + id: int_or_string_to_int(field_value(data, "nid")), + body: parse_body(data), + breadcrumbs: Breadcrumbs.build(data), + page_types: parse_page_types(data), + paragraphs: parse_paragraphs(data, preview_opts), + related_transit: parse_related_transit(data), + sidebar_menu: parse_menu_links(data), + title: field_value(data, "title") || "" + } + end + + @spec parse_menu_links(map) :: MenuLinks.t() | nil + defp parse_menu_links(%{"field_sidebar_menu" => [menu_links_data]}) + when not is_nil(menu_links_data) do + MenuLinks.from_api(menu_links_data) + end + + defp parse_menu_links(_) do + nil + end +end diff --git a/lib/dotcom_web/controllers/cms_controller.ex b/lib/dotcom_web/controllers/cms_controller.ex index f4d637bbe9..a2e83126ba 100644 --- a/lib/dotcom_web/controllers/cms_controller.ex +++ b/lib/dotcom_web/controllers/cms_controller.ex @@ -19,6 +19,7 @@ defmodule DotcomWeb.CMSController do @generic [ Page.Basic, + Page.Diversions, Page.Person, Page.Landing, Page.Project, @@ -137,6 +138,17 @@ defmodule DotcomWeb.CMSController do end end + defp render_page(conn, %Page.Diversions{} = page) do + conn + |> assign( + :alerts, + Alerts.Repo.diversions_by_route_ids(page.related_transit, conn.assigns.date_time) + ) + |> assign(:breadcrumbs, page.breadcrumbs) + |> assign(:page, page) + |> render("diversions.html", conn: conn) + end + defp render_page(conn, %Page.Basic{} = page) do render_generic(conn, page, page.breadcrumbs) end diff --git a/lib/dotcom_web/templates/alert/_item.html.eex b/lib/dotcom_web/templates/alert/_item.html.eex index 7f92c9d666..fd6bda9a54 100644 --- a/lib/dotcom_web/templates/alert/_item.html.eex +++ b/lib/dotcom_web/templates/alert/_item.html.eex @@ -28,6 +28,11 @@ <%= if @alert.description do %>
The MBTA permits musical performances" + assert title == "Arts on the T" + end + + test "it strips out script tags", %{api_page: api_page} do + api_page = update_api_response(api_page, "body", "
Hi
") + + assert %Diversions{body: body} = Diversions.from_api(api_page) + assert HTML.safe_to_string(body) == "alert()Hi
" + end + + test "it parses a sidebar menu" do + api_page = Static.basic_page_with_sidebar_response() + + assert %Diversions{ + sidebar_menu: %MenuLinks{ + blurb: + {:safe, + "Visiting Boston? Learn more about some of the popular spots you can get to on the T.
"} + } + } = Diversions.from_api(api_page) + end + end +end diff --git a/test/cms/page_test.exs b/test/cms/page_test.exs index 9fbc1f3981..7ccfaaa0f8 100644 --- a/test/cms/page_test.exs +++ b/test/cms/page_test.exs @@ -11,6 +11,12 @@ defmodule PageTest do describe "from_api/1" do test "switches on the node type in the json response and returns the proper page struct" do assert %Page.Basic{} = Page.from_api(Static.basic_page_response()) + + diversions_data = + Static.basic_page_response() |> Map.put("field_page_type", [%{"name" => "Diversions"}]) + + assert %Page.Diversions{} = Page.from_api(diversions_data) + assert %Page.Event{} = Page.from_api(List.first(Static.events_response())) assert %Page.Landing{} = Page.from_api(Static.landing_page_response()) assert %Page.NewsEntry{} = Page.from_api(List.first(Static.news_repo())) diff --git a/test/dotcom/transit_near_me_test.exs b/test/dotcom/transit_near_me_test.exs index 723de5a6be..0285110431 100644 --- a/test/dotcom/transit_near_me_test.exs +++ b/test/dotcom/transit_near_me_test.exs @@ -4,7 +4,7 @@ defmodule Dotcom.TransitNearMeTest do import Mox import Mox - import Test.Support.Factory.Prediction + import Test.Support.Factories.Predictions.Prediction alias LocationService.Address alias Predictions.Prediction diff --git a/test/dotcom/trip_plan/itinerary_row_test.exs b/test/dotcom/trip_plan/itinerary_row_test.exs index 1ab9a3c06b..05722e915b 100644 --- a/test/dotcom/trip_plan/itinerary_row_test.exs +++ b/test/dotcom/trip_plan/itinerary_row_test.exs @@ -327,10 +327,10 @@ defmodule TripPlan.ItineraryRowTest do stub(MBTA.Api.Mock, :get_json, fn path, _ -> cond do String.contains?(path, "trips") -> - %JsonApi{data: [Test.Support.Factory.MbtaApi.build(:trip_item)]} + %JsonApi{data: [Test.Support.Factories.MBTA.Api.build(:trip_item)]} String.contains?(path, "routes") -> - %JsonApi{data: [Test.Support.Factory.MbtaApi.build(:route_item)]} + %JsonApi{data: [Test.Support.Factories.MBTA.Api.build(:route_item)]} true -> %JsonApi{data: []} diff --git a/test/dotcom/trip_plan/location_test.exs b/test/dotcom/trip_plan/location_test.exs index 688cface3c..4bd8f7f0fe 100644 --- a/test/dotcom/trip_plan/location_test.exs +++ b/test/dotcom/trip_plan/location_test.exs @@ -4,7 +4,7 @@ defmodule Dotcom.TripPlan.LocationTest do alias TripPlan.NamedPosition import Mox - import Test.Support.Factory.LocationService + import Test.Support.Factories.LocationService.LocationService setup :verify_on_exit! diff --git a/test/dotcom/trip_plan/query_test.exs b/test/dotcom/trip_plan/query_test.exs index 57e4dde484..24fa5c9220 100644 --- a/test/dotcom/trip_plan/query_test.exs +++ b/test/dotcom/trip_plan/query_test.exs @@ -3,7 +3,7 @@ defmodule Dotcom.TripPlan.QueryTest do import Dotcom.TripPlan.Query import Mox - import Test.Support.Factory.LocationService + import Test.Support.Factories.LocationService.LocationService alias Dotcom.TripPlan.Query alias TripPlan.NamedPosition diff --git a/test/dotcom_web/channels/vehicle_map_marker_channel_test.exs b/test/dotcom_web/channels/vehicle_map_marker_channel_test.exs index 2278c9c62a..7ac24ebf1d 100644 --- a/test/dotcom_web/channels/vehicle_map_marker_channel_test.exs +++ b/test/dotcom_web/channels/vehicle_map_marker_channel_test.exs @@ -7,7 +7,7 @@ defmodule DotcomWeb.VehicleMapMarkerChannelTest do import Mock import Mox - import Test.Support.Factory.MbtaApi + import Test.Support.Factories.MBTA.Api @vehicles [ %Vehicle{ diff --git a/test/dotcom_web/controllers/places_controller_test.exs b/test/dotcom_web/controllers/places_controller_test.exs index 76907da2c1..8414ae4e8b 100644 --- a/test/dotcom_web/controllers/places_controller_test.exs +++ b/test/dotcom_web/controllers/places_controller_test.exs @@ -4,7 +4,7 @@ defmodule DotcomWeb.PlacesControllerTest do import DotcomWeb.PlacesController import Mox - import Test.Support.Factory.LocationService + import Test.Support.Factories.LocationService.LocationService setup :verify_on_exit! diff --git a/test/dotcom_web/controllers/schedule/line/helpers_test.exs b/test/dotcom_web/controllers/schedule/line/helpers_test.exs index ad7b042f68..d01fc99c79 100644 --- a/test/dotcom_web/controllers/schedule/line/helpers_test.exs +++ b/test/dotcom_web/controllers/schedule/line/helpers_test.exs @@ -2,7 +2,7 @@ defmodule DotcomWeb.ScheduleController.Line.HelpersTest do use ExUnit.Case, async: false import Mox - import Test.Support.Factory.MbtaApi + import Test.Support.Factories.MBTA.Api alias Routes.{Route} alias DotcomWeb.ScheduleController.Line.Helpers alias Stops.{RouteStops, RouteStop, Stop} diff --git a/test/dotcom_web/controllers/schedule/predictions_test.exs b/test/dotcom_web/controllers/schedule/predictions_test.exs index c07804de3b..294fa63766 100644 --- a/test/dotcom_web/controllers/schedule/predictions_test.exs +++ b/test/dotcom_web/controllers/schedule/predictions_test.exs @@ -3,7 +3,7 @@ defmodule DotcomWeb.ScheduleController.PredictionsTest do import DotcomWeb.ScheduleController.Predictions import Mox - import Test.Support.Factory.Prediction + import Test.Support.Factories.Predictions.Prediction setup %{conn: conn} do conn = diff --git a/test/dotcom_web/controllers/schedule/trip_info_test.exs b/test/dotcom_web/controllers/schedule/trip_info_test.exs index b610e8f617..e028e1a63a 100644 --- a/test/dotcom_web/controllers/schedule/trip_info_test.exs +++ b/test/dotcom_web/controllers/schedule/trip_info_test.exs @@ -3,7 +3,7 @@ defmodule DotcomWeb.ScheduleController.TripInfoTest do import DotcomWeb.ScheduleController.TripInfo import Mox - import Test.Support.Factory.Prediction + import Test.Support.Factories.Predictions.Prediction alias DotcomWeb.ScheduleController.TripInfo alias Schedules.{Schedule, Trip} diff --git a/test/dotcom_web/controllers/transit_near_me/location_test.exs b/test/dotcom_web/controllers/transit_near_me/location_test.exs index 3307819c92..3dfe07412b 100644 --- a/test/dotcom_web/controllers/transit_near_me/location_test.exs +++ b/test/dotcom_web/controllers/transit_near_me/location_test.exs @@ -3,7 +3,7 @@ defmodule DotcomWeb.TransitNearMeController.LocationTest do alias DotcomWeb.TransitNearMeController.Location import Mox - import Test.Support.Factory.LocationService + import Test.Support.Factories.LocationService.LocationService setup :verify_on_exit! diff --git a/test/dotcom_web/controllers/transit_near_me_controller_test.exs b/test/dotcom_web/controllers/transit_near_me_controller_test.exs index fc90f46f9e..45cb1c39e3 100644 --- a/test/dotcom_web/controllers/transit_near_me_controller_test.exs +++ b/test/dotcom_web/controllers/transit_near_me_controller_test.exs @@ -7,7 +7,7 @@ defmodule DotcomWeb.TransitNearMeControllerTest do alias Stops.Stop import Mox - import Test.Support.Factory.MbtaApi + import Test.Support.Factories.MBTA.Api @orange_line %{ id: "Orange", diff --git a/test/dotcom_web/controllers/trip_plan_controller_test.exs b/test/dotcom_web/controllers/trip_plan_controller_test.exs index c6e5075646..cce4f0877b 100644 --- a/test/dotcom_web/controllers/trip_plan_controller_test.exs +++ b/test/dotcom_web/controllers/trip_plan_controller_test.exs @@ -10,7 +10,7 @@ defmodule DotcomWeb.TripPlanControllerTest do doctest DotcomWeb.TripPlanController import Mox - import Test.Support.Factory.MbtaApi + import Test.Support.Factories.MBTA.Api @system_time "2017-01-01T12:20:00-05:00" @morning %{ @@ -166,7 +166,10 @@ defmodule DotcomWeb.TripPlanControllerTest do end) stub(LocationService.Mock, :geocode, fn name -> - {:ok, Test.Support.Factory.LocationService.build_list(2, :address, %{formatted: name})} + {:ok, + Test.Support.Factories.LocationService.LocationService.build_list(2, :address, %{ + formatted: name + })} end) stub(Stops.Repo.Mock, :get_parent, fn _ -> diff --git a/test/dotcom_web/views/page_content_view_test.exs b/test/dotcom_web/views/page_content_view_test.exs index c03695136b..5ddb60eb81 100644 --- a/test/dotcom_web/views/page_content_view_test.exs +++ b/test/dotcom_web/views/page_content_view_test.exs @@ -3,7 +3,7 @@ defmodule DotcomWeb.CMS.PageViewTest do import DotcomWeb.CMS.PageView - alias CMS.Page.{Basic, Project} + alias CMS.Page.{Basic, Diversions, Project} alias CMS.Partial.Paragraph.{ContentList, CustomHTML} alias Phoenix.HTML @@ -18,6 +18,24 @@ defmodule DotcomWeb.CMS.PageViewTest do assert rendered =~ "Hello
" end + + test "renders a CMS.Page.Diversions with sub-templates", %{conn: conn} do + # Setup + food = Faker.Food.description() + + paragraph = %Diversions{ + body: HTML.raw("#{food}
") + } + + # Exercise + rendered = + paragraph + |> render_page(conn) + |> HTML.safe_to_string() + + # Verify + assert rendered =~ "#{food}
" + end end describe "sidebar_classes/2" do diff --git a/test/leaflet/map_data/polyline_test.exs b/test/leaflet/map_data/polyline_test.exs index f9a19afa21..5b26bafaeb 100644 --- a/test/leaflet/map_data/polyline_test.exs +++ b/test/leaflet/map_data/polyline_test.exs @@ -1,7 +1,7 @@ defmodule Leaflet.MapData.PolylineTest do use ExUnit.Case, async: true - import Test.Support.Factory.RoutePattern + import Test.Support.Factories.RoutePatterns.RoutePattern alias Leaflet.MapData.Polyline diff --git a/test/predicted_schedule_test.exs b/test/predicted_schedule_test.exs index f09d3753a9..bb5090726c 100644 --- a/test/predicted_schedule_test.exs +++ b/test/predicted_schedule_test.exs @@ -8,7 +8,7 @@ defmodule PredictedScheduleTest do import PredictedSchedule import Mock import Mox - import Test.Support.Factory.Prediction + import Test.Support.Factories.Predictions.Prediction # set to the end of a month to uncover issues with sorting times as # structs, rather than as integers diff --git a/test/predictions/repo_test.exs b/test/predictions/repo_test.exs index 60804c06d2..39e22f07a7 100644 --- a/test/predictions/repo_test.exs +++ b/test/predictions/repo_test.exs @@ -2,7 +2,7 @@ defmodule Predictions.RepoTest do use ExUnit.Case, async: true import Mox - import Test.Support.Factory.MbtaApi + import Test.Support.Factories.MBTA.Api alias Predictions.Repo alias Routes.Route diff --git a/test/predictions/stream_topic_test.exs b/test/predictions/stream_topic_test.exs index a32591bba2..da3f6b30c5 100644 --- a/test/predictions/stream_topic_test.exs +++ b/test/predictions/stream_topic_test.exs @@ -7,7 +7,7 @@ defmodule Predictions.StreamTopicTest do import Mox import Predictions.StreamTopic - import Test.Support.Factory.RoutePattern + import Test.Support.Factories.RoutePatterns.RoutePattern alias Predictions.StreamTopic diff --git a/test/route_patterns/repo_test.exs b/test/route_patterns/repo_test.exs index 92697dbb6c..5be3260390 100644 --- a/test/route_patterns/repo_test.exs +++ b/test/route_patterns/repo_test.exs @@ -2,7 +2,7 @@ defmodule RoutePatterns.RepoTest do use ExUnit.Case, async: true import Mox - import Test.Support.Factory.MbtaApi + import Test.Support.Factories.MBTA.Api alias RoutePatterns.RoutePattern diff --git a/test/stops/nearby_test.exs b/test/stops/nearby_test.exs index e69c0a2dcb..989433a694 100644 --- a/test/stops/nearby_test.exs +++ b/test/stops/nearby_test.exs @@ -6,7 +6,7 @@ defmodule Stops.NearbyTest do import Mox import Stops.Nearby - import Test.Support.Factory.MbtaApi + import Test.Support.Factories.MBTA.Api @latitude 42.577 @longitude -71.225 diff --git a/test/stops/repo_test.exs b/test/stops/repo_test.exs index 5a4854c4fb..ded0fc3302 100644 --- a/test/stops/repo_test.exs +++ b/test/stops/repo_test.exs @@ -3,7 +3,7 @@ defmodule Stops.RepoTest do import Mox import Stops.Repo - import Test.Support.Factory.MbtaApi + import Test.Support.Factories.MBTA.Api alias Stops.Stop @direction_id Faker.Util.pick([0, 1]) diff --git a/test/stops/route_stops_test.exs b/test/stops/route_stops_test.exs index a1039d43d3..96f3513ece 100644 --- a/test/stops/route_stops_test.exs +++ b/test/stops/route_stops_test.exs @@ -2,7 +2,7 @@ defmodule Stops.RouteStopsTest do use ExUnit.Case, async: true import Mox - import Test.Support.Factory.MbtaApi + import Test.Support.Factories.MBTA.Api alias Routes.Route alias Stops.{RouteStop, RouteStops, Stop} diff --git a/test/support/factories/alerts/alert.ex b/test/support/factories/alerts/alert.ex new file mode 100644 index 0000000000..4fc24f3760 --- /dev/null +++ b/test/support/factories/alerts/alert.ex @@ -0,0 +1,31 @@ +defmodule Test.Support.Factories.Alerts.Alert do + @moduledoc """ + Generated fake data for %Alerts.Alert{} + """ + + use ExMachina + + alias Alerts.{Alert, Priority} + alias Test.Support.Factories.Alerts.InformedEntitySet + + def alert_factory do + %Alert{ + id: :rand.uniform(999) |> Integer.to_string(), + active_period: [{Faker.DateTime.forward(1), Faker.DateTime.forward(2)}], + banner: Faker.Lorem.Shakespeare.king_richard_iii(), + cause: Faker.Lorem.Shakespeare.king_richard_iii(), + created_at: Timex.now(), + description: Faker.Lorem.Shakespeare.king_richard_iii(), + effect: Alert.all_types() |> Faker.Util.pick(), + header: Faker.Lorem.Shakespeare.king_richard_iii(), + image: Faker.Internet.image_url(), + image_alternative_text: Faker.Lorem.Shakespeare.king_richard_iii(), + informed_entity: InformedEntitySet.build(:informed_entity_set), + lifecycle: Alert.lifecycles() |> Faker.Util.pick(), + priority: Priority.priority_levels() |> Faker.Util.pick(), + severity: :rand.uniform(10), + updated_at: Timex.now(), + url: Faker.Internet.url() + } + end +end diff --git a/test/support/factories/alerts/informed_entity.ex b/test/support/factories/alerts/informed_entity.ex new file mode 100644 index 0000000000..3e2a68bb00 --- /dev/null +++ b/test/support/factories/alerts/informed_entity.ex @@ -0,0 +1,22 @@ +defmodule Test.Support.Factories.Alerts.InformedEntity do + @moduledoc """ + Generated fake data for %Alerts.InformedEntity{} + """ + + use ExMachina + + alias Test.Support.Factories.Alerts.InformedEntity + alias Alerts.InformedEntity + + def informed_entity_factory do + %InformedEntity{ + activities: InformedEntity.activities() |> Enum.take_random(3), + direction_id: Faker.Util.pick([0, 1]), + facility: Faker.Lorem.word(), + route: Faker.Lorem.word(), + route_type: Faker.Lorem.word(), + stop: Faker.Lorem.word(), + trip: Faker.Lorem.word() + } + end +end diff --git a/test/support/factories/alerts/informed_entity_set.ex b/test/support/factories/alerts/informed_entity_set.ex new file mode 100644 index 0000000000..a48641b158 --- /dev/null +++ b/test/support/factories/alerts/informed_entity_set.ex @@ -0,0 +1,16 @@ +defmodule Test.Support.Factories.Alerts.InformedEntitySet do + @moduledoc """ + Generated fake data for %Alerts.InformedEntitySet{} + """ + + use ExMachina + + alias Alerts.InformedEntitySet + alias Test.Support.Factories.Alerts.InformedEntity + + def informed_entity_set_factory do + informed_entity = InformedEntity.build(:informed_entity) + + InformedEntitySet.new([informed_entity]) + end +end diff --git a/test/support/factory/location_service.ex b/test/support/factories/location_service/location_service.ex similarity index 89% rename from test/support/factory/location_service.ex rename to test/support/factories/location_service/location_service.ex index f813949755..1ec4801012 100644 --- a/test/support/factory/location_service.ex +++ b/test/support/factories/location_service/location_service.ex @@ -1,4 +1,4 @@ -defmodule Test.Support.Factory.LocationService do +defmodule Test.Support.Factories.LocationService.LocationService do @moduledoc """ Data generation for LocationService outputs. """ diff --git a/test/support/factory/mbta_api.ex b/test/support/factories/mbta/api.ex similarity index 99% rename from test/support/factory/mbta_api.ex rename to test/support/factories/mbta/api.ex index 9a3653e85e..b80c90cd01 100644 --- a/test/support/factory/mbta_api.ex +++ b/test/support/factories/mbta/api.ex @@ -1,4 +1,4 @@ -defmodule Test.Support.Factory.MbtaApi do +defmodule Test.Support.Factories.MBTA.Api do @moduledoc """ Generated fake data for MBTA.Api """ diff --git a/test/support/factory/prediction.ex b/test/support/factories/predictions/prediction.ex similarity index 74% rename from test/support/factory/prediction.ex rename to test/support/factories/predictions/prediction.ex index 057b21ba71..cc5d7176dc 100644 --- a/test/support/factory/prediction.ex +++ b/test/support/factories/predictions/prediction.ex @@ -1,4 +1,4 @@ -defmodule Test.Support.Factory.Prediction do +defmodule Test.Support.Factories.Predictions.Prediction do @moduledoc """ Generated fake data for %RoutePattern{} """ diff --git a/test/support/factory/route_pattern.ex b/test/support/factories/route_patterns/route_pattern.ex similarity index 73% rename from test/support/factory/route_pattern.ex rename to test/support/factories/route_patterns/route_pattern.ex index 4c08fabc87..df9f941757 100644 --- a/test/support/factory/route_pattern.ex +++ b/test/support/factories/route_patterns/route_pattern.ex @@ -1,4 +1,4 @@ -defmodule Test.Support.Factory.RoutePattern do +defmodule Test.Support.Factories.RoutePatterns.RoutePattern do @moduledoc """ Generated fake data for %RoutePattern{} """