capybara 1.1.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/{History.txt → History.md} +138 -0
- data/License.txt +22 -0
- data/README.md +850 -0
- data/lib/capybara/cucumber.rb +2 -5
- data/lib/capybara/driver/base.rb +6 -6
- data/lib/capybara/driver/node.rb +3 -2
- data/lib/capybara/dsl.rb +13 -124
- data/lib/capybara/helpers.rb +33 -0
- data/lib/capybara/node/actions.rb +16 -30
- data/lib/capybara/node/base.rb +56 -13
- data/lib/capybara/node/element.rb +18 -30
- data/lib/capybara/node/finders.rb +28 -90
- data/lib/capybara/node/matchers.rb +121 -73
- data/lib/capybara/node/simple.rb +13 -11
- data/lib/capybara/query.rb +78 -0
- data/lib/capybara/rack_test/browser.rb +27 -39
- data/lib/capybara/rack_test/driver.rb +13 -3
- data/lib/capybara/rack_test/node.rb +31 -2
- data/lib/capybara/result.rb +72 -0
- data/lib/capybara/rspec/features.rb +4 -1
- data/lib/capybara/rspec/matchers.rb +33 -63
- data/lib/capybara/rspec.rb +7 -4
- data/lib/capybara/selector.rb +97 -34
- data/lib/capybara/selenium/driver.rb +15 -62
- data/lib/capybara/selenium/node.rb +14 -21
- data/lib/capybara/server.rb +32 -27
- data/lib/capybara/session.rb +90 -50
- data/lib/capybara/spec/fixtures/another_test_file.txt +1 -0
- 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 +3 -0
- data/lib/capybara/spec/session/all_spec.rb +61 -59
- data/lib/capybara/spec/session/assert_selector.rb +123 -0
- data/lib/capybara/spec/session/attach_file_spec.rb +72 -55
- data/lib/capybara/spec/session/body_spec.rb +21 -0
- data/lib/capybara/spec/session/check_spec.rb +68 -48
- data/lib/capybara/spec/session/choose_spec.rb +32 -18
- data/lib/capybara/spec/session/click_button_spec.rb +263 -232
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +40 -29
- data/lib/capybara/spec/session/click_link_spec.rb +96 -96
- data/lib/capybara/spec/session/current_url_spec.rb +88 -10
- data/lib/capybara/spec/session/evaluate_script_spec.rb +6 -0
- data/lib/capybara/spec/session/execute_script_spec.rb +7 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +119 -103
- data/lib/capybara/spec/session/find_button_spec.rb +16 -14
- data/lib/capybara/spec/session/find_by_id_spec.rb +16 -14
- data/lib/capybara/spec/session/find_field_spec.rb +23 -21
- data/lib/capybara/spec/session/find_link_spec.rb +15 -14
- data/lib/capybara/spec/session/find_spec.rb +93 -115
- data/lib/capybara/spec/session/first_spec.rb +51 -85
- data/lib/capybara/spec/session/has_button_spec.rb +22 -24
- data/lib/capybara/spec/session/has_css_spec.rb +190 -205
- data/lib/capybara/spec/session/has_field_spec.rb +170 -144
- data/lib/capybara/spec/session/has_link_spec.rb +26 -29
- data/lib/capybara/spec/session/has_select_spec.rb +161 -109
- data/lib/capybara/spec/session/has_selector_spec.rb +94 -100
- data/lib/capybara/spec/session/has_table_spec.rb +22 -88
- data/lib/capybara/spec/session/has_text_spec.rb +195 -0
- data/lib/capybara/spec/session/has_xpath_spec.rb +100 -96
- data/lib/capybara/spec/session/headers.rb +4 -17
- data/lib/capybara/spec/session/html_spec.rb +15 -0
- data/lib/capybara/spec/session/node_spec.rb +205 -0
- data/lib/capybara/spec/session/reset_session_spec.rb +42 -0
- data/lib/capybara/spec/session/response_code.rb +4 -17
- data/lib/capybara/spec/session/save_page_spec.rb +46 -0
- data/lib/capybara/spec/session/screenshot.rb +13 -0
- data/lib/capybara/spec/session/select_spec.rb +99 -88
- data/lib/capybara/spec/session/source_spec.rb +12 -0
- data/lib/capybara/spec/session/text_spec.rb +15 -12
- data/lib/capybara/spec/session/uncheck_spec.rb +22 -17
- data/lib/capybara/spec/session/unselect_spec.rb +69 -58
- data/lib/capybara/spec/session/visit_spec.rb +74 -0
- data/lib/capybara/spec/session/within_frame_spec.rb +31 -0
- data/lib/capybara/spec/session/within_spec.rb +118 -131
- data/lib/capybara/spec/session/within_window_spec.rb +38 -0
- data/lib/capybara/spec/spec_helper.rb +84 -0
- data/lib/capybara/spec/test_app.rb +32 -6
- data/lib/capybara/spec/views/form.erb +12 -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 +9 -4
- data/lib/capybara/spec/views/with_js.erb +11 -7
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara.rb +125 -6
- data/spec/basic_node_spec.rb +17 -5
- data/spec/capybara_spec.rb +9 -0
- data/spec/dsl_spec.rb +31 -17
- data/spec/rack_test_spec.rb +157 -0
- data/spec/result_spec.rb +51 -0
- data/spec/rspec/features_spec.rb +19 -2
- data/spec/rspec/matchers_spec.rb +170 -89
- data/spec/rspec_spec.rb +1 -3
- data/spec/selenium_spec.rb +53 -0
- data/spec/server_spec.rb +37 -25
- data/spec/spec_helper.rb +1 -30
- metadata +39 -31
- 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/spec/session/javascript.rb +0 -306
- data/lib/capybara/spec/session.rb +0 -154
- data/lib/capybara/util/save_and_open_page.rb +0 -44
- 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/save_and_open_page_spec.rb +0 -155
- 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
|
@@ -2,13 +2,11 @@ require 'selenium-webdriver'
|
|
|
2
2
|
|
|
3
3
|
class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
4
4
|
DEFAULT_OPTIONS = {
|
|
5
|
-
:resynchronize => false,
|
|
6
|
-
:resynchronization_timeout => 10,
|
|
7
5
|
:browser => :firefox
|
|
8
6
|
}
|
|
9
|
-
SPECIAL_OPTIONS = [:browser
|
|
7
|
+
SPECIAL_OPTIONS = [:browser]
|
|
10
8
|
|
|
11
|
-
attr_reader :app, :
|
|
9
|
+
attr_reader :app, :options
|
|
12
10
|
|
|
13
11
|
def browser
|
|
14
12
|
unless @browser
|
|
@@ -27,20 +25,20 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
27
25
|
|
|
28
26
|
def initialize(app, options={})
|
|
29
27
|
@app = app
|
|
28
|
+
@browser = nil
|
|
29
|
+
@exit_status = nil
|
|
30
30
|
@options = DEFAULT_OPTIONS.merge(options)
|
|
31
|
-
@rack_server = Capybara::Server.new(@app)
|
|
32
|
-
@rack_server.boot if Capybara.run_server
|
|
33
31
|
end
|
|
34
32
|
|
|
35
33
|
def visit(path)
|
|
36
|
-
browser.navigate.to(
|
|
34
|
+
browser.navigate.to(path)
|
|
37
35
|
end
|
|
38
36
|
|
|
39
37
|
def source
|
|
40
38
|
browser.page_source
|
|
41
39
|
end
|
|
42
40
|
|
|
43
|
-
def
|
|
41
|
+
def html
|
|
44
42
|
browser.page_source
|
|
45
43
|
end
|
|
46
44
|
|
|
@@ -53,18 +51,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
53
51
|
end
|
|
54
52
|
|
|
55
53
|
def wait?; true; end
|
|
56
|
-
|
|
57
|
-
def resynchronize
|
|
58
|
-
if options[:resynchronize]
|
|
59
|
-
load_wait_for_ajax_support
|
|
60
|
-
yield
|
|
61
|
-
Capybara.timeout(options[:resynchronization_timeout], self, "failed to resynchronize, ajax request timed out") do
|
|
62
|
-
evaluate_script("!window.capybaraRequestsOutstanding")
|
|
63
|
-
end
|
|
64
|
-
else
|
|
65
|
-
yield
|
|
66
|
-
end
|
|
67
|
-
end
|
|
54
|
+
def needs_server?; true; end
|
|
68
55
|
|
|
69
56
|
def execute_script(script)
|
|
70
57
|
browser.execute_script script
|
|
@@ -74,12 +61,15 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
74
61
|
browser.execute_script "return #{script}"
|
|
75
62
|
end
|
|
76
63
|
|
|
64
|
+
def save_screenshot(path, options={})
|
|
65
|
+
browser.save_screenshot(path)
|
|
66
|
+
end
|
|
67
|
+
|
|
77
68
|
def reset!
|
|
78
69
|
# Use instance variable directly so we avoid starting the browser just to reset the session
|
|
79
70
|
if @browser
|
|
80
|
-
begin
|
|
81
|
-
|
|
82
|
-
rescue Selenium::WebDriver::Error::UnhandledError => e
|
|
71
|
+
begin @browser.manage.delete_all_cookies
|
|
72
|
+
rescue Selenium::WebDriver::Error::UnhandledError
|
|
83
73
|
# delete_all_cookies fails when we've previously gone
|
|
84
74
|
# to about:blank, so we rescue this error and do nothing
|
|
85
75
|
# instead.
|
|
@@ -92,6 +82,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
92
82
|
old_window = browser.window_handle
|
|
93
83
|
browser.switch_to.frame(frame_id)
|
|
94
84
|
yield
|
|
85
|
+
ensure
|
|
95
86
|
browser.switch_to.window old_window
|
|
96
87
|
end
|
|
97
88
|
|
|
@@ -122,44 +113,6 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
122
113
|
end
|
|
123
114
|
|
|
124
115
|
def invalid_element_errors
|
|
125
|
-
[
|
|
126
|
-
Selenium::WebDriver::Error::InvalidSelectorError,
|
|
127
|
-
Selenium::WebDriver::Error::UnknownError ]
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
private
|
|
131
|
-
|
|
132
|
-
def load_wait_for_ajax_support
|
|
133
|
-
browser.execute_script <<-JS
|
|
134
|
-
window.capybaraRequestsOutstanding = 0;
|
|
135
|
-
(function() { // Overriding XMLHttpRequest
|
|
136
|
-
var oldXHR = window.XMLHttpRequest;
|
|
137
|
-
|
|
138
|
-
function newXHR() {
|
|
139
|
-
var realXHR = new oldXHR();
|
|
140
|
-
|
|
141
|
-
window.capybaraRequestsOutstanding++;
|
|
142
|
-
realXHR.addEventListener("readystatechange", function() {
|
|
143
|
-
if( realXHR.readyState == 4 ) {
|
|
144
|
-
setTimeout( function() {
|
|
145
|
-
window.capybaraRequestsOutstanding--;
|
|
146
|
-
if(window.capybaraRequestsOutstanding < 0) {
|
|
147
|
-
window.capybaraRequestsOutstanding = 0;
|
|
148
|
-
}
|
|
149
|
-
}, 500 );
|
|
150
|
-
}
|
|
151
|
-
}, false);
|
|
152
|
-
|
|
153
|
-
return realXHR;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
window.XMLHttpRequest = newXHR;
|
|
157
|
-
})();
|
|
158
|
-
JS
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def url(path)
|
|
162
|
-
rack_server.url(path)
|
|
116
|
+
[Selenium::WebDriver::Error::StaleElementReferenceError, Selenium::WebDriver::Error::UnhandledError, Selenium::WebDriver::Error::ElementNotVisibleError]
|
|
163
117
|
end
|
|
164
|
-
|
|
165
118
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
2
2
|
def text
|
|
3
|
-
|
|
3
|
+
# Selenium doesn't normalize Unicode whitespace.
|
|
4
|
+
Capybara::Helpers.normalize_whitespace(native.text)
|
|
4
5
|
end
|
|
5
6
|
|
|
6
7
|
def [](name)
|
|
@@ -18,39 +19,40 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
def set(value)
|
|
22
|
+
tag_name = self.tag_name
|
|
23
|
+
type = self[:type]
|
|
24
|
+
if (Array === value) && !self[:multiple]
|
|
25
|
+
raise ArgumentError.new "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}"
|
|
26
|
+
end
|
|
21
27
|
if tag_name == 'input' and type == 'radio'
|
|
22
28
|
click
|
|
23
29
|
elsif tag_name == 'input' and type == 'checkbox'
|
|
24
30
|
click if value ^ native.attribute('checked').to_s.eql?("true")
|
|
25
31
|
elsif tag_name == 'input' and type == 'file'
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
end
|
|
32
|
+
path_names = value.to_s.empty? ? [] : value
|
|
33
|
+
native.send_keys(*path_names)
|
|
29
34
|
elsif tag_name == 'textarea' or tag_name == 'input'
|
|
30
|
-
|
|
31
|
-
native.clear
|
|
32
|
-
native.send_keys(value.to_s)
|
|
33
|
-
end
|
|
35
|
+
native.send_keys(("\b" * native[:value].size) + value.to_s)
|
|
34
36
|
end
|
|
35
37
|
end
|
|
36
38
|
|
|
37
39
|
def select_option
|
|
38
|
-
|
|
40
|
+
native.click unless selected?
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
def unselect_option
|
|
42
44
|
if select_node['multiple'] != 'multiple' and select_node['multiple'] != 'true'
|
|
43
45
|
raise Capybara::UnselectNotAllowed, "Cannot unselect option from single select box."
|
|
44
46
|
end
|
|
45
|
-
|
|
47
|
+
native.click if selected?
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
def click
|
|
49
|
-
|
|
51
|
+
native.click
|
|
50
52
|
end
|
|
51
53
|
|
|
52
54
|
def drag_to(element)
|
|
53
|
-
|
|
55
|
+
driver.browser.action.drag_and_drop(native, element.native).perform
|
|
54
56
|
end
|
|
55
57
|
|
|
56
58
|
def tag_name
|
|
@@ -75,17 +77,8 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
|
75
77
|
|
|
76
78
|
private
|
|
77
79
|
|
|
78
|
-
def resynchronize
|
|
79
|
-
driver.resynchronize { yield }
|
|
80
|
-
end
|
|
81
|
-
|
|
82
80
|
# a reference to the select node if this is an option node
|
|
83
81
|
def select_node
|
|
84
82
|
find('./ancestor::select').first
|
|
85
83
|
end
|
|
86
|
-
|
|
87
|
-
def type
|
|
88
|
-
self[:type]
|
|
89
|
-
end
|
|
90
|
-
|
|
91
84
|
end
|
data/lib/capybara/server.rb
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
require 'uri'
|
|
2
2
|
require 'net/http'
|
|
3
3
|
require 'rack'
|
|
4
|
-
require 'capybara/util/timeout'
|
|
5
4
|
|
|
6
5
|
module Capybara
|
|
7
6
|
class Server
|
|
8
|
-
class
|
|
7
|
+
class Middleware
|
|
8
|
+
attr_accessor :error
|
|
9
|
+
|
|
9
10
|
def initialize(app)
|
|
10
11
|
@app = app
|
|
11
12
|
end
|
|
@@ -14,7 +15,12 @@ module Capybara
|
|
|
14
15
|
if env["PATH_INFO"] == "/__identify__"
|
|
15
16
|
[200, {}, [@app.object_id.to_s]]
|
|
16
17
|
else
|
|
17
|
-
|
|
18
|
+
begin
|
|
19
|
+
@app.call(env)
|
|
20
|
+
rescue StandardError => e
|
|
21
|
+
@error = e unless @error
|
|
22
|
+
raise e
|
|
23
|
+
end
|
|
18
24
|
end
|
|
19
25
|
end
|
|
20
26
|
end
|
|
@@ -27,23 +33,30 @@ module Capybara
|
|
|
27
33
|
|
|
28
34
|
attr_reader :app, :port
|
|
29
35
|
|
|
30
|
-
def initialize(app)
|
|
36
|
+
def initialize(app, port=Capybara.server_port)
|
|
31
37
|
@app = app
|
|
38
|
+
@middleware = Middleware.new(@app)
|
|
39
|
+
@server_thread = nil # supress warnings
|
|
40
|
+
@port = port
|
|
41
|
+
@port ||= Capybara::Server.ports[@app.object_id]
|
|
42
|
+
@port ||= find_available_port
|
|
32
43
|
end
|
|
33
44
|
|
|
34
|
-
def
|
|
35
|
-
|
|
45
|
+
def reset_error!
|
|
46
|
+
@middleware.error = nil
|
|
36
47
|
end
|
|
37
48
|
|
|
38
|
-
def
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
def error
|
|
50
|
+
@middleware.error
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def host
|
|
54
|
+
Capybara.server_host || "127.0.0.1"
|
|
44
55
|
end
|
|
45
56
|
|
|
46
57
|
def responsive?
|
|
58
|
+
return false if @server_thread && @server_thread.join(0)
|
|
59
|
+
|
|
47
60
|
res = Net::HTTP.start(host, @port) { |http| http.get('/__identify__') }
|
|
48
61
|
|
|
49
62
|
if res.is_a?(Net::HTTPSuccess) or res.is_a?(Net::HTTPRedirection)
|
|
@@ -54,25 +67,17 @@ module Capybara
|
|
|
54
67
|
end
|
|
55
68
|
|
|
56
69
|
def boot
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if not @port or not responsive?
|
|
61
|
-
@port = Capybara.server_port || find_available_port
|
|
62
|
-
Capybara::Server.ports[@app.object_id] = @port
|
|
63
|
-
|
|
64
|
-
Thread.new do
|
|
65
|
-
Capybara.server.call(Identify.new(@app), @port)
|
|
66
|
-
end
|
|
70
|
+
unless responsive?
|
|
71
|
+
Capybara::Server.ports[@app.object_id] = @port
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
end
|
|
73
|
+
@server_thread = Thread.new do
|
|
74
|
+
Capybara.server.call(@middleware, @port)
|
|
71
75
|
end
|
|
76
|
+
|
|
77
|
+
Timeout.timeout(60) { @server_thread.join(0.1) until responsive? }
|
|
72
78
|
end
|
|
73
79
|
rescue TimeoutError
|
|
74
|
-
|
|
75
|
-
exit
|
|
80
|
+
raise "Rack application timed out during boot"
|
|
76
81
|
else
|
|
77
82
|
self
|
|
78
83
|
end
|
data/lib/capybara/session.rb
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
require 'capybara/util/timeout'
|
|
2
|
-
|
|
3
1
|
module Capybara
|
|
4
2
|
|
|
5
3
|
##
|
|
@@ -30,26 +28,30 @@ module Capybara
|
|
|
30
28
|
:all, :first, :attach_file, :text, :check, :choose,
|
|
31
29
|
:click_link_or_button, :click_button, :click_link, :field_labeled,
|
|
32
30
|
:fill_in, :find, :find_button, :find_by_id, :find_field, :find_link,
|
|
33
|
-
:has_content?, :
|
|
34
|
-
:
|
|
35
|
-
:
|
|
36
|
-
:
|
|
37
|
-
:
|
|
38
|
-
:click_on, :has_no_checked_field?,
|
|
31
|
+
:has_content?, :has_text?, :has_css?, :has_no_content?, :has_no_text?,
|
|
32
|
+
:has_no_css?, :has_no_xpath?, :resolve, :has_xpath?, :select, :uncheck,
|
|
33
|
+
:has_link?, :has_no_link?, :has_button?, :has_no_button?, :has_field?,
|
|
34
|
+
:has_no_field?, :has_checked_field?, :has_unchecked_field?,
|
|
35
|
+
:has_no_table?, :has_table?, :unselect, :has_select?, :has_no_select?,
|
|
36
|
+
:has_selector?, :has_no_selector?, :click_on, :has_no_checked_field?,
|
|
37
|
+
:has_no_unchecked_field?, :query, :assert_selector, :assert_no_selector
|
|
39
38
|
]
|
|
40
39
|
SESSION_METHODS = [
|
|
41
40
|
:body, :html, :current_url, :current_host, :evaluate_script, :source,
|
|
42
|
-
:visit, :
|
|
43
|
-
:
|
|
44
|
-
:
|
|
41
|
+
:visit, :within, :within_fieldset, :within_table, :within_frame,
|
|
42
|
+
:within_window, :current_path, :save_page, :save_and_open_page,
|
|
43
|
+
:save_screenshot, :reset_session!, :response_headers, :status_code
|
|
45
44
|
]
|
|
46
45
|
DSL_METHODS = NODE_METHODS + SESSION_METHODS
|
|
47
46
|
|
|
48
|
-
attr_reader :mode, :app
|
|
47
|
+
attr_reader :mode, :app, :server
|
|
49
48
|
|
|
50
49
|
def initialize(mode, app=nil)
|
|
51
50
|
@mode = mode
|
|
52
51
|
@app = app
|
|
52
|
+
if Capybara.run_server and @app and driver.needs_server?
|
|
53
|
+
@server = Capybara::Server.new(@app).boot
|
|
54
|
+
end
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
def driver
|
|
@@ -67,7 +69,11 @@ module Capybara
|
|
|
67
69
|
# Reset the session, removing all cookies.
|
|
68
70
|
#
|
|
69
71
|
def reset!
|
|
70
|
-
driver.reset!
|
|
72
|
+
driver.reset! if @touched
|
|
73
|
+
@touched = false
|
|
74
|
+
raise @server.error if @server and @server.error
|
|
75
|
+
ensure
|
|
76
|
+
@server.reset_error! if @server
|
|
71
77
|
end
|
|
72
78
|
alias_method :cleanup!, :reset!
|
|
73
79
|
alias_method :reset_session!, :reset!
|
|
@@ -94,12 +100,11 @@ module Capybara
|
|
|
94
100
|
|
|
95
101
|
##
|
|
96
102
|
#
|
|
97
|
-
# @return [String] A snapshot of the
|
|
103
|
+
# @return [String] A snapshot of the DOM of the current document, as it looks right now (potentially modified by JavaScript).
|
|
98
104
|
#
|
|
99
|
-
def
|
|
100
|
-
driver.
|
|
105
|
+
def html
|
|
106
|
+
driver.html
|
|
101
107
|
end
|
|
102
|
-
alias_method :html, :body
|
|
103
108
|
|
|
104
109
|
##
|
|
105
110
|
#
|
|
@@ -108,6 +113,7 @@ module Capybara
|
|
|
108
113
|
def source
|
|
109
114
|
driver.source
|
|
110
115
|
end
|
|
116
|
+
alias_method :body, :source
|
|
111
117
|
|
|
112
118
|
##
|
|
113
119
|
#
|
|
@@ -143,17 +149,39 @@ module Capybara
|
|
|
143
149
|
# session.visit('/foo')
|
|
144
150
|
# session.visit('http://google.com')
|
|
145
151
|
#
|
|
146
|
-
# For drivers which can run against an external application, such as
|
|
152
|
+
# For drivers which can run against an external application, such as the selenium driver
|
|
147
153
|
# giving an absolute URL will navigate to that page. This allows testing applications
|
|
148
|
-
# running on remote servers. For these drivers, setting Capybara.app_host will make the
|
|
154
|
+
# running on remote servers. For these drivers, setting {Capybara.app_host} will make the
|
|
149
155
|
# remote server the default. For example:
|
|
150
156
|
#
|
|
151
157
|
# Capybara.app_host = 'http://google.com'
|
|
152
158
|
# session.visit('/') # visits the google homepage
|
|
153
159
|
#
|
|
160
|
+
# If {Capybara.always_include_port} is set to true and this session is running against
|
|
161
|
+
# a rack application, then the port that the rack application is running on will automatically
|
|
162
|
+
# be inserted into the URL. Supposing the app is running on port `4567`, doing something like:
|
|
163
|
+
#
|
|
164
|
+
# visit("http://google.com/test")
|
|
165
|
+
#
|
|
166
|
+
# Will actually navigate to `http://google.com:4567/test`.
|
|
167
|
+
#
|
|
154
168
|
# @param [String] url The URL to navigate to
|
|
155
169
|
#
|
|
156
170
|
def visit(url)
|
|
171
|
+
@touched = true
|
|
172
|
+
|
|
173
|
+
if @server
|
|
174
|
+
unless url =~ /^http/
|
|
175
|
+
url = (Capybara.app_host || "http://#{@server.host}:#{@server.port}") + url.to_s
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
if Capybara.always_include_port
|
|
179
|
+
uri = URI.parse(url)
|
|
180
|
+
uri.port = @server.port if uri.port == uri.default_port
|
|
181
|
+
url = uri.to_s
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
157
185
|
driver.visit(url)
|
|
158
186
|
end
|
|
159
187
|
|
|
@@ -182,11 +210,7 @@ module Capybara
|
|
|
182
210
|
# @raise [Capybara::ElementNotFound] If the scope can't be found before time expires
|
|
183
211
|
#
|
|
184
212
|
def within(*args)
|
|
185
|
-
new_scope = if args.
|
|
186
|
-
args.first
|
|
187
|
-
else
|
|
188
|
-
find(*args)
|
|
189
|
-
end
|
|
213
|
+
new_scope = if args.first.is_a?(Capybara::Node::Base) then args.first else find(*args) end
|
|
190
214
|
begin
|
|
191
215
|
scopes.push(new_scope)
|
|
192
216
|
yield
|
|
@@ -202,7 +226,7 @@ module Capybara
|
|
|
202
226
|
# @param [String] locator Id or legend of the fieldset
|
|
203
227
|
#
|
|
204
228
|
def within_fieldset(locator)
|
|
205
|
-
within :
|
|
229
|
+
within :fieldset, locator do
|
|
206
230
|
yield
|
|
207
231
|
end
|
|
208
232
|
end
|
|
@@ -214,7 +238,7 @@ module Capybara
|
|
|
214
238
|
# @param [String] locator Id or caption of the table
|
|
215
239
|
#
|
|
216
240
|
def within_table(locator)
|
|
217
|
-
within :
|
|
241
|
+
within :table, locator do
|
|
218
242
|
yield
|
|
219
243
|
end
|
|
220
244
|
end
|
|
@@ -224,7 +248,7 @@ module Capybara
|
|
|
224
248
|
# Execute the given block within the given iframe given the id of that iframe. Only works on
|
|
225
249
|
# some drivers (e.g. Selenium)
|
|
226
250
|
#
|
|
227
|
-
# @param [String]
|
|
251
|
+
# @param [String] frame_id Id of the frame
|
|
228
252
|
#
|
|
229
253
|
def within_frame(frame_id)
|
|
230
254
|
driver.within_frame(frame_id) do
|
|
@@ -237,31 +261,22 @@ module Capybara
|
|
|
237
261
|
# Execute the given block within the given window. Only works on
|
|
238
262
|
# some drivers (e.g. Selenium)
|
|
239
263
|
#
|
|
240
|
-
# @param [String]
|
|
264
|
+
# @param [String] handle of the window
|
|
241
265
|
#
|
|
242
266
|
def within_window(handle, &blk)
|
|
243
267
|
driver.within_window(handle, &blk)
|
|
244
268
|
end
|
|
245
269
|
|
|
246
|
-
##
|
|
247
|
-
#
|
|
248
|
-
# Retry executing the block until a truthy result is returned or the timeout time is exceeded
|
|
249
|
-
#
|
|
250
|
-
# @param [Integer] timeout The amount of seconds to retry executing the given block
|
|
251
|
-
#
|
|
252
|
-
def wait_until(timeout = Capybara.default_wait_time)
|
|
253
|
-
Capybara.timeout(timeout,driver) { yield }
|
|
254
|
-
end
|
|
255
|
-
|
|
256
270
|
##
|
|
257
271
|
#
|
|
258
272
|
# Execute the given script, not returning a result. This is useful for scripts that return
|
|
259
|
-
# complex objects, such as jQuery statements. +execute_script+ should
|
|
273
|
+
# complex objects, such as jQuery statements. +execute_script+ should be used over
|
|
260
274
|
# +evaluate_script+ whenever possible.
|
|
261
275
|
#
|
|
262
276
|
# @param [String] script A string of JavaScript to execute
|
|
263
277
|
#
|
|
264
278
|
def execute_script(script)
|
|
279
|
+
@touched = true
|
|
265
280
|
driver.execute_script(script)
|
|
266
281
|
end
|
|
267
282
|
|
|
@@ -275,21 +290,47 @@ module Capybara
|
|
|
275
290
|
# @return [Object] The result of the evaluated JavaScript (may be driver specific)
|
|
276
291
|
#
|
|
277
292
|
def evaluate_script(script)
|
|
293
|
+
@touched = true
|
|
278
294
|
driver.evaluate_script(script)
|
|
279
295
|
end
|
|
280
296
|
|
|
297
|
+
##
|
|
298
|
+
#
|
|
299
|
+
# Save a snapshot of the page.
|
|
300
|
+
#
|
|
301
|
+
# @param [String] path The path to where it should be saved [optional]
|
|
302
|
+
#
|
|
303
|
+
def save_page(path=nil)
|
|
304
|
+
path ||= "capybara-#{Time.new.strftime("%Y%m%d%H%M%S")}#{rand(10**10)}.html"
|
|
305
|
+
path = File.expand_path(path, Capybara.save_and_open_page_path) if Capybara.save_and_open_page_path
|
|
306
|
+
|
|
307
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
308
|
+
|
|
309
|
+
File.open(path,'w') { |f| f.write(body) }
|
|
310
|
+
path
|
|
311
|
+
end
|
|
312
|
+
|
|
281
313
|
##
|
|
282
314
|
#
|
|
283
315
|
# Save a snapshot of the page and open it in a browser for inspection
|
|
284
316
|
#
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
317
|
+
# @param [String] path The path to where it should be saved [optional]
|
|
318
|
+
#
|
|
319
|
+
def save_and_open_page(file_name=nil)
|
|
320
|
+
require "launchy"
|
|
321
|
+
Launchy.open(save_page(file_name))
|
|
322
|
+
rescue LoadError
|
|
323
|
+
warn "Please install the launchy gem to open page with save_and_open_page"
|
|
288
324
|
end
|
|
289
325
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
326
|
+
##
|
|
327
|
+
#
|
|
328
|
+
# Save a screenshot of page
|
|
329
|
+
#
|
|
330
|
+
# @param [String] path A string of image path
|
|
331
|
+
# @option [Hash] options Options for saving screenshot
|
|
332
|
+
def save_screenshot(path, options={})
|
|
333
|
+
driver.save_screenshot(path, options)
|
|
293
334
|
end
|
|
294
335
|
|
|
295
336
|
def document
|
|
@@ -297,11 +338,10 @@ module Capybara
|
|
|
297
338
|
end
|
|
298
339
|
|
|
299
340
|
NODE_METHODS.each do |method|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
RUBY
|
|
341
|
+
define_method method do |*args, &block|
|
|
342
|
+
@touched = true
|
|
343
|
+
current_node.send(method, *args, &block)
|
|
344
|
+
end
|
|
305
345
|
end
|
|
306
346
|
|
|
307
347
|
def inspect
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ThisIsTheOtherTestFile
|