capybara 0.4.1.2 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/History.txt +46 -0
  2. data/README.rdoc +211 -64
  3. data/lib/capybara.rb +31 -15
  4. data/lib/capybara/cucumber.rb +12 -16
  5. data/lib/capybara/dsl.rb +65 -28
  6. data/lib/capybara/node/actions.rb +7 -5
  7. data/lib/capybara/node/document.rb +8 -0
  8. data/lib/capybara/node/finders.rb +11 -7
  9. data/lib/capybara/node/matchers.rb +32 -6
  10. data/lib/capybara/node/simple.rb +20 -0
  11. data/lib/capybara/rack_test/browser.rb +115 -0
  12. data/lib/capybara/rack_test/driver.rb +77 -0
  13. data/lib/capybara/rack_test/form.rb +80 -0
  14. data/lib/capybara/rack_test/node.rb +101 -0
  15. data/lib/capybara/rspec.rb +11 -3
  16. data/lib/capybara/rspec/features.rb +22 -0
  17. data/lib/capybara/rspec/matchers.rb +146 -0
  18. data/lib/capybara/selector.rb +27 -8
  19. data/lib/capybara/selenium/driver.rb +148 -0
  20. data/lib/capybara/selenium/node.rb +91 -0
  21. data/lib/capybara/session.rb +42 -15
  22. data/lib/capybara/spec/driver.rb +55 -1
  23. data/lib/capybara/spec/fixtures/capybara.jpg +0 -0
  24. data/lib/capybara/spec/public/test.js +7 -2
  25. data/lib/capybara/spec/session.rb +51 -7
  26. data/lib/capybara/spec/session/attach_file_spec.rb +9 -6
  27. data/lib/capybara/spec/session/click_button_spec.rb +35 -0
  28. data/lib/capybara/spec/session/current_host_spec.rb +62 -0
  29. data/lib/capybara/spec/session/fill_in_spec.rb +6 -0
  30. data/lib/capybara/spec/session/find_spec.rb +23 -1
  31. data/lib/capybara/spec/session/first_spec.rb +39 -6
  32. data/lib/capybara/spec/session/has_css_spec.rb +30 -0
  33. data/lib/capybara/spec/session/has_field_spec.rb +47 -11
  34. data/lib/capybara/spec/session/javascript.rb +0 -1
  35. data/lib/capybara/spec/session/text_spec.rb +19 -0
  36. data/lib/capybara/spec/test_app.rb +9 -0
  37. data/lib/capybara/spec/views/form.erb +8 -3
  38. data/lib/capybara/spec/views/header_links.erb +7 -0
  39. data/lib/capybara/spec/views/host_links.erb +12 -0
  40. data/lib/capybara/spec/views/with_html.erb +6 -2
  41. data/lib/capybara/spec/views/with_html_entities.erb +1 -0
  42. data/lib/capybara/spec/views/with_js.erb +4 -0
  43. data/lib/capybara/util/save_and_open_page.rb +7 -3
  44. data/lib/capybara/util/timeout.rb +2 -2
  45. data/lib/capybara/version.rb +1 -1
  46. data/spec/capybara_spec.rb +1 -1
  47. data/spec/driver/rack_test_driver_spec.rb +24 -2
  48. data/spec/driver/selenium_driver_spec.rb +2 -1
  49. data/spec/dsl_spec.rb +56 -4
  50. data/spec/rspec/features_spec.rb +45 -0
  51. data/spec/rspec/matchers_spec.rb +451 -0
  52. data/spec/rspec_spec.rb +9 -2
  53. data/spec/save_and_open_page_spec.rb +9 -13
  54. data/spec/server_spec.rb +4 -0
  55. data/spec/session/rack_test_session_spec.rb +2 -2
  56. data/spec/session/selenium_session_spec.rb +1 -1
  57. data/spec/spec_helper.rb +0 -14
  58. data/spec/string_spec.rb +1 -1
  59. metadata +60 -69
  60. data/lib/capybara/driver/celerity_driver.rb +0 -164
  61. data/lib/capybara/driver/culerity_driver.rb +0 -26
  62. data/lib/capybara/driver/rack_test_driver.rb +0 -303
  63. data/lib/capybara/driver/selenium_driver.rb +0 -161
  64. data/spec/driver/celerity_driver_spec.rb +0 -13
  65. data/spec/driver/culerity_driver_spec.rb +0 -14
  66. data/spec/driver/remote_culerity_driver_spec.rb +0 -22
  67. data/spec/driver/remote_selenium_driver_spec.rb +0 -16
  68. data/spec/session/celerity_session_spec.rb +0 -24
  69. 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,7 @@
1
+ <p>
2
+ <a href="/get_header">Link</a>
3
+ </p>
4
+
5
+ <form action="/get_header" method="get">
6
+ <p><input type="submit" value="Post"/></p>
7
+ </form>
@@ -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="visibility">hidden link</a>
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 &mdash; html entities &raquo;
@@ -34,6 +34,10 @@
34
34
  <p>
35
35
  <input type="checkbox" id="checkbox_with_event"/>
36
36
  </p>
37
+
38
+ <p>
39
+ <input type="submit" id="fire_ajax_request" value="Fire Ajax Request"/>
40
+ </p>
37
41
  </body>
38
42
  </html>
39
43
 
@@ -1,7 +1,8 @@
1
1
  module Capybara
2
2
  class << self
3
- def save_and_open_page(html)
4
- name = File.join(*[Capybara.save_and_open_page_path, "capybara-#{Time.new.strftime("%Y%m%d%H%M%S")}.html"].compact)
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
- open_in_browser(tempfile.path)
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)
@@ -1,3 +1,3 @@
1
1
  module Capybara
2
- VERSION = '0.4.1.2'
2
+ VERSION = '1.0.0.beta1'
3
3
  end
@@ -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::RackTest.new(app)
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::RackTest do
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::RackTest.new(nil)
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::Selenium do
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"
@@ -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
+