-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Client for the enRoute Chouette Valid API (#4106)
* Client for the Enroute Chouette Valid API * Fix enRoute spelling
- Loading branch information
Showing
5 changed files
with
281 additions
and
2 deletions.
There are no files selected for viewing
72 changes: 72 additions & 0 deletions
72
apps/transport/lib/validators/enroute_chouette_valid_client.ex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
defmodule Transport.EnRouteChouetteValidClient.Wrapper do | ||
@moduledoc """ | ||
A client for the enRoute Chouette Valid API. | ||
Documentation: https://documenter.getpostman.com/view/9950294/2sA3e2gVEE | ||
""" | ||
|
||
@callback create_a_validation(Path.t()) :: binary() | ||
@callback get_a_validation(binary()) :: | ||
:pending | {:successful, binary()} | :warning | :failed | :unexpected_validation_status | ||
@callback get_messages(binary()) :: {binary(), map()} | ||
|
||
def impl, do: Application.get_env(:transport, :enroute_validator_client) | ||
end | ||
|
||
defmodule Transport.EnRouteChouetteValidClient do | ||
@moduledoc """ | ||
Implementation of the enRoute Chouette Valid API client. | ||
""" | ||
@behaviour Transport.EnRouteChouetteValidClient.Wrapper | ||
|
||
@base_url "https://chouette-valid.enroute.mobi/api/validations" | ||
|
||
@impl Transport.EnRouteChouetteValidClient.Wrapper | ||
def create_a_validation(filepath) do | ||
form = | ||
{:multipart, | ||
[ | ||
{"validation[rule_set]", "french"}, | ||
make_file_part("validation[file]", filepath) | ||
]} | ||
|
||
%HTTPoison.Response{status_code: 201, body: body} = http_client().post!(@base_url, form, auth_headers()) | ||
body |> Jason.decode!() |> Map.fetch!("id") | ||
end | ||
|
||
@impl Transport.EnRouteChouetteValidClient.Wrapper | ||
def get_a_validation(validation_id) do | ||
url = validation_url(validation_id) | ||
|
||
%HTTPoison.Response{status_code: 200, body: body} = http_client().get!(url, auth_headers()) | ||
|
||
case body |> Jason.decode!() |> Map.fetch!("user_status") do | ||
"pending" -> :pending | ||
"successful" -> {:successful, url} | ||
"warning" -> :warning | ||
"failed" -> :failed | ||
_ -> :unexpected_validation_status | ||
end | ||
end | ||
|
||
@impl Transport.EnRouteChouetteValidClient.Wrapper | ||
def get_messages(validation_id) do | ||
url = Path.join([validation_url(validation_id), "messages"]) | ||
|
||
%HTTPoison.Response{status_code: 200, body: body} = http_client().get!(url, auth_headers()) | ||
{url, body |> Jason.decode!()} | ||
end | ||
|
||
defp make_file_part(field_name, filepath) do | ||
{field_name, filepath, {"form-data", [{:name, "file"}, {:filename, Path.basename(filepath)}]}, []} | ||
end | ||
|
||
defp validation_url(validation_id) do | ||
Path.join([@base_url, validation_id]) | ||
end | ||
|
||
defp http_client, do: Transport.Shared.Wrapper.HTTPoison.impl() | ||
|
||
defp auth_headers do | ||
[{"authorization", "Token token=#{Application.fetch_env!(:transport, :enroute_validation_token)}"}] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
202 changes: 202 additions & 0 deletions
202
apps/transport/test/transport/validators/enroute_chouette_valid_client_test.exs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
defmodule Transport.EnRouteChouetteValidClientTest do | ||
use ExUnit.Case, async: true | ||
import Mox | ||
|
||
alias Transport.EnRouteChouetteValidClient | ||
|
||
doctest Transport.EnRouteChouetteValidClient, import: true | ||
|
||
setup :verify_on_exit! | ||
|
||
@expected_headers [{"authorization", "Token token=fake_enroute_token"}] | ||
|
||
test "create a validation" do | ||
response_body = | ||
""" | ||
{ | ||
"id": "d8e2b6c2-b1e5-4890-84d4-9b761a445882", | ||
"rule_set": "french", | ||
"user_status": "pending", | ||
"created_at": "2024-07-05T14:41:19.933Z", | ||
"updated_at": "2024-07-05T14:41:19.933Z" | ||
} | ||
""" | ||
|
||
url = "https://chouette-valid.enroute.mobi/api/validations" | ||
|
||
tmp_file = System.tmp_dir!() |> Path.join("enroute_validation_netex_#{Ecto.UUID.generate()}") | ||
|
||
expect(Transport.HTTPoison.Mock, :post!, fn ^url, {:multipart, parts}, headers -> | ||
assert @expected_headers == headers | ||
|
||
assert [ | ||
{"validation[rule_set]", "french"}, | ||
{"validation[file]", tmp_file, {"form-data", [{:name, "file"}, {:filename, Path.basename(tmp_file)}]}, | ||
[]} | ||
] == parts | ||
|
||
%HTTPoison.Response{status_code: 201, body: response_body} | ||
end) | ||
|
||
assert "d8e2b6c2-b1e5-4890-84d4-9b761a445882" == EnRouteChouetteValidClient.create_a_validation(tmp_file) | ||
end | ||
|
||
describe "get a validation" do | ||
test "pending" do | ||
validation_id = "d8e2b6c2-b1e5-4890-84d4-9b761a445882" | ||
|
||
response_body = | ||
""" | ||
{ | ||
"id": "#{validation_id}", | ||
"rule_set": "french", | ||
"user_status": "pending", | ||
"started_at": "2024-07-05T14:41:20.680Z", | ||
"created_at": "2024-07-05T14:41:19.933Z", | ||
"updated_at": "2024-07-05T14:41:19.933Z" | ||
} | ||
""" | ||
|
||
url = "https://chouette-valid.enroute.mobi/api/validations/#{validation_id}" | ||
|
||
expect(Transport.HTTPoison.Mock, :get!, fn ^url, headers -> | ||
assert @expected_headers == headers | ||
%HTTPoison.Response{status_code: 200, body: response_body} | ||
end) | ||
|
||
assert :pending == EnRouteChouetteValidClient.get_a_validation(validation_id) | ||
end | ||
|
||
test "successful" do | ||
validation_id = "d8e2b6c2-b1e5-4890-84d4-9b761a445882" | ||
|
||
response_body = | ||
""" | ||
{ | ||
"id": "#{validation_id}", | ||
"rule_set": "french", | ||
"user_status": "successful", | ||
"started_at": "2024-07-05T14:41:20.680Z", | ||
"ended_at": "2024-07-05T14:41:20.685Z", | ||
"created_at": "2024-07-05T14:41:19.933Z", | ||
"updated_at": "2024-07-05T14:41:19.933Z" | ||
} | ||
""" | ||
|
||
url = "https://chouette-valid.enroute.mobi/api/validations/#{validation_id}" | ||
|
||
expect(Transport.HTTPoison.Mock, :get!, fn ^url, headers -> | ||
assert @expected_headers == headers | ||
%HTTPoison.Response{status_code: 200, body: response_body} | ||
end) | ||
|
||
assert {:successful, url} == EnRouteChouetteValidClient.get_a_validation(validation_id) | ||
end | ||
|
||
test "warning" do | ||
validation_id = "d8e2b6c2-b1e5-4890-84d4-9b761a445882" | ||
|
||
response_body = | ||
""" | ||
{ | ||
"id": "#{validation_id}", | ||
"rule_set": "french", | ||
"user_status": "warning", | ||
"started_at": "2024-07-05T14:41:20.680Z", | ||
"ended_at": "2024-07-05T14:41:20.685Z", | ||
"created_at": "2024-07-05T14:41:19.933Z", | ||
"updated_at": "2024-07-05T14:41:19.933Z" | ||
} | ||
""" | ||
|
||
url = "https://chouette-valid.enroute.mobi/api/validations/#{validation_id}" | ||
|
||
expect(Transport.HTTPoison.Mock, :get!, fn ^url, headers -> | ||
assert @expected_headers == headers | ||
%HTTPoison.Response{status_code: 200, body: response_body} | ||
end) | ||
|
||
assert :warning == EnRouteChouetteValidClient.get_a_validation(validation_id) | ||
end | ||
|
||
test "failed" do | ||
validation_id = "d8e2b6c2-b1e5-4890-84d4-9b761a445882" | ||
|
||
response_body = | ||
""" | ||
{ | ||
"id": "#{validation_id}", | ||
"rule_set": "french", | ||
"user_status": "failed", | ||
"started_at": "2024-07-05T14:41:20.680Z", | ||
"ended_at": "2024-07-05T14:41:20.685Z", | ||
"created_at": "2024-07-05T14:41:19.933Z", | ||
"updated_at": "2024-07-05T14:41:19.933Z" | ||
} | ||
""" | ||
|
||
url = "https://chouette-valid.enroute.mobi/api/validations/#{validation_id}" | ||
|
||
expect(Transport.HTTPoison.Mock, :get!, fn ^url, headers -> | ||
assert @expected_headers == headers | ||
%HTTPoison.Response{status_code: 200, body: response_body} | ||
end) | ||
|
||
assert :failed == EnRouteChouetteValidClient.get_a_validation(validation_id) | ||
end | ||
end | ||
|
||
test "get messages" do | ||
response_body = | ||
""" | ||
[ | ||
{ | ||
"code": "uic-operating-period", | ||
"message": "Resource 23504000009 hasn't expected class but Netex::OperatingPeriod", | ||
"resource": { | ||
"id": "23504000009", | ||
"line": 665, | ||
"class": "OperatingPeriod", | ||
"column": 1, | ||
"filename": "RESOURCE.xml" | ||
}, | ||
"criticity": "error" | ||
}, | ||
{ | ||
"code": "valid-day-bits", | ||
"message": "Mandatory attribute valid_day_bits not found", | ||
"resource": { | ||
"id": "23504000057", | ||
"line": 641, | ||
"class": "OperatingPeriod", | ||
"column": 1, | ||
"filename": "RESOURCE.xml" | ||
}, | ||
"criticity": "error" | ||
}, | ||
{ | ||
"code": "frame-arret-resources", | ||
"message": "Tag frame_id doesn't match ''", | ||
"resource": { | ||
"id": "5030", | ||
"line": 424, | ||
"class": "Quay", | ||
"column": 5 | ||
}, | ||
"criticity": "error" | ||
} | ||
] | ||
""" | ||
|
||
validation_id = Ecto.UUID.generate() | ||
url = "https://chouette-valid.enroute.mobi/api/validations/#{validation_id}/messages" | ||
|
||
expect(Transport.HTTPoison.Mock, :get!, fn ^url, headers -> | ||
assert @expected_headers == headers | ||
%HTTPoison.Response{status_code: 200, body: response_body} | ||
end) | ||
|
||
{^url, messages} = EnRouteChouetteValidClient.get_messages(validation_id) | ||
assert length(messages) == 3 | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters