Reputation: 3085
I want to test controller's action and flash messages presence with rspec.
action:
def create
user = Users::User.find_by_email(params[:email])
if user
user.send_reset_password_instructions
flash[:success] = "Reset password instructions have been sent to #{user.email}."
else
flash[:alert] = "Can't find user with this email: #{params[:email]}"
end
redirect_to root_path
end
spec:
describe "#create" do
it "sends reset password instructions if user exists" do
post :create, email: "[email protected]"
expect(response).to redirect_to(root_path)
expect(flash[:success]).to be_present
end
...
But I've got an error:
Failure/Error: expect(flash[:success]).to be_present
expected `nil.present?` to return true, got false
Upvotes: 93
Views: 64922
Reputation: 7276
The another approach is to leave out the fact that a controller has flash messages and write an integration test instead. This way you increase chances that you will not need to alter the test once you decide to show that message using JavaScript or by some other way.
See also https://stackoverflow.com/a/13897912/2987689
Upvotes: 2
Reputation: 7524
The best way to test flash messages is provided by the shoulda gem.
Here are three examples:
expect(controller).to set_flash
expect(controller).to set_flash[:success]
expect(controller).to set_flash.now[:alert].to(/are not valid/)
Upvotes: 54
Reputation: 4516
If you are more interested in the content of the flash messages you can use this:
expect(flash[:success]).to match(/Reset password instructions have been sent to .*/)
or
expect(flash[:alert]).to match(/Can't find user with this email: .*/)
I would advise against checking for a specific message unless that message is critical and/or it does not change often.
Upvotes: 44
Reputation: 101
With: gem 'shoulda-matchers', '~> 3.1'
The .now
should be called directly on the set_flash
.
Using set_flash
with the now
qualifier and specifying now
after other qualifiers is no longer allowed.
You'll want to use now
immediately after set_flash
. For instance:
# Valid
should set_flash.now[:foo]
should set_flash.now[:foo].to('bar')
# Invalid
should set_flash[:foo].now
should set_flash[:foo].to('bar').now
Upvotes: 5
Reputation: 4143
You are testing for the presence of flash[:success]
, but in your controller you are using flash[:notice]
Upvotes: 78