diff --git a/README.md b/README.md index f207221..f841b9c 100644 --- a/README.md +++ b/README.md @@ -70,3 +70,44 @@ job = %{ credentials = %Credentials{client_id: "...", client_secret: "..."} StuartClientElixir.post("/v2/jobs", Jason.encode!(job), %{environment: Environment.sandbox(), credentials: credentials}) ``` + +#### Send a PATCH request to the Stuart API + +```elixir +alias StuartClientElixir.{Environment, Credentials} + +job = %{ + job: %{ + deliveries: [ + %{ + id: "43035", + client_reference: "new_client_reference", + package_description: "new_package_description", + pickup: %{ + comment: "new_comment", + contact: %{ + firstname: "new_firstname", + lastname: "new_lastname", + phone: "+33628046091", + email: "sd@df.com", + company: "new_company" + } + }, + dropoff: %{ + comment: "new_comment", + contact: %{ + firstname: "new_firstname", + lastname: "new_lastname", + phone: "+33628046095", + email: "new_email@mymail.com", + company: "new_company" + } + } + } + ] + } +} + +credentials = %Credentials{client_id: "...", client_secret: "..."} +StuartClientElixir.patch("/v2/jobs/1234", Jason.encode!(job), %{environment: Environment.sandbox(), credentials: credentials}) +``` diff --git a/lib/stuart_client_elixir.ex b/lib/stuart_client_elixir.ex index 6b93ed7..04fc670 100644 --- a/lib/stuart_client_elixir.ex +++ b/lib/stuart_client_elixir.ex @@ -3,5 +3,6 @@ defmodule StuartClientElixir do defdelegate get(resource, options), to: HttpClient defdelegate post(resource, body, options), to: HttpClient + defdelegate patch(resource, body, options), to: HttpClient defdelegate forget_token!(client_id), to: Authenticator end diff --git a/lib/stuart_client_elixir/http_client.ex b/lib/stuart_client_elixir/http_client.ex index d996864..f221480 100644 --- a/lib/stuart_client_elixir/http_client.ex +++ b/lib/stuart_client_elixir/http_client.ex @@ -9,24 +9,42 @@ defmodule StuartClientElixir.HttpClient do @callback get(url, options) :: ok_response | error_response @callback post(url, body, options) :: ok_response | error_response + @callback patch(url, body, options) :: ok_response | error_response - def get(resource, %{environment: environment, credentials: credentials}) do - with url <- url(resource, environment), - {:ok, access_token} <- Authenticator.access_token(environment, credentials), - headers <- default_headers(access_token) do - HTTPoison.get(url, headers, default_options()) - |> to_api_response() - else - {:error, %OAuth2.Response{}} = oauth_response -> to_api_response(oauth_response) - {:error, %OAuth2.Error{}} = oauth_error -> to_api_response(oauth_error) - end + def get(resource, options) do + perform_request(:get, options, resource) + end + + def post(resource, body, options) do + perform_request(:post, options, resource, body) end - def post(resource, body, %{environment: environment, credentials: credentials}) do + def patch(resource, body, options) do + perform_request(:patch, options, resource, body) + end + + ##################### + # Private functions # + ##################### + + def perform_request( + method, + %{ + environment: environment, + credentials: credentials + }, + resource, + body \\ nil + ) + when method in [:get, :post, :patch] do with url <- url(resource, environment), {:ok, access_token} <- Authenticator.access_token(environment, credentials), headers <- default_headers(access_token) do - HTTPoison.post(url, body, headers, default_options()) + case method do + :get -> HTTPoison.get(url, headers, default_options()) + :post -> HTTPoison.post(url, body, headers, default_options()) + :patch -> HTTPoison.patch(url, body, headers, default_options()) + end |> to_api_response() else {:error, %OAuth2.Response{}} = oauth_response -> to_api_response(oauth_response) @@ -34,10 +52,6 @@ defmodule StuartClientElixir.HttpClient do end end - ##################### - # Private functions # - ##################### - defp default_options do [recv_timeout: 10_000] end diff --git a/mix.exs b/mix.exs index 1be1d8a..af40603 100644 --- a/mix.exs +++ b/mix.exs @@ -12,7 +12,7 @@ defmodule StuartClientElixir.MixProject do } }, version: "1.2.0", - elixir: "~> 1.7", + elixir: "~> 1.6", start_permanent: Mix.env() == :prod, deps: deps() ] diff --git a/test/stuart_client_elixir/http_client_test.exs b/test/stuart_client_elixir/http_client_test.exs index d04601c..9b8e2fb 100644 --- a/test/stuart_client_elixir/http_client_test.exs +++ b/test/stuart_client_elixir/http_client_test.exs @@ -32,7 +32,8 @@ defmodule StuartClientElixirTest.HttpClientTest do [], [ get: fn url, _headers, _options -> response(:get, url) end, - post: fn url, _body, _headers, _options -> response(:post, url) end + post: fn url, _body, _headers, _options -> response(:post, url) end, + patch: fn url, _body, _headers, _options -> response(:patch, url) end ] } ]) do @@ -41,7 +42,7 @@ defmodule StuartClientElixirTest.HttpClientTest do describe "get" do test "calls HTTPoison with correct parameters" do - expected_response = %{body: %{"sample" => "get response"}, status_code: 201} + expected_response = %{body: %{"sample" => "get response"}, status_code: 200} assert HttpClient.get("/sample-endpoint", config()) == expected_response @@ -63,8 +64,7 @@ defmodule StuartClientElixirTest.HttpClientTest do test "returns explicit error when authentication fails because of other OAuth error" do expected_response = {:error, oauth2_error()} - assert HttpClient.get("/sample-endpoint", config(@oauth_error)) == - expected_response + assert HttpClient.get("/sample-endpoint", config(@oauth_error)) == expected_response end test "returns explicit error when GET request fails" do @@ -112,26 +112,66 @@ defmodule StuartClientElixirTest.HttpClientTest do end end + describe "patch" do + test "calls HTTPoison with correct parameters" do + expected_response = %{body: %{"sample" => "patch response"}, status_code: 200} + + assert HttpClient.patch("/sample-endpoint", sample_request_body(), config()) == + expected_response + + assert called( + HTTPoison.patch( + "https://sandbox-api.stuart.com/sample-endpoint", + sample_request_body(), + expected_headers(), + expected_options() + ) + ) + end + + test "returns explicit error when authentication fails because of bad credentials" do + expected_response = %{body: %{"error" => "Bad credentials"}, status_code: 401} + + assert HttpClient.patch("/sample-endpoint", sample_request_body(), config(@bad_credentials)) == + expected_response + end + + test "returns explicit error when authentication fails because of other OAuth error" do + expected_response = {:error, oauth2_error()} + + assert HttpClient.patch("/sample-endpoint", sample_request_body(), config(@oauth_error)) == + expected_response + end + + test "returns explicit error when PATCH request fails" do + expected_response = {:error, %HTTPoison.Error{id: nil, reason: :timeout}} + + assert HttpClient.patch("/timeout", sample_request_body(), config()) == expected_response + end + end + ##################### # Private functions # ##################### - defp response(:get, "https://sandbox-api.stuart.com/timeout") do + @timeout_url "https://sandbox-api.stuart.com/timeout" + + defp response(_, @timeout_url) do {:error, %HTTPoison.Error{id: nil, reason: :timeout}} end defp response(:get, _) do - {:ok, %HTTPoison.Response{status_code: 201, body: Jason.encode!(%{sample: "get response"})}} - end - - defp response(:post, "https://sandbox-api.stuart.com/timeout") do - {:error, %HTTPoison.Error{id: nil, reason: :timeout}} + {:ok, %HTTPoison.Response{status_code: 200, body: Jason.encode!(%{sample: "get response"})}} end defp response(:post, _) do {:ok, %HTTPoison.Response{status_code: 201, body: Jason.encode!(%{sample: "post response"})}} end + defp response(:patch, _) do + {:ok, %HTTPoison.Response{status_code: 200, body: Jason.encode!(%{sample: "patch response"})}} + end + defp authenticator_response(@good_credentials) do {:ok, "sample-access-token"} end