Search code examples
ruby-on-railsunit-testingruby-on-rails-4testunit

Why isn't my delete_via_redirect test working in Rails?


I can't get my logout test to work, yet it works in the browser. I cannot see anything wrong.

  test "logout user" do
    chloe = login(:starrychloe, 'passpasspass')
    chloe.delete_via_redirect "/users/logout"
    chloe.assert_equal '/', chloe.path
    chloe.assert_equal "Logged out!", chloe.flash.notice, chloe.flash.to_a
    chloe.assert_select '.button' do |elem|
      puts elem
    end
    chloe.assert_select '.button', 'Login'

Here is the error. It still thinks it is logged in, even though the session was destroyed and the user_id is no longer in the session:

Started DELETE "/users/logout" for 127.0.0.1 at 2014-05-31 23:28:17 -0400
Processing by UsersController#logout as HTML
******************** {"session_id"=>"174289eb62bf8679db7f7b04e28c0822", "invalidLogin"=>0, "user_id"=>1, "flash"=>{"discard"=>["notice"], "flashes"=>{"notice"=>"Logged in! Last seen from 172.196.66.44."}}, "_csrf_token"=>"iKYW4LJvZU/1jrw7P6nnZho2ePms3uDde4EH/y5bRjM="}
******************** {"session_id"=>"7dbc9379256566a5bb642c91a9301501"}
Redirected to http://www.example.com:443/
Completed 302 Found in 2ms (ActiveRecord: 0.0ms)
Started GET "/" for 127.0.0.1 at 2014-05-31 23:28:17 -0400
Completed 200 OK in 8ms (Views: 6.8ms | ActiveRecord: 0.0ms)
<div class="button"><a href="/">All</a></div>
<div class="button"><a data-method="delete" href="/users/logout" rel="nofollow">Logout</a></div>
F

  1) Failure:
UserFlowsTest#test_logout_user [test/integration/user_flows_test.rb:43]:
<Login> expected but was
<All>..
Expected 0 to be >= 1.

1 runs, 0 assertions, 1 failures, 0 errors, 0 skips

Here is the controller method

  def logout
puts "******************** #{session.to_hash}"    
    reset_session
puts "******************** #{session.to_hash}"    
    redirect_to root_url, :notice => "Logged out!"

I recently changed it from method: :post to method: :delete. I also tried redirect_to :root but that didn't help.


Solution

  • Ok I found another bug in Rails. I added puts chloe.response.body and saw that it was printing the correct non-logged in page, but for some reason, assert_select was still using the page from before! I fixed the problem by creating a new HTML::Document element from the response.body and selecting on that text directly.

    puts chloe.response.body
    doc = HTML::Document.new chloe.response.body
    chloe.assert_select doc.root, '.button' do |elem|
      puts elem
    end
    chloe.assert_select doc.root, '.button', 'Login'
    

    Now it correctly lists the links that a new user would see

    <div class="button"><a href="/">All</a></div>
    <div class="button"><a data-no-turbolink="true" href="/users/login">Login</a></div>
    <div class="button"><a data-no-turbolink="true" href="/users/new">Register</a></div>
    

    Here is the issue: https://github.com/rails/rails/issues/15454