I am trying do something inside 2 frames but error raises everytime when I try to switch between frames.
For example:
# 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
Error is:
[remote server]
file:///tmp/webdriver-profile20120810-9163-xy6dtm/extensions/fxdriver@googlecode.com/components/driver_component.js:6638:in
`unknown': Unable to locate frame: main
(Selenium::WebDriver::Error::NoSuchFrameError)
What is the problem? Maybe I am doing something wrong here?
If I change order of switching frames so try first to switch to 'header' then switch to 'main' frame then same error raises except that it says that this time there is no 'main' 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('/')
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
Error:
[remote server]
file:///tmp/webdriver-profile20120810-9247-w3o5hj/extensions/fxdriver@googlecode.com/components/driver_component.js:6638:in
`unknown': Unable to locate frame: main
(Selenium::WebDriver::Error::NoSuchFrameError)
Problem
The problem is that when you do page.driver.browser.switch_to.frame
, it switches the page's context to the frame. All actions against the page are now actually against the frame. So when you are switching frames the second time, you are actually saying find the 'header' frame inside the 'main' frame (rather than, what I assume you want, the 'header' frame inside the main page).
Solution - Capybara within_frame (recommended):
When working inside a frame, you should use Capybara's within_frame
method. You would want to do:
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
Solution - Selenium switch_to:
If you want to do the frame management yourself (ie not use Capybara's built-in method), you can switch the page's context back to the browser and then to the second frame. This would look like the following. Though I would suggest using the built-in Capybara method.
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
I've found solution. within_frame works as expected:
# 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
I've found source code for within_frame in file https://github.com/jnicklas/capybara/blob/master/lib/capybara/selenium/driver.rb. starting from line 81.
EDIT:
While I wrote this answer, @JustinKo answered question, so both answers are correct but +1 and accepted answer for him.