webrat/lib/webrat/core/session.rb

175 lines
4.6 KiB
Ruby

require "forwardable"
require "ostruct"
require "webrat/core/mime"
module Webrat
class Session
extend Forwardable
include Logging
include Flunk
attr_reader :current_url
def initialize
@http_method = :get
@data = {}
@default_headers = {}
@custom_headers = {}
end
# Saves the page out to RAILS_ROOT/tmp/ and opens it in the default
# web browser if on OS X. Useful for debugging.
#
# Example:
# save_and_open_page
def save_and_open_page
return unless File.exist?(saved_page_dir)
filename = "#{saved_page_dir}/webrat-#{Time.now.to_i}.html"
File.open(filename, "w") do |f|
f.write rewrite_css_and_image_references(response_body)
end
open_in_browser(filename)
end
def current_dom
current_scope.dom
end
# For backwards compatibility -- removing in 1.0
def current_page
page = OpenStruct.new
page.url = @current_url
page.http_method = @http_method
page.data = @data
page
end
def doc_root
nil
end
def saved_page_dir
File.expand_path(".")
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*")
header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
end
def headers
@default_headers.dup.merge(@custom_headers.dup)
end
def request_page(url, http_method, data)
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}"
if h.empty?
send "#{http_method}", url, data || {}
else
send "#{http_method}", url, data || {}, h
end
save_and_open_page if exception_caught?
flunk("Page load was not successful (Code: #{response_code.inspect}):\n#{formatted_error}") unless success_code?
@scope = nil
@current_url = url
@http_method = http_method
@data = data
end
def success_code?
(200..499).include?(response_code)
end
def exception_caught?
response_body =~ /Exception caught/
end
def current_scope
@scope ||= Scope.new(self, response_body)
end
# Reloads the last page requested. Note that this will resubmit forms
# and their data.
#
# Example:
# reloads
def reloads
request_page(@current_url, @http_method, @data)
end
alias_method :reload, :reloads
# 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 |scope|
scope.click_link(link_text)
end
end
alias_method :clicks_link_within, :click_link_within
def within(selector)
yield Scope.new(self, response_body, selector)
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
alias_method :visits, :visit
def open_in_browser(path) # :nodoc
`open #{path}`
end
def rewrite_css_and_image_references(response_html) # :nodoc
return response_html unless doc_root
response_html.gsub(/"\/(stylesheets|images)/, doc_root + '/\1')
end
# Subclasses can override this to show error messages without html
def formatted_error
response_body
end
def_delegators :current_scope, :fill_in, :fills_in
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, :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, :should_see
def_delegators :current_scope, :should_not_see
def_delegators :current_scope, :field_labeled
end
end