Capybara(Poltergeist)でiPhoneのfeatureテストを実装する


環境

rspec (3.5.0)
capybara (2.13.0)
poltergeist (1.14.0)

アプリケーション側でUA(UserAgent)を見てPCかスマホか判断してView切り替えをしているので、UA偽装する方針で対応していきます。

さっそく実装してみる(失敗例)

stackoverflowの記事を参考に、iPhoneのUAを偽装したdriverを登録し、metadataを使ってcurrent_driverを切り替える方法です。

Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app)
end

Capybara.register_driver :poltergeist_iphone do |app|
  driver = Capybara::Poltergeist::Driver.new(app)
  # iphoneのUAを偽装する
  driver.headers = { 'User-Agent' => 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A334 Safari/7534.48.3' }
  driver
end

Capybara.configure do |config|
  config.default_driver    = :poltergeist
  config.javascript_driver = :poltergeist
end

RSpec.configure do |config|
  config.before(type: :feature) do |example|
    if example.metadata[:mobile]
      # mobileの場合、iPhone偽装したpoltergeistを設定する
      Capybara.current_driver = :poltergeist_iphone
    end
  end
end

# spec/features/hoge_spec.rb ============
# pc用のfeatureテスト
feature 'hoge' do
  scenario 'hoge1' do
    ...
  end
end

# iphone用のfeatureテスト
feature 'fuga(iphone)', :mobile do
  scenario 'fuga1' do
    ...
  end
  scenario 'fuga2' do
    ...
  end
end

うまくいった!...と思ったら、むむむ

feature 'fuga(iphone)', :mobile do
  scenario 'fuga1' do
    ...
    # Capybara.current_driver => :poltergeist_iphone
    # page.driver.headers => {"User-Agent"=>"Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A334 Safari/7534.48.3"}
  end
  scenario 'fuga2' do
    ...
    # Capybara.current_driver => :poltergeist_iphone
    # page.driver.headers => {}
  end
end

二つ目以降のscenario(fuga2)でなぜかUAが初期化されてる。。

おそらく、

  • fuga1が終了したタイミングでpoltergeist_iphoneのheader情報がクリアされる
  • クリアされた状態のpoltergeist_iphoneを使ってfuga2に移行する

という感じなのかな..?

解決策

これだとぜんぜん使えないので、各scenarioでdriverを切り替えるのではなく、UAを毎回上書きする方法で対応。

Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app)
end

RSpec.configure do |config|
  config.before(type: :feature) do |example|
    if example.metadata[:mobile]
      # mobileの場合、iPhone偽装する
      Capybara.page.driver.headers = { 'User-Agent' => 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A334 Safari/7534.48.3' }
    end
  end
end

うまくいった

参考