diff --git a/lib/capybara.rb b/lib/capybara.rb index 41c9b5f73..02472957f 100644 --- a/lib/capybara.rb +++ b/lib/capybara.rb @@ -314,7 +314,7 @@ def using_wait_time(seconds) # @return [Capybara::Session] The currently used session # def current_session - specified_session || session_pool["#{current_driver}:#{session_name}:#{app.object_id}"] + specified_session || session_pool[build_session_key(session_name)] end ## @@ -407,6 +407,19 @@ def HTML(html) # rubocop:disable Naming/MethodName end end + ## + # + # Returns a list of session names that have been actively used. + # + # @return [Array] A list of session names + # + def touched_session_names + session_pool.keys.filter_map do |key| + session_name = key.split(':')[1].to_sym + session_name if key == build_session_key(session_name) && session_pool[key].touched? + end + end + def session_options config.session_options end @@ -417,6 +430,10 @@ def config @config ||= Capybara::Config.new end + def build_session_key(session_name) + "#{current_driver}:#{session_name}:#{app.object_id}" + end + def session_pool @session_pool ||= Hash.new do |hash, name| hash[name] = Capybara::Session.new(current_driver, app) diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb index 1451a91af..d72d3f61d 100644 --- a/lib/capybara/session.rb +++ b/lib/capybara/session.rb @@ -109,6 +109,17 @@ def driver end end + ## + # + # Returns true if the current session has been touched, indicating it has been actively used. + # This returns true after a `visit` action and false after `quit` or `reset!`. + # + # @return [Boolean] true if the session has been used, false otherwise + # + def touched? + @touched + end + ## # # Reset the session (i.e. remove cookies and navigate to blank page). diff --git a/spec/dsl_spec.rb b/spec/dsl_spec.rb index 02795b091..5ea506fed 100644 --- a/spec/dsl_spec.rb +++ b/spec/dsl_spec.rb @@ -257,6 +257,34 @@ class TestClass end end + describe '#touched_session_names' do + before do + Capybara.send(:session_pool).clear + end + + it 'returns available session names' do + Capybara.current_session.visit '/' + expect(Capybara.touched_session_names).to contain_exactly(:default) + + Capybara.using_session(:administrator) do + Capybara.current_session.visit '/' + end + expect(Capybara.touched_session_names).to contain_exactly(:default, :administrator) + end + + it "doesn't return unmatched app session names" do + old_app = Capybara.app + + Capybara.current_session.visit '/' + expect(Capybara.touched_session_names).to contain_exactly(:default) + + Capybara.app = Class.new(old_app) + expect(Capybara.touched_session_names).to be_empty + ensure + Capybara.app = old_app + end + end + describe '#session_name' do it 'should default to :default' do expect(Capybara.session_name).to eq(:default) diff --git a/spec/session_spec.rb b/spec/session_spec.rb index 0436d8b22..e97c7b944 100644 --- a/spec/session_spec.rb +++ b/spec/session_spec.rb @@ -17,6 +17,19 @@ end end + describe '#touched?' do + it 'returns state of modified session' do + session = described_class.new(:rack_test, TestApp) + expect(session.touched?).to eq(false) + + session.visit '/' + expect(session.touched?).to eq(true) + + session.reset! + expect(session.touched?).to eq(false) + end + end + context 'current_driver' do around do |example| orig_driver = Capybara.current_driver