capybara 0.3.9 → 0.4.0.rc

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.
Files changed (70) hide show
  1. data/History.txt +43 -1
  2. data/README.rdoc +168 -98
  3. data/lib/capybara.rb +77 -15
  4. data/lib/capybara/driver/base.rb +21 -16
  5. data/lib/capybara/driver/celerity_driver.rb +39 -41
  6. data/lib/capybara/driver/culerity_driver.rb +2 -1
  7. data/lib/capybara/driver/node.rb +66 -0
  8. data/lib/capybara/driver/rack_test_driver.rb +66 -67
  9. data/lib/capybara/driver/selenium_driver.rb +43 -47
  10. data/lib/capybara/dsl.rb +44 -6
  11. data/lib/capybara/node.rb +185 -24
  12. data/lib/capybara/node/actions.rb +170 -0
  13. data/lib/capybara/node/finders.rb +150 -0
  14. data/lib/capybara/node/matchers.rb +360 -0
  15. data/lib/capybara/rails.rb +1 -0
  16. data/lib/capybara/selector.rb +52 -0
  17. data/lib/capybara/server.rb +68 -87
  18. data/lib/capybara/session.rb +221 -207
  19. data/lib/capybara/spec/driver.rb +45 -35
  20. data/lib/capybara/spec/public/test.js +1 -1
  21. data/lib/capybara/spec/session.rb +28 -53
  22. data/lib/capybara/spec/session/all_spec.rb +7 -3
  23. data/lib/capybara/spec/session/check_spec.rb +50 -52
  24. data/lib/capybara/spec/session/click_button_spec.rb +9 -0
  25. data/lib/capybara/spec/session/click_link_or_button_spec.rb +37 -0
  26. data/lib/capybara/spec/session/current_url_spec.rb +7 -0
  27. data/lib/capybara/spec/session/find_button_spec.rb +4 -2
  28. data/lib/capybara/spec/session/find_by_id_spec.rb +4 -2
  29. data/lib/capybara/spec/session/find_field_spec.rb +7 -3
  30. data/lib/capybara/spec/session/find_link_spec.rb +5 -3
  31. data/lib/capybara/spec/session/find_spec.rb +71 -6
  32. data/lib/capybara/spec/session/has_field_spec.rb +1 -1
  33. data/lib/capybara/spec/session/has_selector_spec.rb +129 -0
  34. data/lib/capybara/spec/session/has_xpath_spec.rb +4 -4
  35. data/lib/capybara/spec/session/javascript.rb +25 -5
  36. data/lib/capybara/spec/session/select_spec.rb +16 -2
  37. data/lib/capybara/spec/session/unselect_spec.rb +8 -1
  38. data/lib/capybara/spec/session/within_spec.rb +5 -5
  39. data/lib/capybara/spec/views/form.erb +65 -1
  40. data/lib/capybara/spec/views/popup_one.erb +8 -0
  41. data/lib/capybara/spec/views/popup_two.erb +8 -0
  42. data/lib/capybara/spec/views/with_html.erb +5 -0
  43. data/lib/capybara/spec/views/within_popups.erb +25 -0
  44. data/lib/capybara/{save_and_open_page.rb → util/save_and_open_page.rb} +3 -3
  45. data/lib/capybara/util/timeout.rb +27 -0
  46. data/lib/capybara/version.rb +1 -1
  47. data/spec/capybara_spec.rb +18 -8
  48. data/spec/driver/celerity_driver_spec.rb +10 -14
  49. data/spec/driver/culerity_driver_spec.rb +4 -3
  50. data/spec/driver/rack_test_driver_spec.rb +39 -2
  51. data/spec/driver/remote_culerity_driver_spec.rb +5 -7
  52. data/spec/driver/remote_selenium_driver_spec.rb +7 -10
  53. data/spec/driver/selenium_driver_spec.rb +3 -2
  54. data/spec/dsl_spec.rb +5 -14
  55. data/spec/save_and_open_page_spec.rb +19 -19
  56. data/spec/server_spec.rb +22 -10
  57. data/spec/session/celerity_session_spec.rb +17 -21
  58. data/spec/session/culerity_session_spec.rb +3 -3
  59. data/spec/session/rack_test_session_spec.rb +2 -2
  60. data/spec/session/selenium_session_spec.rb +2 -2
  61. data/spec/spec_helper.rb +27 -6
  62. data/spec/{wait_until_spec.rb → timeout_spec.rb} +14 -14
  63. metadata +88 -46
  64. data/lib/capybara/searchable.rb +0 -54
  65. data/lib/capybara/spec/session/click_spec.rb +0 -24
  66. data/lib/capybara/spec/session/locate_spec.rb +0 -65
  67. data/lib/capybara/wait_until.rb +0 -28
  68. data/lib/capybara/xpath.rb +0 -179
  69. data/spec/searchable_spec.rb +0 -66
  70. data/spec/xpath_spec.rb +0 -180
