rack-test 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.rdoc +57 -0
- data/Rakefile +58 -0
- data/lib/rack/test.rb +213 -0
- data/lib/rack/test/cookie_jar.rb +121 -0
- data/lib/rack/test/methods.rb +45 -0
- data/lib/rack/test/utils.rb +27 -0
- metadata +63 -0
data/History.txt
ADDED
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2008-2009 Bryan Helmkamp, Engine Yard Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
= Rack::Test
|
2
|
+
|
3
|
+
- http://gitrdoc.com/brynary/rack-test
|
4
|
+
- http://github.com/brynary/rack-test
|
5
|
+
|
6
|
+
== Description
|
7
|
+
|
8
|
+
Rack::Test is a small, simple testing API for Rack apps. It can be used on its
|
9
|
+
own or as a reusable starting point for Web frameworks and testing libraries
|
10
|
+
to build on. Most of its initial functionality is an extraction of Merb 1.0's
|
11
|
+
request helpers feature.
|
12
|
+
|
13
|
+
== Features
|
14
|
+
|
15
|
+
* Maintains a cookie jar across requests
|
16
|
+
* Easily follow redirects when desired
|
17
|
+
* Set request headers to be used by all subsequent requests
|
18
|
+
* Small footprint. Approximately 200 LOC
|
19
|
+
|
20
|
+
== Example
|
21
|
+
|
22
|
+
require "rack/test"
|
23
|
+
|
24
|
+
class HomepageTest < Test::Unit::TestCase
|
25
|
+
include Rack::Test::Methods
|
26
|
+
|
27
|
+
def app
|
28
|
+
MyApp.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_redirect_logged_in_users_to_dashboard
|
32
|
+
authorize "bryan", "secret"
|
33
|
+
get "/"
|
34
|
+
follow_redirect!
|
35
|
+
|
36
|
+
assert_equal "http://example.org/redirected", last_request.url
|
37
|
+
assert last_response.ok?
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
== Install
|
43
|
+
|
44
|
+
To install the latest release as a gem:
|
45
|
+
|
46
|
+
sudo gem install rack-test
|
47
|
+
|
48
|
+
== Authors
|
49
|
+
|
50
|
+
- Maintained by {Bryan Helmkamp}[mailto:bryan@brynary.com]
|
51
|
+
- Contributions from Simon Rozet and Pat Nakajima
|
52
|
+
- Much of the original code was extracted from Merb 1.0's request helper
|
53
|
+
|
54
|
+
== License
|
55
|
+
|
56
|
+
Copyright (c) 2008-2009 Bryan Helmkamp, Engine Yard Inc.
|
57
|
+
See MIT-LICENSE.txt in this directory.
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake/rdoctask"
|
3
|
+
require "rake/gempackagetask"
|
4
|
+
require "rake/clean"
|
5
|
+
require "spec/rake/spectask"
|
6
|
+
require File.expand_path("./lib/rack/test")
|
7
|
+
|
8
|
+
Spec::Rake::SpecTask.new do |t|
|
9
|
+
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Run all specs in spec directory with RCov"
|
13
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
14
|
+
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
|
15
|
+
t.rcov = true
|
16
|
+
t.rcov_opts = lambda do
|
17
|
+
IO.readlines(File.dirname(__FILE__) + "/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Run the specs"
|
22
|
+
task :default => :spec
|
23
|
+
|
24
|
+
spec = Gem::Specification.new do |s|
|
25
|
+
s.name = "rack-test"
|
26
|
+
s.version = Rack::Test::VERSION
|
27
|
+
s.author = "Bryan Helmkamp"
|
28
|
+
s.email = "bryan" + "@" + "brynary.com"
|
29
|
+
s.homepage = "http://github.com/brynary/rack-test"
|
30
|
+
s.summary = "Simple testing API built on Rack"
|
31
|
+
s.description = s.summary
|
32
|
+
s.files = %w[History.txt Rakefile README.rdoc] + Dir["lib/**/*"]
|
33
|
+
|
34
|
+
# rdoc
|
35
|
+
s.has_rdoc = true
|
36
|
+
s.extra_rdoc_files = %w(README.rdoc MIT-LICENSE.txt)
|
37
|
+
end
|
38
|
+
|
39
|
+
Rake::GemPackageTask.new(spec) do |package|
|
40
|
+
package.gem_spec = spec
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "Delete generated RDoc"
|
44
|
+
task :clobber_docs do
|
45
|
+
FileUtils.rm_rf("doc")
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "Generate RDoc"
|
49
|
+
task :docs => :clobber_docs do
|
50
|
+
system "hanna --title 'Rack::Test #{Rack::Test::VERSION} API Documentation'"
|
51
|
+
end
|
52
|
+
|
53
|
+
desc 'Install the package as a gem.'
|
54
|
+
task :install => [:clean, :package] do
|
55
|
+
gem = Dir['pkg/*.gem'].first
|
56
|
+
sh "sudo gem install --local #{gem}"
|
57
|
+
end
|
58
|
+
|
data/lib/rack/test.rb
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
|
3
|
+
unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__) + "/.."))
|
4
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/.."))
|
5
|
+
end
|
6
|
+
|
7
|
+
require "uri"
|
8
|
+
require "rack"
|
9
|
+
require "rack/test/cookie_jar"
|
10
|
+
require "rack/test/utils"
|
11
|
+
require "rack/test/methods"
|
12
|
+
|
13
|
+
module Rack
|
14
|
+
module Test
|
15
|
+
|
16
|
+
VERSION = "0.1.0"
|
17
|
+
|
18
|
+
# The common base class for exceptions raised by Rack::Test
|
19
|
+
class Error < StandardError
|
20
|
+
end
|
21
|
+
|
22
|
+
class Session
|
23
|
+
include Rack::Test::Utils
|
24
|
+
|
25
|
+
# Initialize a new session for the given Rack app
|
26
|
+
def initialize(app)
|
27
|
+
raise ArgumentError.new("app must respond_to?(:call)") unless app.respond_to?(:call)
|
28
|
+
|
29
|
+
@headers = {}
|
30
|
+
@app = app
|
31
|
+
end
|
32
|
+
|
33
|
+
# Issue a GET request for the given URI with the given params and Rack
|
34
|
+
# environment. Stores the issues request object in #last_request and
|
35
|
+
# the app's response in #last_response. Yield #last_response to a block
|
36
|
+
# if given.
|
37
|
+
#
|
38
|
+
# Example:
|
39
|
+
# get "/"
|
40
|
+
def get(uri, params = {}, env = {}, &block)
|
41
|
+
env = env_for(uri, env.merge(:method => "GET", :params => params))
|
42
|
+
process_request(uri, env, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Issue a POST request for the given URI. See #get
|
46
|
+
#
|
47
|
+
# Example:
|
48
|
+
# post "/signup", "name" => "Bryan"
|
49
|
+
def post(uri, params = {}, env = {}, &block)
|
50
|
+
env = env_for(uri, env.merge(:method => "POST", :params => params))
|
51
|
+
process_request(uri, env, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Issue a PUT request for the given URI. See #get
|
55
|
+
#
|
56
|
+
# Example:
|
57
|
+
# put "/"
|
58
|
+
def put(uri, params = {}, env = {}, &block)
|
59
|
+
env = env_for(uri, env.merge(:method => "PUT", :params => params))
|
60
|
+
process_request(uri, env, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Issue a DELETE request for the given URI. See #get
|
64
|
+
#
|
65
|
+
# Example:
|
66
|
+
# delete "/"
|
67
|
+
def delete(uri, params = {}, env = {}, &block)
|
68
|
+
env = env_for(uri, env.merge(:method => "DELETE", :params => params))
|
69
|
+
process_request(uri, env, &block)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Issue a HEAD request for the given URI. See #get
|
73
|
+
#
|
74
|
+
# Example:
|
75
|
+
# head "/"
|
76
|
+
def head(uri, params = {}, env = {}, &block)
|
77
|
+
env = env_for(uri, env.merge(:method => "HEAD", :params => params))
|
78
|
+
process_request(uri, env, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Issue a request to the Rack app for the given URI and optional Rack
|
82
|
+
# environment. Stores the issues request object in #last_request and
|
83
|
+
# the app's response in #last_response. Yield #last_response to a block
|
84
|
+
# if given.
|
85
|
+
#
|
86
|
+
# Example:
|
87
|
+
# request "/"
|
88
|
+
def request(uri, env = {}, &block)
|
89
|
+
env = env_for(uri, env)
|
90
|
+
process_request(uri, env, &block)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Set a header to be included on all subsequent requests through the
|
94
|
+
# session. Use a value of nil to remove a previously configured header.
|
95
|
+
#
|
96
|
+
# Example:
|
97
|
+
# header "User-Agent", "Firefox"
|
98
|
+
def header(name, value)
|
99
|
+
if value.nil?
|
100
|
+
@headers.delete(name)
|
101
|
+
else
|
102
|
+
@headers[name] = value
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Set the username and password for HTTP Basic authorization, to be
|
107
|
+
# included in subsequent requests in the HTTP_AUTHORIZATION header.
|
108
|
+
#
|
109
|
+
# Example:
|
110
|
+
# authorize "bryan", "secret"
|
111
|
+
def authorize(username, password)
|
112
|
+
encoded_login = ["#{username}:#{password}"].pack("m*")
|
113
|
+
header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
|
114
|
+
end
|
115
|
+
|
116
|
+
# Rack::Test will not follow any redirects automatically. This method
|
117
|
+
# will follow the redirect returned in the last response. If the last
|
118
|
+
# response was not a redirect, an error will be raised.
|
119
|
+
def follow_redirect!
|
120
|
+
unless last_response.redirect?
|
121
|
+
raise Error.new("Last response was not a redirect. Cannot follow_redirect!")
|
122
|
+
end
|
123
|
+
|
124
|
+
get(last_response["Location"])
|
125
|
+
end
|
126
|
+
|
127
|
+
# Return the last request issued in the session. Raises an error if no
|
128
|
+
# requests have been sent yet.
|
129
|
+
def last_request
|
130
|
+
raise Error.new("No request yet. Request a page first.") unless @last_request
|
131
|
+
|
132
|
+
@last_request
|
133
|
+
end
|
134
|
+
|
135
|
+
# Return the last response received in the session. Raises an error if
|
136
|
+
# no requests have been sent yet.
|
137
|
+
def last_response
|
138
|
+
raise Error.new("No response yet. Request a page first.") unless @last_response
|
139
|
+
|
140
|
+
@last_response
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
|
146
|
+
def env_for(path, env)
|
147
|
+
uri = URI.parse(path)
|
148
|
+
uri.host ||= "example.org"
|
149
|
+
|
150
|
+
env = default_env.merge(env)
|
151
|
+
|
152
|
+
if URI::HTTPS === uri
|
153
|
+
env.update("HTTPS" => "on")
|
154
|
+
end
|
155
|
+
|
156
|
+
if env[:xhr]
|
157
|
+
env["X-Requested-With"] = "XMLHttpRequest"
|
158
|
+
end
|
159
|
+
|
160
|
+
if (env[:method] == "POST" || env["REQUEST_METHOD"] == "POST") && !env.has_key?(:input)
|
161
|
+
env["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
|
162
|
+
env[:input] = params_to_string(env.delete(:params))
|
163
|
+
end
|
164
|
+
|
165
|
+
params = env[:params] || {}
|
166
|
+
params.update(parse_query(uri.query))
|
167
|
+
uri.query = requestify(params)
|
168
|
+
|
169
|
+
if env.has_key?(:cookie)
|
170
|
+
# Add the cookies explicitly set by the user
|
171
|
+
env["HTTP_COOKIE"] = cookie_jar.merge(uri, env.delete(:cookie)).for(uri)
|
172
|
+
else
|
173
|
+
env["HTTP_COOKIE"] = cookie_jar.for(uri)
|
174
|
+
end
|
175
|
+
|
176
|
+
Rack::MockRequest.env_for(uri.to_s, env)
|
177
|
+
end
|
178
|
+
|
179
|
+
def cookie_jar
|
180
|
+
@cookie_jar || Rack::Test::CookieJar.new
|
181
|
+
end
|
182
|
+
|
183
|
+
def process_request(uri, env)
|
184
|
+
uri = URI.parse(uri)
|
185
|
+
uri.host ||= "example.org"
|
186
|
+
|
187
|
+
@last_request = Rack::Request.new(env)
|
188
|
+
|
189
|
+
status, headers, body = @app.call(@last_request.env)
|
190
|
+
@last_response = Rack::Response.new(body, status, headers)
|
191
|
+
@cookie_jar = cookie_jar.merge(uri, last_response.headers["Set-Cookie"])
|
192
|
+
|
193
|
+
yield @last_response if block_given?
|
194
|
+
|
195
|
+
@last_response
|
196
|
+
end
|
197
|
+
|
198
|
+
def default_env
|
199
|
+
{ "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(@headers)
|
200
|
+
end
|
201
|
+
|
202
|
+
def params_to_string(params)
|
203
|
+
case params
|
204
|
+
when Hash then requestify(params)
|
205
|
+
when nil then ""
|
206
|
+
else params
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module Rack
|
2
|
+
module Test
|
3
|
+
|
4
|
+
class Cookie
|
5
|
+
include Rack::Utils
|
6
|
+
|
7
|
+
# :api: private
|
8
|
+
attr_reader :name, :value
|
9
|
+
|
10
|
+
# :api: private
|
11
|
+
def initialize(raw, default_host)
|
12
|
+
# separate the name / value pair from the cookie options
|
13
|
+
@name_value_raw, options = raw.split(/[;,] */n, 2)
|
14
|
+
|
15
|
+
@name, @value = parse_query(@name_value_raw, ';').to_a.first
|
16
|
+
@options = parse_query(options, ';')
|
17
|
+
|
18
|
+
@options.delete_if { |k, v| !v || v.empty? }
|
19
|
+
|
20
|
+
@options["domain"] ||= default_host
|
21
|
+
end
|
22
|
+
|
23
|
+
# :api: private
|
24
|
+
def raw
|
25
|
+
@name_value_raw
|
26
|
+
end
|
27
|
+
|
28
|
+
# :api: private
|
29
|
+
def empty?
|
30
|
+
@value.nil? || @value.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
# :api: private
|
34
|
+
def domain
|
35
|
+
@options["domain"]
|
36
|
+
end
|
37
|
+
|
38
|
+
# :api: private
|
39
|
+
def path
|
40
|
+
@options["path"] || "/"
|
41
|
+
end
|
42
|
+
|
43
|
+
# :api: private
|
44
|
+
def expires
|
45
|
+
Time.parse(@options["expires"]) if @options["expires"]
|
46
|
+
end
|
47
|
+
|
48
|
+
# :api: private
|
49
|
+
def expired?
|
50
|
+
expires && expires < Time.now
|
51
|
+
end
|
52
|
+
|
53
|
+
# :api: private
|
54
|
+
def valid?(uri)
|
55
|
+
uri.host =~ Regexp.new("#{Regexp.escape(domain)}$") &&
|
56
|
+
uri.path =~ Regexp.new("^#{Regexp.escape(path)}")
|
57
|
+
end
|
58
|
+
|
59
|
+
# :api: private
|
60
|
+
def matches?(uri)
|
61
|
+
! expired? && valid?(uri)
|
62
|
+
end
|
63
|
+
|
64
|
+
# :api: private
|
65
|
+
def <=>(other)
|
66
|
+
# Orders the cookies from least specific to most
|
67
|
+
[name, path, domain.reverse] <=> [other.name, other.path, other.domain.reverse]
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
class CookieJar
|
73
|
+
|
74
|
+
# :api: private
|
75
|
+
def initialize(cookies = [])
|
76
|
+
@jar = cookies
|
77
|
+
@jar.sort!
|
78
|
+
end
|
79
|
+
|
80
|
+
def merge(uri, raw_cookies)
|
81
|
+
return self unless raw_cookies
|
82
|
+
|
83
|
+
# Initialize all the the received cookies
|
84
|
+
cookies = []
|
85
|
+
raw_cookies.each do |raw|
|
86
|
+
c = Cookie.new(raw, uri.host)
|
87
|
+
cookies << c if c.valid?(uri)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Remove all the cookies that will be updated
|
91
|
+
new_jar = @jar.reject do |existing|
|
92
|
+
cookies.find do |c|
|
93
|
+
[c.name, c.domain, c.path] == [existing.name, existing.domain, existing.path]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
new_jar.concat cookies
|
98
|
+
|
99
|
+
return self.class.new(new_jar)
|
100
|
+
end
|
101
|
+
|
102
|
+
# :api: private
|
103
|
+
def for(uri)
|
104
|
+
cookies = {}
|
105
|
+
|
106
|
+
# The cookies are sorted by most specific first. So, we loop through
|
107
|
+
# all the cookies in order and add it to a hash by cookie name if
|
108
|
+
# the cookie can be sent to the current URI. It's added to the hash
|
109
|
+
# so that when we are done, the cookies will be unique by name and
|
110
|
+
# we'll have grabbed the most specific to the URI.
|
111
|
+
@jar.each do |cookie|
|
112
|
+
cookies[cookie.name] = cookie.raw if cookie.matches?(uri)
|
113
|
+
end
|
114
|
+
|
115
|
+
cookies.values.join(';')
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Rack
|
2
|
+
module Test
|
3
|
+
|
4
|
+
module Methods
|
5
|
+
|
6
|
+
def self.delegate_to_rack_test_session(*meths)
|
7
|
+
meths.each do |meth|
|
8
|
+
self.class_eval <<-RUBY
|
9
|
+
def #{meth}(*args, &blk)
|
10
|
+
rack_test_session.#{meth}(*args, &blk)
|
11
|
+
end
|
12
|
+
RUBY
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def rack_test_session
|
17
|
+
@_rack_test_session ||= Rack::Test::Session.new(app)
|
18
|
+
end
|
19
|
+
|
20
|
+
delegate_to_rack_test_session \
|
21
|
+
:request,
|
22
|
+
|
23
|
+
# HTTP verbs
|
24
|
+
:get,
|
25
|
+
:post,
|
26
|
+
:put,
|
27
|
+
:delete,
|
28
|
+
:head,
|
29
|
+
|
30
|
+
# Redirects
|
31
|
+
:follow_redirect!,
|
32
|
+
|
33
|
+
# Header-related features
|
34
|
+
:header,
|
35
|
+
:authorize,
|
36
|
+
|
37
|
+
# Expose the last request and response
|
38
|
+
:last_response,
|
39
|
+
:last_request
|
40
|
+
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Rack
|
2
|
+
module Test
|
3
|
+
|
4
|
+
module Utils
|
5
|
+
include Rack::Utils
|
6
|
+
|
7
|
+
def requestify(value, prefix = nil)
|
8
|
+
case value
|
9
|
+
when Array
|
10
|
+
value.map do |v|
|
11
|
+
requestify(v, "#{prefix}[]")
|
12
|
+
end.join("&")
|
13
|
+
when Hash
|
14
|
+
value.map do |k, v|
|
15
|
+
requestify(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
|
16
|
+
end.join("&")
|
17
|
+
else
|
18
|
+
"#{prefix}=#{escape(value)}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module_function :requestify
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-test
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bryan Helmkamp
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-04 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Simple testing API built on Rack
|
17
|
+
email: bryan@brynary.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
- MIT-LICENSE.txt
|
25
|
+
files:
|
26
|
+
- History.txt
|
27
|
+
- Rakefile
|
28
|
+
- README.rdoc
|
29
|
+
- lib/rack
|
30
|
+
- lib/rack/test
|
31
|
+
- lib/rack/test/cookie_jar.rb
|
32
|
+
- lib/rack/test/methods.rb
|
33
|
+
- lib/rack/test/utils.rb
|
34
|
+
- lib/rack/test.rb
|
35
|
+
- MIT-LICENSE.txt
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://github.com/brynary/rack-test
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
version:
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
requirements: []
|
56
|
+
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.3.1
|
59
|
+
signing_key:
|
60
|
+
specification_version: 2
|
61
|
+
summary: Simple testing API built on Rack
|
62
|
+
test_files: []
|
63
|
+
|