Reputation: 21
I am struggling at testing api endpoint which requires token header. The idea is to test two cases, with and without authentication token.
I've come up with the following working solution, but it feels somewhat clumsy to me.
defmodule MyApi.SecretControllerTest do
use MyApi.ConnCase
alias MyApi.{Repo, User, Session}
setup %{conn: conn} do
user = create_user(%{name: "john"})
session = create_session(user)
conn = conn
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> session.token)
{:ok, conn: conn}
end
def create_user(%{name: name}) do
User.changeset(%User{}, %{email: "#{name}@gmail.com"})
|> Repo.insert!
end
def create_session(user) do
Session.create_changeset(%Session{user_id: user.id}, %{})
|> Repo.insert!
end
test "returns 401 error when user is not authenticated" do
conn = get build_conn, "/api/secrets"
assert json_response(conn, 401)["error"] != %{}
end
test "renders secret resource when user is authenticated", %{conn: conn} do
conn = get conn, secret_path(conn, :index)
assert json_response(conn, 200)["message"] != %{}
end
end
Upvotes: 0
Views: 1130
Reputation: 2648
If you're using Guardian for authentication, and the endpoint is an API one (e.g. going through an :api
pipeline) you can use the api_sign_in helper method, that doesn't rely on an existing session (so you can remove that session-related code).
Here's an example of putting the "sign in" logic into a test tag, that you can apply to the tests that require a logged in user:
setup %{conn: conn} = config do
cond do
config[:login] ->
user = insert_user()
signed_conn = Guardian.Plug.api_sign_in(conn, user)
{:ok, conn: signed_conn}
true ->
:ok
end
end
@tag :login
test "shows page only when logged in", %{conn: conn} do
conn = get(conn, some_page_path(conn, :index))
assert html_response(conn, 200)
end
Upvotes: 2