Topic: flash cleared, or not cleared, it depends...

I have a login page and a sign-up page. I noticed that if I type the wrong username/password when I try to login, then I choose the sign-up link, my "Login unsuccessful" message shows up on the sign-up page, which is not what I wanted.

I wrote this integration test:

  def test_login_unsuccessful_message_should_not_appear
    post '/', :user => { :username => 'no user', :password => 'incorrect' }
    assert_response :success
    assert_equal "Login unsuccessful", flash[:message], %Q[No 'login unsuccessful' message means this test doesn't make sense.]
   
    get '/users/signup'
    assert_response :success
    assert_equal nil, flash[:message], %Q[Unexpected message at 'sign up' page.]
  end

This test passed, which surprised me, because it doesn't match what I see in the browser. Then I wrote this controller test:
  def test_login_unsuccessful_then_signup
    post :login, :user => { :username => "definitely wrong", :password => "even wronger" }
    assert_equal "Login unsuccessful", flash[:message]
   
    get :signup
    assert_equal nil, flash[:message], %Q[No need to display a message here.]
   
    assert_no_match /Login unsuccessful/, @response.body
  end

This test fails, but only after I check for the string "Login unsuccessful" in the response body. Here is how I learned that, in spite of the fact that the test claims there is no :message in the flash, my view thinks there is, and so displays the message.

Now I know why the defect is there: my login action doesn't redirect after populating the flash with the failure message, so when I click on the sign-up link, the flash isn't reset; but why do neither of these tests reflect this? Why do both tests insist the flash doesn't have a :message, when it clearly does?

If it helps, I'm displaying the message with an ApplicationHelper:

module ApplicationHelper
  def flash_if_message
    if flash[:message]
      %{  <br />
          <div class="messages">
            #{flash[:message]}
          </div>
      }
    end
  end
end

I wouldn't think that would matter, but it might. Also, I'm using WEBrick, in case this is some kind of caching issue. (How would I know?) On that note, clearing the browser cache didn't change the behavior, and of course, when I change the login action to redirect, the feature behaves the way I expect.

Any thoughts? This seems so simple. What am I missing?

Re: flash cleared, or not cleared, it depends...

I'm guessing this is a bug in how integration tests handle the flash message. I don't know the inner workings of it so it's hard to say what's the problem.

As for the solution, if you don't want to redirect after setting the flash, use flash.now instead:

flash.now[:message] = "foo"

Railscasts - Free Ruby on Rails Screencasts