@@ -12,6 +12,13 @@ shared_examples_for "unselect" do
12
12
  extract_results(@session)['underwear'].should_not include('Commando')
13
13
  end
14
14
 
15
+ it "should unselect an option without a select box" do
16
+ @session.unselect('Commando')
17
+ @session.click_button('awesome')
18
+ extract_results(@session)['underwear'].should include('Briefs', 'Boxer Briefs')
19
+ extract_results(@session)['underwear'].should_not include('Commando')
20
+ end
21
+
15
22
  it "should unselect an option from a select box by label" do
16
23
  @session.unselect('Commando', :from => 'Underwear')
17
24
  @session.click_button('awesome')
@@ -47,7 +54,7 @@ shared_examples_for "unselect" do
47
54
 
48
55
  context "with an option that doesn't exist" do
49
56
  it "should raise an error" do
50
- running { @session.unselect('Does not Exist', :from => 'form_underwear') }.should raise_error(Capybara::OptionNotFound)
57
+ running { @session.unselect('Does not Exist', :from => 'form_underwear') }.should raise_error(Capybara::ElementNotFound)
51
58
  end
52
59
  end
53
60
  end
@@ -53,7 +53,7 @@ shared_examples_for "within" do
53
53
  context "with nested scopes" do
54
54
  it "should respect the inner scope" do
55
55
  @session.within("//div[@id='for_bar']") do
56
- @session.within("//li[contains(.,'Bar')]") do
56
+ @session.within(".//li[contains(.,'Bar')]") do
57
57
  @session.click_link('Go')
58
58
  end
59
59
  end
@@ -62,7 +62,7 @@ shared_examples_for "within" do
62
62
 
63
63
  it "should respect the outer scope" do
64
64
  @session.within("//div[@id='another_foo']") do
65
- @session.within("//li[contains(.,'With Simple HTML')]") do
65
+ @session.within(".//li[contains(.,'With Simple HTML')]") do
66
66
  @session.click_link('Go')
67
67
  end
68
68
  end
@@ -82,12 +82,12 @@ shared_examples_for "within" do
82
82
  @session.within("//div[@id='for_bar']") do
83
83
  running {
84
84
  running {
85
- @session.within("//div[@id='doesnotexist']") do
85
+ @session.within(".//div[@id='doesnotexist']") do
86
86
  end
87
87
  }.should raise_error(Capybara::ElementNotFound)
88
- }.should_not change { @session.has_xpath?("//div[@id='another_foo']") }.from(false)
88
+ }.should_not change { @session.has_xpath?(".//div[@id='another_foo']") }.from(false)
89
89
  end
90
- }.should_not change { @session.has_xpath?("//div[@id='another_foo']") }.from(true)
90
+ }.should_not change { @session.has_xpath?(".//div[@id='another_foo']") }.from(true)
91
91
  end
92
92
  end
93
93
 
@@ -155,8 +155,27 @@
155
155
  <option selected="selected">Briefs</option>
156
156
  <option selected="selected">Commando</option>
157
157
  <option selected="selected">Frenchman's Pantalons</option>
158
+ <option selected="selected" value="thermal">Long Johns</option>
158
159
  </select>
159
160
  </p>
161
+
162
+ <p>
163
+ <span>First address<span>
164
+ <label for='address1_street'>Street</label>
165
+ <input type="text" name="form[addresses][][street]" value="" id="address1_street">
166
+
167
+ <label for='address1_city'>City</label>
168
+ <input type="text" name="form[addresses][][city]" value="" id="address1_city">
169
+ </p>
170
+
171
+ <p>
172
+ <span>Second address<span>
173
+ <label for='address2_street'>Street</label>
174
+ <input type="text" name="form[addresses][][street]" value="" id="address2_street">
175
+
176
+ <label for='address2_city'>City</label>
177
+ <input type="text" name="form[addresses][][city]" value="" id="address2_city">
178
+ </p>
160
179
 
