optionsful 0.2.3 → 0.3.0

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.
@@ -1,329 +1,443 @@
1
- require File.dirname(__FILE__) + '/spec_helper'
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ include Rack::Test::Methods
3
+ require 'fileutils'
2
4
 
3
-
4
- describe Baurets::Optionsful::Server do
5
-
6
- include Rack::Test::Methods
5
+ describe "Optionsful" do
7
6
 
8
7
  context "as a Rack middleware" do
9
8
 
10
- it "is a Ruby object that responds to call;" do
11
- assert ::Baurets::Optionsful::Server.new(app).respond_to? :call
9
+ it "is a Ruby object that responds to call" do
10
+ ::Baurets::Optionsful::Server.new(app).respond_to?(:call).should be true
12
11
  end
13
12
 
14
- it "takes exactly one argument, (the environment) and returns an Array;" do
13
+ it "takes exactly one argument, (the environment) and returns an Array" do
15
14
  response = ::Baurets::Optionsful::Server.new(app).call(mock_env({"REQUEST_METHOD" => "OPTIONS", "PATH_INFO" => "/posts"}))
16
- assert response.kind_of?(Array)
15
+ response.should be_a_kind_of Array
17
16
  end
18
17
 
19
- it "the returned Array must have exactly three values: the status, the headers and the body;" do
18
+ it "the returned Array must have exactly three values: the status, the headers and the body" do
20
19
  response = ::Baurets::Optionsful::Server.new(app).call(mock_env({"REQUEST_METHOD" => "OPTIONS", "PATH_INFO" => "/posts"}))
21
- assert response.size.should == 3
22
- assert response[0].kind_of? Fixnum
23
- assert response[1].kind_of? Hash
24
- assert response[2].kind_of? String
20
+ validate_response(response)
25
21
  end
26
22
 
27
23
  before do
28
- ActionController::Routing::Routes.draw do |map|
29
- map.resources :posts, :has_many => :comments
24
+ rails_app.routes.draw do
25
+ resources :posts
30
26
  end
31
27
  end
32
28
 
33
- it "must be nice, acting somewhere on a Rack middleware stack;" do
29
+ it "must be nice, acting somewhere on a Rack middleware stack" do
34
30
  response = fake_opts_app.call(mock_env({"REQUEST_METHOD" => "OPTIONS", "PATH_INFO" => "/posts"}))
35
- assert response.size.should == 3
36
- assert response[0].kind_of? Fixnum
37
- assert response[0].should == 204
38
- assert response[1].kind_of? Hash
39
- assert response[1]["Allow"]
31
+ validate_response(response)
32
+ response[0].should be 204
33
+ response[1]["Allow"].should_not be nil
40
34
  end
41
35
 
42
36
  it "must let the request go through the stack, if it has nothing to it!" do
43
37
  response = fake_opts_app.call(mock_env({"REQUEST_METHOD" => "GET", "PATH_INFO" => "/lobster"}))
44
- assert response.size.should == 3
45
- assert response[0].kind_of? Fixnum
46
- assert response[0].should == 200
47
- assert response[1].kind_of? Hash
38
+ validate_response(response)
39
+ response[0].should be 200
48
40
  end
49
41
 
50
42
  end
51
43
 
52
- context "as an interpreter for HTTP OPTIONS requests, MUST recognize the Rails" do
44
+ context "as an HTTP OPTIONS verb provider must master Rails" do
53
45
 
54
- describe "default resource routing" do
55
- #Sample resource route (maps HTTP verbs to controller actions automatically)
46
+ describe "default resources routing" do
56
47
 
57
48
  before(:all) do
58
- ActionController::Routing::Routes.draw do |map|
59
- map.resources :posts, :has_many => :comments
49
+ rails_app.routes.draw do
50
+ resources :posts
60
51
  end
61
52
  end
62
53
 
63
54
  it "the index action displays a list of all posts in response of a GET request" do
64
55
  response = http_options_request("/posts")
