From the results Google gives on this, it seems that about three people in the world are using integration tests in Rails, and two of them stopped programming in 2007.
My goal: to get at session data from within an integration test.
Bad news: I don’t know any way to do this without first calling a controller action from within your integration test.
Good news: I have example code on how to get at it after making a request.
def add_to_cart_integration_test
s = open_session
s.post url_for(:controller => 'shopping_cart', :action => :add_item, :item_id => 1)
s.session.data # a populated session hash
s.flash # your flash data
end
And there you have it. Here is a more detailed examples that may be of use, derived from working integration tests in our codebase:
open_session do |s|
item_1 = FactoryHelper::ItemFactory.create_sellable_item
add_item_to_cart(item_1, s)
user = Factory(:activated_user, {:password => USER_PASSWORD})
login_user(user, USER_PASSWORD, s)
s.post url_for(:controller => 'offers', :action => :cart_summary)
all_offers = s.assigns(:all_offers_by_booth)
assert_equal all_offers.size, 1
the_offer = all_offers.first
# Trial 1: Simulate dragging item out of cart
s.post url_for(:controller => 'lootbins', :action => :remove_from_lootbin_draggable, :item => item_1.id)
s.post url_for(:controller => 'offers', :action => :cart_summary)
all_offers = s.assigns(:all_offers_by_booth)
assert all_offers.empty?
assert !Offer.exists?(the_offer)
# Trial 2: Simulate removing item from cart on cart page
add_item_to_cart(item_1, s)
s.post url_for(:controller => 'offers', :action => :cart_summary)
all_offers = s.assigns(:all_offers_by_booth)
assert_equal all_offers.size, 1
the_offer = all_offers.first
s.put url_for(:controller => 'offers', :action => :remove_from_offer, :item_id => item_1.id, :id => the_offer.id)
s.post url_for(:controller => 'offers', :action => :cart_summary)
all_offers = s.assigns(:all_offers_by_booth)
assert all_offers.empty?
assert !Offer.exists?(the_offer)
end
And here are the helpers involved:
def add_item_to_cart(item, os)
items_in_bin = begin
lootbin = Lootbin.new(os.session.data) # equivalent to ApplicationController#my_lootbin
lootbin.offer_items.size
rescue
0
end
os.post url_for(:controller => 'lootbins', :action => :add_to_lootbin_draggable, :item => item[:id])
lootbin = Lootbin.new(os.session.data) # equivalent to ApplicationController#my_lootbin
assert lootbin
assert lootbin.has_items?
assert_equal lootbin.offer_items.size, items_in_bin+1
end
def login_user(user, password, integration_session)
integration_session.https!
integration_session.post url_for(:controller => 'sessions', :action => :create, :username => user.user_name, :password => password)
assert_equal integration_session.session.data[:user_id], user.id
end
It’s funny that (a) I had to do a google advanced search, filtering on date to the last year to find any posts about integration testing that were relevant to modern versions of rails, and then (b) that the #1 result was yours, Bill!
Unfortunately my particular issue is still a mystery. The initial s.post works, and I can confirm that the results of the post are fine, but then if I do a subsequent s.post, my controller acts as if the session is gone! The user I’d logged in in the first post, is gone on the second one.
The search continues… 🙁
I think you might need to use the open_session block? I’ve updated the post with a more detailed example that may be of use to you?
@Tom Lianza
I just ran into the same problem with Rails 3.0.4 where each request had a new session. It turned out to be due to an incompatibility between session stores other than :cookie_store (e.g. :active_record_store) and the way the integration testing works.
Try adding a config line to your test.rb to use the cookie store:
config.session_store(:cookie_store)
That fixed it for us – probably worthy of a Rails ticket as well (if I get a chance to do so this weekend), but might be a “won’t fix”, considering the seeming dearth of people using integration testing.