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