Phoenix.ConnTest

Parsed documentation:
View on GitHub
Conveniences for testing Phoenix endpoints and connection related helpers.

You likely want to use this module or make it part of your `ExUnit.CaseTemplate`.
Once used, this module automatically imports all functions defined here as
well as the functions in `Plug.Conn`.

## Endpoint testing

`Phoenix.ConnTest` typically works against endpoints. That's the preferred way
to test anything that your router dispatches to:

    @endpoint MyAppWeb.Endpoint
    
    test "says welcome on the home page" do
      conn = get(build_conn(), "/")
      assert conn.resp_body =~ "Welcome!"
    end

    test "logs in" do
      conn = post(build_conn(), "/login", [username: "john", password: "doe"])
      assert conn.resp_body =~ "Logged in!"
    end

The `@endpoint` module attribute contains the endpoint under testing,
most commonly your application endpoint itself. If you are using the
MyApp.ConnCase generated by Phoenix, it is automatically set for you.

As in your router and controllers, the connection is the main abstraction
in testing. `build_conn()` returns a new connection and functions in this
module can be used to manipulate the connection before dispatching
to the endpoint.

For example, one could set the accepts header for json requests as
follows:

    build_conn()
    |> put_req_header("accept", "application/json")
    |> get("/")

You can also created your own helpers, such as `json_conn()` that uses
`build_conn/0` and `put_req_header/3`, so you avoid repeating the connection
setup throughout your tests.

## Controller testing

The functions in this module can also be used for controller testing.
While endpoint testing is preferred over controller testing, especially
since the controller in Phoenix plays an integration role between your
domain and your views, unit testing controllers may be helpful in some
situations.

For such cases, you need to set the `@endpoint` attribute to your controller
and pass an atom representing the action to dispatch:

  @endpoint MyAppWeb.HomeController
  
  test "says welcome on the home page" do
    conn = get(build_conn(), :index)
    assert conn.resp_body =~ "Welcome!"
  end

Keep in mind that, once the `@endpoint` variable is set, all tests after
setting it will be affected.

## Views testing

Under other circumstances, you may be testing a view or another layer that
requires a connection for processing. For such cases, a connection can be
created using the `conn/3` helper:

    MyApp.UserView.render("hello.html", conn: build_conn(:get, "/"))

While `build_conn/0` returns a connection with no request information to it,
`build_conn/2` returns a connection with the given request information already
filled in.

## Recycling

Browsers implement a storage by using cookies. When a cookie is set in the
response, the browser stores it and sends it in the next request.

To emulate this behaviour, this module provides the idea of recycling.
The `recycle/1` function receives a connection and returns a new connection,
similar to the one returned by `build_conn/0` with all the response cookies
from the previous connection defined as request headers. This is useful when
testing multiple routes that require cookies or session to work.

Keep in mind Phoenix will automatically recycle the connection between
dispatches. This usually works out well most times, but it may discard
information if you are modifying the connection before the next dispatch:

    # No recycling as the connection is fresh
    conn = get(build_conn(), "/")

    # The connection is recycled, creating a new one behind the scenes
    conn = post(conn, "/login")

    # We can also recycle manually in case we want custom headers
    conn =
      conn
      |> recycle()
      |> put_req_header("x-special", "nice")

    # No recycling as we did it explicitly
    conn = delete(conn, "/logout")

Recycling also recycles the "accept" and "authorization" headers,
as well as peer data information.
No suggestions.
Please help! Open an issue on GitHub if this assessment is incorrect.