rack-radar 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,280 @@
1
+ require 'test_setup'
2
+
3
+ class CookiesTest
4
+ include Minispec
5
+
6
+ class App < Air
7
+
8
+ def index names
9
+ cookies.values_at(*names.split(',')).inspect
10
+ end
11
+
12
+ def post_index
13
+ post_params.each_pair do |n, v|
14
+ v.is_a?(Hash) &&
15
+ (expires = v['expires']) &&
16
+ (v['expires'] = ::Time.parse(expires))
17
+ response.set_cookie n, v
18
+ end
19
+ end
20
+
21
+ def delete_index names
22
+ names.split(',').each do |n|
23
+ response.delete_cookie n, params[n] || {}
24
+ end
25
+ end
26
+
27
+ def post_deeper__path
28
+ post_params.each_pair { |n, v| response.set_cookie n, v }
29
+ end
30
+
31
+ def deeper name
32
+ cookies[name]
33
+ end
34
+ end
35
+
36
+ helper :persisted? do
37
+ assert(cookies[@var]) == @val
38
+ end
39
+
40
+ helper :not_persisted do
41
+ is(cookies[@var]).nil?
42
+ end
43
+
44
+ helper :disposed? do
45
+ assert(last_response.body) == @expected
46
+ end
47
+
48
+ helper :not_disposed do
49
+ assert(last_response.body) == @expected_nil
50
+ end
51
+
52
+ before_all { app(App) }
53
+ before { cookies.clear }
54
+
55
+ context 'set/get via HTTP' do
56
+
57
+ before do
58
+ @var, @val = 2.times.map { 5.times.map { (('a'..'z').to_a + ('A'..'Z').to_a + (1..50).to_a)[rand(100)] }.join }
59
+ @expected, @expected_nil = [@val].inspect, [nil].inspect
60
+ end
61
+
62
+ should 'persist/dispose cause by default cookie`s path is set to current URI path' do
63
+ post @var => @val
64
+ is.persisted?
65
+
66
+ get @var
67
+ is.disposed?
68
+ end
69
+
70
+ should 'persist/dispose cause given path matches default cookie`s path' do
71
+ post @var => {:value => @val, :path => '/'}
72
+ is.persisted?
73
+
74
+ get @var
75
+ is.disposed?
76
+ end
77
+
78
+ should 'NOT persist/dispose cause wrong path provided - /blah is not a prefix of /' do
79
+ post @var => {:value => @val, :path => '/blah'}
80
+ assure.not_persisted
81
+
82
+ get @var
83
+ assure.not_disposed
84
+ end
85
+
86
+ should 'persist/dispose cause /deeper is a prefix of /deeper/path' do
87
+ post '/deeper/path', @var => @val
88
+ is.persisted?
89
+
90
+ get '/deeper', @var
91
+ assert(last_response.body) == @val
92
+ end
93
+
94
+ should 'persist but not dispose cause path set automatically to /deeper, and it is not a prefix for /' do
95
+ post '/deeper/path', @var => @val
96
+ is.persisted?
97
+
98
+ get @var
99
+ assure.not_disposed
100
+ end
101
+
102
+ should 'persist and dispose for /deeper path' do
103
+ post '/deeper/path', @var => @val
104
+ is.persisted?
105
+
106
+ get '/deeper', @var
107
+ assert(last_response.body) == @val
108
+ end
109
+
110
+ should 'persist/dispose cause path set to /' do
111
+ post '/deeper/path', @var => {:value => @val, :path => '/'}
112
+ is.persisted?
113
+
114
+ get @var
115
+ is.disposed?
116
+ end
117
+
118
+ should 'NOT dispose - expires is in past' do
119
+ post @var => {:value => @val, :expires => ::Rack::Utils.rfc2822(::Time.now.gmtime - 1)}
120
+ is.persisted?
121
+
122
+ get @var
123
+ assure.not_disposed
124
+ end
125
+
126
+ should 'NOT persist/dispose cause inner domain given' do
127
+ post @var => {:value => @val, :domain => 'x.org'}
128
+ assure.not_persisted
129
+
130
+ get @var
131
+ assure.not_disposed
132
+ end
133
+
134
+ should 'persist/dispose when domains matches' do
135
+ header['HTTP_HOST'] = 'some.tld'
136
+ post 'http://' + header['HTTP_HOST'], @var => @val
137
+ get 'http://' + header['HTTP_HOST'], @var
138
+ is.disposed?
139
+ headers.delete 'HTTP_HOST'
140
+ end
141
+
142
+ should 'prefer more specific cookies' do
143
+ domain = 'http://foo.bar'
144
+ subdomain = 'http://a.foo.bar'
145
+
146
+ header['HTTP_HOST'] = 'a.foo.bar'
147
+ post subdomain, 'var' => subdomain
148
+
149
+ header['HTTP_HOST'] = 'foo.bar'
150
+ post domain, 'var' => domain
151
+
152
+ get domain, 'var'
153
+ is(last_response.body) == [domain].inspect
154
+
155
+ header['HTTP_HOST'] = 'a.foo.bar'
156
+ get subdomain, 'var'
157
+ is(last_response.body) == [subdomain].inspect
158
+ headers.delete 'HTTP_HOST'
159
+ end
160
+
161
+ should 'NOT persist/dispose cause secure cookie are accessed via un-secure connection' do
162
+ post @var => {:value => @val, :secure => 'true'}
163
+ is(cookies[@var]).nil?
164
+
165
+ get @var
166
+ assure.not_disposed
167
+ end
168
+
169
+ should 'persist/dispose cause secure cookie are accessed via secure connection' do
170
+ s_post @var => {:value => @val, :secure => 'true'}
171
+ is(cookies[@var]) == @val
172
+
173
+ s_get @var
174
+ expect(last_response.body) == @expected
175
+ end
176
+
177
+ should 'delete a cookie' do
178
+
179
+ post @var => @val
180
+ get @var
181
+ is.persisted?
182
+
183
+ delete @var
184
+ get @var
185
+ assure.not_disposed
186
+ end
187
+
188
+ should 'set/get multiple cookies at once' do
189
+ vars, vals = 2.times.map { 5.times.map { 5.times.map { ('a'..'z').to_a[rand(26)] }.join } }
190
+ params = Hash[vars.zip vals]
191
+ post params
192
+ get vars.join(',')
193
+ assert(last_response.body) == params.values_at(*vars).inspect
194
+ end
195
+ end
196
+
197
+ context 'jars are domain specific' do
198
+
199
+ should 'use separate jar for each domain' do
200
+
201
+ header['HTTP_HOST'] = 'foo.bar'
202
+ domain = 'http://' + header['HTTP_HOST']
203
+ post domain, 'var' => domain
204
+ get domain, 'var'
205
+ is(last_response.body) == [domain].inspect
206
+ headers.delete 'HTTP_HOST'
207
+
208
+ header['HTTP_HOST'] = 'bar.foo'
209
+ domain = 'http://' + header['HTTP_HOST']
210
+ post domain, 'var' => domain
211
+ get domain, 'var'
212
+ is(last_response.body) == [domain].inspect
213
+ headers.delete 'HTTP_HOST'
214
+
215
+ header['HTTP_HOST'] = 'foo.bar'
216
+ domain = 'http://' + header['HTTP_HOST']
217
+ get domain, 'var'
218
+ is(last_response.body) == [domain].inspect
219
+ headers.delete 'HTTP_HOST'
220
+ end
221
+
222
+ should 'use same jar for a domain and its subdomains' do
223
+ %w[a b c a.b a.b.c].each do |subdomain|
224
+ header['HTTP_HOST'] = '%s.foo.bar' % subdomain
225
+ domain = 'http://' + header['HTTP_HOST']
226
+ get domain, 'var'
227
+ is(last_response.body) == ['http://foo.bar'].inspect
228
+ headers.delete 'HTTP_HOST'
229
+ end
230
+ end
231
+
232
+ should 'domains names are case insensitive' do
233
+ %w[BAR.foo bar.FOO BAR.FOO].each do |host|
234
+ header['HTTP_HOST'] = host
235
+ domain = 'http://' + header['HTTP_HOST']
236
+ get domain, 'var'
237
+ is(last_response.body) == ['http://bar.foo'].inspect
238
+ headers.delete 'HTTP_HOST'
239
+ end
240
+ end
241
+
242
+ end
243
+
244
+ context 'set/get directly' do
245
+
246
+ before_all { app(App) }
247
+
248
+ should 'set/get cookies properly' do
249
+ n, size = 10, cookies.size
250
+ n.times do
251
+ var, val = 2.times.map { 5.times.map { ('a'..'z').to_a[rand(26)] }.join }
252
+ cookies[var] = val
253
+ expect(cookies[var]) == val
254
+ end
255
+ expect(cookies.size) == size + n
256
+ end
257
+
258
+ should 'delete a cookie' do
259
+
260
+ cookies['foo'] = 'bar'
261
+ expect(cookies['foo']) == 'bar'
262
+
263
+ cookies.delete 'foo'
264
+ is(cookies['foo']).nil?
265
+ end
266
+
267
+ should 'clear cookies' do
268
+ cookies.clear
269
+ expect(cookies.size) == 0
270
+ end
271
+
272
+ should 'escape values' do
273
+ cookies['var'] = 'foo;bar'
274
+ expect(cookies['var']) == 'foo;bar'
275
+
276
+ cookies['var'] = ';bar;foo;'
277
+ expect(cookies['var']) == ';bar;foo;'
278
+ end
279
+ end
280
+ end
@@ -0,0 +1,44 @@
1
+ require 'test_setup'
2
+
3
+ class FollowRedirectTest
4
+ include Minispec
5
+
6
+ class App < Air
7
+
8
+ def index
9
+ redirect :destination
10
+ end
11
+
12
+ def destination
13
+ __method__
14
+ end
15
+ end
16
+
17
+ before_all { app(App) }
18
+
19
+ should 'follow redirect' do
20
+
21
+ get
22
+ is(last_response.status) == 302
23
+
24
+ follow_redirect!
25
+ is(last_response.status) == 200
26
+ is(last_response.body) == 'destination'
27
+ end
28
+
29
+ should 'keep scheme' do
30
+ s_get
31
+ is(last_response.status) == 302
32
+
33
+ follow_redirect!
34
+ is(last_request.env['HTTPS']) == 'on'
35
+ is(last_response.status) == 200
36
+ is(last_response.body) == 'destination'
37
+ end
38
+
39
+ should 'raise an error if last response is not an redirect' do
40
+ get :destination
41
+ does { follow_redirect! }.raise_error?
42
+ end
43
+
44
+ end
@@ -0,0 +1,82 @@
1
+ require 'test_setup'
2
+
3
+ class HeadersTest
4
+ include Minispec
5
+
6
+ class App < Air
7
+
8
+ def index headers
9
+ env.values_at(*headers.split(',')).inspect
10
+ end
11
+
12
+ def post_index
13
+ content_type
14
+ end
15
+
16
+ def dry
17
+ end
18
+
19
+ def post_dry
20
+ end
21
+ end
22
+
23
+ before_all { app(App) }
24
+
25
+ testing 'User-Agent' do
26
+
27
+ ua = 'Chrome'
28
+ header['User-Agent'] = ua
29
+ get 'HTTP_USER_AGENT'
30
+ is(last_response.body) == [ua].inspect
31
+
32
+ ua = 'Safari'
33
+ header['User-Agent'] = ua
34
+ get 'HTTP_USER_AGENT'
35
+ is(last_response.body) == [ua].inspect
36
+ end
37
+
38
+ testing 'Content-Type' do
39
+ ct = 'text/plain'
40
+ header['Content-Type'] = ct
41
+ get 'CONTENT_TYPE'
42
+ is(last_response.body) == [ct].inspect
43
+ end
44
+
45
+ should 'not override explicit CONTENT_TYPE on POST requests' do
46
+ ct = 'text/plain'
47
+ header['Content-Type'] = ct
48
+ post
49
+ is(last_response.body) == ct
50
+ end
51
+
52
+ should 'have 127.0.0.1 as default REMOTE_ADDR' do
53
+ get
54
+ expect(last_request.env['REMOTE_ADDR']) == '127.0.0.1'
55
+ end
56
+
57
+ should 'use default SERVER_NAME' do
58
+ get
59
+ expect(last_request.env['SERVER_NAME']) == Rack::Radar::RACK_RADAR__DEFAULT_HOST
60
+ end
61
+
62
+ context 'Rack-related headers' do
63
+
64
+ it 'should override default rack.input' do
65
+ header['rack.input'] = StringIO.new('someString')
66
+ get :dry
67
+ is(last_request.env['rack.input']) == header['rack.input']
68
+ end
69
+
70
+ should 'not add multipart content type on post requests' do
71
+ post :dry
72
+ refute(last_request.env['CONTENT_TYPE']) =~ /x\-www\-form\-urlencoded/
73
+ end
74
+
75
+ should 'keep explicitly set rack.errors' do
76
+ errors = StringIO.new
77
+ header['rack.errors'] = errors
78
+ get
79
+ expect { last_request.env['rack.errors'].__id__ } == errors.__id__
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,64 @@
1
+ require 'test_setup'
2
+
3
+ class MapTest
4
+ include Minispec
5
+
6
+ class App < Air
7
+
8
+ def news a1
9
+ a1
10
+ end
11
+ end
12
+
13
+ before_all { app(App) }
14
+
15
+ testing 'without map' do
16
+ get '/news/1'
17
+ is(last_response).ok?
18
+ is(last_response.body) == '1'
19
+ end
20
+
21
+ it 'should work only with arguments' do
22
+ map '/news'
23
+ get 1
24
+ is(last_response).ok?
25
+ is(last_response.body) == '1'
26
+ end
27
+
28
+ it 'should work without arguments' do
29
+ map '/news/foo'
30
+ get
31
+ expect(last_response.status) == 200
32
+ is(last_response.body) == 'foo'
33
+ end
34
+
35
+ it 'should require full url when map set to nil' do
36
+ map nil
37
+ get
38
+ is(last_response).not_found?
39
+
40
+ get 'foo'
41
+ is(last_response).not_found?
42
+
43
+ get '/news/foo'
44
+ is(last_response).ok?
45
+ end
46
+
47
+ it 'should ignore base URL set by map' do
48
+ map '/blah'
49
+
50
+ get 'news/foo'
51
+ is(last_response).not_found?
52
+
53
+ get '/news/foo'
54
+ is(last_response).ok?
55
+
56
+ get 'http://blah.org/news/foo'
57
+ is(last_response).not_found?
58
+
59
+ header['HTTP_HOST'] = 'blah.org'
60
+ get 'http://blah.org/news/foo'
61
+ is(last_response).ok?
62
+ end
63
+
64
+ end