65
- assert response.kind_of?(Array)
66
- assert allows?(response[1], "GET")
56
+ validate_response(response)
57
+ response[0].should be 204
58
+ response[1]["Allow"].should include "GET"
67
59
  end
68
60
 
69
61
  it "the new action return from a GET request an HTML form for creating a new post" do
70
62
  response = http_options_request("/posts/new")
71
- assert response.kind_of?(Array)
72
- assert allows?(response[1], "GET")
63
+ validate_response(response)
64
+ response[0].should be 204
65
+ response[1]["Allow"].should include "GET"
66
+ response[1]["Allow"].should_not include "POST"
73
67
  end
74
68
 
75
69
  it "the create action uses POST to create a new post instance" do
76
70
  response = http_options_request("/posts")
77
- assert response.kind_of?(Array)
78
- assert allows?(response[1], "POST")
71
+ validate_response(response)
72
+ response[0].should be 204
73
+ response[1]["Allow"].should include "POST"
79
74
  end
80
75
 
81
76
  it "the show action display a specific post in response of a GET request" do
82
77
  response = http_options_request("/posts/1")
83
- assert response.kind_of?(Array)
84
- assert allows?(response[1], "GET")
78
+ validate_response(response)
79
+ response[0].should be 204
80
+ response[1]["Allow"].should include "GET"
85
81
  end
86
82
 
87
83
  it "the edit action return an HTML form for editing a post in response of a GET request" do
88
84
  response = http_options_request("/posts/1/edit")
89
- assert response.kind_of?(Array)
90
- assert allows?(response[1], "GET")
85
+ validate_response(response)
86
+ response[0].should be 204
87
+ response[1]["Allow"].should include "GET"
91
88
  end
92
89
 
93
90
  it "the update action uses PUT to update a specific post" do
94
91
  response = http_options_request("/posts/1")
95
- assert response.kind_of?(Array)
96
- assert allows?(response[1], "PUT")
92
+ validate_response(response)
93
+ response[0].should be 204
94
+ response[1]["Allow"].should include "PUT"
97
95
  end
98
96
 
99
97
  it "the destroy action uses DELETE to delete a specific post" do
100
98
  response = http_options_request("/posts/1")
101
- assert response.kind_of?(Array)
102
- assert allows?(response[1], "DELETE")
99
+ validate_response(response)
100
+ response[0].should be 204
101
+ response[1]["Allow"].should include "DELETE"
103
102
  end
104
103
 
105
- it "not finding a path, return 404 Not Found" do
104
+ it "not finding a path, gently return 404 Not Found" do
106
105
  response = http_options_request("/sblingers/sblongers")
107
- assert response.kind_of?(Array)
108
- assert response[0].should be 404
106
+ validate_response(response)
107
+ response[0].should be 404
109
108
  end
110
109
 
111
- ##
112
- # Note that extension relation types are REQUIRED to be absolute URIs
113
- # in Link headers, and MUST be quoted if they contain a semicolon (";")
114
- # or comma (",") (as these characters are used as delimiters in the
115
- # header itself).
116
- it "the Link header MUST be quoted if it contains a semicolon or comma" do
117
- response = http_options_request("/posts")
118
- assert response.kind_of?(Array)
119
- link = response[1]["Link"]
120
- assert link.should =~ /\A"{1}.+"\z/
110
+
111
+ after(:all) do
112
+ Rails.application.reload_routes!
121
113
  end
122
114
 
123
115
  end
124
116
 
125
- describe "named routes" do
117
+ describe "resources routing with options" do
126
118
 
127
- before(:each) do
128
- ActionController::Routing::Routes.draw do |map|
129
- map.login 'login', :controller => 'accounts', :action => 'login'
119
+ before(:all) do
120
+ rails_app.routes.draw do
121
+ resources :products do
122
+ member do
123
+ get :short
124
+ post :toggle
125
+ end
126
+ collection do
127
+ get :sold
128
+ end
129
+ end
130
130
  end
