Skip to content
This repository
Browse code

Adding documentation to new api generator

Adding rack middleware
More tests
  • Loading branch information...
commit cb187bc5842b8aa5b4a9a5d6ff0701e561206ea8 1 parent 1baeab7
Brian Ploetz authored

Showing 31 changed files with 464 additions and 203 deletions. Show diff stats Hide diff stats

  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
2  Gemfile.lock
@@ -36,6 +36,7 @@ GEM
36 36 activesupport (3.1.3)
37 37 multi_json (~> 1.0)
38 38 arel (2.2.1)
  39 + awesome_print (1.0.2)
39 40 builder (3.0.0)
40 41 diff-lcs (1.1.3)
41 42 erubis (2.7.0)
@@ -111,6 +112,7 @@ PLATFORMS
111 112 ruby
112 113
113 114 DEPENDENCIES
  115 + awesome_print (= 1.0.2)
114 116 generator_spec (= 0.8.4)
115 117 rails (~> 3.0)
116 118 rake (>= 0.9.2)
4 lib/versionist.rb
... ... @@ -1,6 +1,5 @@
1 1 require 'versionist/railtie' if defined?(Rails) && Rails::VERSION::MAJOR == 3
2   -
3   -require 'active_support'
  2 +require 'active_support/dependencies/autoload'
4 3
5 4 module Versionist
6 5 extend ActiveSupport::Autoload
@@ -10,6 +9,7 @@ module Versionist
10 9 autoload :NewControllerGenerator, "versionist/generators/new_controller/new_controller_generator"
11 10 autoload :NewPresenterGenerator, "versionist/generators/new_presenter/new_presenter_generator"
12 11 autoload :VersioningStrategy, "versionist/versioning_strategy"
  12 + autoload :Middleware
13 13 autoload :Routing
14 14
15 15 def self.configuration
27 lib/versionist/configuration.rb
... ... @@ -1,30 +1,9 @@
1   -require 'active_model/validations'
2   -
3 1 module Versionist
4 2 class Configuration
5   - include ActiveModel::Validations
6   - include ActiveModel::Validations::HelperMethods
7   -
8   - attr_accessor :versioning_strategy_name
9   - validates_inclusion_of :versioning_strategy_name, :in => %W( header url )
10   - attr_accessor :versioning_config
11   - attr_accessor :default_version
  3 + attr_accessor :versioning_strategies
12 4
13   - def versioning_strategy=(args)
14   - if args.is_a?(Array)
15   - name = args[0]
16   - raise ArgumentError, "First argument to versioning_strategy= must be a string specifying the versioning_strategy name" if !name.is_a?(String)
17   - @versioning_strategy_name = name
18   - if args.length > 1
19   - config = args[1]
20   - raise ArgumentError, "Second argument to versioning_strategy= must be a hash specifying the versioning_strategy config" if !config.is_a?(Hash)
21   - @versioning_config = config
22   - end
23   - else
24   - name = args
25   - raise ArgumentError, "First argument to versioning_strategy= must be a string specifying the versioning_strategy name" if !name.is_a?(String)
26   - @versioning_strategy_name = name
27   - end
  5 + def initialize
  6 + @versioning_strategies ||= Array.new
28 7 end
29 8 end
30 9 end
3  lib/versionist/generators/new_api_version/new_api_version_generator.rb
@@ -6,6 +6,9 @@ def new_api_version
6 6 empty_directory "app/controllers/#{file_name}"
7 7 template 'base_controller.rb', File.join("app", "controllers", "#{file_name}", "base_controller.rb")
8 8 empty_directory "app/presenters/#{file_name}"
  9 + empty_directory "public/docs/#{file_name}"
  10 + template 'docs_index.rb', File.join("public", "docs", "#{file_name}", "index.html")
  11 + template 'docs_style.rb', File.join("public", "docs", "#{file_name}", "style.css")
9 12 end
10 13 end
11 14 end
10 lib/versionist/generators/new_api_version/templates/docs_index.rb
... ... @@ -0,0 +1,10 @@
  1 +<!DOCTYPE html>
  2 +<html lang="en-US">
  3 + <head>
  4 + <title>Documentation for <%= file_name%></title>
  5 + <link href="default.css" media="screen" rel="stylesheet" type="text/css">
  6 + </head>
  7 + <body>
  8 + <h1>Documentation for <%= file_name%></h1>
  9 + </body>
  10 +</html>
