Skip to content

Commit

Permalink
feat: optionally use OpenTripPlanner for nearby transit (#41)
Browse files Browse the repository at this point in the history
* feat: optionally use OpenTripPlanner for nearby transit

* fix: don't use OTP's wacky route pattern data

* fix Nearby.parse/1 typespec

* refactor: don't parse source as a single-use atom

* feat: ignore massport stops

* test: add OTP parsing parent stations
  • Loading branch information
boringcactus authored Jan 25, 2024
1 parent fd5bedf commit 73aff82
Show file tree
Hide file tree
Showing 17 changed files with 640 additions and 38 deletions.
4 changes: 4 additions & 0 deletions config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ if config_env() != :test do
app_id: System.get_env("ALGOLIA_APP_ID"),
search_key: System.get_env("ALGOLIA_SEARCH_KEY"),
base_url: System.get_env("ALGOLIA_READ_URL")

# open_trip_planner_client configuration in disguise
config :mobile_app_backend,
otp_url: System.get_env("OTP_URL")
end

# ## Using releases
Expand Down
3 changes: 2 additions & 1 deletion config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ config :logger, level: :warning
config :phoenix, :plug_init_mode, :runtime

config :mobile_app_backend,
base_url: "https://api-dev.mbtace.com/"
base_url: "https://api-dev.mbtace.com/",
otp_url: "http://otp.example.com/"

config :mobile_app_backend, MobileAppBackend.Search.Algolia,
app_id: "fake_app",
Expand Down
33 changes: 23 additions & 10 deletions lib/mobile_app_backend_web/controllers/nearby_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,28 @@ defmodule MobileAppBackendWeb.NearbyController do
use MobileAppBackendWeb, :controller

def show(conn, params) do
params = Map.merge(%{"source" => "otp", "radius" => "0.5"}, params)
latitude = String.to_float(Map.fetch!(params, "latitude"))
longitude = String.to_float(Map.fetch!(params, "longitude"))
radius = String.to_float(Map.fetch!(params, "radius"))

{:ok, stops} =
MBTAV3API.Stop.get_all(
filter: [
latitude: String.to_float(params["latitude"]),
longitude: String.to_float(params["longitude"]),
location_type: [0, 1],
radius: miles_to_degrees(0.5)
],
include: :parent_station,
sort: {:distance, :asc}
)
case Map.fetch!(params, "source") do
"v3" ->
MBTAV3API.Stop.get_all(
filter: [
latitude: latitude,
longitude: longitude,
location_type: [0, 1],
radius: miles_to_degrees(radius)
],
include: :parent_station,
sort: {:distance, :asc}
)

"otp" ->
OpenTripPlannerClient.nearby(latitude, longitude, miles_to_meters(radius))
end

stop_ids = MapSet.new(stops, & &1.id)

Expand Down Expand Up @@ -46,6 +57,8 @@ defmodule MobileAppBackendWeb.NearbyController do
})
end

defp miles_to_meters(miles), do: round(miles * 1_609.344)

# The V3 API does not actually calculate distance,
# and it just pretends latitude degrees and longitude degrees are equally sized.
# See https://github.com/mbta/api/blob/1671ba02d4669827fb2a58966d8c3ab39c939b0e/apps/api_web/lib/api_web/controllers/stop_controller.ex#L27-L31.
Expand Down
74 changes: 74 additions & 0 deletions lib/open_trip_planner_client.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
defmodule OpenTripPlannerClient do
@moduledoc """
Fetches data from the OpenTripPlanner API.
## Configuration
```elixir
config :mobile_app_backend,
otp_url: "http://localhost:8080"
```
"""

require Logger

alias OpenTripPlannerClient.Nearby

@doc """
Fetches stops within the given number of meters of the given position.
"""
@spec nearby(float(), float(), integer(), Keyword.t()) ::
{:ok, [MBTAV3API.Stop.t()]} | {:error, term()}
def nearby(latitude, longitude, radius, opts \\ []) do
root_url =
Keyword.get(opts, :root_url, Application.fetch_env!(:mobile_app_backend, :otp_url))

request =
Nearby.request(latitude, longitude, radius)
|> Req.update(base_url: root_url, url: "/otp/routers/default/index/graphql")

