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

Merge branch 'master' of github.com:jnicklas/capybara

This commit is contained in:
Jonas Nicklas and Nicklas Ramhöj 2011-02-08 16:06:14 +01:00
commit 2666951cac
29 changed files with 661 additions and 108 deletions

View file

@ -1,7 +1,7 @@
PATH
remote: .
specs:
capybara (0.4.1.rc)
capybara (0.4.1.1)
celerity (>= 0.7.9)
culerity (>= 0.2.4)
mime-types (>= 1.16)
@ -20,51 +20,67 @@ PATH
GEM
remote: http://rubygems.org/
specs:
celerity (0.8.2)
childprocess (0.1.4)
builder (3.0.0)
celerity (0.8.7)
childprocess (0.1.6)
ffi (~> 0.6.3)
configuration (1.1.0)
culerity (0.2.12)
configuration (1.2.0)
cucumber (0.10.0)
builder (>= 2.1.2)
diff-lcs (~> 1.1.2)
gherkin (~> 2.3.2)
json (~> 1.4.6)
term-ansicolor (~> 1.0.5)
culerity (0.2.15)
diff-lcs (1.1.2)
ffi (0.6.3)
rake (>= 0.8.7)
ffi (0.6.3-java)
fuubar (0.0.1)
progressbar (~> 0.9)
fuubar (0.0.3)
rspec (~> 2.0)
rspec-instafail (~> 0.1)
rspec-instafail (~> 0.1.4)
ruby-progressbar (~> 0.0.9)
gherkin (2.3.3)
json (~> 1.4.6)
gherkin (2.3.3-java)
json (~> 1.4.6)
json (1.4.6)
json (1.4.6-java)
json_pure (1.4.6)
launchy (0.3.7)
configuration (>= 0.0.5)
rake (>= 0.8.1)
mime-types (1.16)
nokogiri (1.4.3.1)
nokogiri (1.4.3.1-java)
nokogiri (1.4.4)
nokogiri (1.4.4-java)
weakling (>= 0.0.3)
progressbar (0.9.0)
rack (1.2.1)
rack-test (0.5.6)
rack-test (0.5.7)
rack (>= 1.0)
rake (0.8.7)
rspec (2.1.0)
rspec-core (~> 2.1.0)
rspec-expectations (~> 2.1.0)
rspec-mocks (~> 2.1.0)
rspec-core (2.1.0)
rspec-expectations (2.1.0)
rspec (2.4.0)
rspec-core (~> 2.4.0)
rspec-expectations (~> 2.4.0)
rspec-mocks (~> 2.4.0)
rspec-core (2.4.0)
rspec-expectations (2.4.0)
diff-lcs (~> 1.1.2)
rspec-instafail (0.1.3)
rspec-mocks (2.1.0)
rspec-instafail (0.1.5)
rspec-mocks (2.4.0)
ruby-progressbar (0.0.9)
rubyzip (0.9.4)
selenium-webdriver (0.0.29)
childprocess (>= 0.0.7)
selenium-webdriver (0.1.2)
childprocess (~> 0.1.5)
ffi (~> 0.6.3)
json_pure
rubyzip
sinatra (1.0)
rack (>= 1.0)
sinatra (1.1.2)
rack (~> 1.1)
tilt (~> 1.2)
term-ansicolor (1.0.5)
tilt (1.2.2)
weakling (0.0.4-java)
yard (0.6.1)
yard (0.6.4)
PLATFORMS
java
@ -74,6 +90,7 @@ DEPENDENCIES
bundler (~> 1.0)
capybara!
celerity (>= 0.7.9)
cucumber (>= 0.10)
culerity (>= 0.2.4)
fuubar (>= 0.0.1)
launchy (>= 0.3.5)

View file

@ -8,7 +8,7 @@ Release date:
# Version 0.4.1
Release date:
Release date: 2011-01-21
### Added
@ -40,6 +40,8 @@ Release date:
* Fix problems with multiple file inputs [Philip Arndt]
* Submit multipart forms as multipart under rack-test even if they contain no files [Ryan Kinderman]
* Matchers like has_select? and has_checked_field? now work with dynamically changed values [John Firebaugh]
* Preserve order of rack params [Joel Chippindale]
* RackTest#reset! is more thorough [Joel Chippindale]
# Version 0.4.0

