In an attempt to reduce the number of page visits with selenium, I wanted to call the visit method from a before :all
hook and run all my examples with a single page load. However, when I specify before :all
vs before :each
, the browser opens, but the url is never visited. Below is a simplified and contrived example...
describe 'foobar', :js => true do
before :all do
Capybara.default_wait_time = 10
obj = Factory(:obj)
visit obj_path(obj)
end
it 'should have foo' do
page.should have_content('foo')
end
it 'should have bar' do
page.should have_content('bar')
end
end
When I set it to before :each
, it works, but the page loads twice. Is this a limitation of Capybara?
Cause of problem
The second example doesn't work because because Capybara resets the session after each RSpec example; the page you visit
-ed in your before :all
block is no longer open at that point. This an explicit behavior of Capybara. It's in the capybara
gem, under /lib/capybara/rspec.rb
:
config.after do
if self.class.include?(Capybara::DSL)
Capybara.reset_sessions!
Capybara.use_default_driver
end
end
I Googled around for a couple of hours and found several others struggling with this, to no avail really.
I also found that a patch that would allow Capybara to be configured not to reset the session after each example has been proposed ... but Capybara creator jnicklas declined the pull request.
Solution
The quickest -- though perhaps not the best -- workable solution I've found (so far) is to monkey-patch Capybara thusly:
module Capybara
class << self
alias_method :old_reset_sessions!, :reset_sessions!
def reset_sessions!; end
end
end
This just makes reset_sessions!
do nothing when it gets called. Note: Beware of unintended side-effects! (You can always revert the alias_method
later on in your code if you need the default resetting behavior to happen again.)