1  lib/versionist/generators/new_api_version/templates/docs_style.rb
... ... @@ -0,0 +1 @@
  1 +body {background-color: #fff; color: #000;}
35 lib/versionist/middleware.rb
... ... @@ -0,0 +1,35 @@
  1 +module Versionist
  2 + # When your routes don't include an explicit format in the URL (i.e. `match 'foos.(:format)' => foos#index`),
  3 + # Rails inspects the `Accept` header to determine the requested format. Since an `Accept` header can have multiple values,
  4 + # Rails uses the first one present to determine the format. If your custom version header happens to be the first value
  5 + # in the `Accept` header, it would incorrectly be interpretted as the format. This middleware moves your custom version header
  6 + # to the end of the `Accept` header so as to not interfere with the format.
  7 + class Middleware
  8 +
  9 + ACCEPT = "Accept"
  10 + HTTP_ACCEPT = "HTTP_ACCEPT"
  11 +
  12 + def initialize(app)
  13 + @app = app
  14 + end
  15 +
  16 + def call(env)
  17 + request = ::Rack::Request.new(env)
  18 + strategy = Versionist.configuration.versioning_strategies.detect {|vs| vs.is_a?(Versionist::VersioningStrategy::Header) && vs.config[:header] == ACCEPT && env[HTTP_ACCEPT].include?(vs.config[:value])}
  19 + if !strategy.nil?
  20 + entries = env[HTTP_ACCEPT].split(',')
  21 + index = -1
  22 + entries.each_with_index do |e, i|
  23 + e.strip!
  24 + index = i if e == strategy.config[:value]
  25 + end
  26 + if (index != -1)
  27 + version = entries.delete_at(index)
  28 + entries << version
  29 + end
  30 + env[HTTP_ACCEPT] = entries.join(", ")
  31 + end
  32 + @app.call(env)
  33 + end
  34 + end
  35 +end
20 lib/versionist/railtie.rb
@@ -5,21 +5,11 @@ class Railtie < Rails::Railtie
5 5 config.versionist = ActiveSupport::OrderedOptions.new
6 6
7 7 initializer 'versionist.configure' do |app|
8   - Versionist.configure do |config|
9   - config.versioning_strategy = 'header'
10   - if app.config.versionist.versioning_strategy
11   - config.versioning_strategy = app.config.versionist.versioning_strategy
12   - raise "Invalid value for config.versionist.versioning_strategy" if !config.valid?
13   -
14   - if config.versioning_strategy == 'header'
15   - if app.config.versionist.vendor_name
16   - config.vendor_name = app.config.versionist.vendor_name
17   - else
18   - raise "Must specify config.versionist.vendor_name if config.versionist.versioning_strategy is set to 'header'."
19   - end
20   - end
21   - end
22   - end
  8 + # Versionist.configure do |config|
  9 + # config.versioning_strategies = Array.new
  10 + # end
23 11 end
  12 +
  13 + config.app_middleware.use Versionist::Middleware
24 14 end
25 15 end
37 lib/versionist/routing.rb
... ... @@ -1,12 +1,39 @@
1 1 module Versionist
2 2 module Routing
3   - def api_version(version)
4   - if Versionist.configuration.versioning_strategy_name == Versionist::VersioningStrategy::Base::HEADER_STRATEGY
5   - return Versionist::VersioningStrategy::Header.new(version, Versionist.configuration.versioning_config)
6   - elsif Versionist.configuration.versioning_strategy_name == Versionist::VersioningStrategy::Base::URL_STRATEGY
7   - return Versionist::VersioningStrategy::Url.new(version, Versionist.configuration.versioning_config)
  3 + # Allows you to constrain routes to specific versions of your api using versioning strategies.
  4 + # Supported formats:
  5 + # api_version(:header => "Accept", :value => "application/vnd.mycompany.com-v1")
  6 + # api_version(:path => "/v2.3.4/")
  7 + # api_version(:parameter => "version", :value => "v20120317")
  8 + #
  9 + # Specifying default version:
  10 + # api_version(:header => "X-MY-HEADER", :value => "v3.0.0", :default => true)
  11 + def api_version(config)
  12 + raise ArgumentError, "you must pass a configuration Hash to api_version" if config.nil? || !config.is_a?(Hash)
  13 + 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)
  14 + if config.has_key?(:header)
  15 + return configure_header(config)
  16 + elsif config.has_key?(:path)
  17 + configure_path(config)
  18 + elsif config.has_key?(:parameter)
  19 + configure_parameter(config)
