nimboids-capybara 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/History.txt +289 -0
  2. data/README.rdoc +722 -0
  3. data/lib/capybara.rb +252 -0
  4. data/lib/capybara/cucumber.rb +28 -0
  5. data/lib/capybara/driver/base.rb +64 -0
  6. data/lib/capybara/driver/node.rb +74 -0
  7. data/lib/capybara/dsl.rb +168 -0
  8. data/lib/capybara/node/actions.rb +162 -0
  9. data/lib/capybara/node/base.rb +63 -0
  10. data/lib/capybara/node/document.rb +25 -0
  11. data/lib/capybara/node/element.rb +201 -0
  12. data/lib/capybara/node/finders.rb +197 -0
  13. data/lib/capybara/node/matchers.rb +417 -0
  14. data/lib/capybara/node/simple.rb +132 -0
  15. data/lib/capybara/rack_test/browser.rb +121 -0
  16. data/lib/capybara/rack_test/driver.rb +80 -0
  17. data/lib/capybara/rack_test/form.rb +80 -0
  18. data/lib/capybara/rack_test/node.rb +105 -0
  19. data/lib/capybara/rails.rb +17 -0
  20. data/lib/capybara/rspec.rb +26 -0
  21. data/lib/capybara/rspec/features.rb +22 -0
  22. data/lib/capybara/rspec/matchers.rb +154 -0
  23. data/lib/capybara/selector.rb +89 -0
  24. data/lib/capybara/selenium/driver.rb +163 -0
  25. data/lib/capybara/selenium/node.rb +91 -0
  26. data/lib/capybara/server.rb +90 -0
  27. data/lib/capybara/session.rb +321 -0
  28. data/lib/capybara/spec/driver.rb +301 -0
  29. data/lib/capybara/spec/fixtures/capybara.jpg +3 -0
  30. data/lib/capybara/spec/fixtures/test_file.txt +1 -0
  31. data/lib/capybara/spec/public/test.js +43 -0
  32. data/lib/capybara/spec/session.rb +154 -0
  33. data/lib/capybara/spec/session/all_spec.rb +78 -0
  34. data/lib/capybara/spec/session/attach_file_spec.rb +73 -0
  35. data/lib/capybara/spec/session/check_spec.rb +65 -0
  36. data/lib/capybara/spec/session/choose_spec.rb +26 -0
  37. data/lib/capybara/spec/session/click_button_spec.rb +304 -0
  38. data/lib/capybara/spec/session/click_link_or_button_spec.rb +36 -0
  39. data/lib/capybara/spec/session/click_link_spec.rb +119 -0
  40. data/lib/capybara/spec/session/current_host_spec.rb +68 -0
  41. data/lib/capybara/spec/session/current_url_spec.rb +15 -0
  42. data/lib/capybara/spec/session/fill_in_spec.rb +125 -0
  43. data/lib/capybara/spec/session/find_button_spec.rb +18 -0
  44. data/lib/capybara/spec/session/find_by_id_spec.rb +18 -0
  45. data/lib/capybara/spec/session/find_field_spec.rb +26 -0
  46. data/lib/capybara/spec/session/find_link_spec.rb +19 -0
  47. data/lib/capybara/spec/session/find_spec.rb +149 -0
  48. data/lib/capybara/spec/session/first_spec.rb +105 -0
  49. data/lib/capybara/spec/session/has_button_spec.rb +32 -0
  50. data/lib/capybara/spec/session/has_content_spec.rb +106 -0
  51. data/lib/capybara/spec/session/has_css_spec.rb +243 -0
  52. data/lib/capybara/spec/session/has_field_spec.rb +192 -0
  53. data/lib/capybara/spec/session/has_link_spec.rb +37 -0
  54. data/lib/capybara/spec/session/has_select_spec.rb +129 -0
  55. data/lib/capybara/spec/session/has_selector_spec.rb +129 -0
  56. data/lib/capybara/spec/session/has_table_spec.rb +96 -0
  57. data/lib/capybara/spec/session/has_xpath_spec.rb +123 -0
  58. data/lib/capybara/spec/session/headers.rb +19 -0
  59. data/lib/capybara/spec/session/javascript.rb +289 -0
  60. data/lib/capybara/spec/session/response_code.rb +19 -0
  61. data/lib/capybara/spec/session/select_spec.rb +113 -0
  62. data/lib/capybara/spec/session/text_spec.rb +19 -0
  63. data/lib/capybara/spec/session/uncheck_spec.rb +21 -0
  64. data/lib/capybara/spec/session/unselect_spec.rb +61 -0
  65. data/lib/capybara/spec/session/within_spec.rb +178 -0
  66. data/lib/capybara/spec/test_app.rb +142 -0
  67. data/lib/capybara/spec/views/buttons.erb +4 -0
  68. data/lib/capybara/spec/views/fieldsets.erb +29 -0
  69. data/lib/capybara/spec/views/form.erb +365 -0
  70. data/lib/capybara/spec/views/frame_one.erb +8 -0
  71. data/lib/capybara/spec/views/frame_two.erb +8 -0
  72. data/lib/capybara/spec/views/header_links.erb +7 -0
  73. data/lib/capybara/spec/views/host_links.erb +12 -0
  74. data/lib/capybara/spec/views/popup_one.erb +8 -0
  75. data/lib/capybara/spec/views/popup_two.erb +8 -0
  76. data/lib/capybara/spec/views/postback.erb +13 -0
  77. data/lib/capybara/spec/views/tables.erb +122 -0
  78. data/lib/capybara/spec/views/with_html.erb +78 -0
  79. data/lib/capybara/spec/views/with_html_entities.erb +1 -0
  80. data/lib/capybara/spec/views/with_js.erb +48 -0
  81. data/lib/capybara/spec/views/with_scope.erb +36 -0
  82. data/lib/capybara/spec/views/with_simple_html.erb +1 -0
  83. data/lib/capybara/spec/views/within_frames.erb +10 -0
  84. data/lib/capybara/spec/views/within_popups.erb +25 -0
  85. data/lib/capybara/util/save_and_open_page.rb +44 -0
  86. data/lib/capybara/util/timeout.rb +27 -0
  87. data/lib/capybara/version.rb +3 -0
  88. data/spec/basic_node_spec.rb +77 -0
  89. data/spec/capybara_spec.rb +46 -0
  90. data/spec/driver/rack_test_driver_spec.rb +89 -0
  91. data/spec/driver/selenium_driver_spec.rb +50 -0
  92. data/spec/dsl_spec.rb +253 -0
  93. data/spec/fixtures/selenium_driver_rspec_failure.rb +8 -0
  94. data/spec/fixtures/selenium_driver_rspec_success.rb +8 -0
  95. data/spec/rspec/features_spec.rb +45 -0
  96. data/spec/rspec/matchers_spec.rb +495 -0
  97. data/spec/rspec_spec.rb +53 -0
  98. data/spec/save_and_open_page_spec.rb +155 -0
  99. data/spec/server_spec.rb +89 -0
  100. data/spec/session/rack_test_session_spec.rb +55 -0
  101. data/spec/session/selenium_session_spec.rb +26 -0
  102. data/spec/spec_helper.rb +30 -0
  103. data/spec/string_spec.rb +77 -0
  104. data/spec/timeout_spec.rb +28 -0
  105. metadata +346 -0
