1
0
Fork 0
mirror of https://github.com/teamcapybara/capybara.git synced 2022-11-09 12:08:07 -05:00

Merge remote branch 'denro/evaluate_script'

Conflicts:
	lib/capybara.rb
	lib/capybara/driver/selenium_driver.rb
	lib/capybara/dsl.rb
	spec/session/culerity_session_spec.rb
	spec/session/selenium_session_spec.rb
	spec/session_spec.rb
This commit is contained in:
Jonas Nicklas 2009-12-12 21:56:32 +01:00
commit d183409d19
14 changed files with 134 additions and 84 deletions

View file

@ -119,6 +119,10 @@ Querying:
find_button
field_labeled
Scripting:
evaluate_script Returns the value of the executed javascript (only works on javascript supported drivers)
Debugging:
save_and_open_page
@ -158,7 +162,7 @@ For ultimate control, you can instantiate and use a session manually.
Capybara does not try to guess what kind of selector you are going to give it,
if you want to use CSS with your 'within' declarations for example, you'll need
to do:
within(:css, 'ul li') { ... }
Alternatively you can set the default selector to CSS, which may help if you are
@ -233,4 +237,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -6,6 +6,7 @@ module Capybara
class CapybaraError < StandardError; end
class DriverNotFoundError < CapybaraError; end
class ElementNotFound < CapybaraError; end
class NotSupportedByDriverError < CapybaraError; end
class << self
attr_accessor :debug, :asset_root
@ -14,7 +15,7 @@ module Capybara
def default_selector
@default_selector ||= :xpath
end
def log(message)
puts "[capybara] #{message}" if debug
true

View file

@ -5,7 +5,7 @@ class Capybara::Driver::Culerity < Capybara::Driver::Base
def text
node.text
end
def [](name)
value = if name.to_sym == :class
node.class_name
@ -18,28 +18,28 @@ class Capybara::Driver::Culerity < Capybara::Driver::Base
def set(value)
node.set(value)
end
def select(option)
node.select(option)
end
def click
node.click
end
def drag_to(element)
node.fire_event('mousedown')
element.node.fire_event('mousemove')
element.node.fire_event('mouseup')
end
def tag_name
# FIXME: this might be the dumbest way ever of getting the tag name
# there has to be something better...
node.to_xml[/^\s*<([a-z0-9\-\:]+)/, 1]
end
end
attr_reader :app, :rack_server
def self.server
@ -57,27 +57,31 @@ class Capybara::Driver::Culerity < Capybara::Driver::Base
@rack_server = Capybara::Server.new(@app)
@rack_server.boot
end
def visit(path)
browser.goto(url(path))
end
def body
browser.html
end
def find(selector)
browser.elements_by_xpath(selector).map { |node| Node.new(self, node) }
end
def wait?; true; end
def evaluate_script(script)
browser.execute_script "#{script}"
end
private
def url(path)
rack_server.url(path)
end
def browser
unless @_browser
@_browser = ::Culerity::RemoteBrowserProxy.new self.class.server, {:browser => :firefox, :log_level => :off}

View file

@ -86,6 +86,10 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
def wait?; true; end
def evaluate_script(script)
driver.execute_script "return #{script}"
end
private
def url(path)

View file

@ -12,7 +12,7 @@ module Capybara
@current_driver || default_driver
end
alias_method :mode, :current_driver
def javascript_driver
@javascript_driver || :selenium
end
@ -24,11 +24,11 @@ module Capybara
def current_session
session_pool["#{current_driver}#{app.object_id}"] ||= Capybara::Session.new(current_driver, app)
end
def current_session?
session_pool.has_key?("#{current_driver}#{app.object_id}")
end
def reset_sessions!
@session_pool = nil
end
@ -50,7 +50,7 @@ module Capybara
:visit, :body, :click_link, :click_button, :fill_in, :choose, :has_xpath?, :has_css?,
:check, :uncheck, :attach_file, :select, :has_content?, :within, :within_fieldset,
:within_table, :save_and_open_page, :find, :find_field, :find_link, :find_button,
:field_labeled, :all, :wait_for
:field_labeled, :all, :wait_for, :evaluate_script
]
SESSION_METHODS.each do |method|
class_eval <<-RUBY, __FILE__, __LINE__+1

