Testing flash.now in Rails
I know this is an old problem, but I was still not satisfied with the current way of testing flash.now messages. If you love writing test cases, I’m sure that you will bump into the problem of testing flash.now message in your controller.
We usually use flash.now to display a message for an immediately rendered page, meaning not redirected:
flash.now[:notice] = 'You gotta be kidding me!'
The :notice key-value pair will be cleared once the action has been performed, and when you perform your test, flash.now[:notice] will return null.
# flahs.now[:notice] returns nil assert_equal 'You gotta be kidding me!', flash.now[:notice] # or in rspec flash.now[:notice].should == 'You gotta be kidding me!'
So, what do we do now? The good news is Rails Wiki suggested two ways, which I’ll probably add the third way shortly after this:
First is to use assert_select:
assert_select "div.message", "You gotta be kidding me!"
The problem with assert_select, it needs to render your view, but often we just want to test the message without rendering the view, rendering view may throw errors especially if you are testing with mock objects.
The second way was suggested by Justin Gus, through his flashblack plugin, pretty nifty I thought, because it meets the objectives in which he stated:
- The solution should only have effect in tests. It should not implicitly weave its way into production behavior.
- I should be conscious when the behavior is in affect.
- It should require very little effort on my part to enable the feature
- It should be simple
Sample codes with flashback plugin:
flashback get :index assert_equal 'You gotta be kidding me!', flash.flashed[:notice]
But there’s one problem I was facing, I don’t like the call the extra flashback method.
So here is my attempt through a simple monkey patching of FlashNow and FlashHash class. The patch will store flash.now messages into flash[:now], which can be easily referred in your test codes, through flash.now_cache.
- Append this code snippet to your
/test/test_helper.rbfile or/spec/spec_helper.rbif you are using RSpec.
module ActionController module Flash class FlashNow def initialize(flash) @flash = flash @flash[:now_cache] = {} end def []=(k, v) @flash[k] = v @flash.discard(k) @flash[:now_cache][k] = v v end end class FlashHash def now_cache self[:now_cache] || {} end end end end - And now you can test flash.now mesages through:
# Unit Test assert_equal 'You gotta be kidding me!', flash.now_cache[:notice] # RSpec flash.now_cache[:notice].should == 'You gotta be kidding me!'
Would welcome suggestion to improve this further. Thanks, and hope it will be helpful to you.



