bbc-capybara 1.1.2

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 (107) hide show
  1. data/History.txt +325 -0
  2. data/License.txt +22 -0
  3. data/README.md +815 -0
  4. data/lib/capybara.rb +368 -0
  5. data/lib/capybara/cucumber.rb +25 -0
  6. data/lib/capybara/driver/base.rb +64 -0
  7. data/lib/capybara/driver/node.rb +74 -0
  8. data/lib/capybara/dsl.rb +50 -0
  9. data/lib/capybara/node/actions.rb +146 -0
  10. data/lib/capybara/node/base.rb +63 -0
  11. data/lib/capybara/node/document.rb +25 -0
  12. data/lib/capybara/node/element.rb +201 -0
  13. data/lib/capybara/node/finders.rb +154 -0
  14. data/lib/capybara/node/matchers.rb +442 -0
  15. data/lib/capybara/node/simple.rb +132 -0
  16. data/lib/capybara/query.rb +63 -0
  17. data/lib/capybara/rack_test/browser.rb +126 -0
  18. data/lib/capybara/rack_test/driver.rb +80 -0
  19. data/lib/capybara/rack_test/form.rb +80 -0
  20. data/lib/capybara/rack_test/node.rb +121 -0
  21. data/lib/capybara/rails.rb +17 -0
  22. data/lib/capybara/rspec.rb +26 -0
  23. data/lib/capybara/rspec/features.rb +22 -0
  24. data/lib/capybara/rspec/matchers.rb +152 -0
  25. data/lib/capybara/selector.rb +156 -0
  26. data/lib/capybara/selenium/driver.rb +169 -0
  27. data/lib/capybara/selenium/node.rb +91 -0
  28. data/lib/capybara/server.rb +87 -0
  29. data/lib/capybara/session.rb +322 -0
  30. data/lib/capybara/spec/driver.rb +329 -0
  31. data/lib/capybara/spec/fixtures/capybara.jpg +3 -0
  32. data/lib/capybara/spec/fixtures/test_file.txt +1 -0
  33. data/lib/capybara/spec/public/jquery-ui.js +791 -0
  34. data/lib/capybara/spec/public/jquery.js +9046 -0
  35. data/lib/capybara/spec/public/test.js +43 -0
  36. data/lib/capybara/spec/session.rb +148 -0
  37. data/lib/capybara/spec/session/all_spec.rb +78 -0
  38. data/lib/capybara/spec/session/attach_file_spec.rb +76 -0
  39. data/lib/capybara/spec/session/check_spec.rb +68 -0
  40. data/lib/capybara/spec/session/choose_spec.rb +29 -0
  41. data/lib/capybara/spec/session/click_button_spec.rb +305 -0
  42. data/lib/capybara/spec/session/click_link_or_button_spec.rb +37 -0
  43. data/lib/capybara/spec/session/click_link_spec.rb +120 -0
  44. data/lib/capybara/spec/session/current_url_spec.rb +83 -0
  45. data/lib/capybara/spec/session/fill_in_spec.rb +127 -0
  46. data/lib/capybara/spec/session/find_button_spec.rb +18 -0
  47. data/lib/capybara/spec/session/find_by_id_spec.rb +18 -0
  48. data/lib/capybara/spec/session/find_field_spec.rb +26 -0
  49. data/lib/capybara/spec/session/find_link_spec.rb +19 -0
  50. data/lib/capybara/spec/session/find_spec.rb +168 -0
  51. data/lib/capybara/spec/session/first_spec.rb +105 -0
  52. data/lib/capybara/spec/session/has_button_spec.rb +32 -0
  53. data/lib/capybara/spec/session/has_css_spec.rb +243 -0
  54. data/lib/capybara/spec/session/has_field_spec.rb +192 -0
  55. data/lib/capybara/spec/session/has_link_spec.rb +37 -0
  56. data/lib/capybara/spec/session/has_select_spec.rb +129 -0
  57. data/lib/capybara/spec/session/has_selector_spec.rb +129 -0
  58. data/lib/capybara/spec/session/has_table_spec.rb +34 -0
  59. data/lib/capybara/spec/session/has_text_spec.rb +138 -0
  60. data/lib/capybara/spec/session/has_xpath_spec.rb +123 -0
  61. data/lib/capybara/spec/session/headers.rb +19 -0
  62. data/lib/capybara/spec/session/javascript.rb +312 -0
  63. data/lib/capybara/spec/session/response_code.rb +19 -0
  64. data/lib/capybara/spec/session/select_spec.rb +119 -0
  65. data/lib/capybara/spec/session/text_spec.rb +24 -0
  66. data/lib/capybara/spec/session/uncheck_spec.rb +21 -0
  67. data/lib/capybara/spec/session/unselect_spec.rb +67 -0
  68. data/lib/capybara/spec/session/within_spec.rb +178 -0
  69. data/lib/capybara/spec/test_app.rb +156 -0
  70. data/lib/capybara/spec/views/buttons.erb +4 -0
  71. data/lib/capybara/spec/views/fieldsets.erb +29 -0
  72. data/lib/capybara/spec/views/form.erb +366 -0
  73. data/lib/capybara/spec/views/frame_one.erb +8 -0
  74. data/lib/capybara/spec/views/frame_two.erb +8 -0
  75. data/lib/capybara/spec/views/header_links.erb +7 -0
  76. data/lib/capybara/spec/views/host_links.erb +12 -0
  77. data/lib/capybara/spec/views/popup_one.erb +8 -0
  78. data/lib/capybara/spec/views/popup_two.erb +8 -0
  79. data/lib/capybara/spec/views/postback.erb +13 -0
  80. data/lib/capybara/spec/views/tables.erb +62 -0
  81. data/lib/capybara/spec/views/with_html.erb +75 -0
  82. data/lib/capybara/spec/views/with_html_entities.erb +1 -0
  83. data/lib/capybara/spec/views/with_js.erb +53 -0
  84. data/lib/capybara/spec/views/with_scope.erb +36 -0
  85. data/lib/capybara/spec/views/with_simple_html.erb +1 -0
  86. data/lib/capybara/spec/views/within_frames.erb +10 -0
  87. data/lib/capybara/spec/views/within_popups.erb +25 -0
  88. data/lib/capybara/util/save_and_open_page.rb +45 -0
  89. data/lib/capybara/util/timeout.rb +27 -0
  90. data/lib/capybara/version.rb +3 -0
  91. data/spec/basic_node_spec.rb +89 -0
  92. data/spec/capybara_spec.rb +46 -0
  93. data/spec/driver/rack_test_driver_spec.rb +90 -0
  94. data/spec/driver/selenium_driver_spec.rb +55 -0
  95. data/spec/dsl_spec.rb +255 -0
  96. data/spec/fixtures/selenium_driver_rspec_failure.rb +8 -0
  97. data/spec/fixtures/selenium_driver_rspec_success.rb +8 -0
  98. data/spec/rspec/features_spec.rb +43 -0
  99. data/spec/rspec/matchers_spec.rb +564 -0
  100. data/spec/rspec_spec.rb +51 -0
  101. data/spec/save_and_open_page_spec.rb +155 -0
  102. data/spec/server_spec.rb +74 -0
  103. data/spec/session/rack_test_session_spec.rb +61 -0
  104. data/spec/session/selenium_session_spec.rb +26 -0
  105. data/spec/spec_helper.rb +31 -0
  106. data/spec/timeout_spec.rb +28 -0
  107. metadata +297 -0