View file

@ -9,11 +9,11 @@ class Capybara::Node
def text
raise "Not implemented"
end
def [](name)
raise "Not implemented"
end
def value
self[:value]
end
@ -21,7 +21,7 @@ class Capybara::Node
def set(value)
raise "Not implemented"
end
def select(option)
raise "Not implemented"
end
@ -29,12 +29,12 @@ class Capybara::Node
def click
raise "Not implemented"
end
def drag_to(element)
raise "Not implemented"
end
def tag_name
raise "Not implemented"
end
end
end

View file

@ -128,7 +128,7 @@ module Capybara
driver.find(path)
end.flatten
end
def find(locator)
all(locator).first
end
@ -156,6 +156,14 @@ module Capybara
find(XPath.button(locator))
end
def evaluate_script(script)
begin
driver.evaluate_script(script)
rescue NoMethodError
raise NotSupportedByDriverError
end
end
private
def css_to_xpath(css)

View file

@ -4,7 +4,7 @@ describe Capybara::Driver::Selenium do
before do
@driver = Capybara::Driver::Selenium.new(TestApp)
end
it_should_behave_like "driver"
it_should_behave_like "driver with javascript support"
end

View file

@ -37,7 +37,7 @@ shared_examples_for 'driver' do
@driver.find('//a')[0].text.should == 'labore'
@driver.find('//a')[1].text.should == 'ullamco'
end
it "should extract node attributes" do
@driver.find('//a')[0][:href].should == '/with_simple_html'
@driver.find('//a')[0][:class].should == 'simple'
@ -51,7 +51,7 @@ shared_examples_for 'driver' do
@driver.find('//input').first.set('gorilla')
@driver.find('//input').first.value.should == 'gorilla'
end
it "should extract node tag name" do
@driver.find('//a')[0].tag_name.should == 'a'
@driver.find('//a')[1].tag_name.should == 'a'
@ -63,20 +63,27 @@ shared_examples_for 'driver' do
end
shared_examples_for "driver with javascript support" do
before { @driver.visit('/with_js') }
describe '#find' do
it "should find dynamically changed nodes" do
@driver.visit('/with_js')
@driver.find('//p').first.text.should == 'I changed it'
end
end
describe '#drag_to' do
it "should drag and drop an object" do
@driver.visit('/with_js')
draggable = @driver.find('//div[@id="drag"]').first
droppable = @driver.find('//div[@id="drop"]').first
draggable.drag_to(droppable)
@driver.find('//div[contains(., "Dropped!")]').should_not be_nil
end
end
describe "#evaluate_script" do
it "should return the value of the executed script" do
@driver.evaluate_script('1+1').should == 2
end
end
end

View file

@ -36,7 +36,7 @@ describe Capybara do
Capybara.current_driver.should == :culerity
end
end
describe '#javascript_driver' do
it "should default to selenium" do
Capybara.javascript_driver.should == :selenium
@ -98,7 +98,7 @@ describe Capybara do
Capybara.current_session.app.should == Capybara.app
end
end
describe '.reset_sessions!' do
it "should clear any persisted sessions" do
object_id = Capybara.current_session.object_id
@ -114,6 +114,7 @@ describe Capybara do
end
it_should_behave_like "session"
it_should_behave_like "session without javascript support"
it "should be possible to include it in another class" do
klass = Class.new do
@ -124,7 +125,7 @@ describe Capybara do
foo.click_link('ullamco')
foo.body.should include('Another World')
end
it "should provide a 'page' shortcut for more expressive tests" do
klass = Class.new do
include Capybara