8 20 end
9 21 end
  22 +
  23 +
  24 + private
  25 +
  26 + def configure_header(config)
  27 + return Versionist::VersioningStrategy::Header.new(config)
  28 + end
  29 +
  30 + def configure_path(config)
  31 +
  32 + end
  33 +
  34 + def configure_parameter(config)
  35 + raise ArgumentError, "you must specify :value in the configuration Hash to api_version" if !config.has_key?(:value)
  36 + end
10 37 end
11 38 end
12 39
13 lib/versionist/versioning_strategy.rb
... ... @@ -1,3 +1,10 @@
1   -require 'versionist/versioning_strategy/base'
2   -require 'versionist/versioning_strategy/header'
3   -require 'versionist/versioning_strategy/url'
  1 +module Versionist
  2 + module VersioningStrategy
  3 + extend ActiveSupport::Autoload
  4 +
  5 + autoload :Base, 'versionist/versioning_strategy/base'
  6 + autoload :Header, 'versionist/versioning_strategy/header'
  7 + autoload :Path, 'versionist/versioning_strategy/path'
  8 + autoload :Parameter, 'versionist/versioning_strategy/parameter'
  9 + end
  10 +end
11 lib/versionist/versioning_strategy/base.rb
... ... @@ -1,14 +1,15 @@
  1 +require 'active_support/core_ext/hash/keys'
  2 +
1 3 module Versionist
2 4 module VersioningStrategy
3 5 class Base
  6 + attr_reader :config
4 7
5   - HEADER_STRATEGY = "header"
6   - URL_STRATEGY = "url"
7   -
8   - def initialize(version, config={})
9   - @version = version
  8 + def initialize(config={})
  9 + raise ArgumentError, "you must pass a configuration Hash" if config.nil? || !config.is_a?(Hash)
10 10 @config = config
11 11 @config.symbolize_keys!
  12 + Versionist.configuration.versioning_strategies << self
12 13 end
13 14 end
14 15 end
31 lib/versionist/versioning_strategy/header.rb
... ... @@ -1,31 +1,22 @@
1   -require 'erb'
2   -
3 1 module Versionist
4 2 module VersioningStrategy
5   - # Implements the header versioning strategy. Inspects the Accept header
6   - # to determine the requested version. Assumes the following format:
7   - # Accept: application/vnd.<vendor_name>-<version>+<format>
  3 + # Implements the header versioning strategy.
8 4 class Header < Base
9 5
10   - # Creates a new Header VersioningStrategy object.
11   - # The config hash must contain the following properties:
12   - # - header the header to inspect
13   - # - template the template of the header
14   - def initialize(version, config={})
  6 + # Creates a new Header VersioningStrategy object. config must contain the following keys:
  7 + # - :header the header to inspect
  8 + # - :value the value of the header specifying the version
  9 + def initialize(config)
  10 + raise ArgumentError, "you must specify :header in the configuration Hash" if !config.has_key?(:header)
  11 + raise ArgumentError, "you must specify :value in the configuration Hash" if !config.has_key?(:value)
15 12 super
16   - raise ArgumentError, "header must be specified for the header versioning_strategy" if !config.has_key?(:header)
17   - raise ArgumentError, "template must be specified for the header versioning_strategy" if !config.has_key?(:template)
18   - @erb_template = ERB.new(@config[:template], 0, "%<>")
19 13 end
20 14
21 15 def matches?(request)
22   - b = binding
23   - version = @version
24   - # TODO:
25   - format = "foobar"
26   - versioned_header_string = @erb_template.result(b)
27   - passed_header_string = request.headers[@config[:header]]
28   - return passed_header_string == versioned_header_string
  16 + #ap request.env
  17 + #ap request.accepts
  18 + #ap request.formats
  19 + return false
29 20 end
30 21 end
31 22 end
23 lib/versionist/versioning_strategy/parameter.rb
... ... @@ -0,0 +1,23 @@
  1 +module Versionist
  2 + module VersioningStrategy
  3 + # Implements the parameter versioning strategy.
  4 + class Parameter < Base
  5 +
  6 + # Creates a new Parameter VersioningStrategy object. config must contain the following keys:
  7 + # - :parameter the parameter to inspect
  8 + # - :value the value of the parameter specifying the version
  9 + def initialize(config)
  10 + raise ArgumentError, "you must specify :parameter in the configuration Hash" if !config.has_key?(:parameter)
  11 + raise ArgumentError, "you must specify :value in the configuration Hash" if !config.has_key?(:value)
  12 + super
  13 + end
  14 +
  15 + def matches?(request)
  16 + #ap request.env
  17 + #ap request.accepts
  18 + #ap request.formats
  19 + return false
  20 + end
  21 + end
  22 + end
  23 +end