131
131
  end
132
132
 
133
- it "should work" do
134
- response = http_options_request("/login")
135
- assert response.kind_of?(Array)
136
- assert response[0].should be 204
137
- assert allows?(response[1], "GET") # WTF? return ANY?!? ;p
133
+ it "a GET member example should work" do
134
+ response = http_options_request("/products/123/short")
135
+ validate_response(response)
136
+ response[0].should be 204
137
+ response[1]["Allow"].should include "GET"
138
+ end
139
+
140
+ it "a POST member example should work" do
141
+ response = http_options_request("/products/123/toggle")
142
+ validate_response(response)
143
+ response[0].should be 204
144
+ response[1]["Allow"].should include "POST"
145
+ end
146
+
147
+ it "a named route with options should work" do
148
+ response = http_options_request("/products/sold")
149
+ validate_response(response)
150
+ response[0].should be 204
151
+ response[1]["Allow"].should include "GET"
138
152
  end
139
153
 
140
154
  after(:all) do
141
- ActionController::Routing::Routes.reload!
155
+ Rails.application.reload_routes!
142
156
  end
143
157
 
144
158
  end
145
159
 
146
- describe "route globbing" do
160
+ describe "resources routing with sub-resources" do
147
161
 
148
162
  before(:all) do
149
- ActionController::Routing::Routes.draw do |map|
150
- map.connect '*path' , :controller => 'blog' , :action => 'unrecognized?'
163
+ rails_app.routes.draw do
164
+ resources :products do
165
+ resources :sales
166
+ resource :seller
167
+ end
151
168
  end
152
169
  end
153
170
 