@@ -0,0 +1,197 @@
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(:xpath, XPath::HTML.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(:xpath, XPath::HTML.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(:xpath, XPath::HTML.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(:css, "##{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
+ # @param [:css, :xpath, String] kind_or_locator Either the kind of selector or the selector itself
103
+ # @param [String] locator The selector
104
+ # @param [Hash{Symbol => Object}] options Additional options
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
107
+ # @return [Capybara::Element] The found elements
108
+ #
109
+ def all(*args)
110
+ options = extract_normalized_options(args)
111
+
112
+ selector = Capybara::Selector.normalize(*args)
113
+ selector.xpaths.
114
+ map { |path| find_in_base(selector, path) }.flatten.
115
+ select { |node| matches_options(node, options) }
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
+ # When only the first matching element is needed, this method can
124
+ # be faster than all(*args).first.
125
+ #
126
+ # @param [:css, :xpath, String] kind_or_locator Either the kind of selector or the selector itself
127
+ # @param [String] locator The selector
128
+ # @param [Hash{Symbol => Object}] options Additional options; see {all}
129
+ # @return Capybara::Element The found element
130
+ #
131
+ def first(*args)
132
+ options = extract_normalized_options(args)
133
+ found_elements = []
134
+
135
+ selector = Capybara::Selector.normalize(*args)
136
+ selector.xpaths.each do |path|
137
+ find_in_base(selector, path).each do |node|
138
+ if matches_options(node, options)
139
+ found_elements << node
140
+ return found_elements.last if not Capybara.prefer_visible_elements or node.visible?
141
+ end
142
+ end
143
+ end
144
+ found_elements.first
145
+ end
146
+
147
+ protected
148
+
149
+ def raise_find_error(*args)
150
+ options = extract_normalized_options(args)
151
+ normalized = Capybara::Selector.normalize(*args)
152
+ message = options[:message] || "Unable to find #{normalized.name} #{normalized.locator.inspect}"
153
+ message = normalized.failure_message.call(self, normalized) if normalized.failure_message
154
+ raise Capybara::ElementNotFound, message
155
+ end
156
+
157
+ def find_in_base(selector, xpath)
158
+ base.find(xpath).map do |node|
159
+ Capybara::Node::Element.new(session, node, self, selector)
160
+ end
161
+ end
162
+
163
+ def extract_normalized_options(args)
164
+ options = if args.last.is_a?(Hash) then args.pop.dup else {} end
165
+
166
+ if text = options[:text]
167
+ options[:text] = Regexp.escape(text) unless text.kind_of?(Regexp)
168
+ end
169
+
170
+ if !options.has_key?(:visible)
171
+ options[:visible] = Capybara.ignore_hidden_elements
172
+ end
173
+
174
+ if selected = options[:selected]
175
+ options[:selected] = [selected].flatten
176
+ end
177
+
178
+ options
179
+ end
180
+
181
+ def matches_options(node, options)
182
+ return false if options[:text] and not node.text.match(options[:text])
183
+ return false if options[:visible] and not node.visible?
184
+ return false if options[:with] and not node.value == options[:with]
185
+ return false if options[:checked] and not node.checked?
186
+ return false if options[:unchecked] and node.checked?
187
+ return false if options[:selected] and not has_selected_options?(node, options[:selected])
188
+ true
189
+ end
190
+
191
+ def has_selected_options?(node, expected)
192
+ actual = node.all(:xpath, './/option').select { |option| option.selected? }.map { |option| option.text }
193
+ (expected - actual).empty?
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,417 @@
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_xpath?(XPath.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_xpath?(XPath.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
+ # @param [String] content The text to check for
181
+ # @return [Boolean] Whether it exists
182
+ #
183
+ def has_content?(content)
184
+ has_xpath?(XPath::HTML.content(content))
185
+ end
186
+
187
+ ##
188
+ #
189
+ # Checks if the page or current node does not have the given text
190
+ # content, ignoring any HTML tags and normalizing whitespace.
191
+ #
192
+ # @param [String] content The text to check for
193
+ # @return [Boolean] Whether it exists
194
+ #
195
+ def has_no_content?(content)
196
+ has_no_xpath?(XPath::HTML.content(content))
197
+ end
198
+
199
+ ##
200
+ #
201
+ # Checks if the page or current node has a link with the given
202
+ # text or id.
203
+ #
204
+ # @param [String] locator The text or id of a link to check for
205
+ # @param options
206
+ # @option options [String] :href The value the href attribute must be
207
+ # @return [Boolean] Whether it exists
208
+ #
209
+ def has_link?(locator, options={})
210
+ has_xpath?(XPath::HTML.link(locator, options))
211
+ end
212
+
213
+ ##
214
+ #
215
+ # Checks if the page or current node has no link with the given
216
+ # text or id.
217
+ #
218
+ # @param (see Capybara::Node::Finders#has_link?)
219
+ # @return [Boolean] Whether it doesn't exist
220
+ #
221
+ def has_no_link?(locator, options={})
222
+ has_no_xpath?(XPath::HTML.link(locator, options))
223
+ end
224
+
225
+ ##
226
+ #
227
+ # Checks if the page or current node has a button with the given
228
+ # text, value or id.
229
+ #
230
+ # @param [String] locator The text, value or id of a button to check for
231
+ # @return [Boolean] Whether it exists
232
+ #
233
+ def has_button?(locator)
234
+ has_xpath?(XPath::HTML.button(locator))
235
+ end
236
+
237
+ ##
238
+ #
239
+ # Checks if the page or current node has no button with the given
240
+ # text, value or id.
241
+ #
242
+ # @param [String] locator The text, value or id of a button to check for
243
+ # @return [Boolean] Whether it doesn't exist
244
+ #
245
+ def has_no_button?(locator)
246
+ has_no_xpath?(XPath::HTML.button(locator))
247
+ end
248
+
249
+ ##
250
+ #
251
+ # Checks if the page or current node has a form field with the given
252
+ # label, name or id.
253
+ #
254
+ # For text fields and other textual fields, such as textareas and
255
+ # HTML5 email/url/etc. fields, it's possible to specify a :with
256
+ # option to specify the text the field should contain:
257
+ #
258
+ # page.has_field?('Name', :with => 'Jonas')
259
+ #
260
+ # @param [String] locator The label, name or id of a field to check for
261
+ # @option options [String] :with The text content of the field
262
+ # @return [Boolean] Whether it exists
263
+ #
264
+ def has_field?(locator, options={})
265
+ options, with = split_options(options, :with)
266
+ has_xpath?(XPath::HTML.field(locator, options), with)
267
+ end
268
+
269
+ ##
270
+ #
271
+ # Checks if the page or current node has no form field with the given
272
+ # label, name or id. See {Capybara::Node::Matchers#has_field?}.
273
+ #
274
+ # @param [String] locator The label, name or id of a field to check for
275
+ # @option options [String] :with The text content of the field
276
+ # @return [Boolean] Whether it doesn't exist
277
+ #
278
+ def has_no_field?(locator, options={})
279
+ options, with = split_options(options, :with)
280
+ has_no_xpath?(XPath::HTML.field(locator, options), with)
281
+ end
282
+
283
+ ##
284
+ #
285
+ # Checks if the page or current node has a radio button or
286
+ # checkbox with the given label, value or id, that is currently
287
+ # checked.
288
+ #
289
+ # @param [String] locator The label, name or id of a checked field
290
+ # @return [Boolean] Whether it exists
291
+ #
292
+ def has_checked_field?(locator)
293
+ has_xpath?(XPath::HTML.field(locator), :checked => true)
294
+ end
295
+
296
+ ##
297
+ #
298
+ # Checks if the page or current node has no radio button or
299
+ # checkbox with the given label, value or id, that is currently
300
+ # checked.
301
+ #
302
+ # @param [String] locator The label, name or id of a checked field
303
+ # @return [Boolean] Whether it doesn't exists
304
+ #
305
+ def has_no_checked_field?(locator)
306
+ has_no_xpath?(XPath::HTML.field(locator), :checked => true)
307
+ end
308
+
309
+ ##
310
+ #
311
+ # Checks if the page or current node has a radio button or
312
+ # checkbox with the given label, value or id, that is currently
313
+ # unchecked.
314
+ #
315
+ # @param [String] locator The label, name or id of an unchecked field
316
+ # @return [Boolean] Whether it exists
317
+ #
318
+ def has_unchecked_field?(locator)
319
+ has_xpath?(XPath::HTML.field(locator), :unchecked => true)
320
+ end
321
+
322
+ ##
323
+ #
324
+ # Checks if the page or current node has no radio button or
325
+ # checkbox with the given label, value or id, that is currently
326
+ # unchecked.
327
+ #
328
+ # @param [String] locator The label, name or id of an unchecked field
329
+ # @return [Boolean] Whether it doesn't exists
330
+ #
331
+ def has_no_unchecked_field?(locator)
332
+ has_no_xpath?(XPath::HTML.field(locator), :unchecked => true)
333
+ end
334
+
335
+ ##
336
+ #
337
+ # Checks if the page or current node has a select field with the
338
+ # given label, name or id.
339
+ #
340
+ # It can be specified which option should currently be selected:
341
+ #
342
+ # page.has_select?('Language', :selected => 'German')
343
+ #
344
+ # For multiple select boxes, several options may be specified:
345
+ #
346
+ # page.has_select?('Language', :selected => ['English', 'German'])
347
+ #
348
+ # It's also possible to check if a given set of options exists for
349
+ # this select box:
350
+ #
351
+ # page.has_select?('Language', :options => ['English', 'German'])
352
+ #
353
+ # @param [String] locator The label, name or id of a select box
354
+ # @option options [Array] :options Options which should be contained in this select box
355
+ # @option options [String, Array] :selected Options which should be selected
356
+ # @return [Boolean] Whether it exists
357
+ #
358
+ def has_select?(locator, options={})
359
+ options, selected = split_options(options, :selected)
360
+ has_xpath?(XPath::HTML.select(locator, options), selected)
361
+ end
362
+
363
+ ##
364
+ #
365
+ # Checks if the page or current node has no select field with the
366
+ # given label, name or id. See {Capybara::Node::Matchers#has_select?}.
367
+ #
368
+ # @param (see Capybara::Node::Matchers#has_select?)
369
+ # @return [Boolean] Whether it doesn't exist
370
+ #
371
+ def has_no_select?(locator, options={})
372
+ options, selected = split_options(options, :selected)
373
+ has_no_xpath?(XPath::HTML.select(locator, options), selected)
374
+ end
375
+
376
+ ##
377
+ #
378
+ # Checks if the page or current node has a table with the given id
379
+ # or caption.
380
+ #
381
+ # If the options :rows is given, it will check that the table contains
382
+ # the rows and columns given:
383
+ #
384
+ # page.has_table?('People', :rows => [['Jonas', '24'], ['Peter', '32']])
385
+ #
386
+ # Note that this option is quite strict, the order needs to be correct
387
+ # and the text needs to match exactly.
388
+ #
389
+ # @param [String] locator The id or caption of a table
390
+ # @option options [Array[Array[String]]] :rows A set of rows the table should contain
391
+ # @return [Boolean] Whether it exist
392
+ #
393
+ def has_table?(locator, options={})
394
+ has_xpath?(XPath::HTML.table(locator, options))
395
+ end
396
+
397
+ ##
398
+ #
399
+ # Checks if the page or current node has no table with the given id
400
+ # or caption. See {Capybara::Node::Matchers#has_table?}.
401
+ #
402
+ # @param (see Capybara::Node::Matchers#has_table?)
403
+ # @return [Boolean] Whether it doesn't exist
404
+ #
405
+ def has_no_table?(locator, options={})
406
+ has_no_xpath?(XPath::HTML.table(locator, options))
407
+ end
408
+
409
+ protected
410
+
411
+ def split_options(options, key)
412
+ options = options.dup
413
+ [options, if options.has_key?(key) then {key => options.delete(key)} else {} end]
414
+ end
415
+ end
416
+ end
417
+ end