/
session.rb
310 lines (249 loc) · 8.3 KB
/
session.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
require "forwardable"
require "ostruct"
require "webrat/core/mime"
require "webrat/core/save_and_open_page"
module Webrat
# A page load or form submission returned an unsuccessful response code (500-599)
class PageLoadError < WebratError
end
class InfiniteRedirectError < WebratError
end
def self.session_class
if Webrat.configuration.mode == :selenium
SeleniumSession
elsif Webrat.configuration.mode == :webdriver
WebdriverSession
else
Session
end
end
def self.adapter_class
case Webrat.configuration.mode
when :rails
RailsAdapter
when :merb
MerbAdapter
when :rack
RackAdapter
when :rack_test
warn("The :rack_test mode is deprecated. Please use :rack instead")
require "webrat/rack"
RackAdapter
when :sinatra
warn("The :sinatra mode is deprecated. Please use :rack instead")
SinatraAdapter
when :mechanize
MechanizeAdapter
else
raise WebratError.new(<<-STR)
Unknown Webrat mode: #{Webrat.configuration.mode.inspect}
Please ensure you have a Webrat configuration block that specifies a mode
in your test_helper.rb, spec_helper.rb, or env.rb (for Cucumber).
This configure block supercedes the need to require "webrat/<framework>".
For example:
Webrat.configure do |config|
config.mode = :rails
end
STR
end
end
class Session
extend Forwardable
include Logging
include SaveAndOpenPage
attr_accessor :adapter
attr_reader :current_url
attr_reader :elements
def_delegators :@adapter, :response, :response_code, :response_body,
:response_body=, :response_code=,
:get, :post, :put, :delete
def initialize(adapter = nil)
@adapter = adapter
@http_method = :get
@data = {}
@default_headers = {}
@custom_headers = {}
reset
end
def current_dom #:nodoc:
current_scope.dom
end
# For backwards compatibility -- removing in 1.0
def current_page #:nodoc:
warn "current_page is deprecated and will be going away in the next release. Use current_url instead."
page = OpenStruct.new
page.url = @current_url
page.http_method = @http_method
page.data = @data
page
end
def doc_root #:nodoc:
nil
end
def header(key, value)
@custom_headers[key] = value
end
def http_accept(mime_type)
header('Accept', Webrat::MIME.mime_type(mime_type))
end
def basic_auth(user, pass)
encoded_login = ["#{user}:#{pass}"].pack("m*").gsub(/\n/, '')
header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
end
def headers #:nodoc:
@default_headers.dup.merge(@custom_headers.dup)
end
def request_page(url, http_method, data) #:nodoc:
h = headers
h['HTTP_REFERER'] = @current_url if @current_url
debug_log "REQUESTING PAGE: #{http_method.to_s.upcase} #{url} with #{data.inspect} and HTTP headers #{h.inspect}"
process_request(http_method, url, data, h)
save_and_open_page if exception_caught? && Webrat.configuration.open_error_files?
raise PageLoadError.new("Page load was not successful (Code: #{response_code.inspect}):\n#{formatted_error}") unless success_code?
reset
@current_url = url
@http_method = http_method
@data = data
if internal_redirect?
check_for_infinite_redirects
request_page(response_location, :get, {})
end
return response
end
def check_for_infinite_redirects
if current_url == response_location
@_identical_redirect_count ||= 0
@_identical_redirect_count += 1
end
if infinite_redirect_limit_exceeded?
raise InfiniteRedirectError.new("#{Webrat.configuration.infinite_redirect_limit} redirects to the same URL (#{current_url.inspect})")
end
end
def infinite_redirect_limit_exceeded?
Webrat.configuration.infinite_redirect_limit &&
(@_identical_redirect_count || 0) > Webrat.configuration.infinite_redirect_limit
end
def success_code? #:nodoc:
(200..499).include?(response_code)
end
def redirect? #:nodoc:
(response_code / 100).to_i == 3
end
def internal_redirect?
return false unless redirect?
#should keep internal_redirects if the subdomain changes
current_host_domain = current_host.split('.')[-2..-1].join('.') rescue current_host
response_location_host_domain = response_location_host.split('.')[-2..-1].join('.') rescue response_location_host
current_host_domain == response_location_host_domain
end
#easy helper to pull out where we were redirected to
def redirected_to
redirect? ? response_location : nil
end
def exception_caught? #:nodoc:
response_body =~ /Exception caught/
end
def current_scope #:nodoc:
scopes.last || page_scope
end
# Reloads the last page requested. Note that this will resubmit forms
# and their data.
def reload
request_page(@current_url, @http_method, @data)
end
webrat_deprecate :reloads, :reload
# Works like click_link, but only looks for the link text within a given selector
#
# Example:
# click_link_within "#user_12", "Vote"
def click_link_within(selector, link_text)
within(selector) do
click_link(link_text)
end
end
webrat_deprecate :clicks_link_within, :click_link_within
def within(selector)
scopes.push(Scope.from_scope(self, current_scope, selector))
ret = yield(current_scope)
scopes.pop
return ret
end
# Issues a GET request for a page, follows any redirects, and verifies the final page
# load was successful.
#
# Example:
# visit "/"
def visit(url = nil, http_method = :get, data = {})
request_page(url, http_method, data)
end
webrat_deprecate :visits, :visit
# Subclasses can override this to show error messages without html
def formatted_error #:nodoc:
response_body
end
def scopes #:nodoc:
@_scopes ||= []
end
def page_scope #:nodoc:
@_page_scope ||= Scope.from_page(self, response, response_body)
end
def dom
page_scope.dom
end
def xml_content_type?
false
end
def simulate
return if Webrat.configuration.mode == :selenium
yield
end
def automate
return unless Webrat.configuration.mode == :selenium
yield
end
def_delegators :current_scope, :fill_in, :fills_in
def_delegators :current_scope, :set_hidden_field
def_delegators :current_scope, :submit_form
def_delegators :current_scope, :check, :checks
def_delegators :current_scope, :uncheck, :unchecks
def_delegators :current_scope, :choose, :chooses
def_delegators :current_scope, :select, :selects
def_delegators :current_scope, :unselect, :unselects
def_delegators :current_scope, :select_datetime, :selects_datetime
def_delegators :current_scope, :select_date, :selects_date
def_delegators :current_scope, :select_time, :selects_time
def_delegators :current_scope, :attach_file, :attaches_file
def_delegators :current_scope, :click_area, :clicks_area
def_delegators :current_scope, :click_link, :clicks_link
def_delegators :current_scope, :click_button, :clicks_button
def_delegators :current_scope, :click
def_delegators :current_scope, :hover
def_delegators :current_scope, :field_labeled
def_delegators :current_scope, :field_by_xpath
def_delegators :current_scope, :field_with_id
def_delegators :current_scope, :select_option
def_delegators :current_scope, :field_named
private
def process_request(http_method, url, data, headers)
if headers.empty?
send "#{http_method}", url, data || {}
else
send "#{http_method}", url, data || {}, headers
end
end
def response_location
response.headers["Location"]
end
def current_host
URI.parse(current_url).host || @custom_headers["Host"] || "www.example.com"
end
def response_location_host
URI.parse(response_location).host || "www.example.com"
end
def reset
@elements = {}
@_scopes = nil
@_page_scope = nil
end
end
end