capybara 1.1.4 → 2.0.0.beta2

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 (84) hide show
  1. data/History.txt +100 -0
  2. data/License.txt +22 -0
  3. data/README.md +829 -0
  4. data/lib/capybara.rb +124 -6
  5. data/lib/capybara/cucumber.rb +2 -5
  6. data/lib/capybara/driver/base.rb +5 -5
  7. data/lib/capybara/driver/node.rb +2 -2
  8. data/lib/capybara/dsl.rb +3 -121
  9. data/lib/capybara/node/actions.rb +12 -28
  10. data/lib/capybara/node/base.rb +5 -13
  11. data/lib/capybara/node/element.rb +21 -21
  12. data/lib/capybara/node/finders.rb +27 -89
  13. data/lib/capybara/node/matchers.rb +107 -69
  14. data/lib/capybara/node/simple.rb +11 -13
  15. data/lib/capybara/query.rb +78 -0
  16. data/lib/capybara/rack_test/browser.rb +16 -27
  17. data/lib/capybara/rack_test/driver.rb +11 -1
  18. data/lib/capybara/rack_test/node.rb +17 -1
  19. data/lib/capybara/result.rb +84 -0
  20. data/lib/capybara/rspec/matchers.rb +28 -63
  21. data/lib/capybara/selector.rb +97 -33
  22. data/lib/capybara/selenium/driver.rb +14 -61
  23. data/lib/capybara/selenium/node.rb +6 -15
  24. data/lib/capybara/server.rb +32 -27
  25. data/lib/capybara/session.rb +54 -30
  26. data/lib/capybara/spec/public/jquery-ui.js +791 -0
  27. data/lib/capybara/spec/public/jquery.js +9046 -0
  28. data/lib/capybara/spec/public/test.js +4 -1
  29. data/lib/capybara/spec/session.rb +56 -27
  30. data/lib/capybara/spec/session/all_spec.rb +8 -4
  31. data/lib/capybara/spec/session/attach_file_spec.rb +12 -9
  32. data/lib/capybara/spec/session/check_spec.rb +6 -3
  33. data/lib/capybara/spec/session/choose_spec.rb +4 -1
  34. data/lib/capybara/spec/session/click_button_spec.rb +5 -14
  35. data/lib/capybara/spec/session/click_link_or_button_spec.rb +2 -1
  36. data/lib/capybara/spec/session/click_link_spec.rb +3 -17
  37. data/lib/capybara/spec/session/current_url_spec.rb +77 -9
  38. data/lib/capybara/spec/session/fill_in_spec.rb +8 -18
  39. data/lib/capybara/spec/session/find_spec.rb +19 -46
  40. data/lib/capybara/spec/session/first_spec.rb +2 -34
  41. data/lib/capybara/spec/session/has_css_spec.rb +1 -1
  42. data/lib/capybara/spec/session/has_field_spec.rb +28 -0
  43. data/lib/capybara/spec/session/has_select_spec.rb +84 -31
  44. data/lib/capybara/spec/session/has_table_spec.rb +7 -69
  45. data/lib/capybara/spec/session/has_text_spec.rb +168 -0
  46. data/lib/capybara/spec/session/javascript.rb +65 -81
  47. data/lib/capybara/spec/session/node_spec.rb +115 -0
  48. data/lib/capybara/spec/session/screenshot.rb +29 -0
  49. data/lib/capybara/spec/session/select_spec.rb +12 -12
  50. data/lib/capybara/spec/session/text_spec.rb +9 -4
  51. data/lib/capybara/spec/session/unselect_spec.rb +12 -6
  52. data/lib/capybara/spec/session/visit_spec.rb +76 -0
  53. data/lib/capybara/spec/session/within_frame_spec.rb +33 -0
  54. data/lib/capybara/spec/session/within_spec.rb +47 -58
  55. data/lib/capybara/spec/session/within_window_spec.rb +40 -0
  56. data/lib/capybara/spec/test_app.rb +27 -3
  57. data/lib/capybara/spec/views/form.erb +11 -10
  58. data/lib/capybara/spec/views/host_links.erb +2 -2
  59. data/lib/capybara/spec/views/tables.erb +6 -66
  60. data/lib/capybara/spec/views/with_html.erb +3 -3
  61. data/lib/capybara/spec/views/with_js.erb +11 -8
  62. data/lib/capybara/util/save_and_open_page.rb +4 -3
  63. data/lib/capybara/version.rb +1 -1
  64. data/spec/basic_node_spec.rb +15 -3
  65. data/spec/dsl_spec.rb +12 -10
  66. data/spec/rack_test_spec.rb +152 -0
  67. data/spec/rspec/features_spec.rb +0 -2
  68. data/spec/rspec/matchers_spec.rb +164 -89
  69. data/spec/rspec_spec.rb +0 -2
  70. data/spec/selenium_spec.rb +67 -0
  71. data/spec/server_spec.rb +35 -23
  72. data/spec/spec_helper.rb +18 -2
  73. metadata +30 -30
  74. data/README.rdoc +0 -722
  75. data/lib/capybara/spec/driver.rb +0 -301
  76. data/lib/capybara/spec/session/current_host_spec.rb +0 -68
  77. data/lib/capybara/spec/session/has_content_spec.rb +0 -106
  78. data/lib/capybara/util/timeout.rb +0 -27
  79. data/spec/driver/rack_test_driver_spec.rb +0 -89
  80. data/spec/driver/selenium_driver_spec.rb +0 -37
  81. data/spec/session/rack_test_session_spec.rb +0 -55
  82. data/spec/session/selenium_session_spec.rb +0 -26
  83. data/spec/string_spec.rb +0 -77
  84. data/spec/timeout_spec.rb +0 -28