161
180
  <div style="display:none;">
162
181
  <label for="form_first_name_hidden">
@@ -165,6 +184,50 @@
165
184
  </label>
166
185
  </div>
167
186
 
187
+ <p>
188
+ <label for="form_disabled_text_field">
189
+ Disabled Text Field
190
+ <input type="text" name="form[disabled_text_field]" value="Should not see me" id="form_disabled_text_field" disabled="disabled" />
191
+ </label>
192
+ </p>
193
+
194
+ <p>
195
+ <label for="form_disabled_textarea">
196
+ Disabled Textarea
197
+ <textarea name="form[disabled_textarea]" value="Should not see me" id="form_disabled_textarea" disabled="disabled"></textarea>
198
+ </label>
199
+ </p>
200
+
201
+ <p>
202
+ <label for="form_disabled_checkbox">
203
+ Disabled Checkbox
204
+ <input type="checkbox" name="form[disabled_checkbox]" value="Should not see me" id="form_disabled_checkbox" checked="checked" disabled="disabled" />
205
+ </label>
206
+ </p>
207
+
208
+ <p>
209
+ <label for="form_disabled_radio">
210
+ Disabled Checkbox
211
+ <input type="radio" name="form[disabled_radio]" value="Should not see me" id="form_disabled_radio" checked="checked" disabled="disabled" />
212
+ </label>
213
+ </p>
214
+
215
+ <p>
216
+ <label for="form_disabled_select">
217
+ Disabled Select
218
+ <select name="form[disabled_select]" id="form_disabled_select" disabled="disabled">
219
+ <option value="Should not see me" selected="selected">Should not see me</option>
220
+ </select>
221
+ </label>
222
+ </p>
223
+
224
+ <p>
225
+ <label for="form_disabled_file">
226
+ Disabled File
227
+ <input type="file" name="form[disabled_file]" value="/should/not/see/me" id="form_disabled_file" disabled="disabled" />
228
+ </label>
229
+ </p>
230
+
168
231
  <p>
169
232
  <input type="button" name="form[fresh]" id="fresh_btn" value="i am fresh"/>
170
233
  <input type="submit" name="form[awesome]" id="awe123" value="awesome"/>
@@ -172,10 +235,11 @@
172
235
  <input type="image" name="form[okay]" id="okay556" value="okay" alt="oh hai thar"/>
173
236
  <button type="submit" id="click_me_123" value="click_me">Click me!</button>
174
237
  <button type="submit" name="form[no_value]">No Value!</button>
238
+ <button id="no_type">No Type!</button>
175
239
  </p>
176
240
  </form>
177
241
 
178
- <form action="/form/get?foo=bar" method="get">
242
+ <form id="get-form" action="/form/get?foo=bar" method="get">
179
243
  <p>
180
244
  <label for="form_middle_name">Middle Name</label>
181
245
  <input type="text" name="form[middle_name]" value="Darren" id="form_middle_name"/>
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <head>
3
+ <title>This is the title of the first popup</title>
4
+ </head>
5
+ <body>
6
+ <div id="divInPopupOne">This is the text of divInPopupOne</div>
7
+ </body>
8
+ </html>
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <head>
3
+ <title>This is the title of popup two</title>
4
+ </head>
5
+ <body>
6
+ <div id="divInPopupTwo">This is the text of divInPopupTwo</div>
7
+ </body>
8
+ </html>
@@ -41,3 +41,8 @@
41
41
  <div id="hidden_via_ancestor">Inside element with hidden ancestor</div>
42
42
  <a href="/with_simple_html" title="awesome title" class="simple">hidden link</a>
43
43
  </div>
44
+
45
+ <ul>
46
+ <li id="john_monkey">Monkey John</li>
47
+ <li id="paul_monkey">Monkey Paul</li>
48
+ </ul>
@@ -0,0 +1,25 @@
1
+ <html>
2
+ <head>
3
+ <title>With Popups</title>
4
+ <script language="javascript" type="text/javascript">
5
+ <!--
6
+
7
+ function popItUp(name, url) {
8
+ newwindow=window.open(url,name,'height=200,width=150');
9
+ if (window.focus) { newwindow.focus() }
10
+ return false;
11
+ }
12
+
13
+ function init() {
14
+ popItUp('firstPopup', '/popup_one');
15
+ popItUp('secondPopup', '/popup_two');
16
+ }
17
+ window.onload = init;
18
+
19
+ // -->
20
+ </script>
21
+ </head>
22
+ <body>
23
+ <div id="divInMainWindow">This is the text for divInMainWindow</div>
24
+ </body>
25
+ </html>
@@ -1,7 +1,5 @@
1
1
  module Capybara
2
- module SaveAndOpenPage
3
- extend(self)
4
-
2
+ class << self
5
3
  def save_and_open_page(html)
6
4
  name = File.join(*[Capybara.save_and_open_page_path, "capybara-#{Time.new.strftime("%Y%m%d%H%M%S")}.html"].compact)
7
5
 
@@ -17,6 +15,8 @@ module Capybara
17
15
  open_in_browser(tempfile.path)
18
16
  end
19
17
 
18
+ protected
19
+
20
20
  def open_in_browser(path) # :nodoc
21
21
  require "launchy"
22
22
  Launchy::Browser.run(path)
@@ -0,0 +1,27 @@
1
+ module Capybara
2
+ class << self
3
+
4
+ ##
5
+ # Provides timeout similar to standard library Timeout, but avoids threads
6
+ #
7
+ def timeout(seconds = 1, driver = nil, &block)
8
+ start_time = Time.now
9
+
10
+ result = nil
11
+
12
+ until result
13
+ return result if result = yield
14
+
15
+ delay = seconds - (Time.now - start_time)
16
+ if delay <= 0
17
+ raise TimeoutError
18
+ end
19
+
20
+ driver && driver.wait_until(delay)
21
+
22
+ sleep(0.05)
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module Capybara
2
- VERSION = '0.3.9'
2
+ VERSION = '0.4.0.rc'
3
3
  end
@@ -1,18 +1,28 @@
1
- require File.expand_path('spec_helper', File.dirname(__FILE__))
2
-
3
- require 'capybara'
1
+ require 'spec_helper'
4
2
 
5
3
  describe Capybara do
6
-
4
+
7
5
  describe 'default_wait_time' do
8
6
  after do
9
- Capybara.default_wait_time = 2
7
+ Capybara.default_wait_time = @previous_default_time
10
8
  end
11
-
9
+
12
10
  it "should be changeable" do
11
+ @previous_default_time = Capybara.default_wait_time
13
12
  Capybara.default_wait_time = 5
14
13
  Capybara.default_wait_time.should == 5
15
14
  end
16
15
  end
17
-
18
- end
16
+
17
+ describe '.register_driver' do
18
+ it "should add a new driver" do
19
+ Capybara.register_driver :schmoo do |app|
20
+ Capybara::Driver::RackTest.new(app)
21
+ end
22
+ session = Capybara::Session.new(:schmoo, TestApp)
23
+ session.visit('/')
24
+ session.body.should include("Hello world!")
25
+ end
26
+ end
27
+
28
+ end
@@ -1,17 +1,13 @@
1
- require File.expand_path('../spec_helper', File.dirname(__FILE__))
1
+ require 'spec_helper'
2
2
 
3
- if RUBY_PLATFORM =~ /java/
4
- describe Capybara::Driver::Celerity do
5
- before(:all) do
6
- @driver = Capybara::Driver::Celerity.new(TestApp)
7
- end
8
-
9
- it_should_behave_like "driver"
10
- it_should_behave_like "driver with javascript support"
11
- it_should_behave_like "driver with header support"
12
- it_should_behave_like "driver with status code support"
13
- it_should_behave_like "driver with cookies support"
3
+ describe Capybara::Driver::Celerity, :jruby => :platform do
4
+ before(:all) do
5
+ @driver = TestSessions::Celerity.driver
14
6
  end
15
- else
16
- puts "#{File.basename(__FILE__)} requires JRuby; skipping.."
7
+
8
+ it_should_behave_like "driver"
9
+ it_should_behave_like "driver with javascript support"
10
+ it_should_behave_like "driver with header support"
11
+ it_should_behave_like "driver with status code support"
12
+ it_should_behave_like "driver with cookies support"
17
13
  end
@@ -1,8 +1,9 @@
1
- require File.expand_path('../spec_helper', File.dirname(__FILE__))
1
+ require 'spec_helper'
2
+
3
+ describe Capybara::Driver::Culerity, :jruby => :installed do
2
4
 
3
- describe Capybara::Driver::Culerity do
4
5
  before(:all) do
