capybara-rails-2-2 0.4.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +202 -0
- data/README.rdoc +540 -0
- data/lib/capybara.rb +231 -0
- data/lib/capybara/cucumber.rb +32 -0
- data/lib/capybara/driver/base.rb +60 -0
- data/lib/capybara/driver/celerity_driver.rb +164 -0
- data/lib/capybara/driver/culerity_driver.rb +26 -0
- data/lib/capybara/driver/node.rb +74 -0
- data/lib/capybara/driver/rack_test_driver.rb +303 -0
- data/lib/capybara/driver/selenium_driver.rb +161 -0
- data/lib/capybara/dsl.rb +109 -0
- data/lib/capybara/node/actions.rb +160 -0
- data/lib/capybara/node/base.rb +47 -0
- data/lib/capybara/node/document.rb +17 -0
- data/lib/capybara/node/element.rb +178 -0
- data/lib/capybara/node/finders.rb +201 -0
- data/lib/capybara/node/matchers.rb +391 -0
- data/lib/capybara/node/simple.rb +116 -0
- data/lib/capybara/rails.rb +16 -0
- data/lib/capybara/rspec.rb +18 -0
- data/lib/capybara/selector.rb +70 -0
- data/lib/capybara/server.rb +90 -0
- data/lib/capybara/session.rb +281 -0
- data/lib/capybara/spec/driver.rb +243 -0
- data/lib/capybara/spec/fixtures/capybara.jpg +0 -0
- data/lib/capybara/spec/fixtures/test_file.txt +1 -0
- data/lib/capybara/spec/public/jquery-ui.js +35 -0
- data/lib/capybara/spec/public/jquery.js +19 -0
- data/lib/capybara/spec/public/test.js +33 -0
- data/lib/capybara/spec/session.rb +110 -0
- data/lib/capybara/spec/session/all_spec.rb +78 -0
- data/lib/capybara/spec/session/attach_file_spec.rb +70 -0
- data/lib/capybara/spec/session/check_spec.rb +65 -0
- data/lib/capybara/spec/session/choose_spec.rb +26 -0
- data/lib/capybara/spec/session/click_button_spec.rb +252 -0
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +36 -0
- data/lib/capybara/spec/session/click_link_spec.rb +113 -0
- data/lib/capybara/spec/session/current_url_spec.rb +15 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +119 -0
- data/lib/capybara/spec/session/find_button_spec.rb +18 -0
- data/lib/capybara/spec/session/find_by_id_spec.rb +18 -0
- data/lib/capybara/spec/session/find_field_spec.rb +26 -0
- data/lib/capybara/spec/session/find_link_spec.rb +19 -0
- data/lib/capybara/spec/session/find_spec.rb +121 -0
- data/lib/capybara/spec/session/first_spec.rb +72 -0
- data/lib/capybara/spec/session/has_button_spec.rb +32 -0
- data/lib/capybara/spec/session/has_content_spec.rb +106 -0
- data/lib/capybara/spec/session/has_css_spec.rb +213 -0
- data/lib/capybara/spec/session/has_field_spec.rb +156 -0
- data/lib/capybara/spec/session/has_link_spec.rb +37 -0
- data/lib/capybara/spec/session/has_select_spec.rb +129 -0
- data/lib/capybara/spec/session/has_selector_spec.rb +129 -0
- data/lib/capybara/spec/session/has_table_spec.rb +96 -0
- data/lib/capybara/spec/session/has_xpath_spec.rb +123 -0
- data/lib/capybara/spec/session/headers.rb +19 -0
- data/lib/capybara/spec/session/javascript.rb +223 -0
- data/lib/capybara/spec/session/response_code.rb +19 -0
- data/lib/capybara/spec/session/select_spec.rb +105 -0
- data/lib/capybara/spec/session/uncheck_spec.rb +21 -0
- data/lib/capybara/spec/session/unselect_spec.rb +61 -0
- data/lib/capybara/spec/session/within_spec.rb +160 -0
- data/lib/capybara/spec/test_app.rb +117 -0
- data/lib/capybara/spec/views/buttons.erb +4 -0
- data/lib/capybara/spec/views/fieldsets.erb +29 -0
- data/lib/capybara/spec/views/form.erb +348 -0
- data/lib/capybara/spec/views/frame_one.erb +8 -0
- data/lib/capybara/spec/views/frame_two.erb +8 -0
- data/lib/capybara/spec/views/popup_one.erb +8 -0
- data/lib/capybara/spec/views/popup_two.erb +8 -0
- data/lib/capybara/spec/views/postback.erb +13 -0
- data/lib/capybara/spec/views/tables.erb +122 -0
- data/lib/capybara/spec/views/with_html.erb +69 -0
- data/lib/capybara/spec/views/with_js.erb +39 -0
- data/lib/capybara/spec/views/with_scope.erb +36 -0
- data/lib/capybara/spec/views/with_simple_html.erb +1 -0
- data/lib/capybara/spec/views/within_frames.erb +10 -0
- data/lib/capybara/spec/views/within_popups.erb +25 -0
- data/lib/capybara/util/save_and_open_page.rb +40 -0
- data/lib/capybara/util/timeout.rb +27 -0
- data/lib/capybara/version.rb +3 -0
- data/spec/basic_node_spec.rb +77 -0
- data/spec/capybara_spec.rb +46 -0
- data/spec/driver/celerity_driver_spec.rb +13 -0
- data/spec/driver/culerity_driver_spec.rb +14 -0
- data/spec/driver/rack_test_driver_spec.rb +84 -0
- data/spec/driver/remote_culerity_driver_spec.rb +22 -0
- data/spec/driver/remote_selenium_driver_spec.rb +16 -0
- data/spec/driver/selenium_driver_spec.rb +14 -0
- data/spec/dsl_spec.rb +157 -0
- data/spec/rspec_spec.rb +47 -0
- data/spec/save_and_open_page_spec.rb +159 -0
- data/spec/server_spec.rb +85 -0
- data/spec/session/celerity_session_spec.rb +24 -0
- data/spec/session/culerity_session_spec.rb +26 -0
- data/spec/session/rack_test_session_spec.rb +44 -0
- data/spec/session/selenium_session_spec.rb +26 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/string_spec.rb +77 -0
- data/spec/timeout_spec.rb +28 -0
- metadata +360 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'culerity'
|
2
|
+
|
3
|
+
class Capybara::Driver::Culerity < Capybara::Driver::Celerity
|
4
|
+
|
5
|
+
def self.server
|
6
|
+
unless @_server
|
7
|
+
@_server = ::Culerity::run_server
|
8
|
+
at_exit do
|
9
|
+
@_server.close
|
10
|
+
end
|
11
|
+
end
|
12
|
+
@_server
|
13
|
+
end
|
14
|
+
|
15
|
+
def browser
|
16
|
+
unless @_browser
|
17
|
+
@_browser = ::Culerity::RemoteBrowserProxy.new self.class.server, options
|
18
|
+
at_exit do
|
19
|
+
@_browser.close
|
20
|
+
@_browser.exit
|
21
|
+
end
|
22
|
+
end
|
23
|
+
@_browser
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Capybara
|
2
|
+
module Driver
|
3
|
+
class Node
|
4
|
+
attr_reader :driver, :native
|
5
|
+
|
6
|
+
def initialize(driver, native)
|
7
|
+
@driver = driver
|
8
|
+
@native = native
|
9
|
+
end
|
10
|
+
|
11
|
+
def text
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](name)
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
def value
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
def set(value)
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
def select_option
|
28
|
+
raise NotImplementedError
|
29
|
+
end
|
30
|
+
|
31
|
+
def unselect_option
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
|
+
|
35
|
+
def click
|
36
|
+
raise NotImplementedError
|
37
|
+
end
|
38
|
+
|
39
|
+
def drag_to(element)
|
40
|
+
raise NotImplementedError
|
41
|
+
end
|
42
|
+
|
43
|
+
def tag_name
|
44
|
+
raise NotImplementedError
|
45
|
+
end
|
46
|
+
|
47
|
+
def visible?
|
48
|
+
raise NotImplementedError
|
49
|
+
end
|
50
|
+
|
51
|
+
def checked?
|
52
|
+
raise NotImplementedError
|
53
|
+
end
|
54
|
+
|
55
|
+
def selected?
|
56
|
+
raise NotImplementedError
|
57
|
+
end
|
58
|
+
|
59
|
+
def path
|
60
|
+
raise NotSupportedByDriverError
|
61
|
+
end
|
62
|
+
|
63
|
+
def trigger(event)
|
64
|
+
raise NotSupportedByDriverError
|
65
|
+
end
|
66
|
+
|
67
|
+
def inspect
|
68
|
+
%(#<Capybara::Driver::Node tag="#{tag_name}" path="#{path}">)
|
69
|
+
rescue NotSupportedByDriverError
|
70
|
+
%(#<Capybara::Driver::Node tag="#{tag_name}">)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,303 @@
|
|
1
|
+
require 'rack/test'
|
2
|
+
require 'rack/utils'
|
3
|
+
require 'mime/types'
|
4
|
+
require 'nokogiri'
|
5
|
+
require 'cgi'
|
6
|
+
|
7
|
+
class Capybara::Driver::RackTest < Capybara::Driver::Base
|
8
|
+
class Node < Capybara::Driver::Node
|
9
|
+
def text
|
10
|
+
native.text
|
11
|
+
end
|
12
|
+
|
13
|
+
def [](name)
|
14
|
+
string_node[name]
|
15
|
+
end
|
16
|
+
|
17
|
+
def value
|
18
|
+
string_node.value
|
19
|
+
end
|
20
|
+
|
21
|
+
def set(value)
|
22
|
+
if tag_name == 'input' and type == 'radio'
|
23
|
+
other_radios_xpath = XPath.generate { |x| x.anywhere(:input)[x.attr(:name).equals(self[:name])] }.to_s
|
24
|
+
driver.html.xpath(other_radios_xpath).each { |node| node.remove_attribute("checked") }
|
25
|
+
native['checked'] = 'checked'
|
26
|
+
elsif tag_name == 'input' and type == 'checkbox'
|
27
|
+
if value && !native['checked']
|
28
|
+
native['checked'] = 'checked'
|
29
|
+
elsif !value && native['checked']
|
30
|
+
native.remove_attribute('checked')
|
31
|
+
end
|
32
|
+
elsif tag_name == 'input'
|
33
|
+
native['value'] = value.to_s
|
34
|
+
elsif tag_name == "textarea"
|
35
|
+
native.content = value.to_s
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def select_option
|
40
|
+
if select_node['multiple'] != 'multiple'
|
41
|
+
select_node.find(".//option[@selected]").each { |node| node.native.remove_attribute("selected") }
|
42
|
+
end
|
43
|
+
native["selected"] = 'selected'
|
44
|
+
end
|
45
|
+
|
46
|
+
def unselect_option
|
47
|
+
if select_node['multiple'] != 'multiple'
|
48
|
+
raise Capybara::UnselectNotAllowed, "Cannot unselect option from single select box."
|
49
|
+
end
|
50
|
+
native.remove_attribute('selected')
|
51
|
+
end
|
52
|
+
|
53
|
+
def click
|
54
|
+
if tag_name == 'a'
|
55
|
+
method = self["data-method"] || :get
|
56
|
+
driver.process(method, self[:href].to_s)
|
57
|
+
elsif (tag_name == 'input' and %w(submit image).include?(type)) or
|
58
|
+
((tag_name == 'button') and type.nil? or type == "submit")
|
59
|
+
Form.new(driver, form).submit(self)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def tag_name
|
64
|
+
native.node_name
|
65
|
+
end
|
66
|
+
|
67
|
+
def visible?
|
68
|
+
string_node.visible?
|
69
|
+
end
|
70
|
+
|
71
|
+
def checked?
|
72
|
+
self[:checked]
|
73
|
+
end
|
74
|
+
|
75
|
+
def selected?
|
76
|
+
self[:selected]
|
77
|
+
end
|
78
|
+
|
79
|
+
def path
|
80
|
+
native.path
|
81
|
+
end
|
82
|
+
|
83
|
+
def find(locator)
|
84
|
+
native.xpath(locator).map { |n| self.class.new(driver, n) }
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def string_node
|
90
|
+
@string_node ||= Capybara::Node::Simple.new(native)
|
91
|
+
end
|
92
|
+
|
93
|
+
# a reference to the select node if this is an option node
|
94
|
+
def select_node
|
95
|
+
find('./ancestor::select').first
|
96
|
+
end
|
97
|
+
|
98
|
+
def type
|
99
|
+
native[:type]
|
100
|
+
end
|
101
|
+
|
102
|
+
def form
|
103
|
+
native.ancestors('form').first
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Form < Node
|
108
|
+
# This only needs to inherit from Rack::Test::UploadedFile because Rack::Test checks for
|
109
|
+
# the class specifically when determing whether to consturct the request as multipart.
|
110
|
+
# That check should be based solely on the form element's 'enctype' attribute value,
|
111
|
+
# which should probably be provided to Rack::Test in its non-GET request methods.
|
112
|
+
class NilUploadedFile < Rack::Test::UploadedFile
|
113
|
+
def initialize
|
114
|
+
@empty_file = Tempfile.new("nil_uploaded_file")
|
115
|
+
@empty_file.close
|
116
|
+
end
|
117
|
+
|
118
|
+
def original_filename; ""; end
|
119
|
+
def content_type; "application/octet-stream"; end
|
120
|
+
def path; @empty_file.path; end
|
121
|
+
end
|
122
|
+
|
123
|
+
def params(button)
|
124
|
+
params = {}
|
125
|
+
|
126
|
+
native.xpath("(.//input|.//select|.//textarea)[not(@disabled)]").map do |field|
|
127
|
+
case field.name
|
128
|
+
when 'input'
|
129
|
+
if %w(radio checkbox).include? field['type']
|
130
|
+
merge_param!(params, field['name'].to_s, field['value'].to_s) if field['checked']
|
131
|
+
elsif %w(submit image).include? field['type']
|
132
|
+
# TO DO identify the click button here (in document order, rather
|
133
|
+
# than leaving until the end of the params)
|
134
|
+
elsif field['type'] =='file'
|
135
|
+
if multipart?
|
136
|
+
file = \
|
137
|
+
if (value = field['value']).to_s.empty?
|
138
|
+
NilUploadedFile.new
|
139
|
+
else
|
140
|
+
content_type = MIME::Types.type_for(value).first.to_s
|
141
|
+
Rack::Test::UploadedFile.new(value, content_type)
|
142
|
+
end
|
143
|
+
merge_param!(params, field['name'].to_s, file)
|
144
|
+
else
|
145
|
+
merge_param!(params, field['name'].to_s, File.basename(field['value'].to_s))
|
146
|
+
end
|
147
|
+
else
|
148
|
+
merge_param!(params, field['name'].to_s, field['value'].to_s)
|
149
|
+
end
|
150
|
+
when 'select'
|
151
|
+
if field['multiple'] == 'multiple'
|
152
|
+
options = field.xpath(".//option[@selected]")
|
153
|
+
options.each do |option|
|
154
|
+
merge_param!(params, field['name'].to_s, (option['value'] || option.text).to_s)
|
155
|
+
end
|
156
|
+
else
|
157
|
+
option = field.xpath(".//option[@selected]").first
|
158
|
+
option ||= field.xpath('.//option').first
|
159
|
+
merge_param!(params, field['name'].to_s, (option['value'] || option.text).to_s) if option
|
160
|
+
end
|
161
|
+
when 'textarea'
|
162
|
+
merge_param!(params, field['name'].to_s, field.text.to_s)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
merge_param!(params, button[:name], button[:value] || "") if button[:name]
|
166
|
+
params
|
167
|
+
end
|
168
|
+
|
169
|
+
def submit(button)
|
170
|
+
driver.submit(method, native['action'].to_s, params(button))
|
171
|
+
end
|
172
|
+
|
173
|
+
def multipart?
|
174
|
+
self[:enctype] == "multipart/form-data"
|
175
|
+
end
|
176
|
+
|
177
|
+
private
|
178
|
+
|
179
|
+
def method
|
180
|
+
self[:method] =~ /post/i ? :post : :get
|
181
|
+
end
|
182
|
+
|
183
|
+
def merge_param!(params, key, value)
|
184
|
+
Rack::Utils.normalize_params(params, key, value)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
include ::Rack::Test::Methods
|
189
|
+
attr_reader :app
|
190
|
+
|
191
|
+
alias_method :response, :last_response
|
192
|
+
alias_method :request, :last_request
|
193
|
+
|
194
|
+
def initialize(app)
|
195
|
+
raise ArgumentError, "rack-test requires a rack application, but none was given" unless app
|
196
|
+
@app = app
|
197
|
+
end
|
198
|
+
|
199
|
+
def visit(path, attributes = {})
|
200
|
+
process(:get, path, attributes)
|
201
|
+
end
|
202
|
+
|
203
|
+
def process(method, path, attributes = {})
|
204
|
+
return if path.gsub(/^#{request_path}/, '') =~ /^#/
|
205
|
+
path = request_path + path if path =~ /^\?/
|
206
|
+
send(method, to_binary(path), to_binary( attributes ), env)
|
207
|
+
follow_redirects!
|
208
|
+
end
|
209
|
+
|
210
|
+
def current_url
|
211
|
+
request.url rescue ""
|
212
|
+
end
|
213
|
+
|
214
|
+
def response_headers
|
215
|
+
response.headers
|
216
|
+
end
|
217
|
+
|
218
|
+
def status_code
|
219
|
+
response.status
|
220
|
+
end
|
221
|
+
|
222
|
+
def to_binary(object)
|
223
|
+
return object unless Kernel.const_defined?(:Encoding)
|
224
|
+
|
225
|
+
if object.respond_to?(:force_encoding)
|
226
|
+
object.dup.force_encoding(Encoding::ASCII_8BIT)
|
227
|
+
elsif object.respond_to?(:each_pair) #Hash
|
228
|
+
{}.tap { |x| object.each_pair {|k,v| x[to_binary(k)] = to_binary(v) } }
|
229
|
+
elsif object.respond_to?(:each) #Array
|
230
|
+
object.map{|x| to_binary(x)}
|
231
|
+
else
|
232
|
+
object
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def submit(method, path, attributes)
|
237
|
+
path = request_path if not path or path.empty?
|
238
|
+
send(method, to_binary(path), to_binary(attributes), env)
|
239
|
+
follow_redirects!
|
240
|
+
end
|
241
|
+
|
242
|
+
def find(selector)
|
243
|
+
html.xpath(selector).map { |node| Node.new(self, node) }
|
244
|
+
end
|
245
|
+
|
246
|
+
def body
|
247
|
+
@body ||= response.body
|
248
|
+
end
|
249
|
+
|
250
|
+
def html
|
251
|
+
@html ||= Nokogiri::HTML(body)
|
252
|
+
end
|
253
|
+
alias_method :source, :body
|
254
|
+
|
255
|
+
def reset!
|
256
|
+
clear_rack_mock_session
|
257
|
+
end
|
258
|
+
|
259
|
+
def get(*args, &block); reset_cache; super; end
|
260
|
+
def post(*args, &block); reset_cache; super; end
|
261
|
+
def put(*args, &block); reset_cache; super; end
|
262
|
+
def delete(*args, &block); reset_cache; super; end
|
263
|
+
|
264
|
+
def follow_redirects!
|
265
|
+
5.times do
|
266
|
+
follow_redirect! if response.redirect?
|
267
|
+
end
|
268
|
+
raise Capybara::InfiniteRedirectError, "redirected more than 5 times, check for infinite redirects." if response.redirect?
|
269
|
+
end
|
270
|
+
|
271
|
+
private
|
272
|
+
|
273
|
+
def reset_cache
|
274
|
+
@body = nil
|
275
|
+
@html = nil
|
276
|
+
end
|
277
|
+
|
278
|
+
def build_rack_mock_session # :nodoc:
|
279
|
+
Rack::MockSession.new(app, Capybara.default_host || "www.example.com")
|
280
|
+
end
|
281
|
+
|
282
|
+
# Rack::Test::Methods does not provide methods for manipulating the session
|
283
|
+
# list so these must be manipulated directly.
|
284
|
+
def clear_rack_mock_session
|
285
|
+
@_rack_test_sessions = nil
|
286
|
+
@_rack_mock_sessions = nil
|
287
|
+
end
|
288
|
+
|
289
|
+
def request_path
|
290
|
+
request.path rescue ""
|
291
|
+
end
|
292
|
+
|
293
|
+
def env
|
294
|
+
env = {}
|
295
|
+
begin
|
296
|
+
env["HTTP_REFERER"] = request.url
|
297
|
+
rescue Rack::Test::Error
|
298
|
+
# no request yet
|
299
|
+
end
|
300
|
+
env
|
301
|
+
end
|
302
|
+
|
303
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'selenium-webdriver'
|
2
|
+
|
3
|
+
class Capybara::Driver::Selenium < Capybara::Driver::Base
|
4
|
+
class Node < Capybara::Driver::Node
|
5
|
+
def text
|
6
|
+
native.text
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](name)
|
10
|
+
if name == :value
|
11
|
+
value
|
12
|
+
else
|
13
|
+
native.attribute(name.to_s)
|
14
|
+
end
|
15
|
+
rescue Selenium::WebDriver::Error::WebDriverError
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def value
|
20
|
+
if tag_name == "select" and self[:multiple] and not self[:multiple] == "false"
|
21
|
+
native.find_elements(:xpath, ".//option").select { |n| n.selected? }.map { |n| n.value || n.text }
|
22
|
+
else
|
23
|
+
native.value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def set(value)
|
28
|
+
if tag_name == 'input' and type == 'radio'
|
29
|
+
native.click
|
30
|
+
elsif tag_name == 'input' and type == 'checkbox'
|
31
|
+
native.click if value ^ native.attribute('checked').to_s.eql?("true")
|
32
|
+
elsif tag_name == 'textarea' or tag_name == 'input'
|
33
|
+
native.clear
|
34
|
+
native.send_keys(value.to_s)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def select_option
|
39
|
+
native.select
|
40
|
+
end
|
41
|
+
|
42
|
+
def unselect_option
|
43
|
+
if select_node['multiple'] != 'multiple' and select_node['multiple'] != 'true'
|
44
|
+
raise Capybara::UnselectNotAllowed, "Cannot unselect option from single select box."
|
45
|
+
end
|
46
|
+
native.toggle if selected?
|
47
|
+
end
|
48
|
+
|
49
|
+
def click
|
50
|
+
native.click
|
51
|
+
end
|
52
|
+
|
53
|
+
def drag_to(element)
|
54
|
+
native.drag_and_drop_on(element.native)
|
55
|
+
end
|
56
|
+
|
57
|
+
def tag_name
|
58
|
+
native.tag_name
|
59
|
+
end
|
60
|
+
|
61
|
+
def visible?
|
62
|
+
displayed = native.displayed?
|
63
|
+
displayed and displayed != "false"
|
64
|
+
end
|
65
|
+
|
66
|
+
def selected?
|
67
|
+
selected = native.selected?
|
68
|
+
selected and selected != "false"
|
69
|
+
end
|
70
|
+
|
71
|
+
alias :checked? :selected?
|
72
|
+
|
73
|
+
def find(locator)
|
74
|
+
native.find_elements(:xpath, locator).map { |n| self.class.new(driver, n) }
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# a reference to the select node if this is an option node
|
80
|
+
def select_node
|
81
|
+
find('./ancestor::select').first
|
82
|
+
end
|
83
|
+
|
84
|
+
def type
|
85
|
+
self[:type]
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
attr_reader :app, :rack_server, :options
|
91
|
+
|
92
|
+
def browser
|
93
|
+
unless @browser
|
94
|
+
@browser = Selenium::WebDriver.for(options[:browser] || :firefox, options)
|
95
|
+
at_exit do
|
96
|
+
@browser.quit
|
97
|
+
end
|
98
|
+
end
|
99
|
+
@browser
|
100
|
+
end
|
101
|
+
|
102
|
+
def initialize(app, options={})
|
103
|
+
@app = app
|
104
|
+
@options = options
|
105
|
+
@rack_server = Capybara::Server.new(@app)
|
106
|
+
@rack_server.boot if Capybara.run_server
|
107
|
+
end
|
108
|
+
|
109
|
+
def visit(path)
|
110
|
+
browser.navigate.to(url(path))
|
111
|
+
end
|
112
|
+
|
113
|
+
def source
|
114
|
+
browser.page_source
|
115
|
+
end
|
116
|
+
|
117
|
+
def body
|
118
|
+
browser.page_source
|
119
|
+
end
|
120
|
+
|
121
|
+
def current_url
|
122
|
+
browser.current_url
|
123
|
+
end
|
124
|
+
|
125
|
+
def find(selector)
|
126
|
+
browser.find_elements(:xpath, selector).map { |node| Node.new(self, node) }
|
127
|
+
end
|
128
|
+
|
129
|
+
def wait?; true; end
|
130
|
+
|
131
|
+
def execute_script(script)
|
132
|
+
browser.execute_script script
|
133
|
+
end
|
134
|
+
|
135
|
+
def evaluate_script(script)
|
136
|
+
browser.execute_script "return #{script}"
|
137
|
+
end
|
138
|
+
|
139
|
+
def reset!
|
140
|
+
# Use instance variable directly so we avoid starting the browser just to reset the session
|
141
|
+
@browser.manage.delete_all_cookies if @browser
|
142
|
+
end
|
143
|
+
|
144
|
+
def within_frame(frame_id)
|
145
|
+
old_window = browser.window_handle
|
146
|
+
browser.switch_to.frame(frame_id)
|
147
|
+
yield
|
148
|
+
browser.switch_to.window old_window
|
149
|
+
end
|
150
|
+
|
151
|
+
def within_window(handle, &blk)
|
152
|
+
browser.switch_to.window(handle, &blk)
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
def url(path)
|
158
|
+
rack_server.url(path)
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|