Merge branch 'merb'
This commit is contained in:
commit
87f549b3af
|
@ -2,9 +2,9 @@ require "webrat/core"
|
||||||
|
|
||||||
module Webrat
|
module Webrat
|
||||||
class Session
|
class Session
|
||||||
include Merb::Test::RequestHelper
|
include Merb::Test::MakeRequest
|
||||||
|
|
||||||
attr_reader :response
|
attr_accessor :response
|
||||||
|
|
||||||
def get(url, data, headers = nil)
|
def get(url, data, headers = nil)
|
||||||
do_request(url, data, headers, "GET")
|
do_request(url, data, headers, "GET")
|
||||||
|
@ -29,17 +29,36 @@ module Webrat
|
||||||
def response_code
|
def response_code
|
||||||
@response.status
|
@response.status
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def do_request(url, data, headers, method)
|
def do_request(url, data, headers, method)
|
||||||
@response = request(url, :params => (data && data.any?) ? data : nil, :headers => headers, :method => method)
|
@response = request(url,
|
||||||
|
:params => (data && data.any?) ? data : nil,
|
||||||
|
:headers => headers, :method => method)
|
||||||
|
self.get(@response.headers['Location'], nil, @response.headers) if @response.status == 302
|
||||||
|
end
|
||||||
|
|
||||||
|
def follow_redirect
|
||||||
self.get(@response.headers['Location'], nil, @response.headers) if @response.status == 302
|
self.get(@response.headers['Location'], nil, @response.headers) if @response.status == 302
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module Merb
|
||||||
|
module Test
|
||||||
|
module RequestHelper
|
||||||
|
def request(uri, env = {})
|
||||||
|
@session ||= Webrat::Session.new
|
||||||
|
@session.response = @session.request(uri, env)
|
||||||
|
end
|
||||||
|
|
||||||
|
def follow_redirect
|
||||||
|
@session.follow_redirect
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class Merb::Test::RspecStory
|
class Merb::Test::RspecStory
|
||||||
def browser
|
def browser
|
||||||
@browser ||= Webrat::Session.new
|
@browser ||= Webrat::Session.new
|
||||||
|
|
|
@ -1,21 +1,14 @@
|
||||||
require "cgi"
|
require "cgi"
|
||||||
require "webrat/core_extensions/blank"
|
gem "extlib"
|
||||||
require "webrat/merb/url_encoded_pair_parser"
|
require "extlib"
|
||||||
|
require "merb-core"
|
||||||
|
|
||||||
|
HashWithIndifferentAccess = Mash
|
||||||
|
|
||||||
module Webrat
|
module Webrat
|
||||||
class ParamParser
|
class ParamParser
|
||||||
def self.parse_query_parameters(query_string)
|
def self.parse_query_parameters(query_string)
|
||||||
return {} if query_string.blank?
|
Merb::Parse.query(query_string)
|
||||||
|
|
||||||
pairs = query_string.split('&').collect do |chunk|
|
|
||||||
next if chunk.empty?
|
|
||||||
key, value = chunk.split('=', 2)
|
|
||||||
next if key.empty?
|
|
||||||
value = value.nil? ? nil : CGI.unescape(value)
|
|
||||||
[ CGI.unescape(key), value ]
|
|
||||||
end.compact
|
|
||||||
|
|
||||||
UrlEncodedPairParser.new(pairs).result
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,97 +0,0 @@
|
||||||
require "cgi"
|
|
||||||
require "strscan"
|
|
||||||
require "webrat/core_extensions/hash_with_indifferent_access"
|
|
||||||
|
|
||||||
class UrlEncodedPairParser < StringScanner #:nodoc:
|
|
||||||
attr_reader :top, :parent, :result
|
|
||||||
|
|
||||||
def initialize(pairs = [])
|
|
||||||
super('')
|
|
||||||
@result = {}
|
|
||||||
pairs.each { |key, value| parse(key, value) }
|
|
||||||
end
|
|
||||||
|
|
||||||
KEY_REGEXP = %r{([^\[\]=&]+)}
|
|
||||||
BRACKETED_KEY_REGEXP = %r{\[([^\[\]=&]+)\]}
|
|
||||||
|
|
||||||
# Parse the query string
|
|
||||||
def parse(key, value)
|
|
||||||
self.string = key
|
|
||||||
@top, @parent = result, nil
|
|
||||||
|
|
||||||
# First scan the bare key
|
|
||||||
key = scan(KEY_REGEXP) or return
|
|
||||||
key = post_key_check(key)
|
|
||||||
|
|
||||||
# Then scan as many nestings as present
|
|
||||||
until eos?
|
|
||||||
r = scan(BRACKETED_KEY_REGEXP) or return
|
|
||||||
key = self[1]
|
|
||||||
key = post_key_check(key)
|
|
||||||
end
|
|
||||||
|
|
||||||
bind(key, value)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
# After we see a key, we must look ahead to determine our next action. Cases:
|
|
||||||
#
|
|
||||||
# [] follows the key. Then the value must be an array.
|
|
||||||
# = follows the key. (A value comes next)
|
|
||||||
# & or the end of string follows the key. Then the key is a flag.
|
|
||||||
# otherwise, a hash follows the key.
|
|
||||||
def post_key_check(key)
|
|
||||||
if scan(/\[\]/) # a[b][] indicates that b is an array
|
|
||||||
container(key, Array)
|
|
||||||
nil
|
|
||||||
elsif check(/\[[^\]]/) # a[b] indicates that a is a hash
|
|
||||||
container(key, Hash)
|
|
||||||
nil
|
|
||||||
else # End of key? We do nothing.
|
|
||||||
key
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Add a container to the stack.
|
|
||||||
def container(key, klass)
|
|
||||||
type_conflict! klass, top[key] if top.is_a?(Hash) && top.key?(key) && ! top[key].is_a?(klass)
|
|
||||||
value = bind(key, klass.new)
|
|
||||||
type_conflict! klass, value unless value.is_a?(klass)
|
|
||||||
push(value)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Push a value onto the 'stack', which is actually only the top 2 items.
|
|
||||||
def push(value)
|
|
||||||
@parent, @top = @top, value
|
|
||||||
end
|
|
||||||
|
|
||||||
# Bind a key (which may be nil for items in an array) to the provided value.
|
|
||||||
def bind(key, value)
|
|
||||||
if top.is_a? Array
|
|
||||||
if key
|
|
||||||
if top[-1].is_a?(Hash) && ! top[-1].key?(key)
|
|
||||||
top[-1][key] = value
|
|
||||||
else
|
|
||||||
top << {key => value}.with_indifferent_access
|
|
||||||
push top.last
|
|
||||||
value = top[key]
|
|
||||||
end
|
|
||||||
else
|
|
||||||
top << value
|
|
||||||
end
|
|
||||||
elsif top.is_a? Hash
|
|
||||||
key = CGI.unescape(key)
|
|
||||||
parent << (@top = {}) if top.key?(key) && parent.is_a?(Array)
|
|
||||||
top[key] ||= value
|
|
||||||
return top[key]
|
|
||||||
else
|
|
||||||
raise ArgumentError, "Don't know what to do: top is #{top.inspect}"
|
|
||||||
end
|
|
||||||
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
|
|
||||||
def type_conflict!(klass, value)
|
|
||||||
raise TypeError, "Conflicting types for parameter containers. Expected an instance of #{klass} but found an instance of #{value.class}. This can be caused by colliding Array and Hash parameters like qs[]=value&qs[key]=value. (The parameters received were #{value.inspect}.)"
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in New Issue