154
- it "should work" do
155
- pending "What the hell is that?"
156
- response = http_options_request("/post/path")
157
- assert response.kind_of?(Array)
158
- assert response[0].should_not be 404
171
+ it "the parent resource collection does listing and creation" do
172
+ response = http_options_request("/products")
173
+ validate_response(response)
174
+ response[0].should be 204
175
+ response[1]["Allow"].should include "GET"
176
+ response[1]["Allow"].should include "POST"
177
+ end
178
+
179
+ it "the parent resource collection have an entry point for creating a new entry" do
180
+ pending "check regexp"
181
+ response = http_options_request("/products/new")
182
+ validate_response(response)
183
+ response[0].should be 204
184
+ response[1]["Allow"].should include "GET"
185
+ response[1]["Allow"].should_not include "POST"
186
+ response[1]["Allow"].should_not include "PUT"
187
+ response[1]["Allow"].should_not include "DELETE"
188
+ end
189
+
190
+ it "the parent resource collection have an entry point for editing an existing entry" do
191
+ response = http_options_request("/products/123/edit")
192
+ validate_response(response)
193
+ response[0].should be 204
194
+ response[1]["Allow"].should include "GET"
195
+ response[1]["Allow"].should_not include "POST"
196
+ response[1]["Allow"].should_not include "PUT"
197
+ response[1]["Allow"].should_not include "DELETE"
198
+ end
199
+
200
+ it "the parent resource collection let its entries be read, updated and deleted" do
201
+ response = http_options_request("/products/123")
202
+ validate_response(response)
203
+ response[0].should be 204
204
+ response[1]["Allow"].should include "GET"
205
+ response[1]["Allow"].should include "PUT"
206
+ response[1]["Allow"].should include "DELETE"
207
+ end
208
+
209
+ it "the parent resource collection let its sub-resource to be created, read, updated and deleted" do
210
+ response = http_options_request("/products/123/seller")
211
+ validate_response(response)
212
+ response[0].should be 204
213
+ response[1]["Allow"].should include "POST"
214
+ response[1]["Allow"].should include "GET"
215
+ response[1]["Allow"].should include "PUT"
216
+ response[1]["Allow"].should include "DELETE"
217
+ end
218
+
219
+ it "the parent resource collection offers its sub-resource an entry point for creating a new entry" do
220
+ response = http_options_request("/products/123/seller/new")
221
+ validate_response(response)
222
+ response[0].should be 204
223
+ response[1]["Allow"].should include "GET"
224
+ response[1]["Allow"].should_not include "POST"
225
+ response[1]["Allow"].should_not include "PUT"
226
+ response[1]["Allow"].should_not include "DELETE"
227
+ end
228
+
229
+ it "the parent resource collection offers its sub-resource an entry point for editing the existing entry" do
230
+ response = http_options_request("/products/123/seller/edit")
231
+ validate_response(response)
232
+ response[0].should be 204
233
+ response[1]["Allow"].should include "GET"
234
+ response[1]["Allow"].should_not include "POST"
235
+ response[1]["Allow"].should_not include "PUT"
236
+ response[1]["Allow"].should_not include "DELETE"
237
+ end
238
+
239
+ it "the sub-resource collection behaves like a common resource collection" do
240
+ response = http_options_request("/products/123/sales")
241
+ validate_response(response)
242
+ response[0].should be 204
243
+ response[1]["Allow"].should include "GET"
244
+ response[1]["Allow"].should include "POST"
245
+ response[1]["Allow"].should_not include "PUT"
246
+ response[1]["Allow"].should_not include "DELETE"
247
+ end
248
+
249
+ it "the sub-resource collection have an entry point for creating a new entry" do
250
+ pending "check regexp"
251
+ response = http_options_request("/products/123/sales/new")
252
+ validate_response(response)
253
+ response[0].should be 204
254
+ response[1]["Allow"].should include "GET"
255
+ response[1]["Allow"].should_not include "POST"
256
+ response[1]["Allow"].should_not include "PUT"
257
+ response[1]["Allow"].should_not include "DELETE"
258
+ end
259
+
260
+ it "the sub-resource collection have an entry point for editing an existing entry" do
261
+ response = http_options_request("/products/123/sales/123/edit")
262
+ validate_response(response)
263
+ response[0].should be 204
264
+ response[1]["Allow"].should include "GET"
265
+ response[1]["Allow"].should_not include "POST"
266
+ response[1]["Allow"].should_not include "PUT"
267
+ response[1]["Allow"].should_not include "DELETE"
268
+ end
269
+
270
+ it "the sub-resource collection let its entries be read, updated and deleted" do
271
+ response = http_options_request("/products/123/sales/456")
272
+ validate_response(response)
273
+ response[0].should be 204
274
+ response[1]["Allow"].should include "GET"
275
+ response[1]["Allow"].should include "PUT"
276
+ response[1]["Allow"].should include "DELETE"
277
+ response[1]["Allow"].should_not include "POST"
159
278
  end
160
279
 
161
280
  after(:all) do
162
- ActionController::Routing::Routes.reload!
281
+ Rails.application.reload_routes!
163
282
  end
164
-
165
283
  end
166
284
 
167
- describe "route conditions" do
285
+ describe "resources routing with more complex sub-resources" do
168
286
 
169
287
  before(:all) do
170
- ActionController::Routing::Routes.draw do |map|
171
- map.connect 'post/:id', :controller => 'posts', :action => 'show', :conditions => { :method => :get }
172
- map.connect 'post/:id', :controller => 'posts', :action => 'create_comment', :conditions => { :method => :post }
288
+ rails_app.routes.draw do
289
+ resources :products do
290
+ resources :sales do
291
+ get :recent, :on => :collection
292
+ end
293
+ end
173
294
  end
174
295
  end
175
296
 
176
- it "should work" do
177
- response = http_options_request("/post/123")
178
- assert response.kind_of?(Array)
179
- assert allows?(response[1], "GET")
180
- assert allows?(response[1], "POST")
297
+ it "blah" do
298
+ response = http_options_request("/products/123/sales/recent.xml")
299
+ validate_response(response)
300
+ response[0].should be 204
301
+ response[1]["Allow"].should include "GET"
181
302
  end
182
303
 
183
304
  after(:all) do
