arkadiy kraportov
arkadiy kraportov

Reputation: 3729

stub Guardian.Plug.EnsureAuthenticated for Phoenix Controller testing

I have Guardian.Plug.EnsureAuthenticated in my router pipeline. How do I make it pass during Controller tests?

Upvotes: 1

Views: 1028

Answers (2)

Svilen
Svilen

Reputation: 2648

I solved this by creating a test tag, that creates and logs the user using Guardian's sign_in method (use api_sign_in if on Guardian 0.14.x). Then you can apply it to the tests that need a logged in user, like so:

  setup %{conn: conn} = config do
    cond do
      config[:login] ->
        user = insert_user()
        signed_conn = Guardian.Plug.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

If you need the user you just created for an assertion, you can pass it along with the connection:

 config[:login] ->
   user = insert_user()
   signed_conn = Guardian.Plug.sign_in(conn, user)
   {:ok, conn: signed_conn, user: user}

And pattern-match it in the test:

  @tag :login
  test "shows page only when logged in", %{conn: conn, user: user} do
    # ...
  end

Consider moving the insert_user logic to a setup_all block to reduce database operations and speed up the tests.

Upvotes: 5

arkadiy kraportov
arkadiy kraportov

Reputation: 3729

I got my Phoenix Authorized Controllers tests pass. Here is my solution:

test/controllers/inbox_controller_test.exs:

defmodule MyApp.InboxControllerTest do
  use MyApp.ConnCase
  alias MyApp.User

  setup do
    user = %User{id: "a1234"}
    {:ok, jwt, full_claims} = Guardian.encode_and_sign(user)
    {:ok, %{user: user, jwt: jwt, claims: full_claims}}
  end

  test "lists all entries on index", %{jwt: jwt} do
    conn = conn()
      |> put_req_header("authorization", "Bearer #{jwt}")
      |> get(inbox_path(conn, :index))
    assert json_response(conn, 200)["inboxes"] == []
  end
end

config/test.exs:

config :guardian, Guardian,
  serializer: MyApp.TestGuardianSerializer

test/support/test_guardian_serializer.ex:

defmodule MyApp.TestGuardianSerializer do
  @behaviour Guardian.Serializer

  alias MyApp.User

  def for_token(user = %User{}), do: { :ok, "User:#{user.id}" }
  def for_token(_), do: { :error, "Unknown resource type" }

  def from_token("User:" <> id) do
    {:ok, %User{id: id, login: "admin"}}
  end

  def from_token(_), do: { :error, "Unknown resource type" }
end

Upvotes: 5

Related Questions