22 lib/versionist/versioning_strategy/path.rb
... ... @@ -0,0 +1,22 @@
  1 +module Versionist
  2 + module VersioningStrategy
  3 + # Implements the path versioning strategy. It expects the following path format:
  4 + # GET /<version>/...
  5 + class Path < Base
  6 +
  7 + # Creates a new Path VersioningStrategy object. config must contain the following keys:
  8 + # - :path the path prefix containing the version
  9 + def initialize(config)
  10 + raise ArgumentError, "you must specify :path in the configuration Hash" if !config.has_key?(:path)
  11 + super
  12 + end
  13 +
  14 + def matches?(request)
  15 + #ap request.env
  16 + #ap request.accepts
  17 + #ap request.formats
  18 + return false
  19 + end
  20 + end
  21 + end
  22 +end
17 lib/versionist/versioning_strategy/url.rb
... ... @@ -1,17 +0,0 @@
1   -module Versionist
2   - module VersioningStrategy
3   - # Implements the URL versioning strategy. It expects the following path format:
4   - # GET /<version>/...
5   - class Url < Base
6   -
7   - # Creates a new Url VersioningStrategy object.
8   - def initialize(version, config={})
9   - super
10   - end
11   -
12   - def matches?(request)
13   -
14   - end
15   - end
16   - end
17   -end
186 spec/api_routing_spec.rb
@@ -2,70 +2,164 @@
2 2
3 3 ENV["RAILS_ENV"] = 'test'
4 4 require File.expand_path("../test-api/config/application", __FILE__)
5   -TestApi::Application.initialize!
6 5
7 6 require 'rspec/rails'
8 7
9 8 describe Versionist::Routing do
10 9 include RSpec::Rails::RequestExampleGroup
11 10
12   - context "header strategy" do
13   - context "version" do
14   - before :each do
15   - Versionist.configure do |config|
16   - config.versioning_strategy = "header", {:header => "Accept", :template => "application/vnd.mycompany.com-<%=version%>"}
17   - config.default_version = "v1"
  11 + context "#api_version" do
  12 + it "should raise an error when config nil" do
  13 + lambda {
  14 + TestApi::Application.routes.draw do
  15 + scope :module => "v1", :constraints => api_version(nil)
18 16 end
  17 + }.should raise_error(ArgumentError, /you must pass a configuration Hash to api_version/)
  18 + end
19 19
  20 + it "should raise an error when config is not a Hash" do
  21 + lambda {
20 22 TestApi::Application.routes.draw do
21   - scope :module => "v1", :constraints => api_version("v1") do
22   - match '/foos.(:format)' => 'foos#index', :via => :get
23   - end
  23 + scope :module => "v1", :constraints => api_version(1)
24 24 end
25   - end
  25 + }.should raise_error(ArgumentError, /you must pass a configuration Hash to api_version/)
  26 + end
26 27
27   - it "should not route to the correct controller when header isn't present" do
28   - @headers ||= {}
29   - begin
30   - get "/foos.json", nil, @headers
31   - rescue => err
32   - print err.message
33   - print err.backtrace.join("\n")
  28 + it "should raise an error when config doesn't contain any supported strategies" do
  29 + lambda {
  30 + TestApi::Application.routes.draw do
  31 + scope :module => "v1", :constraints => api_version({})
34 32 end
35   - assert_response 404
36   - end
  33 + }.should raise_error(ArgumentError, /you must specify :header, :path, or :parameter in configuration Hash passed to api_version/)
  34 + end
37 35
38   - it "should route to the correct controller when the header doesn't match" do
39   - @headers ||= {}
40   - @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v3"
41   - begin
42   - get "/foos.json", nil, @headers
43   - rescue => err
44   - print err.message
45   - print err.backtrace.join("\n")
  36 + context ":header" do
  37 + it "should add the accept header middleware if the header is Accept" do
  38 + TestApi::Application.routes.draw do
  39 + scope :module => "v1", :constraints => api_version({:header => "Accept", :value => "application/vnd.mycompany.com-v1"}) do
  40 + match '/foos.(:format)' => 'foos#index', :via => :get
  41 + match '/foos_no_format' => 'foos#index', :via => :get
  42 + resources :bars
  43 + end
  44 + match '/foos(:format)' => 'foos#index', :via => :get
