bbc-capybara 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
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,154 @@
1
+ module Capybara
2
+ module Node
3
+ module Finders
4
+
5
+ ##
6
+ #
7
+ # Find an {Capybara::Element} based on the given arguments. +find+ will raise an error if the element
8
+ # is not found. The error message can be customized through the +:message+ option.
9
+ #
10
+ # If the driver is capable of executing JavaScript, +find+ will wait for a set amount of time
11
+ # and continuously retry finding the element until either the element is found or the time
12
+ # expires. The length of time +find+ will wait is controlled through {Capybara.default_wait_time}
13
+ # and defaults to 2 seconds.
14
+ #
15
+ # +find+ takes the same options as +all+.
16
+ #
17
+ # page.find('#foo').find('.bar')
18
+ # page.find(:xpath, '//div[contains(., "bar")]')
19
+ # page.find('li', :text => 'Quox').click_link('Delete')
20
+ #
21
+ # @param (see Capybara::Node::Finders#all)
22
+ # @option options [String] :message An error message in case the element can't be found
23
+ # @return [Capybara::Element] The found element
24
+ # @raise [Capybara::ElementNotFound] If the element can't be found before time expires
25
+ #
26
+ def find(*args)
27
+ wait_until { first(*args) or raise_find_error(*args) }
28
+ end
29
+
30
+ ##
31
+ #
32
+ # Find a form field on the page. The field can be found by its name, id or label text.
33
+ #
34
+ # @param [String] locator Which field to find
35
+ # @return [Capybara::Element] The found element
36
+ #
37
+ def find_field(locator)
38
+ find(:field, locator)
39
+ end
40
+ alias_method :field_labeled, :find_field
41
+
42
+ ##
43
+ #
44
+ # Find a link on the page. The link can be found by its id or text.
45
+ #
46
+ # @param [String] locator Which link to find
47
+ # @return [Capybara::Element] The found element
48
+ #
49
+ def find_link(locator)
50
+ find(:link, locator)
51
+ end
52
+
53
+ ##
54
+ #
55
+ # Find a button on the page. The link can be found by its id, name or value.
56
+ #
57
+ # @param [String] locator Which button to find
58
+ # @return [Capybara::Element] The found element
59
+ #
60
+ def find_button(locator)
61
+ find(:button, locator)
62
+ end
63
+
64
+ ##
65
+ #
66
+ # Find a element on the page, given its id.
67
+ #
68
+ # @param [String] locator Which element to find
69
+ # @return [Capybara::Element] The found element
70
+ #
71
+ def find_by_id(id)
72
+ find(:id, id)
73
+ end
74
+
75
+ ##
76
+ #
77
+ # Find all elements on the page matching the given selector
78
+ # and options.
79
+ #
80
+ # Both XPath and CSS expressions are supported, but Capybara
81
+ # does not try to automatically distinguish between them. The
82
+ # following statements are equivalent:
83
+ #
84
+ # page.all(:css, 'a#person_123')
85
+ # page.all(:xpath, '//a[@id="person_123"]')
86
+ #
87
+ #
88
+ # If the type of selector is left out, Capybara uses
89
+ # {Capybara.default_selector}. It's set to :css by default.
90
+ #
91
+ # page.all("a#person_123")
92
+ #
93
+ # Capybara.default_selector = :xpath
94
+ # page.all('//a[@id="person_123"]')
95
+ #
96
+ # The set of found elements can further be restricted by specifying
97
+ # options. It's possible to select elements by their text or visibility:
98
+ #
99
+ # page.all('a', :text => 'Home')
100
+ # page.all('#menu li', :visible => true)
101
+ #
102
+ # @overload all([kind], locator, options)
103
+ # @param [:css, :xpath] kind The type of selector
104
+ # @param [String] locator The selector
105
+ # @option options [String, Regexp] text Only find elements which contain this text or match this regexp
106
+ # @option options [Boolean] visible Only find elements that are visible on the page. Setting this to false
107
+ # (the default, unless Capybara.ignore_hidden_elements = true), finds
108
+ # invisible _and_ visible elements.
109
+ # @return [Array[Capybara::Element]] The found elements
110
+ #
111
+ def all(*args)
112
+ query = Capybara::Query.new(*args)
113
+ query.xpaths.
114
+ map { |path| find_in_base(query, path) }.flatten.
115
+ select { |node| query.matches_filters?(node) }
116
+ end
117
+
118
+ ##
119
+ #
120
+ # Find the first element on the page matching the given selector
121
+ # and options, or nil if no element matches.
122
+ #
123
+ # @overload first([kind], locator, options)
124
+ # @param [:css, :xpath] kind The type of selector
125
+ # @param [String] locator The selector
126
+ # @param [Hash] options Additional options; see {all}
127
+ # @return [Capybara::Element] The found element or nil
128
+ #
129
+ def first(*args)
130
+ results = all(*args)
131
+ if Capybara.prefer_visible_elements
132
+ results.find(&:visible?) or results.first
133
+ else
134
+ results.first
135
+ end
136
+ end
137
+
138
+ protected
139
+
140
+ def raise_find_error(*args)
141
+ query = Capybara::Query.new(*args)
142
+ raise Capybara::ElementNotFound, query.failure_message(:find, self)
143
+ end
144
+
145
+ def find_in_base(query, xpath)
146
+ base.find(xpath).map do |node|
147
+ Capybara::Node::Element.new(session, node, self, query)
148
+ end
149
+ end
150
+
151
+
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,442 @@
1
+ module Capybara
2
+ module Node
3
+ module Matchers
4
+
5
+ ##
6
+ #
7
+ # Checks if a given selector is on the page or current node.
8
+ #
9
+ # page.has_selector?('p#foo')
10
+ # page.has_selector?(:xpath, './/p[@id="foo"]')
11
+ # page.has_selector?(:foo)
12
+ #
13
+ # By default it will check if the expression occurs at least once,
14
+ # but a different number can be specified.
15
+ #
16
+ # page.has_selector?('p#foo', :count => 4)
17
+ #
18
+ # This will check if the expression occurs exactly 4 times.
19
+ #
20
+ # It also accepts all options that {Capybara::Node::Finders#all} accepts,
21
+ # such as :text and :visible.
22
+ #
23
+ # page.has_selector?('li', :text => 'Horse', :visible => true)
24
+ #
25
+ # has_selector? can also accept XPath expressions generated by the
26
+ # XPath gem:
27
+ #
28
+ # xpath = XPath.generate { |x| x.descendant(:p) }
29
+ # page.has_selector?(:xpath, xpath)
30
+ #
31
+ # @param (see Capybara::Node::Finders#all)
32
+ # @option options [Integer] :count (nil) Number of times the expression should occur
33
+ # @return [Boolean] If the expression exists
34
+ #
35
+ def has_selector?(*args)
36
+ options = if args.last.is_a?(Hash) then args.last else {} end
37
+ wait_until do
38
+ results = all(*args)
39
+
40
+ case
41
+ when results.empty?
42
+ false
43
+ when options[:between]
44
+ options[:between] === results.size
45
+ when options[:count]
46
+ options[:count].to_i == results.size
47
+ when options[:maximum]
48
+ options[:maximum].to_i >= results.size
49
+ when options[:minimum]
50
+ options[:minimum].to_i <= results.size
51
+ else
52
+ results.size > 0
53
+ end or raise ExpectationNotMet
54
+ end
55
+ rescue Capybara::ExpectationNotMet
56
+ return false
57
+ end
58
+
59
+ ##
60
+ #
61
+ # Checks if a given selector is not on the page or current node.
62
+ # Usage is identical to Capybara::Node::Matchers#has_selector?
63
+ #
64
+ # @param (see Capybara::Node::Finders#has_selector?)
65
+ # @return [Boolean]
66
+ #
67
+ def has_no_selector?(*args)
68
+ options = if args.last.is_a?(Hash) then args.last else {} end
69
+ wait_until do
70
+ results = all(*args)
71
+
72
+ case
73
+ when results.empty?
74
+ true
75
+ when options[:between]
76
+ not(options[:between] === results.size)
77
+ when options[:count]
78
+ not(options[:count].to_i == results.size)
79
+ when options[:maximum]
80
+ not(options[:maximum].to_i >= results.size)
81
+ when options[:minimum]
82
+ not(options[:minimum].to_i <= results.size)
83
+ else
84
+ results.empty?
85
+ end or raise ExpectationNotMet
86
+ end
87
+ rescue Capybara::ExpectationNotMet
88
+ return false
89
+ end
90
+
91
+ ##
92
+ #
93
+ # Checks if a given XPath expression is on the page or current node.
94
+ #
95
+ # page.has_xpath?('.//p[@id="foo"]')
96
+ #
97
+ # By default it will check if the expression occurs at least once,
98
+ # but a different number can be specified.
99
+ #
100
+ # page.has_xpath?('.//p[@id="foo"]', :count => 4)
101
+ #
102
+ # This will check if the expression occurs exactly 4 times.
103
+ #
104
+ # It also accepts all options that {Capybara::Node::Finders#all} accepts,
105
+ # such as :text and :visible.
106
+ #
107
+ # page.has_xpath?('.//li', :text => 'Horse', :visible => true)
108
+ #
109
+ # has_xpath? can also accept XPath expressions generate by the
110
+ # XPath gem:
111
+ #
112
+ # xpath = XPath.generate { |x| x.descendant(:p) }
113
+ # page.has_xpath?(xpath)
114
+ #
115
+ # @param [String] path An XPath expression
116
+ # @param options (see Capybara::Node::Finders#all)
117
+ # @option options [Integer] :count (nil) Number of times the expression should occur
118
+ # @return [Boolean] If the expression exists
119
+ #
120
+ def has_xpath?(path, options={})
121
+ has_selector?(:xpath, path, options)
122
+ end
123
+
124
+ ##
125
+ #
126
+ # Checks if a given XPath expression is not on the page or current node.
127
+ # Usage is identical to Capybara::Node::Matchers#has_xpath?
128
+ #
129
+ # @param (see Capybara::Node::Finders#has_xpath?)
130
+ # @return [Boolean]
131
+ #
132
+ def has_no_xpath?(path, options={})
133
+ has_no_selector?(:xpath, path, options)
134
+ end
135
+
136
+ ##
137
+ #
138
+ # Checks if a given CSS selector is on the page or current node.
139
+ #
140
+ # page.has_css?('p#foo')
141
+ #
142
+ # By default it will check if the selector occurs at least once,
143
+ # but a different number can be specified.
144
+ #
145
+ # page.has_css?('p#foo', :count => 4)
146
+ #
147
+ # This will check if the selector occurs exactly 4 times.
148
+ #
149
+ # It also accepts all options that {Capybara::Node::Finders#all} accepts,
150
+ # such as :text and :visible.
151
+ #
152
+ # page.has_css?('li', :text => 'Horse', :visible => true)
153
+ #
154
+ # @param [String] path A CSS selector
155
+ # @param options (see Capybara::Node::Finders#all)
156
+ # @option options [Integer] :count (nil) Number of times the selector should occur
157
+ # @return [Boolean] If the selector exists
158
+ #
159
+ def has_css?(path, options={})
160
+ has_selector?(:css, path, options)
161
+ end
162
+
163
+ ##
164
+ #
165
+ # Checks if a given CSS selector is not on the page or current node.
166
+ # Usage is identical to Capybara::Node::Matchers#has_css?
167
+ #
168
+ # @param (see Capybara::Node::Finders#has_css?)
169
+ # @return [Boolean]
170
+ #
171
+ def has_no_css?(path, options={})
172
+ has_no_selector?(:css, path, options)
173
+ end
174
+
175
+ ##
176
+ #
177
+ # Checks if the page or current node has the given text content,
178
+ # ignoring any HTML tags and normalizing whitespace.
179
+ #
180
+ # Unlike has_content this only matches displayable text and specifically
181
+ # excludes text contained within non-display nodes such as script or head tags.
182
+ #
183
+ # @param [String] content The text to check for
184
+ # @return [Boolean] Whether it exists
185
+ #
186
+ def has_text?(content)
187
+ normalized_content = normalize_whitespace(content)
188
+
189
+ wait_until do
190
+ normalize_whitespace(text).include?(normalized_content) or
191
+ raise ExpectationNotMet
192
+ end
193
+ rescue Capybara::ExpectationNotMet
194
+ return false
195
+ end
196
+ alias_method :has_content?, :has_text?
197
+
198
+ ##
199
+ #
200
+ # Checks if the page or current node does not have the given text
201
+ # content, ignoring any HTML tags and normalizing whitespace.
202
+ #
203
+ # Unlike has_content this only matches displayable text and specifically
204
+ # excludes text contained within non-display nodes such as script or head tags.
205
+ #
206
+ # @param [String] content The text to check for
207
+ # @return [Boolean] Whether it exists
208
+ #
209
+ def has_no_text?(content)
210
+ normalized_content = normalize_whitespace(content)
211
+
212
+ wait_until do
213
+ !normalize_whitespace(text).include?(normalized_content) or
214
+ raise ExpectationNotMet
215
+ end
216
+ rescue Capybara::ExpectationNotMet
217
+ return false
218
+ end
219
+ alias_method :has_no_content?, :has_no_text?
220
+
221
+ ##
222
+ #
223
+ # Checks if the page or current node has a link with the given
224
+ # text or id.
225
+ #
226
+ # @param [String] locator The text or id of a link to check for
227
+ # @param options
228
+ # @option options [String] :href The value the href attribute must be
229
+ # @return [Boolean] Whether it exists
230
+ #
231
+ def has_link?(locator, options={})
232
+ has_selector?(:link, locator, options)
233
+ end
234
+
235
+ ##
236
+ #
237
+ # Checks if the page or current node has no link with the given
238
+ # text or id.
239
+ #
240
+ # @param (see Capybara::Node::Finders#has_link?)
241
+ # @return [Boolean] Whether it doesn't exist
242
+ #
243
+ def has_no_link?(locator, options={})
244
+ has_no_selector?(:link, locator, options)
245
+ end
246
+
247
+ ##
248
+ #
249
+ # Checks if the page or current node has a button with the given
250
+ # text, value or id.
251
+ #
252
+ # @param [String] locator The text, value or id of a button to check for
253
+ # @return [Boolean] Whether it exists
254
+ #
255
+ def has_button?(locator)
256
+ has_selector?(:button, locator)
257
+ end
258
+
259
+ ##
260
+ #
261
+ # Checks if the page or current node has no button with the given
262
+ # text, value or id.
263
+ #
264
+ # @param [String] locator The text, value or id of a button to check for
265
+ # @return [Boolean] Whether it doesn't exist
266
+ #
267
+ def has_no_button?(locator)
268
+ has_no_selector?(:button, locator)
269
+ end
270
+
271
+ ##
272
+ #
273
+ # Checks if the page or current node has a form field with the given
274
+ # label, name or id.
275
+ #
276
+ # For text fields and other textual fields, such as textareas and
277
+ # HTML5 email/url/etc. fields, it's possible to specify a :with
278
+ # option to specify the text the field should contain:
279
+ #
280
+ # page.has_field?('Name', :with => 'Jonas')
281
+ #
282
+ # @param [String] locator The label, name or id of a field to check for
283
+ # @option options [String] :with The text content of the field
284
+ # @return [Boolean] Whether it exists
285
+ #
286
+ def has_field?(locator, options={})
287
+ has_selector?(:field, locator, options)
288
+ end
289
+
290
+ ##
291
+ #
292
+ # Checks if the page or current node has no form field with the given
293
+ # label, name or id. See {Capybara::Node::Matchers#has_field?}.
294
+ #
295
+ # @param [String] locator The label, name or id of a field to check for
296
+ # @option options [String] :with The text content of the field
297
+ # @return [Boolean] Whether it doesn't exist
298
+ #
299
+ def has_no_field?(locator, options={})
300
+ has_no_selector?(:field, locator, options)
301
+ end
302
+
303
+ ##
304
+ #
305
+ # Checks if the page or current node has a radio button or
306
+ # checkbox with the given label, value or id, that is currently
307
+ # checked.
308
+ #
309
+ # @param [String] locator The label, name or id of a checked field
310
+ # @return [Boolean] Whether it exists
311
+ #
312
+ def has_checked_field?(locator)
313
+ has_selector?(:field, locator, :checked => true)
314
+ end
315
+
316
+ ##
317
+ #
318
+ # Checks if the page or current node has no radio button or
319
+ # checkbox with the given label, value or id, that is currently
320
+ # checked.
321
+ #
322
+ # @param [String] locator The label, name or id of a checked field
323
+ # @return [Boolean] Whether it doesn't exists
324
+ #
325
+ def has_no_checked_field?(locator)
326
+ has_no_selector?(:field, locator, :checked => true)
327
+ end
328
+
329
+ ##
330
+ #
331
+ # Checks if the page or current node has a radio button or
332
+ # checkbox with the given label, value or id, that is currently
333
+ # unchecked.
334
+ #
335
+ # @param [String] locator The label, name or id of an unchecked field
336
+ # @return [Boolean] Whether it exists
337
+ #
338
+ def has_unchecked_field?(locator)
339
+ has_selector?(:field, locator, :unchecked => true)
340
+ end
341
+
342
+ ##
343
+ #
344
+ # Checks if the page or current node has no radio button or
345
+ # checkbox with the given label, value or id, that is currently
346
+ # unchecked.
347
+ #
348
+ # @param [String] locator The label, name or id of an unchecked field
349
+ # @return [Boolean] Whether it doesn't exists
350
+ #
351
+ def has_no_unchecked_field?(locator)
352
+ has_no_selector?(:field, locator, :unchecked => true)
353
+ end
354
+
355
+ ##
356
+ #
357
+ # Checks if the page or current node has a select field with the
358
+ # given label, name or id.
359
+ #
360
+ # It can be specified which option should currently be selected:
361
+ #
362
+ # page.has_select?('Language', :selected => 'German')
363
+ #
364
+ # For multiple select boxes, several options may be specified:
365
+ #
366
+ # page.has_select?('Language', :selected => ['English', 'German'])
367
+ #
368
+ # It's also possible to check if a given set of options exists for
369
+ # this select box:
370
+ #
371
+ # page.has_select?('Language', :options => ['English', 'German'])
372
+ #
373
+ # @param [String] locator The label, name or id of a select box
374
+ # @option options [Array] :options Options which should be contained in this select box
375
+ # @option options [String, Array] :selected Options which should be selected
376
+ # @return [Boolean] Whether it exists
377
+ #
378
+ def has_select?(locator, options={})
379
+ has_selector?(:select, locator, options)
380
+ end
381
+
382
+ ##
383
+ #
384
+ # Checks if the page or current node has no select field with the
385
+ # given label, name or id. See {Capybara::Node::Matchers#has_select?}.
386
+ #
387
+ # @param (see Capybara::Node::Matchers#has_select?)
388
+ # @return [Boolean] Whether it doesn't exist
389
+ #
390
+ def has_no_select?(locator, options={})
391
+ has_no_selector?(:select, locator, options)
392
+ end
393
+
394
+ ##
395
+ #
396
+ # Checks if the page or current node has a table with the given id
397
+ # or caption.
398
+ #
399
+ # If the options :rows is given, it will check that the table contains
400
+ # the rows and columns given:
401
+ #
402
+ # page.has_table?('People', :rows => [['Jonas', '24'], ['Peter', '32']])
403
+ #
404
+ # Note that this option is quite strict, the order needs to be correct
405
+ # and the text needs to match exactly.
406
+ #
407
+ # @param [String] locator The id or caption of a table
408
+ # @return [Boolean] Whether it exist
409
+ #
410
+ def has_table?(locator, options={})
411
+ has_selector?(:table, locator, options)
412
+ end
413
+
414
+ ##
415
+ #
416
+ # Checks if the page or current node has no table with the given id
417
+ # or caption. See {Capybara::Node::Matchers#has_table?}.
418
+ #
419
+ # @param (see Capybara::Node::Matchers#has_table?)
420
+ # @return [Boolean] Whether it doesn't exist
421
+ #
422
+ def has_no_table?(locator, options={})
423
+ has_no_selector?(:table, locator, options)
424
+ end
425
+
426
+ private
427
+
428
+ ##
429
+ #
430
+ # Normalizes whitespace space by stripping leading and trailing
431
+ # whitespace and replacing sequences of whitespace characters
432
+ # with a single space.
433
+ #
434
+ # @param [String] text Text to normalize
435
+ # @return [String] Normalized text
436
+ #
437
+ def normalize_whitespace(text)
438
+ text.gsub(/\s+/, ' ').strip
439
+ end
440
+ end
441
+ end
442
+ end