Skip to content

Commit

Permalink
Copy headers across redirects (#131)
Browse files Browse the repository at this point in the history
What changed?
=============

In order to emulate browser behavior better, we want to copy headers
across redirects.

Whenever we dispatch to the endpoint, `Phoenix.ConnTest.recycle/2`
automatically gets called. But by default it only recycles "accept",
"accept-language", and "authorization".

This commit adds calls to `recycle/2` where we manually copying all
request headers.

For more, see [recycle/2 docs]:

```
  Recycling receives a connection and returns a new connection,
  containing cookies and relevant information from the given one.

  This emulates behaviour performed by browsers where cookies returned
  in the response are available in following requests.

  By default, only the headers "accept", "accept-language", and
  "authorization" are recycled. However, a custom set of headers can be
  specified by passing a list of strings representing its names as the
  second argument of the function.

  Note recycle/1 is automatically invoked when dispatching to the
  endpoint, unless the connection has already been recycled.
```

[recycle/2 docs]: https://hexdocs.pm/phoenix/Phoenix.ConnTest.html#recycle/2
  • Loading branch information
germsvel authored Oct 2, 2024
1 parent 5f106cd commit 7ad8cb1
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 3 deletions.
14 changes: 12 additions & 2 deletions lib/phoenix_test.ex
Original file line number Diff line number Diff line change
Expand Up @@ -214,19 +214,29 @@ defmodule PhoenixTest do
you're visiting.
"""
def visit(conn, path) do
case get(conn, path) do
conn
|> recycle(all_headers(conn))
|> get(path)
|> case do
%{assigns: %{live_module: _}} = conn ->
PhoenixTest.Live.build(conn)

%{status: 302} = conn ->
path = redirected_to(conn)
visit(conn, path)

conn
|> recycle(all_headers(conn))
|> visit(path)

conn ->
PhoenixTest.Static.build(conn)
end
end

defp all_headers(conn) do
Enum.map(conn.req_headers, &elem(&1, 0))
end

@doc """
Clicks a link with given text and performs the action.
Expand Down
9 changes: 8 additions & 1 deletion lib/phoenix_test/static.ex
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,18 @@ defmodule PhoenixTest.Static do
end

defp perform_submit(session, form, form_data) do
session.conn
conn = session.conn

conn
|> recycle(all_headers(conn))
|> dispatch(@endpoint, form.method, form.action, form_data)
|> maybe_redirect(session)
end

defp all_headers(conn) do
Enum.map(conn.req_headers, &elem(&1, 0))
end

defp update_active_form(session, form, form_data) do
active_form =
form
Expand Down
36 changes: 36 additions & 0 deletions test/phoenix_test/live_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ defmodule PhoenixTest.LiveTest do
|> assert_has("h1", text: "LiveView main page")
end

test "preserves headers across redirects", %{conn: conn} do
conn
|> Plug.Conn.put_req_header("x-custom-header", "Some-Value")
|> visit("/live/redirect_on_mount/redirect")
|> assert_has("h1", text: "LiveView main page")
|> then(fn %{conn: conn} ->
assert {"x-custom-header", "Some-Value"} in conn.req_headers
end)
end

test "raises error if route doesn't exist", %{conn: conn} do
assert_raise ArgumentError, ~r/404/, fn ->
visit(conn, "/live/non_route")
Expand Down Expand Up @@ -102,6 +112,17 @@ defmodule PhoenixTest.LiveTest do
|> assert_has("h1", text: "Main page")
end

test "preserves headers across navigation", %{conn: conn} do
conn
|> Plug.Conn.put_req_header("x-custom-header", "Some-Value")
|> visit("/live/index")
|> click_link("Navigate to non-liveview")
|> assert_has("h1", text: "Main page")
|> then(fn %{conn: conn} ->
assert {"x-custom-header", "Some-Value"} in conn.req_headers
end)
end

test "raises error when there are multiple links with same text", %{conn: conn} do
assert_raise ArgumentError, ~r/2 of them matched the text filter/, fn ->
conn
Expand Down Expand Up @@ -860,6 +881,21 @@ defmodule PhoenixTest.LiveTest do
|> assert_has("h1", text: "Main page")
end

test "preserves headers after form submission and redirect", %{conn: conn} do
conn
|> Plug.Conn.put_req_header("x-custom-header", "Some-Value")
|> visit("/live/index")
|> within("#redirect-form-to-static", fn session ->
session
|> fill_in("Name", with: "Aragorn")
|> submit()
end)
|> assert_has("h1", text: "Main page")
|> then(fn %{conn: conn} ->
assert {"x-custom-header", "Some-Value"} in conn.req_headers
end)
end

test "submits regular (non phx-submit) form", %{conn: conn} do
conn
|> visit("/live/index")
Expand Down
36 changes: 36 additions & 0 deletions test/phoenix_test/static_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ defmodule PhoenixTest.StaticTest do
|> assert_has("h1", text: "Main page")
end

test "preserves headers across redirects", %{conn: conn} do
conn
|> Plug.Conn.put_req_header("x-custom-header", "Some-Value")
|> visit("/page/redirect_to_static")
|> assert_has("h1", text: "Main page")
|> then(fn %{conn: conn} ->
assert {"x-custom-header", "Some-Value"} in conn.req_headers
end)
end

test "raises error if route doesn't exist", %{conn: conn} do
assert_raise ArgumentError, ~r/404/, fn ->
visit(conn, "/non_route")
Expand Down Expand Up @@ -70,6 +80,17 @@ defmodule PhoenixTest.StaticTest do
|> assert_has("h1", text: "Page 2")
end

test "preserves headers across navigation", %{conn: conn} do
conn
|> Plug.Conn.put_req_header("x-custom-header", "Some-Value")
|> visit("/page/index")
|> click_link("a", "Page 2")
|> assert_has("h1", text: "Page 2")
|> then(fn %{conn: conn} ->
assert {"x-custom-header", "Some-Value"} in conn.req_headers
end)
end

test "handles navigation to a LiveView", %{conn: conn} do
conn
|> visit("/page/index")
Expand Down Expand Up @@ -774,6 +795,21 @@ defmodule PhoenixTest.StaticTest do
|> assert_has("h1", text: "LiveView main page")
end

test "preserves headers after form submission and redirect", %{conn: conn} do
conn
|> Plug.Conn.put_req_header("x-custom-header", "Some-Value")
|> visit("/page/index")
|> within("#no-submit-button-and-redirect", fn session ->
session
|> fill_in("Name", with: "Aragorn")
|> submit()
end)
|> assert_has("h1", text: "LiveView main page")
|> then(fn %{conn: conn} ->
assert {"x-custom-header", "Some-Value"} in conn.req_headers
end)
end

test "handles when form PUTs data through hidden input", %{conn: conn} do
conn
|> visit("/page/index")
Expand Down

0 comments on commit 7ad8cb1

Please sign in to comment.