46 45 end
47   - assert_response 404
  46 + TestApi::Application.initialize!
  47 + TestApi::Application.config.middleware.should include(Versionist::Middleware)
48 48 end
  49 + end
49 50
50   - it "should route to the correct controller when header matches" do
51   - @headers ||= {}
52   - @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v1"
53   - begin
54   - get "/foos.json", nil, @headers
55   - rescue => err
56   - print err.message
57   - print err.backtrace.join("\n")
58   - end
59   - assert_response 200
60   - assert_equal 'application/json', response.content_type
61   - assert_equal "v1", response.body
62   - end
  51 + context ":path" do
63 52 end
64   - end
65 53
66   - context "url strategy" do
67   - it "should route to the correct controller" do
68   -
  54 + context ":parameter" do
69 55 end
  56 +
  57 + # before :each do
  58 + # TestApi::Application.routes.draw do
  59 + # scope :module => "v1", :constraints => api_version(:version => "v1", :header => "Accept", :template => "application/vnd.mycompany.com-<%=version%>") do
  60 + # match '/foos.(:format)' => 'foos#index', :via => :get
  61 + # match '/foos_no_format' => 'foos#index', :via => :get
  62 + # resources :bars
  63 + # end
  64 + # match '*a', :to => 'application#not_found'
  65 + # end
  66 + # end
  67 + end
  68 +
  69 + # context "header strategy" do
  70 + # context "Accept header" do
  71 + # before :each do
  72 + # Versionist.configure do |config|
  73 + # config.versioning_strategy = "header", {:header => "Accept", :template => "application/vnd.mycompany.com-<%=version%>"}
  74 + # config.default_version = "v1"
  75 + # end
  76 +#
  77 + # TestApi::Application.routes.draw do
  78 + # scope :module => "v1", :constraints => api_version("v1") do
  79 + # match '/foos.(:format)' => 'foos#index', :via => :get
  80 + # match '/foos_no_format' => 'foos#index', :via => :get
  81 + # end
  82 + # match '*a', :to => 'application#not_found'
  83 + # end
  84 + # end
  85 +#
  86 + # it "should not route when the configured header isn't present" do
  87 + # @headers ||= {}
  88 + # get "/foos.json", nil, @headers
  89 + # assert_response 404
  90 + # end
  91 +#
  92 + # it "should not route when the header doesn't match" do
  93 + # @headers ||= {}
  94 + # @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v3"
  95 + # get "/foos.json", nil, @headers
  96 + # assert_response 404
  97 + # end
  98 +#
  99 + # it "should route to the correct controller when header matches" do
  100 + # @headers ||= {}
  101 + # @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v1"
  102 + # get "/foos.json", nil, @headers
  103 + # assert_response 200
  104 + # assert_equal 'application/json', response.content_type
  105 + # assert_equal "v1", response.body
  106 + # end
  107 +#
  108 + # it "should route to the correct controller when format specified via accept header" do
  109 + # @headers ||= {}
  110 + # @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v1,application/json"
  111 + # get "/foos_no_format", nil, @headers
  112 + # assert_response 200
  113 + # assert_equal 'application/json', response.content_type
  114 + # assert_equal "v1", response.body
  115 + # end
  116 + # end
  117 +#
  118 + # context "custom header" do
  119 + # before :each do
  120 + # Versionist.configure do |config|
  121 + # config.versioning_strategy = "header", {:header => "X-MY-CUSTOM-HEADER", :template => "<%=version%>"}
  122 + # config.default_version = "v1"
  123 + # end
  124 +#
  125 + # TestApi::Application.routes.draw do
  126 + # scope :module => "v1", :constraints => api_version("v1") do
  127 + # match '/foos.(:format)' => 'foos#index', :via => :get
  128 + # match '/foos_no_format' => 'foos#index', :via => :get
  129 + # end
  130 + # match '*a', :to => 'application#not_found'
  131 + # end
  132 + # end
  133 +#
  134 + # it "should not route when the configured header isn't present" do
  135 + # @headers ||= {}
  136 + # get "/foos.json", nil, @headers
  137 + # assert_response 404
  138 + # end
  139 +#
  140 + # it "should not route when the header doesn't match" do
  141 + # @headers ||= {}
  142 + # @headers["HTTP_X_MY_CUSTOM_HEADER"] = "v3"
  143 + # get "/foos.json", nil, @headers
  144 + # assert_response 404
  145 + # end
  146 +#
  147 + # it "should route to the correct controller when header matches" do
  148 + # @headers ||= {}
  149 + # @headers["HTTP_X_MY_CUSTOM_HEADER"] = "v3"
  150 + # get "/foos.json", nil, @headers
  151 + # assert_response 200
  152 + # assert_equal 'application/json', response.content_type
  153 + # assert_equal "v3", response.body
  154 + # end
  155 + # end
  156 + # end
  157 +
  158 + context "path strategy" do
  159 + it "should route to the correct controller"
  160 + end
  161 +
  162 + context "query string strategy" do
  163 + it "should route to the correct controller"