@@ -1,301 +0,0 @@
1
- require 'capybara/spec/test_app'
2
-
3
- shared_examples_for 'driver' do
4
-
5
- describe '#visit' do
6
- it "should move to another page" do
7
- @driver.visit('/')
8
- @driver.body.should include('Hello world!')
9
- @driver.visit('/foo')
10
- @driver.body.should include('Another World')
11
- end
12
-
13
- it "should show the correct URL" do
14
- @driver.visit('/foo')
15
- @driver.current_url.should include('/foo')
16
- end
17
- end
18
-
19
- describe '#body' do
20
- it "should return text reponses" do
21
- @driver.visit('/')
22
- @driver.body.should include('Hello world!')
23
- end
24
-
25
- it "should return the full response html" do
26
- @driver.visit('/with_simple_html')
27
- @driver.body.should include('Bar')
28
- end
29
-
30
- if "".respond_to?(:encoding)
31
- context "encoding of response between ascii and utf8" do
32
- it "should be valid with html entities" do
33
- @driver.visit('/with_html_entities')
34
- lambda { @driver.body.encode!("UTF-8") }.should_not raise_error
35
- end
36
-
37
- it "should be valid without html entities" do
38
- @driver.visit('/with_html')
39
- lambda { @driver.body.encode!("UTF-8") }.should_not raise_error
40
- end
41
- end
42
- end
43
- end
44
-
45
- describe '#find' do
46
- context "with xpath selector" do
47
- before do
48
- @driver.visit('/with_html')
49
- end
50
-
51
- it "should extract node texts" do
52
- @driver.find('//a')[0].text.should == 'labore'
53
- @driver.find('//a')[1].text.should == 'ullamco'
54
- end
55
-
56
- it "should extract node attributes" do
57
- @driver.find('//a')[0][:class].should == 'simple'
58
- @driver.find('//a')[1][:id].should == 'foo'
59
- @driver.find('//input')[0][:type].should == 'text'
60
- end
61
-
62
- it "should extract boolean node attributes" do
63
- @driver.find('//input[@id="checked_field"]')[0][:checked].should be_true
64
- end
65
-
66
- it "should allow retrieval of the value" do
67
- @driver.find('//textarea[@id="normal"]').first.value.should == 'banana'
68
- end
69
-
70
- it "should not swallow extra newlines in textarea" do
71
- @driver.find('//textarea[@id="additional_newline"]').first.value.should == "\nbanana"
72
- end
73
-
74
- it "should allow assignment of field value" do
75
- @driver.find('//input').first.value.should == 'monkey'
76
- @driver.find('//input').first.set('gorilla')
77
- @driver.find('//input').first.value.should == 'gorilla'
78
- end
79
-
80
- it "should extract node tag name" do
81
- @driver.find('//a')[0].tag_name.should == 'a'
82
- @driver.find('//a')[1].tag_name.should == 'a'
83
- @driver.find('//p')[1].tag_name.should == 'p'
84
- end
85
-
86
- it "should extract node visibility" do
87
- @driver.find('//a')[0].should be_visible
88
-
89
- @driver.find('//div[@id="hidden"]')[0].should_not be_visible
90
- @driver.find('//div[@id="hidden_via_ancestor"]')[0].should_not be_visible
91
- end
92
-
93
- it "should extract node checked state" do
94
- @driver.visit('/form')
95
- @driver.find('//input[@id="gender_female"]')[0].should be_checked
96
- @driver.find('//input[@id="gender_male"]')[0].should_not be_checked
97
- @driver.find('//h1')[0].should_not be_checked
98
- end
99
-
100
- it "should extract node selected state" do
101
- @driver.visit('/form')
102
- @driver.find('//option[@value="en"]')[0].should be_selected
103
- @driver.find('//option[@value="sv"]')[0].should_not be_selected
104
- @driver.find('//h1')[0].should_not be_selected
105
- end
106
-
107
- it "should return document text on /html selector" do
108
- @driver.visit('/with_simple_html')
109
- @driver.find('/html')[0].text.should == 'Bar'
110
- end
111
- end
112
- end
113
- end
114
-
115
- shared_examples_for "driver with javascript support" do
116
- before { @driver.visit('/with_js') }
117
-
118
- describe '#find' do
119
- it "should find dynamically changed nodes" do
120
- @driver.find('//p').first.text.should == 'I changed it'
121
- end
122
- end
123
-
124
- describe '#drag_to' do
125
- it "should drag and drop an object" do
126
- draggable = @driver.find('//div[@id="drag"]').first
127
- droppable = @driver.find('//div[@id="drop"]').first
128
- draggable.drag_to(droppable)
129
- @driver.find('//div[contains(., "Dropped!")]').should_not be_empty
130
- end
131
- end
132
-
133
- describe "#evaluate_script" do
134
- it "should return the value of the executed script" do
135
- @driver.evaluate_script('1+1').should == 2
136
- end
137
- end
138
-
139
- end
140
-
141
- shared_examples_for "driver with resynchronization support" do
142
- before { @driver.visit('/with_js') }
143
- describe "#find" do
144
- context "with synchronization turned on" do
145
- before { @driver.options[:resynchronize] = true }
146
- it "should wait for all ajax requests to finish" do
147
- @driver.find('//input[@id="fire_ajax_request"]').first.click
148
- @driver.find('//p[@id="ajax_request_done"]').should_not be_empty
149
- end
150
- end
151
-
152
- context "with resynchronization turned off" do
153
- before { @driver.options[:resynchronize] = false }
154
- it "should not wait for ajax requests to finish" do
155
- @driver.find('//input[@id="fire_ajax_request"]').first.click
156
- @driver.find('//p[@id="ajax_request_done"]').should be_empty
157
- end
158
- end
159
-
160
- context "with short synchronization timeout" do
161
- before { @driver.options[:resynchronize] = true }
162
- before { @driver.options[:resynchronization_timeout] = 0.1 }
163
-
164
- it "should raise an error" do
165
- expect do
166
- @driver.find('//input[@id="fire_ajax_request"]').first.click
167
- end.to raise_error(Capybara::TimeoutError, "failed to resynchronize, ajax request timed out")
168
- end
169
- end
170
- end
171
-
172
- after { @driver.options[:resynchronize] = false }
173
- after { @driver.options[:resynchronization_timeout] = 10 }
174
- end
175
-
176
- shared_examples_for "driver with header support" do
177
- it "should make headers available through response_headers" do
178
- @driver.visit('/with_simple_html')
179
- @driver.response_headers['Content-Type'].should =~ /text\/html/
180
- end
181
- end
182
-
183
- shared_examples_for "driver with status code support" do
184
- it "should make the status code available through status_code" do
185
- @driver.visit('/with_simple_html')
186
- @driver.status_code.should == 200
187
- end
188
- end
189
-
190
- shared_examples_for "driver without status code support" do
191
- it "should raise when trying to access the status code available through status_code" do
192
- @driver.visit('/with_simple_html')
193
- lambda {
194
- @driver.status_code
195
- }.should raise_error(Capybara::NotSupportedByDriverError)
196
- end
197
- end
198
-
199
- shared_examples_for "driver with frame support" do
200
- describe '#within_frame' do
201
- before(:each) do
202
- @driver.visit('/within_frames')
203
- end
204
-
205
- it "should find the div in frameOne" do
206
- @driver.within_frame("frameOne") do
207
- @driver.find("//*[@id='divInFrameOne']")[0].text.should eql 'This is the text of divInFrameOne'
208
- end
209
- end
210
- it "should find the div in FrameTwo" do
211
- @driver.within_frame("frameTwo") do
212
- @driver.find("//*[@id='divInFrameTwo']")[0].text.should eql 'This is the text of divInFrameTwo'
213
- end
214
- end
215
- it "should find the text div in the main window after finding text in frameOne" do
216
- @driver.within_frame("frameOne") do
217
- @driver.find("//*[@id='divInFrameOne']")[0].text.should eql 'This is the text of divInFrameOne'
218
- end
219
- @driver.find("//*[@id='divInMainWindow']")[0].text.should eql 'This is the text for divInMainWindow'
220
- end
221
- it "should find the text div in the main window after finding text in frameTwo" do
222
- @driver.within_frame("frameTwo") do
223
- @driver.find("//*[@id='divInFrameTwo']")[0].text.should eql 'This is the text of divInFrameTwo'
224
- end
225
- @driver.find("//*[@id='divInMainWindow']")[0].text.should eql 'This is the text for divInMainWindow'
226
- end
227
- end
228
- end
229
-
230
- shared_examples_for "driver with support for window switching" do
231
- describe '#within_window' do
232
- before(:each) do
233
- @driver.visit('/within_popups')
234
- end
235
- after(:each) do
236
- @driver.within_window("firstPopup") do
237
- @driver.evaluate_script('window.close()')
238
- end
239
- @driver.within_window("secondPopup") do
240
- @driver.evaluate_script('window.close()')
241
- end
242
- end
243
-
244
- it "should find the div in firstPopup" do
245
- @driver.within_window("firstPopup") do
246
- @driver.find("//*[@id='divInPopupOne']")[0].text.should eql 'This is the text of divInPopupOne'
247
- end
248
- end
249
- it "should find the div in secondPopup" do
250
- @driver.within_window("secondPopup") do
251
- @driver.find("//*[@id='divInPopupTwo']")[0].text.should eql 'This is the text of divInPopupTwo'
252
- end
253
- end
254
- it "should find the divs in both popups" do
255
- @driver.within_window("secondPopup") do
256
- @driver.find("//*[@id='divInPopupTwo']")[0].text.should eql 'This is the text of divInPopupTwo'
257
- end
258
- @driver.within_window("firstPopup") do
259
- @driver.find("//*[@id='divInPopupOne']")[0].text.should eql 'This is the text of divInPopupOne'
260
- end
261
- end
262
- it "should find the div in the main window after finding a div in a popup" do
263
- @driver.within_window("secondPopup") do
264
- @driver.find("//*[@id='divInPopupTwo']")[0].text.should eql 'This is the text of divInPopupTwo'
265
- end
266
- @driver.find("//*[@id='divInMainWindow']")[0].text.should eql 'This is the text for divInMainWindow'
267
- end
268
- end
269
- end
270
-
271
- shared_examples_for "driver with cookies support" do
272
- describe "#reset!" do
273
- it "should set and clean cookies" do
274
- @driver.visit('/get_cookie')
275
- @driver.body.should_not include('test_cookie')
276
-
277
- @driver.visit('/set_cookie')
278
- @driver.body.should include('Cookie set to test_cookie')
279
-
280
- @driver.visit('/get_cookie')
281
- @driver.body.should include('test_cookie')
282
-
283
- @driver.reset!
284
- @driver.visit('/get_cookie')
285
- @driver.body.should_not include('test_cookie')
286
- end
287
- end
288
- end
289
-
290
- shared_examples_for "driver with infinite redirect detection" do
291
- it "should follow 5 redirects" do
292
- @driver.visit('/redirect/5/times')
293
- @driver.body.should include('redirection complete')
294
- end
295
-
296
- it "should not follow more than 5 redirects" do
297
- running do
298
- @driver.visit('/redirect/6/times')
299
- end.should raise_error(Capybara::InfiniteRedirectError)
300
- end
301
- end
@@ -1,68 +0,0 @@
1
- shared_examples_for "current_host" do
2
- after do
3
- Capybara.app_host = nil
4
- end
5
-
6
- describe '#current_host' do
7
- it "is affected by visiting a page directly" do
8
- @session.visit('http://capybara-testapp.heroku.com/host')
9
- @session.body.should include('Current host is http://capybara-testapp.heroku.com')
10
- @session.current_host.should == 'http://capybara-testapp.heroku.com'
11
- end
12
-
13
- it "returns to the app host when visiting a relative url" do
14
- Capybara.app_host = "http://capybara1.elabs.se"
15
- @session.visit('http://capybara-testapp.heroku.com/host')
16
- @session.body.should include('Current host is http://capybara-testapp.heroku.com')
17
- @session.current_host.should == 'http://capybara-testapp.heroku.com'
18
- @session.visit('/host')
19
- @session.body.should include('Current host is http://capybara1.elabs.se')
20
- @session.current_host.should == 'http://capybara1.elabs.se'
21
- end
22
-
23
- it "is affected by setting Capybara.app_host" do
24
- Capybara.app_host = "http://capybara-testapp.heroku.com"
25
- @session.visit('/host')
26
- @session.body.should include('Current host is http://capybara-testapp.heroku.com')
27
- @session.current_host.should == 'http://capybara-testapp.heroku.com'
28
- Capybara.app_host = "http://capybara1.elabs.se"
29
- @session.visit('/host')
30
- @session.body.should include('Current host is http://capybara1.elabs.se')
31
- @session.current_host.should == 'http://capybara1.elabs.se'
32
- end
33
-
34
- it "is unaffected by following a relative link" do
35
- @session.visit('http://capybara-testapp.heroku.com/host_links')
36
- @session.click_link('Relative Host')
37
- @session.body.should include('Current host is http://capybara-testapp.heroku.com')
38
- @session.current_host.should == 'http://capybara-testapp.heroku.com'
39
- end
40
-
41
- it "is affected by following an absolute link" do
42
- @session.visit('http://capybara-testapp.heroku.com/host_links')
43
- @session.click_link('Absolute Host')
44
- @session.body.should include('Current host is http://capybara2.elabs.se')
45
- @session.current_host.should == 'http://capybara2.elabs.se'
46
- end
47
-
48
- it "is unaffected by posting through a relative form" do
49
- @session.visit('http://capybara-testapp.heroku.com/host_links')
50
- @session.click_button('Relative Host')
51
- @session.body.should include('Current host is http://capybara-testapp.heroku.com')
52
- @session.current_host.should == 'http://capybara-testapp.heroku.com'
53
- end
54
-
55
- it "is affected by posting through an absolute form" do
56
- @session.visit('http://capybara-testapp.heroku.com/host_links')
57
- @session.click_button('Absolute Host')
58
- @session.body.should include('Current host is http://capybara2.elabs.se')
59
- @session.current_host.should == 'http://capybara2.elabs.se'
60
- end
61
-
62
- it "is affected by following a redirect" do
63
- @session.visit('http://capybara-testapp.heroku.com/redirect_secure')
64
- @session.body.should include('Current host is https://capybara-testapp.heroku.com')
65
- @session.current_host.should == 'https://capybara-testapp.heroku.com'
66
- end
67
- end
68
- end
@@ -1,106 +0,0 @@
1
- shared_examples_for "has_content" do
2
- describe '#has_content?' do
3
- it "should be true if the given content is on the page at least once" do
4
- @session.visit('/with_html')
5
- @session.should have_content('est')
6
- @session.should have_content('Lorem')
7
- @session.should have_content('Redirect')
8
- end
9
-
10
- it "should be true if scoped to an element which has the content" do
11
- @session.visit('/with_html')
12
- @session.within("//a[@title='awesome title']") do
13
- @session.should have_content('labore')
14
- end
15
- end
16
-
17
- it "should be false if scoped to an element which does not have the content" do
18
- @session.visit('/with_html')
19
- @session.within("//a[@title='awesome title']") do
20
- @session.should_not have_content('monkey')
21
- end
22
- end
23
-
24
- it "should ignore tags" do
25
- @session.visit('/with_html')
26
- @session.should_not have_content('exercitation <a href="/foo" id="foo">ullamco</a> laboris')
27
- @session.should have_content('exercitation ullamco laboris')
28
- end
29
-
30
- it "should ignore extra whitespace and newlines" do
31
- @session.visit('/with_html')
32
- @session.should have_content('text with whitespace')
33
- end
34
-
35
- it "should be false if the given content is not on the page" do
36
- @session.visit('/with_html')
37
- @session.should_not have_content('xxxxyzzz')
38
- @session.should_not have_content('monkey')
39
- end
40
-
41
- it 'should handle single quotes in the content' do
42
- @session.visit('/with-quotes')
43
- @session.should have_content("can't")
44
- end
45
-
46
- it 'should handle double quotes in the content' do
47
- @session.visit('/with-quotes')
48
- @session.should have_content(%q{"No," he said})
49
- end
50
-
51
- it 'should handle mixed single and double quotes in the content' do
52
- @session.visit('/with-quotes')
53
- @session.should have_content(%q{"you can't do that."})
54
- end
55
- end
56
-
57
- describe '#has_no_content?' do
58
- it "should be false if the given content is on the page at least once" do
59
- @session.visit('/with_html')
60
- @session.should_not have_no_content('est')
61
- @session.should_not have_no_content('Lorem')
62
- @session.should_not have_no_content('Redirect')
63
- end
64
-
65
- it "should be false if scoped to an element which has the content" do
66
- @session.visit('/with_html')
67
- @session.within("//a[@title='awesome title']") do
68
- @session.should_not have_no_content('labore')
69
- end
70
- end
71
-
72
- it "should be true if scoped to an element which does not have the content" do
73
- @session.visit('/with_html')
74
- @session.within("//a[@title='awesome title']") do
75
- @session.should have_no_content('monkey')
76
- end
77
- end
78
-
79
- it "should ignore tags" do
80
- @session.visit('/with_html')
81
- @session.should have_no_content('exercitation <a href="/foo" id="foo">ullamco</a> laboris')
82
- @session.should_not have_no_content('exercitation ullamco laboris')
83
- end
84
-
85
- it "should be true if the given content is not on the page" do
86
- @session.visit('/with_html')
87
- @session.should have_no_content('xxxxyzzz')
88
- @session.should have_no_content('monkey')
89
- end
90
-
91
- it 'should handle single quotes in the content' do
92
- @session.visit('/with-quotes')
93
- @session.should_not have_no_content("can't")
94
- end
95
-
96
- it 'should handle double quotes in the content' do
97
- @session.visit('/with-quotes')
98
- @session.should_not have_no_content(%q{"No," he said})
99
- end
100
-
101
- it 'should handle mixed single and double quotes in the content' do
102
- @session.visit('/with-quotes')
103
- @session.should_not have_no_content(%q{"you can't do that."})
104
- end
105
- end
106
- end