spec/optionsful_server_spec.rb in optionsful-0.2.3 vs spec/optionsful_server_spec.rb in optionsful-0.3.0
- old
+ new
@@ -1,335 +1,447 @@
-require File.dirname(__FILE__) + '/spec_helper'
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+include Rack::Test::Methods
+require 'fileutils'
+describe "Optionsful" do
-describe Baurets::Optionsful::Server do
-
- include Rack::Test::Methods
-
context "as a Rack middleware" do
- it "is a Ruby object that responds to call;" do
- assert ::Baurets::Optionsful::Server.new(app).respond_to? :call
+ it "is a Ruby object that responds to call" do
+ ::Baurets::Optionsful::Server.new(app).respond_to?(:call).should be true
end
- it "takes exactly one argument, (the environment) and returns an Array;" do
+ it "takes exactly one argument, (the environment) and returns an Array" do
response = ::Baurets::Optionsful::Server.new(app).call(mock_env({"REQUEST_METHOD" => "OPTIONS", "PATH_INFO" => "/posts"}))
- assert response.kind_of?(Array)
+ response.should be_a_kind_of Array
end
- it "the returned Array must have exactly three values: the status, the headers and the body;" do
+ it "the returned Array must have exactly three values: the status, the headers and the body" do
response = ::Baurets::Optionsful::Server.new(app).call(mock_env({"REQUEST_METHOD" => "OPTIONS", "PATH_INFO" => "/posts"}))
- assert response.size.should == 3
- assert response[0].kind_of? Fixnum
- assert response[1].kind_of? Hash
- assert response[2].kind_of? String
+ validate_response(response)
end
before do
- ActionController::Routing::Routes.draw do |map|
- map.resources :posts, :has_many => :comments
+ rails_app.routes.draw do
+ resources :posts
end
end
- it "must be nice, acting somewhere on a Rack middleware stack;" do
+ it "must be nice, acting somewhere on a Rack middleware stack" do
response = fake_opts_app.call(mock_env({"REQUEST_METHOD" => "OPTIONS", "PATH_INFO" => "/posts"}))
- assert response.size.should == 3
- assert response[0].kind_of? Fixnum
- assert response[0].should == 204
- assert response[1].kind_of? Hash
- assert response[1]["Allow"]
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should_not be nil
end
it "must let the request go through the stack, if it has nothing to it!" do
response = fake_opts_app.call(mock_env({"REQUEST_METHOD" => "GET", "PATH_INFO" => "/lobster"}))
- assert response.size.should == 3
- assert response[0].kind_of? Fixnum
- assert response[0].should == 200
- assert response[1].kind_of? Hash
+ validate_response(response)
+ response[0].should be 200
end
end
- context "as an interpreter for HTTP OPTIONS requests, MUST recognize the Rails" do
+ context "as an HTTP OPTIONS verb provider must master Rails" do
- describe "default resource routing" do
- #Sample resource route (maps HTTP verbs to controller actions automatically)
+ describe "default resources routing" do
before(:all) do
- ActionController::Routing::Routes.draw do |map|
- map.resources :posts, :has_many => :comments
+ rails_app.routes.draw do
+ resources :posts
end
end
it "the index action displays a list of all posts in response of a GET request" do
response = http_options_request("/posts")
- assert response.kind_of?(Array)
- assert allows?(response[1], "GET")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
end
it "the new action return from a GET request an HTML form for creating a new post" do
response = http_options_request("/posts/new")
- assert response.kind_of?(Array)
- assert allows?(response[1], "GET")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
+ response[1]["Allow"].should_not include "POST"
end
it "the create action uses POST to create a new post instance" do
response = http_options_request("/posts")
- assert response.kind_of?(Array)
- assert allows?(response[1], "POST")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "POST"
end
it "the show action display a specific post in response of a GET request" do
response = http_options_request("/posts/1")
- assert response.kind_of?(Array)
- assert allows?(response[1], "GET")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
end
it "the edit action return an HTML form for editing a post in response of a GET request" do
response = http_options_request("/posts/1/edit")
- assert response.kind_of?(Array)
- assert allows?(response[1], "GET")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
end
it "the update action uses PUT to update a specific post" do
response = http_options_request("/posts/1")
- assert response.kind_of?(Array)
- assert allows?(response[1], "PUT")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "PUT"
end
it "the destroy action uses DELETE to delete a specific post" do
response = http_options_request("/posts/1")
- assert response.kind_of?(Array)
- assert allows?(response[1], "DELETE")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "DELETE"
end
- it "not finding a path, return 404 Not Found" do
+ it "not finding a path, gently return 404 Not Found" do
response = http_options_request("/sblingers/sblongers")
- assert response.kind_of?(Array)
- assert response[0].should be 404
+ validate_response(response)
+ response[0].should be 404
end
- ##
- # Note that extension relation types are REQUIRED to be absolute URIs
- # in Link headers, and MUST be quoted if they contain a semicolon (";")
- # or comma (",") (as these characters are used as delimiters in the
- # header itself).
- it "the Link header MUST be quoted if it contains a semicolon or comma" do
- response = http_options_request("/posts")
- assert response.kind_of?(Array)
- link = response[1]["Link"]
- assert link.should =~ /\A"{1}.+"\z/
+
+ after(:all) do
+ Rails.application.reload_routes!
end
end
- describe "named routes" do
+ describe "resources routing with options" do
- before(:each) do
- ActionController::Routing::Routes.draw do |map|
- map.login 'login', :controller => 'accounts', :action => 'login'
+ before(:all) do
+ rails_app.routes.draw do
+ resources :products do
+ member do
+ get :short
+ post :toggle
+ end
+ collection do
+ get :sold
+ end
+ end
end
end
- it "should work" do
- response = http_options_request("/login")
- assert response.kind_of?(Array)
- assert response[0].should be 204
- assert allows?(response[1], "GET") # WTF? return ANY?!? ;p
+ it "a GET member example should work" do
+ response = http_options_request("/products/123/short")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
end
+ it "a POST member example should work" do
+ response = http_options_request("/products/123/toggle")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "POST"
+ end
+
+ it "a named route with options should work" do
+ response = http_options_request("/products/sold")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
+ end
+
after(:all) do
- ActionController::Routing::Routes.reload!
+ Rails.application.reload_routes!
end
end
- describe "route globbing" do
+ describe "resources routing with sub-resources" do
before(:all) do
- ActionController::Routing::Routes.draw do |map|
- map.connect '*path' , :controller => 'blog' , :action => 'unrecognized?'
+ rails_app.routes.draw do
+ resources :products do
+ resources :sales
+ resource :seller
+ end
end
end
- it "should work" do
- pending "What the hell is that?"
- response = http_options_request("/post/path")
- assert response.kind_of?(Array)
- assert response[0].should_not be 404
+ it "the parent resource collection does listing and creation" do
+ response = http_options_request("/products")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
+ response[1]["Allow"].should include "POST"
end
- after(:all) do
- ActionController::Routing::Routes.reload!
+ it "the parent resource collection have an entry point for creating a new entry" do
+ pending "check regexp"
+ response = http_options_request("/products/new")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
+ response[1]["Allow"].should_not include "POST"
+ response[1]["Allow"].should_not include "PUT"
+ response[1]["Allow"].should_not include "DELETE"
end
- end
+ it "the parent resource collection have an entry point for editing an existing entry" do
+ response = http_options_request("/products/123/edit")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
+ response[1]["Allow"].should_not include "POST"
+ response[1]["Allow"].should_not include "PUT"
+ response[1]["Allow"].should_not include "DELETE"
+ end
- describe "route conditions" do
+ it "the parent resource collection let its entries be read, updated and deleted" do
+ response = http_options_request("/products/123")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
+ response[1]["Allow"].should include "PUT"
+ response[1]["Allow"].should include "DELETE"
+ end
- before(:all) do
- ActionController::Routing::Routes.draw do |map|
- map.connect 'post/:id', :controller => 'posts', :action => 'show', :conditions => { :method => :get }
- map.connect 'post/:id', :controller => 'posts', :action => 'create_comment', :conditions => { :method => :post }
- end
+ it "the parent resource collection let its sub-resource to be created, read, updated and deleted" do
+ response = http_options_request("/products/123/seller")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "POST"
+ response[1]["Allow"].should include "GET"
+ response[1]["Allow"].should include "PUT"
+ response[1]["Allow"].should include "DELETE"
end
- it "should work" do
- response = http_options_request("/post/123")
- assert response.kind_of?(Array)
- assert allows?(response[1], "GET")
- assert allows?(response[1], "POST")
+ it "the parent resource collection offers its sub-resource an entry point for creating a new entry" do
+ response = http_options_request("/products/123/seller/new")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
+ response[1]["Allow"].should_not include "POST"
+ response[1]["Allow"].should_not include "PUT"
+ response[1]["Allow"].should_not include "DELETE"
end
+ it "the parent resource collection offers its sub-resource an entry point for editing the existing entry" do
+ response = http_options_request("/products/123/seller/edit")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
+ response[1]["Allow"].should_not include "POST"
+ response[1]["Allow"].should_not include "PUT"
+ response[1]["Allow"].should_not include "DELETE"
+ end
+
+ it "the sub-resource collection behaves like a common resource collection" do
+ response = http_options_request("/products/123/sales")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
+ response[1]["Allow"].should include "POST"
+ response[1]["Allow"].should_not include "PUT"
+ response[1]["Allow"].should_not include "DELETE"
+ end
+
+ it "the sub-resource collection have an entry point for creating a new entry" do
+ pending "check regexp"
+ response = http_options_request("/products/123/sales/new")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
+ response[1]["Allow"].should_not include "POST"
+ response[1]["Allow"].should_not include "PUT"
+ response[1]["Allow"].should_not include "DELETE"
+ end
+
+ it "the sub-resource collection have an entry point for editing an existing entry" do
+ response = http_options_request("/products/123/sales/123/edit")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
+ response[1]["Allow"].should_not include "POST"
+ response[1]["Allow"].should_not include "PUT"
+ response[1]["Allow"].should_not include "DELETE"
+ end
+
+ it "the sub-resource collection let its entries be read, updated and deleted" do
+ response = http_options_request("/products/123/sales/456")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
+ response[1]["Allow"].should include "PUT"
+ response[1]["Allow"].should include "DELETE"
+ response[1]["Allow"].should_not include "POST"
+ end
+
after(:all) do
- ActionController::Routing::Routes.reload!
+ Rails.application.reload_routes!
end
end
- describe "pretty URLs" do
+ describe "resources routing with more complex sub-resources" do
before(:all) do
- ActionController::Routing::Routes.draw do |map|
- map.connect "articles/:year/:month/:day", :controller => 'articles', :action => 'find_by_date', :requirements => { :year => /\d{4}/, :month => /\d{1,2}/, :day => /\d{1,2}/ }
+ rails_app.routes.draw do
+ resources :products do
+ resources :sales do
+ get :recent, :on => :collection
+ end
+ end
end
end
- it "should work" do
- response = http_options_request("/articles/2010/07/23")
- assert response.kind_of?(Array)
- assert response[0].should be 204
+ it "blah" do
+ response = http_options_request("/products/123/sales/recent.xml")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
end
after(:all) do
- ActionController::Routing::Routes.reload!
+ Rails.application.reload_routes!
end
-
end
- describe "regular expressions and parameters" do
+ describe "resources routing within a namespace" do
before(:all) do
- ActionController::Routing::Routes.draw do |map|
- map.geocode 'geocode/:postalcode', :controller => 'geocode', :action => 'show', :requirements => { :postalcode => /\d{5}(-\d{4})?/ }
+ rails_app.routes.draw do
+ namespace :admin do
+ resources :products
+ end
end
end
- it "should work" do
- response = http_options_request("/geocode/20100")
- assert response.kind_of?(Array)
- assert response[0].should be 204
- assert allows?(response[1], "GET")
+ it "a simple matching should work" do
+ response = http_options_request("/admin/products/123")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
end
after(:all) do
- ActionController::Routing::Routes.reload!
+ Rails.application.reload_routes!
end
end
- describe "resource route within a namespace" do
+ describe "custom regular routing" do
before(:all) do
- ActionController::Routing::Routes.draw do |map|
- map.namespace :admin do |admin|
- # Directs /admin/posts/* to Admin::PostsController (app/controllers/admin/posts_controller.rb)
- admin.resources :posts
- end
+ rails_app.routes.draw do
+ match 'products/:id' => 'catalog#view'
end
end
- it "must understand an namespaced path" do
- response = http_options_request("/admin/posts")
- assert response.kind_of?(Array)
- assert response[0].should be 204
- assert allows?(response[1], "GET")
- assert allows?(response[1], "POST")
+ it "a simple matching should work" do
+ response = http_options_request("/products/123")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
end
after(:all) do
- ActionController::Routing::Routes.reload!
+ Rails.application.reload_routes!
end
end
- describe "deal the catch all" do
+ describe "the root" do
before(:all) do
- ActionController::Routing::Routes.draw do |map|
- map.resources :posts
- map.connect ':controller/:action/:id'
+ rails_app.routes.draw do
+ root :to => "welcome#index"
end
end
- it "must cheat :P" do
- response = http_options_request("/posts")
- assert response.kind_of?(Array)
- assert response[0].should be 204
- assert allows?(response[1], "GET")
- assert allows?(response[1], "POST")
+ it " / should work" do
+ response = http_options_request("/")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
end
after(:all) do
- ActionController::Routing::Routes.reload!
+ Rails.application.reload_routes!
end
end
-
- describe "another sample of named route" do
+
+ describe "the legacy 'WILD' controller" do
+
before(:all) do
- ActionController::Routing::Routes.draw do |map|
- map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
+ rails_app.routes.draw do
+ match ':controller(/:action(/:id(.:format)))'
end
end
- it "should work" do
- response = http_options_request("/products/123/purchase")
- assert response.kind_of?(Array)
- assert response[0].should be 204
- assert allows?(response[1], "ANY")
+ it "a simple matching should work" do
+ response = http_options_request("/products/show/123.json")
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Allow"].should include "GET"
end
after(:all) do
- ActionController::Routing::Routes.reload!
+ Rails.application.reload_routes!
end
end
- describe "Sample resource route with options" do
- before(:all) do
- ActionController::Routing::Routes.draw do |map|
- map.resources :products, :member => { :short => :get, :toggle => :post }, :collection => { :sold => :get }
+
+ end
+
+ context "Link" do
+
+ describe "should not be present" do
+
+ before(:each) do
+ rails_app.routes.draw do
+ resources :posts
end
end
- it "should work" do
- response = http_options_request("/products/123/toggle")
- assert response.kind_of?(Array)
- assert response[0].should be 204
- assert allows?(response[1], "POST")
+ it "if no directions were given" do
+ FileUtils.mv File.join(Rails.root, 'config', 'optionsful.yml'), File.join(Rails.root, 'optionsful.yml')
+ response = http_options_request("/posts")
+ FileUtils.mv File.join(Rails.root, 'optionsful.yml'), File.join(Rails.root, 'config', 'optionsful.yml')
+ validate_response(response)
+ response[0].should be 204
+ response[1]["Link"].should be nil
end
- it "should work" do
- response = http_options_request("/products/123/short")
- assert response.kind_of?(Array)
- assert response[0].should be 204
- assert allows?(response[1], "GET")
+ after(:each) do
+ Rails.application.reload_routes!
end
- it "should work" do
- response = http_options_request("/products/sold")
- assert response.kind_of?(Array)
- assert response[0].should be 204
- assert allows?(response[1], "GET")
+ end
+
+ describe "behave arbitrarily if directions were given" do
+
+ before(:all) do
+ rails_app.routes.draw do
+ resources :posts
+ end
end
+ it "the Link header MUST be quoted if it contains a semicolon or comma" do
+ response = http_options_request("/posts")
+ validate_response(response)
+ response[0].should be 204
+ link = response[1]["Link"]
+ link.should match /\A\".+\"\z/
+ end
+
after(:all) do
- ActionController::Routing::Routes.reload!
+ Rails.application.reload_routes!
end
end
end
end
-
-