From 4fc6572a6f956152ef38da51fdf488c9738fa02d Mon Sep 17 00:00:00 2001 From: Josh Larson Date: Mon, 31 Aug 2026 17:33:45 -0400 Subject: [PATCH 1/6] feat(robot): Update all `:express_bus` prices to match `:local_bus` --- lib/fares/fare_info.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/fares/fare_info.ex b/lib/fares/fare_info.ex index 7e451a206c..5cce44eeae 100644 --- a/lib/fares/fare_info.ex +++ b/lib/fares/fare_info.ex @@ -202,10 +202,10 @@ defmodule Fares.FareInfo do charlie_card_price: "1.70", day_reduced_price: "0.85", week_reduced_price: "10.00", - month_reduced_price: "67.00", + month_reduced_price: "30.00", day_pass_price: "11.00", week_pass_price: "22.50", - month_pass_price: "136.00" + month_pass_price: "55.00" }, %{ mode: :ferry, From 47d6bfffd7994d92c414e447667a524899eeabc1 Mon Sep 17 00:00:00 2001 From: Josh Larson Date: Mon, 31 Aug 2026 18:03:08 -0400 Subject: [PATCH 2/6] feat(robot): Update transfer logic to allow unlimited subway/bus/ferry transfers --- lib/dotcom/trip_plan/fares.ex | 72 +++++++------- lib/dotcom/trip_plan/transfer.ex | 120 ++++-------------------- test/dotcom/trip_plan/fares_test.exs | 32 +++++-- test/dotcom/trip_plan/transfer_test.exs | 82 ++++------------ 4 files changed, 97 insertions(+), 209 deletions(-) diff --git a/lib/dotcom/trip_plan/fares.ex b/lib/dotcom/trip_plan/fares.ex index 26e4e9abd6..bfcff9fab9 100644 --- a/lib/dotcom/trip_plan/fares.ex +++ b/lib/dotcom/trip_plan/fares.ex @@ -25,48 +25,50 @@ defmodule Dotcom.TripPlan.Fares do nil else transit_legs - |> Stream.with_index() - |> Enum.reduce(0, &add_fares(&1, &2, transit_legs)) + |> group_transferable_legs() + |> Enum.map(&group_fare/1) + |> Enum.sum() end end - defp add_fares({leg, 0}, 0, _), do: cents_for_leg(leg) - - # credo:disable-for-next-line - defp add_fares({leg, leg_index}, total, transit_legs) do - # Look at this transit leg and previous transit leg(s) - two_legs = transit_legs |> Enum.slice(leg_index - 1, 2) - three_legs = transit_legs |> Enum.slice(leg_index - 2, 3) - # If this is part of a free transfer, don't add fare - cond do - Transfer.subway_transfer?(three_legs) -> - total - - Transfer.bus_to_subway_transfer?(three_legs) -> - if total == cents_for_leg(List.first(three_legs)), - do: total + 70, - else: total - - Transfer.maybe_transfer?(three_legs) -> - total - - Transfer.subway_transfer?(two_legs) -> - total - - Transfer.subway_after_sl1_from_airport?(two_legs) -> - total - - Transfer.bus_to_subway_transfer?(two_legs) -> - total + 70 - - Transfer.maybe_transfer?(two_legs) -> - total + # Splits legs into consecutive groups that can be transferred between one + # another (per `Transfer.maybe_transfer?/1`). There's no limit on the + # number of transfers within a group. + @spec group_transferable_legs([Leg.t()]) :: [[Leg.t()]] + defp group_transferable_legs([]), do: [] + + defp group_transferable_legs([first_leg | rest_legs]) do + rest_legs + |> Enum.reduce([[first_leg]], fn leg, [current_group | finished_groups] -> + if Transfer.maybe_transfer?([List.last(current_group), leg]) do + [current_group ++ [leg] | finished_groups] + else + [[leg], current_group | finished_groups] + end + end) + |> Enum.reverse() + end - true -> - total + cents_for_leg(leg) + # A group of transferable legs is charged only the cost of its + # highest-priced leg -- unless it starts with a free SL1 boarding from the + # airport, in which case the whole group remains free. + @spec group_fare([Leg.t()]) :: non_neg_integer() + defp group_fare([first_leg | _] = group) do + if free_airport_boarding?(first_leg) do + 0 + else + group + |> Enum.map(¢s_for_leg/1) + |> Enum.max() end end + defp free_airport_boarding?(%Leg{route: route, from: from}) do + Fares.silver_line_airport_stop?(mbta_id(route), mbta_id(from.stop)) + end + + defp free_airport_boarding?(_), do: false + # Massport shuttles are free def cents_for_leg(leg) when agency_name?(leg, "Massport"), do: 0 diff --git a/lib/dotcom/trip_plan/transfer.ex b/lib/dotcom/trip_plan/transfer.ex index ce85decb78..04b63a0f34 100644 --- a/lib/dotcom/trip_plan/transfer.ex +++ b/lib/dotcom/trip_plan/transfer.ex @@ -4,71 +4,42 @@ defmodule Dotcom.TripPlan.Transfer do The MBTA allows transfers between services depending on the fare media used and the amount paid. + Local Bus, Express Bus, Silver Line, Subway, and Ferry legs can all be + freely transferred between one another (in any combination, for any + number of consecutive transfers), so a chain of such legs is only + charged the cost of its single highest-priced leg. + This logic may be superseded by the upcoming fares work. """ import Dotcom.TripPlan.Helpers - alias OpenTripPlannerClient.Schema.{Leg, Place, Route, Stop} + alias OpenTripPlannerClient.Schema.{Leg, Route} # Paying a single-ride fare for the first may get you a transfer to the second # (can't be certain, as it depends on media used)! @single_ride_transfers %{ - :bus => [:subway, :bus], - :subway => [:bus], + :bus => [:subway, :bus, :ferry], + :subway => [:bus, :subway, :ferry], + :ferry => [:bus, :subway, :ferry], :express_bus => [:subway, :bus, :express_bus] } - # For Local Bus, Express Bus, Silver Line, and/or Subway, transfer up to two times - # and pay only the cost of the highest-priced service. - @multi_ride_transfers [ - [:bus, :subway, :bus], - [:bus, :subway, :subway], - [:bus, :bus, :subway], - [:bus, :bus, :bus], - [:subway, :bus, :bus], - [:subway, :bus, :subway], - [:subway, :subway, :bus], - [:subway, :subway, :subway] - ] - - @doc "Searches a list of legs for evidence of an in-station subway transfer." - @spec subway_transfer?([Leg.t()]) :: boolean - def subway_transfer?([first_leg, next_leg]) - when agency_name?(first_leg, "MBTA") and agency_name?(next_leg, "MBTA") do - same_station?(first_leg.to, next_leg.from) and subway?(first_leg.route) and - subway?(next_leg.route) - end - - def subway_transfer?([first_leg, next_leg, last_leg]) - when agency_name?(first_leg, "MBTA") and agency_name?(next_leg, "MBTA") and - agency_name?(last_leg, "MBTA") do - same_station?(first_leg.to, next_leg.from) and subway?(first_leg.route) and - subway?(next_leg.route) and same_station?(next_leg.to, last_leg.from) and - subway?(last_leg.route) - end - - def subway_transfer?([_ | legs]), do: subway_transfer?(legs) - - def subway_transfer?(_), do: false - @doc """ - Takes a set of legs and returns true if there might be a transfer between the legs, based on the lists in @single_ride_transfers and @multi_ride_transfers. + Takes a set of legs and returns true if there might be a transfer between + every consecutive pair of legs, based on the list in @single_ride_transfers. + Any number of legs may be passed; there's no limit on how many consecutive + transfers can be made. Exceptions: - no transfers from bus route to same bus route - no transfers from a shuttle to any other mode """ @spec maybe_transfer?([Leg.t()]) :: boolean - def maybe_transfer?([first_leg, middle_leg, last_leg]) - when agency_name?(first_leg, "MBTA") and agency_name?(middle_leg, "MBTA") and - agency_name?(last_leg, "MBTA") do - @multi_ride_transfers - |> Enum.member?( - Enum.map([first_leg.route, middle_leg.route, last_leg.route], &to_fare_atom/1) - ) - |> Kernel.and(maybe_transfer?([first_leg, middle_leg])) - |> Kernel.and(maybe_transfer?([middle_leg, last_leg])) + def maybe_transfer?([_first, _second, _third | _] = legs) do + legs + |> Enum.chunk_every(2, 1, :discard) + |> Enum.all?(&maybe_transfer?/1) end def maybe_transfer?([from, to]) when agency_name?(from, "MBTA") and agency_name?(to, "MBTA") do @@ -103,53 +74,6 @@ defmodule Dotcom.TripPlan.Transfer do end end - @doc """ - Is there a bus to subway transfer? - """ - def bus_to_subway_transfer?([first, middle, last]) - when agency_name?(first, "MBTA") and agency_name?(middle, "MBTA") and - agency_name?(last, "MBTA") do - (bus_to_subway_transfer?([first, middle]) || - bus_to_subway_transfer?([middle, last])) && !commuter_rail?([first, middle, last]) - end - - def bus_to_subway_transfer?([from, to]) - when agency_name?(from, "MBTA") and agency_name?(to, "MBTA") do - bus?(from.route) && subway?(to.route) - end - - def bus_to_subway_transfer?(_), do: false - - def commuter_rail?([_, _, _] = legs) do - legs |> Enum.any?(fn leg -> commuter_rail?(leg) end) - end - - def commuter_rail?(%{mode: :RAIL}) do - true - end - - def commuter_rail?(_) do - false - end - - defp same_station?(%Place{stop: %Stop{} = from_stop}, %Place{stop: %Stop{} = to_stop}) do - cond do - is_nil(from_stop.parent_station) or is_nil(to_stop.parent_station) -> - false - - from_stop.parent_station == to_stop.parent_station -> - true - - true -> - # Check whether this is DTX <-> Park St via. the Winter St. Concourse - stop_id = mbta_id(to_stop.parent_station) - other_stop_id = mbta_id(from_stop.parent_station) - Enum.all?([stop_id, other_stop_id], &Enum.member?(["place-dwnxg", "place-pktrm"], &1)) - end - end - - defp same_station?(_, _), do: false - defp bus?(route) when route.type == 3 and not mbta_shuttle?(route) do route_id = mbta_id(route) not Fares.silver_line_rapid_transit?(route_id) @@ -171,14 +95,4 @@ defmodule Dotcom.TripPlan.Transfer do end def bus_or_subway?(_), do: false - - def subway_after_sl1_from_airport?([first_leg, second_leg]) - when agency_name?(first_leg, "MBTA") and agency_name?(second_leg, "MBTA") and - second_leg.route.type in [0, 1] do - from_route_id = mbta_id(first_leg.route) - from_stop_id = mbta_id(first_leg.from) - Fares.silver_line_airport_stop?(from_route_id, from_stop_id) - end - - def subway_after_sl1_from_airport?(_), do: false end diff --git a/test/dotcom/trip_plan/fares_test.exs b/test/dotcom/trip_plan/fares_test.exs index 4dd8079ca6..12fa4f3647 100644 --- a/test/dotcom/trip_plan/fares_test.exs +++ b/test/dotcom/trip_plan/fares_test.exs @@ -60,7 +60,6 @@ defmodule Dotcom.TripPlan.FaresTest do assert fare2 == fare3 end - @tag skip: "The code is incorrect" test "free transfers for up to 3 consecutive bus or subway legs" do bus_or_subway_routes = [ build(:route, @@ -192,7 +191,7 @@ defmodule Dotcom.TripPlan.FaresTest do assert fare <= one_subway_fare end - test "invalid two leg subway transfers (eg red <-> blue)" do + test "subway to subway transfers are free even between different lines/stations (eg red <-> blue)" do start_leg = build(:transit_leg, from: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-start"})), @@ -211,7 +210,7 @@ defmodule Dotcom.TripPlan.FaresTest do route: build(:route, agency: build(:agency, name: "MBTA"), - type: 0 + type: 1 ) ) @@ -229,10 +228,10 @@ defmodule Dotcom.TripPlan.FaresTest do |> fare() fare = build(:itinerary, legs: [start_leg, end_leg]) |> fare() - assert fare > one_subway_fare + assert fare == one_subway_fare end - test "invalid three leg subway transfers (eg red <-> blue)" do + test "subway to subway to subway transfers are free even between different lines/stations (eg red <-> blue)" do start_leg = build(:transit_leg, from: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-start"})), @@ -251,7 +250,7 @@ defmodule Dotcom.TripPlan.FaresTest do route: build(:route, agency: build(:agency, name: "MBTA"), - type: 0 + type: 1 ) ) @@ -280,7 +279,26 @@ defmodule Dotcom.TripPlan.FaresTest do |> fare() fare = build(:itinerary, legs: [start_leg, mid_leg, end_leg]) |> fare() - assert fare > one_subway_fare + assert fare == one_subway_fare + end + + test "unlimited transfers between bus, subway, and ferry only charge the highest-priced leg" do + bus_leg = + build(:transit_leg, + route: build(:route, agency: build(:agency, name: "MBTA"), type: 3, desc: "Local Bus") + ) + + subway_leg = + build(:transit_leg, route: build(:route, agency: build(:agency, name: "MBTA"), type: 0)) + + ferry_leg = + build(:transit_leg, route: build(:route, agency: build(:agency, name: "MBTA"), type: 4)) + + itinerary = build(:itinerary, legs: [bus_leg, subway_leg, ferry_leg, bus_leg, subway_leg]) + + fares_for_legs = [bus_leg, subway_leg, ferry_leg] |> Enum.map(¢s_for_leg/1) + + assert fare(itinerary) == Enum.max(fares_for_legs) end describe "cents_for_leg/1" do diff --git a/test/dotcom/trip_plan/transfer_test.exs b/test/dotcom/trip_plan/transfer_test.exs index 32ac64adb1..2e948cbd12 100644 --- a/test/dotcom/trip_plan/transfer_test.exs +++ b/test/dotcom/trip_plan/transfer_test.exs @@ -100,12 +100,19 @@ defmodule Dotcom.TripPlan.TransferTest do refute [cr_leg(), sl_rapid_leg()] |> maybe_transfer? end - test "ferry -> any other mode" do - refute [ferry_leg(), ferry_leg()] |> maybe_transfer? - refute [ferry_leg(), subway_leg()] |> maybe_transfer? - refute [ferry_leg(), bus_leg()] |> maybe_transfer? + test "ferry -> bus, subway, or ferry" do + assert [ferry_leg(), ferry_leg()] |> maybe_transfer? + assert [ferry_leg(), subway_leg()] |> maybe_transfer? + assert [ferry_leg(), bus_leg()] |> maybe_transfer? + assert [ferry_leg(), sl_rapid_leg()] |> maybe_transfer? + end + + test "ferry -> express bus is not a transfer" do refute [ferry_leg(), xp_leg()] |> maybe_transfer? - refute [ferry_leg(), sl_rapid_leg()] |> maybe_transfer? + end + + test "subway -> subway" do + assert [subway_leg(), subway_leg()] |> maybe_transfer? end test "shuttle -> subway or bus" do @@ -132,68 +139,15 @@ defmodule Dotcom.TripPlan.TransferTest do test "subway -> bus -> subway" do assert [subway_leg(), bus_leg(), subway_leg()] |> maybe_transfer? end - end - - describe "subway_transfer?/1" do - test "handles transfers between different stops" do - [parent1, parent2] = Faker.Util.sample_uniq(2, fn -> build(:parent_stop) end) - - leg1 = - build(:transit_leg, - agency: build(:agency, name: "MBTA"), - route: build(:route, type: 1), - to: build(:place_with_stop, stop: build(:stop, parent_station: parent1)) - ) - - leg2 = - build(:transit_leg, - agency: build(:agency, name: "MBTA"), - route: build(:route, type: 1), - from: build(:place_with_stop, stop: build(:stop, parent_station: parent2)) - ) - refute subway_transfer?([leg1, leg2]) + test "any number of consecutive bus, subway, and/or ferry legs" do + assert [bus_leg(), subway_leg(), ferry_leg(), bus_leg(), subway_leg()] + |> maybe_transfer? end - test "handles transfers within same parent stop" do - same_parent = build(:parent_stop) - - leg1 = - build(:transit_leg, - agency: build(:agency, name: "MBTA"), - route: build(:route, type: 1), - to: build(:place_with_stop, stop: build(:stop, parent_station: same_parent)) - ) - - leg2 = - build(:transit_leg, - agency: build(:agency, name: "MBTA"), - route: build(:route, type: 1), - from: build(:place_with_stop, stop: build(:stop, parent_station: same_parent)) - ) - - assert subway_transfer?([leg1, leg2]) - end - - test "handles transfers within the Winter St. Concourse" do - parent1 = build(:parent_stop, gtfs_id: "mbta-ma-us:place-dwnxg") - parent2 = build(:parent_stop, gtfs_id: "mbta-ma-us:place-pktrm") - - leg1 = - build(:transit_leg, - agency: build(:agency, name: "MBTA"), - route: build(:route, type: 1), - to: build(:place_with_stop, stop: build(:stop, parent_station: parent1)) - ) - - leg2 = - build(:transit_leg, - agency: build(:agency, name: "MBTA"), - route: build(:route, type: 1), - from: build(:place_with_stop, stop: build(:stop, parent_station: parent2)) - ) - - assert subway_transfer?([leg1, leg2]) + test "a bus route repeated mid-chain breaks the transfer" do + bus_leg = bus_leg() + refute [subway_leg(), bus_leg, bus_leg, subway_leg()] |> maybe_transfer? end end end From c65fab2a7d380b02c0af12f4144c04a2184efbdb Mon Sep 17 00:00:00 2001 From: Josh Larson Date: Tue, 1 Sep 2026 10:06:45 -0400 Subject: [PATCH 3/6] cleanup(robot): Remove duplicative tests AI Prompt: Of the tests in transfer_test and fares_test, check to see whether any of them are duplicates of each other, now that the overall logic is simpler --- test/dotcom/trip_plan/fares_test.exs | 130 ------------------------ test/dotcom/trip_plan/transfer_test.exs | 20 ---- 2 files changed, 150 deletions(-) diff --git a/test/dotcom/trip_plan/fares_test.exs b/test/dotcom/trip_plan/fares_test.exs index 12fa4f3647..7335c3e3cf 100644 --- a/test/dotcom/trip_plan/fares_test.exs +++ b/test/dotcom/trip_plan/fares_test.exs @@ -59,136 +59,6 @@ defmodule Dotcom.TripPlan.FaresTest do assert fare1 == fare2 assert fare2 == fare3 end - - test "free transfers for up to 3 consecutive bus or subway legs" do - bus_or_subway_routes = [ - build(:route, - agency: build(:agency, name: "MBTA"), - type: 0 - ), - build(:route, - agency: build(:agency, name: "MBTA"), - type: 1 - ), - build(:route, - agency: build(:agency, name: "MBTA"), - type: 3, - desc: "Local Bus" - ) - ] - - three_subway_or_bus_legs = - 3 - |> Faker.Util.sample_uniq(fn -> Faker.Util.pick(bus_or_subway_routes) end) - |> Enum.map(&build(:transit_leg, route: &1)) - - one_subway_fare = - build(:itinerary, - legs: - build_list(1, :transit_leg, - route: - build(:route, - agency: build(:agency, name: "MBTA"), - type: 0 - ) - ) - ) - |> fare() - - fare = build(:itinerary, legs: three_subway_or_bus_legs) |> fare() - assert fare <= one_subway_fare - end - end - - test "valid two leg subway transfers" do - start_leg = - build(:transit_leg, - from: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-start"})), - to: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-midA"})), - route: - build(:route, - agency: build(:agency, name: "MBTA"), - type: 0 - ) - ) - - end_leg = - build(:transit_leg, - from: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-midA"})), - to: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-end"})), - route: - build(:route, - agency: build(:agency, name: "MBTA"), - type: 0 - ) - ) - - one_subway_fare = - build(:itinerary, - legs: - build_list(1, :transit_leg, - route: - build(:route, - agency: build(:agency, name: "MBTA"), - type: 0 - ) - ) - ) - |> fare() - - fare = build(:itinerary, legs: [start_leg, end_leg]) |> fare() - assert fare <= one_subway_fare - end - - test "valid three leg subway transfers" do - start_leg = - build(:transit_leg, - from: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-start"})), - to: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-midA"})), - route: - build(:route, - agency: build(:agency, name: "MBTA"), - type: 0 - ) - ) - - mid_leg = - build(:transit_leg, - from: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-midA"})), - to: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-midB"})), - route: - build(:route, - agency: build(:agency, name: "MBTA"), - type: 0 - ) - ) - - end_leg = - build(:transit_leg, - from: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-midB"})), - to: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-end"})), - route: - build(:route, - agency: build(:agency, name: "MBTA"), - type: 0 - ) - ) - - one_subway_fare = - build(:itinerary, - legs: - build_list(1, :transit_leg, - route: - build(:route, - agency: build(:agency, name: "MBTA"), - type: 0 - ) - ) - ) - |> fare() - - fare = build(:itinerary, legs: [start_leg, mid_leg, end_leg]) |> fare() - assert fare <= one_subway_fare end test "subway to subway transfers are free even between different lines/stations (eg red <-> blue)" do diff --git a/test/dotcom/trip_plan/transfer_test.exs b/test/dotcom/trip_plan/transfer_test.exs index 2e948cbd12..358cf70338 100644 --- a/test/dotcom/trip_plan/transfer_test.exs +++ b/test/dotcom/trip_plan/transfer_test.exs @@ -120,26 +120,6 @@ defmodule Dotcom.TripPlan.TransferTest do refute maybe_transfer?([shuttle_leg(), subway_leg()]) end - test "bus -> bus -> subway" do - assert [bus_leg(), bus_leg(), subway_leg()] |> maybe_transfer? - end - - test "subway -> bus -> bus" do - assert [subway_leg(), bus_leg(), bus_leg()] |> maybe_transfer? - end - - test "bus -> bus -> bus" do - assert [bus_leg(), bus_leg(), bus_leg()] |> maybe_transfer? - end - - test "bus -> subway -> bus" do - assert [bus_leg(), subway_leg(), bus_leg()] |> maybe_transfer? - end - - test "subway -> bus -> subway" do - assert [subway_leg(), bus_leg(), subway_leg()] |> maybe_transfer? - end - test "any number of consecutive bus, subway, and/or ferry legs" do assert [bus_leg(), subway_leg(), ferry_leg(), bus_leg(), subway_leg()] |> maybe_transfer? From 5b15afcb1389c0e7252ddf4a1c360b5842e53eb4 Mon Sep 17 00:00:00 2001 From: Josh Larson Date: Tue, 1 Sep 2026 11:44:54 -0400 Subject: [PATCH 4/6] fix(robot): Test --- test/dotcom/content_rewriters/liquid_objects/fare_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dotcom/content_rewriters/liquid_objects/fare_test.exs b/test/dotcom/content_rewriters/liquid_objects/fare_test.exs index 745ba81ef3..020d3f0d6e 100644 --- a/test/dotcom/content_rewriters/liquid_objects/fare_test.exs +++ b/test/dotcom/content_rewriters/liquid_objects/fare_test.exs @@ -73,7 +73,7 @@ defmodule Dotcom.ContentRewriters.LiquidObjects.FareTest do assert fare_request("commuter_rail:month:reduced") == {:ok, "$30.00 – $209.00"} assert fare_request("commuter_ferry:month:reduced") == {:ok, "$164.00"} - assert fare_request("express_bus:month:reduced") == {:ok, "$67.00"} + assert fare_request("express_bus:month:reduced") == {:ok, "$30.00"} end test "it handles weekend rail fare requests" do From 659587887eb7597ef587e66c3a7f0cc8a6e17aa2 Mon Sep 17 00:00:00 2001 From: Josh Larson Date: Tue, 1 Sep 2026 14:34:07 -0400 Subject: [PATCH 5/6] style/tests: Use `Faker.Util.pick([0, 1])` for subway route types --- test/dotcom/trip_plan/fares_test.exs | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/test/dotcom/trip_plan/fares_test.exs b/test/dotcom/trip_plan/fares_test.exs index 7335c3e3cf..9f25b1edbc 100644 --- a/test/dotcom/trip_plan/fares_test.exs +++ b/test/dotcom/trip_plan/fares_test.exs @@ -33,7 +33,8 @@ defmodule Dotcom.TripPlan.FaresTest do ) ), build(:transit_leg, - route: build(:route, agency: build(:agency, name: "MBTA"), type: 0) + route: + build(:route, agency: build(:agency, name: "MBTA"), type: Faker.Util.pick([0, 1])) ) ] @@ -64,23 +65,23 @@ defmodule Dotcom.TripPlan.FaresTest do test "subway to subway transfers are free even between different lines/stations (eg red <-> blue)" do start_leg = build(:transit_leg, - from: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-start"})), - to: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-midA"})), + from: build(:place, stop: build(:stop)), + to: build(:place, stop: build(:stop)), route: build(:route, agency: build(:agency, name: "MBTA"), - type: 0 + type: Faker.Util.pick([0, 1]) ) ) end_leg = build(:transit_leg, - from: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-midB"})), - to: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-end"})), + from: build(:place, stop: build(:stop)), + to: build(:place, stop: build(:stop)), route: build(:route, agency: build(:agency, name: "MBTA"), - type: 1 + type: Faker.Util.pick([0, 1]) ) ) @@ -91,7 +92,7 @@ defmodule Dotcom.TripPlan.FaresTest do route: build(:route, agency: build(:agency, name: "MBTA"), - type: 0 + type: Faker.Util.pick([0, 1]) ) ) ) @@ -109,7 +110,7 @@ defmodule Dotcom.TripPlan.FaresTest do route: build(:route, agency: build(:agency, name: "MBTA"), - type: 0 + type: Faker.Util.pick([0, 1]) ) ) @@ -120,7 +121,7 @@ defmodule Dotcom.TripPlan.FaresTest do route: build(:route, agency: build(:agency, name: "MBTA"), - type: 1 + type: Faker.Util.pick([0, 1]) ) ) @@ -131,7 +132,7 @@ defmodule Dotcom.TripPlan.FaresTest do route: build(:route, agency: build(:agency, name: "MBTA"), - type: 0 + type: Faker.Util.pick([0, 1]) ) ) @@ -142,7 +143,7 @@ defmodule Dotcom.TripPlan.FaresTest do route: build(:route, agency: build(:agency, name: "MBTA"), - type: 0 + type: Faker.Util.pick([0, 1]) ) ) ) @@ -159,7 +160,9 @@ defmodule Dotcom.TripPlan.FaresTest do ) subway_leg = - build(:transit_leg, route: build(:route, agency: build(:agency, name: "MBTA"), type: 0)) + build(:transit_leg, + route: build(:route, agency: build(:agency, name: "MBTA"), type: Faker.Util.pick([0, 1])) + ) ferry_leg = build(:transit_leg, route: build(:route, agency: build(:agency, name: "MBTA"), type: 4)) From af1bc3eb8534633e4d1335b7a29cf3079e7ba4da Mon Sep 17 00:00:00 2001 From: Josh Larson Date: Tue, 1 Sep 2026 14:35:32 -0400 Subject: [PATCH 6/6] style/tests: Clean up more hard-coded stop ID's --- test/dotcom/trip_plan/fares_test.exs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/dotcom/trip_plan/fares_test.exs b/test/dotcom/trip_plan/fares_test.exs index 9f25b1edbc..8e5ce8b902 100644 --- a/test/dotcom/trip_plan/fares_test.exs +++ b/test/dotcom/trip_plan/fares_test.exs @@ -105,8 +105,8 @@ defmodule Dotcom.TripPlan.FaresTest do test "subway to subway to subway transfers are free even between different lines/stations (eg red <-> blue)" do start_leg = build(:transit_leg, - from: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-start"})), - to: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-midA"})), + from: build(:place, stop: build(:stop)), + to: build(:place, stop: build(:stop)), route: build(:route, agency: build(:agency, name: "MBTA"), @@ -116,8 +116,8 @@ defmodule Dotcom.TripPlan.FaresTest do mid_leg = build(:transit_leg, - from: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-midA"})), - to: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-midB"})), + from: build(:place, stop: build(:stop)), + to: build(:place, stop: build(:stop)), route: build(:route, agency: build(:agency, name: "MBTA"), @@ -127,8 +127,8 @@ defmodule Dotcom.TripPlan.FaresTest do end_leg = build(:transit_leg, - from: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-other"})), - to: build(:place, stop: build(:stop, parent_station: %{gtfs_id: "mock-end"})), + from: build(:place, stop: build(:stop)), + to: build(:place, stop: build(:stop)), route: build(:route, agency: build(:agency, name: "MBTA"),