I am not sure how to check flash messages using functional tests. My problem has something to do with redirect_to because my test for flash[:error] is running. This is what my create action looks like:
def create @user = User.new(params[:user]) if @user.save redirect_to @user, flash: { success: "Welcome!" } else flash.now[:error] = "Signup failed:" render 'new' end end
I have a passing test for flash[:error] , which 1) checks the value of flash[:error] , 2) checks the page for the flash div and 3) receives a new page and checks that the flash message has been cleared. I tried to do a similar test for flash[:success] , but it does not work when I try to find the div on the page. Here is a failed test:
should "show flash[:success] message" do post :create, user: { name: "valid user", password: "userpw", password_confirmation: "userpw", email: "a@b.com" } assert_redirected_to user_path(assigns(:user)), "user isn't being redirected to their page after registration" assert_equal flash[:success], "Welcome!", "flash[:success] isn't being set properly" assert_select "div.alert-success", flash[:success] get :new assert flash.empty?, "there shouldn't be any flash messages left after getting new page" end
When I check this manually in the browser, it behaves as expected, but I'm not sure how to write tests to reflect this. The first two statements pass (therefore, the test recognizes that it is being redirected correctly and that flash[:success] set to "Welcome!" ). Based on this, I would think that the assert_select operator assert_select be able to find the div, but if this error message fails:
Expected at least 1 element matching "div.alert-success", found 0.
So, I tried adding puts @response.body immediately before the assert_select statement that printed this:
<html><body>You are being <a href="http://test.host/users/3">redirected</a>.</body></html>
This explains why he couldn’t find the flash file, but I’m not sure how to “finish” the redirection so that it displays the correct representation using the flash div. If I add a get statement immediately before the assert_select , the test passes because @response.body now has a flash div. However, this does not seem to be an effective test, because it does not reflect the behavior of my application - the user does not need to make a new request to see the flash message.
It also does not guarantee that the flash message appears on the correct page. If I use the get :new operator, the assertion still passes, which means that the flash message will be present in the users#new view. Even if I use
get :show, id: assigns(:user).id
to make sure the flash message is displayed on the correct page, it still seems wrong, because 1) now it is a success response instead of a redirect response, and 2) it still does not explain why I need to manually request ANY page to find flash drive - according to docs , "Flash is a special part of the session that is cleared with every request. "
In any case, is there a way to check if the flash message is displayed correctly after redirecting?