webrat 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/History.txt +76 -14
- data/README.txt +40 -36
- data/Rakefile +80 -18
- data/TODO.txt +9 -3
- data/init.rb +1 -1
- data/lib/webrat.rb +30 -5
- data/lib/webrat/core.rb +12 -0
- data/lib/webrat/core/area.rb +44 -0
- data/lib/webrat/core/field.rb +332 -0
- data/lib/webrat/core/flunk.rb +7 -0
- data/lib/webrat/core/form.rb +130 -0
- data/lib/webrat/core/label.rb +18 -0
- data/lib/webrat/core/link.rb +101 -0
- data/lib/webrat/core/locators.rb +92 -0
- data/lib/webrat/core/logging.rb +25 -0
- data/lib/webrat/core/matchers.rb +4 -0
- data/lib/webrat/core/matchers/have_content.rb +94 -0
- data/lib/webrat/core/matchers/have_selector.rb +39 -0
- data/lib/webrat/core/matchers/have_tag.rb +58 -0
- data/lib/webrat/core/matchers/have_xpath.rb +85 -0
- data/lib/webrat/core/methods.rb +44 -0
- data/lib/webrat/core/mime.rb +29 -0
- data/lib/webrat/core/nokogiri.rb +42 -0
- data/lib/webrat/core/scope.rb +208 -0
- data/lib/webrat/core/select_option.rb +29 -0
- data/lib/webrat/core/session.rb +188 -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 +28 -0
- data/lib/webrat/merb.rb +75 -0
- data/lib/webrat/rack.rb +24 -0
- data/lib/webrat/rails.rb +102 -0
- data/lib/webrat/rails/redirect_actions.rb +18 -0
- data/lib/webrat/selenium.rb +3 -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 +137 -0
- data/lib/webrat/sinatra.rb +19 -0
- metadata +66 -52
- data/Manifest.txt +0 -20
- data/lib/webrat/rails_extensions.rb +0 -27
- data/lib/webrat/session.rb +0 -523
- data/test/checks_test.rb +0 -121
- data/test/chooses_test.rb +0 -74
- data/test/clicks_button_test.rb +0 -308
- data/test/clicks_link_test.rb +0 -193
- data/test/fills_in_test.rb +0 -139
- data/test/helper.rb +0 -21
- data/test/reloads_test.rb +0 -26
- data/test/selects_test.rb +0 -93
- data/test/visits_test.rb +0 -31
@@ -0,0 +1,44 @@
|
|
1
|
+
module Webrat
|
2
|
+
module Methods #:nodoc:
|
3
|
+
|
4
|
+
def self.delegate_to_session(*meths)
|
5
|
+
meths.each do |meth|
|
6
|
+
self.class_eval <<-RUBY
|
7
|
+
def #{meth}(*args, &blk)
|
8
|
+
@session ||= ::Webrat::MerbSession.new
|
9
|
+
@session.#{meth}(*args, &blk)
|
10
|
+
end
|
11
|
+
RUBY
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# all of these methods delegate to the @session, which should
|
16
|
+
# be created transparently.
|
17
|
+
#
|
18
|
+
# Note that when using Webrat, #request also uses @session, so
|
19
|
+
# that #request and webrat native functions behave interchangably
|
20
|
+
|
21
|
+
delegate_to_session \
|
22
|
+
:visits, :visit,
|
23
|
+
:within,
|
24
|
+
:header, :http_accept, :basic_auth,
|
25
|
+
:save_and_open_page,
|
26
|
+
:fill_in,
|
27
|
+
:check,
|
28
|
+
:uncheck,
|
29
|
+
:choose,
|
30
|
+
:select,
|
31
|
+
:attach_file,
|
32
|
+
:cookies,
|
33
|
+
:response,
|
34
|
+
:current_page,
|
35
|
+
:current_url,
|
36
|
+
:click_link,
|
37
|
+
:click_area,
|
38
|
+
:click_button,
|
39
|
+
:reload, :reloads,
|
40
|
+
:clicks_link_within,
|
41
|
+
:field_labeled
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Webrat
|
2
|
+
module MIME
|
3
|
+
|
4
|
+
def self.mime_type(string_or_symbol)
|
5
|
+
if string_or_symbol.is_a?(String)
|
6
|
+
string_or_symbol
|
7
|
+
else
|
8
|
+
case string_or_symbol
|
9
|
+
when :text then "text/plain"
|
10
|
+
when :html then "text/html"
|
11
|
+
when :js then "text/javascript"
|
12
|
+
when :css then "text/css"
|
13
|
+
when :ics then "text/calendar"
|
14
|
+
when :csv then "text/csv"
|
15
|
+
when :xml then "application/xml"
|
16
|
+
when :rss then "application/rss+xml"
|
17
|
+
when :atom then "application/atom+xml"
|
18
|
+
when :yaml then "application/x-yaml"
|
19
|
+
when :multipart_form then "multipart/form-data"
|
20
|
+
when :url_encoded_form then "application/x-www-form-urlencoded"
|
21
|
+
when :json then "application/json"
|
22
|
+
else
|
23
|
+
raise ArgumentError.new("Invalid Mime type: #{string_or_symbol.inspect}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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 stringlike === Nokogiri::HTML::Document || stringlike === Nokogiri::XML::NodeSet
|
9
|
+
stringlike
|
10
|
+
elsif stringlike === StringIO
|
11
|
+
Nokogiri::HTML(stringlike.string)
|
12
|
+
elsif stringlike.respond_to?(:body)
|
13
|
+
Nokogiri::HTML(stringlike.body.to_s)
|
14
|
+
else
|
15
|
+
Nokogiri::HTML(stringlike.to_s)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.define_dom_method(object, dom) #:nodoc:
|
20
|
+
object.meta_class.send(:define_method, :dom) do
|
21
|
+
dom
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
module Nokogiri
|
29
|
+
module CSS
|
30
|
+
class XPathVisitor
|
31
|
+
|
32
|
+
def visit_pseudo_class_text(node) #:nodoc:
|
33
|
+
"@type='text'"
|
34
|
+
end
|
35
|
+
|
36
|
+
def visit_pseudo_class_password(node) #:nodoc:
|
37
|
+
"@type='password'"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
require "nokogiri"
|
2
|
+
require "webrat/core/form"
|
3
|
+
require "webrat/core/locators"
|
4
|
+
|
5
|
+
module Webrat
|
6
|
+
class Scope
|
7
|
+
include Logging
|
8
|
+
include Flunk
|
9
|
+
include Locators
|
10
|
+
|
11
|
+
def self.from_page(session, response, response_body) #:nodoc:
|
12
|
+
new(session) do
|
13
|
+
@response = response
|
14
|
+
@response_body = response_body
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.from_scope(session, scope, selector) #:nodoc:
|
19
|
+
new(session) do
|
20
|
+
@scope = scope
|
21
|
+
@selector = selector
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(session, &block) #:nodoc:
|
26
|
+
@session = session
|
27
|
+
instance_eval(&block) if block_given?
|
28
|
+
end
|
29
|
+
|
30
|
+
# Verifies an input field or textarea exists on the current page, and stores a value for
|
31
|
+
# it which will be sent when the form is submitted.
|
32
|
+
#
|
33
|
+
# Examples:
|
34
|
+
# fill_in "Email", :with => "user@example.com"
|
35
|
+
# fill_in "user[email]", :with => "user@example.com"
|
36
|
+
#
|
37
|
+
# The field value is required, and must be specified in <tt>options[:with]</tt>.
|
38
|
+
# <tt>field</tt> can be either the value of a name attribute (i.e. <tt>user[email]</tt>)
|
39
|
+
# or the text inside a <tt><label></tt> element that points at the <tt><input></tt> field.
|
40
|
+
def fill_in(field_locator, options = {})
|
41
|
+
field = locate_field(field_locator, TextField, TextareaField, PasswordField)
|
42
|
+
field.raise_error_if_disabled
|
43
|
+
field.set(options[:with])
|
44
|
+
end
|
45
|
+
|
46
|
+
alias_method :fills_in, :fill_in
|
47
|
+
|
48
|
+
# Verifies that an input checkbox exists on the current page and marks it
|
49
|
+
# as checked, so that the value will be submitted with the form.
|
50
|
+
#
|
51
|
+
# Example:
|
52
|
+
# check 'Remember Me'
|
53
|
+
def check(field_locator)
|
54
|
+
locate_field(field_locator, CheckboxField).check
|
55
|
+
end
|
56
|
+
|
57
|
+
alias_method :checks, :check
|
58
|
+
|
59
|
+
# Verifies that an input checkbox exists on the current page and marks it
|
60
|
+
# as unchecked, so that the value will not be submitted with the form.
|
61
|
+
#
|
62
|
+
# Example:
|
63
|
+
# uncheck 'Remember Me'
|
64
|
+
def uncheck(field_locator)
|
65
|
+
locate_field(field_locator, CheckboxField).uncheck
|
66
|
+
end
|
67
|
+
|
68
|
+
alias_method :unchecks, :uncheck
|
69
|
+
|
70
|
+
# Verifies that an input radio button exists on the current page and marks it
|
71
|
+
# as checked, so that the value will be submitted with the form.
|
72
|
+
#
|
73
|
+
# Example:
|
74
|
+
# choose 'First Option'
|
75
|
+
def choose(field_locator)
|
76
|
+
locate_field(field_locator, RadioField).choose
|
77
|
+
end
|
78
|
+
|
79
|
+
alias_method :chooses, :choose
|
80
|
+
|
81
|
+
# Verifies that a an option element exists on the current page with the specified
|
82
|
+
# text. You can optionally restrict the search to a specific select list by
|
83
|
+
# assigning <tt>options[:from]</tt> the value of the select list's name or
|
84
|
+
# a label. Stores the option's value to be sent when the form is submitted.
|
85
|
+
#
|
86
|
+
# Examples:
|
87
|
+
# selects "January"
|
88
|
+
# selects "February", :from => "event_month"
|
89
|
+
# selects "February", :from => "Event Month"
|
90
|
+
def selects(option_text, options = {})
|
91
|
+
find_select_option(option_text, options[:from]).choose
|
92
|
+
end
|
93
|
+
|
94
|
+
alias_method :select, :selects
|
95
|
+
|
96
|
+
# Verifies that an input file field exists on the current page and sets
|
97
|
+
# its value to the given +file+, so that the file will be uploaded
|
98
|
+
# along with the form. An optional <tt>content_type</tt> may be given.
|
99
|
+
#
|
100
|
+
# Example:
|
101
|
+
# attaches_file "Resume", "/path/to/the/resume.txt"
|
102
|
+
# attaches_file "Photo", "/path/to/the/image.png", "image/png"
|
103
|
+
def attach_file(field_locator, path, content_type = nil)
|
104
|
+
locate_field(field_locator, FileField).set(path, content_type)
|
105
|
+
end
|
106
|
+
|
107
|
+
alias_method :attaches_file, :attach_file
|
108
|
+
|
109
|
+
def click_area(area_name)
|
110
|
+
find_area(area_name).click
|
111
|
+
end
|
112
|
+
|
113
|
+
alias_method :clicks_area, :click_area
|
114
|
+
|
115
|
+
# Issues a request for the URL pointed to by a link on the current page,
|
116
|
+
# follows any redirects, and verifies the final page load was successful.
|
117
|
+
#
|
118
|
+
# click_link has very basic support for detecting Rails-generated
|
119
|
+
# JavaScript onclick handlers for PUT, POST and DELETE links, as well as
|
120
|
+
# CSRF authenticity tokens if they are present.
|
121
|
+
#
|
122
|
+
# Javascript imitation can be disabled by passing the option :javascript => false
|
123
|
+
#
|
124
|
+
# Passing a :method in the options hash overrides the HTTP method used
|
125
|
+
# for making the link request
|
126
|
+
#
|
127
|
+
# Example:
|
128
|
+
# click_link "Sign up"
|
129
|
+
#
|
130
|
+
# click_link "Sign up", :javascript => false
|
131
|
+
#
|
132
|
+
# click_link "Sign up", :method => :put
|
133
|
+
def click_link(link_text, options = {})
|
134
|
+
find_link(link_text).click(options)
|
135
|
+
end
|
136
|
+
|
137
|
+
alias_method :clicks_link, :click_link
|
138
|
+
|
139
|
+
# Verifies that a submit button exists for the form, then submits the form, follows
|
140
|
+
# any redirects, and verifies the final page was successful.
|
141
|
+
#
|
142
|
+
# Example:
|
143
|
+
# click_button "Login"
|
144
|
+
# click_button
|
145
|
+
#
|
146
|
+
# The URL and HTTP method for the form submission are automatically read from the
|
147
|
+
# <tt>action</tt> and <tt>method</tt> attributes of the <tt><form></tt> element.
|
148
|
+
def click_button(value = nil)
|
149
|
+
find_button(value).click
|
150
|
+
end
|
151
|
+
|
152
|
+
alias_method :clicks_button, :click_button
|
153
|
+
|
154
|
+
def dom # :nodoc:
|
155
|
+
return @dom if @dom
|
156
|
+
|
157
|
+
if @selector
|
158
|
+
@dom = scoped_dom
|
159
|
+
else
|
160
|
+
@dom = page_dom
|
161
|
+
end
|
162
|
+
|
163
|
+
return @dom
|
164
|
+
end
|
165
|
+
|
166
|
+
protected
|
167
|
+
|
168
|
+
def page_dom #:nodoc:
|
169
|
+
return @response.dom if @response.respond_to?(:dom)
|
170
|
+
dom = Webrat.nokogiri_document(@response_body)
|
171
|
+
Webrat.define_dom_method(@response, dom)
|
172
|
+
return dom
|
173
|
+
end
|
174
|
+
|
175
|
+
def scoped_dom #:nodoc:
|
176
|
+
Webrat.nokogiri_document(@scope.dom.search(@selector).first.to_html)
|
177
|
+
end
|
178
|
+
|
179
|
+
def locate_field(field_locator, *field_types) #:nodoc:
|
180
|
+
if field_locator.is_a?(Field)
|
181
|
+
field_locator
|
182
|
+
else
|
183
|
+
field(field_locator, *field_types)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def areas #:nodoc:
|
188
|
+
dom.search("area").map do |element|
|
189
|
+
Area.new(@session, element)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def links #:nodoc:
|
194
|
+
dom.search("a[@href]").map do |link_element|
|
195
|
+
Link.new(@session, link_element)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def forms #:nodoc:
|
200
|
+
return @forms if @forms
|
201
|
+
|
202
|
+
@forms = dom.search("form").map do |form_element|
|
203
|
+
Form.new(@session, form_element)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Webrat
|
2
|
+
class SelectOption #:nodoc:
|
3
|
+
|
4
|
+
def initialize(select, element)
|
5
|
+
@select = select
|
6
|
+
@element = element
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches_text?(text)
|
10
|
+
if text.is_a?(Regexp)
|
11
|
+
@element.inner_html =~ text
|
12
|
+
else
|
13
|
+
@element.inner_html == text.to_s
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def choose
|
18
|
+
@select.raise_error_if_disabled
|
19
|
+
@select.set(value)
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def value
|
25
|
+
@element["value"] || @element.inner_html
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "ostruct"
|
3
|
+
|
4
|
+
require "webrat/core/mime"
|
5
|
+
|
6
|
+
module Webrat
|
7
|
+
class Session
|
8
|
+
extend Forwardable
|
9
|
+
include Logging
|
10
|
+
include Flunk
|
11
|
+
|
12
|
+
attr_reader :current_url
|
13
|
+
|
14
|
+
def initialize #:nodoc:
|
15
|
+
@http_method = :get
|
16
|
+
@data = {}
|
17
|
+
@default_headers = {}
|
18
|
+
@custom_headers = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Saves the page out to RAILS_ROOT/tmp/ and opens it in the default
|
22
|
+
# web browser if on OS X. Useful for debugging.
|
23
|
+
#
|
24
|
+
# Example:
|
25
|
+
# save_and_open_page
|
26
|
+
def save_and_open_page
|
27
|
+
return unless File.exist?(saved_page_dir)
|
28
|
+
|
29
|
+
filename = "#{saved_page_dir}/webrat-#{Time.now.to_i}.html"
|
30
|
+
|
31
|
+
File.open(filename, "w") do |f|
|
32
|
+
f.write rewrite_css_and_image_references(response_body)
|
33
|
+
end
|
34
|
+
|
35
|
+
open_in_browser(filename)
|
36
|
+
end
|
37
|
+
|
38
|
+
def current_dom #:nodoc:
|
39
|
+
current_scope.dom
|
40
|
+
end
|
41
|
+
|
42
|
+
# For backwards compatibility -- removing in 1.0
|
43
|
+
def current_page #:nodoc:
|
44
|
+
page = OpenStruct.new
|
45
|
+
page.url = @current_url
|
46
|
+
page.http_method = @http_method
|
47
|
+
page.data = @data
|
48
|
+
page
|
49
|
+
end
|
50
|
+
|
51
|
+
def doc_root #:nodoc:
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def saved_page_dir #:nodoc:
|
56
|
+
File.expand_path(".")
|
57
|
+
end
|
58
|
+
|
59
|
+
def header(key, value)
|
60
|
+
@custom_headers[key] = value
|
61
|
+
end
|
62
|
+
|
63
|
+
def http_accept(mime_type)
|
64
|
+
header('Accept', Webrat::MIME.mime_type(mime_type))
|
65
|
+
end
|
66
|
+
|
67
|
+
def basic_auth(user, pass)
|
68
|
+
encoded_login = ["#{user}:#{pass}"].pack("m*")
|
69
|
+
header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
|
70
|
+
end
|
71
|
+
|
72
|
+
def headers #:nodoc:
|
73
|
+
@default_headers.dup.merge(@custom_headers.dup)
|
74
|
+
end
|
75
|
+
|
76
|
+
def request_page(url, http_method, data) #:nodoc:
|
77
|
+
h = headers
|
78
|
+
h['HTTP_REFERER'] = @current_url if @current_url
|
79
|
+
|
80
|
+
debug_log "REQUESTING PAGE: #{http_method.to_s.upcase} #{url} with #{data.inspect} and HTTP headers #{h.inspect}"
|
81
|
+
if h.empty?
|
82
|
+
send "#{http_method}", url, data || {}
|
83
|
+
else
|
84
|
+
send "#{http_method}", url, data || {}, h
|
85
|
+
end
|
86
|
+
|
87
|
+
save_and_open_page if exception_caught?
|
88
|
+
flunk("Page load was not successful (Code: #{response_code.inspect}):\n#{formatted_error}") unless success_code?
|
89
|
+
|
90
|
+
@_scopes = nil
|
91
|
+
@_page_scope = nil
|
92
|
+
@current_url = url
|
93
|
+
@http_method = http_method
|
94
|
+
@data = data
|
95
|
+
|
96
|
+
return response
|
97
|
+
end
|
98
|
+
|
99
|
+
def success_code? #:nodoc:
|
100
|
+
(200..499).include?(response_code)
|
101
|
+
end
|
102
|
+
|
103
|
+
def exception_caught? #:nodoc:
|
104
|
+
response_body =~ /Exception caught/
|
105
|
+
end
|
106
|
+
|
107
|
+
def current_scope #:nodoc:
|
108
|
+
scopes.last || page_scope
|
109
|
+
end
|
110
|
+
|
111
|
+
# Reloads the last page requested. Note that this will resubmit forms
|
112
|
+
# and their data.
|
113
|
+
#
|
114
|
+
# Example:
|
115
|
+
# reloads
|
116
|
+
def reloads
|
117
|
+
request_page(@current_url, @http_method, @data)
|
118
|
+
end
|
119
|
+
|
120
|
+
alias_method :reload, :reloads
|
121
|
+
|
122
|
+
|
123
|
+
# Works like click_link, but only looks for the link text within a given selector
|
124
|
+
#
|
125
|
+
# Example:
|
126
|
+
# click_link_within "#user_12", "Vote"
|
127
|
+
def click_link_within(selector, link_text)
|
128
|
+
within(selector) do
|
129
|
+
click_link(link_text)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
alias_method :clicks_link_within, :click_link_within
|
134
|
+
|
135
|
+
def within(selector)
|
136
|
+
scopes.push(Scope.from_scope(self, current_scope, selector))
|
137
|
+
ret = yield(current_scope)
|
138
|
+
scopes.pop
|
139
|
+
return ret
|
140
|
+
end
|
141
|
+
|
142
|
+
# Issues a GET request for a page, follows any redirects, and verifies the final page
|
143
|
+
# load was successful.
|
144
|
+
#
|
145
|
+
# Example:
|
146
|
+
# visit "/"
|
147
|
+
def visit(url = nil, http_method = :get, data = {})
|
148
|
+
request_page(url, http_method, data)
|
149
|
+
end
|
150
|
+
|
151
|
+
alias_method :visits, :visit
|
152
|
+
|
153
|
+
def open_in_browser(path) #:nodoc
|
154
|
+
`open #{path}`
|
155
|
+
end
|
156
|
+
|
157
|
+
def rewrite_css_and_image_references(response_html) #:nodoc
|
158
|
+
return response_html unless doc_root
|
159
|
+
response_html.gsub(/"\/(stylesheets|images)/, doc_root + '/\1')
|
160
|
+
end
|
161
|
+
|
162
|
+
# Subclasses can override this to show error messages without html
|
163
|
+
def formatted_error #:nodoc:
|
164
|
+
response_body
|
165
|
+
end
|
166
|
+
|
167
|
+
def scopes #:nodoc:
|
168
|
+
@_scopes ||= []
|
169
|
+
end
|
170
|
+
|
171
|
+
def page_scope #:nodoc:
|
172
|
+
@_page_scope ||= Scope.from_page(self, response, response_body)
|
173
|
+
end
|
174
|
+
|
175
|
+
def_delegators :current_scope, :fill_in, :fills_in
|
176
|
+
def_delegators :current_scope, :check, :checks
|
177
|
+
def_delegators :current_scope, :uncheck, :unchecks
|
178
|
+
def_delegators :current_scope, :choose, :chooses
|
179
|
+
def_delegators :current_scope, :select, :selects
|
180
|
+
def_delegators :current_scope, :attach_file, :attaches_file
|
181
|
+
def_delegators :current_scope, :click_area, :clicks_area
|
182
|
+
def_delegators :current_scope, :click_link, :clicks_link
|
183
|
+
def_delegators :current_scope, :click_button, :clicks_button
|
184
|
+
def_delegators :current_scope, :should_see
|
185
|
+
def_delegators :current_scope, :should_not_see
|
186
|
+
def_delegators :current_scope, :field_labeled
|
187
|
+
end
|
188
|
+
end
|