Как повторно использовать сеансы Capybara между тестами?

Я хочу продолжать использовать один и тот же сеанс, и я имею в виду сеанс Rails между различными тегами интеграции Test::Unit, которые используют Capybara. Объект Capybara::Session одинаковый во всех тестах, поскольку он повторно используется, но когда я обращаюсь к другой странице в другом тесте, я немедленно выхожу из системы.

Копаем я обнаружил, что capybara_session.driver.browser.manage.all_cookies очищается между одним тестом и следующим.

Любые идеи как? или почему? или как его избежать?

Попытка обойти это, я сохранил файл cookie в переменной класса и повторно добавил позже:

capybara_session.driver.browser.manage.add_cookie(@@cookie)

и, похоже, работает, файл cookie есть, но когда есть запрос, cookie заменяется на другой, поэтому он не имеет никакого эффекта.

Есть ли другой способ достижения этого?

Ответы

Ответ 2

Если вы пытаетесь объединить отдельные примеры в историю (стиль огурца, но без огурца), вы можете использовать драгоценный камень, называемый rspec-шагами, чтобы выполнить это. Например, обычно это не будет работать:

describe "logging in" do
  it "when I visit the sign-in page" do 
    visit "/login"
  end
  it "and I fill in my registration info and click submit" do
    fill_in :username, :with => 'Foo'
    fill_in :password, :with => 'foobar'
    click_on "Submit"
  end
  it "should show a successful login" do
    page.should have_content("Successfully logged in")
  end
end

Поскольку rspec откатывает все свои переменные экземпляра, сеансы, файлы cookie и т.д.

Если вы устанавливаете rspec-шаги (обратите внимание: в настоящее время несовместимо с rspec новее, чем 2.9), вы можете заменить "описать" на "шаги", а Rspec и capybara сохранит состояние между примерами, что позволит вам построить более длинную историю, например:

steps "logging in" do
  it "when I visit the sign-in page" #... etc.
  it "and I fill in" # ... etc.
  it "should show a successful" # ... etc.
end

Ответ 3

Вы можете предотвратить вызов @browser.manage.delete_all_cookies, который происходит между тестами путем обезглавливания метода Capybara::Selenium::Driver#reset!. Это не чистый способ сделать это, но он должен работать...

Добавьте следующий код в свой проект, чтобы он выполнялся после require 'capybara':

class Capybara::Selenium::Driver < Capybara::Driver::Base
  def reset!
    # Use instance variable directly so we avoid starting the browser just to reset the session
    if @browser
      begin
        #@browser.manage.delete_all_cookies <= cookie deletion is commented out!
      rescue Selenium::WebDriver::Error::UnhandledError => e
        # delete_all_cookies fails when we've previously gone
        # to about:blank, so we rescue this error and do nothing
        # instead.
      end
      @browser.navigate.to('about:blank')
    end
  end
end

Для интереса, оскорбительная строка видна в Capybara codebase здесь: https://github.com/jnicklas/capybara/blob/master/lib/capybara/selenium/driver.rb#L71

Ответ 4

Возможно, стоит опубликовать причину, по которой вам нужно такое поведение. Обычно, имея необходимость в обезьянном патче Capybara, является признаком того, что вы пытаетесь использовать его для чего-то, для чего он не предназначался. Часто можно реструктурировать тесты, так что вам не нужны файлы cookie, сохраненные в тестах интеграции.