rack-radar 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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