diff --git a/apps/transport/lib/transport/data_checker.ex b/apps/transport/lib/transport/data_checker.ex index edb1659cff..94aa8f64c4 100644 --- a/apps/transport/lib/transport/data_checker.ex +++ b/apps/transport/lib/transport/data_checker.ex @@ -93,13 +93,14 @@ defmodule Transport.DataChecker do resources |> Stream.map(fn r -> - compute_gbfs_feed_meta(r) |> IO.inspect() + r |> compute_gbfs_feed_meta() + # |> IO.inspect() end) |> Stream.run() end @spec compute_gbfs_feed_meta(Resource.t()) :: map() - defp compute_gbfs_feed_meta(resource) do + def compute_gbfs_feed_meta(resource) do Logger.debug(fn -> "Handling feed #{resource.url}" end) with {:ok, %{status_code: 200, body: body}} <- http_client().get(resource.url), @@ -122,16 +123,16 @@ defmodule Transport.DataChecker do feed = payload |> gbfs_first_feed() has_bike_status = gbfs_has_feed?(feed, "free_bike_status") - has_station_status = gbfs_has_feed?(feed, "station_status") + has_station_information = gbfs_has_feed?(feed, "station_information") cond do - has_bike_status and has_station_status -> + has_bike_status and has_station_information -> ["free_floating", "stations"] has_bike_status -> ["free_floating"] - has_station_status -> + has_station_information -> ["stations"] true -> @@ -143,16 +144,20 @@ defmodule Transport.DataChecker do defp gbfs_ttl(%{"data" => _data} = payload) do feed = payload |> gbfs_first_feed() - case gbfs_types(payload) do - ["free_floating", "stations"] -> feed |> gbfs_feed_url_by_name("free_bike_status") - ["free_floating"] -> feed |> gbfs_feed_url_by_name("free_bike_status") - ["stations"] -> feed |> gbfs_feed_url_by_name("station_status") - nil -> payload["ttl"] - end - |> gbfs_feed_ttl() + value = + case gbfs_types(payload) do + ["free_floating", "stations"] -> feed |> gbfs_feed_url_by_name("free_bike_status") + ["free_floating"] -> feed |> gbfs_feed_url_by_name("free_bike_status") + ["stations"] -> feed |> gbfs_feed_url_by_name("station_information") + nil -> payload["ttl"] + end + + gbfs_feed_ttl(value) end - defp gbfs_feed_ttl(feed_url) do + defp gbfs_feed_ttl(value) when is_integer(value) and value >= 0, do: value + + defp gbfs_feed_ttl(feed_url) when is_binary(feed_url) do with {:ok, %{status_code: 200, body: body}} <- http_client().get(feed_url), {:ok, json} <- Jason.decode(body) do json["ttl"] @@ -182,7 +187,7 @@ defmodule Transport.DataChecker do end defp gbfs_first_feed(%{"data" => data} = payload) do - (data["en"] || data["fr"] || data[gbfs_languages(payload).at(0)])["feeds"] + (data["en"] || data["fr"] || data[payload |> gbfs_languages() |> Enum.at(0)])["feeds"] end defp gbfs_languages(%{"data" => data}) do diff --git a/apps/transport/test/transport/data_checker_test.exs b/apps/transport/test/transport/data_checker_test.exs new file mode 100644 index 0000000000..1332be0f2e --- /dev/null +++ b/apps/transport/test/transport/data_checker_test.exs @@ -0,0 +1,75 @@ +defmodule Transport.DataCheckerTest do + use ExUnit.Case, async: true + import Mox + + import Transport.DataChecker, only: [compute_gbfs_feed_meta: 1] + + @gbfs_url "https://example.com/gbfs.json" + + setup :verify_on_exit! + + describe "Compute GBFS metadata for a feed" do + test "for a stations feed with a single version" do + setup_feeds([:gbfs, :system_information, :station_information]) + + expected = %{ + languages: ["fr"], + system_details: %{name: "velhop", timezone: "Europe/Paris"}, + ttl: 3600, + types: ["stations"], + versions: ["1.1"] + } + + assert expected == compute_gbfs_feed_meta(%DB.Resource{url: @gbfs_url}) + end + end + + defp setup_feeds(feeds) do + feeds + |> Enum.map(fn feed -> + case feed do + :gbfs -> setup_gbfs_response() + :system_information -> setup_system_information_response() + :station_information -> setup_station_information_response() + end + end) + end + + defp setup_response(expected_url, body) do + Transport.HTTPoison.Mock + |> expect(:get, fn url -> + assert url == expected_url + + {:ok, + %HTTPoison.Response{ + status_code: 200, + body: body, + headers: [{"Content-Type", "application/json"}] + }} + end) + end + + defp setup_gbfs_response do + body = """ + {"data":{"fr":{"feeds":[{"name":"system_information","url":"https://example.com/system_information.json"},{"name":"station_information","url":"https://example.com/station_information.json"},{"name":"station_status","url":"https://example.com/station_status.json"}]}},"last_updated":1636116464,"ttl":3600,"version":"1.1"} + """ + + setup_response(@gbfs_url, body) + end + + defp setup_system_information_response do + body = """ + {"data":{"language":"fr","name":"velhop","system_id":"strasbourg","timezone":"Europe/Paris"},"last_updated":1636116522,"ttl":3600,"version":"1.1"} + """ + + setup_response("https://example.com/system_information.json", body) + end + + defp setup_station_information_response do + body = """ + {"data":{"stations":[{"capacity":16,"lat":48.568644,"lon":7.795621,"name":"124 Auberge de jeunesse","rental_method":"CREDIT_CARD","station_id":"124"}]},"last_updated":1636116909,"ttl":3600,"version":"1.1"} + """ + + setup_response("https://example.com/station_information.json", body) + end +end