case send_request(request) do
{:ok, body} -> Nearby.parse(body)
{:error, error} -> {:error, error}
end
end

@spec send_request(Req.Request.t()) :: {:ok, term()} | {:error, term()}
defp send_request(request) do
with {:ok, response} <- log_response(request),
%{status: 200, body: body} <- response do
{:ok, body}
else
%{status: _} = response ->
{:error, response}

error ->
error
end
end

@spec log_response(Req.Request.t()) :: {:ok, Req.Response.t()} | {:error, term()}
defp log_response(request) do
{duration, response} =
:timer.tc(
MobileAppBackend.HTTP,
:request,
[request]
)

_ =
Logger.info(fn ->
"#{__MODULE__}.otp_response query=#{inspect(request.options[:graphql])} #{status_text(response)} duration=#{duration / :timer.seconds(1)}"
end)

response
end

defp status_text({:ok, %{status: code}}) do
"status=#{code}"
end

defp status_text({:error, error}) do
"status=error error=#{inspect(error)}"
end
end
111 changes: 111 additions & 0 deletions lib/open_trip_planner_client/nearby.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
defmodule OpenTripPlannerClient.Nearby do
@spec request(float(), float(), integer()) :: Req.Request.t()
def request(latitude, longitude, radius) do
Req.new(method: :post)
|> AbsintheClient.attach(
graphql: {graphql_query(), %{latitude: latitude, longitude: longitude, radius: radius}}
)
end

@spec parse(map()) :: {:ok, [MBTAV3API.Stop.t()]} | {:error, term()}
def parse(data) do
with {:ok, edges} <- get_edges(data),
{:ok, stops} <- parse_edges(edges) do
{:ok, stops}
else
{:error, error} -> {:error, error}
end
end

defp graphql_query do
"""
query NearbyQuery($latitude: Float!, $longitude: Float!, $radius: Int!) {
nearest(lat: $latitude, lon: $longitude, maxDistance: $radius, filterByPlaceTypes: [STOP]) {
edges {
node {
place {
... on Stop {
...stopDetails
parentStation {
...stopDetails
}
}
}
distance
}
}
}
}
fragment stopDetails on Stop {
gtfsId
lat
lon
name
}
"""
end

@spec get_edges(map()) :: {:ok, list(map())} | {:error, term()}
defp get_edges(data) do
case data do
%{"data" => %{"nearest" => %{"edges" => edges}}} -> {:ok, edges}
_ -> {:error, :bad_format}
end
end

@spec parse_edges(list(map())) :: {:ok, list(MBTAV3API.Stop.t())} | {:error, term()}
defp parse_edges(edges) do
edges
|> Enum.reduce({:ok, []}, fn
edge, {:ok, reversed_stops} ->
with {:ok, stop} <- get_stop(edge),
{:ok, stop} <- parse_stop(stop) do
{:ok, [stop | reversed_stops]}
else
:ignore -> {:ok, reversed_stops}
{:error, error} -> {:error, error}
end

_edge, {:error, error} ->
{:error, error}
end)
|> case do
{:ok, reversed_stops} -> {:ok, Enum.reverse(reversed_stops)}
{:error, error} -> {:error, error}
end
end

@spec get_stop(map()) :: {:ok, map()} | {:error, term()}
defp get_stop(edge) do
case edge do
%{"node" => %{"place" => stop}} -> {:ok, stop}
_ -> {:error, :bad_format}
end
end

@spec parse_stop(map()) :: {:ok, MBTAV3API.Stop.t()} | :ignore | {:error, term()}
defp parse_stop(place) do
case place do
%{"lat" => latitude, "lon" => longitude, "gtfsId" => "mbta-ma-us:" <> id, "name" => name} ->
{:ok,
%MBTAV3API.Stop{
id: id,
latitude: latitude,
longitude: longitude,
name: name,
parent_station:
with {:ok, parent_station} when not is_nil(parent_station) <-
Map.fetch(place, "parentStation"),
{:ok, parent_station} <- parse_stop(parent_station) do
parent_station
else
_ -> nil
end
}}

