Skip to content

Instantly share code, notes, and snippets.

@moroz
Created November 21, 2020 03:28
Show Gist options
  • Save moroz/0a592504f9b22501f871787a4eaabfd6 to your computer and use it in GitHub Desktop.
Save moroz/0a592504f9b22501f871787a4eaabfd6 to your computer and use it in GitHub Desktop.
Test helper for testing Absinthe GraphQL APIs in ExUnit
defmodule MyAppWeb.ApiCase do
use ExUnit.CaseTemplate
using(opts) do
schema = Keyword.get(opts, :schema, MyAppWeb.Api.Schema)
api_path = Keyword.get(opts, :api_path, "/api")
quote do
@__schema__ unquote(schema)
@__api_path__ unquote(api_path)
@endpoint MyAppWeb.Endpoint
alias MyApp.Repo
use ExUnit.Case
import Ecto
import Ecto.Changeset
import Ecto.Query
import MyAppWeb.ConnCase
import MyApp.DataCase
import MyApp.Factory
import MyAppWeb.ApiCase
import Phoenix.ConnTest
def run_query(document, variables, context \\ %{}) do
opts = [variables: normalize_variables(variables), context: context]
with %{data: data} <- Absinthe.run!(document, @__schema__, opts) do
data
else
error -> {:error, error}
end
end
def query(document, variables) do
run_query(document, variables)
end
def mutate(document, variables) do
run_query(document, variables)
end
def query(document, user, variables) do
query_with_user(document, user, variables)
end
def query_with_user(document, user, variables) do
run_query(document, variables, %{current_user: user})
end
def mutate_with_user(document, user, variables) do
query_with_user(document, user, variables)
end
def query_over_router(conn, query, variables \\ %{}) do
conn
|> Plug.Conn.put_req_header("content-type", "application/json")
|> post(@__api_path__, Jason.encode!(%{query: query, variables: variables}))
end
setup tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(MyApp.Repo)
Absinthe.Test.prime(@__schema__)
unless tags[:async] do
Ecto.Adapters.SQL.Sandbox.mode(MyApp.Repo, {:shared, self()})
end
[conn: Phoenix.ConnTest.build_conn()]
end
end
end
def normalize_variables([]), do: []
def normalize_variables([id | _tail] = list) when is_binary(id) or is_integer(id), do: list
def normalize_variables([head | _tail] = list) when is_map(head) do
Enum.map(list, &normalize_variables/1)
end
def normalize_variables(variables) when is_map(variables) or is_list(variables) do
Map.new(variables, fn {key, val} -> {camelize_key(key), normalize_variables(val)} end)
end
def normalize_variables(atom) when is_atom(atom) and atom not in [true, false, nil],
do: to_string(atom) |> String.upcase()
def normalize_variables(other), do: other
def camelize_key(key) do
to_string(key)
|> Absinthe.Utils.camelize(lower: true)
end
def get_ids(actual) do
Enum.map(actual, fn
%{"id" => id} when is_binary(id) -> String.to_integer(id)
%{id: id} when is_integer(id) -> id
end)
|> Enum.sort()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment