capybara 0.4.0 → 0.4.1.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/History.txt +35 -0
  2. data/README.rdoc +60 -19
  3. data/lib/capybara.rb +81 -5
  4. data/lib/capybara/driver/base.rb +1 -6
  5. data/lib/capybara/driver/celerity_driver.rb +19 -9
  6. data/lib/capybara/driver/node.rb +8 -0
  7. data/lib/capybara/driver/rack_test_driver.rb +42 -29
  8. data/lib/capybara/driver/selenium_driver.rb +11 -3
  9. data/lib/capybara/dsl.rb +11 -0
  10. data/lib/capybara/node/actions.rb +4 -14
  11. data/lib/capybara/node/base.rb +47 -0
  12. data/lib/capybara/node/document.rb +17 -0
  13. data/lib/capybara/node/element.rb +178 -0
  14. data/lib/capybara/node/finders.rb +78 -27
  15. data/lib/capybara/node/matchers.rb +40 -11
  16. data/lib/capybara/node/simple.rb +116 -0
  17. data/lib/capybara/rspec.rb +18 -0
  18. data/lib/capybara/server.rb +5 -10
  19. data/lib/capybara/session.rb +7 -16
  20. data/lib/capybara/spec/driver.rb +16 -1
  21. data/lib/capybara/spec/session.rb +1 -0
  22. data/lib/capybara/spec/session/all_spec.rb +5 -0
  23. data/lib/capybara/spec/session/attach_file_spec.rb +6 -0
  24. data/lib/capybara/spec/session/click_link_or_button_spec.rb +2 -3
  25. data/lib/capybara/spec/session/find_spec.rb +0 -6
  26. data/lib/capybara/spec/session/first_spec.rb +72 -0
  27. data/lib/capybara/spec/session/has_css_spec.rb +107 -1
  28. data/lib/capybara/spec/session/has_field_spec.rb +60 -0
  29. data/lib/capybara/spec/session/has_select_spec.rb +40 -0
  30. data/lib/capybara/spec/session/javascript.rb +4 -13
  31. data/lib/capybara/spec/session/within_spec.rb +10 -3
  32. data/lib/capybara/spec/test_app.rb +20 -1
  33. data/lib/capybara/spec/views/form.erb +27 -0
  34. data/lib/capybara/spec/views/with_html.erb +21 -5
  35. data/lib/capybara/util/save_and_open_page.rb +8 -5
  36. data/lib/capybara/version.rb +1 -1
  37. data/spec/basic_node_spec.rb +77 -0
  38. data/spec/capybara_spec.rb +18 -0
  39. data/spec/dsl_spec.rb +26 -0
  40. data/spec/rspec_spec.rb +47 -0
  41. data/spec/save_and_open_page_spec.rb +83 -7
  42. data/spec/server_spec.rb +20 -0
  43. data/spec/session/rack_test_session_spec.rb +10 -0
  44. data/spec/string_spec.rb +77 -0
  45. metadata +306 -295
  46. data/lib/capybara/node.rb +0 -221
@@ -22,13 +22,30 @@ shared_examples_for "has_css" do
22
22
  end
23
23
  end
24
24
 
25
+ context "with between" do
26
+ it "should be true if the content occurs within the range given" do
27
+ @session.should have_css("p", :between => 1..4)
28
+ @session.should have_css("p a#foo", :between => 1..3)
29
+ end
30
+
31
+ it "should be false if the content occurs more or fewer times than range" do
32
+ @session.should_not have_css("p", :between => 6..11 )
33
+ @session.should_not have_css("p a#foo", :between => 4..7)
34
+ end
35
+
36
+ it "should be false if the content isn't on the page at all" do
37
+ @session.should_not have_css("abbr", :between => 1..8)
38
+ @session.should_not have_css("p a.doesnotexist", :between => 3..8)
39
+ end
40
+ end
41
+
25
42
  context "with count" do
26
43
  it "should be true if the content is on the page the given number of times" do
27
44
  @session.should have_css("p", :count => 3)
28
45
  @session.should have_css("p a#foo", :count => 1)
29
46
  end
30
47
 
31
- it "should be false if the content is on the page the given number of times" do
48
+ it "should be false if the content occurs the given number of times" do
32
49
  @session.should_not have_css("p", :count => 6)
33
50
  @session.should_not have_css("p a#foo", :count => 2)
34
51
  end
@@ -39,6 +56,42 @@ shared_examples_for "has_css" do
39
56
  end
40
57
  end
41
58
 
59
+ context "with maximum" do
60
+ it "should be true when content occurs same or fewer times than given" do
61
+ @session.should have_css("h2.head", :maximum => 5) # edge case
62
+ @session.should have_css("h2", :maximum => 10)
63
+ end
64
+
65
+ it "should be false when content occurs more times than given" do
66
+ @session.should_not have_css("h2.head", :maximum => 4) # edge case
67
+ @session.should_not have_css("h2", :maximum => 6)
68
+ @session.should_not have_css("p", :maximum => 1)
69
+ end
70
+
71
+ it "should be false if the content isn't on the page at all" do
72
+ @session.should_not have_css("abbr", :maximum => 2)
73
+ @session.should_not have_css("p a.doesnotexist", :maximum => 1)
74
+ end
75
+ end
76
+
77
+ context "with minimum" do
78
+ it "should be true when content occurs same or more times than given" do
79
+ @session.should have_css("h2.head", :minimum => 5) # edge case
80
+ @session.should have_css("h2", :minimum => 3)
81
+ end
82
+
83
+ it "should be false when content occurs fewer times than given" do
84
+ @session.should_not have_css("h2.head", :minimum => 6) # edge case
85
+ @session.should_not have_css("h2", :minimum => 8)
86
+ @session.should_not have_css("p", :minimum => 10)
87
+ end
88
+
89
+ it "should be false if the content isn't on the page at all" do
90
+ @session.should_not have_css("abbr", :minimum => 2)
91
+ @session.should_not have_css("p a.doesnotexist", :minimum => 7)
92
+ end
93
+ end
94
+
42
95
  context "with text" do
43
96
  it "should discard all matches where the given string is not contained" do
44
97
  @session.should have_css("p a", :text => "Redirect", :count => 1)
@@ -75,6 +128,23 @@ shared_examples_for "has_css" do
75
128
  end
76
129
  end
77
130
 
131
+ context "with between" do
132
+ it "should be false if the content occurs within the range given" do
133
+ @session.should_not have_no_css("p", :between => 1..4)
134
+ @session.should_not have_no_css("p a#foo", :between => 1..3)
135
+ end
136
+
137
+ it "should be true if the content occurs more or fewer times than range" do
138
+ @session.should have_no_css("p", :between => 6..11 )
139
+ @session.should have_no_css("p a#foo", :between => 4..7)
140
+ end
141
+
142
+ it "should be true if the content isn't on the page at all" do
143
+ @session.should have_no_css("abbr", :between => 1..8)
144
+ @session.should have_no_css("p a.doesnotexist", :between => 3..8)
145
+ end
146
+ end
147
+
78
148
  context "with count" do
79
149
  it "should be false if the content is on the page the given number of times" do
80
150
  @session.should_not have_no_css("p", :count => 3)
@@ -92,6 +162,42 @@ shared_examples_for "has_css" do
92
162
  end
93
163
  end
94
164
 
165
+ context "with maximum" do
166
+ it "should be false when content occurs same or fewer times than given" do
167
+ @session.should_not have_no_css("h2.head", :maximum => 5) # edge case
168
+ @session.should_not have_no_css("h2", :maximum => 10)
169
+ end
170
+
171
+ it "should be true when content occurs more times than given" do
172
+ @session.should have_no_css("h2.head", :maximum => 4) # edge case
173
+ @session.should have_no_css("h2", :maximum => 6)
174
+ @session.should have_no_css("p", :maximum => 1)
175
+ end
176
+
177
+ it "should be true if the content isn't on the page at all" do
178
+ @session.should have_no_css("abbr", :maximum => 5)
179
+ @session.should have_no_css("p a.doesnotexist", :maximum => 10)
180
+ end
181
+ end
182
+
183
+ context "with minimum" do
184
+ it "should be false when content occurs more times than given" do
185
+ @session.should_not have_no_css("h2.head", :minimum => 4) # edge case
186
+ @session.should_not have_no_css("h2", :minimum => 3)
187
+ end
188
+
189
+ it "should be true when content occurs fewer times than given" do
190
+ @session.should have_no_css("h2.head", :minimum => 6) # edge case
191
+ @session.should have_no_css("h2", :minimum => 8)
192
+ @session.should have_no_css("p", :minimum => 15)
193
+ end
194
+
195
+ it "should be true if the content isn't on the page at all" do
196
+ @session.should have_no_css("abbr", :minimum => 5)
197
+ @session.should have_no_css("p a.doesnotexist", :minimum => 10)
198
+ end
199
+ end
200
+
95
201
  context "with text" do
96
202
  it "should discard all matches where the given string is not contained" do
97
203
  @session.should_not have_no_css("p a", :text => "Redirect", :count => 1)
@@ -25,6 +25,16 @@ shared_examples_for "has_field" do
25
25
  @session.should_not have_field('Wrong Name', :with => 'John')
26
26
  @session.should_not have_field('Description', :with => 'Monkey')
27
27
  end
28
+
29
+ it "should be true after the field has been filled in with the given value" do
30
+ @session.fill_in('First Name', :with => 'Jonas')
31
+ @session.should have_field('First Name', :with => 'Jonas')
32
+ end
33
+
34
+ it "should be false after the field has been filled in with a different value" do
35
+ @session.fill_in('First Name', :with => 'Jonas')
36
+ @session.should_not have_field('First Name', :with => 'John')
37
+ end
28
38
  end
29
39
  end
30
40
 
@@ -54,6 +64,16 @@ shared_examples_for "has_field" do
54
64
  @session.should have_no_field('Wrong Name', :with => 'John')
55
65
  @session.should have_no_field('Description', :with => 'Monkey')
56
66
  end
67
+
68
+ it "should be false after the field has been filled in with the given value" do
69
+ @session.fill_in('First Name', :with => 'Jonas')
70
+ @session.should_not have_no_field('First Name', :with => 'Jonas')
71
+ end
72
+
73
+ it "should be true after the field has been filled in with a different value" do
74
+ @session.fill_in('First Name', :with => 'Jonas')
75
+ @session.should have_no_field('First Name', :with => 'John')
76
+ end
57
77
  end
58
78
  end
59
79
 
@@ -73,6 +93,26 @@ shared_examples_for "has_field" do
73
93
  it "should be false if no field is on the page" do
74
94
  @session.should_not have_checked_field('Does Not Exist')
75
95
  end
96
+
97
+ it "should be true after an unchecked checkbox is checked" do
98
+ @session.check('form_pets_cat')
99
+ @session.should have_checked_field('form_pets_cat')
100
+ end
101
+
102
+ it "should be false after a checked checkbox is unchecked" do
103
+ @session.uncheck('form_pets_dog')
104
+ @session.should_not have_checked_field('form_pets_dog')
105
+ end
106
+
107
+ it "should be true after an unchecked radio button is chosen" do
108
+ @session.choose('gender_male')
109
+ @session.should have_checked_field('gender_male')
110
+ end
111
+
112
+ it "should be false after another radio button in the group is chosen" do
113
+ @session.choose('gender_male')
114
+ @session.should_not have_checked_field('gender_female')
115
+ end
76
116
  end
77
117
 
78
118
  describe '#has_unchecked_field?' do
@@ -91,6 +131,26 @@ shared_examples_for "has_field" do
91
131
  it "should be false if no field is on the page" do
92
132
  @session.should_not have_unchecked_field('Does Not Exist')
93
133
  end
134
+
135
+ it "should be false after an unchecked checkbox is checked" do
136
+ @session.check('form_pets_cat')
137
+ @session.should_not have_unchecked_field('form_pets_cat')
138
+ end
139
+
140
+ it "should be true after a checked checkbox is unchecked" do
141
+ @session.uncheck('form_pets_dog')
142
+ @session.should have_unchecked_field('form_pets_dog')
143
+ end
144
+
145
+ it "should be false after an unchecked radio button is chosen" do
146
+ @session.choose('gender_male')
147
+ @session.should_not have_unchecked_field('gender_male')
148
+ end
149
+
150
+ it "should be true after another radio button in the group is chosen" do
151
+ @session.choose('gender_male')
152
+ @session.should have_unchecked_field('gender_female')
153
+ end
94
154
  end
95
155
  end
96
156
 
@@ -26,6 +26,26 @@ shared_examples_for "has_select" do
26
26
  @session.should_not have_select('Underwear', :selected => ['Briefs', 'Nonexistant'])
27
27
  @session.should_not have_select('Underwear', :selected => ['Briefs', 'Boxers'])
28
28
  end
29
+
30
+ it "should be true after the given value is selected" do
31
+ @session.select('Swedish', :from => 'Locale')
32
+ @session.should have_select('Locale', :selected => 'Swedish')
33
+ end
34
+
35
+ it "should be false after a different value is selected" do
36
+ @session.select('Swedish', :from => 'Locale')
37
+ @session.should_not have_select('Locale', :selected => 'English')
38
+ end
39
+
40
+ it "should be true after the given values are selected" do
41
+ @session.select('Boxers', :from => 'Underwear')
42
+ @session.should have_select('Underwear', :selected => ['Briefs', 'Boxers', 'Commando'])
43
+ end
44
+
45
+ it "should be false after one of the values is unselected" do
46
+ @session.unselect('Briefs', :from => 'Underwear')
47
+ @session.should_not have_select('Underwear', :selected => ['Briefs', 'Commando'])
48
+ end
29
49
  end
30
50
 
31
51
  context 'with options' do
@@ -69,6 +89,26 @@ shared_examples_for "has_select" do
69
89
  @session.should have_no_select('Underwear', :selected => ['Briefs', 'Nonexistant'])
70
90
  @session.should have_no_select('Underwear', :selected => ['Briefs', 'Boxers'])
71
91
  end
92
+
93
+ it "should be false after the given value is selected" do
94
+ @session.select('Swedish', :from => 'Locale')
95
+ @session.should_not have_no_select('Locale', :selected => 'Swedish')
96
+ end
97
+
98
+ it "should be true after a different value is selected" do
99
+ @session.select('Swedish', :from => 'Locale')
100
+ @session.should have_no_select('Locale', :selected => 'English')
101
+ end
102
+
103
+ it "should be false after the given values are selected" do
104
+ @session.select('Boxers', :from => 'Underwear')
105
+ @session.should_not have_no_select('Underwear', :selected => ['Briefs', 'Boxers', 'Commando'])
106
+ end
107
+
108
+ it "should be true after one of the values is unselected" do
109
+ @session.unselect('Briefs', :from => 'Underwear')
110
+ @session.should have_no_select('Underwear', :selected => ['Briefs', 'Commando'])
111
+ end
72
112
  end
73
113
 
74
114
  context 'with options' do
@@ -8,15 +8,6 @@ shared_examples_for "session with javascript support" do
8
8
  Capybara.default_wait_time = 0
9
9
  end
10
10
 
11
- describe '#drag' do
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
- @session.visit('/with_js')
15
- @session.drag('//div[@id="drag"]', '//div[@id="drop"]')
16
- @session.find('//div[contains(., "Dropped!")]').should_not be_nil
17
- end
18
- end
19
-
20
11
  describe 'Node#drag_to' do
21
12
  it "should drag and drop an object" do
22
13
  pending "drag/drop is currently broken under celerity/culerity" if @session.driver.is_a?(Capybara::Driver::Celerity)
@@ -27,7 +18,7 @@ shared_examples_for "session with javascript support" do
27
18
  @session.find('//div[contains(., "Dropped!")]').should_not be_nil
28
19
  end
29
20
  end
30
-
21
+
31
22
  describe '#find' do
32
23
  it "should allow triggering of custom JS events" do
33
24
  pending "cannot figure out how to do this with selenium" if @session.mode == :selenium
@@ -111,7 +102,7 @@ shared_examples_for "session with javascript support" do
111
102
  begin
112
103
  @session.wait_until(0.1) { false }
113
104
  rescue Capybara::TimeoutError; end
114
- (Time.now - start).should be_close(0.1, 0.1)
105
+ (Time.now - start).should be_within(0.1).of(0.1)
115
106
  end
116
107
 
117
108
  it "should default to Capybara.default_wait_time before timeout" do
@@ -122,9 +113,9 @@ shared_examples_for "session with javascript support" do
122
113
  @session.wait_until { false }
123
114
  rescue Capybara::TimeoutError; end
124
115
  if @session.driver.has_shortcircuit_timeout?
125
- (Time.now - start).should be_close(0, 0.1)
116
+ (Time.now - start).should be_within(0.1).of(0)
126
117
  else
127
- (Time.now - start).should be_close(0.2, 0.1)
118
+ (Time.now - start).should be_within(0.1).of(0.2)
128
119
  end
129
120
  end
130
121
  end
@@ -1,4 +1,4 @@
1
- shared_examples_for "within" do
1
+ shared_examples_for "within" do
2
2
  describe '#within' do
3
3
  before do
4
4
  @session.visit('/with_scope')
@@ -11,6 +11,13 @@ shared_examples_for "within" do
11
11
  end
12
12
  @session.body.should include('Bar')
13
13
  end
14
+
15
+ it "should accept additional options" do
16
+ @session.within(:css, "ul li", :text => 'With Simple HTML') do
17
+ @session.click_link('Go')
18
+ end
19
+ @session.body.should include('Bar')
20
+ end
14
21
  end
15
22
 
16
23
  context "with XPath selector" do
@@ -32,14 +39,14 @@ shared_examples_for "within" do
32
39
  end
33
40
 
34
41
  context "with the default selector set to CSS" do
35
- before { Capybara.default_selector = :css }
42
+ before { Capybara.default_selector = :css }
36
43
  it "should use CSS" do
37
44
  @session.within("ul li[contains('With Simple HTML')]") do
38
45
  @session.click_link('Go')
39
46
  end
40
47
  @session.body.should include('Bar')
41
48
  end
42
- after { Capybara.default_selector = :xpath }
49
+ after { Capybara.default_selector = :xpath }
43
50
  end
44
51
 
45
52
  context "with click_link" do
@@ -77,6 +77,14 @@ class TestApp < Sinatra::Base
77
77
  '<pre id="results">' + params[:form].to_yaml + '</pre>'
78
78
  end
79
79
 
80
+ post '/upload_empty' do
81
+ if params[:form][:file].nil?
82
+ 'Successfully ignored empty file field.'
83
+ else
84
+ 'Something went wrong.'
85
+ end
86
+ end
87
+
80
88
  post '/upload' do
81
89
  begin
82
90
  buffer = []
@@ -87,8 +95,19 @@ class TestApp < Sinatra::Base
87
95
  'No file uploaded'
88
96
  end
89
97
  end
98
+
99
+ post '/upload_multiple' do
100
+ begin
101
+ buffer = []
102
+ buffer << "Content-type: #{params[:form][:multiple_documents][0][:type]}"
103
+ buffer << "File content: #{params[:form][:multiple_documents][0][:tempfile].read}"
104
+ buffer.join(' | ')
105
+ rescue
106
+ 'No files uploaded'
107
+ end
108
+ end
90
109
  end
91
110
 
92
111
  if __FILE__ == $0
93
- Rack::Handler::Mongrel.run TestApp, :Port => 8070
112
+ Rack::Handler::WEBrick.run TestApp, :Port => 8070
94
113
  end
@@ -250,6 +250,17 @@
250
250
  <p>
251
251
  </form>
252
252
 
253
+ <form action="/upload_empty" method="post" enctype="multipart/form-data">
254
+ <p>
255
+ <label for="form_file_name">File Name</label>
256
+ <input type="file" name="form[file]" id="form_file"/>
257
+ </p>
258
+
259
+ <p>
260
+ <input type="submit" value="Upload Empty"/>
261
+ <p>
262
+ </form>
263
+
253
264
  <form action="/upload" method="post" enctype="multipart/form-data">
254
265
  <p>
255
266
  <label for="form_file_name">File Name</label>
@@ -266,6 +277,22 @@
266
277
  <p>
267
278
  </form>
268
279
 
280
+ <form action="/upload_multiple" method="post" enctype="multipart/form-data">
281
+ <p>
282
+ <label for="form_multiple_file_name">File Name</label>
283
+ <input type="file" name="form[multiple_file_name]" id="form_multiple_file_name"/>
284
+ </p>
285
+
286
+ <p>
287
+ <label for="form_multiple_documents">Multiple Documents</label>
288
+ <input type="file" name="form[multiple_documents][]" id="form_multiple_documents" multiple />
289
+ </p>
290
+
291
+ <p>
292
+ <input type="submit" value="Upload Multiple"/>
293
+ <p>
294
+ </form>
295
+
269
296
  <form action="/redirect" method="post">
270
297
  <p>
271
298
  <input type="submit" value="Go FAR"/>
@@ -1,15 +1,23 @@
1
1
  <h1>This is a test</h1>
2
2
 
3
- <p id="first">
3
+ <h2 class="no text"></h2>
4
+ <h2 class="no text"></h2>
5
+ <h2 class="head" id="h2one">Header Class Test One</h2>
6
+ <h2 class="head" id="h2two">Header Class Test Two</h2>
7
+ <h2 class="head">Header Class Test Three</h2>
8
+ <h2 class="head">Header Class Test Four</h2>
9
+ <h2 class="head">Header Class Test Five</h2>
10
+
11
+ <p class="para" id="first">
4
12
  Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
5
13
  tempor incididunt ut <a href="/with_simple_html" title="awesome title" class="simple">labore</a>
6
14
  et dolore magna aliqua. Ut enim ad minim veniam,
7
15
  quis nostrud exercitation <a href="/foo" id="foo">ullamco</a> laboris nisi
8
16
  ut aliquip ex ea commodo consequat.
9
- <a href="/with_simple_html"><img src="http://www.foobar.sun/dummy_image.jpg" width="20" height="20" alt="awesome image" /></a>
17
+ <a href="/with_simple_html"><img width="20" height="20" alt="awesome image" /></a>
10
18
  </p>
11
19
 
12
- <p id="second">
20
+ <p class="para" id="second">
13
21
  Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
14
22
  dolore eu fugiat <a href="/redirect" id="red">Redirect</a> pariatur. Excepteur sint occaecat cupidatat non proident,
15
23
  sunt in culpa qui officia
@@ -33,8 +41,8 @@
33
41
  <a href="/with_html#anchor">Anchor on same page</a>
34
42
  <input type="text" value="" id="test_field">
35
43
  <input type="text" checked="checked" id="checked_field">
36
- <a href="/redirect"><img src="http://www.foobar.sun/dummy_image.jpg" width="20" height="20" alt="very fine image" /></a>
37
- <a href="/with_simple_html"><img src="http://www.foobar.sun/dummy_image.jpg" width="20" height="20" alt="fine image" /></a>
44
+ <a href="/redirect"><img width="20" height="20" alt="very fine image" /></a>
45
+ <a href="/with_simple_html"><img width="20" height="20" alt="fine image" /></a>
38
46
 
39
47
  <a href="?query_string=true">Naked Query String</a>
40
48
  <% if params[:query_string] %>
@@ -47,6 +55,14 @@
47
55
  <a href="/with_simple_html" title="awesome title" class="simple">hidden link</a>
48
56
  </div>
49
57
 
58
+ <div style="display: none;">
59
+ <a class="visibility">hidden link</a>
60
+ </div>
61
+
62
+ <div>
63
+ <a class="visibility">visible link</a>
64
+ </div>
65
+
50
66
  <ul>
51
67
  <li id="john_monkey">Monkey John</li>
52
68
  <li id="paul_monkey">Monkey Paul</li>