%{"gtfsId" => "2272_2274:" <> _} ->
:ignore
end
end
end
5 changes: 3 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ defmodule MobileAppBackend.MixProject do
{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false},
{:mox, "~> 1.0", only: :test},
{:uniq, "~> 0.6", only: :test},
{:req, "~> 0.4.8"},
{:req, "~> 0.3"},
{:sentry, "~> 10.0"},
{:timex, "~> 3.7"},
{:lcov_ex, "~> 0.3", only: [:test], runtime: false}
{:lcov_ex, "~> 0.3", only: [:test], runtime: false},
{:absinthe_client, "~> 0.1.0"}
]
end

Expand Down
5 changes: 4 additions & 1 deletion mix.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
%{
"absinthe_client": {:hex, :absinthe_client, "0.1.0", "a3bafc1dff141073a2a7fd926942fb10afb4d45295f0b6df46f6f1955ececaac", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:req, "~> 0.3.0", [hex: :req, repo: "hexpm", optional: false]}, {:slipstream, "~> 1.0", [hex: :slipstream, repo: "hexpm", optional: false]}], "hexpm", "a7ec3e13da9b463cb024dba4733c2fa31a0690a3bfa897b9df6bdd544a4d6f91"},
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
"castore": {:hex, :castore, "1.0.5", "9eeebb394cc9a0f3ae56b813459f990abb0a3dedee1be6b27fdb50301930502f", [:mix], [], "hexpm", "8d7c597c3e4a64c395980882d4bca3cebb8d74197c590dc272cfd3b6a6310578"},
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
Expand Down Expand Up @@ -28,6 +29,7 @@
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
"mint": {:hex, :mint, "1.5.2", "4805e059f96028948870d23d7783613b7e6b0e2fb4e98d720383852a760067fd", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "d77d9e9ce4eb35941907f1d3df38d8f750c357865353e21d335bdcdf6d892a02"},
"mint_web_socket": {:hex, :mint_web_socket, "1.0.3", "aab42fff792a74649916236d0b01f560a0b3f03ca5dea693c230d1c44736b50e", [:mix], [{:mint, ">= 1.4.1 and < 2.0.0-0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "ca3810ca44cc8532e3dce499cc17f958596695d226bb578b2fbb88c09b5954b0"},
"mox": {:hex, :mox, "1.1.0", "0f5e399649ce9ab7602f72e718305c0f9cdc351190f72844599545e4996af73c", [:mix], [], "hexpm", "d44474c50be02d5b72131070281a5d3895c0e7a95c780e90bc0cfe712f633a13"},
"nimble_options": {:hex, :nimble_options, "1.1.0", "3b31a57ede9cb1502071fade751ab0c7b8dbe75a9a4c2b5bbb0943a690b63172", [:mix], [], "hexpm", "8bbbb3941af3ca9acc7835f5655ea062111c9c27bcac53e004460dfd19008a99"},
"nimble_pool": {:hex, :nimble_pool, "1.0.0", "5eb82705d138f4dd4423f69ceb19ac667b3b492ae570c9f5c900bb3d2f50a847", [:mix], [], "hexpm", "80be3b882d2d351882256087078e1b1952a28bf98d0a287be87e4a24a710b67a"},
Expand All @@ -43,8 +45,9 @@
"plug_cowboy": {:hex, :plug_cowboy, "2.6.2", "753611b23b29231fb916b0cdd96028084b12aff57bfd7b71781bd04b1dbeb5c9", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "951ed2433df22f4c97b85fdb145d4cee561f36b74854d64c06d896d7cd2921a7"},
"plug_crypto": {:hex, :plug_crypto, "2.0.0", "77515cc10af06645abbfb5e6ad7a3e9714f805ae118fa1a70205f80d2d70fe73", [:mix], [], "hexpm", "53695bae57cc4e54566d993eb01074e4d894b65a3766f1c43e2c61a1b0f45ea9"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
"req": {:hex, :req, "0.4.8", "2b754a3925ddbf4ad78c56f30208ced6aefe111a7ea07fb56c23dccc13eb87ae", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.9", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "7146e51d52593bb7f20d00b5308a5d7d17d663d6e85cd071452b613a8277100c"},
"req": {:hex, :req, "0.3.12", "f84c2f9e7cc71c81d7cbeacf7c61e763e53ab5f3065703792a4ab264b4f22672", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.9", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "c91103d4d1c8edeba90c84e0ba223a59865b673eaab217bfd17da3aa54ab136c"},
"sentry": {:hex, :sentry, "10.1.0", "5d73c23deb5d95f3027fbb09801bd8e787065be61f0065418aed3961becbbe9f", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 2.3", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "f4319e7491133046912b4cf7cbe6f5226b309275d1a6d05386cce2ac7f97b2d2"},
"slipstream": {:hex, :slipstream, "1.1.0", "e3581e9bc73036e4283b33447475499d18c813c7662aa6b86e131633a7e912f3", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mint_web_socket, "~> 0.2 or ~> 1.0", [hex: :mint_web_socket, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.1 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "66eb1ac7c43573511b5bad90c24c128bb4e69f588bff65d0c409adf4c7eb02e6"},
"sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
"tailwind": {:hex, :tailwind, "0.2.2", "9e27288b568ede1d88517e8c61259bc214a12d7eed271e102db4c93fcca9b2cd", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "ccfb5025179ea307f7f899d1bb3905cd0ac9f687ed77feebc8f67bdca78565c4"},
Expand Down
1 change: 1 addition & 0 deletions priv/test_data/018d3879-36f2-709a-b94f-1c2cba8612fb.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions priv/test_data/018d3c77-9e37-7ec8-b618-b1d5ec8fc4ba.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"data":{"nearest":{"edges":[{"node":{"distance":354,"place":{"gtfsId":"mbta-ma-us:67120","lat":42.28101,"lon":-71.177035,"name":"Millennium Park","parentStation":null}}},{"node":{"distance":618,"place":{"gtfsId":"mbta-ma-us:129","lat":42.278959,"lon":-71.175667,"name":"Rivermoor St @ Charles Park Rd","parentStation":null}}},{"node":{"distance":627,"place":{"gtfsId":"mbta-ma-us:137","lat":42.278907,"lon":-71.175492,"name":"Charles Park Rd @ Rivermoor St","parentStation":null}}}]}}}
1 change: 1 addition & 0 deletions priv/test_data/018d3d24-3bc2-75e8-afce-e2831dd4eb03.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"data":{"nearest":{"edges":[{"node":{"distance":44,"place":{"gtfsId":"mbta-ma-us:7097","lat":42.374518,"lon":-71.029532,"name":"Airport","parentStation":{"gtfsId":"mbta-ma-us:place-aport","lat":42.374262,"lon":-71.030395,"name":"Airport"}}}},{"node":{"distance":44,"place":{"gtfsId":"mbta-ma-us:7096","lat":42.374693,"lon":-71.029333,"name":"Airport","parentStation":{"gtfsId":"mbta-ma-us:place-aport","lat":42.374262,"lon":-71.030395,"name":"Airport"}}}},{"node":{"distance":44,"place":{"gtfsId":"mbta-ma-us:70048","lat":42.374262,"lon":-71.030395,"name":"Airport","parentStation":{"gtfsId":"mbta-ma-us:place-aport","lat":42.374262,"lon":-71.030395,"name":"Airport"}}}},{"node":{"distance":44,"place":{"gtfsId":"mbta-ma-us:70047","lat":42.374262,"lon":-71.030395,"name":"Airport","parentStation":{"gtfsId":"mbta-ma-us:place-aport","lat":42.374262,"lon":-71.030395,"name":"Airport"}}}},{"node":{"distance":69,"place":{"gtfsId":"2272_2274:52","lat":42.373908,"lon":-71.030087,"name":"Blue Line - MBTA","parentStation":null}}},{"node":{"distance":80,"place":{"gtfsId":"2272_2274:41","lat":42.37374,"lon":-71.03005,"name":"Blue Line - MBTA","parentStation":null}}}]}}}
7 changes: 7 additions & 0 deletions priv/test_data/meta.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
{
"OPEN_TRIP_PLANNER": {
"/otp/routers/default/index/graphql": {
"{\"variables\":{\"latitude\":42.281877070443166,\"longitude\":-71.18020826779917,\"radius\":805},\"query\":\"query NearbyQuery($latitude: Float!, $longitude: Float!, $radius: Int!) {\\n nearest(lat: $latitude, lon: $longitude, maxDistance: $radius, filterByPlaceTypes: [STOP]) {\\n edges {\\n node {\\n place {\\n ... on Stop {\\n ...stopDetails\\n parentStation {\\n ...stopDetails\\n }\\n }\\n }\\n distance\\n }\\n }\\n }\\n}\\n\\nfragment stopDetails on Stop {\\n gtfsId\\n lat\\n lon\\n name\\n}\\n\"}": "018d3c77-9e37-7ec8-b618-b1d5ec8fc4ba",
"{\"variables\":{\"latitude\":42.37434840767488,\"longitude\":-71.03021663692962,\"radius\":100},\"query\":\"query NearbyQuery($latitude: Float!, $longitude: Float!, $radius: Int!) {\\n nearest(lat: $latitude, lon: $longitude, maxDistance: $radius, filterByPlaceTypes: [STOP]) {\\n edges {\\n node {\\n place {\\n ... on Stop {\\n ...stopDetails\\n parentStation {\\n ...stopDetails\\n }\\n }\\n }\\n distance\\n }\\n }\\n }\\n}\\n\\nfragment stopDetails on Stop {\\n gtfsId\\n lat\\n lon\\n name\\n}\\n\"}": "018d3d24-3bc2-75e8-afce-e2831dd4eb03"
}
},
"V3_API": {
"/route_patterns": {
"fields%5Broute%5D=color%2Cdirection_names%2Cdirection_destinations%2Clong_name%2Cshort_name%2Csort_order%2Ctext_color&fields%5Broute_pattern%5D=direction_id%2Cname%2Csort_order&fields%5Bstop%5D=&fields%5Btrip%5D=&filter%5Bstop%5D=10821%2C10830%2C120%2C129%2C137%2C67120&include=route%2Crepresentative_trip%2Crepresentative_trip.stops": "018d3216-51c1-7f1c-bf27-7221e39ab293",
"fields%5Broute%5D=color%2Cdirection_names%2Cdirection_destinations%2Clong_name%2Cshort_name%2Csort_order%2Ctext_color&fields%5Broute_pattern%5D=direction_id%2Cname%2Csort_order&fields%5Bstop%5D=&fields%5Btrip%5D=&filter%5Bstop%5D=129%2C137%2C67120&include=route%2Crepresentative_trip%2Crepresentative_trip.stops": "018d3879-36f2-709a-b94f-1c2cba8612fb",
"fields%5Broute%5D=color%2Cdirection_names%2Cdirection_destinations%2Clong_name%2Cshort_name%2Csort_order%2Ctext_color&fields%5Broute_pattern%5D=direction_id%2Cname%2Csort_order&fields%5Bstop%5D=&fields%5Btrip%5D=&filter%5Bstop%5D=GB-0198%2CGB-0198-01%2CGB-0198-02%2Cplace-GB-0198&include=route%2Crepresentative_trip%2Crepresentative_trip.stops": "018d3216-5250-7087-a8a3-fd451c0f56db"
},
"/stops": {
Expand Down
7 changes: 4 additions & 3 deletions test/mbta_v3_api/mbta_v3_api_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ defmodule MBTAV3APITest do
:request,
fn %Req.Request{
url: %URI{path: "/with_api_key"},
headers: %{"x-api-key" => ["test_key"]},
headers: headers,
options: %{params: [other: "value"]}
} ->
assert {"x-api-key", "test_key"} in headers
{:ok, Req.Response.json(%{data: []})}
end
)
Expand All @@ -98,9 +99,9 @@ defmodule MBTAV3APITest do
:request,
fn %Req.Request{
url: %URI{path: "/without_api_key"},
headers: %{} = headers
headers: headers
} ->
refute Map.has_key?(headers, "x-api-key")
refute Enum.any?(headers, &(elem(&1, 0) == "x-api-key"))
{:ok, Req.Response.json(%{data: []})}
end
)
Expand Down
Loading

0 comments on commit 73aff82

Please sign in to comment.