Как я могу переключаться между двумя кадрами с Capybara

Я пытаюсь сделать что-то внутри 2 кадров, но ошибка возникает каждый раз, когда я пытаюсь переключаться между кадрами. Например:

# encoding: utf-8

require "capybara/dsl"

Capybara.run_server = false
Capybara.current_driver = :selenium
Capybara.app_host = 'https://hb.posted.co.rs/posted'

class Account
  include Capybara::DSL

  def check_balance
    visit('/')
    page.driver.browser.switch_to.frame 'main'
    fill_in 'korisnik', :with => 'foo'
    fill_in 'lozinka', :with => 'bar'
    click_button 'Potvrda unosa'

    page.driver.browser.switch_to.frame 'header'
    click_on 'Stanje' 
  end
end

account = Account.new
account.check_balance

Ошибка:

[удаленный сервер] Файл:///tmp/webdriver-profile20120810-9163-xy6dtm/extensions/[email protected]/components/driver_component.js: 6638: в `unknown ': невозможно найти фрейм: main (Селен:: WebDriver:: Error:: NoSuchFrameError)

В чем проблема? Может, я здесь что-то не так?

Если я меняю порядок переключения кадров, попробуйте сначала переключиться на "заголовок", а затем переключитесь на "основной" кадр, а затем повторите ту же ошибку, за исключением того, что в нем указано, что на этот раз нет "основного" кадра:

# encoding: utf-8

require "capybara/dsl"

Capybara.run_server = false
Capybara.current_driver = :selenium
Capybara.app_host = 'https://hb.posted.co.rs/posted'

class Account
  include Capybara::DSL

  def check_balance
    visit('/')
    page.driver.browser.switch_to.frame 'header'
    click_on 'Stanje' 

    page.driver.browser.switch_to.frame 'main'
    fill_in 'korisnik', :with => 'foo'
    fill_in 'lozinka', :with => 'bar'
    click_button 'Potvrda unosa'
  end
end

account = Account.new
account.check_balance

Ошибка:

[удаленный сервер] Файл:///tmp/webdriver-profile20120810-9247-w3o5hj/extensions/[email protected]/components/driver_component.js: 6638: в `unknown ': невозможно найти фрейм: main (Селен:: WebDriver:: Error:: NoSuchFrameError)

Ответы

Ответ 1

Проблема

Проблема заключается в том, что когда вы выполняете page.driver.browser.switch_to.frame, он переключает контекст страницы в фрейм. Все действия против страницы теперь фактически против фрейма. Поэтому, когда вы переключаете фреймы во второй раз, вы на самом деле говорите, что находите кадр заголовка внутри основного фона (вместо того, что я предполагаю, вы хотите, кадр заголовка на главной странице).

Решение - Capybara inside_frame (рекомендуется):

При работе внутри рамки вы должны использовать метод Capybara within_frame. Вы бы хотели:

  def check_balance
    visit('/')

    within_frame('main'){
      fill_in 'korisnik', :with => 'foo'
      fill_in 'lozinka', :with => 'bar'
      click_button 'Potvrda unosa'
    }

    within_frame('header'){
      click_on 'Stanje' 
    }
  end

Решение - Селен switch_to:

Если вы хотите самостоятельно управлять кадром (т.е. не использовать встроенный метод Capybara), вы можете переключить контекст страницы обратно в браузер, а затем во второй кадр. Это будет выглядеть следующим образом. Хотя я бы предложил использовать встроенный метод Capybara.

  def check_balance
    visit('/')
    page.driver.browser.switch_to.frame 'header'
    click_on 'Stanje' 

    #Switch page context back to the main browser
    page.driver.browser.switch_to.default_content

    page.driver.browser.switch_to.frame 'main'
    fill_in 'korisnik', :with => 'foo'
    fill_in 'lozinka', :with => 'bar'
    click_button 'Potvrda unosa'
  end

Ответ 2

Я нашел решение. in_frame работает как ожидалось:

# encoding: utf-8

require "capybara/dsl"

Capybara.run_server = false
Capybara.current_driver = :selenium
Capybara.app_host = 'https://hb.posted.co.rs/posted'
class Account
  include Capybara::DSL
  def check_balance
    visit('/')

    within_frame 'main' do
      fill_in 'korisnik', :with => 'foo'
      fill_in 'lozinka', :with => 'bar'
      click_button 'Potvrda unosa'
    end

    within_frame 'header' do
      click_on 'Stanje'
    end
  end
end

account = Account.new
account.check_balance

Я нашел исходный код для inside_frame в файле https://github.com/jnicklas/capybara/blob/master/lib/capybara/selenium/driver.rb. начиная с строки 81.

EDIT: В то время как я написал этот ответ, @JustinKo ответил на вопрос, поэтому оба ответа верны, но +1 и принятый для него ответ.