Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Difficulty setting the session in tests #861

Closed
crismali opened this issue May 10, 2015 · 9 comments

Comments

Projects
None yet
5 participants
@crismali
Copy link
Contributor

commented May 10, 2015

I was trying to test an action that would clear the session, but I ran into a bit of trouble.

First I tried setting the session:

use MyApp.ConnCase

setup do
  conn = conn()
  {:ok, conn: conn}
end

test "DELETE /sign_out clears the session", %{conn: conn} do
  conn = conn
    |> put_session(:foo, "bar") # raises ** (ArgumentError) session not fetched, call fetch_session/2
    |> delete(session_path(conn, :delete))

  refute get_session(conn, :foo)
end

Next I followed the error to fetch_session:

test "DELETE /sign_out clears the session", %{conn: conn} do
  conn = conn
    |> fetch_session # raises ** (ArgumentError) cannot fetch session without a configured session plug
    |> put_session(:foo, "bar")
    |> delete(session_path(conn, :delete))

  refute get_session(conn, :foo)
end

I followed that error to configure_session:

test "DELETE /sign_out clears the session", %{conn: conn} do
  conn = conn
    |> configure_session(true) # raises ** (ArgumentError) session not fetched, call fetch_session/2
    |> fetch_session
    |> put_session(:foo, "bar")
    |> delete(session_path(conn, :delete))

  refute get_session(conn, :foo)
end

And I tried passing different arguments to configure_session:

test "DELETE /sign_out clears the session", %{conn: conn} do
  conn = conn
    |> configure_session(renew: true) # raises ** (ArgumentError) session not fetched, call fetch_session/2
    |> fetch_session
    |> put_session(:foo, "bar")
    |> delete(session_path(conn, :delete))

  refute get_session(conn, :foo)
end

test "DELETE /sign_out clears the session", %{conn: conn} do
  conn = conn
    |> configure_session(drop: true) # raises ** (ArgumentError) session not fetched, call fetch_session/2
    |> fetch_session
    |> put_session(:foo, "bar")
    |> delete(session_path(conn, :delete))

  refute get_session(conn, :foo)
end

Not sure, but it looks like there might be a chicken and the egg sort of problem here.

I'm not sure if this is more of a Phoenix issue or a Plug issue, but it seems to me that conn should come out ready to have arbitrary data added to the session.

There might also be no issue and I'm just missing something of course =)

Also, this is how I worked around it:

test "DELETE /sign_out clears the session", %{conn: conn} do
  create_user(@user_attrs)
  conn = conn
    |> post(session_path(conn, :create), @valid_params)
    |> delete(session_path(conn, :delete))

  refute get_session(conn, :foo)
end
@gjaldon

This comment has been minimized.

Copy link
Contributor

commented May 10, 2015

The generator should have generated a MyApp.ConnCase which imports test helpers from Phoenix.ConnTest. Try using MyApp.ConnCase in your tests and you can do

conn = get conn(), "/"
assert conn.resp_body =~ "Welcome!"

conn/0 in the above example comes from Phoenix.ConnTest and it does the set-up for you so that you have a conn struct that you can easily test.

You can look up some more at- http://hexdocs.pm/phoenix/Phoenix.ConnTest.html

@crismali

This comment has been minimized.

Copy link
Contributor Author

commented May 10, 2015

I am creating the conn via the MyApp.ConnCase helpers in my tests and am able to make assertions against the response body and the database. For some reason put_session raises as I described above when given a MyApp.ConnCase conn.

@gjaldon

This comment has been minimized.

Copy link
Contributor

commented May 10, 2015

Ah, I see! You will need to call one of the http_methods(preferrably get) on the conn struct before doing any session stuff. For example:

test "DELETE /sign_out clears the session", %{conn: conn} do
  conn = conn
    |> get("/") # <---- Added this line
    |> put_session(:foo, "bar") # raises ** (ArgumentError) session not fetched, call fetch_session/2
    |> delete(session_path(conn, :delete))

  refute get_session(conn, :foo)
end

Calling get/2 will lead to calling Endpoint.dispatch where it will go through each of the plugs you have plugged into your MyApp.Endpoint including Plug.Session by default. After that, session will be configured, fetched and you could call the session functions on conn without error.

@josevalim

This comment has been minimized.

Copy link
Member

commented May 10, 2015

Yes, you need to setup your connection somehow, be it by calling the endpoint or doing it manually. For doing it manually, you can check the examples in plug itself:

https://github.com/elixir-lang/plug/blob/master/test/plug/session/cookie_test.exs#L31-L35

@josevalim josevalim closed this May 10, 2015

@crismali

This comment has been minimized.

Copy link
Contributor Author

commented May 10, 2015

Cool, thanks all!

sionide21 referenced this issue in sionide21/tech_talks Dec 22, 2016

Require log in to manage videos
* Setup code in video_controller_test shows how to put a session on a
  test connection before making a request
@valo

This comment has been minimized.

Copy link

commented Apr 18, 2017

I just encountered this problem and it seems like a much better solution is to use https://hexdocs.pm/plug/Plug.Test.html#init_test_session/2 to init your session:

import Plug.Test

test "DELETE /sign_out clears the session", %{conn: conn} do
  conn = conn
    |> init_test_session(foo: "bar")
    |> delete(session_path(conn, :delete))

  refute get_session(conn, :foo)
end
@josevalim

This comment has been minimized.

Copy link
Member

commented Apr 18, 2017

@valo yes, init_test_session was added to Plug later. :D

@epinault

This comment has been minimized.

Copy link

commented Feb 6, 2018

would be nice to add an example in the Phx doc. Took me a while to find this

@josevalim

This comment has been minimized.

Copy link
Member

commented Feb 6, 2018

PR for better docs is always appreciated. Please do send one!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.