defmodule Chaperon.Action do
@moduledoc """
Helper functions to be used with `Chaperon.Actionable`.
"""
@doc """
Retries `action` within `session` by calling `Chaperon.Actionable.abort/2`
followed by `Chaperon.Actionable.run/2`.
"""
def retry(action, session) do
with {:ok, action, session} <- Chaperon.Actionable.abort(action, session) do
Chaperon.Actionable.run(action, session)
end
end
@doc """
Returns a `Chaperon.Action.Error` for the given arguments.
"""
def error(action, session, reason) do
%Chaperon.Action.Error{
reason: reason,
action: action,
session: session
}
end
@doc """
Every `Chaperon.Actionable` can expose a `callback` field.
`callback` can be either:
- a callback function or atom naming the callback function inside the session's current scenario module:
`atom | ((Chaperon.Session.t, any | {:error, any}) -> any)`
- a map containing callback and error functions:
```
%{
ok: atom | ((Chaperon.Session.t, any) -> any),
error: atom | ((Chaperon.Session.t, any) -> any)
}
```
When defining just a single callback function, it will be called in both
success and error cases (passed in as `{:error, reason}`).
To handle each case individually, you can just use pattern matching:
session
|> post("/greet", json: [hello: "world!"], with_result: fn
(session, {:error, reason}) ->
# handle error case here
session
|> log_error("Failed to greet")
(session, %HTTPoison.Response{body: response}) ->
# do something with successful response here
session
|> log_info("Greeted successfully!")
end)
"""
def callback(%{callback: %{ok: cb}}), do: cb
def callback(%{callback: cb}), do: cb
def error_callback(%{callback: %{error: cb}}), do: cb
def error_callback(%{callback: cb}),
do: fn session, resp ->
session
|> Chaperon.Session.call_callback(cb, {:error, resp})
end
def error_callback(_), do: nil
end