70 164 end
71 165 end
50 spec/configuration_spec.rb
... ... @@ -1,46 +1,18 @@
1 1 require 'spec_helper'
2 2
3 3 describe Versionist do
4   - context ".configure" do
5   - before :each do
6   - Versionist.configure do |config|
7   - config.versioning_strategy = "header", {:vendor_name => "mydomain.com"}
8   - config.default_version = "v1"
9   - end
10   - end
11   -
12   - it "should configure the versioning_strategy" do
13   - Versionist.configuration.versioning_strategy_name.should == "header"
14   - end
15   -
16   - it "should configure the vendor_name" do
17   - Versionist.configuration.versioning_config[:vendor_name].should == "mydomain.com"
18   - end
19   -
20   - it "should configure the default_version" do
21   - Versionist.configuration.default_version.should == "v1"
22   - end
23   -
24   - it "should validate versioning_strategy" do
25   - Versionist.configure do |config|
26   - config.versioning_strategy = "bogus"
27   - end
28   - Versionist.configuration.valid?.should == false
29   -
30   - Versionist.configure do |config|
31   - config.versioning_strategy = "bogus", {:vendor_name => "foo"}
32   - end
33   - Versionist.configuration.valid?.should == false
  4 + before :each do
  5 + Versionist.configuration.versioning_strategies.clear
  6 + end
34 7
35   - Versionist.configure do |config|
36   - config.versioning_strategy = "header"
37   - end
38   - Versionist.configuration.valid?.should == true
  8 + after :each do
  9 + Versionist.configuration.versioning_strategies.clear
  10 + end
39 11
40   - Versionist.configure do |config|
41   - config.versioning_strategy = "url"
42   - end
43   - Versionist.configuration.valid?.should == true
44   - end
  12 + it "should add versioning strategies" do
  13 + Versionist.configuration.versioning_strategies.should be_empty
  14 + Versionist::VersioningStrategy::Base.new({})
  15 + Versionist.configuration.versioning_strategies.should_not be_nil
  16 + Versionist.configuration.versioning_strategies.size.should == 1