View file

@ -5,19 +5,19 @@ describe Capybara::Session do
before do
@session = Capybara::Session.new(:culerity, TestApp)
end
describe '#driver' do
it "should be a rack test driver" do
@session.driver.should be_an_instance_of(Capybara::Driver::Culerity)
end
end
describe '#mode' do
it "should remember the mode" do
@session.mode.should == :culerity
end
end
it_should_behave_like "session"
it_should_behave_like "session with javascript support"
end

View file

@ -5,19 +5,20 @@ describe Capybara::Session do
before do
@session = Capybara::Session.new(:rack_test, TestApp)
end
describe '#driver' do
it "should be a rack test driver" do
@session.driver.should be_an_instance_of(Capybara::Driver::RackTest)
end
end
describe '#mode' do
it "should remember the mode" do
@session.mode.should == :rack_test
end
end
it_should_behave_like "session"
it_should_behave_like "session without javascript support"
end
end

View file

@ -5,19 +5,19 @@ describe Capybara::Session do
before do
@session = Capybara::Session.new(:selenium, TestApp)
end
describe '#driver' do
it "should be a rack test driver" do
it "should be a selenium driver" do
@session.driver.should be_an_instance_of(Capybara::Driver::Selenium)
end
end
describe '#mode' do
it "should remember the mode" do
@session.mode.should == :selenium
end
end
it_should_behave_like "session"
it_should_behave_like "session with javascript support"
end

View file

