A section of an app I’m working on is hosted on a subdomain: foo.app.com
. I use setup
to add the host to the conn
. I’m new to Phoenix and Elixir and I don’t know if this is right:
setup do
host = "foo." <> MyAppWeb.Endpoint.config(:url)[:host]
conn = Phoenix.ConnTest.build_conn(:get, "http://#{host}/", nil)
{:ok, conn: conn}
end
It works unless I want to reuse the conn to make a new request. Then the route for the follow up request is not recognized. For example
describe "delete role" do
test "deletes chosen role", %{conn: conn, role: role} do
conn = delete conn, telesales_admin_role_path(conn, :delete, role)
assert redirected_to(conn) == telesales_admin_role_path(conn, :index)
conn = get conn, telesales_admin_role_path(conn, :index)
refute html_response(conn, 200) =~ role.user.name
end
end
When the test gets to conn = get conn, telesales_admin_role_path(conn, :index)
, I get this error:
2) test delete role deletes chosen role (MyAppWeb.Telesales.Admin.RoleControllerTest)
test/my_app_web/controllers/telesales/admin/role_controller_test.exs:41
** (Phoenix.Router.NoRouteError) no route found for DELETE /admin/roles/230 (MyAppWeb.Router)
code: conn = delete conn, telesales_admin_role_path(conn, :delete, role)
stacktrace:
(my_app) lib/my_app_web/router.ex:1: MyAppWeb.Router.__match_route__/4
(my_app) lib/phoenix/router.ex:303: MyAppWeb.Router.call/2
(my_app) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.plug_builder_call/2
(my_app) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.call/2
(phoenix) lib/phoenix/test/conn_test.ex:224: Phoenix.ConnTest.dispatch/5
test/my_app_web/controllers/telesales/admin/role_controller_test.exs:43: (test)
I have passing tests for the route telesales_admin_role_path(conn, :index)
. So something is wrong.
Can someone please explain to me what is happening?
I dumped the conn
before and after the first request to find clues, but I can’t see anything.
Before the first request (delete conn, telesales_admin_role_path(conn, :delete, role)
):
%Plug.Conn{adapter: {Plug.Adapters.Test.Conn, :...}, assigns: %{},
before_send: [], body_params: %Plug.Conn.Unfetched{aspect: :body_params},
cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false,
host: "foo.localhost", method: "GET", owner: #PID<0.617.0>,
params: %Plug.Conn.Unfetched{aspect: :params}, path_info: [], path_params: %{},
peer: {{127, 0, 0, 1}, 111317}, port: 80,
private: %{guardian_default_claims: %{"aud" => "my_app", "exp" => 1530883668,
"iat" => 1528464468, "iss" => "my_app",
"jti" => "a6a55bdf-d35a-4b52-948c-128dbc286ef6", "nbf" => 1528464467,
"sub" => "1453", "typ" => "access"},
guardian_default_resource: %MyApp.Accounts.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
email: "email_8866@example.com", id: 1453, image: "avatar.jpg",
inserted_at: ~N[2018-06-08 13:27:48.545323], name: "Elmer J. Fudd 8866",
uid: "8866", updated_at: ~N[2018-06-08 13:27:48.545340]},
guardian_default_token: "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJvYnJhbWF4IiwiZXhwIjoxNTMwODgzNjY4LCJpYXQiOjE1Mjg0NjQ0NjgsImlzcyI6Im9icmFtYXgiLCJqdGkiOiJhNmE1NWJkZi1kMzVhLTRiNTItOTQ4Yy0xMjhkYmMyODZlZjYiLCJuYmYiOjE1Mjg0NjQ0NjcsInN1YiI6IjE0NTMiLCJ0eXAiOiJhY2Nlc3MifQ.ZW0vcNyRTiM_tgM27njihrLWLx8Qqqh_vGyJZdnsnzKu99865YaN03VttTznzuybaBAg8NqrGeDsVsg3WZTsPQ",
phoenix_recycled: true, plug_skip_csrf_protection: true},
query_params: %Plug.Conn.Unfetched{aspect: :query_params}, query_string: "",
remote_ip: {127, 0, 0, 1}, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies},
req_headers: [], request_path: "/", resp_body: nil, resp_cookies: %{},
resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}],
scheme: :http, script_name: [], secret_key_base: nil, state: :unset,
status: nil}
After the first request:
%Plug.Conn{adapter: {Plug.Adapters.Test.Conn, :...},
assigns: %{current_user: %MyApp.Accounts.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
email: "email_8866@example.com", id: 1453, image: "avatar.jpg",
inserted_at: ~N[2018-06-08 13:27:48.545323], name: "Elmer J. Fudd 8866",
uid: "8866", updated_at: ~N[2018-06-08 13:27:48.545340]}},
before_send: [#Function<0.113748926/1 in Plug.CSRFProtection.call/2>,
#Function<4.31088025/1 in Phoenix.Controller.fetch_flash/2>,
#Function<0.112984571/1 in Plug.Session.before_send/2>,
#Function<1.125774924/1 in Plug.Logger.call/2>], body_params: %{},
cookies: %{"_my_app_key" => "SFMyNTY.g3QAAAABbQAAAA1waG9lbml4X2ZsYXNodAAAAAFtAAAABGluZm9tAAAAGlJvbGUgZGVsZXRlZCBzdWNjZXNzZnVsbHku.x1KW5_8UKbMmKGRtuWO4Htx5WV37QAI3nYqleFSdT80"},
halted: false, host: "foo.localhost", method: "DELETE", owner: #PID<0.617.0>,
params: %{"id" => "238"}, path_info: ["admin", "roles", "238"],
path_params: %{"id" => "238"}, peer: {{127, 0, 0, 1}, 111317}, port: 80,
private: %{MyAppWeb.Router => {[],
%{MyAppWeb.Plug.API.Version => ["api"]}},
:guardian_default_claims => %{"aud" => "my_app", "exp" => 1530883668,
"iat" => 1528464468, "iss" => "my_app",
"jti" => "a6a55bdf-d35a-4b52-948c-128dbc286ef6", "nbf" => 1528464467,
"sub" => "1453", "typ" => "access"},
:guardian_default_resource => %MyApp.Accounts.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
email: "email_8866@example.com", id: 1453, image: "avatar.jpg",
inserted_at: ~N[2018-06-08 13:27:48.545323], name: "Elmer J. Fudd 8866",
uid: "8866", updated_at: ~N[2018-06-08 13:27:48.545340]},
:guardian_default_token => "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJvYnJhbWF4IiwiZXhwIjoxNTMwODgzNjY4LCJpYXQiOjE1Mjg0NjQ0NjgsImlzcyI6Im9icmFtYXgiLCJqdGkiOiJhNmE1NWJkZi1kMzVhLTRiNTItOTQ4Yy0xMjhkYmMyODZlZjYiLCJuYmYiOjE1Mjg0NjQ0NjcsInN1YiI6IjE0NTMiLCJ0eXAiOiJhY2Nlc3MifQ.ZW0vcNyRTiM_tgM27njihrLWLx8Qqqh_vGyJZdnsnzKu99865YaN03VttTznzuybaBAg8NqrGeDsVsg3WZTsPQ",
:guardian_error_handler => MyAppWeb.Guardian.ErrorHandler,
:guardian_module => MyApp.Guardian, :phoenix_action => :delete,
:phoenix_controller => MyAppWeb.Telesales.Admin.RoleController,
:phoenix_endpoint => MyAppWeb.Endpoint,
:phoenix_flash => %{"info" => "Role deleted successfully."},
:phoenix_format => "html", :phoenix_layout => {MyAppWeb.LayoutView, :app},
:phoenix_pipelines => [:browser, :login_required],
:phoenix_recycled => false, :phoenix_router => MyAppWeb.Router,
:phoenix_view => MyAppWeb.Telesales.Admin.RoleView,
:plug_session => %{"phoenix_flash" => %{"info" => "Role deleted successfully."}},
:plug_session_fetch => :done, :plug_session_info => :write,
:plug_skip_csrf_protection => true}, query_params: %{}, query_string: "",
remote_ip: {127, 0, 0, 1}, req_cookies: %{}, req_headers: [],
request_path: "/admin/roles/238",
resp_body: "<html><body>You are being <a href=\"/admin/roles\">redirected</a>.</body></html>",
resp_cookies: %{"_my_app_key" => %{value: "SFMyNTY.g3QAAAABbQAAAA1waG9lbml4X2ZsYXNodAAAAAFtAAAABGluZm9tAAAAGlJvbGUgZGVsZXRlZCBzdWNjZXNzZnVsbHku.x1KW5_8UKbMmKGRtuWO4Htx5WV37QAI3nYqleFSdT80"}},
resp_headers: [{"set-cookie",
"_my_app_key=SFMyNTY.g3QAAAABbQAAAA1waG9lbml4X2ZsYXNodAAAAAFtAAAABGluZm9tAAAAGlJvbGUgZGVsZXRlZCBzdWNjZXNzZnVsbHku.x1KW5_8UKbMmKGRtuWO4Htx5WV37QAI3nYqleFSdT80; path=/; HttpOnly"},
{"content-type", "text/html; charset=utf-8"},
{"cache-control", "max-age=0, private, must-revalidate"},
{"x-frame-options", "SAMEORIGIN"}, {"x-xss-protection", "1; mode=block"},
{"x-content-type-options", "nosniff"}, {"x-download-options", "noopen"},
{"x-permitted-cross-domain-policies", "none"}, {"location", "/admin/roles"}],
scheme: :http, script_name: [],
secret_key_base: "CTLiPUrLFZE13qML+i7pPbZqkHJUgQC/+u/e96EdcqT4DlNOxMGCw4+vItUos3k2",
state: :sent, status: 302}
Here is my router:
defmodule MyAppWeb.Router do
use MyAppWeb, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :login_required do
plug MyAppWeb.Guardian.AuthPipeline
plug MyAppWeb.Plug.CurrentUser
end
forward "/api", MyAppWeb.Plug.API.Version
scope host: "foo.", alias: MyAppWeb.Telesales, as: :telesales do
pipe_through :browser
scope "/admin", Admin, as: :admin do
pipe_through :login_required
resources "/roles", RoleController, only: [:index, :delete]
end
scope "/" do
pipe_through :login_required
resources "/sessions", SessionController, only: [:show], singleton: true
end
delete "/auth/logout", SessionController, :delete
get "/auth/login", SessionController, :new
get "/auth/:provider/callback", SessionController, :callback
get "/auth/:provider", SessionController, :request
end
scope "/", MyAppWeb do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
end
# Other scopes may use custom stacks.
# scope "/api", MyAppWeb do
# pipe_through :api
# end
end