View file

@ -83,14 +83,14 @@ There are also explicit <tt>@selenium</tt>, <tt>@culerity</tt> and
== Using Capybara with RSpec
If you prefer RSpec to using Cucumber, you can use the built in RSpec support:
If you prefer RSpec to using Cucumber, you can use the built in RSpec support
by adding the following line (typically to your <tt>spec_helper.rb</tt> file):
require 'capybara/rspec'
Capybara.app = MyRackApp
You can now use it in your examples:
describe "the signup process", :type => :acceptance do
describe "the signup process", :type => :request do
it "signs me in" do
within("#session") do
fill_in 'Login', :with => 'user@example.com'
@ -100,8 +100,14 @@ You can now use it in your examples:
end
end
Capybara is only included for examples which have the type
<tt>:acceptance</tt>.
Capybara is only included for examples with <tt>:type => :request</tt> (or
<tt>:acceptance</tt> for compatibility).
Note that if you use the <tt>rspec-rails</tt> gem, <tt>:type => :request</tt>
is automatically set on all files under <tt>spec/requests</tt> (and also
<tt>spec/integration</tt>), so that's a good directory to place your Capybara specs
in. <tt>rspec-rails</tt> will also automatically include Capybara in
<tt>:controller</tt> and <tt>:mailer</tt> examples.
RSpec's metadata feature can be used to switch to a different driver. Use
<tt>:js => true</tt> to switch to the javascript driver, or provide a
@ -115,13 +121,25 @@ RSpec's metadata feature can be used to switch to a different driver. Use
Note that Capybara's built in RSpec support only works with RSpec 2.0 or later.
You'll need to roll your own for earlier versions of RSpec.
== Using Capybara with Ruby on Rails
You can use the built-in Rails support to easily get Capybara running with
Rails:
requires 'capybara/rails'
== Using Capybara with Rack
If you're using Capybara with a non-Rails Rack application, set
<tt>Capybara.app</tt> to your application class:
Capybara.app = MyRackApp
== Default and current driver
You can set up a default driver for your features. For example if you'd prefer
to run Selenium, you could do:
require 'capybara/rails'
require 'capybara/cucumber'
Capybara.default_driver = :selenium
You can change the driver temporarily:
@ -223,7 +241,7 @@ certain elements, and working with and manipulating those elements.
page.has_css?('table tr.foo')
page.has_content?('foo')
You can these use with RSpec's magic matchers:
You can use these with RSpec's magic matchers:
page.should have_selector('table tr')
page.should have_selector(:xpath, '//table/tr')

View file

@ -36,4 +36,5 @@ Gem::Specification.new do |s|
s.add_development_dependency("launchy", [">= 0.3.5"])
s.add_development_dependency("yard", [">= 0.5.8"])
s.add_development_dependency("fuubar", [">= 0.0.1"])
s.add_development_dependency("cucumber", [">= 0.10"])
end

View file

@ -1,7 +0,0 @@
ENV['RACK_ENV'] = "production"
require 'rubygems'
require 'bundler/setup'
require File.expand_path('lib/capybara/spec/test_app', File.dirname(__FILE__))
run TestApp

23
features/capybara.feature Normal file
View file

@ -0,0 +1,23 @@
Feature: Capybara's cucumber integration
In order to integrate with the lovely plain text testing framework
As Capybara
I want to integrate successfully with Cucumber
Scenario: hello world
When I visit the root page
Then I should see "Hello world!"
@javascript
Scenario: javascript tag
When I visit the root page
Then Capybara should use the "selenium" driver
@selenium
Scenario: selenium tag
When I visit the root page
Then Capybara should use the "selenium" driver
Scenario: matchers
When I visit the root page
And I use a matcher that fails
Then the failing exception should be nice

View file