184
- ActionController::Routing::Routes.reload!
305
+ Rails.application.reload_routes!
185
306
  end
186
307
  end
187
308
 
188
- describe "pretty URLs" do
309
+ describe "resources routing within a namespace" do
189
310
 
190
311
  before(:all) do
191
- ActionController::Routing::Routes.draw do |map|
192
- map.connect "articles/:year/:month/:day", :controller => 'articles', :action => 'find_by_date', :requirements => { :year => /\d{4}/, :month => /\d{1,2}/, :day => /\d{1,2}/ }
312
+ rails_app.routes.draw do
313
+ namespace :admin do
314
+ resources :products
315
+ end
193
316
  end
194
317
  end
195
318
 
196
- it "should work" do
197
- response = http_options_request("/articles/2010/07/23")
198
- assert response.kind_of?(Array)
199
- assert response[0].should be 204
319
+ it "a simple matching should work" do
320
+ response = http_options_request("/admin/products/123")
321
+ validate_response(response)
322
+ response[0].should be 204
323
+ response[1]["Allow"].should include "GET"
200
324
  end
201
325
 
202
326
  after(:all) do
203
- ActionController::Routing::Routes.reload!
327
+ Rails.application.reload_routes!
204
328
  end
205
-
206
329
  end
207
330
 
208
- describe "regular expressions and parameters" do
331
+ describe "custom regular routing" do
209
332
 
210
333
  before(:all) do
211
- ActionController::Routing::Routes.draw do |map|
212
- map.geocode 'geocode/:postalcode', :controller => 'geocode', :action => 'show', :requirements => { :postalcode => /\d{5}(-\d{4})?/ }
334
+ rails_app.routes.draw do
335
+ match 'products/:id' => 'catalog#view'
213
336
  end
214
337
  end
215
338
 
216
- it "should work" do
217
- response = http_options_request("/geocode/20100")
218
- assert response.kind_of?(Array)
219
- assert response[0].should be 204
220
- assert allows?(response[1], "GET")
339
+ it "a simple matching should work" do
340
+ response = http_options_request("/products/123")
341
+ validate_response(response)
342
+ response[0].should be 204
343
+ response[1]["Allow"].should include "GET"
221
344
  end
222
345
 
223
346
  after(:all) do
224
- ActionController::Routing::Routes.reload!
347
+ Rails.application.reload_routes!
225
348
  end
349
+
226
350
  end
227
351
 
228
- describe "resource route within a namespace" do
352
+ describe "the root" do
229
353
 
230
354
  before(:all) do
231
- ActionController::Routing::Routes.draw do |map|
232
- map.namespace :admin do |admin|
233
- # Directs /admin/posts/* to Admin::PostsController (app/controllers/admin/posts_controller.rb)
234
- admin.resources :posts
235
- end
355
+ rails_app.routes.draw do
356
+ root :to => "welcome#index"
236
357
  end
237
358
  end
238
359
 
239
- it "must understand an namespaced path" do
240
- response = http_options_request("/admin/posts")
241
- assert response.kind_of?(Array)
242
- assert response[0].should be 204
243
- assert allows?(response[1], "GET")
244
- assert allows?(response[1], "POST")
360
+ it " / should work" do
361
+ response = http_options_request("/")
362
+ validate_response(response)
363
+ response[0].should be 204
364
+ response[1]["Allow"].should include "GET"
245
365
  end
246
366
 
247
367
  after(:all) do
248
- ActionController::Routing::Routes.reload!
368
+ Rails.application.reload_routes!
249
369
  end
250
370
 
251
371
  end
252
372
 
253
- describe "deal the catch all" do
373
+ describe "the legacy 'WILD' controller" do
254
374
 
255
375
  before(:all) do
256
- ActionController::Routing::Routes.draw do |map|
257
- map.resources :posts
258
- map.connect ':controller/:action/:id'
376
+ rails_app.routes.draw do
377
+ match ':controller(/:action(/:id(.:format)))'
259
378
  end
