diff --git a/lib/phoenix/test/conn_test.ex b/lib/phoenix/test/conn_test.ex index 470538e714..9bcd6086e7 100644 --- a/lib/phoenix/test/conn_test.ex +++ b/lib/phoenix/test/conn_test.ex @@ -243,6 +243,29 @@ defmodule Phoenix.ConnTest do |> endpoint.call(endpoint.init(action)) end + @doc """ + Follows a redirected conn. + + ## Examples + + + assert follow_redirect(conn, ~"/").resp_body =~ "foo" + """ + def follow_redirect(%Conn{status: status} = conn, expected_to) when status in 300..308 do + to = Plug.Conn.get_resp_header(conn, "location") + if "#{expected_to}" == "#{to}" do + dispatch(conn, conn.private.phoenix_endpoint, :get, expected_to) + else + raise ArgumentError, "expected connection to redirect to #{inspect(expected_to)}, but got #{inspect(to)}" + end + end + def follow_redirect(%Conn{status: status}, _expected_to) when status not in 300..308 do + raise "expected redirection with status 302, got: #{status}" + end + def follow_redirect(%Conn{} = _conn, _exptected_to) do + raise "expected connection to have redirected but no response was set/sent" + end + defp from_set_to_sent(%Conn{state: :set} = conn), do: Conn.send_resp(conn) defp from_set_to_sent(conn), do: conn diff --git a/test/phoenix/test/conn_test.exs b/test/phoenix/test/conn_test.exs index 1041794e13..73049ad941 100644 --- a/test/phoenix/test/conn_test.exs +++ b/test/phoenix/test/conn_test.exs @@ -156,6 +156,47 @@ defmodule Phoenix.Test.ConnTest do refute conn.private.phoenix_recycled end + test "follow_redirect/2" do + Enum.each 300..308, fn(status) -> + conn = + build_conn(:get, "/") + |> Endpoint.call(Endpoint.init([])) + |> put_resp_header("location", "/new_location") + |> send_resp(status, "foo") + + assert follow_redirect(conn, "/new_location").resp_body == "foo" + end + end + + test "follow_redirect/2 without header" do + assert_raise ArgumentError, + "expected connection to redirect to \"/new_location\", but got []", fn -> + build_conn(:get, "/") + |> send_resp(302, "ok") + |> follow_redirect("/new_location") + end + end + + test "follow_redirect/2 without redirection" do + assert_raise RuntimeError, + "expected redirection with status 302, got: 200", fn -> + build_conn(:get, "/") + |> put_resp_header("location", "new location") + |> send_resp(200, "ok") + |> follow_redirect("/new_location") + end + end + + test "follow_redirect/2 with wrong path" do + assert_raise ArgumentError, + "expected connection to redirect to \"/wrong_location\", but got [\"/new_location\"]", fn -> + build_conn(:get, "/") + |> put_resp_header("location", "/new_location") + |> send_resp(302, "ok") + |> follow_redirect("/wrong_location") + end + end + describe "recycle/1" do test "relevant request headers are persisted" do conn =