rack-test_app 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE.txt +21 -0
- data/README.md +122 -0
- data/Rakefile +49 -0
- data/lib/rack/test_app.rb +487 -0
- data/rack-test_app.gemspec +31 -0
- data/test/rack/test_app/MultipartBuilder_test.rb +158 -0
- data/test/rack/test_app/Result_test.rb +184 -0
- data/test/rack/test_app/TestApp_test.rb +238 -0
- data/test/rack/test_app/Util_test.rb +168 -0
- data/test/rack/test_app/Wrapper_test.rb +182 -0
- data/test/rack/test_app/data/example1.jpg +0 -0
- data/test/rack/test_app/data/example1.png +0 -0
- data/test/rack/test_app/data/multipart.form +0 -0
- data/test/test_helper.rb +4 -0
- metadata +116 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rack/test_app'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rack-test_app"
|
8
|
+
spec.version = Rack::TestApp::VERSION
|
9
|
+
spec.authors = ["makoto kuwata"]
|
10
|
+
spec.email = ["kwa@kuwata-lab.com"]
|
11
|
+
spec.summary = "more intuitive testing helper library for Rack app"
|
12
|
+
spec.description = <<END
|
13
|
+
Rack::TestApp is another testing helper library for Rack application.
|
14
|
+
IMO it is more intuitive than Rack::Test.
|
15
|
+
END
|
16
|
+
spec.homepage = "https://github.com/kwatch/rack-test_app"
|
17
|
+
spec.license = "MIT-LICENCE"
|
18
|
+
spec.files = Dir[*%w[
|
19
|
+
README.md MIT-LICENSE.txt Rakefile rack-test_app.gemspec
|
20
|
+
lib/rack/test_app.rb
|
21
|
+
test/test_helper.rb
|
22
|
+
test/rack/**/*_test.rb
|
23
|
+
test/rack/test_app/data/**/*.*
|
24
|
+
]]
|
25
|
+
spec.require_paths = ["lib"]
|
26
|
+
spec.required_ruby_version = '>= 2.0'
|
27
|
+
spec.add_runtime_dependency 'rack'
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
29
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
30
|
+
spec.add_development_dependency "minitest"
|
31
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
###
|
4
|
+
### $Release: 1.0.0 $
|
5
|
+
### $Copyright: copyright(c) 2015 kuwata-lab.com all rights reserved $
|
6
|
+
### $License: MIT License $
|
7
|
+
###
|
8
|
+
|
9
|
+
|
10
|
+
require_relative '../../test_helper'
|
11
|
+
|
12
|
+
require 'tempfile'
|
13
|
+
require 'rack/multipart'
|
14
|
+
require 'rack/mock'
|
15
|
+
require 'rack/request'
|
16
|
+
|
17
|
+
|
18
|
+
describe Rack::TestApp::MultipartBuilder do
|
19
|
+
|
20
|
+
|
21
|
+
describe '#initialize()' do
|
22
|
+
|
23
|
+
it "[!ajfgl] sets random string as boundary when boundary is nil." do
|
24
|
+
arr = []
|
25
|
+
1000.times do
|
26
|
+
mp = Rack::TestApp::MultipartBuilder.new(nil)
|
27
|
+
refute_nil mp.boundary
|
28
|
+
assert_kind_of String, mp.boundary
|
29
|
+
arr << mp.boundary
|
30
|
+
end
|
31
|
+
assert_equal 1000, arr.sort.uniq.length
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
describe '#add()' do
|
38
|
+
|
39
|
+
it "[!tp4bk] detects content type from filename when filename is not nil." do
|
40
|
+
mp = Rack::TestApp::MultipartBuilder.new
|
41
|
+
mp.add("name1", "value1")
|
42
|
+
mp.add("name2", "value2", "foo.csv")
|
43
|
+
mp.add("name3", "value3", "bar.csv", "text/plain")
|
44
|
+
expected = [
|
45
|
+
["name1", "value1", nil, nil],
|
46
|
+
#["name2", "value2", "foo.csv", "text/comma-separated-values"],
|
47
|
+
["name2", "value2", "foo.csv", "text/csv"],
|
48
|
+
["name3", "value3", "bar.csv", "text/plain"],
|
49
|
+
]
|
50
|
+
assert_equal expected, mp.instance_variable_get('@params')
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
describe '#add_file()' do
|
57
|
+
|
58
|
+
data_dir = File.join(File.dirname(__FILE__), 'data')
|
59
|
+
filename1 = File.join(data_dir, 'example1.png')
|
60
|
+
filename2 = File.join(data_dir, 'example1.jpg')
|
61
|
+
datafile = File.join(data_dir, 'multipart.form')
|
62
|
+
multipart_data = File.open(datafile, 'rb') {|f| f.read }
|
63
|
+
|
64
|
+
it "[!uafqa] detects content type from filename when content type is not provided." do
|
65
|
+
file1 = File.open(filename1)
|
66
|
+
file2 = File.open(filename2)
|
67
|
+
begin
|
68
|
+
mp = Rack::TestApp::MultipartBuilder.new
|
69
|
+
mp.add_file('image1', file1)
|
70
|
+
mp.add_file('image2', file2)
|
71
|
+
params = mp.instance_variable_get('@params')
|
72
|
+
assert_equal "example1.png" , params[0][2]
|
73
|
+
assert_equal "image/png" , params[0][3]
|
74
|
+
assert_equal "example1.jpg" , params[1][2]
|
75
|
+
assert_equal "image/jpeg" , params[1][3]
|
76
|
+
ensure
|
77
|
+
[file1, file2].each {|f| f.close() unless f.closed? }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "[!b5811] reads file content and adds it as param value." do
|
82
|
+
file1 = File.open(filename1)
|
83
|
+
file2 = File.open(filename2)
|
84
|
+
begin
|
85
|
+
boundary = '---------------------------68927884511827559971471404947'
|
86
|
+
mp = Rack::TestApp::MultipartBuilder.new(boundary)
|
87
|
+
mp.add('text1', "test1")
|
88
|
+
mp.add('text2', "日本語\r\nあいうえお\r\n")
|
89
|
+
mp.add_file('file1', file1)
|
90
|
+
mp.add_file('file2', file2)
|
91
|
+
expected = multipart_data
|
92
|
+
assert expected, mp.to_s
|
93
|
+
ensure
|
94
|
+
[file1, file2].each {|f| f.close() unless f.closed? }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "[!36bsu] closes opened file automatically." do
|
99
|
+
file1 = File.open(filename1)
|
100
|
+
file2 = File.open(filename2)
|
101
|
+
begin
|
102
|
+
assert_equal false, file1.closed?
|
103
|
+
assert_equal false, file2.closed?
|
104
|
+
mp = Rack::TestApp::MultipartBuilder.new()
|
105
|
+
mp.add_file('file1', file1)
|
106
|
+
mp.add_file('file2', file2)
|
107
|
+
assert_equal true, file1.closed?
|
108
|
+
assert_equal true, file2.closed?
|
109
|
+
ensure
|
110
|
+
[file1, file2].each {|f| f.close() unless f.closed? }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
describe '#to_s()' do
|
118
|
+
|
119
|
+
it "[!61gc4] returns multipart form string." do
|
120
|
+
mp = Rack::TestApp::MultipartBuilder.new("abc123")
|
121
|
+
mp.add("name1", "value1")
|
122
|
+
mp.add("name2", "value2", "foo.txt", "text/plain")
|
123
|
+
s = mp.to_s
|
124
|
+
expected = [
|
125
|
+
"--abc123\r\n",
|
126
|
+
"Content-Disposition: form-data; name=\"name1\"\r\n",
|
127
|
+
"\r\n",
|
128
|
+
"value1\r\n",
|
129
|
+
"--abc123\r\n",
|
130
|
+
"Content-Disposition: form-data; name=\"name2\"; filename=\"foo.txt\"\r\n",
|
131
|
+
"Content-Type: text/plain\r\n",
|
132
|
+
"\r\n",
|
133
|
+
"value2\r\n",
|
134
|
+
"--abc123--\r\n",
|
135
|
+
].join()
|
136
|
+
s = mp.to_s
|
137
|
+
assert_equal expected, s
|
138
|
+
#
|
139
|
+
opts = {
|
140
|
+
:method => "POST",
|
141
|
+
:input => s,
|
142
|
+
"CONTENT_TYPE" => "multipart/form-data; boundary=abc123",
|
143
|
+
"CONTENT_LENGTH" => s.bytesize,
|
144
|
+
}
|
145
|
+
env = Rack::MockRequest.env_for('http://localhost/form', opts)
|
146
|
+
req = Rack::Request.new(env)
|
147
|
+
params = req.POST
|
148
|
+
assert_equal "value1", params["name1"]
|
149
|
+
assert_equal "name2", params["name2"][:name]
|
150
|
+
assert_equal "foo.txt", params["name2"][:filename]
|
151
|
+
assert_equal "text/plain", params["name2"][:type]
|
152
|
+
assert_kind_of Tempfile, params["name2"][:tempfile]
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
###
|
4
|
+
### $Release: 1.0.0 $
|
5
|
+
### $Copyright: copyright(c) 2015 kuwata-lab.com all rights reserved $
|
6
|
+
### $License: MIT License $
|
7
|
+
###
|
8
|
+
|
9
|
+
|
10
|
+
require_relative '../../test_helper'
|
11
|
+
|
12
|
+
|
13
|
+
describe Rack::TestApp::Result do
|
14
|
+
|
15
|
+
|
16
|
+
describe '#initialize()' do
|
17
|
+
|
18
|
+
it "[!3lcsj] accepts response status, headers and body." do
|
19
|
+
r = Rack::TestApp::Result.new(200, {"Content-Type"=>"text/plain"}, ["Hello"])
|
20
|
+
assert 200, r.status
|
21
|
+
assert({"Content-Type"=>"text/plain"}, r.headers)
|
22
|
+
assert ["Hello"], r.body
|
23
|
+
end
|
24
|
+
|
25
|
+
it "[!n086q] parses 'Set-Cookie' header." do
|
26
|
+
headers = {
|
27
|
+
"Content-Type"=>"text/plain",
|
28
|
+
"Set-Cookie"=>("key1=value1; Path=/; Domain=example.com; HttpOnly; Secure\n" +
|
29
|
+
"key2=value2"),
|
30
|
+
}
|
31
|
+
expected = {
|
32
|
+
'key1' => {
|
33
|
+
:name => 'key1',
|
34
|
+
:value => 'value1',
|
35
|
+
:path => '/',
|
36
|
+
:domain => 'example.com',
|
37
|
+
:httponly => true,
|
38
|
+
:secure => true,
|
39
|
+
},
|
40
|
+
'key2' => {
|
41
|
+
:name => 'key2',
|
42
|
+
:value => 'value2',
|
43
|
+
},
|
44
|
+
}
|
45
|
+
r = Rack::TestApp::Result.new(200, headers, ["Hello"])
|
46
|
+
assert_equal expected, r.cookies
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
describe '#body_binary' do
|
53
|
+
|
54
|
+
it "[!mb0i4] returns body as binary string." do
|
55
|
+
r = Rack::TestApp::Result.new(200, {}, ["Hello"])
|
56
|
+
assert_equal "Hello", r.body_binary
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
describe '#body_text' do
|
63
|
+
|
64
|
+
it "[!vkj9h] returns body as text string, according to 'charset' in 'Content-Type'." do
|
65
|
+
headers = {'Content-Type' => 'text/plain; charset=utf-8'}
|
66
|
+
r = Rack::TestApp::Result.new(200, headers, ["Hello"])
|
67
|
+
assert_equal "Hello", r.body_text
|
68
|
+
end
|
69
|
+
|
70
|
+
it "[!rr18d] error when 'Content-Type' header is missing." do
|
71
|
+
headers = {}
|
72
|
+
r = Rack::TestApp::Result.new(200, headers, ["Hello"])
|
73
|
+
ex = assert_raises(TypeError) { r.body_text }
|
74
|
+
assert_equal "body_text(): missing 'Content-Type' header.", ex.message
|
75
|
+
end
|
76
|
+
|
77
|
+
it "[!dou1n] converts body text according to 'charset' in 'Content-Type' header." do
|
78
|
+
headers = {'Content-Type' => 'text/plain; charset=utf-8'}
|
79
|
+
binary = "\u3042\u3044\u3046\u3048\u304A"
|
80
|
+
assert_equal binary, "あいうえお".encode('utf-8')
|
81
|
+
r = Rack::TestApp::Result.new(200, headers, [binary])
|
82
|
+
assert_equal "あいうえお", r.body_text
|
83
|
+
assert_equal 'UTF-8', r.body_text.encoding.name
|
84
|
+
end
|
85
|
+
|
86
|
+
it "[!cxje7] assumes charset as 'utf-8' when 'Content-Type' is json." do
|
87
|
+
headers = {'Content-Type' => 'application/json'}
|
88
|
+
binary = %Q`{"msg":"\u3042\u3044\u3046\u3048\u304A"}`
|
89
|
+
assert_equal binary, %Q`{"msg":"あいうえお"}`.encode('utf-8')
|
90
|
+
r = Rack::TestApp::Result.new(200, headers, [binary])
|
91
|
+
assert_equal %Q`{"msg":"あいうえお"}`, r.body_text
|
92
|
+
assert_equal 'UTF-8', r.body_text.encoding.name
|
93
|
+
end
|
94
|
+
|
95
|
+
it "[!n4c71] error when non-json 'Content-Type' header has no 'charset'." do
|
96
|
+
headers = {'Content-Type' => 'text/plain'}
|
97
|
+
binary = "\u3042\u3044\u3046\u3048\u304A"
|
98
|
+
assert_equal binary, "あいうえお".encode('utf-8')
|
99
|
+
r = Rack::TestApp::Result.new(200, headers, [binary])
|
100
|
+
ex = assert_raises(TypeError) { r.body_text }
|
101
|
+
assert_equal "body_text(): missing 'charset' in 'Content-Type' header.", ex.message
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
describe '#body_json' do
|
108
|
+
|
109
|
+
it "[!qnic1] returns Hash object representing JSON string." do
|
110
|
+
headers = {'Content-Type' => 'application/json'}
|
111
|
+
binary = %Q`{"msg":"\u3042\u3044\u3046\u3048\u304A"}`
|
112
|
+
assert_equal binary, %Q`{"msg":"あいうえお"}`.encode('utf-8')
|
113
|
+
r = Rack::TestApp::Result.new(200, headers, [binary])
|
114
|
+
assert_equal({"msg"=>"あいうえお"}, r.body_json)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
describe '#content_type' do
|
121
|
+
|
122
|
+
it "[!40hcz] returns 'Content-Type' header value." do
|
123
|
+
headers = {'Content-Type' => 'application/json'}
|
124
|
+
r = Rack::TestApp::Result.new(200, headers, [])
|
125
|
+
assert_equal "application/json", r.content_type
|
126
|
+
#
|
127
|
+
headers = {'content-type' => 'application/json'}
|
128
|
+
r = Rack::TestApp::Result.new(200, headers, [])
|
129
|
+
assert_equal "application/json", r.content_type
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
describe '' do
|
136
|
+
|
137
|
+
it "[!5lb19] returns 'Content-Length' header value as integer." do
|
138
|
+
headers = {'Content-Length' => '123'}
|
139
|
+
r = Rack::TestApp::Result.new(200, headers, [])
|
140
|
+
assert_equal 123, r.content_length
|
141
|
+
#
|
142
|
+
headers = {'content-length' => '123'}
|
143
|
+
r = Rack::TestApp::Result.new(200, headers, [])
|
144
|
+
assert_equal 123, r.content_length
|
145
|
+
end
|
146
|
+
|
147
|
+
it "[!qjktz] returns nil when 'Content-Length' is not set." do
|
148
|
+
headers = {'Content-Type' => 'text/plain'}
|
149
|
+
r = Rack::TestApp::Result.new(200, headers, ["Hello"])
|
150
|
+
assert_nil r.content_length
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
describe '#location' do
|
157
|
+
|
158
|
+
it "[!8y8lg] returns 'Location' header value." do
|
159
|
+
headers = {'Location' => '/foo'}
|
160
|
+
r = Rack::TestApp::Result.new(302, headers, [])
|
161
|
+
assert_equal '/foo', r.location
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
describe '#cookie_value' do
|
168
|
+
|
169
|
+
it "[!neaf8] returns cookie value if exists." do
|
170
|
+
headers = {'Set-Cookie' => 'name1=value1'}
|
171
|
+
r = Rack::TestApp::Result.new(200, headers, [])
|
172
|
+
assert_equal 'value1', r.cookie_value('name1')
|
173
|
+
end
|
174
|
+
|
175
|
+
it "[!oapns] returns nil if cookie not exists." do
|
176
|
+
headers = {'Set-Cookie' => 'name1=value1'}
|
177
|
+
r = Rack::TestApp::Result.new(200, headers, [])
|
178
|
+
assert_equal nil, r.cookie_value('name2')
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
end
|
@@ -0,0 +1,238 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
###
|
4
|
+
### $Release: 1.0.0 $
|
5
|
+
### $Copyright: copyright(c) 2015 kuwata-lab.com all rights reserved $
|
6
|
+
### $License: MIT License $
|
7
|
+
###
|
8
|
+
|
9
|
+
|
10
|
+
require_relative '../../test_helper'
|
11
|
+
|
12
|
+
|
13
|
+
describe Rack::TestApp do
|
14
|
+
|
15
|
+
class << self
|
16
|
+
alias context describe # minitest doesn't provide 'context' method
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
describe '::VERSION' do
|
21
|
+
|
22
|
+
it "represents release version number." do
|
23
|
+
expected = '$Release: 1.0.0 $'.split()[1]
|
24
|
+
assert_equal expected, Rack::TestApp::VERSION
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
describe '.new_env()' do
|
31
|
+
|
32
|
+
it "[!b3ts8] returns environ hash object." do
|
33
|
+
env = Rack::TestApp.new_env()
|
34
|
+
assert_kind_of Hash, env
|
35
|
+
assert_equal 'GET', env['REQUEST_METHOD']
|
36
|
+
assert_equal '/', env['PATH_INFO']
|
37
|
+
end
|
38
|
+
|
39
|
+
it "[!j879z] sets 'HTTPS' with 'on' when 'rack.url_scheme' is 'https'." do
|
40
|
+
env = Rack::TestApp.new_env(env: {'rack.url_scheme'=>'https'})
|
41
|
+
assert_equal 'on', env['HTTPS']
|
42
|
+
assert_equal 'https', env['rack.url_scheme']
|
43
|
+
end
|
44
|
+
|
45
|
+
it "[!vpwvu] sets 'HTTPS' with 'on' when 'HTTPS' is 'on'." do
|
46
|
+
env = Rack::TestApp.new_env(env: {'HTTPS'=>'on'})
|
47
|
+
assert_equal 'on', env['HTTPS']
|
48
|
+
assert_equal 'https', env['rack.url_scheme']
|
49
|
+
end
|
50
|
+
|
51
|
+
it "[!2uvyb] raises ArgumentError when both query string and 'query' kwarg specified." do
|
52
|
+
ex = assert_raises(ArgumentError) do
|
53
|
+
Rack::TestApp.new_env(:GET, '/path?x=1', query: {'y'=>2})
|
54
|
+
end
|
55
|
+
assert_equal "new_env(): not allowed both query string and 'query' kwarg at a time.", ex.message
|
56
|
+
end
|
57
|
+
|
58
|
+
it "[!8tq3m] accepts query string in path string." do
|
59
|
+
env = Rack::TestApp.new_env(:GET, '/path?x=1')
|
60
|
+
assert_equal 'x=1', env['QUERY_STRING']
|
61
|
+
end
|
62
|
+
|
63
|
+
context "[!d1c83] when 'form' kwarg specified..." do
|
64
|
+
|
65
|
+
it "[!c779l] raises ArgumentError when both 'form' and 'json' are specified." do
|
66
|
+
ex = assert_raises(ArgumentError) do
|
67
|
+
Rack::TestApp.new_env(form: {}, json: {})
|
68
|
+
end
|
69
|
+
assert_equal "new_env(): not allowed both 'form' and 'json' at a time.", ex.message
|
70
|
+
end
|
71
|
+
|
72
|
+
it "[!5iv35] sets content type with 'application/x-www-form-urlencoded'." do
|
73
|
+
env = Rack::TestApp.new_env(form: {'x'=>1})
|
74
|
+
assert_equal 'application/x-www-form-urlencoded', env['CONTENT_TYPE']
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
context "[!prv5z] when 'json' kwarg specified..." do
|
80
|
+
|
81
|
+
it "[!2o0ph] raises ArgumentError when both 'json' and 'multipart' are specified." do
|
82
|
+
ex = assert_raises(ArgumentError) do
|
83
|
+
Rack::TestApp.new_env(json: {}, multipart: {})
|
84
|
+
end
|
85
|
+
assert_equal "new_env(): not allowed both 'json' and 'multipart' at a time.", ex.message
|
86
|
+
end
|
87
|
+
|
88
|
+
it "[!ta24a] sets content type with 'application/json'." do
|
89
|
+
env = Rack::TestApp.new_env(json: {'x'=>1})
|
90
|
+
assert_equal 'application/json', env['CONTENT_TYPE']
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
context "[!dnvgj] when 'multipart' kwarg specified..." do
|
96
|
+
|
97
|
+
it "[!b1d1t] raises ArgumentError when both 'multipart' and 'form' are specified." do
|
98
|
+
ex = assert_raises(ArgumentError) do
|
99
|
+
Rack::TestApp.new_env(multipart: {}, form: {})
|
100
|
+
end
|
101
|
+
assert_equal "new_env(): not allowed both 'multipart' and 'form' at a time.", ex.message
|
102
|
+
end
|
103
|
+
|
104
|
+
it "[!dq33d] sets content type with 'multipart/form-data'." do
|
105
|
+
env = Rack::TestApp.new_env(multipart: {})
|
106
|
+
assert_match /\Amultipart\/form-data; boundary=\S+\z/, env['CONTENT_TYPE']
|
107
|
+
end
|
108
|
+
|
109
|
+
it "[!gko8g] 'multipart:' kwarg accepts Hash object (which is converted into multipart data)." do
|
110
|
+
fpath = File.join(File.dirname(__FILE__), "data", "example1.jpg")
|
111
|
+
file = File.open(fpath, 'rb')
|
112
|
+
env = Rack::TestApp.new_env(multipart: {
|
113
|
+
"value" => 123,
|
114
|
+
"upload" => file,
|
115
|
+
})
|
116
|
+
assert_equal true, file.closed?
|
117
|
+
req = Rack::Request.new(env)
|
118
|
+
params = req.POST
|
119
|
+
assert_equal "123", params['value']
|
120
|
+
assert_equal "upload", params['upload'][:name]
|
121
|
+
assert_equal "example1.jpg", params['upload'][:filename]
|
122
|
+
assert_equal "image/jpeg", params['upload'][:type]
|
123
|
+
assert_kind_of Tempfile, params['upload'][:tempfile]
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
it "[!iamrk] uses 'application/x-www-form-urlencoded' as default content type of input." do
|
129
|
+
env = Rack::TestApp.new_env(:POST, '/', input: 'x=1')
|
130
|
+
assert_equal 'application/x-www-form-urlencoded', env['CONTENT_TYPE']
|
131
|
+
end
|
132
|
+
|
133
|
+
it "[!7hfri] converts input string into binary." do
|
134
|
+
form = {"x"=>"あいうえお"}
|
135
|
+
env = Rack::TestApp.new_env(:POST, '/api/hello', form: form)
|
136
|
+
s = env['rack.input'].read()
|
137
|
+
assert_equal Encoding::ASCII_8BIT, s.encoding
|
138
|
+
end
|
139
|
+
|
140
|
+
it "[!r3soc] converts query string into binary." do
|
141
|
+
query = {"x"=>"あいうえお"}
|
142
|
+
env = Rack::TestApp.new_env(:POST, '/api/hello', query: query)
|
143
|
+
s = env['QUERY_STRING']
|
144
|
+
assert_equal Encoding::ASCII_8BIT, s.encoding
|
145
|
+
end
|
146
|
+
|
147
|
+
it "[!na9w6] builds environ hash object." do
|
148
|
+
env = Rack::TestApp.new_env(:POST, '/api/session?q=test')
|
149
|
+
#
|
150
|
+
assert_equal Rack::VERSION , env['rack.version']
|
151
|
+
assert_kind_of Array , env['rack.version']
|
152
|
+
assert_match /\A\[1, \d+\]\z/, env['rack.version'].inspect
|
153
|
+
assert_kind_of StringIO , env['rack.input']
|
154
|
+
assert_kind_of StringIO , env['rack.errors']
|
155
|
+
assert_equal true , env['rack.multithread']
|
156
|
+
assert_equal true , env['rack.multiprocess']
|
157
|
+
assert_equal false , env['rack.run_once']
|
158
|
+
assert_equal 'http' , env['rack.url_scheme']
|
159
|
+
#
|
160
|
+
assert_equal 'POST' , env['REQUEST_METHOD']
|
161
|
+
assert_equal 'q=test' , env['QUERY_STRING']
|
162
|
+
assert_equal 'localhost' , env['SERVER_NAME']
|
163
|
+
assert_equal '80' , env['SERVER_PORT']
|
164
|
+
assert_equal 'q=test' , env['QUERY_STRING']
|
165
|
+
assert_equal '/api/session' , env['PATH_INFO']
|
166
|
+
assert_equal 'off' , env['HTTPS']
|
167
|
+
assert_equal '' , env['SCRIPT_NAME']
|
168
|
+
assert_equal '0' , env['CONTENT_LENGTH']
|
169
|
+
assert_equal nil , env['CONTENT_TYPE']
|
170
|
+
end
|
171
|
+
|
172
|
+
it "[!ezvdn] unsets CONTENT_TYPE when not input." do
|
173
|
+
env = Rack::TestApp.new_env(:POST, '/api/session?q=test')
|
174
|
+
assert_nil env['CONTENT_TYPE']
|
175
|
+
assert_equal false, env.key?('CONTENT_TYPE')
|
176
|
+
end
|
177
|
+
|
178
|
+
it "[!r4jz8] copies 'headers' kwarg content into environ with 'HTTP_' prefix." do
|
179
|
+
headers = {
|
180
|
+
'If-Modified-Since' => 'Mon, 02 Feb 2015 19:05:06 GMT',
|
181
|
+
'X-Requested-With' => 'XMLHttpRequest'
|
182
|
+
}
|
183
|
+
env = Rack::TestApp.new_env(:PUT, '/', headers: headers)
|
184
|
+
assert_equal 'Mon, 02 Feb 2015 19:05:06 GMT', env['HTTP_IF_MODIFIED_SINCE']
|
185
|
+
assert_equal 'XMLHttpRequest', env['HTTP_X_REQUESTED_WITH']
|
186
|
+
end
|
187
|
+
|
188
|
+
it "[!ai9t3] don't add 'HTTP_' to Content-Length and Content-Type headers." do
|
189
|
+
headers = {
|
190
|
+
'Content-Type' => 'application/json',
|
191
|
+
'Content-Length' => '123',
|
192
|
+
}
|
193
|
+
env = Rack::TestApp.new_env(:PUT, '/', headers: headers)
|
194
|
+
assert_equal 'application/json', env['CONTENT_TYPE']
|
195
|
+
assert_equal '123', env['CONTENT_LENGTH']
|
196
|
+
assert_equal false, env.key?('HTTP_CONTENT_TYPE')
|
197
|
+
assert_equal false, env.key?('HTTP_CONTENT_LENGTH')
|
198
|
+
end
|
199
|
+
|
200
|
+
it "[!a47n9] copies 'env' kwarg content into environ." do
|
201
|
+
environ = {
|
202
|
+
'rack.session' => {'k1'=>'v1'},
|
203
|
+
}
|
204
|
+
env = Rack::TestApp.new_env(:PUT, '/', env: environ)
|
205
|
+
expected = {'k1'=>'v1'}
|
206
|
+
assert_equal expected, env['rack.session']
|
207
|
+
end
|
208
|
+
|
209
|
+
it "[!pmefk] sets 'HTTP_COOKIE' when 'cookie' kwarg specified." do
|
210
|
+
env = Rack::TestApp.new_env(cookies: 'c1=v1')
|
211
|
+
assert_equal 'c1=v1', env['HTTP_COOKIE']
|
212
|
+
env = Rack::TestApp.new_env(cookies: {'c2'=>'v2'})
|
213
|
+
assert_equal 'c2=v2', env['HTTP_COOKIE']
|
214
|
+
end
|
215
|
+
|
216
|
+
it "[!qj7b8] cookie value can be {:name=>'name', :value=>'value'}." do
|
217
|
+
env = Rack::TestApp.new_env(cookies: {'c3'=>{name: 'c3', value: 'v3'}})
|
218
|
+
assert_equal 'c3=v3', env['HTTP_COOKIE']
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
describe '.wrap()' do
|
225
|
+
|
226
|
+
it "[!grqlf] creates new Wrapper object." do
|
227
|
+
app = proc {|env| [200, {}, []] }
|
228
|
+
env = {"HTTPS"=>"on"}
|
229
|
+
wrapper = Rack::TestApp.wrap(app, env)
|
230
|
+
assert_kind_of Rack::TestApp::Wrapper, wrapper
|
231
|
+
assert_equal app, wrapper.instance_variable_get('@app')
|
232
|
+
assert_equal env, wrapper.instance_variable_get('@env')
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
end
|