Multiple sessions in capybara

2019-06-02 10:19发布

问题:

Background

I want to test logging in as multiple users on my webapp, and I am using cucumber and capybara to do this. I found this link on how to handle multiple sessions, but unfortunately, it doesn't look like cucumber can find the in_session method that is defined. How can I access it?

Cucumber scenario

Given I go to teacher login in Steve's browser

When I enter "Steve" in the username field 
     And I enter "StevesPassword" in the password field 
     And I click login 
Then I should see "Steve Lastname" as the current user

When I go to teacher login in Lisa's browser
     And I enter "Lisa" in the username field 
     And I enter "LisasPassword" in the password field 
     And I click login 
Then I should see "Lisa Lastname" as the current user

Ruby code

#standard_definitions/switching_sessions.rb
When /^(.*) in (.*) browser$/ do |next_step, name|
    in_session(name) do
        step next_step
    end 
end

  #features/support/sessions.rb
  module Capybara
  module Driver
    module Sessions
      def set_session(id)
        Capybara.instance_variable_set("@session_pool", {
          "#{Capybara.current_driver}#{Capybara.app.object_id}" => $sessions[id]
        })
      end

      def in_session(id, &block)
        $sessions ||= {}
        $sessions[:default] ||= Capybara.current_session
        $sessions[id]       ||= Capybara::Session.new(Capybara.current_driver, Capybara.app)
        set_session(id)

        yield

        set_session(:default)
      end
    end
  end
end

Errors

When I run this, I get the following:

Scenario: multiple users                                  # features/Provebank/Provebank.feature:23
Given I go to teacher login in Steve's browser         # features/step_definitions/standard_definitions/switching_sessions.rb:5
  undefined method `in_session' for Capybara::Driver::Sessions:Module (NoMethodError)
  ./features/step_definitions/standard_definitions/switching_sessions.rb:8:in `/^(.*) in (.*) browser$/'
  features/test.feature:24:in `Given I go to teacher login in Steve's browser'

回答1:

As mentioned at the top of the article you linked "This is now included in the Capybara library." - except the method is named Capybara.using_session rather than in_session, so you don't need features/support/session.rb. Note that the way your test is written, and the code in the link you shared, only the steps ending in "in xxxx's browser" would actually occur in a different session, not the ones you have tabbed over under those lines. To make each of those groups of steps occur in their own sessions you would either need "in xxx's browser" on every line or instead use Capybara.session_name = <name> in a step which would then be used for future steps. If setting the session_name directly you may wish to reset it to :default in an After block if you want future scenarios to default to that session.

# only next_step will be executed in the alternate session
When /^(.) in (.*) browser$/ do |next_step, name|
  Capybara.using_session(name) do
     step next_step
  end 
end

# all future steps will be executed in the alternate session
# you probably want to reset this to :default in an After block
Given /^I switch to (.*) browser$/ do |name|
  Capybara.session_name = name
end


回答2:

If I understood your question correctly then one way of doing it is by renaming Capybara session to something like:

user1 = Capybara::Session.new(:selenium)
user1.visit "foo/bar"

user2 = Capybara::Session.new(:selenium)
user2.visit "bar/foo"
user1.click_on "Sign in"
user2.click_on "Log in"

etc.

Also look into the rack_session_access gem. Maybe that's what you're looking for?