Browse files

Adding documentation to new api generator

Adding rack middleware
More tests
  • Loading branch information...
1 parent 1baeab7 commit cb187bc5842b8aa5b4a9a5d6ff0701e561206ea8 Brian Ploetz committed Jan 3, 2012
Showing with 464 additions and 203 deletions.
  1. +2 −0 Gemfile.lock
  2. +2 −2 lib/versionist.rb
  3. +3 −24 lib/versionist/configuration.rb
  4. +3 −0 lib/versionist/generators/new_api_version/new_api_version_generator.rb
  5. +10 −0 lib/versionist/generators/new_api_version/templates/docs_index.rb
  6. +1 −0 lib/versionist/generators/new_api_version/templates/docs_style.rb
  7. +35 −0 lib/versionist/middleware.rb
  8. +5 −15 lib/versionist/railtie.rb
  9. +32 −5 lib/versionist/routing.rb
  10. +10 −3 lib/versionist/versioning_strategy.rb
  11. +6 −5 lib/versionist/versioning_strategy/base.rb
  12. +11 −20 lib/versionist/versioning_strategy/header.rb
  13. +23 −0 lib/versionist/versioning_strategy/parameter.rb
  14. +22 −0 lib/versionist/versioning_strategy/path.rb
  15. +0 −17 lib/versionist/versioning_strategy/url.rb
  16. +140 −46 spec/api_routing_spec.rb
  17. +11 −39 spec/configuration_spec.rb
  18. +29 −0 spec/generators/new_api_version_generator_spec.rb
  19. +0 −15 spec/header_versioning_strategy_spec.rb
  20. +39 −0 spec/middleware_spec.rb
  21. +1 −0 spec/spec_helper.rb
  22. +6 −0 spec/test-api/app/controllers/application_controller.rb
  23. +1 −1 spec/test-api/app/controllers/v1/foos_controller.rb
  24. +3 −5 spec/test-api/app/controllers/v2.1/foos_controller.rb
  25. +3 −5 spec/test-api/app/controllers/v2/foos_controller.rb
  26. +4 −1 spec/test-api/config/application.rb
  27. +22 −0 spec/versioning_strategy/base_spec.rb
  28. +15 −0 spec/versioning_strategy/header_spec.rb
  29. +15 −0 spec/versioning_strategy/parameter_spec.rb
  30. +9 −0 spec/versioning_strategy/path_spec.rb
  31. +1 −0 versionist.gemspec
