benschwarz-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.
Files changed (65) hide show
  1. data/History.txt +184 -0
  2. data/MIT-LICENSE.txt +19 -0
  3. data/README.rdoc +81 -0
  4. data/Rakefile +104 -0
  5. data/install.rb +1 -0
  6. data/lib/webrat.rb +34 -0
  7. data/lib/webrat/core.rb +13 -0
  8. data/lib/webrat/core/configuration.rb +44 -0
  9. data/lib/webrat/core/elements/area.rb +31 -0
  10. data/lib/webrat/core/elements/element.rb +29 -0
  11. data/lib/webrat/core/elements/field.rb +386 -0
  12. data/lib/webrat/core/elements/form.rb +103 -0
  13. data/lib/webrat/core/elements/label.rb +31 -0
  14. data/lib/webrat/core/elements/link.rb +94 -0
  15. data/lib/webrat/core/elements/select_option.rb +35 -0
  16. data/lib/webrat/core/locators.rb +20 -0
  17. data/lib/webrat/core/locators/area_locator.rb +38 -0
  18. data/lib/webrat/core/locators/button_locator.rb +54 -0
  19. data/lib/webrat/core/locators/field_by_id_locator.rb +37 -0
  20. data/lib/webrat/core/locators/field_labeled_locator.rb +50 -0
  21. data/lib/webrat/core/locators/field_locator.rb +25 -0
  22. data/lib/webrat/core/locators/field_named_locator.rb +41 -0
  23. data/lib/webrat/core/locators/form_locator.rb +19 -0
  24. data/lib/webrat/core/locators/label_locator.rb +34 -0
  25. data/lib/webrat/core/locators/link_locator.rb +66 -0
  26. data/lib/webrat/core/locators/locator.rb +20 -0
  27. data/lib/webrat/core/locators/select_option_locator.rb +59 -0
  28. data/lib/webrat/core/logging.rb +21 -0
  29. data/lib/webrat/core/matchers.rb +4 -0
  30. data/lib/webrat/core/matchers/have_content.rb +55 -0
  31. data/lib/webrat/core/matchers/have_selector.rb +37 -0
  32. data/lib/webrat/core/matchers/have_tag.rb +57 -0
  33. data/lib/webrat/core/matchers/have_xpath.rb +83 -0
  34. data/lib/webrat/core/methods.rb +54 -0
  35. data/lib/webrat/core/mime.rb +29 -0
  36. data/lib/webrat/core/scope.rb +318 -0
  37. data/lib/webrat/core/session.rb +241 -0
  38. data/lib/webrat/core/xml.rb +99 -0
  39. data/lib/webrat/core/xml/hpricot.rb +19 -0
  40. data/lib/webrat/core/xml/nokogiri.rb +44 -0
  41. data/lib/webrat/core/xml/rexml.rb +24 -0
  42. data/lib/webrat/core_extensions/blank.rb +58 -0
  43. data/lib/webrat/core_extensions/deprecate.rb +8 -0
  44. data/lib/webrat/core_extensions/detect_mapped.rb +12 -0
  45. data/lib/webrat/core_extensions/hash_with_indifferent_access.rb +131 -0
  46. data/lib/webrat/core_extensions/meta_class.rb +6 -0
  47. data/lib/webrat/core_extensions/nil_to_param.rb +5 -0
  48. data/lib/webrat/mechanize.rb +43 -0
  49. data/lib/webrat/merb.rb +77 -0
  50. data/lib/webrat/rack.rb +26 -0
  51. data/lib/webrat/rails.rb +88 -0
  52. data/lib/webrat/rails/redirect_actions.rb +18 -0
  53. data/lib/webrat/rspec-rails.rb +13 -0
  54. data/lib/webrat/selenium.rb +58 -0
  55. data/lib/webrat/selenium/location_strategy_javascript/button.js +12 -0
  56. data/lib/webrat/selenium/location_strategy_javascript/label.js +16 -0
  57. data/lib/webrat/selenium/location_strategy_javascript/webrat.js +5 -0
  58. data/lib/webrat/selenium/location_strategy_javascript/webratlink.js +9 -0
  59. data/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +15 -0
  60. data/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +5 -0
  61. data/lib/webrat/selenium/selenium_extensions.js +6 -0
  62. data/lib/webrat/selenium/selenium_session.rb +186 -0
  63. data/lib/webrat/sinatra.rb +21 -0
  64. data/vendor/selenium-server.jar +0 -0
  65. metadata +144 -0