260
379
  end
261
380
 
262
- it "must cheat :P" do
263
- response = http_options_request("/posts")
264
- assert response.kind_of?(Array)
265
- assert response[0].should be 204
266
- assert allows?(response[1], "GET")
267
- assert allows?(response[1], "POST")
381
+ it "a simple matching should work" do
382
+ response = http_options_request("/products/show/123.json")
383
+ validate_response(response)
384
+ response[0].should be 204
385
+ response[1]["Allow"].should include "GET"
268
386
  end
269
387
 
270
388
  after(:all) do
271
- ActionController::Routing::Routes.reload!
389
+ Rails.application.reload_routes!
272
390
  end
273
391
 
274
392
  end
275
-
276
- describe "another sample of named route" do
277
- before(:all) do
278
- ActionController::Routing::Routes.draw do |map|
279
- map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
393
+
394
+
395
+
396
+ end
397
+
398
+ context "Link" do
399
+
400
+ describe "should not be present" do
401
+
402
+ before(:each) do
403
+ rails_app.routes.draw do
404
+ resources :posts
280
405
  end
281
406
  end
282
407
 
283
- it "should work" do
284
- response = http_options_request("/products/123/purchase")
285
- assert response.kind_of?(Array)
286
- assert response[0].should be 204
287
- assert allows?(response[1], "ANY")
408
+ it "if no directions were given" do
409
+ FileUtils.mv File.join(Rails.root, 'config', 'optionsful.yml'), File.join(Rails.root, 'optionsful.yml')
410
+ response = http_options_request("/posts")
411
+ FileUtils.mv File.join(Rails.root, 'optionsful.yml'), File.join(Rails.root, 'config', 'optionsful.yml')
412
+ validate_response(response)
413
+ response[0].should be 204
414
+ response[1]["Link"].should be nil
288
415
  end
289
416
 
290
- after(:all) do
291
- ActionController::Routing::Routes.reload!
417
+ after(:each) do
418
+ Rails.application.reload_routes!
292
419
  end
293
420
 
294
421
  end
295
422
 
296
- describe "Sample resource route with options" do
423
+ describe "behave arbitrarily if directions were given" do
297
424
 
298
425
  before(:all) do
299
- ActionController::Routing::Routes.draw do |map|
300
- map.resources :products, :member => { :short => :get, :toggle => :post }, :collection => { :sold => :get }
426
+ rails_app.routes.draw do
427
+ resources :posts
301
428
  end
302
429
  end
303
430
 
304
- it "should work" do
305
- response = http_options_request("/products/123/toggle")
306
- assert response.kind_of?(Array)
307
- assert response[0].should be 204
308
- assert allows?(response[1], "POST")
309
- end
310
-
311
- it "should work" do
312
- response = http_options_request("/products/123/short")
313
- assert response.kind_of?(Array)
314
- assert response[0].should be 204
315
- assert allows?(response[1], "GET")
316
- end
317
-
318
- it "should work" do
319
- response = http_options_request("/products/sold")
320
- assert response.kind_of?(Array)
321
- assert response[0].should be 204
322
- assert allows?(response[1], "GET")
431
+ it "the Link header MUST be quoted if it contains a semicolon or comma" do
432
+ response = http_options_request("/posts")
433
+ validate_response(response)
434
+ response[0].should be 204
435
+ link = response[1]["Link"]
436
+ link.should match /\A\".+\"\z/
323
437
  end
324
438
 
325
439
  after(:all) do
326
- ActionController::Routing::Routes.reload!
440
+ Rails.application.reload_routes!
327
441
  end
328
442
 
329
443
  end
@@ -331,5 +445,3 @@ describe Baurets::Optionsful::Server do
331
445
  end
332
446
 
333
447
  end
334
-
335
-
data/spec/spec.opts CHANGED
@@ -1,4 +1 @@
1
- --color
2
- --format progress
3
- --loadby mtime
4
- --reverse
1
+ --color