capybara 1.1.4 → 2.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +100 -0
- data/License.txt +22 -0
- data/README.md +829 -0
- data/lib/capybara.rb +124 -6
- data/lib/capybara/cucumber.rb +2 -5
- data/lib/capybara/driver/base.rb +5 -5
- data/lib/capybara/driver/node.rb +2 -2
- data/lib/capybara/dsl.rb +3 -121
- data/lib/capybara/node/actions.rb +12 -28
- data/lib/capybara/node/base.rb +5 -13
- data/lib/capybara/node/element.rb +21 -21
- data/lib/capybara/node/finders.rb +27 -89
- data/lib/capybara/node/matchers.rb +107 -69
- data/lib/capybara/node/simple.rb +11 -13
- data/lib/capybara/query.rb +78 -0
- data/lib/capybara/rack_test/browser.rb +16 -27
- data/lib/capybara/rack_test/driver.rb +11 -1
- data/lib/capybara/rack_test/node.rb +17 -1
- data/lib/capybara/result.rb +84 -0
- data/lib/capybara/rspec/matchers.rb +28 -63
- data/lib/capybara/selector.rb +97 -33
- data/lib/capybara/selenium/driver.rb +14 -61
- data/lib/capybara/selenium/node.rb +6 -15
- data/lib/capybara/server.rb +32 -27
- data/lib/capybara/session.rb +54 -30
- data/lib/capybara/spec/public/jquery-ui.js +791 -0
- data/lib/capybara/spec/public/jquery.js +9046 -0
- data/lib/capybara/spec/public/test.js +4 -1
- data/lib/capybara/spec/session.rb +56 -27
- data/lib/capybara/spec/session/all_spec.rb +8 -4
- data/lib/capybara/spec/session/attach_file_spec.rb +12 -9
- data/lib/capybara/spec/session/check_spec.rb +6 -3
- data/lib/capybara/spec/session/choose_spec.rb +4 -1
- data/lib/capybara/spec/session/click_button_spec.rb +5 -14
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +2 -1
- data/lib/capybara/spec/session/click_link_spec.rb +3 -17
- data/lib/capybara/spec/session/current_url_spec.rb +77 -9
- data/lib/capybara/spec/session/fill_in_spec.rb +8 -18
- data/lib/capybara/spec/session/find_spec.rb +19 -46
- data/lib/capybara/spec/session/first_spec.rb +2 -34
- data/lib/capybara/spec/session/has_css_spec.rb +1 -1
- data/lib/capybara/spec/session/has_field_spec.rb +28 -0
- data/lib/capybara/spec/session/has_select_spec.rb +84 -31
- data/lib/capybara/spec/session/has_table_spec.rb +7 -69
- data/lib/capybara/spec/session/has_text_spec.rb +168 -0
- data/lib/capybara/spec/session/javascript.rb +65 -81
- data/lib/capybara/spec/session/node_spec.rb +115 -0
- data/lib/capybara/spec/session/screenshot.rb +29 -0
- data/lib/capybara/spec/session/select_spec.rb +12 -12
- data/lib/capybara/spec/session/text_spec.rb +9 -4
- data/lib/capybara/spec/session/unselect_spec.rb +12 -6
- data/lib/capybara/spec/session/visit_spec.rb +76 -0
- data/lib/capybara/spec/session/within_frame_spec.rb +33 -0
- data/lib/capybara/spec/session/within_spec.rb +47 -58
- data/lib/capybara/spec/session/within_window_spec.rb +40 -0
- data/lib/capybara/spec/test_app.rb +27 -3
- data/lib/capybara/spec/views/form.erb +11 -10
- data/lib/capybara/spec/views/host_links.erb +2 -2
- data/lib/capybara/spec/views/tables.erb +6 -66
- data/lib/capybara/spec/views/with_html.erb +3 -3
- data/lib/capybara/spec/views/with_js.erb +11 -8
- data/lib/capybara/util/save_and_open_page.rb +4 -3
- data/lib/capybara/version.rb +1 -1
- data/spec/basic_node_spec.rb +15 -3
- data/spec/dsl_spec.rb +12 -10
- data/spec/rack_test_spec.rb +152 -0
- data/spec/rspec/features_spec.rb +0 -2
- data/spec/rspec/matchers_spec.rb +164 -89
- data/spec/rspec_spec.rb +0 -2
- data/spec/selenium_spec.rb +67 -0
- data/spec/server_spec.rb +35 -23
- data/spec/spec_helper.rb +18 -2
- metadata +30 -30
- data/README.rdoc +0 -722
- data/lib/capybara/spec/driver.rb +0 -301
- data/lib/capybara/spec/session/current_host_spec.rb +0 -68
- data/lib/capybara/spec/session/has_content_spec.rb +0 -106
- data/lib/capybara/util/timeout.rb +0 -27
- data/spec/driver/rack_test_driver_spec.rb +0 -89
- data/spec/driver/selenium_driver_spec.rb +0 -37
- data/spec/session/rack_test_session_spec.rb +0 -55
- data/spec/session/selenium_session_spec.rb +0 -26
- data/spec/string_spec.rb +0 -77
- data/spec/timeout_spec.rb +0 -28
data/lib/capybara/node/simple.rb
CHANGED
@@ -95,7 +95,7 @@ module Capybara
|
|
95
95
|
# @return [Boolean] Whether the element is visible
|
96
96
|
#
|
97
97
|
def visible?
|
98
|
-
native.xpath("./ancestor-or-self::*[contains(@style, 'display:none') or contains(@style, 'display: none')]").size == 0
|
98
|
+
native.xpath("./ancestor-or-self::*[contains(@style, 'display:none') or contains(@style, 'display: none') or name()='script' or name()='head']").size == 0
|
99
99
|
end
|
100
100
|
|
101
101
|
##
|
@@ -118,22 +118,20 @@ module Capybara
|
|
118
118
|
native[:selected]
|
119
119
|
end
|
120
120
|
|
121
|
-
def
|
122
|
-
#
|
123
|
-
end
|
124
|
-
|
125
|
-
def without_wait
|
126
|
-
yield
|
121
|
+
def synchronize
|
122
|
+
yield # simple nodes don't need to wait
|
127
123
|
end
|
128
124
|
|
129
|
-
|
130
|
-
|
131
|
-
def find_in_base(selector, xpath)
|
132
|
-
native.xpath(xpath).map { |node| self.class.new(node) }
|
125
|
+
def allow_reload!
|
126
|
+
# no op
|
133
127
|
end
|
134
128
|
|
135
|
-
def
|
136
|
-
|
129
|
+
def all(*args)
|
130
|
+
query = Capybara::Query.new(*args)
|
131
|
+
elements = native.xpath(query.xpath).map do |node|
|
132
|
+
self.class.new(node)
|
133
|
+
end
|
134
|
+
Capybara::Result.new(elements, query)
|
137
135
|
end
|
138
136
|
end
|
139
137
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Capybara
|
2
|
+
class Query
|
3
|
+
attr_accessor :selector, :locator, :options, :xpath, :find, :negative
|
4
|
+
|
5
|
+
VALID_KEYS = [:text, :visible, :between, :count, :maximum, :minimum]
|
6
|
+
|
7
|
+
def initialize(*args)
|
8
|
+
@options = if args.last.is_a?(Hash) then args.pop.dup else {} end
|
9
|
+
|
10
|
+
unless options.has_key?(:visible)
|
11
|
+
@options[:visible] = Capybara.ignore_hidden_elements
|
12
|
+
end
|
13
|
+
|
14
|
+
if args[1]
|
15
|
+
@selector = Selector.all[args[0]]
|
16
|
+
@locator = args[1]
|
17
|
+
else
|
18
|
+
@selector = Selector.all.values.find { |s| s.match?(args[0]) }
|
19
|
+
@locator = args[0]
|
20
|
+
end
|
21
|
+
@selector ||= Selector.all[Capybara.default_selector]
|
22
|
+
|
23
|
+
@xpath = @selector.call(@locator).to_s
|
24
|
+
|
25
|
+
assert_valid_keys!
|
26
|
+
end
|
27
|
+
|
28
|
+
def name; selector.name; end
|
29
|
+
def label; selector.label or selector.name; end
|
30
|
+
|
31
|
+
def description
|
32
|
+
@description = "#{label} #{locator.inspect}"
|
33
|
+
@description << " with text #{options[:text].inspect}" if options[:text]
|
34
|
+
@description
|
35
|
+
end
|
36
|
+
|
37
|
+
def matches_filters?(node)
|
38
|
+
if options[:text]
|
39
|
+
regexp = options[:text].is_a?(Regexp) ? options[:text] : Regexp.escape(options[:text])
|
40
|
+
return false if not node.text.match(regexp)
|
41
|
+
end
|
42
|
+
return false if options[:visible] and not node.visible?
|
43
|
+
selector.custom_filters.each do |name, block|
|
44
|
+
return false if options.has_key?(name) and not block.call(node, options[name])
|
45
|
+
end
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def matches_count?(count)
|
50
|
+
case
|
51
|
+
when count.zero?
|
52
|
+
false
|
53
|
+
when options[:between]
|
54
|
+
options[:between] === count
|
55
|
+
when options[:count]
|
56
|
+
options[:count].to_i == count
|
57
|
+
when options[:maximum]
|
58
|
+
options[:maximum].to_i >= count
|
59
|
+
when options[:minimum]
|
60
|
+
options[:minimum].to_i <= count
|
61
|
+
else
|
62
|
+
count > 0
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def assert_valid_keys!
|
69
|
+
valid_keys = VALID_KEYS + @selector.custom_filters.keys
|
70
|
+
invalid_keys = @options.keys - valid_keys
|
71
|
+
unless invalid_keys.empty?
|
72
|
+
invalid_names = invalid_keys.map(&:inspect).join(", ")
|
73
|
+
valid_names = valid_keys.map(&:inspect).join(", ")
|
74
|
+
raise ArgumentError, "invalid keys #{invalid_names}, should be one of #{valid_names}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -18,35 +18,36 @@ class Capybara::RackTest::Browser
|
|
18
18
|
|
19
19
|
def visit(path, attributes = {})
|
20
20
|
reset_host!
|
21
|
-
|
22
|
-
follow_redirects!
|
21
|
+
process_and_follow_redirects(:get, path, attributes)
|
23
22
|
end
|
24
23
|
|
25
24
|
def submit(method, path, attributes)
|
26
25
|
path = request_path if not path or path.empty?
|
27
|
-
|
28
|
-
follow_redirects!
|
26
|
+
process_and_follow_redirects(method, path, attributes, {'HTTP_REFERER' => current_url})
|
29
27
|
end
|
30
28
|
|
31
29
|
def follow(method, path, attributes = {})
|
32
30
|
return if path.gsub(/^#{request_path}/, '').start_with?('#')
|
33
|
-
|
34
|
-
follow_redirects!
|
31
|
+
process_and_follow_redirects(method, path, attributes, {'HTTP_REFERER' => current_url})
|
35
32
|
end
|
36
33
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
34
|
+
def process_and_follow_redirects(method, path, attributes = {}, env = {})
|
35
|
+
process(method, path, attributes, env)
|
36
|
+
if driver.follow_redirects?
|
37
|
+
driver.redirect_limit.times do
|
38
|
+
process(:get, last_response["Location"], {}, env) if last_response.redirect?
|
39
|
+
end
|
40
|
+
raise Capybara::InfiniteRedirectError, "redirected more than #{driver.redirect_limit} times, check for infinite redirects." if last_response.redirect?
|
40
41
|
end
|
41
|
-
raise Capybara::InfiniteRedirectError, "redirected more than 5 times, check for infinite redirects." if last_response.redirect?
|
42
42
|
end
|
43
43
|
|
44
|
-
def process(method, path, attributes = {})
|
44
|
+
def process(method, path, attributes = {}, env = {})
|
45
45
|
new_uri = URI.parse(path)
|
46
|
-
|
46
|
+
method.downcase! unless method.is_a? Symbol
|
47
47
|
|
48
48
|
if new_uri.host
|
49
|
-
@current_host = new_uri.scheme
|
49
|
+
@current_host = "#{new_uri.scheme}://#{new_uri.host}"
|
50
|
+
@current_host << ":#{new_uri.port}" if new_uri.port != new_uri.default_port
|
50
51
|
end
|
51
52
|
|
52
53
|
if new_uri.relative?
|
@@ -59,7 +60,7 @@ class Capybara::RackTest::Browser
|
|
59
60
|
end
|
60
61
|
|
61
62
|
reset_cache!
|
62
|
-
send(method, path, attributes, env)
|
63
|
+
send(method, path, attributes, env.merge(options[:headers] || {}))
|
63
64
|
end
|
64
65
|
|
65
66
|
def current_url
|
@@ -91,7 +92,7 @@ class Capybara::RackTest::Browser
|
|
91
92
|
def source
|
92
93
|
last_response.body
|
93
94
|
rescue Rack::Test::Error
|
94
|
-
|
95
|
+
""
|
95
96
|
end
|
96
97
|
|
97
98
|
protected
|
@@ -106,16 +107,4 @@ protected
|
|
106
107
|
rescue Rack::Test::Error
|
107
108
|
""
|
108
109
|
end
|
109
|
-
|
110
|
-
def env
|
111
|
-
env = {}
|
112
|
-
begin
|
113
|
-
env["HTTP_REFERER"] = last_request.url
|
114
|
-
rescue Rack::Test::Error
|
115
|
-
# no request yet
|
116
|
-
end
|
117
|
-
env.merge!(options[:headers]) if options[:headers]
|
118
|
-
env
|
119
|
-
end
|
120
|
-
|
121
110
|
end
|
@@ -6,7 +6,9 @@ require 'cgi'
|
|
6
6
|
|
7
7
|
class Capybara::RackTest::Driver < Capybara::Driver::Base
|
8
8
|
DEFAULT_OPTIONS = {
|
9
|
-
:respect_data_method =>
|
9
|
+
:respect_data_method => false,
|
10
|
+
:follow_redirects => true,
|
11
|
+
:redirect_limit => 5
|
10
12
|
}
|
11
13
|
attr_reader :app, :options
|
12
14
|
|
@@ -20,6 +22,14 @@ class Capybara::RackTest::Driver < Capybara::Driver::Base
|
|
20
22
|
@browser ||= Capybara::RackTest::Browser.new(self)
|
21
23
|
end
|
22
24
|
|
25
|
+
def follow_redirects?
|
26
|
+
@options[:follow_redirects]
|
27
|
+
end
|
28
|
+
|
29
|
+
def redirect_limit
|
30
|
+
@options[:redirect_limit]
|
31
|
+
end
|
32
|
+
|
23
33
|
def response
|
24
34
|
browser.last_response
|
25
35
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Capybara::RackTest::Node < Capybara::Driver::Node
|
2
2
|
def text
|
3
|
-
|
3
|
+
unnormalized_text.strip.gsub(/\s+/, ' ')
|
4
4
|
end
|
5
5
|
|
6
6
|
def [](name)
|
@@ -84,6 +84,22 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
84
84
|
native.xpath(locator).map { |n| self.class.new(driver, n) }
|
85
85
|
end
|
86
86
|
|
87
|
+
protected
|
88
|
+
|
89
|
+
def unnormalized_text
|
90
|
+
if !visible?
|
91
|
+
''
|
92
|
+
elsif native.text?
|
93
|
+
native.text
|
94
|
+
elsif native.element?
|
95
|
+
native.children.map do |child|
|
96
|
+
Capybara::RackTest::Node.new(driver, child).unnormalized_text
|
97
|
+
end.join
|
98
|
+
else
|
99
|
+
''
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
87
103
|
private
|
88
104
|
|
89
105
|
def string_node
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Capybara
|
2
|
+
class Result
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(elements, query)
|
6
|
+
@elements = elements
|
7
|
+
@result = elements.select { |node| query.matches_filters?(node) }
|
8
|
+
@rest = @elements - @result
|
9
|
+
@query = query
|
10
|
+
end
|
11
|
+
|
12
|
+
def each(&block)
|
13
|
+
@result.each(&block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def first
|
17
|
+
@result.first
|
18
|
+
end
|
19
|
+
|
20
|
+
def matches_count?
|
21
|
+
@query.matches_count?(@result.size)
|
22
|
+
end
|
23
|
+
|
24
|
+
def find!
|
25
|
+
raise find_error if @result.count != 1
|
26
|
+
@result.first
|
27
|
+
end
|
28
|
+
|
29
|
+
def size; @result.size; end
|
30
|
+
alias_method :length, :size
|
31
|
+
alias_method :count, :size
|
32
|
+
|
33
|
+
def find_error
|
34
|
+
if @result.count == 0
|
35
|
+
Capybara::ElementNotFound.new("Unable to find #{@query.description}")
|
36
|
+
elsif @result.count > 1
|
37
|
+
Capybara::Ambiguous.new("Ambiguous match, found #{size} elements matching #{@query.description}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def failure_message
|
42
|
+
message = if @query.options[:count]
|
43
|
+
"expected #{@query.description} to be found #{@query.options[:count]} #{declension("time", "times", @query.options[:count])}"
|
44
|
+
elsif @query.options[:between]
|
45
|
+
"expected #{@query.description} to be found between #{@query.options[:between].first} and #{@query.options[:between].last} times"
|
46
|
+
elsif @query.options[:maximum]
|
47
|
+
"expected #{@query.description} to be found at most #{@query.options[:maximum]} #{declension("time", "times", @query.options[:maximum])}"
|
48
|
+
elsif @query.options[:minimum]
|
49
|
+
"expected #{@query.description} to be found at least #{@query.options[:minimum]} #{declension("time", "times", @query.options[:minimum])}"
|
50
|
+
else
|
51
|
+
"expected to find #{@query.description}"
|
52
|
+
end
|
53
|
+
if count > 0
|
54
|
+
message << ", found #{count} #{declension("match", "matches")}: " << @result.map(&:text).map(&:inspect).join(", ")
|
55
|
+
else
|
56
|
+
message << " but there were no matches"
|
57
|
+
end
|
58
|
+
unless @rest.empty?
|
59
|
+
elements = @rest.map(&:text).map(&:inspect).join(", ")
|
60
|
+
message << ". Also found " << elements << ", which matched the selector but not all filters."
|
61
|
+
end
|
62
|
+
message
|
63
|
+
end
|
64
|
+
|
65
|
+
def negative_failure_message
|
66
|
+
"expected not to find #{@query.description}, but there #{declension("was", "were")} #{count} #{declension("match", "matches")}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def empty?
|
70
|
+
@result.empty?
|
71
|
+
end
|
72
|
+
def [](key); @result[key]; end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def declension(singular, plural, count=count)
|
77
|
+
if count == 1
|
78
|
+
singular
|
79
|
+
else
|
80
|
+
plural
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -6,35 +6,15 @@ module Capybara
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def matches?(actual)
|
9
|
-
|
10
|
-
@actual.has_selector?(*@args)
|
9
|
+
wrap(actual).assert_selector(*@args)
|
11
10
|
end
|
12
11
|
|
13
12
|
def does_not_match?(actual)
|
14
|
-
|
15
|
-
@actual.has_no_selector?(*@args)
|
16
|
-
end
|
17
|
-
|
18
|
-
def failure_message_for_should
|
19
|
-
if normalized.failure_message
|
20
|
-
normalized.failure_message.call(@actual, normalized)
|
21
|
-
else
|
22
|
-
"expected #{selector_name} to return something"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def failure_message_for_should_not
|
27
|
-
"expected #{selector_name} not to return anything"
|
13
|
+
wrap(actual).assert_no_selector(*@args)
|
28
14
|
end
|
29
15
|
|
30
16
|
def description
|
31
|
-
"
|
32
|
-
end
|
33
|
-
|
34
|
-
def selector_name
|
35
|
-
name = "#{normalized.name} #{normalized.locator.inspect}"
|
36
|
-
name << " with text #{normalized.options[:text].inspect}" if normalized.options[:text]
|
37
|
-
name
|
17
|
+
"have #{query.description}"
|
38
18
|
end
|
39
19
|
|
40
20
|
def wrap(actual)
|
@@ -45,55 +25,38 @@ module Capybara
|
|
45
25
|
end
|
46
26
|
end
|
47
27
|
|
48
|
-
def
|
49
|
-
@
|
28
|
+
def query
|
29
|
+
@query ||= Capybara::Query.new(*@args)
|
50
30
|
end
|
51
31
|
end
|
52
32
|
|
53
|
-
class
|
54
|
-
attr_reader :
|
55
|
-
|
56
|
-
def initialize(name, locator, options={}, &block)
|
57
|
-
@name = name
|
58
|
-
@locator = locator
|
59
|
-
@options = options
|
60
|
-
@failure_message = block
|
61
|
-
end
|
33
|
+
class HaveText
|
34
|
+
attr_reader :text
|
62
35
|
|
63
|
-
def
|
64
|
-
|
36
|
+
def initialize(text)
|
37
|
+
@text = text
|
65
38
|
end
|
66
39
|
|
67
40
|
def matches?(actual)
|
68
41
|
@actual = wrap(actual)
|
69
|
-
@actual.
|
42
|
+
@actual.has_text?(text)
|
70
43
|
end
|
71
44
|
|
72
45
|
def does_not_match?(actual)
|
73
46
|
@actual = wrap(actual)
|
74
|
-
@actual.
|
47
|
+
@actual.has_no_text?(text)
|
75
48
|
end
|
76
49
|
|
77
50
|
def failure_message_for_should
|
78
|
-
|
79
|
-
failure_message.call(actual, self)
|
80
|
-
else
|
81
|
-
"expected #{selector_name} to return something"
|
82
|
-
end
|
51
|
+
"expected there to be text #{text.inspect} in #{@actual.text.inspect}"
|
83
52
|
end
|
84
53
|
|
85
54
|
def failure_message_for_should_not
|
86
|
-
"expected
|
55
|
+
"expected there not to be text #{text.inspect} in #{@actual.text.inspect}"
|
87
56
|
end
|
88
57
|
|
89
58
|
def description
|
90
|
-
"
|
91
|
-
end
|
92
|
-
|
93
|
-
def selector_name
|
94
|
-
selector_name = "#{name} #{locator.inspect}"
|
95
|
-
selector_name << " with text #{options[:text].inspect}" if options[:text]
|
96
|
-
selector_name
|
59
|
+
"have text #{text.inspect}"
|
97
60
|
end
|
98
61
|
|
99
62
|
def wrap(actual)
|
@@ -110,45 +73,47 @@ module Capybara
|
|
110
73
|
end
|
111
74
|
|
112
75
|
def have_xpath(xpath, options={})
|
113
|
-
|
76
|
+
HaveSelector.new(:xpath, xpath, options)
|
114
77
|
end
|
115
78
|
|
116
79
|
def have_css(css, options={})
|
117
|
-
|
80
|
+
HaveSelector.new(:css, css, options)
|
118
81
|
end
|
119
82
|
|
120
83
|
def have_content(text)
|
121
|
-
|
122
|
-
|
123
|
-
|
84
|
+
HaveText.new(text)
|
85
|
+
end
|
86
|
+
|
87
|
+
def have_text(text)
|
88
|
+
HaveText.new(text)
|
124
89
|
end
|
125
90
|
|
126
91
|
def have_link(locator, options={})
|
127
|
-
|
92
|
+
HaveSelector.new(:link, locator, options)
|
128
93
|
end
|
129
94
|
|
130
95
|
def have_button(locator)
|
131
|
-
|
96
|
+
HaveSelector.new(:button, locator)
|
132
97
|
end
|
133
98
|
|
134
99
|
def have_field(locator, options={})
|
135
|
-
|
100
|
+
HaveSelector.new(:field, locator, options)
|
136
101
|
end
|
137
102
|
|
138
103
|
def have_checked_field(locator)
|
139
|
-
|
104
|
+
HaveSelector.new(:field, locator, :checked => true)
|
140
105
|
end
|
141
106
|
|
142
107
|
def have_unchecked_field(locator)
|
143
|
-
|
108
|
+
HaveSelector.new(:field, locator, :unchecked => true)
|
144
109
|
end
|
145
110
|
|
146
111
|
def have_select(locator, options={})
|
147
|
-
|
112
|
+
HaveSelector.new(:select, locator, options)
|
148
113
|
end
|
149
114
|
|
150
115
|
def have_table(locator, options={})
|
151
|
-
|
116
|
+
HaveSelector.new(:table, locator, options)
|
152
117
|
end
|
153
118
|
end
|
154
119
|
end
|