@ -0,0 +1,24 @@
When /^I visit the root page$/ do
visit('/')
end
Then /^I should see "([^"]*)"$/ do |text|
page.should have_content(text)
end
Then /^Capybara should use the "([^"]*)" driver$/ do |driver|
Capybara.current_driver.should == driver.to_sym
end
When /^I use a matcher that fails$/ do
begin
page.should have_css('h1#doesnotexist')
rescue StandardError => e
@error_message = e.message
end
end
Then /^the failing exception should be nice$/ do
@error_message.should =~ %r(expected css \"h1#doesnotexist\" to return)
end

7
features/support/env.rb Normal file
View file

@ -0,0 +1,7 @@
require 'rubygems'
require 'bundler/setup'
require 'capybara/cucumber'
require 'capybara/spec/test_app'
Capybara.app = TestApp

View file

@ -74,7 +74,7 @@ module Capybara
# xpath { |num| ".//tbody/tr[#{num}]" }
# end
#
# This makes it possible to use this selector in a cariety of ways:
# This makes it possible to use this selector in a variety of ways:
#
# find(:row, 3)
# page.find('table#myTable').find(:row, 3).text

View file

@ -1,7 +1,9 @@
require 'capybara'
require 'capybara/dsl'
require 'capybara/rspec_matchers'
World(Capybara)
World(Capybara::RSpecMatchers)
After do
Capybara.reset_sessions!

View file

@ -123,39 +123,43 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
def params(button)
params = {}
native.xpath(".//input[not(@disabled) and (not(@type) or (@type!='radio' and @type!='file' and @type!='checkbox' and @type!='submit' and @type!='image'))]").map do |input|
merge_param!(params, input['name'].to_s, input['value'].to_s)
end
native.xpath(".//textarea[not(@disabled)]").map do |textarea|
merge_param!(params, textarea['name'].to_s, textarea.text.to_s)
end
native.xpath(".//input[not(@disabled) and (@type='radio' or @type='checkbox')]").map do |input|
merge_param!(params, input['name'].to_s, input['value'].to_s) if input['checked']
end
native.xpath(".//select[not(@disabled)]").map do |select|
if select['multiple'] == 'multiple'
options = select.xpath(".//option[@selected]")
options.each do |option|
merge_param!(params, select['name'].to_s, (option['value'] || option.text).to_s)
end
else
option = select.xpath(".//option[@selected]").first
option ||= select.xpath('.//option').first
merge_param!(params, select['name'].to_s, (option['value'] || option.text).to_s) if option
end
end
native.xpath(".//input[not(@disabled) and @type='file']").map do |input|
if multipart?
file = \
if (value = input['value']).to_s.empty?
NilUploadedFile.new
native.xpath("(.//input|.//select|.//textarea)[not(@disabled)]").map do |field|
case field.name
when 'input'
if %w(radio checkbox).include? field['type']
merge_param!(params, field['name'].to_s, field['value'].to_s) if field['checked']
elsif %w(submit image).include? field['type']
# TO DO identify the click button here (in document order, rather
# than leaving until the end of the params)
elsif field['type'] =='file'
if multipart?
file = \
if (value = field['value']).to_s.empty?
NilUploadedFile.new
else
content_type = MIME::Types.type_for(value).first.to_s
Rack::Test::UploadedFile.new(value, content_type)
end
merge_param!(params, field['name'].to_s, file)
else
content_type = MIME::Types.type_for(value).first.to_s
Rack::Test::UploadedFile.new(value, content_type)
merge_param!(params, field['name'].to_s, File.basename(field['value'].to_s))
end
merge_param!(params, input['name'].to_s, file)
else
merge_param!(params, input['name'].to_s, File.basename(input['value'].to_s))
else
merge_param!(params, field['name'].to_s, field['value'].to_s)
end
when 'select'
if field['multiple'] == 'multiple'
options = field.xpath(".//option[@selected]")
options.each do |option|
merge_param!(params, field['name'].to_s, (option['value'] || option.text).to_s)
end
else
option = field.xpath(".//option[@selected]").first
option ||= field.xpath('.//option').first
merge_param!(params, field['name'].to_s, (option['value'] || option.text).to_s) if option
end
when 'textarea'
merge_param!(params, field['name'].to_s, field.text.to_s)
end
end
merge_param!(params, button[:name], button[:value] || "") if button[:name]
@ -249,7 +253,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
alias_method :source, :body
def reset!
clear_cookies
clear_rack_mock_session
end
def get(*args, &block); reset_cache; super; end
@ -275,6 +279,13 @@ private
Rack::MockSession.new(app, Capybara.default_host || "www.example.com")
end
# Rack::Test::Methods does not provide methods for manipulating the session
# list so these must be manipulated directly.
def clear_rack_mock_session
@_rack_test_sessions = nil
@_rack_mock_sessions = nil
end
def request_path
request.path rescue ""
end

View file

@ -2,7 +2,7 @@ require 'capybara'
module Capybara
class << self
attr_writer :default_driver, :current_driver, :javascript_driver
attr_writer :default_driver, :current_driver, :javascript_driver, :session_name
attr_accessor :app
@ -57,7 +57,7 @@ module Capybara
# @return [Capybara::Session] The currently used session
#
def current_session
session_pool["#{current_driver}#{app.object_id}"] ||= Capybara::Session.new(current_driver, app)
session_pool["#{current_driver}:#{session_name}:#{app.object_id}"] ||= Capybara::Session.new(current_driver, app)
end
##
@ -70,6 +70,27 @@ module Capybara
end
alias_method :reset!, :reset_sessions!
##
#
# The current session name.
#
# @return [Symbol] The name of the currently used session.
#
def session_name
@session_name ||= :default
end
##
#
# Yield a block using a specific session name.
#
def using_session(name)
self.session_name = name
yield
ensure
self.session_name = :default
end
private
def session_pool
@ -79,6 +100,15 @@ module Capybara
extend(self)
##
#
# Shortcut to working in a different session. This is useful when Capybara is included
# in a class or module.
#
def using_session(name, &block)
Capybara.using_session(name, &block)
end
##
#
# Shortcut to accessing the current session. This is useful when Capybara is included in a

View file

@ -29,8 +29,11 @@ module Capybara
rescue TimeoutError
end
unless node
options = if args.last.is_a?(Hash) then args.last else {} end
raise Capybara::ElementNotFound, options[:message] || "Unable to find '#{args[1] || args[0]}'"
options = extract_normalized_options(args)
normalized = Capybara::Selector.normalize(*args)
message = options[:message] || "Unable to find #{normalized[:selector].name} #{normalized[:locator].inspect}"
message = normalized[:selector].failure_message.call(self) if normalized[:selector].failure_message
raise Capybara::ElementNotFound, message
end
return node
end
@ -117,7 +120,7 @@ module Capybara
def all(*args)
options = extract_normalized_options(args)
Capybara::Selector.normalize(*args).
Capybara::Selector.normalize(*args)[:xpaths].
map { |path| find_in_base(path) }.flatten.
select { |node| matches_options(node, options) }.
map { |node| convert_element(node) }
@ -140,7 +143,7 @@ module Capybara
options = extract_normalized_options(args)
found_elements = []
Capybara::Selector.normalize(*args).each do |path|
Capybara::Selector.normalize(*args)[:xpaths].each do |path|
find_in_base(path).each do |node|
if matches_options(node, options)
found_elements << convert_element(node)

View file

@ -1,16 +1,23 @@
require 'capybara'
require 'capybara/dsl'
require 'rspec/core'
require 'capybara/rspec_matchers'
RSpec.configure do |config|
config.include Capybara, :type => :request
config.include Capybara, :type => :acceptance
config.include Capybara::RSpecMatchers, :type => :request
config.include Capybara::RSpecMatchers, :type => :acceptance
# The before and after blocks must run instantaneously, because Capybara
# might not actually be used in all examples where it's included.
config.after do
if example.metadata[:type] == :acceptance
if self.class.include?(Capybara)
Capybara.reset_sessions!
Capybara.use_default_driver
end
end
config.before do
if example.metadata[:type] == :acceptance
if self.class.include?(Capybara)
Capybara.current_driver = Capybara.javascript_driver if example.metadata[:js]
Capybara.current_driver = example.metadata[:driver] if example.metadata[:driver]
end

View file

@ -0,0 +1,61 @@
module Capybara
module RSpecMatchers
class HaveSelector
def initialize(*args)
@args = args
end
def matches?(actual)
@actual = wrap(actual)
@actual.has_selector?(*@args)
end
def does_not_match?(actual)
@actual = wrap(actual)
@actual.has_no_selector?(*@args)
end
def failure_message_for_should
if normalized[:selector].failure_message
normalized[:selector].failure_message.call(@actual)
else
"expected #{selector_name} to return something"
end
end
def failure_message_for_should_not
"expected #{selector_name} not to return anything"
end
def selector_name
name = "#{normalized[:selector].name} #{normalized[:locator].inspect}"
name << " with text #{normalized[:options][:text].inspect}" if normalized[:options][:text]
name
end
def wrap(actual)
if actual.respond_to?("has_selector?")
actual
else
Capybara.string(actual.to_s)
end
end
def normalized
@normalized ||= Capybara::Selector.normalize(*@args)
end
end
def have_selector(*args)
HaveSelector.new(*args)
end
def have_xpath(*args)
HaveSelector.new(:xpath, *args)
end
def have_css(*args)
HaveSelector.new(:css, *args)
end
end
end

View file

@ -15,19 +15,26 @@ module Capybara
all.delete(name.to_sym)
end
def normalize(name_or_locator, locator=nil)
xpath = if locator
all[name_or_locator.to_sym].call(locator)
def normalize(*args)
result = {}
result[:options] = if args.last.is_a?(Hash) then args.pop else {} end
if args[1]
result[:selector] = all[args[0]]
result[:locator] = args[1]
else
selector = all.values.find { |s| s.match?(name_or_locator) }
selector ||= all[Capybara.default_selector]
selector.call(name_or_locator)
result[:selector] = all.values.find { |s| s.match?(args[0]) }
result[:locator] = args[0]
end
result[:selector] ||= all[Capybara.default_selector]
xpath = result[:selector].call(result[:locator])
if xpath.respond_to?(:to_xpaths)
xpath.to_xpaths
result[:xpaths] = xpath.to_xpaths
else
[xpath.to_s].flatten
result[:xpaths] = [xpath.to_s].flatten
end
result
end
end
@ -46,6 +53,11 @@ module Capybara
@match
end
def failure_message(&block)
@failure_message = block if block
@failure_message
end
def call(locator)
@xpath.call(locator)
end

View file

@ -26,6 +26,20 @@ shared_examples_for 'driver' do
@driver.visit('/with_simple_html')
@driver.body.should include('Bar')
end
if "".respond_to?(:encoding)
context "encoding of response between ascii and utf8" do
it "should be valid with html entities" do
@driver.visit('/with_html_entities')
lambda { @driver.body.encode!("UTF-8") }.should_not raise_error
end
it "should be valid without html entities" do
@driver.visit('/with_html')
lambda { @driver.body.encode!("UTF-8") }.should_not raise_error
end
end
end
end
describe '#find' do

View file

@ -75,18 +75,25 @@ shared_examples_for "session" do
@session.visit('/form')
@session.fill_in('address1_city', :with =>'Paris')
@session.fill_in('address1_street', :with =>'CDG')
@session.fill_in('address1_street', :with =>'CDG')
@session.select("France", :from => 'address1_country')
@session.fill_in('address2_city', :with => 'Mikolaiv')
@session.fill_in('address2_street', :with => 'PGS')
@session.select("Ukraine", :from => 'address2_country')
@session.click_button "awesome"
addresses=extract_results(@session)["addresses"]
addresses.should have(2).addresses
addresses[0]["street"].should == 'CDG'
addresses[0]["city"].should == 'Paris'
addresses[0]["street"].should == 'CDG'
addresses[0]["city"].should == 'Paris'
addresses[0]["country"].should == 'France'
addresses[1]["street"].should == 'PGS'
addresses[1]["city"].should == 'Mikolaiv'
addresses[1]["street"].should == 'PGS'
addresses[1]["city"].should == 'Mikolaiv'
addresses[1]["country"].should == 'Ukraine'
end
end

View file

@ -79,6 +79,18 @@ shared_examples_for "find" do
end
end
context "with custom selector with failure_message option", :focus => true do
it "it should raise an error with the failure message if the element is not found" do
Capybara.add_selector(:monkey) do
xpath { |num| ".//*[contains(@id, 'monkey')][#{num}]" }
failure_message { |node| node.all(".//*[contains(@id, 'monkey')]").map { |node| node.text }.sort.join(', ') }
end
running do
@session.find(:monkey, '14').text.should == 'Monkey Paul'
end.should raise_error(Capybara::ElementNotFound, "Monkey John, Monkey Paul")
end
end
context "with css as default selector" do
before { Capybara.default_selector = :css }
it "should find the first element using the given locator" do
@ -97,7 +109,7 @@ shared_examples_for "find" do
it "should raise ElementNotFound with a useful default message if nothing was found" do
running do
@session.find(:xpath, '//div[@id="nosuchthing"]').should be_nil
end.should raise_error(Capybara::ElementNotFound, "Unable to find '//div[@id=\"nosuchthing\"]'")
end.should raise_error(Capybara::ElementNotFound, "Unable to find xpath \"//div[@id=\\\"nosuchthing\\\"]\"")
end
it "should accept an XPath instance and respect the order of paths" do

View file

@ -1,8 +1,8 @@
shared_examples_for "session with headers support" do
describe '#response_headers' do
it "should return response headers" do
@session.visit('/with_simple_html')
@session.response_headers['Content-Type'].should == 'text/html'
@session.visit('/with_simple_html')
@session.response_headers['Content-Type'].should =~ %r(text/html)
end
end
end

View file

@ -69,6 +69,10 @@ class TestApp < Sinatra::Base
request.cookies['capybara']
end
get '/get_header' do
env['HTTP_FOO']
end
get '/:view' do |view|
erb view.to_sym
end

View file

@ -163,18 +163,30 @@
<span>First address<span>
<label for='address1_street'>Street</label>
<input type="text" name="form[addresses][][street]" value="" id="address1_street">
<label for='address1_city'>City</label>
<input type="text" name="form[addresses][][city]" value="" id="address1_city">
</p>
<p>
<label for='address1_city'>City</label>
<input type="text" name="form[addresses][][city]" value="" id="address1_city">
<label for='address1_country'>Country</label>
<select name="form[addresses][][country]" id="address1_country">
<option>France</option>
<option>Ukraine</option>
</select>
</p>
<p>
<span>Second address<span>
<label for='address2_street'>Street</label>
<input type="text" name="form[addresses][][street]" value="" id="address2_street">
<label for='address2_city'>City</label>
<input type="text" name="form[addresses][][city]" value="" id="address2_city">
<label for='address2_country'>Country</label>
<select name="form[addresses][][country]" id="address2_country">
<option>France</option>
<option>Ukraine</option>
</select>
</p>
<div style="display:none;">
@ -207,7 +219,7 @@
<p>
<label for="form_disabled_radio">
Disabled Checkbox
Disabled Radio
<input type="radio" name="form[disabled_radio]" value="Should not see me" id="form_disabled_radio" checked="checked" disabled="disabled" />
</label>
</p>

View file

@ -0,0 +1 @@
Encoding with &mdash; html entities &raquo;

View file

@ -21,7 +21,8 @@ module Capybara
require "launchy"
Launchy::Browser.run(path)
rescue LoadError
warn "Sorry, you need to install launchy to open pages: `gem install launchy`"
warn "Sorry, you need to install launchy (`gem install launchy`) and " <<
"make sure it's available to open pages with `save_and_open_page`."
end
def rewrite_css_and_image_references(response_html) # :nodoc:

View file

@ -1,3 +1,3 @@
module Capybara
VERSION = '0.4.1.rc'
VERSION = '0.4.1.1'
end

View file

@ -53,4 +53,32 @@ describe Capybara::Driver::RackTest do
it_should_behave_like "driver with status code support"
it_should_behave_like "driver with cookies support"
it_should_behave_like "driver with infinite redirect detection"
describe '#reset!' do
it { @driver.visit('/foo'); lambda { @driver.reset! }.should change(@driver, :current_url).to('') }
it 'should reset headers' do
@driver.header('FOO', 'BAR')
@driver.visit('/get_header')
@driver.body.should include('BAR')
@driver.reset!
@driver.visit('/get_header')
@driver.body.should_not include('BAR')
end
it 'should reset response' do
@driver.visit('/foo')
lambda { @driver.response }.should_not raise_error
@driver.reset!
lambda { @driver.response }.should raise_error
end
it 'should request response' do
@driver.visit('/foo')
lambda { @driver.request }.should_not raise_error
@driver.reset!
lambda { @driver.request }.should raise_error
end
end
end

View file

@ -9,6 +9,7 @@ describe Capybara do
end
after do
Capybara.session_name = nil
Capybara.default_driver = nil
Capybara.use_default_driver
end
@ -123,6 +124,48 @@ describe Capybara do
Capybara.current_session.object_id.should_not == object_id
Capybara.current_session.app.should == Capybara.app
end
it "should change when the session name changes" do
object_id = Capybara.current_session.object_id
Capybara.session_name = :administrator
Capybara.session_name.should == :administrator
Capybara.current_session.object_id.should_not == object_id
Capybara.session_name = :default
Capybara.session_name.should == :default
Capybara.current_session.object_id.should == object_id
end
end
describe "#using_session" do
it "should change the session name for the duration of the block" do
Capybara.session_name.should == :default
Capybara.using_session(:administrator) do
Capybara.session_name.should == :administrator
end
Capybara.session_name.should == :default
end
it "should reset the session to the default, even if an exception occurs" do
begin
Capybara.using_session(:raise) do
raise
end
rescue Exception
end
Capybara.session_name.should == :default
end
it "should yield the passed block" do
called = false
Capybara.using_session(:administrator) { called = true }
called.should == true
end
end
describe "#session_name" do
it "should default to :default" do
Capybara.session_name.should == :default
end
end
describe 'the DSL' do
@ -152,6 +195,15 @@ describe Capybara do
foo.page.click_link('ullamco')
foo.page.body.should include('Another World')
end
it "should provide an 'using_session' shortcut" do
klass = Class.new do
include Capybara
end
Capybara.should_receive(:using_session).with(:name)
foo = klass.new
foo.using_session(:name)
end
end
end

211
spec/rspec_matchers_spec.rb Normal file
View file

@ -0,0 +1,211 @@
require 'spec_helper'
require 'capybara/dsl'
require 'capybara/rspec_matchers'
Capybara.app = TestApp
describe Capybara::RSpecMatchers do
include Capybara
include Capybara::RSpecMatchers
describe "have_css matcher" do
context "on a string" do
context "with should" do
it "passes if has_css? returns true" do
"<h1>Text</h1>".should have_css('h1')
end
it "fails if has_css? returns false" do
expect do
"<h1>Text</h1>".should have_css('h2')
end.to raise_error(/expected css "h2" to return something/)
end
end
context "with should_not" do
it "passes if has_no_css? returns true" do
"<h1>Text</h1>".should_not have_css('h2')
end
it "fails if has_no_css? returns false" do
expect do
"<h1>Text</h1>".should_not have_css('h1')
end.to raise_error(/expected css "h1" not to return anything/)
end
end
end
context "on a page or node" do
before do
visit('/with_html')
end
context "with should" do
it "passes if has_css? returns true" do
page.should have_css('h1')
end
it "fails if has_css? returns false" do
expect do
page.should have_css('h1#doesnotexist')
end.to raise_error(/expected css "h1#doesnotexist" to return something/)
end
end
context "with should_not" do
it "passes if has_no_css? returns true" do
page.should_not have_css('h1#doesnotexist')
end
it "fails if has_no_css? returns false" do
expect do
page.should_not have_css('h1')
end.to raise_error(/expected css "h1" not to return anything/)
end
end
end
end
describe "have_xpath matcher" do
context "on a string" do
context "with should" do
it "passes if has_css? returns true" do
"<h1>Text</h1>".should have_xpath('//h1')
end
it "fails if has_css? returns false" do
expect do
"<h1>Text</h1>".should have_xpath('//h2')
end.to raise_error(%r(expected xpath "//h2" to return something))
end
end
context "with should_not" do
it "passes if has_no_css? returns true" do
"<h1>Text</h1>".should_not have_xpath('//h2')
end
it "fails if has_no_css? returns false" do
expect do
"<h1>Text</h1>".should_not have_xpath('//h1')
end.to raise_error(%r(expected xpath "//h1" not to return anything))
end
end
end
context "on a page or node" do
before do
visit('/with_html')
end
context "with should" do
it "passes if has_css? returns true" do
page.should have_xpath('//h1')
end
it "fails if has_css? returns false" do
expect do
page.should have_xpath("//h1[@id='doesnotexist']")
end.to raise_error(%r(expected xpath "//h1\[@id='doesnotexist'\]" to return something))
end
end
context "with should_not" do
it "passes if has_no_css? returns true" do
page.should_not have_xpath('//h1[@id="doesnotexist"]')
end
it "fails if has_no_css? returns false" do
expect do
page.should_not have_xpath('//h1')
end.to raise_error(%r(expected xpath "//h1" not to return anything))
end
end
end
end
describe "have_selector matcher" do
context "on a string" do
context "with should" do
it "passes if has_css? returns true" do
"<h1>Text</h1>".should have_selector('//h1')
end
it "fails if has_css? returns false" do
expect do
"<h1>Text</h1>".should have_selector('//h2')
end.to raise_error(%r(expected xpath "//h2" to return something))
end
it "fails with the selector's failure_message if set" do
Capybara.add_selector(:monkey) do
xpath { |num| ".//*[contains(@id, 'monkey')][#{num}]" }
failure_message { |node| node.all(".//*[contains(@id, 'monkey')]").map { |node| node.text }.sort.join(', ') }
end
expect do
'<h1 id="monkey_paul">Monkey John</h1>'.should have_selector(:monkey, 14)
end.to raise_error("Monkey John")
end
end
context "with should_not" do
it "passes if has_no_css? returns true" do
"<h1>Text</h1>".should_not have_selector(:css, 'h2')
end
it "fails if has_no_css? returns false" do
expect do
"<h1>Text</h1>".should_not have_selector(:css, 'h1')
end.to raise_error(%r(expected css "h1" not to return anything))
end
end
end
context "on a page or node" do
before do
visit('/with_html')
end
context "with should" do
it "passes if has_css? returns true" do
page.should have_selector('//h1', :text => 'test')
end
it "fails if has_css? returns false" do
expect do
page.should have_selector("//h1[@id='doesnotexist']")
end.to raise_error(%r(expected xpath "//h1\[@id='doesnotexist'\]" to return something))
end
it "includes text in error message" do
expect do
page.should have_selector("//h1", :text => 'wrong text')
end.to raise_error(%r(expected xpath "//h1" with text "wrong text" to return something))
end
it "fails with the selector's failure_message if set" do
Capybara.add_selector(:monkey) do
xpath { |num| ".//*[contains(@id, 'monkey')][#{num}]" }
failure_message { |node| node.all(".//*[contains(@id, 'monkey')]").map { |node| node.text }.sort.join(', ') }
end
expect do
page.should have_selector(:monkey, 14)
end.to raise_error("Monkey John, Monkey Paul")
end
end
context "with should_not" do
it "passes if has_no_css? returns true" do
page.should_not have_selector(:css, 'h1#doesnotexist')
end
it "fails if has_no_css? returns false" do
expect do
page.should_not have_selector(:css, 'h1', :text => 'test')
end.to raise_error(%r(expected css "h1" with text "test" not to return anything))
end
end
end
end
end

View file

@ -3,8 +3,8 @@ require 'capybara/rspec'
Capybara.app = TestApp
describe 'capybara/rspec', :type => :acceptance do
it "should include Capybara in rpsec" do
describe 'capybara/rspec', :type => :request do
it "should include Capybara in rspec" do
visit('/foo')
page.body.should include('Another World')
end