@@ -0,0 +1,123 @@
1
+ shared_examples_for "has_xpath" do
2
+ describe '#has_xpath?' do
3
+ before do
4
+ @session.visit('/with_html')
5
+ end
6
+
7
+ it "should be true if the given selector is on the page" do
8
+ @session.should have_xpath("//p")
9
+ @session.should have_xpath("//p//a[@id='foo']")
10
+ @session.should have_xpath("//p[contains(.,'est')]")
11
+ end
12
+
13
+ it "should be false if the given selector is not on the page" do
14
+ @session.should_not have_xpath("//abbr")
15
+ @session.should_not have_xpath("//p//a[@id='doesnotexist']")
16
+ @session.should_not have_xpath("//p[contains(.,'thisstringisnotonpage')]")
17
+ end
18
+
19
+ it "should use xpath even if default selector is CSS" do
20
+ Capybara.default_selector = :css
21
+ @session.should_not have_xpath("//p//a[@id='doesnotexist']")
22
+ end
23
+
24
+ it "should respect scopes" do
25
+ @session.within "//p[@id='first']" do
26
+ @session.should have_xpath(".//a[@id='foo']")
27
+ @session.should_not have_xpath(".//a[@id='red']")
28
+ end
29
+ end
30
+
31
+ context "with count" do
32
+ it "should be true if the content is on the page the given number of times" do
33
+ @session.should have_xpath("//p", :count => 3)
34
+ @session.should have_xpath("//p//a[@id='foo']", :count => 1)
35
+ @session.should have_xpath("//p[contains(.,'est')]", :count => 1)
36
+ end
37
+
38
+ it "should be false if the content is on the page the given number of times" do
39
+ @session.should_not have_xpath("//p", :count => 6)
40
+ @session.should_not have_xpath("//p//a[@id='foo']", :count => 2)
41
+ @session.should_not have_xpath("//p[contains(.,'est')]", :count => 5)
42
+ end
43
+
44
+ it "should be false if the content isn't on the page at all" do
45
+ @session.should_not have_xpath("//abbr", :count => 2)
46
+ @session.should_not have_xpath("//p//a[@id='doesnotexist']", :count => 1)
47
+ end
48
+ end
49
+
50
+ context "with text" do
51
+ it "should discard all matches where the given string is not contained" do
52
+ @session.should have_xpath("//p//a", :text => "Redirect", :count => 1)
53
+ @session.should_not have_xpath("//p", :text => "Doesnotexist")
54
+ end
55
+
56
+ it "should discard all matches where the given regexp is not matched" do
57
+ @session.should have_xpath("//p//a", :text => /re[dab]i/i, :count => 1)
58
+ @session.should_not have_xpath("//p//a", :text => /Red$/)
59
+ end
60
+ end
61
+ end
62
+
63
+ describe '#has_no_xpath?' do
64
+ before do
65
+ @session.visit('/with_html')
66
+ end
67
+
68
+ it "should be false if the given selector is on the page" do
69
+ @session.should_not have_no_xpath("//p")
70
+ @session.should_not have_no_xpath("//p//a[@id='foo']")
71
+ @session.should_not have_no_xpath("//p[contains(.,'est')]")
72
+ end
73
+
74
+ it "should be true if the given selector is not on the page" do
75
+ @session.should have_no_xpath("//abbr")
76
+ @session.should have_no_xpath("//p//a[@id='doesnotexist']")
77
+ @session.should have_no_xpath("//p[contains(.,'thisstringisnotonpage')]")
78
+ end
79
+
80
+ it "should use xpath even if default selector is CSS" do
81
+ Capybara.default_selector = :css
82
+ @session.should have_no_xpath("//p//a[@id='doesnotexist']")
83
+ end
84
+
85
+ it "should respect scopes" do
86
+ @session.within "//p[@id='first']" do
87
+ @session.should_not have_no_xpath(".//a[@id='foo']")
88
+ @session.should have_no_xpath(".//a[@id='red']")
89
+ end
90
+ end
91
+
92
+ context "with count" do
93
+ it "should be false if the content is on the page the given number of times" do
94
+ @session.should_not have_no_xpath("//p", :count => 3)
95
+ @session.should_not have_no_xpath("//p//a[@id='foo']", :count => 1)
96
+ @session.should_not have_no_xpath("//p[contains(.,'est')]", :count => 1)
97
+ end
98
+
99
+ it "should be true if the content is on the page the wrong number of times" do
100
+ @session.should have_no_xpath("//p", :count => 6)
101
+ @session.should have_no_xpath("//p//a[@id='foo']", :count => 2)
102
+ @session.should have_no_xpath("//p[contains(.,'est')]", :count => 5)
103
+ end
104
+
105
+ it "should be true if the content isn't on the page at all" do
106
+ @session.should have_no_xpath("//abbr", :count => 2)
107
+ @session.should have_no_xpath("//p//a[@id='doesnotexist']", :count => 1)
108
+ end
109
+ end
110
+
111
+ context "with text" do
112
+ it "should discard all matches where the given string is contained" do
113
+ @session.should_not have_no_xpath("//p//a", :text => "Redirect", :count => 1)
114
+ @session.should have_no_xpath("//p", :text => "Doesnotexist")
115
+ end
116
+
117
+ it "should discard all matches where the given regexp is matched" do
118
+ @session.should_not have_no_xpath("//p//a", :text => /re[dab]i/i, :count => 1)
119
+ @session.should have_no_xpath("//p//a", :text => /Red$/)
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,19 @@
1
+ shared_examples_for "session with headers support" do
2
+ describe '#response_headers' do
3
+ it "should return response headers" do
4
+ @session.visit('/with_simple_html')
5
+ @session.response_headers['Content-Type'].should =~ %r(text/html)
6
+ end
7
+ end
8
+ end
9
+
10
+ shared_examples_for "session without headers support" do
11
+ describe "#response_headers" do
12
+ before{ @session.visit('/with_simple_html') }
13
+ it "should raise an error" do
14
+ running {
15
+ @session.response_headers
16
+ }.should raise_error(Capybara::NotSupportedByDriverError)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,312 @@
1
+ shared_examples_for "session with javascript support" do
2
+ describe 'all JS specs' do
3
+ before do
4
+ Capybara.default_wait_time = 1
5
+ end
6
+
7
+ after do
8
+ Capybara.default_wait_time = 0
9
+ end
10
+
11
+ describe 'Node#drag_to' do
12
+ it "should drag and drop an object" do
13
+ @session.visit('/with_js')
14
+ element = @session.find('//div[@id="drag"]')
15
+ target = @session.find('//div[@id="drop"]')
16
+ element.drag_to(target)
17
+ @session.find('//div[contains(., "Dropped!")]').should_not be_nil
18
+ end
19
+ end
20
+
21
+ describe 'Node#reload' do
22
+ context "without automatic reload" do
23
+ before { Capybara.automatic_reload = false }
24
+ it "should reload the current context of the node" do
25
+ @session.visit('/with_js')
26
+ node = @session.find(:css, '#reload-me')
27
+ @session.click_link('Reload!')
28
+ sleep(0.3)
29
+ node.reload.text.should == 'RELOADED'
30
+ node.text.should == 'RELOADED'
31
+ end
32
+
33
+ it "should reload a parent node" do
34
+ @session.visit('/with_js')
35
+ node = @session.find(:css, '#reload-me').find(:css, 'em')
36
+ @session.click_link('Reload!')
37
+ sleep(0.3)
38
+ node.reload.text.should == 'RELOADED'
39
+ node.text.should == 'RELOADED'
40
+ end
41
+
42
+ it "should not automatically reload" do
43
+ @session.visit('/with_js')
44
+ node = @session.find(:css, '#reload-me')
45
+ @session.click_link('Reload!')
46
+ sleep(0.3)
47
+ running { node.text.should == 'RELOADED' }.should raise_error
48
+ end
49
+ after { Capybara.automatic_reload = true }
50
+ end
51
+
52
+ context "with automatic reload" do
53
+ it "should reload the current context of the node automatically" do
54
+ @session.visit('/with_js')
55
+ node = @session.find(:css, '#reload-me')
56
+ @session.click_link('Reload!')
57
+ sleep(0.3)
58
+ node.text.should == 'RELOADED'
59
+ end
60
+
61
+ it "should reload a parent node automatically" do
62
+ @session.visit('/with_js')
63
+ node = @session.find(:css, '#reload-me').find(:css, 'em')
64
+ @session.click_link('Reload!')
65
+ sleep(0.3)
66
+ node.text.should == 'RELOADED'
67
+ end
68
+
69
+ it "should reload a node automatically when using find" do
70
+ @session.visit('/with_js')
71
+ node = @session.find(:css, '#reload-me')
72
+ @session.click_link('Reload!')
73
+ sleep(0.3)
74
+ node.find(:css, 'a').text.should == 'RELOADED'
75
+ end
76
+ end
77
+ end
78
+
79
+ describe '#find' do
80
+ it "should allow triggering of custom JS events" do
81
+ # Not supported by Selenium without resorting to JavaScript execution
82
+ # http://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions#Q:_How_can_I_trigger_arbitrary_events_on_the_page?
83
+ unless @session.mode == :selenium
84
+ @session.visit('/with_js')
85
+ @session.find(:css, '#with_focus_event').trigger(:focus)
86
+ @session.should have_css('#focus_event_triggered')
87
+ end
88
+ end
89
+ end
90
+
91
+ describe '#html' do
92
+ it "should return the current state of the page" do
93
+ @session.visit('/with_js')
94
+ @session.html.should include('I changed it')
95
+ @session.html.should_not include('This is text')
96
+ end
97
+ end
98
+
99
+ [:body, :source].each do |method|
100
+ describe "##{method}" do
101
+ it "should return the original, unmodified source of the page" do
102
+ # Not supported by Selenium. See for example
103
+ # http://stackoverflow.com/questions/6050805
104
+ unless @session.mode == :selenium
105
+ @session.visit('/with_js')
106
+ @session.send(method).should include('This is text')
107
+ @session.send(method).should_not include('I changed it')
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ describe "#evaluate_script" do
114
+ it "should evaluate the given script and return whatever it produces" do
115
+ @session.visit('/with_js')
116
+ @session.evaluate_script("1+3").should == 4
117
+ end
118
+ end
119
+
120
+ describe "#execute_script" do
121
+ it "should execute the given script and return nothing" do
122
+ @session.visit('/with_js')
123
+ @session.execute_script("$('#change').text('Funky Doodle')").should be_nil
124
+ @session.should have_css('#change', :text => 'Funky Doodle')
125
+ end
126
+ end
127
+
128
+ describe '#find' do
129
+ it "should wait for asynchronous load" do
130
+ @session.visit('/with_js')
131
+ @session.click_link('Click me')
132
+ @session.find(:css, "a#has-been-clicked").text.should include('Has been clicked')
133
+ end
134
+
135
+ context "with frozen time" do
136
+ it "raises an error suggesting that Capybara is stuck in time" do
137
+ @session.visit('/with_js')
138
+ now = Time.now
139
+ Time.stub(:now).and_return(now)
140
+ expect { @session.find('//isnotthere') }.to raise_error(Capybara::FrozenInTime)
141
+ end
142
+ end
143
+ end
144
+
145
+ describe '#wait_until' do
146
+ before do
147
+ @default_timeout = Capybara.default_wait_time
148
+ end
149
+
150
+ after do
151
+ Capybara.default_wait_time = @default_wait_time
152
+ end
153
+
154
+ it "should wait for block to return true" do
155
+ @session.visit('/with_js')
156
+ @session.select('My Waiting Option', :from => 'waiter')
157
+ @session.evaluate_script('activeRequests == 1').should be_true
158
+ @session.wait_until do
159
+ @session.evaluate_script('activeRequests == 0')
160
+ end
161
+ @session.evaluate_script('activeRequests == 0').should be_true
162
+ end
163
+
164
+ it "should raise Capybara::TimeoutError if block doesn't return true within timeout" do
165
+ @session.visit('/with_html')
166
+ Proc.new do
167
+ @session.wait_until(0.1) do
168
+ @session.all('//div[@id="nosuchthing"]').first
169
+ end
170
+ end.should raise_error(::Capybara::TimeoutError)
171
+ end
172
+
173
+ it "should accept custom timeout in seconds" do
174
+ start = Time.now
175
+ Capybara.default_wait_time = 5
176
+ begin
177
+ @session.wait_until(0.1) { false }
178
+ rescue Capybara::TimeoutError; end
179
+ (Time.now - start).should be_within(0.1).of(0.1)
180
+ end
181
+
182
+ it "should default to Capybara.default_wait_time before timeout" do
183
+ @session.driver # init the driver to exclude init timing from test
184
+ start = Time.now
185
+ Capybara.default_wait_time = 0.2
186
+ begin
187
+ @session.wait_until { false }
188
+ rescue Capybara::TimeoutError; end
189
+ if @session.driver.has_shortcircuit_timeout?
190
+ (Time.now - start).should be_within(0.1).of(0)
191
+ else
192
+ (Time.now - start).should be_within(0.1).of(0.2)
193
+ end
194
+ end
195
+ end
196
+
197
+ describe '#click_link_or_button' do
198
+ it "should wait for asynchronous load" do
199
+ @session.visit('/with_js')
200
+ @session.click_link('Click me')
201
+ @session.click_link_or_button('Has been clicked')
202
+ end
203
+ end
204
+
205
+ describe '#click_link' do
206
+ it "should wait for asynchronous load" do
207
+ @session.visit('/with_js')
208
+ @session.click_link('Click me')
209
+ @session.click_link('Has been clicked')
210
+ end
211
+ end
212
+
213
+ describe '#click_button' do
214
+ it "should wait for asynchronous load" do
215
+ @session.visit('/with_js')
216
+ @session.click_link('Click me')
217
+ @session.click_button('New Here')
218
+ end
219
+ end
220
+
221
+ describe '#fill_in' do
222
+ it "should wait for asynchronous load" do
223
+ @session.visit('/with_js')
224
+ @session.click_link('Click me')
225
+ @session.fill_in('new_field', :with => 'Testing...')
226
+ end
227
+ end
228
+
229
+ describe '#check' do
230
+ it "should trigger associated events" do
231
+ @session.visit('/with_js')
232
+ @session.check('checkbox_with_event')
233
+ @session.should have_css('#checkbox_event_triggered');
234
+ end
235
+ end
236
+
237
+ describe '#has_xpath?' do
238
+ it "should wait for content to appear" do
239
+ @session.visit('/with_js')
240
+ @session.click_link('Click me')
241
+ @session.should have_xpath("//input[@type='submit' and @value='New Here']")
242
+ end
243
+ end
244
+
245
+ describe '#has_no_xpath?' do
246
+ it "should wait for content to disappear" do
247
+ @session.visit('/with_js')
248
+ @session.click_link('Click me')
249
+ @session.should have_no_xpath("//p[@id='change']")
250
+ end
251
+ end
252
+
253
+ describe '#has_css?' do
254
+ it "should wait for content to appear" do
255
+ @session.visit('/with_js')
256
+ @session.click_link('Click me')
257
+ @session.should have_css("input[type='submit'][value='New Here']")
258
+ end
259
+ end
260
+
261
+ describe '#has_no_xpath?' do
262
+ it "should wait for content to disappear" do
263
+ @session.visit('/with_js')
264
+ @session.click_link('Click me')
265
+ @session.should have_no_css("p#change")
266
+ end
267
+ end
268
+
269
+ describe '#has_content?' do
270
+ it "should wait for content to appear" do
271
+ @session.visit('/with_js')
272
+ @session.click_link('Click me')
273
+ @session.should have_content("Has been clicked")
274
+ end
275
+ end
276
+
277
+ describe '#has_no_content?' do
278
+ it "should wait for content to disappear" do
279
+ @session.visit('/with_js')
280
+ @session.click_link('Click me')
281
+ @session.should have_no_content("I changed it")
282
+ end
283
+ end
284
+
285
+ describe '#has_text?' do
286
+ it "should wait for text to appear" do
287
+ @session.visit('/with_js')
288
+ @session.click_link('Click me')
289
+ @session.should have_text("Has been clicked")
290
+ end
291
+ end
292
+
293
+ describe '#has_no_text?' do
294
+ it "should wait for text to disappear" do
295
+ @session.visit('/with_js')
296
+ @session.click_link('Click me')
297
+ @session.should have_no_text("I changed it")
298
+ end
299
+ end
300
+ end
301
+ end
302
+
303
+ shared_examples_for "session without javascript support" do
304
+ describe "#evaluate_script" do
305
+ before{ @session.visit('/with_simple_html') }
306
+ it "should raise an error" do
307
+ running {
308
+ @session.evaluate_script('3 + 3')
309
+ }.should raise_error(Capybara::NotSupportedByDriverError)
310
+ end
311
+ end
312
+ end