Current section
Files
Jump to
Current section
Files
lib/seat_json.ex
defmodule SeatJson do
use ExUnit.CaseTemplate
defp usings(auth, mod) do
quote do
require SeatJson
import SeatJson, only: [api: 3, api: 4, check_call_before: 2]
setup context do
context = context
|> unquote(auth).()
|> check_call_before(unquote(mod))
{:ok, context}
end
end
end
using auth: auth do
usings(auth, __CALLER__.module)
end
using [] do
usings(fn a -> a end, __CALLER__.module)
end
def check_call_before(%{call_before: {name, params}} = context, module) do
apply(module, name, params)
context
end
def check_call_before(context, module), do: context
def test_api(opts \\ [], auth, conn, ep)
def test_api([headers: headers, params: p, body_params: bp], auth, conn, ep) do
response = conn |> send_request(headers, p, bp, auth, ep)
## Check the body only if the page exists, otherwise Phoenix informs not existing entry in HTML
{response.status, (unless response.status == 404, do: (Poison.decode! response.resp_body), else: %{})}
end
def test_api(opts, auth, conn, ep) do
test_api [
headers: opts[:headers] || [],
params: opts[:params] || %{},
body_params: opts[:body_params] || %{}
], auth, conn, ep
end
def parse(conn, opts \\ []) do
opts = Keyword.put_new(opts, :parsers, [Plug.Parsers.URLENCODED, Plug.Parsers.MULTIPART])
Plug.Parsers.call(conn, Plug.Parsers.init(opts))
end
defp send_request(conn, headers, params, body_params, auth, ep) do
conn
|> with_session
|> with_auth(auth)
|> with_headers(headers)
|> with_params(params, body_params)
|> ep.call([])
end
def with_auth(conn, {:none, _, _}), do: conn
def with_auth(conn, {level, auth, perms}) do
conn
|> Guardian.Plug.sign_in(auth.user, :token, perms: perms)
end
def with_headers(conn, headers) do
Enum.reduce headers, conn, fn {k, v}, conn -> ConnCase.put_req_header(conn, k, v) end
end
def with_params(conn, params, body_params) do
parse(%{conn | body_params: body_params, params: params})
end
def with_session(conn) do
session_opts = Plug.Session.init(store: :cookie, key: "_app",
encryption_salt: "abc", signing_salt: "abc")
conn
|> Map.put(:secret_key_base, String.duplicate("abcdefgh", 8))
|> Plug.Session.call(session_opts)
|> Plug.Conn.fetch_session()
|> Plug.Conn.fetch_query_params()
end
defp get_counter() do
quote do: Module.put_attribute(__MODULE__, :counter, (Module.get_attribute(__MODULE__, :counter) || 0) + 1)
end
defp quoted_api(method, url, opts, returns: returns, guards: guards) do
method = to_string(method) |> String.upcase
tag = opts[:as] || :none
info = opts[:info]
assertion = case guards do
nil -> quote do: true
g -> quote do: assert(unquote(g))
end
quote do
unquote(get_counter())
@tag as: unquote(tag)
test "API - #{unquote(method)} #{unquote(url)} as #{unquote(tag)} ##{@counter} #{unquote(info) || ""}", meta do
result = SeatJson.test_api(unquote(opts), meta[:auth] || {:none, nil, nil}, conn(unquote(method), unquote(url)), @endpoint)
try do
(fn unquote(returns) -> unquote(assertion) end).(result)
rescue
FunctionClauseError -> raise "Got #{inspect(result, [pretty: true])}"
end
end
end
end
defmacro api(method, url, returns: returns) do
quoted_api(method, url, [], returns: returns, guards: nil)
end
defmacro api(method, url, returns: returns, guards: guards) do
quoted_api(method, url, [], returns: returns, guards: guards)
end
defmacro api(method, url, opts, returns: returns) do
quoted_api(method, url, opts, returns: returns, guards: nil)
end
defmacro api(method, url, opts, returns: returns, guards: guards) do
quoted_api(method, url, opts, returns: returns, guards: guards)
end
end