@@ -0,0 +1,54 @@
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
+ webrat_session.#{meth}(*args, &blk)
9
+ end
10
+
11
+ def webrat_session
12
+ @_webrat_session ||= ::Webrat.session_class.new(self)
13
+ end
14
+ RUBY
15
+ end
16
+ end
17
+
18
+ # all of these methods delegate to the @session, which should
19
+ # be created transparently.
20
+ #
21
+ # Note that when using Webrat, #request also uses @session, so
22
+ # that #request and webrat native functions behave interchangably
23
+
24
+ delegate_to_session \
25
+ :visits, :visit,
26
+ :within,
27
+ :header, :http_accept, :basic_auth,
28
+ :save_and_open_page,
29
+ :fills_in, :fill_in,
30
+ :checks, :check,
31
+ :unchecks, :uncheck,
32
+ :chooses, :choose,
33
+ :selects, :select,
34
+ :attaches_file, :attach_file,
35
+ :current_page,
36
+ :current_url,
37
+ :clicks_link, :click_link,
38
+ :clicks_area, :click_area,
39
+ :clicks_button, :click_button,
40
+ :reload, :reloads,
41
+ :clicks_link_within, :click_link_within,
42
+ :field_labeled,
43
+ :select_option,
44
+ :set_hidden_field, :submit_form,
45
+ :request_page, :current_dom,
46
+ :selects_date, :selects_time, :selects_datetime,
47
+ :select_date, :select_time, :select_datetime,
48
+ :wait_for_page_to_load,
49
+ :field_by_xpath,
50
+ :field_with_id
51
+
52
+
53
+ end
54
+ end
@@ -0,0 +1,29 @@
1
+ module Webrat #:nodoc:
2
+ module MIME #:nodoc:
3
+
4
+ def self.mime_type(string_or_symbol) #:nodoc:
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,318 @@
1
+ require "webrat/core/elements/form"
2
+ require "webrat/core/locators"
3
+ require "webrat/core_extensions/deprecate"
4
+
5
+ module Webrat
6
+ # An HTML element (link, button, field, etc.) that Webrat expected was not found on the page
7
+ class NotFoundError < WebratError
8
+ end
9
+
10
+ class Scope
11
+ include Logging
12
+ include Locators
13
+
14
+ def self.from_page(session, response, response_body) #:nodoc:
15
+ new(session) do
16
+ @response = response
17
+ @response_body = response_body
18
+ end
19
+ end
20
+
21
+ def self.from_scope(session, scope, selector) #:nodoc:
22
+ new(session) do
23
+ @scope = scope
24
+ @selector = selector
25
+ end
26
+ end
27
+
28
+ attr_reader :session
29
+
30
+ def initialize(session, &block) #:nodoc:
31
+ @session = session
32
+ instance_eval(&block) if block_given?
33
+ end
34
+
35
+ # Verifies an input field or textarea exists on the current page, and stores a value for
36
+ # it which will be sent when the form is submitted.
37
+ #
38
+ # Examples:
39
+ # fill_in "Email", :with => "user@example.com"
40
+ # fill_in "user[email]", :with => "user@example.com"
41
+ #
42
+ # The field value is required, and must be specified in <tt>options[:with]</tt>.
43
+ # <tt>field</tt> can be either the value of a name attribute (i.e. <tt>user[email]</tt>)
44
+ # or the text inside a <tt><label></tt> element that points at the <tt><input></tt> field.
45
+ def fill_in(field_locator, options = {})
46
+ field = locate_field(field_locator, TextField, TextareaField, PasswordField)
47
+ field.raise_error_if_disabled
48
+ field.set(options[:with])
49
+ end
50
+
51
+ webrat_deprecate :fills_in, :fill_in
52
+
53
+ def set_hidden_field(field_locator, options = {})
54
+ field = locate_field(field_locator, HiddenField)
55
+ field.set(options[:to])
56
+ end
57
+
58
+ # Verifies that an input checkbox exists on the current page and marks it
59
+ # as checked, so that the value will be submitted with the form.
60
+ #
61
+ # Example:
62
+ # check 'Remember Me'
63
+ def check(field_locator)
64
+ locate_field(field_locator, CheckboxField).check
65
+ end
66
+
67
+ webrat_deprecate :checks, :check
68
+
69
+ # Verifies that an input checkbox exists on the current page and marks it
70
+ # as unchecked, so that the value will not be submitted with the form.
71
+ #
72
+ # Example:
73
+ # uncheck 'Remember Me'
74
+ def uncheck(field_locator)
75
+ locate_field(field_locator, CheckboxField).uncheck
76
+ end
77
+
78
+ webrat_deprecate :unchecks, :uncheck
79
+
80
+ # Verifies that an input radio button exists on the current page and marks it
81
+ # as checked, so that the value will be submitted with the form.
82
+ #
83
+ # Example:
84
+ # choose 'First Option'
85
+ def choose(field_locator)
86
+ locate_field(field_locator, RadioField).choose
87
+ end
88
+
89
+ webrat_deprecate :chooses, :choose
90
+
91
+ # Verifies that a an option element exists on the current page with the specified
92
+ # text. You can optionally restrict the search to a specific select list by
93
+ # assigning <tt>options[:from]</tt> the value of the select list's name or
94
+ # a label. Stores the option's value to be sent when the form is submitted.
95
+ #
96
+ # Examples:
97
+ # select "January"
98
+ # select "February", :from => "event_month"
99
+ # select "February", :from => "Event Month"
100
+ def select(option_text, options = {})
101
+ select_option(option_text, options[:from]).choose
102
+ end
103
+
104
+ webrat_deprecate :selects, :select
105
+
106
+ DATE_TIME_SUFFIXES = {
107
+ :year => '1i',
108
+ :month => '2i',
109
+ :day => '3i',
110
+ :hour => '4i',
111
+ :minute => '5i'
112
+ }
113
+
114
+ # Verifies that date elements (year, month, day) exist on the current page
115
+ # with the specified values. You can optionally restrict the search to a specific
116
+ # date's elements by assigning <tt>options[:from]</tt> the value of the date's
117
+ # label. Selects all the date elements with date provided. The date provided may
118
+ # be a string or a Date/Time object.
119
+ #
120
+ # Rail's convention is used for detecting the date elements. All elements
121
+ # are assumed to have a shared prefix. You may also specify the prefix
122
+ # by assigning <tt>options[:id_prefix]</tt>.
123
+ #
124
+ # Examples:
125
+ # select_date "January 23, 2004"
126
+ # select_date "April 26, 1982", :from => "Birthday"
127
+ # select_date Date.parse("December 25, 2000"), :from => "Event"
128
+ # select_date "April 26, 1982", :id_prefix => 'birthday'
129
+ def select_date(date_to_select, options ={})
130
+ date = date_to_select.is_a?(Date) || date_to_select.is_a?(Time) ?
131
+ date_to_select : Date.parse(date_to_select)
132
+
133
+ id_prefix = locate_id_prefix(options) do
134
+ year_field = FieldByIdLocator.new(@session, dom, /(.*?)_#{DATE_TIME_SUFFIXES[:year]}$/).locate
135
+ raise NotFoundError.new("No date fields were found") unless year_field && year_field.id =~ /(.*?)_1i/
136
+ $1
137
+ end
138
+
139
+ select date.year, :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:year]}"
140
+ select date.strftime('%B'), :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:month]}"
141
+ select date.day, :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:day]}"
142
+ end
143
+
144
+ webrat_deprecate :selects_date, :select_date
145
+
146
+ # Verifies that time elements (hour, minute) exist on the current page
147
+ # with the specified values. You can optionally restrict the search to a specific
148
+ # time's elements by assigning <tt>options[:from]</tt> the value of the time's
149
+ # label. Selects all the time elements with date provided. The time provided may
150
+ # be a string or a Time object.
151
+ #
152
+ # Rail's convention is used for detecting the time elements. All elements are
153
+ # assumed to have a shared prefix. You may specify the prefix by assigning
154
+ # <tt>options[:id_prefix]</tt>.
155
+ #
156
+ # Note: Just like Rails' time_select helper this assumes the form is using
157
+ # 24 hour select boxes, and not 12 hours with AM/PM.
158
+ #
159
+ # Examples:
160
+ # select_time "9:30"
161
+ # select_date "3:30PM", :from => "Party Time"
162
+ # select_date Time.parse("10:00PM"), :from => "Event"
163
+ # select_date "10:30AM", :id_prefix => 'meeting'
164
+ def select_time(time_to_select, options ={})
165
+ time = time_to_select.is_a?(Time) ? time_to_select : Time.parse(time_to_select)
166
+
167
+ id_prefix = locate_id_prefix(options) do
168
+ hour_field = FieldByIdLocator.new(@session, dom, /(.*?)_#{DATE_TIME_SUFFIXES[:hour]}$/).locate
169
+ raise NotFoundError.new("No time fields were found") unless hour_field && hour_field.id =~ /(.*?)_4i/
170
+ $1
171
+ end
172
+
173
+ select time.hour.to_s.rjust(2,'0'), :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:hour]}"
174
+ select time.min.to_s.rjust(2,'0'), :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:minute]}"
175
+ end
176
+
177
+ webrat_deprecate :selects_time, :select_time
178
+
179
+ # Verifies and selects all the date and time elements on the current page.
180
+ # See #select_time and #select_date for more details and available options.
181
+ #
182
+ # Examples:
183
+ # select_datetime "January 23, 2004 10:30AM"
184
+ # select_datetime "April 26, 1982 7:00PM", :from => "Birthday"
185
+ # select_datetime Time.parse("December 25, 2000 15:30"), :from => "Event"
186
+ # select_datetime "April 26, 1982 5:50PM", :id_prefix => 'birthday'
187
+ def select_datetime(time_to_select, options ={})
188
+ time = time_to_select.is_a?(Time) ? time_to_select : Time.parse(time_to_select)
189
+
190
+ options[:id_prefix] ||= (options[:from] ? FieldByIdLocator.new(@session, dom, options[:from]).locate : nil)
191
+
192
+ select_date time, options
193
+ select_time time, options
194
+ end
195
+
196
+ webrat_deprecate :selects_datetime, :select_datetime
197
+
198
+ # Verifies that an input file field exists on the current page and sets
199
+ # its value to the given +file+, so that the file will be uploaded
200
+ # along with the form. An optional <tt>content_type</tt> may be given.
201
+ #
202
+ # Example:
203
+ # attaches_file "Resume", "/path/to/the/resume.txt"
204
+ # attaches_file "Photo", "/path/to/the/image.png", "image/png"
205
+ def attach_file(field_locator, path, content_type = nil)
206
+ locate_field(field_locator, FileField).set(path, content_type)
207
+ end
208
+
209
+ webrat_deprecate :attaches_file, :attach_file
210
+
211
+ def click_area(area_name)
212
+ find_area(area_name).click
213
+ end
214
+
215
+ webrat_deprecate :clicks_area, :click_area
216
+
217
+ # Issues a request for the URL pointed to by a link on the current page,
218
+ # follows any redirects, and verifies the final page load was successful.
219
+ #
220
+ # click_link has very basic support for detecting Rails-generated
221
+ # JavaScript onclick handlers for PUT, POST and DELETE links, as well as
222
+ # CSRF authenticity tokens if they are present.
223
+ #
224
+ # Javascript imitation can be disabled by passing the option :javascript => false
225
+ #
226
+ # Passing a :method in the options hash overrides the HTTP method used
227
+ # for making the link request
228
+ #
229
+ # It will try to find links by (in order of precedence):
230
+ # innerHTML, with simple &nbsp; handling
231
+ # title
232
+ # id
233
+ #
234
+ # innerHTML and title are matchable by text subtring or Regexp
235
+ # id is matchable by full text equality or Regexp
236
+ #
237
+ # Example:
238
+ # click_link "Sign up"
239
+ # click_link "Sign up", :javascript => false
240
+ # click_link "Sign up", :method => :put
241
+ def click_link(text_or_title_or_id, options = {})
242
+ find_link(text_or_title_or_id).click(options)
243
+ end
244
+
245
+ webrat_deprecate :clicks_link, :click_link
246
+
247
+ # Verifies that a submit button exists for the form, then submits the form, follows
248
+ # any redirects, and verifies the final page was successful.
249
+ #
250
+ # Example:
251
+ # click_button "Login"
252
+ # click_button
253
+ #
254
+ # The URL and HTTP method for the form submission are automatically read from the
255
+ # <tt>action</tt> and <tt>method</tt> attributes of the <tt><form></tt> element.
256
+ def click_button(value = nil)
257
+ find_button(value).click
258
+ end
259
+
260
+ webrat_deprecate :clicks_button, :click_button
261
+
262
+ def submit_form(id)
263
+ FormLocator.new(@session, dom, id).locate.submit
264
+ end
265
+
266
+ def dom # :nodoc:
267
+ return @dom if @dom
268
+
269
+ if @selector
270
+ @dom = scoped_dom
271
+ else
272
+ @dom = page_dom
273
+ end
274
+
275
+ return @dom
276
+ end
277
+
278
+ protected
279
+
280
+ def page_dom #:nodoc:
281
+ return @response.dom if @response.respond_to?(:dom)
282
+ dom = Webrat::XML.document(@response_body)
283
+ Webrat.define_dom_method(@response, dom)
284
+ return dom
285
+ end
286
+
287
+ def scoped_dom #:nodoc:
288
+ Webrat::XML.document("<html>" + Webrat::XML.to_html(Webrat::XML.css_search(@scope.dom, @selector).first) + "</html>")
289
+ end
290
+
291
+ def locate_field(field_locator, *field_types) #:nodoc:
292
+ if field_locator.is_a?(Field)
293
+ field_locator
294
+ else
295
+ field(field_locator, *field_types)
296
+ end
297
+ end
298
+
299
+ def locate_id_prefix(options, &location_strategy) #:nodoc:
300
+ return options[:id_prefix] if options[:id_prefix]
301
+
302
+ if options[:from]
303
+ if (label = LabelLocator.new(@session, dom, options[:from]).locate)
304
+ label.for_id
305
+ else
306
+ raise NotFoundError.new("Could not find the label with text #{options[:from]}")
307
+ end
308
+ else
309
+ yield
310
+ end
311
+ end
312
+
313
+ def forms #:nodoc:
314
+ @forms ||= Form.load_all(@session, dom)
315
+ end
316
+
317
+ end
318
+ end
@@ -0,0 +1,241 @@
1
+ require "forwardable"
2
+ require "ostruct"
3
+
4
+ require "webrat/core/mime"
5
+
6
+ module Webrat
7
+ # A page load or form submission returned an unsuccessful response code (500-599)
8
+ class PageLoadError < WebratError
9
+ end
10
+
11
+ def self.session_class
12
+ case Webrat.configuration.mode
13
+ when :rails
14
+ RailsSession
15
+ when :merb
16
+ MerbSession
17
+ when :selenium
18
+ SeleniumSession
19
+ when :rack
20
+ RackSession
21
+ when :sinatra
22
+ SinatraSession
23
+ when :mechanize
24
+ MechanizeSession
25
+ else
26
+ raise WebratError.new("Unknown Webrat mode: #{Webrat.configuration.mode.inspect}")
27
+ end
28
+ end
29
+
30
+ class Session
31
+ extend Forwardable
32
+ include Logging
33
+
34
+ attr_reader :current_url
35
+ attr_reader :elements
36
+
37
+ def initialize(context = nil) #:nodoc:
38
+ @http_method = :get
39
+ @data = {}
40
+ @default_headers = {}
41
+ @custom_headers = {}
42
+ @context = context
43
+
44
+ reset
45
+ end
46
+
47
+ # Saves the page out to RAILS_ROOT/tmp/ and opens it in the default
48
+ # web browser if on OS X. Useful for debugging.
49
+ #
50
+ # Example:
51
+ # save_and_open_page
52
+ def save_and_open_page
53
+ return unless File.exist?(saved_page_dir)
54
+
55
+ filename = "#{saved_page_dir}/webrat-#{Time.now.to_i}.html"
56
+
57
+ File.open(filename, "w") do |f|
58
+ f.write rewrite_css_and_image_references(response_body)
59
+ end
60
+
61
+ open_in_browser(filename)
62
+ end
63
+
64
+ def current_dom #:nodoc:
65
+ current_scope.dom
66
+ end
67
+
68
+ # For backwards compatibility -- removing in 1.0
69
+ def current_page #:nodoc:
70
+ page = OpenStruct.new
71
+ page.url = @current_url
72
+ page.http_method = @http_method
73
+ page.data = @data
74
+ page
75
+ end
76
+
77
+ def doc_root #:nodoc:
78
+ nil
79
+ end
80
+
81
+ def saved_page_dir #:nodoc:
82
+ File.expand_path(".")
83
+ end
84
+
85
+ def header(key, value)
86
+ @custom_headers[key] = value
87
+ end
88
+
89
+ def http_accept(mime_type)
90
+ header('Accept', Webrat::MIME.mime_type(mime_type))
91
+ end
92
+
93
+ def basic_auth(user, pass)
94
+ encoded_login = ["#{user}:#{pass}"].pack("m*")
95
+ header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
96
+ end
97
+
98
+ def headers #:nodoc:
99
+ @default_headers.dup.merge(@custom_headers.dup)
100
+ end
101
+
102
+ def request_page(url, http_method, data) #:nodoc:
103
+ h = headers
104
+ h['HTTP_REFERER'] = @current_url if @current_url
105
+
106
+ debug_log "REQUESTING PAGE: #{http_method.to_s.upcase} #{url} with #{data.inspect} and HTTP headers #{h.inspect}"
107
+ if h.empty?
108
+ send "#{http_method}", url, data || {}
109
+ else
110
+ send "#{http_method}", url, data || {}, h
111
+ end
112
+
113
+ save_and_open_page if exception_caught? && Webrat.configuration.open_error_files?
114
+ raise PageLoadError.new("Page load was not successful (Code: #{response_code.inspect}):\n#{formatted_error}") unless success_code?
115
+
116
+ reset
117
+
118
+ @current_url = url
119
+ @http_method = http_method
120
+ @data = data
121
+
122
+ return response
123
+ end
124
+
125
+ def success_code? #:nodoc:
126
+ (200..499).include?(response_code)
127
+ end
128
+
129
+ def exception_caught? #:nodoc:
130
+ response_body =~ /Exception caught/
131
+ end
132
+
133
+ def current_scope #:nodoc:
134
+ scopes.last || page_scope
135
+ end
136
+
137
+ # Reloads the last page requested. Note that this will resubmit forms
138
+ # and their data.
139
+ def reloads
140
+ request_page(@current_url, @http_method, @data)
141
+ end
142
+
143
+ webrat_deprecate :reload, :reloads
144
+
145
+
146
+ # Works like click_link, but only looks for the link text within a given selector
147
+ #
148
+ # Example:
149
+ # click_link_within "#user_12", "Vote"
150
+ def click_link_within(selector, link_text)
151
+ within(selector) do
152
+ click_link(link_text)
153
+ end
154
+ end
155
+
156
+ webrat_deprecate :clicks_link_within, :click_link_within
157
+
158
+ def within(selector)
159
+ scopes.push(Scope.from_scope(self, current_scope, selector))
160
+ ret = yield(current_scope)
161
+ scopes.pop
162
+ return ret
163
+ end
164
+
165
+ # Issues a GET request for a page, follows any redirects, and verifies the final page
166
+ # load was successful.
167
+ #
168
+ # Example:
169
+ # visit "/"
170
+ def visit(url = nil, http_method = :get, data = {})
171
+ request_page(url, http_method, data)
172
+ end
173
+
174
+ webrat_deprecate :visits, :visit
175
+
176
+ def open_in_browser(path) # :nodoc
177
+ platform = ruby_platform
178
+ if platform =~ /cygwin/ || platform =~ /win32/
179
+ `rundll32 url.dll,FileProtocolHandler #{path.gsub("/", "\\\\")}`
180
+ elsif platform =~ /darwin/
181
+ `open #{path}`
182
+ end
183
+ end
184
+
185
+ def rewrite_css_and_image_references(response_html) # :nodoc:
186
+ return response_html unless doc_root
187
+ response_html.gsub(/"\/(stylesheets|images)/, doc_root + '/\1')
188
+ end
189
+
190
+ # Subclasses can override this to show error messages without html
191
+ def formatted_error #:nodoc:
192
+ response_body
193
+ end
194
+
195
+ def scopes #:nodoc:
196
+ @_scopes ||= []
197
+ end
198
+
199
+ def page_scope #:nodoc:
200
+ @_page_scope ||= Scope.from_page(self, response, response_body)
201
+ end
202
+
203
+ def dom
204
+ page_scope.dom
205
+ end
206
+
207
+ def_delegators :current_scope, :fill_in, :fills_in
208
+ def_delegators :current_scope, :set_hidden_field
209
+ def_delegators :current_scope, :submit_form
210
+ def_delegators :current_scope, :check, :checks
211
+ def_delegators :current_scope, :uncheck, :unchecks
212
+ def_delegators :current_scope, :choose, :chooses
213
+ def_delegators :current_scope, :select, :selects
214
+ def_delegators :current_scope, :select_datetime, :selects_datetime
215
+ def_delegators :current_scope, :select_date, :selects_date
216
+ def_delegators :current_scope, :select_time, :selects_time
217
+ def_delegators :current_scope, :attach_file, :attaches_file
218
+ def_delegators :current_scope, :click_area, :clicks_area
219
+ def_delegators :current_scope, :click_link, :clicks_link
220
+ def_delegators :current_scope, :click_button, :clicks_button
221
+ def_delegators :current_scope, :should_see
222
+ def_delegators :current_scope, :should_not_see
223
+ def_delegators :current_scope, :field_labeled
224
+ def_delegators :current_scope, :field_by_xpath
225
+ def_delegators :current_scope, :field_with_id
226
+ def_delegators :current_scope, :select_option
227
+
228
+ private
229
+
230
+ def reset
231
+ @elements = {}
232
+ @_scopes = nil
233
+ @_page_scope = nil
234
+ end
235
+
236
+ # accessor for testing
237
+ def ruby_platform
238
+ RUBY_PLATFORM
239
+ end
240
+ end
241
+ end