Support Merb 1.0

This commit is contained in:
Yehuda Katz 2008-11-02 19:11:20 -08:00
parent 42506924ae
commit 85f16d2cdc
3 changed files with 30 additions and 115 deletions

View File

@ -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

View File

@ -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

View File

@ -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