45 17 end
46 18 end
29 spec/generators/new_api_version_generator_spec.rb
@@ -30,6 +30,31 @@ class V1::BaseController < ApplicationController
30 30 it "should create a namespaced presenters directory" do
31 31 assert_directory "app/presenters/v1"
32 32 end
  33 +
  34 + it "should create a documentation directory" do
  35 + assert_directory "public/docs/v1"
  36 + end
  37 +
  38 + it "should create a documentation index.html" do
  39 + assert_file "public/docs/v1/index.html", <<-CONTENTS
  40 +<!DOCTYPE html>
  41 +<html lang="en-US">
  42 + <head>
  43 + <title>Documentation for v1</title>
  44 + <link href="default.css" media="screen" rel="stylesheet" type="text/css">
  45 + </head>
  46 + <body>
  47 + <h1>Documentation for v1</h1>
  48 + </body>
  49 +</html>
  50 + CONTENTS
  51 + end
  52 +
  53 + it "should create a documentation style.css" do
  54 + assert_file "public/docs/v1/style.css", <<-CONTENTS
  55 +body {background-color: #fff; color: #000;}
  56 + CONTENTS
  57 + end
33 58 end
34 59
35 60 context "special characters in version name" do
@@ -51,5 +76,9 @@ class V3_4_2::BaseController < ApplicationController
51 76 it "should create a namespaced presenters directory" do
52 77 assert_directory "app/presenters/v3.4.2"
53 78 end
  79 +
  80 + it "should create a documentation directory" do
  81 + assert_directory "public/docs/v3.4.2"
  82 + end
54 83 end
55 84 end
15 spec/header_versioning_strategy_spec.rb
... ... @@ -1,15 +0,0 @@
1   -require 'spec_helper'
2   -
3   -describe Versionist::VersioningStrategy::Header do
4   - it "should raise an ArgumentError if header is not specified" do
5   - lambda {
6   - Versionist::VersioningStrategy::Header.new("v1")
7   - }.should raise_error(ArgumentError, /header must be specified for the header versioning_strategy/)
8   - end
9   -
10   - it "should raise an ArgumentError if template is not specified" do
11   - lambda {
12   - Versionist::VersioningStrategy::Header.new("v1", {:header => "Accept"})
13   - }.should raise_error(ArgumentError, /template must be specified for the header versioning_strategy/)
14   - end
15   -end
39 spec/middleware_spec.rb
... ... @@ -0,0 +1,39 @@
  1 +require 'spec_helper'
  2 +require 'rack/test'
  3 +
  4 +describe Versionist::Middleware do
  5 + before :all do
  6 + Versionist::VersioningStrategy::Header.new({:header => "Accept", :value => "application/vnd.mycompany.com-v2.3.0"})
  7 + @app = lambda {|env| [200, {"Content-Type" => "text/plain"}, [env["HTTP_ACCEPT"]]]}
  8 + end
  9 +
  10 + after :all do
  11 + Versionist.configuration.versioning_strategies.clear
  12 + end
  13 +
  14 + context "Accept header" do
  15 + it "should not alter the header if the version is not present" do
  16 + request = Rack::MockRequest.env_for("/foos", "HTTP_ACCEPT" => "application/json", :lint => true, :fatal => true)
  17 + status, headers, response = described_class.new(@app).call(request)
  18 + response[0].should == "application/json"
  19 + end
  20 +
  21 + it "should not alter the header if an unconfigured version is present" do
  22 + request = Rack::MockRequest.env_for("/foos", "HTTP_ACCEPT" => "application/vnd.mycompany.com-v1,application/json", :lint => true, :fatal => true)
  23 + status, headers, response = described_class.new(@app).call(request)
  24 + response[0].should == "application/vnd.mycompany.com-v1,application/json"
  25 + end
  26 +
  27 + it "should move the version to the end" do
  28 + request = Rack::MockRequest.env_for("/foos", "HTTP_ACCEPT" => "application/vnd.mycompany.com-v2.3.0,application/json", :lint => true, :fatal => true)
  29 + status, headers, response = described_class.new(@app).call(request)
  30 + response[0].should == "application/json, application/vnd.mycompany.com-v2.3.0"
  31 + end
  32 +
  33 + it "should move the version to the end and retain accept params" do
  34 + 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)
  35 + status, headers, response = described_class.new(@app).call(request)
  36 + response[0].should == "audio/*; q=0.2, audio/basic, application/json, application/vnd.mycompany.com-v2.3.0"
  37 + end
  38 + end
  39 +end
1  spec/spec_helper.rb
@@ -21,6 +21,7 @@
21 21
22 22 require 'versionist'
23 23 require 'fileutils'
  24 +require 'ap'
24 25
25 26 RSpec.configure do |config|
26 27 config.mock_with :rspec
6 spec/test-api/app/controllers/application_controller.rb
... ... @@ -0,0 +1,6 @@
  1 +class ApplicationController < ActionController::Base
  2 + def not_found
  3 + # just silence it
  4 + head :not_found
  5 + end
  6 +end
2  spec/test-api/app/controllers/v1/foos_controller.rb
... ... @@ -1,4 +1,4 @@
1   -class V1::FoosController < ActionController::Base
  1 +class V1::FoosController < ApplicationController
2 2 def index
3 3 render :text => "v1"
4 4 end
8 spec/test-api/app/controllers/v2.1/foos_controller.rb
... ... @@ -1,7 +1,5 @@
1   -module V2_1
2   - class FoosController < ActionController::Base
3   - def index
4   - render :text => "v2.1"
5   - end
  1 +class V2_1::FoosController < ApplicationController
  2 + def index
  3 + render :text => "v2.1"
6 4 end
7 5 end
8 spec/test-api/app/controllers/v2/foos_controller.rb
... ... @@ -1,7 +1,5 @@
1   -module V2
2   - class FoosController < ActionController::Base
3   - def index
4   - render :text => "v2"
5   - end
  1 +class V2::FoosController < ApplicationController
  2 + def index
  3 + render :text => "v2"
