capybara 0.4.1.2 → 1.0.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +46 -0
- data/README.rdoc +211 -64
- data/lib/capybara.rb +31 -15
- data/lib/capybara/cucumber.rb +12 -16
- data/lib/capybara/dsl.rb +65 -28
- data/lib/capybara/node/actions.rb +7 -5
- data/lib/capybara/node/document.rb +8 -0
- data/lib/capybara/node/finders.rb +11 -7
- data/lib/capybara/node/matchers.rb +32 -6
- data/lib/capybara/node/simple.rb +20 -0
- data/lib/capybara/rack_test/browser.rb +115 -0
- data/lib/capybara/rack_test/driver.rb +77 -0
- data/lib/capybara/rack_test/form.rb +80 -0
- data/lib/capybara/rack_test/node.rb +101 -0
- data/lib/capybara/rspec.rb +11 -3
- data/lib/capybara/rspec/features.rb +22 -0
- data/lib/capybara/rspec/matchers.rb +146 -0
- data/lib/capybara/selector.rb +27 -8
- data/lib/capybara/selenium/driver.rb +148 -0
- data/lib/capybara/selenium/node.rb +91 -0
- data/lib/capybara/session.rb +42 -15
- data/lib/capybara/spec/driver.rb +55 -1
- data/lib/capybara/spec/fixtures/capybara.jpg +0 -0
- data/lib/capybara/spec/public/test.js +7 -2
- data/lib/capybara/spec/session.rb +51 -7
- data/lib/capybara/spec/session/attach_file_spec.rb +9 -6
- data/lib/capybara/spec/session/click_button_spec.rb +35 -0
- data/lib/capybara/spec/session/current_host_spec.rb +62 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +6 -0
- data/lib/capybara/spec/session/find_spec.rb +23 -1
- data/lib/capybara/spec/session/first_spec.rb +39 -6
- data/lib/capybara/spec/session/has_css_spec.rb +30 -0
- data/lib/capybara/spec/session/has_field_spec.rb +47 -11
- data/lib/capybara/spec/session/javascript.rb +0 -1
- data/lib/capybara/spec/session/text_spec.rb +19 -0
- data/lib/capybara/spec/test_app.rb +9 -0
- data/lib/capybara/spec/views/form.erb +8 -3
- data/lib/capybara/spec/views/header_links.erb +7 -0
- data/lib/capybara/spec/views/host_links.erb +12 -0
- data/lib/capybara/spec/views/with_html.erb +6 -2
- data/lib/capybara/spec/views/with_html_entities.erb +1 -0
- data/lib/capybara/spec/views/with_js.erb +4 -0
- data/lib/capybara/util/save_and_open_page.rb +7 -3
- data/lib/capybara/util/timeout.rb +2 -2
- data/lib/capybara/version.rb +1 -1
- data/spec/capybara_spec.rb +1 -1
- data/spec/driver/rack_test_driver_spec.rb +24 -2
- data/spec/driver/selenium_driver_spec.rb +2 -1
- data/spec/dsl_spec.rb +56 -4
- data/spec/rspec/features_spec.rb +45 -0
- data/spec/rspec/matchers_spec.rb +451 -0
- data/spec/rspec_spec.rb +9 -2
- data/spec/save_and_open_page_spec.rb +9 -13
- data/spec/server_spec.rb +4 -0
- data/spec/session/rack_test_session_spec.rb +2 -2
- data/spec/session/selenium_session_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -14
- data/spec/string_spec.rb +1 -1
- metadata +60 -69
- data/lib/capybara/driver/celerity_driver.rb +0 -164
- data/lib/capybara/driver/culerity_driver.rb +0 -26
- data/lib/capybara/driver/rack_test_driver.rb +0 -303
- data/lib/capybara/driver/selenium_driver.rb +0 -161
- data/spec/driver/celerity_driver_spec.rb +0 -13
- data/spec/driver/culerity_driver_spec.rb +0 -14
- data/spec/driver/remote_culerity_driver_spec.rb +0 -22
- data/spec/driver/remote_selenium_driver_spec.rb +0 -16
- data/spec/session/celerity_session_spec.rb +0 -24
- data/spec/session/culerity_session_spec.rb +0 -26
@@ -10,7 +10,6 @@ shared_examples_for "session with javascript support" do
|
|
10
10
|
|
11
11
|
describe 'Node#drag_to' do
|
12
12
|
it "should drag and drop an object" do
|
13
|
-
pending "drag/drop is currently broken under celerity/culerity" if @session.driver.is_a?(Capybara::Driver::Celerity)
|
14
13
|
@session.visit('/with_js')
|
15
14
|
element = @session.find('//div[@id="drag"]')
|
16
15
|
target = @session.find('//div[@id="drop"]')
|
@@ -0,0 +1,19 @@
|
|
1
|
+
shared_examples_for "text" do
|
2
|
+
describe '#text' do
|
3
|
+
before do
|
4
|
+
@session.visit('/with_simple_html')
|
5
|
+
end
|
6
|
+
|
7
|
+
it "should print the text of the page" do
|
8
|
+
@session.text.should == 'Bar'
|
9
|
+
end
|
10
|
+
|
11
|
+
context "with css as default selector" do
|
12
|
+
before { Capybara.default_selector = :css }
|
13
|
+
it "should print the text of the page" do
|
14
|
+
@session.text.should == 'Bar'
|
15
|
+
end
|
16
|
+
after { Capybara.default_selector = :xpath }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -22,6 +22,10 @@ class TestApp < Sinatra::Base
|
|
22
22
|
redirect '/landed'
|
23
23
|
end
|
24
24
|
|
25
|
+
get '/host' do
|
26
|
+
"Current host is #{request.scheme}://#{request.host}"
|
27
|
+
end
|
28
|
+
|
25
29
|
get '/redirect/:times/times' do
|
26
30
|
times = params[:times].to_i
|
27
31
|
if times.zero?
|
@@ -59,6 +63,11 @@ class TestApp < Sinatra::Base
|
|
59
63
|
redirect back
|
60
64
|
end
|
61
65
|
|
66
|
+
get '/slow_response' do
|
67
|
+
sleep 2
|
68
|
+
'Finally!'
|
69
|
+
end
|
70
|
+
|
62
71
|
get '/set_cookie' do
|
63
72
|
cookie_value = 'test_cookie'
|
64
73
|
response.set_cookie('capybara', cookie_value)
|
@@ -109,6 +109,11 @@
|
|
109
109
|
</select>
|
110
110
|
</p>
|
111
111
|
|
112
|
+
<p>
|
113
|
+
<label for="form_zipcode">Zipcode</label>
|
114
|
+
<input type="text" maxlength="5" name="form[zipcode]" id="form_zipcode" />
|
115
|
+
</p>
|
116
|
+
|
112
117
|
<p>
|
113
118
|
<label for="form_tendency">Tendency</label>
|
114
119
|
<select name="form[tendency]" id="form_tendency"></select>
|
@@ -242,10 +247,10 @@
|
|
242
247
|
|
243
248
|
<p>
|
244
249
|
<input type="button" name="form[fresh]" id="fresh_btn" value="i am fresh"/>
|
245
|
-
<input type="submit" name="form[awesome]" id="awe123" value="awesome"/>
|
250
|
+
<input type="submit" name="form[awesome]" id="awe123" title="What an Awesome Button" value="awesome"/>
|
246
251
|
<input type="submit" name="form[crappy]" id="crap321" value="crappy"/>
|
247
|
-
<input type="image" name="form[okay]" id="okay556" value="okay" alt="oh hai thar"/>
|
248
|
-
<button type="submit" id="click_me_123" value="click_me">Click me!</button>
|
252
|
+
<input type="image" name="form[okay]" id="okay556" title="Okay 556 Image" value="okay" alt="oh hai thar"/>
|
253
|
+
<button type="submit" id="click_me_123" title="Click Title button" value="click_me">Click me!</button>
|
249
254
|
<button type="submit" name="form[no_value]">No Value!</button>
|
250
255
|
<button id="no_type">No Type!</button>
|
251
256
|
</p>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<p>
|
2
|
+
<a href="/host">Relative Host</a>
|
3
|
+
<a href="http://capybara2.elabs.se/host">Absolute Host</a>
|
4
|
+
</p>
|
5
|
+
|
6
|
+
<form action="/host">
|
7
|
+
<p><input type="submit" value="Relative Host"/></p>
|
8
|
+
</form>
|
9
|
+
|
10
|
+
<form action="http://capybara2.elabs.se/host">
|
11
|
+
<p><input type="submit" value="Absolute Host"/></p>
|
12
|
+
</form>
|
@@ -56,11 +56,15 @@
|
|
56
56
|
</div>
|
57
57
|
|
58
58
|
<div style="display: none;">
|
59
|
-
<a class="
|
59
|
+
<a id="first_invisble" class="hidden">first hidden link</a>
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<div style="display: none;">
|
63
|
+
<a id="invisible" class="visibility hidden">hidden link</a>
|
60
64
|
</div>
|
61
65
|
|
62
66
|
<div>
|
63
|
-
<a class="visibility">visible link</a>
|
67
|
+
<a id="visible" class="visibility">visible link</a>
|
64
68
|
</div>
|
65
69
|
|
66
70
|
<ul>
|
@@ -0,0 +1 @@
|
|
1
|
+
Encoding with — html entities »
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module Capybara
|
2
2
|
class << self
|
3
|
-
def
|
4
|
-
|
3
|
+
def save_page(html, file_name=nil)
|
4
|
+
file_name ||= "capybara-#{Time.new.strftime("%Y%m%d%H%M%S")}#{rand(10**10)}.html"
|
5
|
+
name = File.join(*[Capybara.save_and_open_page_path, file_name].compact)
|
5
6
|
|
6
7
|
unless Capybara.save_and_open_page_path.nil? || File.directory?(Capybara.save_and_open_page_path )
|
7
8
|
FileUtils.mkdir_p(Capybara.save_and_open_page_path)
|
@@ -11,8 +12,11 @@ module Capybara
|
|
11
12
|
tempfile = File.new(name,'w')
|
12
13
|
tempfile.write(rewrite_css_and_image_references(html))
|
13
14
|
tempfile.close
|
15
|
+
tempfile.path
|
16
|
+
end
|
14
17
|
|
15
|
-
|
18
|
+
def save_and_open_page(html, file_name=nil)
|
19
|
+
open_in_browser save_page(html, file_name)
|
16
20
|
end
|
17
21
|
|
18
22
|
protected
|
@@ -4,7 +4,7 @@ module Capybara
|
|
4
4
|
##
|
5
5
|
# Provides timeout similar to standard library Timeout, but avoids threads
|
6
6
|
#
|
7
|
-
def timeout(seconds = 1, driver = nil, &block)
|
7
|
+
def timeout(seconds = 1, driver = nil, error_message = nil, &block)
|
8
8
|
start_time = Time.now
|
9
9
|
|
10
10
|
result = nil
|
@@ -14,7 +14,7 @@ module Capybara
|
|
14
14
|
|
15
15
|
delay = seconds - (Time.now - start_time)
|
16
16
|
if delay <= 0
|
17
|
-
raise TimeoutError
|
17
|
+
raise TimeoutError, error_message || "timed out"
|
18
18
|
end
|
19
19
|
|
20
20
|
driver && driver.wait_until(delay)
|
data/lib/capybara/version.rb
CHANGED
data/spec/capybara_spec.rb
CHANGED
@@ -17,7 +17,7 @@ describe Capybara do
|
|
17
17
|
describe '.register_driver' do
|
18
18
|
it "should add a new driver" do
|
19
19
|
Capybara.register_driver :schmoo do |app|
|
20
|
-
Capybara::Driver
|
20
|
+
Capybara::RackTest::Driver.new(app)
|
21
21
|
end
|
22
22
|
session = Capybara::Session.new(:schmoo, TestApp)
|
23
23
|
session.visit('/')
|
@@ -14,14 +14,14 @@ def capture(*streams)
|
|
14
14
|
result.string
|
15
15
|
end
|
16
16
|
|
17
|
-
describe Capybara::Driver
|
17
|
+
describe Capybara::RackTest::Driver do
|
18
18
|
before do
|
19
19
|
@driver = TestSessions::RackTest.driver
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should throw an error when no rack app is given" do
|
23
23
|
running do
|
24
|
-
Capybara::Driver
|
24
|
+
Capybara::RackTest::Driver.new(nil)
|
25
25
|
end.should raise_error(ArgumentError)
|
26
26
|
end
|
27
27
|
|
@@ -81,4 +81,26 @@ describe Capybara::Driver::RackTest do
|
|
81
81
|
lambda { @driver.request }.should raise_error
|
82
82
|
end
|
83
83
|
end
|
84
|
+
|
85
|
+
describe ':headers option' do
|
86
|
+
it 'should always set headers' do
|
87
|
+
@driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
|
88
|
+
@driver.visit('/get_header')
|
89
|
+
@driver.body.should include('foobar')
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should keep headers on link clicks' do
|
93
|
+
@driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
|
94
|
+
@driver.visit('/header_links')
|
95
|
+
@driver.find('.//a').first.click
|
96
|
+
@driver.body.should include('foobar')
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should keep headers on form submit' do
|
100
|
+
@driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
|
101
|
+
@driver.visit('/header_links')
|
102
|
+
@driver.find('.//input').first.click
|
103
|
+
@driver.body.should include('foobar')
|
104
|
+
end
|
105
|
+
end
|
84
106
|
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Capybara::Driver
|
3
|
+
describe Capybara::Selenium::Driver do
|
4
4
|
before do
|
5
5
|
@driver = TestSessions::Selenium.driver
|
6
6
|
end
|
7
7
|
|
8
8
|
it_should_behave_like "driver"
|
9
9
|
it_should_behave_like "driver with javascript support"
|
10
|
+
it_should_behave_like "driver with resynchronization support"
|
10
11
|
it_should_behave_like "driver with frame support"
|
11
12
|
it_should_behave_like "driver with support for window switching"
|
12
13
|
it_should_behave_like "driver without status code support"
|
data/spec/dsl_spec.rb
CHANGED
@@ -2,13 +2,14 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
require 'capybara/dsl'
|
4
4
|
|
5
|
-
describe Capybara do
|
5
|
+
describe Capybara::DSL do
|
6
6
|
|
7
7
|
before do
|
8
8
|
Capybara.app = TestApp
|
9
9
|
end
|
10
10
|
|
11
11
|
after do
|
12
|
+
Capybara.session_name = nil
|
12
13
|
Capybara.default_driver = nil
|
13
14
|
Capybara.use_default_driver
|
14
15
|
end
|
@@ -123,11 +124,53 @@ describe Capybara do
|
|
123
124
|
Capybara.current_session.object_id.should_not == object_id
|
124
125
|
Capybara.current_session.app.should == Capybara.app
|
125
126
|
end
|
127
|
+
|
128
|
+
it "should change when the session name changes" do
|
129
|
+
object_id = Capybara.current_session.object_id
|
130
|
+
Capybara.session_name = :administrator
|
131
|
+
Capybara.session_name.should == :administrator
|
132
|
+
Capybara.current_session.object_id.should_not == object_id
|
133
|
+
Capybara.session_name = :default
|
134
|
+
Capybara.session_name.should == :default
|
135
|
+
Capybara.current_session.object_id.should == object_id
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "#using_session" do
|
140
|
+
it "should change the session name for the duration of the block" do
|
141
|
+
Capybara.session_name.should == :default
|
142
|
+
Capybara.using_session(:administrator) do
|
143
|
+
Capybara.session_name.should == :administrator
|
144
|
+
end
|
145
|
+
Capybara.session_name.should == :default
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should reset the session to the default, even if an exception occurs" do
|
149
|
+
begin
|
150
|
+
Capybara.using_session(:raise) do
|
151
|
+
raise
|
152
|
+
end
|
153
|
+
rescue Exception
|
154
|
+
end
|
155
|
+
Capybara.session_name.should == :default
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should yield the passed block" do
|
159
|
+
called = false
|
160
|
+
Capybara.using_session(:administrator) { called = true }
|
161
|
+
called.should == true
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "#session_name" do
|
166
|
+
it "should default to :default" do
|
167
|
+
Capybara.session_name.should == :default
|
168
|
+
end
|
126
169
|
end
|
127
170
|
|
128
171
|
describe 'the DSL' do
|
129
172
|
before do
|
130
|
-
@session = Capybara
|
173
|
+
@session = Class.new { include Capybara::DSL }.new
|
131
174
|
end
|
132
175
|
|
133
176
|
it_should_behave_like "session"
|
@@ -135,7 +178,7 @@ describe Capybara do
|
|
135
178
|
|
136
179
|
it "should be possible to include it in another class" do
|
137
180
|
klass = Class.new do
|
138
|
-
include Capybara
|
181
|
+
include Capybara::DSL
|
139
182
|
end
|
140
183
|
foo = klass.new
|
141
184
|
foo.visit('/with_html')
|
@@ -145,13 +188,22 @@ describe Capybara do
|
|
145
188
|
|
146
189
|
it "should provide a 'page' shortcut for more expressive tests" do
|
147
190
|
klass = Class.new do
|
148
|
-
include Capybara
|
191
|
+
include Capybara::DSL
|
149
192
|
end
|
150
193
|
foo = klass.new
|
151
194
|
foo.page.visit('/with_html')
|
152
195
|
foo.page.click_link('ullamco')
|
153
196
|
foo.page.body.should include('Another World')
|
154
197
|
end
|
198
|
+
|
199
|
+
it "should provide an 'using_session' shortcut" do
|
200
|
+
klass = Class.new do
|
201
|
+
include Capybara::DSL
|
202
|
+
end
|
203
|
+
Capybara.should_receive(:using_session).with(:name)
|
204
|
+
foo = klass.new
|
205
|
+
foo.using_session(:name)
|
206
|
+
end
|
155
207
|
end
|
156
208
|
|
157
209
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'capybara/rspec'
|
3
|
+
|
4
|
+
Capybara.app = TestApp
|
5
|
+
|
6
|
+
RSpec.configuration.before(:each, :example_group => {:file_path => __FILE__}) do
|
7
|
+
@in_filtered_hook = true
|
8
|
+
end
|
9
|
+
|
10
|
+
feature "Capybara's feature DSL" do
|
11
|
+
background do
|
12
|
+
@in_background = true
|
13
|
+
end
|
14
|
+
|
15
|
+
scenario "includes Capybara" do
|
16
|
+
visit('/')
|
17
|
+
page.should have_content('Hello world!')
|
18
|
+
end
|
19
|
+
|
20
|
+
scenario "preserves description" do
|
21
|
+
example.metadata[:full_description].should == "Capybara's feature DSL preserves description"
|
22
|
+
end
|
23
|
+
|
24
|
+
scenario "allows driver switching", :driver => :selenium do
|
25
|
+
Capybara.current_driver.should == :selenium
|
26
|
+
end
|
27
|
+
|
28
|
+
scenario "runs background" do
|
29
|
+
@in_background.should be_true
|
30
|
+
end
|
31
|
+
|
32
|
+
scenario "runs hooks filtered by file path" do
|
33
|
+
@in_filtered_hook.should be_true
|
34
|
+
end
|
35
|
+
|
36
|
+
scenario "doesn't pollute the Object namespace" do
|
37
|
+
Object.new.respond_to?(:feature, true).should be_false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
feature "Capybara's feature DSL with driver", :driver => :culerity do
|
42
|
+
scenario "switches driver" do
|
43
|
+
Capybara.current_driver.should == :culerity
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,451 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'capybara/dsl'
|
3
|
+
require 'capybara/rspec/matchers'
|
4
|
+
|
5
|
+
Capybara.app = TestApp
|
6
|
+
|
7
|
+
describe Capybara::RSpecMatchers do
|
8
|
+
include Capybara::DSL
|
9
|
+
include Capybara::RSpecMatchers
|
10
|
+
|
11
|
+
describe "have_css matcher" do
|
12
|
+
context "on a string" do
|
13
|
+
context "with should" do
|
14
|
+
it "passes if has_css? returns true" do
|
15
|
+
"<h1>Text</h1>".should have_css('h1')
|
16
|
+
end
|
17
|
+
|
18
|
+
it "fails if has_css? returns false" do
|
19
|
+
expect do
|
20
|
+
"<h1>Text</h1>".should have_css('h2')
|
21
|
+
end.to raise_error(/expected css "h2" to return something/)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "passes if matched node count equals expected count" do
|
25
|
+
"<h1>Text</h1>".should have_css('h1', :count => 1)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "fails if matched node count does not equal expected count" do
|
29
|
+
expect do
|
30
|
+
"<h1>Text</h1>".should have_css('h1', :count => 2)
|
31
|
+
end.to raise_error(/expected css "h1" to return something/)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with should_not" do
|
36
|
+
it "passes if has_no_css? returns true" do
|
37
|
+
"<h1>Text</h1>".should_not have_css('h2')
|
38
|
+
end
|
39
|
+
|
40
|
+
it "fails if has_no_css? returns false" do
|
41
|
+
expect do
|
42
|
+
"<h1>Text</h1>".should_not have_css('h1')
|
43
|
+
end.to raise_error(/expected css "h1" not to return anything/)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "passes if matched node count does not equal expected count" do
|
47
|
+
"<h1>Text</h1>".should_not have_css('h1', :count => 2)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "fails if matched node count equals expected count" do
|
51
|
+
expect do
|
52
|
+
"<h1>Text</h1>".should_not have_css('h1', :count => 1)
|
53
|
+
end.to raise_error(/expected css "h1" not to return anything/)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "on a page or node" do
|
59
|
+
before do
|
60
|
+
visit('/with_html')
|
61
|
+
end
|
62
|
+
|
63
|
+
context "with should" do
|
64
|
+
it "passes if has_css? returns true" do
|
65
|
+
page.should have_css('h1')
|
66
|
+
end
|
67
|
+
|
68
|
+
it "fails if has_css? returns false" do
|
69
|
+
expect do
|
70
|
+
page.should have_css('h1#doesnotexist')
|
71
|
+
end.to raise_error(/expected css "h1#doesnotexist" to return something/)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "with should_not" do
|
76
|
+
it "passes if has_no_css? returns true" do
|
77
|
+
page.should_not have_css('h1#doesnotexist')
|
78
|
+
end
|
79
|
+
|
80
|
+
it "fails if has_no_css? returns false" do
|
81
|
+
expect do
|
82
|
+
page.should_not have_css('h1')
|
83
|
+
end.to raise_error(/expected css "h1" not to return anything/)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "have_xpath matcher" do
|
90
|
+
context "on a string" do
|
91
|
+
context "with should" do
|
92
|
+
it "passes if has_css? returns true" do
|
93
|
+
"<h1>Text</h1>".should have_xpath('//h1')
|
94
|
+
end
|
95
|
+
|
96
|
+
it "fails if has_css? returns false" do
|
97
|
+
expect do
|
98
|
+
"<h1>Text</h1>".should have_xpath('//h2')
|
99
|
+
end.to raise_error(%r(expected xpath "//h2" to return something))
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "with should_not" do
|
104
|
+
it "passes if has_no_css? returns true" do
|
105
|
+
"<h1>Text</h1>".should_not have_xpath('//h2')
|
106
|
+
end
|
107
|
+
|
108
|
+
it "fails if has_no_css? returns false" do
|
109
|
+
expect do
|
110
|
+
"<h1>Text</h1>".should_not have_xpath('//h1')
|
111
|
+
end.to raise_error(%r(expected xpath "//h1" not to return anything))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "on a page or node" do
|
117
|
+
before do
|
118
|
+
visit('/with_html')
|
119
|
+
end
|
120
|
+
|
121
|
+
context "with should" do
|
122
|
+
it "passes if has_css? returns true" do
|
123
|
+
page.should have_xpath('//h1')
|
124
|
+
end
|
125
|
+
|
126
|
+
it "fails if has_css? returns false" do
|
127
|
+
expect do
|
128
|
+
page.should have_xpath("//h1[@id='doesnotexist']")
|
129
|
+
end.to raise_error(%r(expected xpath "//h1\[@id='doesnotexist'\]" to return something))
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "with should_not" do
|
134
|
+
it "passes if has_no_css? returns true" do
|
135
|
+
page.should_not have_xpath('//h1[@id="doesnotexist"]')
|
136
|
+
end
|
137
|
+
|
138
|
+
it "fails if has_no_css? returns false" do
|
139
|
+
expect do
|
140
|
+
page.should_not have_xpath('//h1')
|
141
|
+
end.to raise_error(%r(expected xpath "//h1" not to return anything))
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "have_selector matcher" do
|
148
|
+
context "on a string" do
|
149
|
+
context "with should" do
|
150
|
+
it "passes if has_css? returns true" do
|
151
|
+
"<h1>Text</h1>".should have_selector('//h1')
|
152
|
+
end
|
153
|
+
|
154
|
+
it "fails if has_css? returns false" do
|
155
|
+
expect do
|
156
|
+
"<h1>Text</h1>".should have_selector('//h2')
|
157
|
+
end.to raise_error(%r(expected xpath "//h2" to return something))
|
158
|
+
end
|
159
|
+
|
160
|
+
it "fails with the selector's failure_message if set" do
|
161
|
+
Capybara.add_selector(:monkey) do
|
162
|
+
xpath { |num| ".//*[contains(@id, 'monkey')][#{num}]" }
|
163
|
+
failure_message { |node, selector| node.all(".//*[contains(@id, 'monkey')]").map { |node| node.text }.sort.join(', ') }
|
164
|
+
end
|
165
|
+
expect do
|
166
|
+
'<h1 id="monkey_paul">Monkey John</h1>'.should have_selector(:monkey, 14)
|
167
|
+
end.to raise_error("Monkey John")
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "with should_not" do
|
172
|
+
it "passes if has_no_css? returns true" do
|
173
|
+
"<h1>Text</h1>".should_not have_selector(:css, 'h2')
|
174
|
+
end
|
175
|
+
|
176
|
+
it "fails if has_no_css? returns false" do
|
177
|
+
expect do
|
178
|
+
"<h1>Text</h1>".should_not have_selector(:css, 'h1')
|
179
|
+
end.to raise_error(%r(expected css "h1" not to return anything))
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context "on a page or node" do
|
185
|
+
before do
|
186
|
+
visit('/with_html')
|
187
|
+
end
|
188
|
+
|
189
|
+
context "with should" do
|
190
|
+
it "passes if has_css? returns true" do
|
191
|
+
page.should have_selector('//h1', :text => 'test')
|
192
|
+
end
|
193
|
+
|
194
|
+
it "fails if has_css? returns false" do
|
195
|
+
expect do
|
196
|
+
page.should have_selector("//h1[@id='doesnotexist']")
|
197
|
+
end.to raise_error(%r(expected xpath "//h1\[@id='doesnotexist'\]" to return something))
|
198
|
+
end
|
199
|
+
|
200
|
+
it "includes text in error message" do
|
201
|
+
expect do
|
202
|
+
page.should have_selector("//h1", :text => 'wrong text')
|
203
|
+
end.to raise_error(%r(expected xpath "//h1" with text "wrong text" to return something))
|
204
|
+
end
|
205
|
+
|
206
|
+
it "fails with the selector's failure_message if set" do
|
207
|
+
Capybara.add_selector(:monkey) do
|
208
|
+
xpath { |num| ".//*[contains(@id, 'monkey')][#{num}]" }
|
209
|
+
failure_message { |node, selector| node.all(".//*[contains(@id, 'monkey')]").map { |node| node.text }.sort.join(', ') }
|
210
|
+
end
|
211
|
+
expect do
|
212
|
+
page.should have_selector(:monkey, 14)
|
213
|
+
end.to raise_error("Monkey John, Monkey Paul")
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
context "with should_not" do
|
218
|
+
it "passes if has_no_css? returns true" do
|
219
|
+
page.should_not have_selector(:css, 'h1#doesnotexist')
|
220
|
+
end
|
221
|
+
|
222
|
+
it "fails if has_no_css? returns false" do
|
223
|
+
expect do
|
224
|
+
page.should_not have_selector(:css, 'h1', :text => 'test')
|
225
|
+
end.to raise_error(%r(expected css "h1" with text "test" not to return anything))
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "have_content matcher" do
|
232
|
+
context "on a string" do
|
233
|
+
context "with should" do
|
234
|
+
it "passes if has_css? returns true" do
|
235
|
+
"<h1>Text</h1>".should have_content('Text')
|
236
|
+
end
|
237
|
+
|
238
|
+
it "fails if has_css? returns false" do
|
239
|
+
expect do
|
240
|
+
"<h1>Text</h1>".should have_content('No such Text')
|
241
|
+
end.to raise_error(/expected there to be content "No such Text" in "Text"/)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
context "with should_not" do
|
246
|
+
it "passes if has_no_css? returns true" do
|
247
|
+
"<h1>Text</h1>".should_not have_content('No such Text')
|
248
|
+
end
|
249
|
+
|
250
|
+
it "fails if has_no_css? returns false" do
|
251
|
+
expect do
|
252
|
+
"<h1>Text</h1>".should_not have_content('Text')
|
253
|
+
end.to raise_error(/expected content "Text" not to return anything/)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context "on a page or node" do
|
259
|
+
before do
|
260
|
+
visit('/with_html')
|
261
|
+
end
|
262
|
+
|
263
|
+
context "with should" do
|
264
|
+
it "passes if has_css? returns true" do
|
265
|
+
page.should have_content('This is a test')
|
266
|
+
end
|
267
|
+
|
268
|
+
it "fails if has_css? returns false" do
|
269
|
+
expect do
|
270
|
+
page.should have_content('No such Text')
|
271
|
+
end.to raise_error(/expected there to be content "No such Text" in "(.*)This is a test(.*)"/)
|
272
|
+
end
|
273
|
+
|
274
|
+
context "with default selector CSS" do
|
275
|
+
before { Capybara.default_selector = :css }
|
276
|
+
it "fails if has_css? returns false" do
|
277
|
+
expect do
|
278
|
+
page.should have_content('No such Text')
|
279
|
+
end.to raise_error(/expected there to be content "No such Text" in "(.*)This is a test(.*)"/)
|
280
|
+
end
|
281
|
+
after { Capybara.default_selector = :xpath }
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context "with should_not" do
|
286
|
+
it "passes if has_no_css? returns true" do
|
287
|
+
page.should_not have_content('No such Text')
|
288
|
+
end
|
289
|
+
|
290
|
+
it "fails if has_no_css? returns false" do
|
291
|
+
expect do
|
292
|
+
page.should_not have_content('This is a test')
|
293
|
+
end.to raise_error(/expected content "This is a test" not to return anything/)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
describe "have_link matcher" do
|
300
|
+
let(:html) { '<a href="#">Just a link</a>' }
|
301
|
+
|
302
|
+
it "passes if there is such a button" do
|
303
|
+
html.should have_link('Just a link')
|
304
|
+
end
|
305
|
+
|
306
|
+
it "fails if there is no such button" do
|
307
|
+
expect do
|
308
|
+
html.should have_link('No such Link')
|
309
|
+
end.to raise_error(/expected link "No such Link"/)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
describe "have_button matcher" do
|
314
|
+
let(:html) { '<button>A button</button><input type="submit" value="Another button"/>' }
|
315
|
+
|
316
|
+
it "passes if there is such a button" do
|
317
|
+
html.should have_button('A button')
|
318
|
+
end
|
319
|
+
|
320
|
+
it "fails if there is no such button" do
|
321
|
+
expect do
|
322
|
+
html.should have_button('No such Button')
|
323
|
+
end.to raise_error(/expected button "No such Button"/)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
describe "have_field matcher" do
|
328
|
+
let(:html) { '<p><label>Text field<input type="text"/></label></p>' }
|
329
|
+
|
330
|
+
it "passes if there is such a field" do
|
331
|
+
html.should have_field('Text field')
|
332
|
+
end
|
333
|
+
|
334
|
+
it "fails if there is no such field" do
|
335
|
+
expect do
|
336
|
+
html.should have_field('No such Field')
|
337
|
+
end.to raise_error(/expected field "No such Field"/)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
describe "have_checked_field matcher" do
|
342
|
+
let(:html) do
|
343
|
+
'<label>it is checked<input type="checkbox" checked="checked"/></label>
|
344
|
+
<label>unchecked field<input type="checkbox"/></label>'
|
345
|
+
end
|
346
|
+
|
347
|
+
context "with should" do
|
348
|
+
it "passes if there is such a field and it is checked" do
|
349
|
+
html.should have_checked_field('it is checked')
|
350
|
+
end
|
351
|
+
|
352
|
+
it "fails if there is such a field but it is not checked" do
|
353
|
+
expect do
|
354
|
+
html.should have_checked_field('unchecked field')
|
355
|
+
end.to raise_error(/expected checked_field "unchecked field"/)
|
356
|
+
end
|
357
|
+
|
358
|
+
it "fails if there is no such field" do
|
359
|
+
expect do
|
360
|
+
html.should have_checked_field('no such field')
|
361
|
+
end.to raise_error(/expected checked_field "no such field"/)
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
context "with should not" do
|
366
|
+
it "fails if there is such a field and it is checked" do
|
367
|
+
expect do
|
368
|
+
html.should_not have_checked_field('it is checked')
|
369
|
+
end.to raise_error(/expected checked_field "it is checked" not to return anything/)
|
370
|
+
end
|
371
|
+
|
372
|
+
it "passes if there is such a field but it is not checked" do
|
373
|
+
html.should_not have_checked_field('unchecked field')
|
374
|
+
end
|
375
|
+
|
376
|
+
it "passes if there is no such field" do
|
377
|
+
html.should_not have_checked_field('no such field')
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
describe "have_unchecked_field matcher" do
|
383
|
+
let(:html) do
|
384
|
+
'<label>it is checked<input type="checkbox" checked="checked"/></label>
|
385
|
+
<label>unchecked field<input type="checkbox"/></label>'
|
386
|
+
end
|
387
|
+
|
388
|
+
context "with should" do
|
389
|
+
it "passes if there is such a field and it is not checked" do
|
390
|
+
html.should have_unchecked_field('unchecked field')
|
391
|
+
end
|
392
|
+
|
393
|
+
it "fails if there is such a field but it is checked" do
|
394
|
+
expect do
|
395
|
+
html.should have_unchecked_field('it is checked')
|
396
|
+
end.to raise_error(/expected unchecked_field "it is checked"/)
|
397
|
+
end
|
398
|
+
|
399
|
+
it "fails if there is no such field" do
|
400
|
+
expect do
|
401
|
+
html.should have_unchecked_field('no such field')
|
402
|
+
end.to raise_error(/expected unchecked_field "no such field"/)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
context "with should not" do
|
407
|
+
it "fails if there is such a field and it is not checked" do
|
408
|
+
expect do
|
409
|
+
html.should_not have_unchecked_field('unchecked field')
|
410
|
+
end.to raise_error(/expected unchecked_field "unchecked field" not to return anything/)
|
411
|
+
end
|
412
|
+
|
413
|
+
it "passes if there is such a field but it is checked" do
|
414
|
+
html.should_not have_unchecked_field('it is checked')
|
415
|
+
end
|
416
|
+
|
417
|
+
it "passes if there is no such field" do
|
418
|
+
html.should_not have_unchecked_field('no such field')
|
419
|
+
end
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
describe "have_select matcher" do
|
424
|
+
let(:html) { '<label>Select Box<select></select></label>' }
|
425
|
+
|
426
|
+
it "passes if there is such a select" do
|
427
|
+
html.should have_select('Select Box')
|
428
|
+
end
|
429
|
+
|
430
|
+
it "fails if there is no such select" do
|
431
|
+
expect do
|
432
|
+
html.should have_select('No such Select box')
|
433
|
+
end.to raise_error(/expected select "No such Select box"/)
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
describe "have_table matcher" do
|
438
|
+
let(:html) { '<table><caption>Lovely table</caption></table>' }
|
439
|
+
|
440
|
+
it "passes if there is such a select" do
|
441
|
+
html.should have_table('Lovely table')
|
442
|
+
end
|
443
|
+
|
444
|
+
it "fails if there is no such select" do
|
445
|
+
expect do
|
446
|
+
html.should have_table('No such Table')
|
447
|
+
end.to raise_error(/expected table "No such Table"/)
|
448
|
+
end
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|