View
2 Gemfile.lock
@@ -36,6 +36,7 @@ GEM
activesupport (3.1.3)
multi_json (~> 1.0)
arel (2.2.1)
+ awesome_print (1.0.2)
builder (3.0.0)
diff-lcs (1.1.3)
erubis (2.7.0)
@@ -111,6 +112,7 @@ PLATFORMS
ruby
DEPENDENCIES
+ awesome_print (= 1.0.2)
generator_spec (= 0.8.4)
rails (~> 3.0)
rake (>= 0.9.2)
View
4 lib/versionist.rb
@@ -1,6 +1,5 @@
require 'versionist/railtie' if defined?(Rails) && Rails::VERSION::MAJOR == 3
-
-require 'active_support'
+require 'active_support/dependencies/autoload'
module Versionist
extend ActiveSupport::Autoload
@@ -10,6 +9,7 @@ module Versionist
autoload :NewControllerGenerator, "versionist/generators/new_controller/new_controller_generator"
autoload :NewPresenterGenerator, "versionist/generators/new_presenter/new_presenter_generator"
autoload :VersioningStrategy, "versionist/versioning_strategy"
+ autoload :Middleware
autoload :Routing
def self.configuration
View
27 lib/versionist/configuration.rb
@@ -1,30 +1,9 @@
-require 'active_model/validations'
-
module Versionist
class Configuration
- include ActiveModel::Validations
- include ActiveModel::Validations::HelperMethods
-
- attr_accessor :versioning_strategy_name
- validates_inclusion_of :versioning_strategy_name, :in => %W( header url )
- attr_accessor :versioning_config
- attr_accessor :default_version
+ attr_accessor :versioning_strategies
- def versioning_strategy=(args)
- if args.is_a?(Array)
- name = args[0]
- raise ArgumentError, "First argument to versioning_strategy= must be a string specifying the versioning_strategy name" if !name.is_a?(String)
- @versioning_strategy_name = name
- if args.length > 1
- config = args[1]
- raise ArgumentError, "Second argument to versioning_strategy= must be a hash specifying the versioning_strategy config" if !config.is_a?(Hash)
- @versioning_config = config
- end
- else
- name = args
- raise ArgumentError, "First argument to versioning_strategy= must be a string specifying the versioning_strategy name" if !name.is_a?(String)
- @versioning_strategy_name = name
- end
+ def initialize
+ @versioning_strategies ||= Array.new
end
end
end
View
3 lib/versionist/generators/new_api_version/new_api_version_generator.rb
@@ -6,6 +6,9 @@ def new_api_version
empty_directory "app/controllers/#{file_name}"
template 'base_controller.rb', File.join("app", "controllers", "#{file_name}", "base_controller.rb")
empty_directory "app/presenters/#{file_name}"
+ empty_directory "public/docs/#{file_name}"
+ template 'docs_index.rb', File.join("public", "docs", "#{file_name}", "index.html")
+ template 'docs_style.rb', File.join("public", "docs", "#{file_name}", "style.css")
end
end
end
View
10 lib/versionist/generators/new_api_version/templates/docs_index.rb
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <title>Documentation for <%= file_name%></title>
+ <link href="default.css" media="screen" rel="stylesheet" type="text/css">
+ </head>
+ <body>
+ <h1>Documentation for <%= file_name%></h1>
+ </body>
+</html>
View
1 lib/versionist/generators/new_api_version/templates/docs_style.rb
@@ -0,0 +1 @@
+body {background-color: #fff; color: #000;}
View
35 lib/versionist/middleware.rb
@@ -0,0 +1,35 @@
+module Versionist
+ # When your routes don't include an explicit format in the URL (i.e. `match 'foos.(:format)' => foos#index`),
+ # Rails inspects the `Accept` header to determine the requested format. Since an `Accept` header can have multiple values,
+ # Rails uses the first one present to determine the format. If your custom version header happens to be the first value
+ # in the `Accept` header, it would incorrectly be interpretted as the format. This middleware moves your custom version header
+ # to the end of the `Accept` header so as to not interfere with the format.
+ class Middleware
+
+ ACCEPT = "Accept"
+ HTTP_ACCEPT = "HTTP_ACCEPT"
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ request = ::Rack::Request.new(env)
+ strategy = Versionist.configuration.versioning_strategies.detect {|vs| vs.is_a?(Versionist::VersioningStrategy::Header) && vs.config[:header] == ACCEPT && env[HTTP_ACCEPT].include?(vs.config[:value])}
+ if !strategy.nil?
+ entries = env[HTTP_ACCEPT].split(',')
+ index = -1
+ entries.each_with_index do |e, i|
+ e.strip!
+ index = i if e == strategy.config[:value]
+ end
+ if (index != -1)
+ version = entries.delete_at(index)
+ entries << version
+ end
+ env[HTTP_ACCEPT] = entries.join(", ")
+ end
+ @app.call(env)
+ end
+ end
+end
View
20 lib/versionist/railtie.rb
@@ -5,21 +5,11 @@ class Railtie < Rails::Railtie
config.versionist = ActiveSupport::OrderedOptions.new
initializer 'versionist.configure' do |app|
- Versionist.configure do |config|
- config.versioning_strategy = 'header'
- if app.config.versionist.versioning_strategy
- config.versioning_strategy = app.config.versionist.versioning_strategy
- raise "Invalid value for config.versionist.versioning_strategy" if !config.valid?
-
- if config.versioning_strategy == 'header'
- if app.config.versionist.vendor_name
- config.vendor_name = app.config.versionist.vendor_name
- else
- raise "Must specify config.versionist.vendor_name if config.versionist.versioning_strategy is set to 'header'."
- end
- end
- end
- end
+ # Versionist.configure do |config|
+ # config.versioning_strategies = Array.new
+ # end
end
+
+ config.app_middleware.use Versionist::Middleware
end
end
View
37 lib/versionist/routing.rb
@@ -1,12 +1,39 @@
module Versionist
module Routing
- def api_version(version)
- if Versionist.configuration.versioning_strategy_name == Versionist::VersioningStrategy::Base::HEADER_STRATEGY
- return Versionist::VersioningStrategy::Header.new(version, Versionist.configuration.versioning_config)
- elsif Versionist.configuration.versioning_strategy_name == Versionist::VersioningStrategy::Base::URL_STRATEGY
- return Versionist::VersioningStrategy::Url.new(version, Versionist.configuration.versioning_config)
+ # Allows you to constrain routes to specific versions of your api using versioning strategies.
+ # Supported formats:
+ # api_version(:header => "Accept", :value => "application/vnd.mycompany.com-v1")
+ # api_version(:path => "/v2.3.4/")
+ # api_version(:parameter => "version", :value => "v20120317")
+ #
+ # Specifying default version:
+ # api_version(:header => "X-MY-HEADER", :value => "v3.0.0", :default => true)
+ def api_version(config)
+ raise ArgumentError, "you must pass a configuration Hash to api_version" if config.nil? || !config.is_a?(Hash)
+ raise ArgumentError, "you must specify :header, :path, or :parameter in configuration Hash passed to api_version" if !config.has_key?(:header) && !config.has_key?(:path) && !config.has_key?(:parameter)
+ if config.has_key?(:header)
+ return configure_header(config)
+ elsif config.has_key?(:path)
+ configure_path(config)
+ elsif config.has_key?(:parameter)
+ configure_parameter(config)
end
end
+
+
+ private
+
+ def configure_header(config)
+ return Versionist::VersioningStrategy::Header.new(config)
+ end
+
+ def configure_path(config)
+
+ end
+
+ def configure_parameter(config)
+ raise ArgumentError, "you must specify :value in the configuration Hash to api_version" if !config.has_key?(:value)
+ end
end
end
View
13 lib/versionist/versioning_strategy.rb
@@ -1,3 +1,10 @@
-require 'versionist/versioning_strategy/base'
-require 'versionist/versioning_strategy/header'
-require 'versionist/versioning_strategy/url'
+module Versionist
+ module VersioningStrategy
+ extend ActiveSupport::Autoload
+
+ autoload :Base, 'versionist/versioning_strategy/base'
+ autoload :Header, 'versionist/versioning_strategy/header'
+ autoload :Path, 'versionist/versioning_strategy/path'
+ autoload :Parameter, 'versionist/versioning_strategy/parameter'
+ end
+end
View
11 lib/versionist/versioning_strategy/base.rb
@@ -1,14 +1,15 @@
+require 'active_support/core_ext/hash/keys'
+
module Versionist
module VersioningStrategy
class Base
+ attr_reader :config
- HEADER_STRATEGY = "header"
- URL_STRATEGY = "url"
-
- def initialize(version, config={})
- @version = version
+ def initialize(config={})
+ raise ArgumentError, "you must pass a configuration Hash" if config.nil? || !config.is_a?(Hash)
@config = config
@config.symbolize_keys!
+ Versionist.configuration.versioning_strategies << self
end
end
end
View
31 lib/versionist/versioning_strategy/header.rb
@@ -1,31 +1,22 @@
-require 'erb'
-
module Versionist
module VersioningStrategy
- # Implements the header versioning strategy. Inspects the Accept header
- # to determine the requested version. Assumes the following format:
- # Accept: application/vnd.<vendor_name>-<version>+<format>
+ # Implements the header versioning strategy.
class Header < Base
- # Creates a new Header VersioningStrategy object.
- # The config hash must contain the following properties:
- # - header the header to inspect
- # - template the template of the header
- def initialize(version, config={})
+ # Creates a new Header VersioningStrategy object. config must contain the following keys:
+ # - :header the header to inspect
+ # - :value the value of the header specifying the version
+ def initialize(config)
+ raise ArgumentError, "you must specify :header in the configuration Hash" if !config.has_key?(:header)
+ raise ArgumentError, "you must specify :value in the configuration Hash" if !config.has_key?(:value)
super
- raise ArgumentError, "header must be specified for the header versioning_strategy" if !config.has_key?(:header)
- raise ArgumentError, "template must be specified for the header versioning_strategy" if !config.has_key?(:template)
- @erb_template = ERB.new(@config[:template], 0, "%<>")
end
def matches?(request)
- b = binding
- version = @version
- # TODO:
- format = "foobar"
- versioned_header_string = @erb_template.result(b)
- passed_header_string = request.headers[@config[:header]]
- return passed_header_string == versioned_header_string
+ #ap request.env
+ #ap request.accepts
+ #ap request.formats
+ return false
end
end
end
View
23 lib/versionist/versioning_strategy/parameter.rb
@@ -0,0 +1,23 @@
+module Versionist
+ module VersioningStrategy
+ # Implements the parameter versioning strategy.
+ class Parameter < Base
+
+ # Creates a new Parameter VersioningStrategy object. config must contain the following keys:
+ # - :parameter the parameter to inspect
+ # - :value the value of the parameter specifying the version
+ def initialize(config)
+ raise ArgumentError, "you must specify :parameter in the configuration Hash" if !config.has_key?(:parameter)
+ raise ArgumentError, "you must specify :value in the configuration Hash" if !config.has_key?(:value)
+ super
+ end
+
+ def matches?(request)
+ #ap request.env
+ #ap request.accepts
+ #ap request.formats
+ return false
+ end
+ end
+ end
+end
View
22 lib/versionist/versioning_strategy/path.rb
@@ -0,0 +1,22 @@
+module Versionist
+ module VersioningStrategy
+ # Implements the path versioning strategy. It expects the following path format:
+ # GET /<version>/...
+ class Path < Base
+
+ # Creates a new Path VersioningStrategy object. config must contain the following keys:
+ # - :path the path prefix containing the version
+ def initialize(config)
+ raise ArgumentError, "you must specify :path in the configuration Hash" if !config.has_key?(:path)
+ super
+ end
+
+ def matches?(request)
+ #ap request.env
+ #ap request.accepts
+ #ap request.formats
+ return false
+ end
+ end
+ end
+end
View
17 lib/versionist/versioning_strategy/url.rb
@@ -1,17 +0,0 @@
-module Versionist
- module VersioningStrategy
- # Implements the URL versioning strategy. It expects the following path format:
- # GET /<version>/...
- class Url < Base
-
- # Creates a new Url VersioningStrategy object.
- def initialize(version, config={})
- super
- end
-
- def matches?(request)
-
- end
- end
- end
-end
View
186 spec/api_routing_spec.rb
@@ -2,70 +2,164 @@
ENV["RAILS_ENV"] = 'test'
require File.expand_path("../test-api/config/application", __FILE__)
-TestApi::Application.initialize!
require 'rspec/rails'
describe Versionist::Routing do
include RSpec::Rails::RequestExampleGroup
- context "header strategy" do
- context "version" do
- before :each do
- Versionist.configure do |config|
- config.versioning_strategy = "header", {:header => "Accept", :template => "application/vnd.mycompany.com-<%=version%>"}
- config.default_version = "v1"
+ context "#api_version" do
+ it "should raise an error when config nil" do
+ lambda {
+ TestApi::Application.routes.draw do
+ scope :module => "v1", :constraints => api_version(nil)
end
+ }.should raise_error(ArgumentError, /you must pass a configuration Hash to api_version/)
+ end
+ it "should raise an error when config is not a Hash" do
+ lambda {
TestApi::Application.routes.draw do
- scope :module => "v1", :constraints => api_version("v1") do
- match '/foos.(:format)' => 'foos#index', :via => :get
- end
+ scope :module => "v1", :constraints => api_version(1)
end
- end
+ }.should raise_error(ArgumentError, /you must pass a configuration Hash to api_version/)
+ end
- it "should not route to the correct controller when header isn't present" do
- @headers ||= {}
- begin
- get "/foos.json", nil, @headers
- rescue => err
- print err.message
- print err.backtrace.join("\n")
+ it "should raise an error when config doesn't contain any supported strategies" do
+ lambda {
+ TestApi::Application.routes.draw do
+ scope :module => "v1", :constraints => api_version({})
end
- assert_response 404
- end
+ }.should raise_error(ArgumentError, /you must specify :header, :path, or :parameter in configuration Hash passed to api_version/)
+ end
- it "should route to the correct controller when the header doesn't match" do
- @headers ||= {}
- @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v3"
- begin
- get "/foos.json", nil, @headers
- rescue => err
- print err.message
- print err.backtrace.join("\n")
+ context ":header" do
+ it "should add the accept header middleware if the header is Accept" do
+ TestApi::Application.routes.draw do
+ scope :module => "v1", :constraints => api_version({:header => "Accept", :value => "application/vnd.mycompany.com-v1"}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+ match '/foos(:format)' => 'foos#index', :via => :get
end
- assert_response 404
+ TestApi::Application.initialize!
+ TestApi::Application.config.middleware.should include(Versionist::Middleware)
end
+ end
- it "should route to the correct controller when header matches" do
- @headers ||= {}
- @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v1"
- begin
- get "/foos.json", nil, @headers
- rescue => err
- print err.message
- print err.backtrace.join("\n")
- end
- assert_response 200
- assert_equal 'application/json', response.content_type
- assert_equal "v1", response.body
- end
+ context ":path" do
end
- end
- context "url strategy" do
- it "should route to the correct controller" do
-
+ context ":parameter" do
end
+
+ # before :each do
+ # TestApi::Application.routes.draw do
+ # scope :module => "v1", :constraints => api_version(:version => "v1", :header => "Accept", :template => "application/vnd.mycompany.com-<%=version%>") do
+ # match '/foos.(:format)' => 'foos#index', :via => :get
+ # match '/foos_no_format' => 'foos#index', :via => :get
+ # resources :bars
+ # end
+ # match '*a', :to => 'application#not_found'
+ # end
+ # end
+ end
+
+ # context "header strategy" do
+ # context "Accept header" do
+ # before :each do
+ # Versionist.configure do |config|
+ # config.versioning_strategy = "header", {:header => "Accept", :template => "application/vnd.mycompany.com-<%=version%>"}
+ # config.default_version = "v1"
+ # end
+#
+ # TestApi::Application.routes.draw do
+ # scope :module => "v1", :constraints => api_version("v1") do
+ # match '/foos.(:format)' => 'foos#index', :via => :get
+ # match '/foos_no_format' => 'foos#index', :via => :get
+ # end
+ # match '*a', :to => 'application#not_found'
+ # end
+ # end
+#
+ # it "should not route when the configured header isn't present" do
+ # @headers ||= {}
+ # get "/foos.json", nil, @headers
+ # assert_response 404
+ # end
+#
+ # it "should not route when the header doesn't match" do
+ # @headers ||= {}
+ # @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v3"
+ # get "/foos.json", nil, @headers
+ # assert_response 404
+ # end
+#
+ # it "should route to the correct controller when header matches" do
+ # @headers ||= {}
+ # @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v1"
+ # get "/foos.json", nil, @headers
+ # assert_response 200
+ # assert_equal 'application/json', response.content_type
+ # assert_equal "v1", response.body
+ # end
+#
+ # it "should route to the correct controller when format specified via accept header" do
+ # @headers ||= {}
+ # @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v1,application/json"
+ # get "/foos_no_format", nil, @headers
+ # assert_response 200
+ # assert_equal 'application/json', response.content_type
+ # assert_equal "v1", response.body
+ # end
+ # end
+#
+ # context "custom header" do
+ # before :each do
+ # Versionist.configure do |config|
+ # config.versioning_strategy = "header", {:header => "X-MY-CUSTOM-HEADER", :template => "<%=version%>"}
+ # config.default_version = "v1"
+ # end
+#
+ # TestApi::Application.routes.draw do
+ # scope :module => "v1", :constraints => api_version("v1") do
+ # match '/foos.(:format)' => 'foos#index', :via => :get
+ # match '/foos_no_format' => 'foos#index', :via => :get
+ # end
+ # match '*a', :to => 'application#not_found'
+ # end
+ # end
+#
+ # it "should not route when the configured header isn't present" do
+ # @headers ||= {}
+ # get "/foos.json", nil, @headers
+ # assert_response 404
+ # end
+#
+ # it "should not route when the header doesn't match" do
+ # @headers ||= {}
+ # @headers["HTTP_X_MY_CUSTOM_HEADER"] = "v3"
+ # get "/foos.json", nil, @headers
+ # assert_response 404
+ # end
+#
+ # it "should route to the correct controller when header matches" do
+ # @headers ||= {}
+ # @headers["HTTP_X_MY_CUSTOM_HEADER"] = "v3"
+ # get "/foos.json", nil, @headers
+ # assert_response 200
+ # assert_equal 'application/json', response.content_type
+ # assert_equal "v3", response.body
+ # end
+ # end
+ # end
+
+ context "path strategy" do
+ it "should route to the correct controller"
+ end
+
+ context "query string strategy" do
+ it "should route to the correct controller"
end
end
View
50 spec/configuration_spec.rb
@@ -1,46 +1,18 @@
require 'spec_helper'
describe Versionist do
- context ".configure" do
- before :each do
- Versionist.configure do |config|
- config.versioning_strategy = "header", {:vendor_name => "mydomain.com"}
- config.default_version = "v1"
- end
- end
-
- it "should configure the versioning_strategy" do
- Versionist.configuration.versioning_strategy_name.should == "header"
- end
-
- it "should configure the vendor_name" do
- Versionist.configuration.versioning_config[:vendor_name].should == "mydomain.com"
- end
-
- it "should configure the default_version" do
- Versionist.configuration.default_version.should == "v1"
- end
-
- it "should validate versioning_strategy" do
- Versionist.configure do |config|
- config.versioning_strategy = "bogus"
- end
- Versionist.configuration.valid?.should == false
-
- Versionist.configure do |config|
- config.versioning_strategy = "bogus", {:vendor_name => "foo"}
- end
- Versionist.configuration.valid?.should == false
+ before :each do
+ Versionist.configuration.versioning_strategies.clear
+ end
- Versionist.configure do |config|
- config.versioning_strategy = "header"
- end
- Versionist.configuration.valid?.should == true
+ after :each do
+ Versionist.configuration.versioning_strategies.clear
+ end
- Versionist.configure do |config|
- config.versioning_strategy = "url"
- end
- Versionist.configuration.valid?.should == true
- end
+ it "should add versioning strategies" do
+ Versionist.configuration.versioning_strategies.should be_empty
+ Versionist::VersioningStrategy::Base.new({})
+ Versionist.configuration.versioning_strategies.should_not be_nil
+ Versionist.configuration.versioning_strategies.size.should == 1
end
end
View
29 spec/generators/new_api_version_generator_spec.rb
@@ -30,6 +30,31 @@ class V1::BaseController < ApplicationController
it "should create a namespaced presenters directory" do
assert_directory "app/presenters/v1"
end
+
+ it "should create a documentation directory" do
+ assert_directory "public/docs/v1"
+ end
+
+ it "should create a documentation index.html" do
+ assert_file "public/docs/v1/index.html", <<-CONTENTS
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <title>Documentation for v1</title>
+ <link href="default.css" media="screen" rel="stylesheet" type="text/css">
+ </head>
+ <body>
+ <h1>Documentation for v1</h1>
+ </body>
+</html>
+ CONTENTS
+ end
+
+ it "should create a documentation style.css" do
+ assert_file "public/docs/v1/style.css", <<-CONTENTS
+body {background-color: #fff; color: #000;}
+ CONTENTS
+ end
end
context "special characters in version name" do
@@ -51,5 +76,9 @@ class V3_4_2::BaseController < ApplicationController
it "should create a namespaced presenters directory" do
assert_directory "app/presenters/v3.4.2"
end
+
+ it "should create a documentation directory" do
+ assert_directory "public/docs/v3.4.2"
+ end
end
end
View
15 spec/header_versioning_strategy_spec.rb
@@ -1,15 +0,0 @@
-require 'spec_helper'
-
-describe Versionist::VersioningStrategy::Header do
- it "should raise an ArgumentError if header is not specified" do
- lambda {
- Versionist::VersioningStrategy::Header.new("v1")
- }.should raise_error(ArgumentError, /header must be specified for the header versioning_strategy/)
- end
-
- it "should raise an ArgumentError if template is not specified" do
- lambda {
- Versionist::VersioningStrategy::Header.new("v1", {:header => "Accept"})
- }.should raise_error(ArgumentError, /template must be specified for the header versioning_strategy/)
- end
-end
View
39 spec/middleware_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+require 'rack/test'
+
+describe Versionist::Middleware do
+ before :all do
+ Versionist::VersioningStrategy::Header.new({:header => "Accept", :value => "application/vnd.mycompany.com-v2.3.0"})
+ @app = lambda {|env| [200, {"Content-Type" => "text/plain"}, [env["HTTP_ACCEPT"]]]}
+ end
+
+ after :all do
+ Versionist.configuration.versioning_strategies.clear
+ end
+
+ context "Accept header" do
+ it "should not alter the header if the version is not present" do
+ request = Rack::MockRequest.env_for("/foos", "HTTP_ACCEPT" => "application/json", :lint => true, :fatal => true)
+ status, headers, response = described_class.new(@app).call(request)
+ response[0].should == "application/json"
+ end
+
+ it "should not alter the header if an unconfigured version is present" do
+ request = Rack::MockRequest.env_for("/foos", "HTTP_ACCEPT" => "application/vnd.mycompany.com-v1,application/json", :lint => true, :fatal => true)
+ status, headers, response = described_class.new(@app).call(request)
+ response[0].should == "application/vnd.mycompany.com-v1,application/json"
+ end
+
+ it "should move the version to the end" do
+ request = Rack::MockRequest.env_for("/foos", "HTTP_ACCEPT" => "application/vnd.mycompany.com-v2.3.0,application/json", :lint => true, :fatal => true)
+ status, headers, response = described_class.new(@app).call(request)
+ response[0].should == "application/json, application/vnd.mycompany.com-v2.3.0"
+ end
+
+ it "should move the version to the end and retain accept params" do
+ request = Rack::MockRequest.env_for("/foos", "HTTP_ACCEPT" => "audio/*; q=0.2, audio/basic, application/vnd.mycompany.com-v2.3.0, application/json", :lint => true, :fatal => true)
+ status, headers, response = described_class.new(@app).call(request)
+ response[0].should == "audio/*; q=0.2, audio/basic, application/json, application/vnd.mycompany.com-v2.3.0"
+ end
+ end
+end
View
1 spec/spec_helper.rb
@@ -21,6 +21,7 @@
require 'versionist'
require 'fileutils'
+require 'ap'
RSpec.configure do |config|
config.mock_with :rspec
View
6 spec/test-api/app/controllers/application_controller.rb
@@ -0,0 +1,6 @@
+class ApplicationController < ActionController::Base
+ def not_found
+ # just silence it
+ head :not_found
+ end
+end
View
2 spec/test-api/app/controllers/v1/foos_controller.rb
@@ -1,4 +1,4 @@
-class V1::FoosController < ActionController::Base
+class V1::FoosController < ApplicationController
def index
render :text => "v1"
end
View
8 spec/test-api/app/controllers/v2.1/foos_controller.rb
@@ -1,7 +1,5 @@
-module V2_1
- class FoosController < ActionController::Base
- def index
- render :text => "v2.1"
- end
+class V2_1::FoosController < ApplicationController
+ def index
+ render :text => "v2.1"
end
end
View
8 spec/test-api/app/controllers/v2/foos_controller.rb
@@ -1,7 +1,5 @@
-module V2
- class FoosController < ActionController::Base
- def index
- render :text => "v2"
- end
+class V2::FoosController < ApplicationController
+ def index
+ render :text => "v2"
end
end
View
5 spec/test-api/config/application.rb
@@ -1,5 +1,6 @@
require "action_controller/railtie"
require "sprockets/railtie"
+require 'versionist/railtie'
module TestApi
class Application < Rails::Application
@@ -8,6 +9,8 @@ class Application < Rails::Application
config.active_support.deprecation = :log
config.action_controller.logger = nil
config.logger = Logger.new(STDOUT)
- config.log_level = Logger::Severity::FATAL
+ config.log_level = Logger::Severity::UNKNOWN
+ config.action_controller.logger = nil
+ config.middleware.delete Rails::Rack::Logger
end
end
View
22 spec/versioning_strategy/base_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe Versionist::VersioningStrategy::Base do
+ it "should raise an error when config nil" do
+ lambda {
+ Versionist::VersioningStrategy::Base.new(nil)
+ }.should raise_error(ArgumentError, /you must pass a configuration Hash/)
+ end
+
+ it "should raise an error when config is not a Hash" do
+ lambda {
+ Versionist::VersioningStrategy::Base.new(1)
+ }.should raise_error(ArgumentError, /you must pass a configuration Hash/)
+ end
+
+ it "should add self to Versionist::Configuration.versioning_strategies" do
+ Versionist.configuration.versioning_strategies.should be_empty
+ Versionist::VersioningStrategy::Base.new({})
+ Versionist.configuration.versioning_strategies.should_not be_empty
+ Versionist.configuration.versioning_strategies.size.should == 1
+ end
+end
View
15 spec/versioning_strategy/header_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe Versionist::VersioningStrategy::Header do
+ it "should raise an ArgumentError if :header is not specified" do
+ lambda {
+ Versionist::VersioningStrategy::Header.new({:foo => :bar})
+ }.should raise_error(ArgumentError, /you must specify :header in the configuration Hash/)
+ end
+
+ it "should raise an ArgumentError if :value is not specified" do
+ lambda {
+ Versionist::VersioningStrategy::Header.new({:header => "foo"})
+ }.should raise_error(ArgumentError, /you must specify :value in the configuration Hash/)
+ end
+end
View
15 spec/versioning_strategy/parameter_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe Versionist::VersioningStrategy::Parameter do
+ it "should raise an ArgumentError if :parameter is not specified" do
+ lambda {
+ Versionist::VersioningStrategy::Parameter.new({})
+ }.should raise_error(ArgumentError, /you must specify :parameter in the configuration Hash/)
+ end
+
+ it "should raise an ArgumentError if :value is not specified" do
+ lambda {
+ Versionist::VersioningStrategy::Parameter.new({:parameter => "version"})
+ }.should raise_error(ArgumentError, /you must specify :value in the configuration Hash/)
+ end
+end
View
9 spec/versioning_strategy/path_spec.rb
@@ -0,0 +1,9 @@
+require 'spec_helper'
+
+describe Versionist::VersioningStrategy::Path do
+ it "should raise an ArgumentError if :path is not specified" do
+ lambda {
+ Versionist::VersioningStrategy::Path.new({})
+ }.should raise_error(ArgumentError, /you must specify :path in the configuration Hash/)
+ end
+end
View
1 versionist.gemspec
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
s.add_dependency('rails', '~> 3.0')
+ s.add_development_dependency('awesome_print', '= 1.0.2')
s.add_development_dependency('rake', '>= 0.9.2')
s.add_development_dependency('rspec', '2.7.0')
s.add_development_dependency('rspec-rails', '2.7.0')

0 comments on commit cb187bc

Please sign in to comment.