capybara 0.2.0 → 0.3.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/Manifest.txt +39 -0
- data/README.rdoc +181 -57
- data/Rakefile +7 -16
- data/config.ru +6 -0
- data/lib/capybara.rb +19 -9
- data/lib/capybara/cucumber.rb +4 -0
- data/lib/capybara/driver/base.rb +25 -8
- data/lib/capybara/driver/celerity_driver.rb +108 -0
- data/lib/capybara/driver/culerity_driver.rb +1 -70
- data/lib/capybara/driver/rack_test_driver.rb +57 -25
- data/lib/capybara/driver/selenium_driver.rb +28 -10
- data/lib/capybara/dsl.rb +7 -4
- data/lib/capybara/node.rb +50 -29
- data/lib/capybara/rails.rb +1 -1
- data/lib/capybara/save_and_open_page.rb +1 -1
- data/lib/capybara/searchable.rb +45 -0
- data/lib/capybara/server.rb +11 -4
- data/lib/capybara/session.rb +94 -94
- data/lib/capybara/wait_until.rb +23 -0
- data/lib/capybara/xpath.rb +55 -41
- data/spec/capybara_spec.rb +18 -0
- data/spec/driver/celerity_driver_spec.rb +17 -0
- data/spec/driver/culerity_driver_spec.rb +3 -0
- data/spec/driver/rack_test_driver_spec.rb +3 -0
- data/spec/driver/remote_culerity_driver_spec.rb +19 -0
- data/spec/driver/remote_selenium_driver_spec.rb +18 -0
- data/spec/driver/selenium_driver_spec.rb +2 -0
- data/spec/drivers_spec.rb +51 -5
- data/spec/dsl/all_spec.rb +38 -0
- data/spec/dsl/attach_file_spec.rb +66 -0
- data/spec/dsl/check_spec.rb +28 -0
- data/spec/dsl/choose_spec.rb +28 -0
- data/spec/dsl/click_button_spec.rb +183 -0
- data/spec/dsl/click_link_spec.rb +88 -0
- data/spec/dsl/click_spec.rb +26 -0
- data/spec/dsl/current_url_spec.rb +10 -0
- data/spec/dsl/fill_in_spec.rb +83 -0
- data/spec/dsl/find_button_spec.rb +18 -0
- data/spec/dsl/find_field_spec.rb +24 -0
- data/spec/dsl/find_link_spec.rb +19 -0
- data/spec/dsl/find_spec.rb +36 -0
- data/spec/dsl/has_content_spec.rb +103 -0
- data/spec/dsl/has_css_spec.rb +109 -0
- data/spec/dsl/has_xpath_spec.rb +115 -0
- data/spec/dsl/locate_spec.rb +38 -0
- data/spec/dsl/select_spec.rb +27 -0
- data/spec/dsl/uncheck_spec.rb +29 -0
- data/spec/dsl/within_spec.rb +145 -0
- data/spec/fixtures/capybara.jpg +0 -0
- data/spec/public/test.js +27 -0
- data/spec/searchable_spec.rb +61 -0
- data/spec/server_spec.rb +47 -0
- data/spec/session/celerity_session_spec.rb +27 -0
- data/spec/session/culerity_session_spec.rb +1 -0
- data/spec/session/rack_test_session_spec.rb +1 -0
- data/spec/session/selenium_session_spec.rb +1 -0
- data/spec/session_spec.rb +32 -903
- data/spec/session_with_headers_support_spec.rb +13 -0
- data/spec/session_with_javascript_support_spec.rb +165 -0
- data/spec/session_without_headers_support_spec.rb +15 -0
- data/spec/session_without_javascript_support_spec.rb +15 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/test_app.rb +9 -1
- data/spec/views/form.erb +38 -0
- data/spec/views/postback.erb +13 -0
- data/spec/views/with_html.erb +13 -0
- data/spec/views/with_js.erb +9 -24
- data/spec/views/with_simple_html.erb +1 -1
- data/spec/wait_until_spec.rb +28 -0
- data/spec/xpath_spec.rb +34 -3
- metadata +54 -5
data/lib/capybara/cucumber.rb
CHANGED
data/lib/capybara/driver/base.rb
CHANGED
@@ -1,17 +1,34 @@
|
|
1
1
|
class Capybara::Driver::Base
|
2
|
+
def current_url
|
3
|
+
raise NotImplementedError
|
4
|
+
end
|
5
|
+
|
2
6
|
def visit(path)
|
3
|
-
raise
|
7
|
+
raise NotImplementedError
|
4
8
|
end
|
5
|
-
|
9
|
+
|
6
10
|
def find(query)
|
7
|
-
raise
|
11
|
+
raise NotImplementedError
|
8
12
|
end
|
9
|
-
|
10
|
-
def
|
11
|
-
raise
|
13
|
+
|
14
|
+
def evaluate_script(script)
|
15
|
+
raise Capybara::NotSupportedByDriverError
|
12
16
|
end
|
13
|
-
|
17
|
+
|
14
18
|
def wait?
|
15
19
|
false
|
16
20
|
end
|
17
|
-
|
21
|
+
|
22
|
+
def response_headers
|
23
|
+
raise Capybara::NotSupportedByDriverError
|
24
|
+
end
|
25
|
+
|
26
|
+
def body
|
27
|
+
raise NotImplementedError
|
28
|
+
end
|
29
|
+
|
30
|
+
def source
|
31
|
+
raise NotImplementedError
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
class Capybara::Driver::Celerity < Capybara::Driver::Base
|
2
|
+
class Node < Capybara::Node
|
3
|
+
def text
|
4
|
+
node.text
|
5
|
+
end
|
6
|
+
|
7
|
+
def [](name)
|
8
|
+
value = if name.to_sym == :class
|
9
|
+
node.class_name
|
10
|
+
else
|
11
|
+
node.send(name.to_sym)
|
12
|
+
end
|
13
|
+
return value if value and not value.empty?
|
14
|
+
end
|
15
|
+
|
16
|
+
def set(value)
|
17
|
+
node.set(value)
|
18
|
+
end
|
19
|
+
|
20
|
+
def select(option)
|
21
|
+
node.select(option)
|
22
|
+
end
|
23
|
+
|
24
|
+
def click
|
25
|
+
node.click
|
26
|
+
end
|
27
|
+
|
28
|
+
def drag_to(element)
|
29
|
+
node.fire_event('mousedown')
|
30
|
+
element.node.fire_event('mousemove')
|
31
|
+
element.node.fire_event('mouseup')
|
32
|
+
end
|
33
|
+
|
34
|
+
def tag_name
|
35
|
+
# FIXME: this might be the dumbest way ever of getting the tag name
|
36
|
+
# there has to be something better...
|
37
|
+
node.to_xml[/^\s*<([a-z0-9\-\:]+)/, 1]
|
38
|
+
end
|
39
|
+
|
40
|
+
def visible?
|
41
|
+
node.visible?
|
42
|
+
end
|
43
|
+
|
44
|
+
def path
|
45
|
+
node.xpath
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
attr_reader :app, :rack_server
|
51
|
+
|
52
|
+
def initialize(app)
|
53
|
+
@app = app
|
54
|
+
unless Capybara.app_host
|
55
|
+
@rack_server = Capybara::Server.new(@app)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def visit(path)
|
60
|
+
browser.goto(url(path))
|
61
|
+
end
|
62
|
+
|
63
|
+
def current_url
|
64
|
+
browser.url
|
65
|
+
end
|
66
|
+
|
67
|
+
def source
|
68
|
+
browser.html
|
69
|
+
end
|
70
|
+
|
71
|
+
def body
|
72
|
+
browser.document.as_xml
|
73
|
+
end
|
74
|
+
|
75
|
+
def response_headers
|
76
|
+
browser.response_headers
|
77
|
+
end
|
78
|
+
|
79
|
+
def find(selector)
|
80
|
+
browser.elements_by_xpath(selector).map { |node| Node.new(self, node) }
|
81
|
+
end
|
82
|
+
|
83
|
+
def wait?; true; end
|
84
|
+
|
85
|
+
def evaluate_script(script)
|
86
|
+
browser.execute_script "#{script}"
|
87
|
+
end
|
88
|
+
|
89
|
+
def browser
|
90
|
+
unless @_browser
|
91
|
+
require 'celerity'
|
92
|
+
@_browser = ::Celerity::Browser.new(:browser => :firefox, :log_level => :off)
|
93
|
+
end
|
94
|
+
|
95
|
+
@_browser
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def url(path)
|
101
|
+
if rack_server
|
102
|
+
rack_server.url(path)
|
103
|
+
else
|
104
|
+
Capybara.app_host.to_s + path
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
@@ -1,46 +1,6 @@
|
|
1
1
|
require 'culerity'
|
2
2
|
|
3
|
-
class Capybara::Driver::Culerity < Capybara::Driver::
|
4
|
-
class Node < Capybara::Node
|
5
|
-
def text
|
6
|
-
node.text
|
7
|
-
end
|
8
|
-
|
9
|
-
def [](name)
|
10
|
-
value = if name.to_sym == :class
|
11
|
-
node.class_name
|
12
|
-
else
|
13
|
-
node.send(name.to_sym)
|
14
|
-
end
|
15
|
-
return value if value and not value.empty?
|
16
|
-
end
|
17
|
-
|
18
|
-
def set(value)
|
19
|
-
node.set(value)
|
20
|
-
end
|
21
|
-
|
22
|
-
def select(option)
|
23
|
-
node.select(option)
|
24
|
-
end
|
25
|
-
|
26
|
-
def click
|
27
|
-
node.click
|
28
|
-
end
|
29
|
-
|
30
|
-
def drag_to(element)
|
31
|
-
node.fire_event('mousedown')
|
32
|
-
element.node.fire_event('mousemove')
|
33
|
-
element.node.fire_event('mouseup')
|
34
|
-
end
|
35
|
-
|
36
|
-
def tag_name
|
37
|
-
# FIXME: this might be the dumbest way ever of getting the tag name
|
38
|
-
# there has to be something better...
|
39
|
-
node.to_xml[/^\s*<([a-z0-9\-\:]+)/, 1]
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
attr_reader :app, :rack_server
|
3
|
+
class Capybara::Driver::Culerity < Capybara::Driver::Celerity
|
44
4
|
|
45
5
|
def self.server
|
46
6
|
unless @_server
|
@@ -52,35 +12,6 @@ class Capybara::Driver::Culerity < Capybara::Driver::Base
|
|
52
12
|
@_server
|
53
13
|
end
|
54
14
|
|
55
|
-
def initialize(app)
|
56
|
-
@app = app
|
57
|
-
@rack_server = Capybara::Server.new(@app)
|
58
|
-
end
|
59
|
-
|
60
|
-
def visit(path)
|
61
|
-
browser.goto(url(path))
|
62
|
-
end
|
63
|
-
|
64
|
-
def body
|
65
|
-
browser.html
|
66
|
-
end
|
67
|
-
|
68
|
-
def find(selector)
|
69
|
-
browser.elements_by_xpath(selector).map { |node| Node.new(self, node) }
|
70
|
-
end
|
71
|
-
|
72
|
-
def wait?; true; end
|
73
|
-
|
74
|
-
def evaluate_script(script)
|
75
|
-
browser.execute_script "#{script}"
|
76
|
-
end
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
|
-
def url(path)
|
81
|
-
rack_server.url(path)
|
82
|
-
end
|
83
|
-
|
84
15
|
def browser
|
85
16
|
unless @_browser
|
86
17
|
@_browser = ::Culerity::RemoteBrowserProxy.new self.class.server, {:browser => :firefox, :log_level => :off}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rack/test'
|
2
|
+
require 'mime/types'
|
2
3
|
require 'nokogiri'
|
3
4
|
require 'cgi'
|
4
5
|
|
@@ -7,7 +8,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
7
8
|
def text
|
8
9
|
node.text
|
9
10
|
end
|
10
|
-
|
11
|
+
|
11
12
|
def [](name)
|
12
13
|
value = node[name.to_s]
|
13
14
|
return value.to_s if value
|
@@ -29,7 +30,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
29
30
|
node.content = value.to_s
|
30
31
|
end
|
31
32
|
end
|
32
|
-
|
33
|
+
|
33
34
|
def select(option)
|
34
35
|
node.xpath(".//option").each { |node| node.remove_attribute("selected") }
|
35
36
|
node.xpath(".//option[contains(.,'#{option}')]").first["selected"] = 'selected'
|
@@ -37,18 +38,26 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
37
38
|
|
38
39
|
def click
|
39
40
|
if tag_name == 'a'
|
40
|
-
driver.visit(self[:href])
|
41
|
+
driver.visit(self[:href].to_s)
|
41
42
|
elsif (tag_name == 'input' or tag_name == 'button') and %w(submit image).include?(type)
|
42
43
|
Form.new(driver, form).submit(self)
|
43
44
|
end
|
44
45
|
end
|
45
|
-
|
46
|
+
|
46
47
|
def tag_name
|
47
48
|
node.node_name
|
48
49
|
end
|
49
50
|
|
51
|
+
def visible?
|
52
|
+
node.xpath("./ancestor-or-self::*[contains(@style, 'display:none')]").size == 0
|
53
|
+
end
|
54
|
+
|
55
|
+
def path
|
56
|
+
node.path
|
57
|
+
end
|
58
|
+
|
50
59
|
private
|
51
|
-
|
60
|
+
|
52
61
|
def type
|
53
62
|
self[:type]
|
54
63
|
end
|
@@ -76,9 +85,11 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
76
85
|
merge_param!(params, select['name'].to_s, (option['value'] || option.text).to_s) if option
|
77
86
|
end
|
78
87
|
node.xpath(".//input[@type='file']").map do |input|
|
79
|
-
|
88
|
+
unless input['value'].to_s.empty?
|
80
89
|
if multipart?
|
81
|
-
|
90
|
+
content_type = MIME::Types.type_for(input['value'].to_s).first.to_s
|
91
|
+
file = Rack::Test::UploadedFile.new(input['value'].to_s, content_type)
|
92
|
+
merge_param!(params, input['name'].to_s, file)
|
82
93
|
else
|
83
94
|
merge_param!(params, input['name'].to_s, File.basename(input['value'].to_s))
|
84
95
|
end
|
@@ -89,23 +100,19 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
89
100
|
end
|
90
101
|
|
91
102
|
def submit(button)
|
92
|
-
|
93
|
-
driver.submit(node['action'].to_s, params(button))
|
94
|
-
else
|
95
|
-
driver.visit(node['action'].to_s, params(button))
|
96
|
-
end
|
103
|
+
driver.submit(method, node['action'].to_s, params(button))
|
97
104
|
end
|
98
105
|
|
99
106
|
def multipart?
|
100
107
|
self[:enctype] == "multipart/form-data"
|
101
108
|
end
|
109
|
+
|
110
|
+
private
|
102
111
|
|
103
|
-
def
|
104
|
-
self[:method] =~ /post/i
|
112
|
+
def method
|
113
|
+
self[:method] =~ /post/i ? :post : :get
|
105
114
|
end
|
106
|
-
|
107
|
-
private
|
108
|
-
|
115
|
+
|
109
116
|
def merge_param!(params, key, value)
|
110
117
|
collection = key.sub!(/\[\]$/, '')
|
111
118
|
if collection
|
@@ -119,26 +126,37 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
119
126
|
end
|
120
127
|
end
|
121
128
|
end
|
122
|
-
|
129
|
+
|
123
130
|
include ::Rack::Test::Methods
|
124
131
|
attr_reader :app, :html, :body
|
125
132
|
|
126
133
|
alias_method :response, :last_response
|
127
134
|
alias_method :request, :last_request
|
128
|
-
|
135
|
+
alias_method :source, :body
|
136
|
+
|
129
137
|
def initialize(app)
|
130
138
|
@app = app
|
131
139
|
end
|
132
|
-
|
140
|
+
|
133
141
|
def visit(path, attributes = {})
|
142
|
+
return if path.gsub(/^#{current_path}/, '') =~ /^#/
|
134
143
|
get(path, attributes)
|
135
|
-
|
144
|
+
follow_redirects!
|
136
145
|
cache_body
|
137
146
|
end
|
138
147
|
|
139
|
-
def
|
140
|
-
|
141
|
-
|
148
|
+
def current_url
|
149
|
+
request.url rescue ""
|
150
|
+
end
|
151
|
+
|
152
|
+
def response_headers
|
153
|
+
response.headers
|
154
|
+
end
|
155
|
+
|
156
|
+
def submit(method, path, attributes)
|
157
|
+
path = current_path if not path or path.empty?
|
158
|
+
send(method, path, attributes)
|
159
|
+
follow_redirects!
|
142
160
|
cache_body
|
143
161
|
end
|
144
162
|
|
@@ -146,7 +164,21 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
146
164
|
html.xpath(selector).map { |node| Node.new(self, node) }
|
147
165
|
end
|
148
166
|
|
149
|
-
|
167
|
+
private
|
168
|
+
|
169
|
+
def current_path
|
170
|
+
request.path rescue ""
|
171
|
+
end
|
172
|
+
|
173
|
+
def follow_redirects!
|
174
|
+
Capybara::WaitUntil.timeout(4) do
|
175
|
+
redirect = response.redirect?
|
176
|
+
follow_redirect! if redirect
|
177
|
+
not redirect
|
178
|
+
end
|
179
|
+
rescue Capybara::TimeoutError
|
180
|
+
raise Capybara::InfiniteRedirectError, "infinite redirect detected!"
|
181
|
+
end
|
150
182
|
|
151
183
|
def cache_body
|
152
184
|
@body = response.body
|
@@ -43,6 +43,10 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
|
|
43
43
|
node.tag_name
|
44
44
|
end
|
45
45
|
|
46
|
+
def visible?
|
47
|
+
node.displayed? and node.displayed? != "false"
|
48
|
+
end
|
49
|
+
|
46
50
|
private
|
47
51
|
|
48
52
|
def type
|
@@ -65,35 +69,49 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
|
|
65
69
|
|
66
70
|
def initialize(app)
|
67
71
|
@app = app
|
68
|
-
|
72
|
+
unless Capybara.app_host
|
73
|
+
@rack_server = Capybara::Server.new(@app)
|
74
|
+
end
|
69
75
|
end
|
70
76
|
|
71
77
|
def visit(path)
|
72
|
-
|
78
|
+
browser.navigate.to(url(path))
|
79
|
+
end
|
80
|
+
|
81
|
+
def source
|
82
|
+
browser.page_source
|
73
83
|
end
|
74
84
|
|
75
85
|
def body
|
76
|
-
|
86
|
+
browser.page_source
|
87
|
+
end
|
88
|
+
|
89
|
+
def current_url
|
90
|
+
browser.current_url
|
77
91
|
end
|
78
92
|
|
79
93
|
def find(selector)
|
80
|
-
|
94
|
+
browser.find_elements(:xpath, selector).map { |node| Node.new(self, node) }
|
81
95
|
end
|
82
96
|
|
83
97
|
def wait?; true; end
|
84
98
|
|
85
99
|
def evaluate_script(script)
|
86
|
-
|
100
|
+
browser.execute_script "return #{script}"
|
101
|
+
end
|
102
|
+
|
103
|
+
def browser
|
104
|
+
self.class.driver
|
87
105
|
end
|
88
106
|
|
89
107
|
private
|
90
108
|
|
91
109
|
def url(path)
|
92
|
-
rack_server
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
110
|
+
if rack_server
|
111
|
+
rack_server.url(path)
|
112
|
+
else
|
113
|
+
Capybara.app_host.to_s + path
|
114
|
+
end
|
97
115
|
end
|
98
116
|
|
99
117
|
end
|