capybara 0.3.9 → 0.4.0.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/History.txt +43 -1
  2. data/README.rdoc +168 -98
  3. data/lib/capybara.rb +77 -15
  4. data/lib/capybara/driver/base.rb +21 -16
  5. data/lib/capybara/driver/celerity_driver.rb +39 -41
  6. data/lib/capybara/driver/culerity_driver.rb +2 -1
  7. data/lib/capybara/driver/node.rb +66 -0
  8. data/lib/capybara/driver/rack_test_driver.rb +66 -67
  9. data/lib/capybara/driver/selenium_driver.rb +43 -47
  10. data/lib/capybara/dsl.rb +44 -6
  11. data/lib/capybara/node.rb +185 -24
  12. data/lib/capybara/node/actions.rb +170 -0
  13. data/lib/capybara/node/finders.rb +150 -0
  14. data/lib/capybara/node/matchers.rb +360 -0
  15. data/lib/capybara/rails.rb +1 -0
  16. data/lib/capybara/selector.rb +52 -0
  17. data/lib/capybara/server.rb +68 -87
  18. data/lib/capybara/session.rb +221 -207
  19. data/lib/capybara/spec/driver.rb +45 -35
  20. data/lib/capybara/spec/public/test.js +1 -1
  21. data/lib/capybara/spec/session.rb +28 -53
  22. data/lib/capybara/spec/session/all_spec.rb +7 -3
  23. data/lib/capybara/spec/session/check_spec.rb +50 -52
  24. data/lib/capybara/spec/session/click_button_spec.rb +9 -0
  25. data/lib/capybara/spec/session/click_link_or_button_spec.rb +37 -0
  26. data/lib/capybara/spec/session/current_url_spec.rb +7 -0
  27. data/lib/capybara/spec/session/find_button_spec.rb +4 -2
  28. data/lib/capybara/spec/session/find_by_id_spec.rb +4 -2
  29. data/lib/capybara/spec/session/find_field_spec.rb +7 -3
  30. data/lib/capybara/spec/session/find_link_spec.rb +5 -3
  31. data/lib/capybara/spec/session/find_spec.rb +71 -6
  32. data/lib/capybara/spec/session/has_field_spec.rb +1 -1
  33. data/lib/capybara/spec/session/has_selector_spec.rb +129 -0
  34. data/lib/capybara/spec/session/has_xpath_spec.rb +4 -4
  35. data/lib/capybara/spec/session/javascript.rb +25 -5
  36. data/lib/capybara/spec/session/select_spec.rb +16 -2
  37. data/lib/capybara/spec/session/unselect_spec.rb +8 -1
  38. data/lib/capybara/spec/session/within_spec.rb +5 -5
  39. data/lib/capybara/spec/views/form.erb +65 -1
  40. data/lib/capybara/spec/views/popup_one.erb +8 -0
  41. data/lib/capybara/spec/views/popup_two.erb +8 -0
  42. data/lib/capybara/spec/views/with_html.erb +5 -0
  43. data/lib/capybara/spec/views/within_popups.erb +25 -0
  44. data/lib/capybara/{save_and_open_page.rb → util/save_and_open_page.rb} +3 -3
  45. data/lib/capybara/util/timeout.rb +27 -0
  46. data/lib/capybara/version.rb +1 -1
  47. data/spec/capybara_spec.rb +18 -8
  48. data/spec/driver/celerity_driver_spec.rb +10 -14
  49. data/spec/driver/culerity_driver_spec.rb +4 -3
  50. data/spec/driver/rack_test_driver_spec.rb +39 -2
  51. data/spec/driver/remote_culerity_driver_spec.rb +5 -7
  52. data/spec/driver/remote_selenium_driver_spec.rb +7 -10
  53. data/spec/driver/selenium_driver_spec.rb +3 -2
  54. data/spec/dsl_spec.rb +5 -14
  55. data/spec/save_and_open_page_spec.rb +19 -19
  56. data/spec/server_spec.rb +22 -10
  57. data/spec/session/celerity_session_spec.rb +17 -21
  58. data/spec/session/culerity_session_spec.rb +3 -3
  59. data/spec/session/rack_test_session_spec.rb +2 -2
  60. data/spec/session/selenium_session_spec.rb +2 -2
  61. data/spec/spec_helper.rb +27 -6
  62. data/spec/{wait_until_spec.rb → timeout_spec.rb} +14 -14
  63. metadata +88 -46
  64. data/lib/capybara/searchable.rb +0 -54
  65. data/lib/capybara/spec/session/click_spec.rb +0 -24
  66. data/lib/capybara/spec/session/locate_spec.rb +0 -65
  67. data/lib/capybara/wait_until.rb +0 -28
  68. data/lib/capybara/xpath.rb +0 -179
  69. data/spec/searchable_spec.rb +0 -66
  70. data/spec/xpath_spec.rb +0 -180