6 4 end
7 5 end
5 spec/test-api/config/application.rb
... ... @@ -1,5 +1,6 @@
1 1 require "action_controller/railtie"
2 2 require "sprockets/railtie"
  3 +require 'versionist/railtie'
3 4
4 5 module TestApi
5 6 class Application < Rails::Application
@@ -8,6 +9,8 @@ class Application < Rails::Application
8 9 config.active_support.deprecation = :log
9 10 config.action_controller.logger = nil
10 11 config.logger = Logger.new(STDOUT)
11   - config.log_level = Logger::Severity::FATAL
  12 + config.log_level = Logger::Severity::UNKNOWN
  13 + config.action_controller.logger = nil
  14 + config.middleware.delete Rails::Rack::Logger
12 15 end
13 16 end
22 spec/versioning_strategy/base_spec.rb
... ... @@ -0,0 +1,22 @@
  1 +require 'spec_helper'
  2 +
  3 +describe Versionist::VersioningStrategy::Base do
  4 + it "should raise an error when config nil" do
  5 + lambda {
  6 + Versionist::VersioningStrategy::Base.new(nil)
  7 + }.should raise_error(ArgumentError, /you must pass a configuration Hash/)
  8 + end
  9 +
  10 + it "should raise an error when config is not a Hash" do
  11 + lambda {
  12 + Versionist::VersioningStrategy::Base.new(1)
  13 + }.should raise_error(ArgumentError, /you must pass a configuration Hash/)
  14 + end
  15 +
  16 + it "should add self to Versionist::Configuration.versioning_strategies" do
  17 + Versionist.configuration.versioning_strategies.should be_empty
  18 + Versionist::VersioningStrategy::Base.new({})
  19 + Versionist.configuration.versioning_strategies.should_not be_empty
  20 + Versionist.configuration.versioning_strategies.size.should == 1
  21 + end
  22 +end
15 spec/versioning_strategy/header_spec.rb
... ... @@ -0,0 +1,15 @@
  1 +require 'spec_helper'
  2 +
  3 +describe Versionist::VersioningStrategy::Header do
  4 + it "should raise an ArgumentError if :header is not specified" do
  5 + lambda {
  6 + Versionist::VersioningStrategy::Header.new({:foo => :bar})
  7 + }.should raise_error(ArgumentError, /you must specify :header in the configuration Hash/)
  8 + end
  9 +
  10 + it "should raise an ArgumentError if :value is not specified" do
  11 + lambda {
  12 + Versionist::VersioningStrategy::Header.new({:header => "foo"})
  13 + }.should raise_error(ArgumentError, /you must specify :value in the configuration Hash/)
  14 + end
  15 +end
15 spec/versioning_strategy/parameter_spec.rb
... ... @@ -0,0 +1,15 @@
  1 +require 'spec_helper'
  2 +
  3 +describe Versionist::VersioningStrategy::Parameter do
  4 + it "should raise an ArgumentError if :parameter is not specified" do
  5 + lambda {
  6 + Versionist::VersioningStrategy::Parameter.new({})
  7 + }.should raise_error(ArgumentError, /you must specify :parameter in the configuration Hash/)
  8 + end
  9 +
  10 + it "should raise an ArgumentError if :value is not specified" do
  11 + lambda {
  12 + Versionist::VersioningStrategy::Parameter.new({:parameter => "version"})
  13 + }.should raise_error(ArgumentError, /you must specify :value in the configuration Hash/)
  14 + end
  15 +end
9 spec/versioning_strategy/path_spec.rb
... ... @@ -0,0 +1,9 @@
  1 +require 'spec_helper'
  2 +
  3 +describe Versionist::VersioningStrategy::Path do
  4 + it "should raise an ArgumentError if :path is not specified" do
  5 + lambda {
  6 + Versionist::VersioningStrategy::Path.new({})
  7 + }.should raise_error(ArgumentError, /you must specify :path in the configuration Hash/)
  8 + end
  9 +end
1  versionist.gemspec
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
19 19
20 20 s.add_dependency('rails', '~> 3.0')
21 21
  22 + s.add_development_dependency('awesome_print', '= 1.0.2')
22 23 s.add_development_dependency('rake', '>= 0.9.2')
23 24 s.add_development_dependency('rspec', '2.7.0')
24 25 s.add_development_dependency('rspec-rails', '2.7.0')

0 comments on commit cb187bc

Please sign in to comment.
Something went wrong with that request. Please try again.