@ -185,7 +185,7 @@ shared_examples_for "session" do
end.should raise_error(Capybara::ElementNotFound)
end
end
it "should serialize and send GET forms" do
@session.visit('/form')
@session.click_button('med')
@ -272,7 +272,7 @@ shared_examples_for "session" do
@session.click_button('awesome')
extract_results(@session)['gender'].should == 'both'
end
context "with a locator that doesn't exist" do
it "should raise an error" do
running { @session.choose('does not exist') }.should raise_error(Capybara::ElementNotFound)
@ -296,7 +296,7 @@ shared_examples_for "session" do
@session.click_button('awesome')
extract_results(@session)['pets'].should include('dog', 'cat', 'hamster')
end
context "with a locator that doesn't exist" do
it "should raise an error" do
running { @session.check('does not exist') }.should raise_error(Capybara::ElementNotFound)
@ -322,7 +322,7 @@ shared_examples_for "session" do
extract_results(@session)['pets'].should include('dog')
extract_results(@session)['pets'].should_not include('hamster')
end
context "with a locator that doesn't exist" do
it "should raise an error" do
running { @session.uncheck('does not exist') }.should raise_error(Capybara::ElementNotFound)
@ -346,7 +346,7 @@ shared_examples_for "session" do
@session.click_button('awesome')
extract_results(@session)['locale'].should == 'fi'
end
context "with a locator that doesn't exist" do
it "should raise an error" do
running { @session.select('foo', :from => 'does not exist') }.should raise_error(Capybara::ElementNotFound)
@ -400,7 +400,7 @@ shared_examples_for "session" do
@session.should_not have_xpath("//p//a[@id='doesnotexist']")
@session.should_not have_xpath("//p[contains(.,'thisstringisnotonpage')]")
end
it "should respect scopes" do
@session.within "//p[@id='first']" do
@session.should have_xpath("//a[@id='foo']")
@ -426,20 +426,20 @@ shared_examples_for "session" do
@session.should_not have_xpath("//p//a[@id='doesnotexist']", :count => 1)
end
end
context "with text" do
it "should discard all matches where the given string is not contained" do
@session.should have_xpath("//p//a", :text => "Redirect", :count => 1)
@session.should_not have_xpath("//p", :text => "Doesnotexist")
end
it "should discard all matches where the given regexp is not matched" do
@session.should have_xpath("//p//a", :text => /re[dab]i/i, :count => 1)
@session.should_not have_xpath("//p//a", :text => /Red$/)
end
end
end
describe '#has_css?' do
before do
@session.visit('/with_html')
@ -455,7 +455,7 @@ shared_examples_for "session" do
@session.should_not have_css("p a#doesnotexist")
@session.should_not have_css("p.nosuchclass")
end
it "should respect scopes" do
@session.within "//p[@id='first']" do
@session.should have_css("a#foo")
@ -479,13 +479,13 @@ shared_examples_for "session" do
@session.should_not have_css("p a.doesnotexist", :count => 1)
end
end
context "with text" do
it "should discard all matches where the given string is not contained" do
@session.should have_css("p a", :text => "Redirect", :count => 1)
@session.should_not have_css("p a", :text => "Doesnotexist")
end
it "should discard all matches where the given regexp is not matched" do
@session.should have_css("p a", :text => /re[dab]i/i, :count => 1)
@session.should_not have_css("p a", :text => /Red$/)
@ -533,14 +533,14 @@ shared_examples_for "session" do
@session.click_button('Upload')
end
end
context "with a locator that doesn't exist" do
it "should raise an error" do
running { @session.attach_file('does not exist', 'foo.txt') }.should raise_error(Capybara::ElementNotFound)
end
end
end
describe '#find_field' do
before do
@session.visit('/form')
@ -551,17 +551,17 @@ shared_examples_for "session" do
@session.find_field('form_description').text.should == 'Descriptive text goes here'
@session.find_field('Region')[:name].should == 'form[region]'
end
it "should be nil if the field doesn't exist" do
@session.find_field('Does not exist').should be_nil
end
it "should be aliased as 'field_labeled' for webrat compatibility" do
@session.field_labeled('Dog').value.should == 'dog'
@session.field_labeled('Does not exist').should be_nil
end
end
describe '#find_link' do
before do
@session.visit('/with_html')
@ -571,12 +571,12 @@ shared_examples_for "session" do
@session.find_link('foo').text.should == "ullamco"
@session.find_link('labore')[:href].should == "/with_simple_html"
end
it "should return nil if the field doesn't exist" do
@session.find_link('Does not exist').should be_nil
end
end
describe '#find_button' do
before do
@session.visit('/form')
@ -586,7 +586,7 @@ shared_examples_for "session" do
@session.find_button('med')[:id].should == "mediocre"
@session.find_button('crap321').value.should == "crappy"
end
it "should return nil if the field doesn't exist" do
@session.find_button('Does not exist').should be_nil
end
@ -602,18 +602,18 @@ shared_examples_for "session" do
@session.all('//h1').first.text.should == 'This is a test'
@session.all("//input[@id='test_field']").first[:value].should == 'monkey'
end
it "should return an empty array when nothing was found" do
@session.all('//div').should be_empty
end
it "should accept an XPath instance" do
@session.visit('/form')
@xpath = Capybara::XPath.text_field('Name')
@result = @session.all(@xpath)
@result.map(&:value).should include('Smith', 'John', 'John Smith')
end
context "within a scope" do
before do
@session.visit('/with_scope')
@ -622,7 +622,7 @@ shared_examples_for "session" do
it "should find any element using the given locator" do
@session.within(:xpath, "//div[@id='for_bar']") do
@session.all('//li').should have(2).elements
end
end
end
end
end
@ -636,17 +636,17 @@ shared_examples_for "session" do
@session.find('//h1').text.should == 'This is a test'
@session.find("//input[@id='test_field']")[:value].should == 'monkey'
end
it "should return nil when nothing was found" do
@session.find('//div').should be_nil
end
it "should accept an XPath instance and respect the order of paths" do
@session.visit('/form')
@xpath = Capybara::XPath.text_field('Name')
@session.find(@xpath).value.should == 'John Smith'
end
context "within a scope" do
before do
@session.visit('/with_scope')
@ -655,7 +655,7 @@ shared_examples_for "session" do
it "should find the first element using the given locator" do
@session.within(:xpath, "//div[@id='for_bar']") do
@session.find('//li').text.should =~ /With Simple HTML/
end
end
end
end
end
@ -697,7 +697,7 @@ shared_examples_for "session" do
before do
@session.visit('/with_scope')
end
context "with CSS selector" do
it "should click links in the given scope" do
@session.within(:css, "ul li[contains('With Simple HTML')]") do
@ -706,7 +706,7 @@ shared_examples_for "session" do
@session.body.should include('<h1>Bar</h1>')
end
end
context "with XPath selector" do
it "should click links in the given scope" do
@session.within(:xpath, "//li[contains(.,'With Simple HTML')]") do
@ -715,7 +715,7 @@ shared_examples_for "session" do
@session.body.should include('<h1>Bar</h1>')
end
end
context "with the default selector" do
it "should use XPath" do
@session.within("//li[contains(., 'With Simple HTML')]") do
@ -724,12 +724,12 @@ shared_examples_for "session" do
@session.body.should include('<h1>Bar</h1>')
end
end
context "with the default selector set to CSS" do
after do
Capybara.default_selector = :xpath
end
it "should use CSS" do
Capybara.default_selector = :css
@session.within("ul li[contains('With Simple HTML')]") do
@ -738,7 +738,7 @@ shared_examples_for "session" do
@session.body.should include('<h1>Bar</h1>')
end
end
context "with click_link" do
it "should click links in the given scope" do
@session.within("//li[contains(.,'With Simple HTML')]") do
@ -766,7 +766,7 @@ shared_examples_for "session" do
@session.body.should include('Hello world')
end
end
it "should raise an error if the scope is not found on the page" do
running {
@session.within("//div[@id='doesnotexist']") do
@ -790,12 +790,12 @@ shared_examples_for "session" do
end
end
end
describe '#within_fieldset' do
before do
@session.visit('/fieldsets')
end
it "should restrict scope to a fieldset given by id" do
@session.within_fieldset("villain_fieldset") do
@session.fill_in("Name", :with => 'Goldfinger')
@ -803,7 +803,7 @@ shared_examples_for "session" do
end
extract_results(@session)['villain_name'].should == 'Goldfinger'
end
it "should restrict scope to a fieldset given by legend" do
@session.within_fieldset("Villain") do
@session.fill_in("Name", :with => 'Goldfinger')
@ -812,12 +812,12 @@ shared_examples_for "session" do
extract_results(@session)['villain_name'].should == 'Goldfinger'
end
end
describe '#within_table' do
before do
@session.visit('/tables')
end
it "should restrict scope to a fieldset given by id" do
@session.within_table("girl_table") do
@session.fill_in("Name", :with => 'Christmas')
@ -825,7 +825,7 @@ shared_examples_for "session" do
end
extract_results(@session)['girl_name'].should == 'Christmas'
end
it "should restrict scope to a fieldset given by legend" do
@session.within_table("Villain") do
@session.fill_in("Name", :with => 'Quantum')
@ -834,9 +834,28 @@ shared_examples_for "session" do
extract_results(@session)['villain_name'].should == 'Quantum'
end
end
end
shared_examples_for "session without javascript support" do
describe "#evaluate_script" do
before{ @session.visit('/with_js') }
it "should raise an error" do
running {
@session.evaluate_script("1+5")
}.should raise_error(Capybara::NotSupportedByDriverError)
end
end
end
shared_examples_for "session with javascript support" do
describe "#evaluate_script" do
before{ @session.visit('/with_js') }
it "should return the evaluated script" do
@session.evaluate_script("1+3").should == 4
end
end
describe '#wait_for' do
it "should wait for asynchronous load" do
@session.visit('/with_js')
@ -880,3 +899,4 @@ describe Capybara::Session do
end
end
end