5
- @driver = Capybara::Driver::Culerity.new(TestApp)
6
+ @driver = TestSessions::Culerity.driver
6
7
  end
7
8
 
8
9
  it_should_behave_like "driver"
@@ -1,8 +1,22 @@
1
- require File.expand_path('../spec_helper', File.dirname(__FILE__))
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'stringio'
4
+
5
+ def capture(*streams)
6
+ streams.map! { |stream| stream.to_s }
7
+ begin
8
+ result = StringIO.new
9
+ streams.each { |stream| eval "$#{stream} = result" }
10
+ yield
11
+ ensure
12
+ streams.each { |stream| eval("$#{stream} = #{stream.upcase}") }
13
+ end
14
+ result.string
15
+ end
2
16
 
3
17
  describe Capybara::Driver::RackTest do
4
18
  before do
5
- @driver = Capybara::Driver::RackTest.new(TestApp)
19
+ @driver = TestSessions::RackTest.driver
6
20
  end
7
21
 
8
22
  it "should throw an error when no rack app is given" do
@@ -11,6 +25,29 @@ describe Capybara::Driver::RackTest do
11
25
  end.should raise_error(ArgumentError)
12
26
  end
13
27
 
28
+ if '1.9'.respond_to?(:encode)
29
+ describe "with non-binary parameters" do
30
+
31
+ it "should convert attribute values to binary" do
32
+ output = capture(:stderr) {
33
+ @driver.visit('/mypage', :param => 'µ')
34
+ }.should_not =~ %r{warning: regexp match /.../n against to UTF-8 string}
35
+ end
36
+
37
+ it "should convert attribute with Array to binary" do
38
+ output = capture(:stderr) {
39
+ @driver.visit('/mypage', :param => ['µ'])
40
+ }.should_not =~ %r{warning: regexp match /.../n against to UTF-8 string}
41
+ end
42
+
43
+ it "should convert path to binary" do
44
+ output = capture(:stderr) {
45
+ @driver.visit('/mypage'.encode('utf-8'))
46
+ }.should_not =~ %r{warning: regexp match /.../n against to UTF-8 string}
47
+ end
48
+ end
49
+ end
50
+
14
51
  it_should_behave_like "driver"
15
52
  it_should_behave_like "driver with header support"
16
53
  it_should_behave_like "driver with status code support"
@@ -1,22 +1,20 @@
1
- require File.expand_path('../spec_helper', File.dirname(__FILE__))
1
+ require 'spec_helper'
2
2
 
3
- describe Capybara::Driver::Culerity do
3
+ describe Capybara::Driver::Culerity, :jruby => :installed do
4
4
  before(:all) do
5
5
  Capybara.app_host = "http://capybara-testapp.heroku.com"
6
- Capybara.run_server = false
7
- @driver = Capybara::Driver::Culerity.new(TestApp)
6
+ @driver = TestSessions::Culerity.driver
8
7
  end
9
-
8
+
10
9
  after(:all) do
11
10
  Capybara.app_host = nil
12
- Capybara.run_server = true
13
11
  end
14
12
 
15
13
  it "should navigate to a fully qualified remote page" do
16
14
  @driver.visit('http://capybara-testapp.heroku.com/foo')
17
15
  @driver.body.should include('Another World')
18
16
  end
19
-
17
+
20
18
  it_should_behave_like "driver"
21
19
  it_should_behave_like "driver with javascript support"
22
20
  it_should_behave_like "driver with header support"
@@ -1,19 +1,16 @@
1
- require File.expand_path('../spec_helper', File.dirname(__FILE__))
1
+ require 'spec_helper'
2
2
 
3
3
  describe Capybara::Driver::Selenium do
4
- before(:all) do
5
- Capybara.app_host = "http://capybara-testapp.heroku.com"
6
- end
7
-
8
- after(:all) do
9
- Capybara.app_host = nil
4
+ before do
5
+ #Capybara.app_host = "http://capybara-testapp.heroku.com"
6
+ @driver = TestSessions::Selenium.driver
10
7
  end
11
8
 
12
- before do
13
- @driver = Capybara::Driver::Selenium.new(TestApp)
9
+ after do
10
+ Capybara.app_host = nil
14
11
  end
15
12
 
16
13
  it_should_behave_like "driver"
17
14
  it_should_behave_like "driver with javascript support"
18
15
  it_should_behave_like "driver without status code support"
19
- end
16
+ end