@@ -0,0 +1,170 @@
1
+ module Capybara
2
+ class Node
3
+ module Actions
4
+
5
+ ##
6
+ #
7
+ # Finds a button or link by id, text or value and clicks it. Also looks at image
8
+ # alt text inside the link.
9
+ #
10
+ # @param [String] locator Text, id or value of link or button
11
+ #
12
+ def click_link_or_button(locator)
13
+ msg = "no link or button '#{locator}' found"
14
+ find(:xpath, XPath::HTML.link_or_button(locator), :message => msg).click
15
+ end
16
+
17
+ ##
18
+ #
19
+ # Finds a link by id or text and clicks it. Also looks at image
20
+ # alt text inside the link.
21
+ #
22
+ # @param [String] locator Text, id or text of link
23
+ #
24
+ def click_link(locator)
25
+ msg = "no link with title, id or text '#{locator}' found"
26
+ find(:xpath, XPath::HTML.link(locator), :message => msg).click
27
+ end
28
+
29
+ ##
30
+ #
31
+ # Finds a button by id, text or value and clicks it.
32
+ #
33
+ # @param [String] locator Text, id or value of button
34
+ #
35
+ def click_button(locator)
36
+ msg = "no button with value or id or text '#{locator}' found"
37
+ find(:xpath, XPath::HTML.button(locator), :message => msg).click
38
+ end
39
+
40
+ ##
41
+ #
42
+ # Locate a text field or text area and fill it in with the given text
43
+ # The field can be found via its name, id or label text.
44
+ #
45
+ # page.fill_in 'Name', :with => 'Bob'
46
+ #
47
+ # @param [String] locator Which field to fill in
48
+ # @param [Hash{:with => String}] The value to fill in
49
+ #
50
+ def fill_in(locator, options={})
51
+ msg = "cannot fill in, no text field, text area or password field with id, name, or label '#{locator}' found"
52
+ raise "Must pass a hash containing 'with'" if not options.is_a?(Hash) or not options.has_key?(:with)
53
+ find(:xpath, XPath::HTML.fillable_field(locator), :message => msg).set(options[:with])
54
+ end
55
+
56
+ ##
57
+ #
58
+ # Find a radio button and mark it as checked. The radio button can be found
59
+ # via name, id or label text.
60
+ #
61
+ # page.choose('Male')
62
+ #
63
+ # @param [String] locator Which radio button to choose
64
+ #
65
+ def choose(locator)
66
+ msg = "cannot choose field, no radio button with id, name, or label '#{locator}' found"
67
+ find(:xpath, XPath::HTML.radio_button(locator), :message => msg).set(true)
68
+ end
69
+
70
+ ##
71
+ #
72
+ # Find a check box and mark it as checked. The check box can be found
73
+ # via name, id or label text.
74
+ #
75
+ # page.check('German')
76
+ #
77
+ # @param [String] locator Which check box to check
78
+ #
79
+ def check(locator)
80
+ msg = "cannot check field, no checkbox with id, name, or label '#{locator}' found"
81
+ find(:xpath, XPath::HTML.checkbox(locator), :message => msg).set(true)
82
+ end
83
+
84
+ ##
85
+ #
86
+ # Find a check box and mark uncheck it. The check box can be found
87
+ # via name, id or label text.
88
+ #
89
+ # page.uncheck('German')
90
+ #
91
+ # @param [String] locator Which check box to uncheck
92
+ #
93
+ def uncheck(locator)
94
+ msg = "cannot uncheck field, no checkbox with id, name, or label '#{locator}' found"
95
+ find(:xpath, XPath::HTML.checkbox(locator), :message => msg).set(false)
96
+ end
97
+
98
+ ##
99
+ #
100
+ # Find a select box on the page and select a particular option from it. If the select
101
+ # box is a multiple select, +select+ can be called multiple times to select more than
102
+ # one option. The select box can be found via its name, id or label text.
103
+ #
104
+ # page.uncheck('German')
105
+ #
106
+ # @param [String] locator Which check box to uncheck
107
+ #
108
+ def select(value, options={})
109
+ if options.has_key?(:from)
110
+ no_select_msg = "cannot select option, no select box with id, name, or label '#{options[:from]}' found"
111
+ no_option_msg = "cannot select option, no option with text '#{value}' in select box '#{options[:from]}'"
112
+ select = find(:xpath, XPath::HTML.select(options[:from]), :message => no_select_msg)
113
+ select.find(:xpath, XPath::HTML.option(value), :message => no_option_msg).select_option
114
+ else
115
+ no_option_msg = "cannot select option, no option with text '#{value}'"
116
+ find(:xpath, XPath::HTML.option(value), :message => no_option_msg).select_option
117
+ end
118
+ end
119
+
120
+ ##
121
+ #
122
+ # Find a select box on the page and select a particular option from it. If the select
123
+ # box is a multiple select, +select+ can be called multiple times to select more than
124
+ # one option. The select box can be found via its name, id or label text.
125
+ #
126
+ # page.uncheck('German')
127
+ #
128
+ # @param [String] locator Which check box to uncheck
129
+ #
130
+ def unselect(value, options={})
131
+ if options.has_key?(:from)
132
+ no_select_msg = "cannot unselect option, no select box with id, name, or label '#{options[:from]}' found"
133
+ no_option_msg = "cannot unselect option, no option with text '#{value}' in select box '#{options[:from]}'"
134
+ select = find(:xpath, XPath::HTML.select(options[:from]), :message => no_select_msg)
135
+ select.find(:xpath, XPath::HTML.option(value), :message => no_option_msg).unselect_option
136
+ else
137
+ no_option_msg = "cannot unselect option, no option with text '#{value}'"
138
+ find(:xpath, XPath::HTML.option(value), :message => no_option_msg).unselect_option
139
+ end
140
+ end
141
+
142
+ ##
143
+ #
144
+ # Find a file field on the page and attach a file given its path. The file field can
145
+ # be found via its name, id or label text.
146
+ #
147
+ # page.attach_file(locator, '/path/to/file.png')
148
+ #
149
+ # @param [String] locator Which field to attach the file to
150
+ # @param [String] path The path of the file that will be attached
151
+ #
152
+ def attach_file(locator, path)
153
+ msg = "cannot attach file, no file field with id, name, or label '#{locator}' found"
154
+ find(:xpath, XPath::HTML.file_field(locator), :message => msg).set(path)
155
+ end
156
+
157
+ ##
158
+ #
159
+ # Drag one element to another
160
+ #
161
+ # @deprecated Use Capybara::Element#drag_to instead.
162
+ #
163
+ def drag(source_locator, target_locator)
164
+ source = find(:xpath, source_locator, :message => "drag source '#{source_locator}' not found on page")
165
+ target = find(:xpath, target_locator, :message => "drag target '#{target_locator}' not found on page")
166
+ source.drag_to(target)
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,150 @@
1
+ module Capybara
2
+ class 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
+ node = wait_conditionally_until { all(*args).first }
28
+ ensure
29
+ options = if args.last.is_a?(Hash) then args.last else {} end
30
+ raise Capybara::ElementNotFound, options[:message] || "Unable to find '#{args[1] || args[0]}'" unless node
31
+ return node
32
+ end
33
+
34
+ ##
35
+ #
36
+ # @deprecated {#find} now behaves like locate used to. Use {#find} instead.
37
+ #
38
+ def locate(*args)
39
+ Capybara.deprecate("locate", "find")
40
+ find(*args)
41
+ end
42
+
43
+ ##
44
+ #
45
+ # Find a form field on the page. The field can be found by its name, id or label text.
46
+ #
47
+ # @param [String] locator Which field to find
48
+ # @return [Capybara::Element] The found element
49
+ #
50
+ def find_field(locator)
51
+ find(:xpath, XPath::HTML.field(locator))
52
+ end
53
+ alias_method :field_labeled, :find_field
54
+
55
+ ##
56
+ #
57
+ # Find a link on the page. The link can be found by its id or text.
58
+ #
59
+ # @param [String] locator Which link to find
60
+ # @return [Capybara::Element] The found element
61
+ #
62
+ def find_link(locator)
63
+ find(:xpath, XPath::HTML.link(locator))
64
+ end
65
+
66
+ ##
67
+ #
68
+ # Find a button on the page. The link can be found by its id, name or value.
69
+ #
70
+ # @param [String] locator Which button to find
71
+ # @return [Capybara::Element] The found element
72
+ #
73
+ def find_button(locator)
74
+ find(:xpath, XPath::HTML.button(locator))
75
+ end
76
+
77
+ ##
78
+ #
79
+ # Find a element on the page, given its id.
80
+ #
81
+ # @param [String] locator Which element to find
82
+ # @return [Capybara::Element] The found element
83
+ #
84
+ def find_by_id(id)
85
+ find(:css, "##{id}")
86
+ end
87
+
88
+ ##
89
+ #
90
+ # Find all elements on the page matching the given selector
91
+ # and options.
92
+ #
93
+ # Both XPath and CSS expressions are supported, but Capybara
94
+ # does not try to automatically distinguish between them. The
95
+ # following statements are equivalent:
96
+ #
97
+ # page.all(:css, 'a#person_123')
98
+ # page.all(:xpath, '//a[@id="person_123"]')
99
+ #
100
+ #
101
+ # If the type of selector is left out, Capybara uses
102
+ # {Capybara.default_selector}. It's set to :css by default.
103
+ #
104
+ # page.all("a#person_123")
105
+ #
106
+ # Capybara.default_selector = :xpath
107
+ # page.all('//a[@id="person_123"]')
108
+ #
109
+ # The set of found elements can further be restricted by specifying
110
+ # options. It's possible to select elements by their text or visibility:
111
+ #
112
+ # page.all('a', :text => 'Home')
113
+ # page.all('#menu li', :visible => true)
114
+ #
115
+ # @param [:css, :xpath, String] kind_or_locator Either the kind of selector or the selector itself
116
+ # @param [String] locator The selector
117
+ # @param [Hash{Symbol => Object}] options Additional options
118
+ # @option options [String, Regexp] text Only find elements which contain this text or match this regexp
119
+ # @option options [Boolean] visible Only find elements that are visible on the page
120
+ # @return [Capybara::Element] The found elements
121
+ #
122
+ def all(*args)
123
+ options = if args.last.is_a?(Hash) then args.pop else {} end
124
+
125
+ results = Capybara::Selector.normalize(*args).map do |path|
126
+ base.find(path)
127
+ end.flatten
128
+
129
+ if text = options[:text]
130
+ text = Regexp.escape(text) unless text.kind_of?(Regexp)
131
+
132
+ results = results.select { |node| node.text.match(text) }
133
+ end
134
+
135
+ if options[:visible] or Capybara.ignore_hidden_elements
136
+ results = results.select { |node| node.visible? }
137
+ end
138
+
139
+ results.map { |n| Capybara::Element.new(session, n) }
140
+ end
141
+
142
+ protected
143
+
144
+ def wait_conditionally_until
145
+ if driver.wait? then session.wait_until { yield } else yield end
146
+ end
147
+
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,360 @@
1
+ module Capybara
2
+ class 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_conditionally_until do
38
+ results = all(*args)
39
+
40
+ if options[:count]
41
+ results.size == options[:count]
42
+ else
43
+ results.size > 0
44
+ end
45
+ end
46
+ rescue Capybara::TimeoutError
47
+ return false
48
+ end
49
+
50
+ ##
51
+ #
52
+ # Checks if a given selector is not on the page or current node.
53
+ # Usage is identical to Capybara::Node::Matchers#has_selector?
54
+ #
55
+ # @param (see Capybara::Node::Finders#has_selector?)
56
+ # @return [Boolean]
57
+ #
58
+ def has_no_selector?(*args)
59
+ options = if args.last.is_a?(Hash) then args.last else {} end
60
+ wait_conditionally_until do
61
+ results = all(*args)
62
+
63
+ if options[:count]
64
+ results.size != options[:count]
65
+ else
66
+ results.empty?
67
+ end
68
+ end
69
+ rescue Capybara::TimeoutError
70
+ return false
71
+ end
72
+
73
+ ##
74
+ #
75
+ # Checks if a given XPath expression is on the page or current node.
76
+ #
77
+ # page.has_xpath?('.//p[@id="foo"]')
78
+ #
79
+ # By default it will check if the expression occurs at least once,
80
+ # but a different number can be specified.
81
+ #
82
+ # page.has_xpath?('.//p[@id="foo"]', :count => 4)
83
+ #
84
+ # This will check if the expression occurs exactly 4 times.
85
+ #
86
+ # It also accepts all options that {Capybara::Node::Finders#all} accepts,
87
+ # such as :text and :visible.
88
+ #
89
+ # page.has_xpath?('.//li', :text => 'Horse', :visible => true)
90
+ #
91
+ # has_xpath? can also accept XPath expressions generate by the
92
+ # XPath gem:
93
+ #
94
+ # xpath = XPath.generate { |x| x.descendant(:p) }
95
+ # page.has_xpath?(xpath)
96
+ #
97
+ # @param [String] path An XPath expression
98
+ # @param options (see Capybara::Node::Finders#all)
99
+ # @option options [Integer] :count (nil) Number of times the expression should occur
100
+ # @return [Boolean] If the expression exists
101
+ #
102
+ def has_xpath?(path, options={})
103
+ has_selector?(:xpath, path, options)
104
+ end
105
+
106
+ ##
107
+ #
108
+ # Checks if a given XPath expression is not on the page or current node.
109
+ # Usage is identical to Capybara::Node::Matchers#has_xpath?
110
+ #
111
+ # @param (see Capybara::Node::Finders#has_xpath?)
112
+ # @return [Boolean]
113
+ #
114
+ def has_no_xpath?(path, options={})
115
+ has_no_selector?(:xpath, path, options)
116
+ end
117
+
118
+ ##
119
+ #
120
+ # Checks if a given CSS selector is on the page or current node.
121
+ #
122
+ # page.has_css?('p#foo')
123
+ #
124
+ # By default it will check if the selector occurs at least once,
125
+ # but a different number can be specified.
126
+ #
127
+ # page.has_css?('p#foo', :count => 4)
128
+ #
129
+ # This will check if the selector occurs exactly 4 times.
130
+ #
131
+ # It also accepts all options that {Capybara::Node::Finders#all} accepts,
132
+ # such as :text and :visible.
133
+ #
134
+ # page.has_css?('li', :text => 'Horse', :visible => true)
135
+ #
136
+ # @param [String] path A CSS selector
137
+ # @param options (see Capybara::Node::Finders#all)
138
+ # @option options [Integer] :count (nil) Number of times the selector should occur
139
+ # @return [Boolean] If the selector exists
140
+ #
141
+ def has_css?(path, options={})
142
+ has_xpath?(XPath.css(path), options)
143
+ end
144
+
145
+ ##
146
+ #
147
+ # Checks if a given CSS selector is not on the page or current node.
148
+ # Usage is identical to Capybara::Node::Matchers#has_css?
149
+ #
150
+ # @param (see Capybara::Node::Finders#has_css?)
151
+ # @return [Boolean]
152
+ #
153
+ def has_no_css?(path, options={})
154
+ has_no_xpath?(XPath.css(path), options)
155
+ end
156
+
157
+ ##
158
+ #
159
+ # Checks if the page or current node has the given text content,
160
+ # ignoring any HTML tags and normalizing whitespace.
161
+ #
162
+ # @param [String] content The text to check for
163
+ # @return [Boolean] Whether it exists
164
+ #
165
+ def has_content?(content)
166
+ has_xpath?(XPath::HTML.content(content))
167
+ end
168
+
169
+ ##
170
+ #
171
+ # Checks if the page or current node does not have the given text
172
+ # content, ignoring any HTML tags and normalizing whitespace.
173
+ #
174
+ # @param [String] content The text to check for
175
+ # @return [Boolean] Whether it exists
176
+ #
177
+ def has_no_content?(content)
178
+ has_no_xpath?(XPath::HTML.content(content))
179
+ end
180
+
181
+ ##
182
+ #
183
+ # Checks if the page or current node has a link with the given
184
+ # text or id.
185
+ #
186
+ # @param [String] locator The text or id of a link to check for
187
+ # @return [Boolean] Whether it exists
188
+ #
189
+ def has_link?(locator)
190
+ has_xpath?(XPath::HTML.link(locator))
191
+ end
192
+
193
+ ##
194
+ #
195
+ # Checks if the page or current node has no link with the given
196
+ # text or id.
197
+ #
198
+ # @param [String] locator The text or id of a link to check for
199
+ # @return [Boolean] Whether it doesn't exist
200
+ #
201
+ def has_no_link?(locator)
202
+ has_no_xpath?(XPath::HTML.link(locator))
203
+ end
204
+
205
+ ##
206
+ #
207
+ # Checks if the page or current node has a button with the given
208
+ # text, value or id.
209
+ #
210
+ # @param [String] locator The text, value or id of a button to check for
211
+ # @return [Boolean] Whether it exists
212
+ #
213
+ def has_button?(locator)
214
+ has_xpath?(XPath::HTML.button(locator))
215
+ end
216
+
217
+ ##
218
+ #
219
+ # Checks if the page or current node has no button with the given
220
+ # text, value or id.
221
+ #
222
+ # @param [String] locator The text, value or id of a button to check for
223
+ # @return [Boolean] Whether it doesn't exist
224
+ #
225
+ def has_no_button?(locator)
226
+ has_no_xpath?(XPath::HTML.button(locator))
227
+ end
228
+
229
+ ##
230
+ #
231
+ # Checks if the page or current node has a form field with the given
232
+ # label, name or id.
233
+ #
234
+ # For text fields and other textual fields, such as textareas and
235
+ # HTML5 email/url/etc. fields, it's possible to specify a :with
236
+ # option to specify the text the field should contain:
237
+ #
238
+ # page.has_field?('Name', :with => 'Jonas')
239
+ #
240
+ # @param [String] locator The label, name or id of a field to check for
241
+ # @option options [String] :with The text content of the field
242
+ # @return [Boolean] Whether it exists
243
+ #
244
+ def has_field?(locator, options={})
245
+ has_xpath?(XPath::HTML.field(locator, options))
246
+ end
247
+
248
+ ##
249
+ #
250
+ # Checks if the page or current node has no form field with the given
251
+ # label, name or id. See {Capybara::Node::Matchers#has_field?}.
252
+ #
253
+ # @param [String] locator The label, name or id of a field to check for
254
+ # @option options [String] :with The text content of the field
255
+ # @return [Boolean] Whether it doesn't exist
256
+ #
257
+ def has_no_field?(locator, options={})
258
+ has_no_xpath?(XPath::HTML.field(locator, options))
259
+ end
260
+
261
+ ##
262
+ #
263
+ # Checks if the page or current node has a radio button or
264
+ # checkbox with the given label, value or id, that is currently
265
+ # checked.
266
+ #
267
+ # @param [String] locator The label, name or id of a checked field
268
+ # @return [Boolean] Whether it exists
269
+ #
270
+ def has_checked_field?(locator)
271
+ has_xpath?(XPath::HTML.field(locator, :checked => true))
272
+ end
273
+
274
+ ##
275
+ #
276
+ # Checks if the page or current node has a radio button or
277
+ # checkbox with the given label, value or id, that is currently
278
+ # unchecked.
279
+ #
280
+ # @param [String] locator The label, name or id of an unchecked field
281
+ # @return [Boolean] Whether it exists
282
+ #
283
+ def has_unchecked_field?(locator)
284
+ has_xpath?(XPath::HTML.field(locator, :unchecked => true))
285
+ end
286
+
287
+ ##
288
+ #
289
+ # Checks if the page or current node has a select field with the
290
+ # given label, name or id.
291
+ #
292
+ # It can be specified which option should currently be selected:
293
+ #
294
+ # page.has_select?('Language', :selected => 'German')
295
+ #
296
+ # For multiple select boxes, several options may be specified:
297
+ #
298
+ # page.has_select?('Language', :selected => ['English', 'German'])
299
+ #
300
+ # It's also possible to check if a given set of options exists for
301
+ # this select box:
302
+ #
303
+ # page.has_select?('Language', :options => ['English', 'German'])
304
+ #
305
+ # @param [String] locator The label, name or id of a select box
306
+ # @option options [Array] :options Options which should be contained in this select box
307
+ # @option options [String, Array] :selected Options which should be selected
308
+ # @return [Boolean] Whether it exists
309
+ #
310
+ def has_select?(locator, options={})
311
+ has_xpath?(XPath::HTML.select(locator, options))
312
+ end
313
+
314
+ ##
315
+ #
316
+ # Checks if the page or current node has no select field with the
317
+ # given label, name or id. See {Capybara::Node::Matchers#has_select?}.
318
+ #
319
+ # @param (see Capybara::Node::Matchers#has_select?)
320
+ # @return [Boolean] Whether it doesn't exist
321
+ #
322
+ def has_no_select?(locator, options={})
323
+ has_no_xpath?(XPath::HTML.select(locator, options))
324
+ end
325
+
326
+ ##
327
+ #
328
+ # Checks if the page or current node has a table with the given id
329
+ # or caption.
330
+ #
331
+ # If the options :rows is given, it will check that the table contains
332
+ # the rows and columns given:
333
+ #
334
+ # page.has_table?('People', :rows => [['Jonas', '24'], ['Peter', '32']])
335
+ #
336
+ # Note that this option is quite strict, the order needs to be correct
337
+ # and the text needs to match exactly.
338
+ #
339
+ # @param [String] locator The id or caption of a table
340
+ # @option options [Array[Array[String]]] :rows A set of rows the table should contain
341
+ # @return [Boolean] Whether it exist
342
+ #
343
+ def has_table?(locator, options={})
344
+ has_xpath?(XPath::HTML.table(locator, options))
345
+ end
346
+
347
+ ##
348
+ #
349
+ # Checks if the page or current node has no table with the given id
350
+ # or caption. See {Capybara::Node::Matchers#has_table?}.
351
+ #
352
+ # @param (see Capybara::Node::Matchers#has_table?)
353
+ # @return [Boolean] Whether it doesn't exist
354
+ #
355
+ def has_no_table?(locator, options={})
356
+ has_no_xpath?(XPath::HTML.table(locator, options))
357
+ end
358
+ end
359
+ end
360
+ end