defmodule GitHub.Plugin.TestClient do
@moduledoc """
Local client used for testing purposes
For more information on the testing facilities available in this library, see `GitHub.Testing`.
"""
alias GitHub.Error
alias GitHub.Operation
alias GitHub.Plugin.TypedDecoder
alias GitHub.Testing
@generic_documentation "https://docs.github.com/en/rest"
@not_found_message "Not Found"
@rate_limited_documentation "https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting"
@rate_limited_message "API rate limit exceeded for xxx.xxx.xxx.xxx. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)"
@unauthorized_message "Must have admin rights to [resource]"
@doc """
Perform a client operation using mocks, and record the call for later assertions
"""
@spec request(Operation.t(), keyword) :: {:ok, Operation.t()} | {:error, Error.t()}
def request(operation, _opts) do
Testing.put_call(operation)
case Testing.get_mock_result(operation) do
{:ok, data} -> ok(operation, data)
{:ok, data, opts} -> ok(operation, data, opts)
{:error, data} -> error(operation, data)
{:error, data, opts} -> error(operation, data, opts)
end
end
@spec ok(Operation.t(), any, keyword) :: {:ok, Operation.t()}
defp ok(operation, data, opts \\ []) do
code = Keyword.get(opts, :code, 200)
{:ok, %Operation{operation | response_body: data, response_code: code}}
end
@spec error(Operation.t(), any, keyword) :: {:error, Error.t()}
defp error(operation, data, opts \\ [])
defp error(operation, :not_found, _opts) do
error =
struct(GitHub.BasicError, %{
documentation_url: @generic_documentation,
message: @not_found_message
})
TypedDecoder.normalize_errors(
%Operation{operation | response_body: error, response_code: 404},
[]
)
end
defp error(operation, :rate_limited, _opts) do
error =
struct(GitHub.BasicError, %{
documentation_url: @rate_limited_documentation,
message: @rate_limited_message
})
TypedDecoder.normalize_errors(
%Operation{operation | response_body: error, response_code: 403},
[]
)
end
defp error(operation, :unauthorized, _opts) do
error =
struct(GitHub.BasicError, %{
documentation_url: @generic_documentation,
message: @unauthorized_message
})
TypedDecoder.normalize_errors(
%Operation{operation | response_body: error, response_code: 403},
[]
)
end
defp error(operation, data, opts) do
code = opts[:code] || 400
message = "Error during test request"
step = {__MODULE__, :request}
{:error,
Error.new(code: code, message: message, operation: operation, source: data, step: step)}
end
end