aslakhellesoy-webrat 0.3.2.1
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 +193 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.rdoc +81 -0
- data/Rakefile +104 -0
- data/install.rb +1 -0
- data/lib/webrat.rb +34 -0
- data/lib/webrat/core.rb +14 -0
- data/lib/webrat/core/configuration.rb +44 -0
- data/lib/webrat/core/elements/area.rb +31 -0
- data/lib/webrat/core/elements/element.rb +33 -0
- data/lib/webrat/core/elements/field.rb +386 -0
- data/lib/webrat/core/elements/form.rb +103 -0
- data/lib/webrat/core/elements/label.rb +31 -0
- data/lib/webrat/core/elements/link.rb +90 -0
- data/lib/webrat/core/elements/select_option.rb +35 -0
- data/lib/webrat/core/locators.rb +20 -0
- data/lib/webrat/core/locators/area_locator.rb +38 -0
- data/lib/webrat/core/locators/button_locator.rb +54 -0
- data/lib/webrat/core/locators/field_by_id_locator.rb +37 -0
- data/lib/webrat/core/locators/field_labeled_locator.rb +50 -0
- data/lib/webrat/core/locators/field_locator.rb +25 -0
- data/lib/webrat/core/locators/field_named_locator.rb +41 -0
- data/lib/webrat/core/locators/form_locator.rb +19 -0
- data/lib/webrat/core/locators/label_locator.rb +34 -0
- data/lib/webrat/core/locators/link_locator.rb +66 -0
- data/lib/webrat/core/locators/locator.rb +20 -0
- data/lib/webrat/core/locators/select_option_locator.rb +59 -0
- data/lib/webrat/core/logging.rb +21 -0
- data/lib/webrat/core/matchers.rb +4 -0
- data/lib/webrat/core/matchers/have_content.rb +55 -0
- data/lib/webrat/core/matchers/have_selector.rb +37 -0
- data/lib/webrat/core/matchers/have_tag.rb +57 -0
- data/lib/webrat/core/matchers/have_xpath.rb +83 -0
- data/lib/webrat/core/methods.rb +60 -0
- data/lib/webrat/core/mime.rb +29 -0
- data/lib/webrat/core/save_and_open_page.rb +50 -0
- data/lib/webrat/core/scope.rb +330 -0
- data/lib/webrat/core/session.rb +218 -0
- data/lib/webrat/core/xml.rb +115 -0
- data/lib/webrat/core/xml/hpricot.rb +19 -0
- data/lib/webrat/core/xml/nokogiri.rb +76 -0
- data/lib/webrat/core/xml/rexml.rb +24 -0
- data/lib/webrat/core_extensions/blank.rb +58 -0
- data/lib/webrat/core_extensions/deprecate.rb +8 -0
- data/lib/webrat/core_extensions/detect_mapped.rb +12 -0
- data/lib/webrat/core_extensions/hash_with_indifferent_access.rb +131 -0
- data/lib/webrat/core_extensions/meta_class.rb +6 -0
- data/lib/webrat/core_extensions/nil_to_param.rb +5 -0
- data/lib/webrat/mechanize.rb +43 -0
- data/lib/webrat/merb.rb +77 -0
- data/lib/webrat/rack.rb +26 -0
- data/lib/webrat/rails.rb +96 -0
- data/lib/webrat/rails/redirect_actions.rb +18 -0
- data/lib/webrat/rspec-rails.rb +13 -0
- data/lib/webrat/selenium.rb +107 -0
- data/lib/webrat/selenium/location_strategy_javascript/button.js +12 -0
- data/lib/webrat/selenium/location_strategy_javascript/label.js +16 -0
- data/lib/webrat/selenium/location_strategy_javascript/webrat.js +5 -0
- data/lib/webrat/selenium/location_strategy_javascript/webratlink.js +9 -0
- data/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +15 -0
- data/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +5 -0
- data/lib/webrat/selenium/selenium_extensions.js +6 -0
- data/lib/webrat/selenium/selenium_session.rb +230 -0
- data/lib/webrat/sinatra.rb +21 -0
- data/vendor/selenium-server.jar +0 -0
- metadata +136 -0
@@ -0,0 +1,218 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "ostruct"
|
3
|
+
|
4
|
+
require "webrat/core/mime"
|
5
|
+
require "webrat/core/save_and_open_page"
|
6
|
+
|
7
|
+
module Webrat
|
8
|
+
# A page load or form submission returned an unsuccessful response code (500-599)
|
9
|
+
class PageLoadError < WebratError
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.session_class
|
13
|
+
case Webrat.configuration.mode
|
14
|
+
when :rails
|
15
|
+
RailsSession
|
16
|
+
when :merb
|
17
|
+
MerbSession
|
18
|
+
when :selenium
|
19
|
+
SeleniumSession
|
20
|
+
when :rack
|
21
|
+
RackSession
|
22
|
+
when :sinatra
|
23
|
+
SinatraSession
|
24
|
+
when :mechanize
|
25
|
+
MechanizeSession
|
26
|
+
else
|
27
|
+
raise WebratError.new("Unknown Webrat mode: #{Webrat.configuration.mode.inspect}")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Session
|
32
|
+
extend Forwardable
|
33
|
+
include Logging
|
34
|
+
include SaveAndOpenPage
|
35
|
+
|
36
|
+
attr_reader :current_url
|
37
|
+
attr_reader :elements
|
38
|
+
|
39
|
+
def initialize(context = nil) #:nodoc:
|
40
|
+
@http_method = :get
|
41
|
+
@data = {}
|
42
|
+
@default_headers = {}
|
43
|
+
@custom_headers = {}
|
44
|
+
@context = context
|
45
|
+
|
46
|
+
reset
|
47
|
+
end
|
48
|
+
|
49
|
+
def current_dom #:nodoc:
|
50
|
+
current_scope.dom
|
51
|
+
end
|
52
|
+
|
53
|
+
# For backwards compatibility -- removing in 1.0
|
54
|
+
def current_page #:nodoc:
|
55
|
+
page = OpenStruct.new
|
56
|
+
page.url = @current_url
|
57
|
+
page.http_method = @http_method
|
58
|
+
page.data = @data
|
59
|
+
page
|
60
|
+
end
|
61
|
+
|
62
|
+
def doc_root #:nodoc:
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def header(key, value)
|
67
|
+
@custom_headers[key] = value
|
68
|
+
end
|
69
|
+
|
70
|
+
def http_accept(mime_type)
|
71
|
+
header('Accept', Webrat::MIME.mime_type(mime_type))
|
72
|
+
end
|
73
|
+
|
74
|
+
def basic_auth(user, pass)
|
75
|
+
encoded_login = ["#{user}:#{pass}"].pack("m*")
|
76
|
+
header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
|
77
|
+
end
|
78
|
+
|
79
|
+
def headers #:nodoc:
|
80
|
+
@default_headers.dup.merge(@custom_headers.dup)
|
81
|
+
end
|
82
|
+
|
83
|
+
def request_page(url, http_method, data) #:nodoc:
|
84
|
+
h = headers
|
85
|
+
h['HTTP_REFERER'] = @current_url if @current_url
|
86
|
+
|
87
|
+
debug_log "REQUESTING PAGE: #{http_method.to_s.upcase} #{url} with #{data.inspect} and HTTP headers #{h.inspect}"
|
88
|
+
if h.empty?
|
89
|
+
send "#{http_method}", url, data || {}
|
90
|
+
else
|
91
|
+
send "#{http_method}", url, data || {}, h
|
92
|
+
end
|
93
|
+
|
94
|
+
save_and_open_page if exception_caught? && Webrat.configuration.open_error_files?
|
95
|
+
raise PageLoadError.new("Page load was not successful (Code: #{response_code.inspect}):\n#{formatted_error}") unless success_code?
|
96
|
+
|
97
|
+
reset
|
98
|
+
|
99
|
+
@current_url = url
|
100
|
+
@http_method = http_method
|
101
|
+
@data = data
|
102
|
+
|
103
|
+
return response
|
104
|
+
end
|
105
|
+
|
106
|
+
def success_code? #:nodoc:
|
107
|
+
(200..499).include?(response_code)
|
108
|
+
end
|
109
|
+
|
110
|
+
def exception_caught? #:nodoc:
|
111
|
+
response_body =~ /Exception caught/
|
112
|
+
end
|
113
|
+
|
114
|
+
def current_scope #:nodoc:
|
115
|
+
scopes.last || page_scope
|
116
|
+
end
|
117
|
+
|
118
|
+
# Reloads the last page requested. Note that this will resubmit forms
|
119
|
+
# and their data.
|
120
|
+
def reloads
|
121
|
+
request_page(@current_url, @http_method, @data)
|
122
|
+
end
|
123
|
+
|
124
|
+
webrat_deprecate :reload, :reloads
|
125
|
+
|
126
|
+
|
127
|
+
# Works like click_link, but only looks for the link text within a given selector
|
128
|
+
#
|
129
|
+
# Example:
|
130
|
+
# click_link_within "#user_12", "Vote"
|
131
|
+
def click_link_within(selector, link_text)
|
132
|
+
within(selector) do
|
133
|
+
click_link(link_text)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
webrat_deprecate :clicks_link_within, :click_link_within
|
138
|
+
|
139
|
+
def within(selector)
|
140
|
+
scopes.push(Scope.from_scope(self, current_scope, selector))
|
141
|
+
ret = yield(current_scope)
|
142
|
+
scopes.pop
|
143
|
+
return ret
|
144
|
+
end
|
145
|
+
|
146
|
+
# Issues a GET request for a page, follows any redirects, and verifies the final page
|
147
|
+
# load was successful.
|
148
|
+
#
|
149
|
+
# Example:
|
150
|
+
# visit "/"
|
151
|
+
def visit(url = nil, http_method = :get, data = {})
|
152
|
+
request_page(url, http_method, data)
|
153
|
+
end
|
154
|
+
|
155
|
+
webrat_deprecate :visits, :visit
|
156
|
+
|
157
|
+
# Subclasses can override this to show error messages without html
|
158
|
+
def formatted_error #:nodoc:
|
159
|
+
response_body
|
160
|
+
end
|
161
|
+
|
162
|
+
def scopes #:nodoc:
|
163
|
+
@_scopes ||= []
|
164
|
+
end
|
165
|
+
|
166
|
+
def page_scope #:nodoc:
|
167
|
+
@_page_scope ||= Scope.from_page(self, response, response_body)
|
168
|
+
end
|
169
|
+
|
170
|
+
def dom
|
171
|
+
page_scope.dom
|
172
|
+
end
|
173
|
+
|
174
|
+
def xml_content_type?
|
175
|
+
false
|
176
|
+
end
|
177
|
+
|
178
|
+
def simulate
|
179
|
+
return if Webrat.configuration.mode == :selenium
|
180
|
+
yield
|
181
|
+
end
|
182
|
+
|
183
|
+
def automate
|
184
|
+
return unless Webrat.configuration.mode == :selenium
|
185
|
+
yield
|
186
|
+
end
|
187
|
+
|
188
|
+
def_delegators :current_scope, :fill_in, :fills_in
|
189
|
+
def_delegators :current_scope, :set_hidden_field
|
190
|
+
def_delegators :current_scope, :submit_form
|
191
|
+
def_delegators :current_scope, :check, :checks
|
192
|
+
def_delegators :current_scope, :uncheck, :unchecks
|
193
|
+
def_delegators :current_scope, :choose, :chooses
|
194
|
+
def_delegators :current_scope, :select, :selects
|
195
|
+
def_delegators :current_scope, :select_datetime, :selects_datetime
|
196
|
+
def_delegators :current_scope, :select_date, :selects_date
|
197
|
+
def_delegators :current_scope, :select_time, :selects_time
|
198
|
+
def_delegators :current_scope, :attach_file, :attaches_file
|
199
|
+
def_delegators :current_scope, :click_area, :clicks_area
|
200
|
+
def_delegators :current_scope, :click_link, :clicks_link
|
201
|
+
def_delegators :current_scope, :click_button, :clicks_button
|
202
|
+
def_delegators :current_scope, :should_see
|
203
|
+
def_delegators :current_scope, :should_not_see
|
204
|
+
def_delegators :current_scope, :field_labeled
|
205
|
+
def_delegators :current_scope, :field_by_xpath
|
206
|
+
def_delegators :current_scope, :field_with_id
|
207
|
+
def_delegators :current_scope, :select_option
|
208
|
+
|
209
|
+
private
|
210
|
+
|
211
|
+
def reset
|
212
|
+
@elements = {}
|
213
|
+
@_scopes = nil
|
214
|
+
@_page_scope = nil
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require "webrat/core/xml/nokogiri"
|
2
|
+
require "webrat/core/xml/hpricot"
|
3
|
+
require "webrat/core/xml/rexml"
|
4
|
+
|
5
|
+
module Webrat #:nodoc:
|
6
|
+
module XML #:nodoc:
|
7
|
+
|
8
|
+
def self.document(stringlike) #:nodoc:
|
9
|
+
if Webrat.configuration.parse_with_nokogiri?
|
10
|
+
Webrat.nokogiri_document(stringlike)
|
11
|
+
else
|
12
|
+
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.html_document(stringlike) #:nodoc:
|
17
|
+
if Webrat.configuration.parse_with_nokogiri?
|
18
|
+
Webrat.html_nokogiri_document(stringlike)
|
19
|
+
else
|
20
|
+
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.xml_document(stringlike) #:nodoc:
|
25
|
+
if Webrat.configuration.parse_with_nokogiri?
|
26
|
+
Webrat.xml_nokogiri_document(stringlike)
|
27
|
+
else
|
28
|
+
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.to_html(element)
|
33
|
+
if Webrat.configuration.parse_with_nokogiri?
|
34
|
+
element.to_html
|
35
|
+
else
|
36
|
+
element.to_s
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.inner_html(element)
|
41
|
+
if Webrat.configuration.parse_with_nokogiri?
|
42
|
+
element.inner_html
|
43
|
+
else
|
44
|
+
element.text
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.all_inner_text(element)
|
49
|
+
if Webrat.configuration.parse_with_nokogiri?
|
50
|
+
element.inner_text
|
51
|
+
else
|
52
|
+
Hpricot(element.to_s).children.first.inner_text
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.inner_text(element)
|
57
|
+
if Webrat.configuration.parse_with_nokogiri?
|
58
|
+
element.inner_text
|
59
|
+
else
|
60
|
+
if defined?(Hpricot::Doc) && element.is_a?(Hpricot::Doc)
|
61
|
+
element.inner_text
|
62
|
+
else
|
63
|
+
element.text
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.xpath_to(element)
|
69
|
+
if Webrat.configuration.parse_with_nokogiri?
|
70
|
+
element.path
|
71
|
+
else
|
72
|
+
element.xpath
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.attribute(element, attribute_name)
|
77
|
+
return element[attribute_name] if element.is_a?(Hash)
|
78
|
+
|
79
|
+
if Webrat.configuration.parse_with_nokogiri?
|
80
|
+
element[attribute_name]
|
81
|
+
else
|
82
|
+
element.attributes[attribute_name]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.xpath_at(*args)
|
87
|
+
xpath_search(*args).first
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.css_at(*args)
|
91
|
+
css_search(*args).first
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.xpath_search(element, *searches)
|
95
|
+
searches.flatten.map do |search|
|
96
|
+
if Webrat.configuration.parse_with_nokogiri?
|
97
|
+
element.xpath(search)
|
98
|
+
else
|
99
|
+
REXML::XPath.match(element, search)
|
100
|
+
end
|
101
|
+
end.flatten.compact
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.css_search(element, *searches) #:nodoc:
|
105
|
+
xpath_search(element, css_to_xpath(*searches))
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.css_to_xpath(*selectors)
|
109
|
+
selectors.map do |rule|
|
110
|
+
Nokogiri::CSS.xpath_for(rule, :prefix => ".//")
|
111
|
+
end.flatten.uniq
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Webrat
|
2
|
+
|
3
|
+
def self.hpricot_document(stringlike)
|
4
|
+
return stringlike.dom if stringlike.respond_to?(:dom)
|
5
|
+
|
6
|
+
if Hpricot::Doc === stringlike
|
7
|
+
stringlike
|
8
|
+
elsif Hpricot::Elements === stringlike
|
9
|
+
stringlike
|
10
|
+
elsif StringIO === stringlike
|
11
|
+
Hpricot(stringlike.string)
|
12
|
+
elsif stringlike.respond_to?(:body)
|
13
|
+
Hpricot(stringlike.body.to_s)
|
14
|
+
else
|
15
|
+
Hpricot(stringlike.to_s)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "webrat/core_extensions/meta_class"
|
2
|
+
|
3
|
+
module Webrat
|
4
|
+
|
5
|
+
def self.nokogiri_document(stringlike) #:nodoc:
|
6
|
+
return stringlike.dom if stringlike.respond_to?(:dom)
|
7
|
+
|
8
|
+
if Nokogiri::HTML::Document === stringlike
|
9
|
+
stringlike
|
10
|
+
elsif Nokogiri::XML::NodeSet === stringlike
|
11
|
+
stringlike
|
12
|
+
elsif StringIO === stringlike
|
13
|
+
Nokogiri.parse(stringlike.string)
|
14
|
+
elsif stringlike.respond_to?(:body)
|
15
|
+
Nokogiri.parse(stringlike.body.to_s)
|
16
|
+
else
|
17
|
+
Nokogiri.parse(stringlike.to_s)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.html_nokogiri_document(stringlike) #:nodoc:
|
22
|
+
return stringlike.dom if stringlike.respond_to?(:dom)
|
23
|
+
|
24
|
+
if Nokogiri::HTML::Document === stringlike
|
25
|
+
stringlike
|
26
|
+
elsif Nokogiri::XML::NodeSet === stringlike
|
27
|
+
stringlike
|
28
|
+
elsif StringIO === stringlike
|
29
|
+
Nokogiri::HTML(stringlike.string)
|
30
|
+
elsif stringlike.respond_to?(:body)
|
31
|
+
Nokogiri::HTML(stringlike.body.to_s)
|
32
|
+
else
|
33
|
+
Nokogiri::HTML(stringlike.to_s)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.xml_nokogiri_document(stringlike) #:nodoc:
|
38
|
+
return stringlike.dom if stringlike.respond_to?(:dom)
|
39
|
+
|
40
|
+
if Nokogiri::HTML::Document === stringlike
|
41
|
+
stringlike
|
42
|
+
elsif Nokogiri::XML::NodeSet === stringlike
|
43
|
+
stringlike
|
44
|
+
elsif StringIO === stringlike
|
45
|
+
Nokogiri::XML(stringlike.string)
|
46
|
+
elsif stringlike.respond_to?(:body)
|
47
|
+
Nokogiri::XML(stringlike.body.to_s)
|
48
|
+
else
|
49
|
+
Nokogiri::XML(stringlike.to_s)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.define_dom_method(object, dom) #:nodoc:
|
54
|
+
object.meta_class.send(:define_method, :dom) do
|
55
|
+
dom
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
module Nokogiri #:nodoc:
|
63
|
+
module CSS #:nodoc:
|
64
|
+
class XPathVisitor #:nodoc:
|
65
|
+
|
66
|
+
def visit_pseudo_class_text(node) #:nodoc:
|
67
|
+
"@type='text'"
|
68
|
+
end
|
69
|
+
|
70
|
+
def visit_pseudo_class_password(node) #:nodoc:
|
71
|
+
"@type='password'"
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Webrat
|
2
|
+
|
3
|
+
def self.rexml_document(stringlike)
|
4
|
+
stringlike = stringlike.body.to_s if stringlike.respond_to?(:body)
|
5
|
+
|
6
|
+
case stringlike
|
7
|
+
when REXML::Document
|
8
|
+
stringlike.root
|
9
|
+
when REXML::Node, Array
|
10
|
+
stringlike
|
11
|
+
else
|
12
|
+
begin
|
13
|
+
REXML::Document.new(stringlike.to_s).root
|
14
|
+
rescue REXML::ParseException => e
|
15
|
+
if e.message.include?("second root element")
|
16
|
+
REXML::Document.new("<fake-root-element>#{stringlike}</fake-root-element>").root
|
17
|
+
else
|
18
|
+
raise e
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|