New Upstream Snapshot - ruby-versionist
Ready changes
Summary
Merged new upstream version: 2.0.1+git20210211.1.80b09ce (was: 2.0.1).
Resulting package
Built on 2023-01-11T04:27 (took 2m44s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-snapshots ruby-versionist
Lintian Result
Diff
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..7438fbe
--- /dev/null
+++ b/.rspec
@@ -0,0 +1,2 @@
+--colour
+--format documentation
diff --git a/.rvmrc b/.rvmrc
new file mode 100644
index 0000000..8dfc6c5
--- /dev/null
+++ b/.rvmrc
@@ -0,0 +1 @@
+rvm use ruby-2.2.2@versionist --create
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..1cfe518
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,42 @@
+language: ruby
+rvm:
+ - 1.9.3
+ - 2.0.0
+ - 2.2.2
+ - 2.3.4
+ - 2.4.1
+ - jruby-18mode
+ - jruby-19mode
+ - jruby-head
+before_install: # https://github.com/travis-ci/travis-ci/issues/5861
+ - gem install bundler
+ - gem update bundler
+jdk:
+ - oraclejdk7
+matrix:
+ exclude:
+ - gemfile: gemfiles/Rails-5.0
+ rvm: 1.9.3
+ - gemfile: gemfiles/Rails-5.0
+ rvm: 2.0.0
+ - gemfile: gemfiles/Rails-5.0
+ rvm: jruby-18mode
+ - gemfile: gemfiles/Rails-5.0
+ rvm: jruby-19mode
+ - gemfile: gemfiles/Rails-5.1
+ rvm: 1.9.3
+ - gemfile: gemfiles/Rails-5.1
+ rvm: 2.0.0
+ - gemfile: gemfiles/Rails-5.1
+ rvm: jruby-18mode
+ - gemfile: gemfiles/Rails-5.1
+ rvm: jruby-19mode
+
+gemfile:
+ - gemfiles/Rails-3.0
+ - gemfiles/Rails-3.1
+ - gemfiles/Rails-3.2
+ - gemfiles/Rails-4.0
+ - gemfiles/Rails-5.0
+ - gemfiles/Rails-5.1
+ - gemfiles/RailsAPI-0.0
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ac3b0b6
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2012 Brian Ploetz (bploetz@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.markdown b/README.markdown
new file mode 100644
index 0000000..3b9e93a
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,363 @@
+# versionist
+
+[![Build Status](https://travis-ci.org/bploetz/versionist.svg?branch=master)](https://travis-ci.org/bploetz/versionist)
+
+A plugin for versioning Rails based RESTful APIs. Versionist supports three versioning strategies out of the box:
+
+- Specifying version via an HTTP header
+- Specifying version by prepending paths with a version slug
+- Specifying version via a request parameter
+
+A version of your API consists of:
+
+- Namespaced controllers/routes
+- Namespaced presenters
+- Namespaced tests
+- Documentation
+
+Versionist includes Rails generators for generating new versions of your API as well as new components within an existing version.
+
+
+## Installation
+
+Add the following dependency to your Rails application's `Gemfile` file and run `bundle install`:
+
+ gem 'versionist'
+
+
+## Configuration
+
+Versionist provides the method `api_version` that you use in your Rails application's `config/routes.rb` file to constrain a collection of routes to a specific version of your API.
+The versioning strategies used by the collection of routes constrained by `api_version` is set by specifying `:header`, `:path`, and/or `:parameter` (and their supporting values)
+in the configuration Hash passed to `api_version`. You configure the module namespace for your API version by specifying `:module` in the configuration Hash passed to `api_version`.
+
+### Upgrading from Versionist 0.x to 1.x+
+
+A backwards incompatible change was made to the format of the configuration hash passed to `api_version` starting in Versionist 1.0.
+Prior to 1.0, `api_version` expected hashes with the following structure:
+
+```ruby
+api_version(:module => "V1", :header => "Accept", :value => "application/vnd.mycompany.com; version=1") do
+ ...
+end
+```
+
+In order to support multiple concurrent versioning strategies per api version, `api_version` expects that the `:header`, `:parameter`, and `:path`
+keys point to hashes and contain the required keys.
+
+```ruby
+api_version(:module => "V1", :header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=1"}) do
+ ...
+end
+
+api_version(:module => "V1", :parameter => {:name => "version", :value => "1"}) do
+ ...
+end
+
+api_version(:module => "V1", :path => {:value => "v1"}) do
+ ...
+end
+```
+
+An error will be thrown at startup if your `config/routes.rb` file contains 0.x style `api_version` entries when running with Versionist 1.x+.
+
+## Versioning Strategies
+
+### HTTP Header
+
+This strategy uses an HTTP header to request a specific version of your API.
+
+ Accept: application/vnd.mycompany.com; version=1,application/json
+ GET /foos
+
+You configure the header to be inspected and the header value specifying the version in the configuration Hash passed to `api_version`.
+
+Examples:
+
+##### Content negotiation via the `Accept` header:
+
+```ruby
+MyApi::Application.routes.draw do
+ api_version(:module => "V1", :header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=1"}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+end
+```
+
+`Accept` Header Gotcha
+
+Please note: when your routes do not 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, Rails would
+incorrectly try to interpret it as the format. If you use the `Accept` header, Versionist will move your custom version header (if found) to the end of the `Accept` header so as to not interfere with
+Rails' format resolution logic. This is the only case where Versionist will alter the incoming request.
+
+
+##### Custom header:
+
+```ruby
+MyApi::Application.routes.draw do
+ api_version(:module => "V20120317", :header => {:name => "Api-Version", :value => "v20120317"}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+end
+```
+
+### Path
+
+This strategy uses a URL path prefix to request a specific version of your API.
+
+ GET /v3/foos
+
+You configure the path version prefix to be applied to the routes.
+
+Example:
+
+```ruby
+MyApi::Application.routes.draw do
+ api_version(:module => "V3", :path => {:value => "v3"}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+end
+```
+
+### Request Parameter
+
+This strategy uses a request parameter to request a specific version of your API.
+
+ GET /foos?version=v2
+
+You configure the parameter name and value to be applied to the routes.
+
+Example:
+
+```ruby
+MyApi::Application.routes.draw do
+ api_version(:module => "V2", :parameter => {:name => "version", :value => "v2"}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+end
+```
+
+### Default Version
+
+If a request is made to your API without specifying a specific version, by default a RoutingError (i.e. 404) will occur. You can optionally configure Versionist to
+return a specific version by default when none is specified. To specify that a version should be used as the default, include `:default => true` in the config hash
+passed to the `api_version` method.
+
+Example.
+
+```ruby
+MyApi::Application.routes.draw do
+ api_version(:module => "V20120317", :header => {:name => "Api-Version", :value => "v20120317"}, :default => true) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+end
+```
+
+If you attempt to specify more than one default version, an error will be thrown at startup.
+
+Note that when you configure a default API version, you will see the routes under your default version show up twice when running `rake routes`. This is due to the fact that Versionist adds another `scope` to your routes to handle the default case. Unfortunately `rake routes` does not show you enough contextual information to be able to differentiate the two, but this is the expected behavior.
+
+
+### Rails Route :defaults Hash
+
+The `api_version` method also supports Rails' [`:defaults`](http://guides.rubyonrails.org/routing.html#defining-defaults) hash (note that this is different than
+the `:default` key which controls the default API version described above). If a `:defaults` hash is passed to `api_version`, it will be applied to the collection
+of routes constrainted by `api_version`.
+
+Example.
+
+```ruby
+MyApi::Application.routes.draw do
+ api_version(:module => "V20120317", :header => {:name => "Api-Version", :value => "v20120317"}, :defaults => {:format => :json}, :default => true) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+end
+```
+
+## Multiple Versioning Strategies Per API Version
+
+An API version may optionally support multiple concurrent versioning strategies.
+
+Example.
+```ruby
+MyApi::Application.routes.draw do
+ api_version(:module => "V1", :header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=1"}, :path => {:value => "v1"}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+end
+```
+
+## A Note About Testing
+
+Rails functional tests (ActionController::TestCase) and RSpec Controller specs are for testing controller action methods in isolation.
+They do not go through the full Rails stack, specifically the Rails dispatcher code path, which is where versionist hooks in to do its thing.
+
+In order to test your versioned API routes, use integration tests (ActionDispatch::IntegrationTest) if you're using Test::Unit, or Request specs if you're using RSpec.
+
+Test::Unit Example:
+```ruby
+# test/integration/v1/test_controller_test.rb
+require 'test_helper'
+
+class V1::TestControllerTest < ActionDispatch::IntegrationTest
+ test "should get v1" do
+ get '/test', {}, {'Accept' => 'application/vnd.mycompany.com; version=1'}
+ assert_response 200
+ assert_equal "v1", @response.body
+ end
+end
+```
+
+RSpec Example:
+```ruby
+# spec/requests/v1/test_controller_spec.rb
+require 'spec_helper'
+
+describe V1::TestController do
+ it "should get v1" do
+ get '/test', {}, {'Accept' => 'application/vnd.mycompany.com; version=1'}
+ assert_response 200
+ assert_equal "v1", response.body
+ end
+end
+```
+
+## Generators
+
+Versionist comes with generators to facilitate managing the versions of your API. To see the available generators, simply run
+`rails generate`, and you will see the versionist generators under the `versionist` namespace.
+
+The following generators are available:
+
+### `versionist:new_api_version`
+
+creates the infrastructure for a new API version. This will create:
+
+- A new controller namespace, base controller and test
+- A new presenters namespace, base presenter and test
+- A new documentation directory and base files
+
+Usage
+
+ rails generate versionist:new_api_version <version> <module namespace> [options]
+
+Examples:
+
+ # HTTP header versioning strategy
+ rails generate versionist:new_api_version v2 V2 --header=name:Accept value:"application/vnd.mycompany.com; version=2"
+
+ # request parameter versioning strategy
+ rails generate versionist:new_api_version v2 V2 --parameter=name:version value:2
+
+ # path versioning strategy
+ rails generate versionist:new_api_version v2 V2 --path=value:v2
+
+ # multiple versioning strategies
+ rails generate versionist:new_api_version v2 V2 --header=name:Accept value:"application/vnd.mycompany.com; version=2" --parameter=name:version value:2
+
+ # default version
+ rails generate versionist:new_api_version v2 V2 --path=value:v2 --default
+
+ # route :defaults hash
+ rails generate versionist:new_api_version v2 V2 --path=value:v2 --defaults=format:json
+
+
+ rails generate versionist:new_api_version v2 V2 --header=name:Accept value:"application/vnd.mycompany.com; version=2"
+ route api_version(:module => "V2", :header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=2"}) do
+ end
+ create app/controllers/v2
+ create app/controllers/v2/base_controller.rb
+ create spec/controllers/v2
+ create spec/controllers/v2/base_controller_spec.rb
+ create spec/requests/v2
+ create spec/requests/v2/base_controller_spec.rb
+ create app/presenters/v2
+ create app/presenters/v2/base_presenter.rb
+ create spec/presenters/v2
+ create spec/presenters/v2/base_presenter_spec.rb
+ create app/helpers/v2
+ create spec/helpers/v2
+ create public/docs/v2
+ create public/docs/v2/index.html
+ create public/docs/v2/style.css
+
+
+### `versionist:new_controller`
+
+creates a new controller class with the given name under the given version module.
+
+Usage
+
+ rails generate versionist:new_controller <name> <module namespace>
+
+Example:
+
+ rails generate versionist:new_controller foos V2
+ create app/controllers/v2/foos_controller.rb
+ create spec/controllers/v2/foos_controller_spec.rb
+ create spec/requests/v2/foos_controller_spec.rb
+
+
+### `versionist:new_presenter`
+
+creates a new presenter class with the given name under the given version module.
+
+Usage
+
+ rails generate versionist:new_presenter <name> <module namespace>
+
+Example:
+
+ rails generate versionist:new_presenter foos V2
+ create app/presenters/v2/foos_presenter.rb
+ create spec/presenters/v2/foos_presenter_spec.rb
+
+
+### `versionist:copy_api_version`
+
+copies an existing API version to a new API version. This will do the following:
+
+- Copy all existing routes in config/routes.rb from the old API version to routes for the new API version in config/routes.rb (**see note below**)
+- Copy all existing controllers and tests from the old API version to the new API version
+- Copy all existing presenters and tests from the old API version to the new API version
+- Copy all existing helpers and tests from the old API version to the new API version
+- Copy all documentation from the old API version to the new API version
+
+**Note**: routes can only be copied with MRI Ruby 1.9 and above, as this feature relies on Ripper which is only available
+in stdlib in MRI Ruby 1.9 and above. Outside of routes copying, the other copy steps will work just fine in Ruby 1.8 and other
+non-MRI Ruby implementations.
+
+Usage
+
+ rails generate versionist:copy_api_version <old version> <old module namespace> <new version> <new module namespace>
+
+Example:
+
+ rails generate versionist:copy_api_version v2 V2 v3 V3
+ route api_version(:module => "V3", :header=>"Accept", :value=>"application/vnd.mycompany.com; version=3") do
+ end
+ Copying all files from app/controllers/v2 to app/controllers/v3
+ Copying all files from spec/controllers/v2 to spec/controllers/v3
+ Copying all files from app/presenters/v2 to app/presenters/v3
+ Copying all files from spec/presenters/v2 to spec/presenters/v3
+ Copying all files from app/helpers/v2 to app/helpers/v3
+ Copying all files from spec/helpers/v2 to spec/helpers/v3
+ Copying all files from public/docs/v2 to public/docs/v3
+
+## Additional Resources
+- [API Versioning using Versionist](http://www.multunus.com/blog/2014/04/api-versioning-using-versionist/)
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..0691006
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,33 @@
+GEMFILE_MAP = {"gemfiles/Rails-3.0" => "Rails 3.0", "gemfiles/Rails-3.1" => "Rails 3.1", "gemfiles/Rails-3.2" => "Rails 3.2", "gemfiles/RailsAPI-0.0" => "Rails API 0.0", "gemfiles/Rails-4.0" => "Rails 4.0", "gemfiles/Rails-4.0-RSpec3" => "RSpec 3", "gemfiles/Rails-5.0" => "Rails 5.0", "gemfiles/Rails-5.1" => "Rails 5.1"}
+
+# To run the tests locally:
+# gem install bundler
+# rake test:all
+namespace :test do
+ desc "Installs all dependencies"
+ task :setup do
+ GEMFILE_MAP.each do |gemfile, name|
+ puts "Installing gems for testing with #{name} ..."
+ sh "env BUNDLE_GEMFILE=#{File.dirname(__FILE__) + '/' + gemfile} bundle install"
+ end
+ end
+
+ GEMFILE_MAP.each do |gemfile, name|
+ desc "Run all tests against #{name}"
+ task gemfile.downcase.gsub(/\./, "_") do
+ sh "env BUNDLE_GEMFILE=#{gemfile} bundle exec rake"
+ end
+ end
+ task :all=> [:setup] + GEMFILE_MAP.map {|gemfile, name| "test:#{gemfile.downcase.gsub(/\./, "_")}"}
+end
+
+require 'rspec/core/rake_task'
+
+desc "Run all specs"
+RSpec::Core::RakeTask.new
+task :default => [:spec]
+
+task :build do
+ system "gem build versionist.gemspec"
+end
+
diff --git a/debian/changelog b/debian/changelog
index b1f5552..abf8b3e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,4 @@
-ruby-versionist (2.0.1-3) UNRELEASED; urgency=medium
+ruby-versionist (2.0.1+git20210211.1.80b09ce-1) UNRELEASED; urgency=medium
* Update watch file format version to 4.
* Bump debhelper from old 12 to 13.
@@ -9,8 +9,9 @@ ruby-versionist (2.0.1-3) UNRELEASED; urgency=medium
+ ruby-versionist: Drop versioned constraint on ruby-activesupport and
ruby-railties in Depends.
* Update standards version to 4.6.2, no changes needed.
+ * New upstream snapshot.
- -- Debian Janitor <janitor@jelmer.uk> Fri, 10 Sep 2021 13:56:58 -0000
+ -- Debian Janitor <janitor@jelmer.uk> Wed, 11 Jan 2023 04:25:48 -0000
ruby-versionist (2.0.1-2) unstable; urgency=medium
diff --git a/gemfiles/Rails-3.0 b/gemfiles/Rails-3.0
new file mode 100644
index 0000000..2dbfa51
--- /dev/null
+++ b/gemfiles/Rails-3.0
@@ -0,0 +1,14 @@
+source "http://rubygems.org"
+
+gem "rails", "~> 3.0.0"
+
+gemspec :path => "../"
+
+group :development, :test do
+ gem 'rake', '>= 0.9.2', '< 10.5.0'
+ gem 'rspec', '2.8.0'
+ gem 'rspec-rails', '2.8.0'
+ gem 'generator_spec', '0.8.5'
+ gem 'simplecov', '0.5.4'
+ gem 'test-unit'
+end
diff --git a/gemfiles/Rails-3.1 b/gemfiles/Rails-3.1
new file mode 100644
index 0000000..20c79df
--- /dev/null
+++ b/gemfiles/Rails-3.1
@@ -0,0 +1,14 @@
+source "http://rubygems.org"
+
+gem "rails", "~> 3.1.0"
+
+gemspec :path => "../"
+
+group :development, :test do
+ gem 'rake', '>= 0.9.2', '< 10.5.0'
+ gem 'rspec', '2.8.0'
+ gem 'rspec-rails', '2.8.0'
+ gem 'generator_spec', '0.8.5'
+ gem 'simplecov', '0.5.4'
+ gem 'test-unit'
+end
diff --git a/gemfiles/Rails-3.2 b/gemfiles/Rails-3.2
new file mode 100644
index 0000000..2280c5f
--- /dev/null
+++ b/gemfiles/Rails-3.2
@@ -0,0 +1,14 @@
+source "http://rubygems.org"
+
+gem "rails", "~> 3.2.0"
+
+gemspec :path => "../"
+
+group :development, :test do
+ gem 'rake', '>= 0.9.2', '< 10.5.0'
+ gem 'rspec', '2.8.0'
+ gem 'rspec-rails', '2.8.0'
+ gem 'generator_spec', '0.8.5'
+ gem 'simplecov', '0.5.4'
+ gem 'test-unit'
+end
diff --git a/gemfiles/Rails-4.0 b/gemfiles/Rails-4.0
new file mode 100644
index 0000000..7ce4090
--- /dev/null
+++ b/gemfiles/Rails-4.0
@@ -0,0 +1,13 @@
+source "http://rubygems.org"
+
+gem "rails", "4.0.0"
+
+gemspec :path => "../"
+
+group :development, :test do
+ gem 'rake'
+ gem 'rspec', '>= 2.13.0'
+ gem 'rspec-rails', '>= 2.13.0'
+ gem 'generator_spec', '0.9.0'
+ gem 'simplecov'
+end
diff --git a/gemfiles/Rails-4.0-RSpec3 b/gemfiles/Rails-4.0-RSpec3
new file mode 100644
index 0000000..d08a92c
--- /dev/null
+++ b/gemfiles/Rails-4.0-RSpec3
@@ -0,0 +1,13 @@
+source "http://rubygems.org"
+
+gem "rails", "4.0.0"
+
+gemspec :path => "../"
+
+group :development, :test do
+ gem 'rake'
+ gem 'rspec', '>= 3'
+ gem 'rspec-rails', '>= 3'
+ gem 'generator_spec', '0.9.0'
+ gem 'simplecov'
+end
diff --git a/gemfiles/Rails-5.0 b/gemfiles/Rails-5.0
new file mode 100644
index 0000000..ce093d4
--- /dev/null
+++ b/gemfiles/Rails-5.0
@@ -0,0 +1,13 @@
+source "http://rubygems.org"
+
+gem "rails", "5.0.0"
+
+gemspec :path => "../"
+
+group :development, :test do
+ gem 'rake'
+ gem 'rspec', '>= 2.13.0'
+ gem 'rspec-rails', '>= 2.13.0'
+ gem 'generator_spec'
+ gem 'simplecov'
+end
diff --git a/gemfiles/Rails-5.1 b/gemfiles/Rails-5.1
new file mode 100644
index 0000000..ac104b9
--- /dev/null
+++ b/gemfiles/Rails-5.1
@@ -0,0 +1,13 @@
+source "http://rubygems.org"
+
+gem "rails", "5.1.0"
+
+gemspec :path => "../"
+
+group :development, :test do
+ gem 'rake'
+ gem 'rspec', '>= 2.13.0'
+ gem 'rspec-rails', '>= 2.13.0'
+ gem 'generator_spec'
+ gem 'simplecov'
+end
diff --git a/gemfiles/RailsAPI-0.0 b/gemfiles/RailsAPI-0.0
new file mode 100644
index 0000000..122c674
--- /dev/null
+++ b/gemfiles/RailsAPI-0.0
@@ -0,0 +1,14 @@
+source "http://rubygems.org"
+
+gem "rails-api", "~> 0.0"
+
+gemspec :path => "../"
+
+group :development, :test do
+ gem 'rake', '>= 0.9.2', '< 10.5.0'
+ gem 'rspec', '2.8.0'
+ gem 'rspec-rails', '2.8.0'
+ gem 'generator_spec', '0.8.5'
+ gem 'simplecov', '0.5.4'
+ gem 'test-unit'
+end
diff --git a/spec/api_routing_spec.rb b/spec/api_routing_spec.rb
new file mode 100644
index 0000000..946607c
--- /dev/null
+++ b/spec/api_routing_spec.rb
@@ -0,0 +1,1037 @@
+require 'spec_helper'
+require 'rspec/rails'
+
+describe Versionist::Routing do
+ include RSpec::Rails::RequestExampleGroup
+
+ before :all do
+ ENV["RAILS_ENV"] = 'test'
+ require File.expand_path("../test-api/config/application", __FILE__)
+ TestApi::Application.initialize!
+ end
+
+ context "#api_version" do
+ before :each do
+ Versionist.configuration.clear!
+ TestApi::Application.routes.clear!
+ end
+
+ it "should raise an error when config nil" do
+ lambda {
+ TestApi::Application.routes.draw do
+ 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
+ api_version(1)
+ end
+ }.should raise_error(ArgumentError, /you must pass a configuration Hash to api_version/)
+ end
+
+ it "should raise an error when config doesn't contain any supported strategies" do
+ lambda {
+ TestApi::Application.routes.draw do
+ api_version({})
+ end
+ }.should raise_error(ArgumentError, /you must specify :header, :path, or :parameter in configuration Hash passed to api_version/)
+ end
+
+ it "should raise an error when strategy key doesn't point to a Hash" do
+ [:header, :path, :parameter].each do |s|
+ lambda {
+ TestApi::Application.routes.draw do
+ api_version({s => 1})
+ end
+ }.should raise_error(ArgumentError, /#{s} key in configuration Hash passed to api_version must point to a Hash/)
+ end
+ end
+
+ it "should raise an error when config doesn't contain :module" do
+ lambda {
+ TestApi::Application.routes.draw do
+ api_version({:path => {:value => "v1"}})
+ end
+ }.should raise_error(ArgumentError, /you must specify :module in configuration Hash passed to api_version/)
+ end
+
+ it "should raise an error when config contains a :defaults key which isn't a Hash" do
+ lambda {
+ TestApi::Application.routes.draw do
+ api_version({:module => "V1", :path => {:value => "v1"}, :defaults => 1})
+ end
+ }.should raise_error(ArgumentError, /:defaults must be a Hash/)
+ end
+
+ it "should add the middleware" do
+ TestApi::Application.routes.draw do
+ api_version({:module => "v1", :header => {:name => "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
+ TestApi::Application.config.middleware.should include(Versionist::Middleware)
+ end
+
+ {"v1" => "v1", "v1" => "V1", "v2" => "v2", "v2" => "V2", "v2.1" => "v2__1", "v2.1" => "V2__1", "v3" => "Api::V3", "v3" => "api/v3"}.each do |ver, mod|
+ # Skip module names with underscores in Rails 3.2+
+ # https://github.com/rails/rails/issues/5849
+ next if ((Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR == 2) || (Rails::VERSION::MAJOR >= 4)) && mod.include?('_')
+ context ver do
+ before :each do
+ @headers = Hash.new
+ end
+
+ context ":header" do
+ context "Accept" do
+ before :each do
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :header => {:name => "Accept", :value => "application/vnd.mycompany.com-#{ver}"}}) 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', :via => :get
+ end
+ end
+
+ it "should not route when header isn't present" do
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 404
+ end
+
+ it "should not route when header doesn't match" do
+ @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v4"
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 404
+ end
+
+ it "should route to the correct controller when header matches" do
+ @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-#{ver}"
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ if older_than_rails_5?
+ get "/foos.xml", nil, @headers
+ else
+ get "/foos.xml", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+ end
+
+ it "should route to the correct controller when format specified via accept header" do
+ @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-#{ver},application/json"
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = "application/xml, application/vnd.mycompany.com-#{ver}"
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = "application/xml, application/vnd.mycompany.com-#{ver}, application/json"
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+ end
+
+ context ":default => true" do
+ before :each do
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :header => {:name => "Accept", :value => "application/vnd.mycompany.com-#{ver}"}, :default => true}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ end
+ api_version({:module => "not_default", :header => {:name => "Accept", :value => "application/vnd.mycompany.com-not_default"}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ end
+ end
+ end
+
+ it "should route to the default when no version given" do
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = ""
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = " "
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+ end
+
+ it "should not route to the default when another configured version is given" do
+ @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-not_default"
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal "not_default", response.body
+ end
+ end
+
+ context ":defaults" do
+ it "should pass the :defaults hash on to the scope() call" do
+ ActionDispatch::Routing::Mapper.any_instance.should_receive(:scope).with(hash_including(:defaults => {:format => :json}))
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :header => {:name => "Accept", :value => "application/vnd.mycompany.com-#{ver}"}, :defaults => {:format => :json}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+ end
+ end
+ end
+ end
+
+ context "Accept with parameters" do
+ before :each do
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=#{ver}"}}) 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', :via => :get
+ end
+ end
+
+ it "should not route when header isn't present" do
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 404
+ end
+
+ it "should not route when header doesn't match" do
+ @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com; version=v4"
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 404
+ end
+
+ it "should route to the correct controller when header matches" do
+ @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com; version=#{ver}"
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ if older_than_rails_5?
+ get "/foos.xml", nil, @headers
+ else
+ get "/foos.xml", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+ end
+
+ it "should route to the correct controller when format specified via accept header" do
+ @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com; version=#{ver},application/json"
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = "application/xml, application/vnd.mycompany.com; version=#{ver}"
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = "application/xml, application/vnd.mycompany.com; version=#{ver}, application/json"
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+ end
+
+ context ":default => true" do
+ before :each do
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=#{ver}"}, :default => true}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ end
+ api_version({:module => "not_default", :header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=not_default"}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ end
+ end
+ end
+
+ it "should route to the default when no version given" do
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = ""
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = " "
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+ end
+
+ it "should not route to the default when another configured version is given" do
+ @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com; version=not_default"
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal "not_default", response.body
+ end
+ end
+
+ context ":defaults" do
+ it "should pass the :defaults hash on to the scope() call" do
+ ActionDispatch::Routing::Mapper.any_instance.should_receive(:scope).with(hash_including(:defaults => {:format => :json}))
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=#{ver}"}, :defaults => {:format => :json}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+ end
+ end
+ end
+ end
+
+ context "custom header" do
+ before :each do
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :header => {:name => "API-VERSION", :value => ver}}) 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', :via => :get
+ end
+ end
+
+ it "should not route when header isn't present" do
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 404
+ end
+
+ it "should not route when header doesn't match" do
+ @headers["API_VERSION"] = "v3"
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 404
+ end
+
+ it "should route to the correct controller when header matches" do
+ @headers["HTTP_API_VERSION"] = ver
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ if older_than_rails_5?
+ get "/foos.xml", nil, @headers
+ else
+ get "/foos.xml", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+ end
+
+ it "should route to the correct controller when format specified via accept header" do
+ @headers["HTTP_ACCEPT"] = "application/json,application/xml"
+ @headers["HTTP_API_VERSION"] = ver
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = "application/xml,application/json"
+ @headers["HTTP_API_VERSION"] = ver
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+ end
+
+ context ":default => true" do
+ before :each do
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :header => {:name => "API-VERSION", :value => ver}, :default => true}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ end
+ api_version({:module => "not_default", :header => {:name => "API-VERSION", :value => "not_default"}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ end
+ end
+ end
+
+ it "should route to the default when no version given" do
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_API_VERSION"] = ""
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_API_VERSION"] = " "
+ if older_than_rails_5?
+ get "/foos.xml", nil, @headers
+ else
+ get "/foos.xml", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+ end
+
+ it "should not route to the default when another configured version is given" do
+ @headers["HTTP_API_VERSION"] = "not_default"
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal "not_default", response.body
+ end
+ end
+
+ context ":defaults" do
+ it "should pass the :defaults hash on to the scope() call" do
+ ActionDispatch::Routing::Mapper.any_instance.should_receive(:scope).with(hash_including(:defaults => {:format => :json}))
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :header => {:name => "API-VERSION", :value => ver}, :defaults => {:format => :json}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+ end
+ end
+ end
+ end
+ end
+
+ context ":path" do
+ before :each do
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :path => {:value => "/#{ver}"}}) 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', :via => :get
+ end
+ end
+
+ it "should not route when path isn't present" do
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 404
+ end
+
+ it "should not route when path doesn't match" do
+ if older_than_rails_5?
+ get "/bogu/foos.json", nil, @headers
+ else
+ get "/bogus/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 404
+ end
+
+ it "should route to the correct controller when path matches" do
+ if older_than_rails_5?
+ get "/#{ver}/foos.json", nil, @headers
+ else
+ get "/#{ver}/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ if older_than_rails_5?
+ get "/#{ver}/bars.json", nil, @headers
+ else
+ get "/#{ver}/bars.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ if older_than_rails_5?
+ get "/#{ver}/foos.xml", nil, @headers
+ else
+ get "/#{ver}/foos.xml", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+
+ if older_than_rails_5?
+ get "/#{ver}/bars.xml", nil, @headers
+ else
+ get "/#{ver}/bars.xml", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+ end
+
+ it "should route to the correct controller when path matches and format specified via accept header" do
+ @headers["HTTP_ACCEPT"] = "application/json,application/xml"
+ if older_than_rails_5?
+ get "/#{ver}/foos_no_format", nil, @headers
+ else
+ get "/#{ver}/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = "application/xml,application/json"
+ if older_than_rails_5?
+ get "/#{ver}/foos_no_format", nil, @headers
+ else
+ get "/#{ver}/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+ end
+
+ context ":default => true" do
+ before :each do
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :path => {:value => "/#{ver}"}, :default => true}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ resources :bars
+ end
+ api_version({:module => "not_default", :path => {:value => "/not_default"}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ resources :bars
+ end
+ end
+ end
+
+ it "should route to the default when no version given" do
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ if older_than_rails_5?
+ get "/#{ver}/bars.json", nil, @headers
+ else
+ get "/#{ver}/bars.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ if older_than_rails_5?
+ get "/foos.xml", nil, @headers
+ else
+ get "/foos.xml", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+
+ if older_than_rails_5?
+ get "/#{ver}/bars.xml", nil, @headers
+ else
+ get "/#{ver}/bars.xml", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+ end
+
+ it "should not route to the default when another configured version is given" do
+ if older_than_rails_5?
+ get "/not_default/foos.json", nil, @headers
+ else
+ get "/not_default/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal "not_default", response.body
+ end
+ end
+
+ context ":defaults" do
+ it "should pass the :defaults hash on to the namespace() call" do
+ ActionDispatch::Routing::Mapper.any_instance.should_receive(:namespace).with("#{ver}", hash_including(:defaults => {:format => :json}))
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :path => {:value => "/#{ver}"}, :defaults => {:format => :json}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+ end
+ end
+
+ it "should pass the :defaults hash on to the namespace() call and the scope() call when :default is present" do
+ ActionDispatch::Routing::Mapper.any_instance.should_receive(:namespace).with("#{ver}", hash_including(:defaults => {:format => :json}))
+ ActionDispatch::Routing::Mapper.any_instance.should_receive(:scope).with(hash_including(:defaults => {:format => :json}))
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :path => {:value => "/#{ver}"}, :default => true, :defaults => {:format => :json}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+ end
+ end
+ end
+ end
+
+ context ":parameter" do
+ before :each do
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :parameter => {:name => "version", :value => ver}}) 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', :via => :get
+ end
+ end
+
+ it "should not route when parameter isn't present" do
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 404
+ end
+
+ it "should not route when parameter doesn't match" do
+ if older_than_rails_5?
+ get "/foos.json?version=3", nil, @headers
+ else
+ get "/foos.json?version=3", :params => nil, :headers => @headers
+ end
+ assert_response 404
+ end
+
+ it "should route to the correct controller when parameter matches" do
+ if older_than_rails_5?
+ get "/foos.json?version=#{ver}", nil, @headers
+ else
+ get "/foos.json?version=#{ver}", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ if older_than_rails_5?
+ get "/foos.xml?version=#{ver}", nil, @headers
+ else
+ get "/foos.xml?version=#{ver}", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+ end
+
+ it "should route to the correct controller when parameter matches and format specified via accept header" do
+ @headers["HTTP_ACCEPT"] = "application/json,application/xml"
+ if older_than_rails_5?
+ get "/foos_no_format?version=#{ver}", nil, @headers
+ else
+ get "/foos_no_format?version=#{ver}", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = "application/xml,application/json"
+ if older_than_rails_5?
+ get "/foos_no_format?version=#{ver}", nil, @headers
+ else
+ get "/foos_no_format?version=#{ver}", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal ver, response.body
+ end
+
+ context ":default => true" do
+ before :each do
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :parameter => {:name => "version", :value => ver}, :default => true}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ end
+ api_version({:module => "not_default", :parameter => {:name => "version", :value => "not_default"}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ end
+ end
+ end
+
+ it "should route to the default when no version given" do
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ if older_than_rails_5?
+ get "/foos.json?version=", nil, @headers
+ else
+ get "/foos.json?version=", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+ end
+
+ it "should not route to the default when another configured version is given" do
+ if older_than_rails_5?
+ get "/foos.json?version=not_default", nil, @headers
+ else
+ get "/foos.json?version=not_default", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal "not_default", response.body
+ end
+ end
+
+ context ":defaults" do
+ it "should pass the :defaults hash on to the scope() call" do
+ ActionDispatch::Routing::Mapper.any_instance.should_receive(:scope).with(hash_including(:defaults => {:format => :json}))
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :parameter => {:name => "version", :value => ver}, :defaults => {:format => :json}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+ end
+ end
+ end
+ end
+
+ context "multi-strategy :default => true" do
+ before :each do
+ TestApi::Application.routes.draw do
+ api_version({:module => mod, :header => {:name => "Accept", :value => "application/vnd.mycompany.com-#{ver}"}, :parameter => {:name => "version", :value => "#{ver}"}, :default => true}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ end
+ api_version({:module => "not_default", :header => {:name => "Accept", :value => "application/vnd.mycompany.com-not_default"}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ end
+ end
+ end
+
+ it "should route to the default when no version given" do
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = ""
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+
+ @headers["HTTP_ACCEPT"] = " "
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal ver, response.body
+ end
+
+ it "should not route to the default when another configured version is given" do
+ @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-not_default"
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal "not_default", response.body
+ end
+ end
+ end
+ end
+
+ context "Accept header version substring matches" do
+ before :each do
+ @headers = Hash.new
+
+ TestApi::Application.routes.draw do
+ api_version({:module => "v1", :header => {:name => "Accept", :value => "application/vnd.mycompany.com-v1"}, :default => true}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+
+ api_version({:module => "v11", :header => {:name => "Accept", :value => "application/vnd.mycompany.com-v11"}}) do
+ match '/foos.(:format)' => 'foos#index', :via => :get
+ match '/foos_no_format' => 'foos#index', :via => :get
+ resources :bars
+ end
+ end
+ end
+
+ it "should route to the correct controller" do
+ @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v1"
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal "v1", response.body
+
+ @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v1"
+ if older_than_rails_5?
+ get "/foos.json", nil, @headers
+ else
+ get "/foos.json", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal "v1", response.body
+
+ # default routing
+ if older_than_rails_5?
+ get "/foos.json", nil, {}
+ else
+ get "/foos.json", :params => nil, :headers => {}
+ end
+ 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["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v1,application/json"
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal "v1", response.body
+
+ @headers["HTTP_ACCEPT"] = "application/xml, application/vnd.mycompany.com-v1"
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal "v1", response.body
+
+ @headers["HTTP_ACCEPT"] = "application/xml, application/vnd.mycompany.com-v1, application/json"
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal "v1", response.body
+
+ @headers["HTTP_ACCEPT"] = "application/vnd.mycompany.com-v11,application/json"
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/json', response.content_type
+ assert_equal "v11", response.body
+
+ @headers["HTTP_ACCEPT"] = "application/xml, application/vnd.mycompany.com-v11"
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal "v11", response.body
+
+ @headers["HTTP_ACCEPT"] = "application/xml, application/vnd.mycompany.com-v11, application/json"
+ if older_than_rails_5?
+ get "/foos_no_format", nil, @headers
+ else
+ get "/foos_no_format", :params => nil, :headers => @headers
+ end
+ assert_response 200
+ assert_equal 'application/xml', response.content_type
+ assert_equal "v11", response.body
+ end
+ end
+ end
+
+ context "route reloading" do
+ it "should handle Rails.application.reload_routes!" do
+ lambda {
+ Rails.application.reload_routes!
+ Rails.application.reload_routes!
+ }.should_not raise_error
+ end
+ end
+end
diff --git a/spec/generators/copy_api_version_generator_spec.rb b/spec/generators/copy_api_version_generator_spec.rb
new file mode 100644
index 0000000..7c882c1
--- /dev/null
+++ b/spec/generators/copy_api_version_generator_spec.rb
@@ -0,0 +1,451 @@
+require 'spec_helper'
+require 'generator_spec/test_case'
+
+describe Versionist::CopyApiVersionGenerator do
+ include GeneratorSpec::TestCase
+ include Versionist::InflectorFixes
+
+ destination File.expand_path("../../tmp", __FILE__)
+
+ before :each do
+ prepare_destination
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers", __FILE__))
+ ::Dir.mkdir(::File.expand_path("../../tmp/config", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ end
+
+ {"v1" => "V1", "v2" => "V2", "v2.1" => "V2_1", "v20120119" => "Api::V20120119"}.each do |ver, mod|
+ context "#{ver} => #{mod}" do
+ context "api version doesn't exist" do
+ before :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\nend"}
+ end
+
+ after :each do
+ if older_than_rails_5?
+ ::FileUtils.rm_rf(::File.expand_path("../../tmp/test/integration/#{module_name_for_path(mod)}", __FILE__))
+ end
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.rm_rf(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.rm_rf(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.rm_rf(::File.expand_path("../../tmp/app/helpers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.rm_rf(::File.expand_path("../../tmp/#{test_path}/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.rm_rf(::File.expand_path("../../tmp/spec/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.rm_rf(::File.expand_path("../../tmp/spec/requests/#{module_name_for_path(mod)}", __FILE__))
+ Versionist.configuration.configured_test_framework = nil
+ end
+
+ it "should not raise an error if old version not found config/routes.rb" do
+ lambda {
+ run_generator [ver, mod, "x", "X", {}]
+ }.should_not raise_error
+ end
+
+ it "should not raise an error if old version module not found in app/controllers" do
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-#{ver}\") do\n end\nend"}
+ lambda {
+ run_generator [ver, mod, "x", "X", {}]
+ }.should_not raise_error
+ end
+
+ it "should not raise an error if old version module not found in test path when Test::Unit is the test framework" do
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-#{ver}\") do\n end\nend"}
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}", __FILE__))
+ Versionist.configuration.configured_test_framework = :test_unit
+ lambda {
+ run_generator [ver, mod, "x", "X", {}]
+ }.should_not raise_error
+ end
+
+ it "should not raise an error if old version module not found in test/integration when Test::Unit is the test framework" do
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-#{ver}\") do\n end\nend"}
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}", __FILE__))
+ Versionist.configuration.configured_test_framework = :test_unit
+ lambda {
+ run_generator [ver, mod, "x", "X", {}]
+ }.should_not raise_error
+ end
+
+ it "should not raise an error if old version module not found in spec/controllers when rspec is the test framework" do
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-#{ver}\") do\n end\nend"}
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}", __FILE__))
+ Versionist.configuration.configured_test_framework = :rspec
+ lambda {
+ run_generator [ver, mod, "x", "X", {}]
+ }.should_not raise_error
+ end
+
+ it "should not raise an error if old version module not found in spec/requests when rspec is the test framework" do
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-#{ver}\") do\n end\nend"}
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}", __FILE__))
+ Versionist.configuration.configured_test_framework = :rspec
+ lambda {
+ run_generator [ver, mod, "x", "X", {}]
+ }.should_not raise_error
+ end
+
+ it "should not raise an error if old version module not found in app/presenters" do
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-#{ver}\") do\n end\nend"}
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec/controllers/#{module_name_for_path(mod)}", __FILE__))
+ Versionist.configuration.configured_test_framework = :rspec
+ lambda {
+ run_generator [ver, mod, "x", "X", {}]
+ }.should_not raise_error
+ end
+
+ it "should not raise an error if old version module not found in test/presenters when Test::Unit is the test framework" do
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-#{ver}\") do\n end\nend"}
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/#{test_path}/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}", __FILE__))
+ Versionist.configuration.configured_test_framework = :test_unit
+ lambda {
+ run_generator [ver, mod, "x", "X", {}]
+ }.should_not raise_error
+ end
+
+ it "should not raise an error if old version module not found in spec/presenters when rspec is the test framework" do
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-#{ver}\") do\n end\nend"}
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}", __FILE__))
+ Versionist.configuration.configured_test_framework = :rspec
+ lambda {
+ run_generator [ver, mod, "x", "X", {}]
+ }.should_not raise_error
+ end
+
+ it "should not raise an error if old version not found in public/docs" do
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-#{ver}\") do\n end\nend"}
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec/presenters/#{module_name_for_path(mod)}", __FILE__))
+ Versionist.configuration.configured_test_framework = :rspec
+ lambda {
+ run_generator [ver, mod, "x", "X", {}]
+ }.should_not raise_error
+ end
+ end
+
+ context "api version exists" do
+ before :each do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec/presenters/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/helpers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec/helpers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/public/docs/#{ver}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-#{ver}\") do\n end\nend"}
+ ::File.open(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}/base_controller.rb", __FILE__), "w") {|f| f.write "class #{mod}::BaseController < ApplicationController\nend"}
+ ::File.open(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}/foos_controller.rb", __FILE__), "w") {|f| f.write "class #{mod}::FoosController < #{mod}::BaseController\nend"}
+ ::File.open(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}/base_presenter.rb", __FILE__), "w") {|f| f.write "class #{mod}::BasePresenter\n\n def initialize(#{ver})\n @#{ver} = #{ver}\n end\n\n def as_json(options={})\n # fill me in...\n end\n\n def to_xml(options={}, &block)\n xml = options[:builder] ||= Builder::XmlMarkup.new\n # fill me in...\n end\nend"}
+ ::File.open(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}/foo_presenter.rb", __FILE__), "w") {|f| f.write "class #{mod}::FooPresenter < #{mod}::BasePresenter\n\n def initialize(#{ver})\n @#{ver} = #{ver}\n end\n\n def as_json(options={})\n # fill me in...\n end\n\n def to_xml(options={}, &block)\n xml = options[:builder] ||= Builder::XmlMarkup.new\n # fill me in...\n end\nend"}
+ ::File.open(::File.expand_path("../../tmp/app/helpers/#{module_name_for_path(mod)}/foos_helper.rb", __FILE__), "w") {|f| f.write "module #{mod}::FoosHelper\n\n def help\n end\nend"}
+ ::File.open(::File.expand_path("../../tmp/public/docs/#{ver}/style.css", __FILE__), "w") {|f| f.write "body {margin: 0; background-color: #fff; color: #000; font-family: Arial,sans-serif;}\ncontent {margin-left: 200px;}\ncontent h1 {text-align: center;}\noperations {float: left; width: 200px; border-right: 1px solid #ccc;}\noperations h3 {text-align: center;}"}
+ ::File.open(::File.expand_path("../../tmp/public/docs/#{ver}/index.html", __FILE__), "w") {|f| f.write "<!DOCTYPE html>\n<html lang=\"en-US\">\n <head>\n <title>Documentation for #{ver}</title>\n <link href=\"#{ver}/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\">\n </head>\n <body>\n <div id=\"container\">\n <div id=\"operations\">\n <h3>API Operations</h3>\n </div>\n <div id=\"content\">\n <h1>Documentation for #{ver}</h1>\n </div>\n </div>\n </body>\n</html>"}
+ Versionist.configuration.configured_test_framework = nil
+ run_generator [ver, mod, "x", "X"]
+ end
+
+ it "should copy correct api_version to config/routes.rb" do
+ if RUBY_VERSION =~ /1.9/ && defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby"
+ assert_file "config/routes.rb"
+ expected = <<-CONTENTS
+Test::Application.routes.draw do
+ api_version(:module => \"X\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-x\") do
+ end
+
+ api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-#{ver}\") do
+ end
+end
+ CONTENTS
+
+ # Rails 4 removed the trailing newline from the 'route' generator
+ # https://github.com/rails/rails/commit/7cdb12286639b38db2eb1e9fd0c8b2e6bc3b39dc
+ if Rails::VERSION::MAJOR < 4
+ assert_file "config/routes.rb", expected.chop
+ elsif Rails::VERSION::MAJOR == 4
+ assert_file "config/routes.rb", expected.gsub(/^$\n/, '').chop
+ end
+ end
+ end
+
+ it "should copy old controllers to new controllers" do
+ expected_base_controller = <<-BASE
+class X::BaseController < ApplicationController
+end
+ BASE
+
+ expected_foos_controller = <<-FOOS
+class X::FoosController < X::BaseController
+end
+ FOOS
+
+ assert_file "app/controllers/#{module_name_for_path("X")}/base_controller.rb", expected_base_controller.chop
+ assert_file "app/controllers/#{module_name_for_path("X")}/foos_controller.rb", expected_foos_controller.chop
+ end
+
+ it "should copy old presenters to new presenters" do
+ expected_base_presenter = <<-BASE
+class X::BasePresenter
+
+ def initialize(#{ver})
+ @#{ver} = #{ver}
+ end
+
+ def as_json(options={})
+ # fill me in...
+ end
+
+ def to_xml(options={}, &block)
+ xml = options[:builder] ||= Builder::XmlMarkup.new
+ # fill me in...
+ end
+end
+ BASE
+
+ expected_foo_presenter = <<-FOOS
+class X::FooPresenter < X::BasePresenter
+
+ def initialize(#{ver})
+ @#{ver} = #{ver}
+ end
+
+ def as_json(options={})
+ # fill me in...
+ end
+
+ def to_xml(options={}, &block)
+ xml = options[:builder] ||= Builder::XmlMarkup.new
+ # fill me in...
+ end
+end
+ FOOS
+
+ assert_file "app/presenters/#{module_name_for_path("X")}/base_presenter.rb", expected_base_presenter.chop
+ assert_file "app/presenters/#{module_name_for_path("X")}/foo_presenter.rb", expected_foo_presenter.chop
+ end
+
+ it "should copy old helpers to new helpers" do
+ expected_foos_helper = <<-DOC
+module X::FoosHelper
+
+ def help
+ end
+end
+ DOC
+
+ assert_file "app/helpers/#{module_name_for_path("X")}/foos_helper.rb", expected_foos_helper.chop
+ end
+
+ it "should copy documentation" do
+ assert_file "public/docs/x/style.css"
+ assert_file "public/docs/x/index.html"
+ end
+
+ context "test_framework: test_unit" do
+ before :each do
+ if older_than_rails_5?
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/test/integration/#{module_name_for_path(mod)}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/test/integration/#{module_name_for_path(mod)}/base_controller_test.rb", __FILE__), "w") {|f| f.write "require 'test_helper'\n\nclass #{mod}::BaseControllerTest < ActionDispatch::IntegrationTest\n # Replace this with your real tests.\n test \"the truth\" do\n assert true\n end\nend"}
+ ::File.open(::File.expand_path("../../tmp/test/integration/#{module_name_for_path(mod)}/foos_controller_test.rb", __FILE__), "w") {|f| f.write "require 'test_helper'\n\nclass #{mod}::FoosControllerTest < ActionDispatch::IntegrationTest\n # Replace this with your real tests.\n test \"the truth\" do\n assert true\n end\nend"}
+ end
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/#{test_path}/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/test/presenters/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/test/helpers/#{module_name_for_path(mod)}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/#{test_path}/#{module_name_for_path(mod)}/base_controller_test.rb", __FILE__), "w") {|f| f.write "require 'test_helper'\n\nclass #{mod}::BaseControllerTest < ActionController::TestCase\n # Replace this with your real tests.\n test \"the truth\" do\n assert true\n end\nend"}
+ ::File.open(::File.expand_path("../../tmp/#{test_path}/#{module_name_for_path(mod)}/foos_controller_test.rb", __FILE__), "w") {|f| f.write "require 'test_helper'\n\nclass #{mod}::FoosControllerTest < ActionController::TestCase\n # Replace this with your real tests.\n test \"the truth\" do\n assert true\n end\nend"}
+ ::File.open(::File.expand_path("../../tmp/test/presenters/#{module_name_for_path(mod)}/base_presenter_test.rb", __FILE__), "w") {|f| f.write "require 'test_helper'\n\nclass #{mod}::BasePresenterTest < Test::Unit::TestCase\n # Replace this with your real tests.\n test \"the truth\" do\n assert true\n end\nend"}
+ ::File.open(::File.expand_path("../../tmp/test/presenters/#{module_name_for_path(mod)}/foo_presenter_test.rb", __FILE__), "w") {|f| f.write "require 'test_helper'\n\nclass #{mod}::FooPresenterTest < Test::Unit::TestCase\n # Replace this with your real tests.\n test \"the truth\" do\n assert true\n end\nend"}
+ ::File.open(::File.expand_path("../../tmp/test/helpers/#{module_name_for_path(mod)}/foos_helper_test.rb", __FILE__), "w") {|f| f.write "require 'test_helper'\n\nclass #{mod}::FoosHelperTest < Test::Unit::TestCase\n # Replace this with your real tests.\n test \"the truth\" do\n assert true\n end\nend"}
+ Versionist.configuration.configured_test_framework = :test_unit
+ run_generator [ver, mod, "x", "X"]
+ end
+
+ it "should copy old controller tests to new controller tests" do
+ expected_base_controller_functional_test = <<-BASE
+require 'test_helper'
+
+class X::BaseControllerTest < ActionController::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ BASE
+
+ if older_than_rails_5?
+ expected_base_controller_integration_test = <<-BASE
+require 'test_helper'
+
+class X::BaseControllerTest < ActionDispatch::IntegrationTest
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ BASE
+ end
+
+ expected_foos_controller_functional_test = <<-FOOS
+require 'test_helper'
+
+class X::FoosControllerTest < ActionController::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ FOOS
+
+ if older_than_rails_5?
+ expected_foos_controller_integration_test = <<-FOOS
+require 'test_helper'
+
+class X::FoosControllerTest < ActionDispatch::IntegrationTest
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ FOOS
+ end
+
+
+ assert_file "#{test_path}/#{module_name_for_path("X")}/base_controller_test.rb", expected_base_controller_functional_test.chop
+ assert_file "#{test_path}/#{module_name_for_path("X")}/foos_controller_test.rb", expected_foos_controller_functional_test.chop
+ if older_than_rails_5?
+ assert_file "test/integration/#{module_name_for_path("X")}/base_controller_test.rb", expected_base_controller_integration_test.chop
+ assert_file "test/integration/#{module_name_for_path("X")}/foos_controller_test.rb", expected_foos_controller_integration_test.chop
+ end
+ end
+
+ it "should copy old presenter tests to new presenter tests" do
+ expected_base_presenter_test = <<-BASE
+require 'test_helper'
+
+class X::BasePresenterTest < Test::Unit::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ BASE
+
+ expected_foo_presenter_test = <<-FOOS
+require 'test_helper'
+
+class X::FooPresenterTest < Test::Unit::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ FOOS
+
+ assert_file "test/presenters/#{module_name_for_path("X")}/base_presenter_test.rb", expected_base_presenter_test.chop
+ assert_file "test/presenters/#{module_name_for_path("X")}/foo_presenter_test.rb", expected_foo_presenter_test.chop
+ end
+
+ it "should copy old helper tests to new helper tests" do
+ expected_foos_helper_test = <<-DOC
+require 'test_helper'
+
+class X::FoosHelperTest < Test::Unit::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ DOC
+
+ assert_file "test/helpers/#{module_name_for_path("X")}/foos_helper_test.rb", expected_foos_helper_test.chop
+ end
+ end
+
+ context "test_framework: rspec" do
+ before :each do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec/requests/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec/presenters/#{module_name_for_path(mod)}", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec/helpers/#{module_name_for_path(mod)}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/spec/controllers/#{module_name_for_path(mod)}/base_controller_spec.rb", __FILE__), "w") {|f| f.write "require 'spec_helper'\n\ndescribe #{mod}::BaseController do\n\nend"}
+ ::File.open(::File.expand_path("../../tmp/spec/controllers/#{module_name_for_path(mod)}/foos_controller_spec.rb", __FILE__), "w") {|f| f.write "require 'spec_helper'\n\ndescribe #{mod}::FoosController do\n\nend"}
+ ::File.open(::File.expand_path("../../tmp/spec/requests/#{module_name_for_path(mod)}/base_controller_spec.rb", __FILE__), "w") {|f| f.write "require 'spec_helper'\n\ndescribe #{mod}::BaseController do\n\nend"}
+ ::File.open(::File.expand_path("../../tmp/spec/requests/#{module_name_for_path(mod)}/foos_controller_spec.rb", __FILE__), "w") {|f| f.write "require 'spec_helper'\n\ndescribe #{mod}::FoosController do\n\nend"}
+ ::File.open(::File.expand_path("../../tmp/spec/presenters/#{module_name_for_path(mod)}/base_presenter_spec.rb", __FILE__), "w") {|f| f.write "require 'spec_helper'\n\ndescribe #{mod}::BasePresenter do\n\nend"}
+ ::File.open(::File.expand_path("../../tmp/spec/presenters/#{module_name_for_path(mod)}/foo_presenter_spec.rb", __FILE__), "w") {|f| f.write "require 'spec_helper'\n\ndescribe #{mod}::FooPresenter do\n\nend"}
+ ::File.open(::File.expand_path("../../tmp/spec/helpers/#{module_name_for_path(mod)}/foos_helper_spec.rb", __FILE__), "w") {|f| f.write "require 'spec_helper'\n\ndescribe #{mod}::FoosHelper do\n\nend"}
+ Versionist.configuration.configured_test_framework = :rspec
+ run_generator [ver, mod, "x", "X"]
+ end
+
+ it "should copy old controller specs to new controller specs" do
+ expected_base_controller_spec = <<-BASE
+require 'spec_helper'
+
+describe X::BaseController do
+
+end
+ BASE
+
+ expected_foos_controller_spec = <<-FOOS
+require 'spec_helper'
+
+describe X::FoosController do
+
+end
+ FOOS
+
+ assert_file "spec/controllers/#{module_name_for_path("X")}/base_controller_spec.rb", expected_base_controller_spec.chop
+ assert_file "spec/controllers/#{module_name_for_path("X")}/foos_controller_spec.rb", expected_foos_controller_spec.chop
+ assert_file "spec/requests/#{module_name_for_path("X")}/base_controller_spec.rb", expected_base_controller_spec.chop
+ assert_file "spec/requests/#{module_name_for_path("X")}/foos_controller_spec.rb", expected_foos_controller_spec.chop
+ end
+
+ it "should copy old presenter specs to new presenter specs" do
+ expected_base_presenter_spec = <<-BASE
+require 'spec_helper'
+
+describe X::BasePresenter do
+
+end
+ BASE
+
+ expected_foo_presenter_spec = <<-FOOS
+require 'spec_helper'
+
+describe X::FooPresenter do
+
+end
+ FOOS
+
+ assert_file "spec/presenters/#{module_name_for_path("X")}/base_presenter_spec.rb", expected_base_presenter_spec.chop
+ assert_file "spec/presenters/#{module_name_for_path("X")}/foo_presenter_spec.rb", expected_foo_presenter_spec.chop
+ end
+
+ it "should copy old helper specs to new helper specs" do
+ expected_foos_helper_spec = <<-DOC
+require 'spec_helper'
+
+describe X::FoosHelper do
+
+end
+ DOC
+
+ assert_file "spec/helpers/#{module_name_for_path("X")}/foos_helper_spec.rb", expected_foos_helper_spec.chop
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/generators/inflector_fixes_spec.rb b/spec/generators/inflector_fixes_spec.rb
new file mode 100644
index 0000000..5e2bca3
--- /dev/null
+++ b/spec/generators/inflector_fixes_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Versionist::InflectorFixes do
+ before :each do
+ @object = Object.new
+ @object.extend(Versionist::InflectorFixes)
+ end
+
+ context "#module_name_for_route" do
+ it "should transform" do
+ @object.module_name_for_route("V2_1_3").should == "V2__1__3"
+ end
+ end
+
+ context "#module_name_for_path" do
+ it "should transform" do
+ @object.module_name_for_path("V2_1_3").should == "v2_1_3"
+ end
+ end
+end
diff --git a/spec/generators/new_api_version_generator_spec.rb b/spec/generators/new_api_version_generator_spec.rb
new file mode 100644
index 0000000..ddbbf20
--- /dev/null
+++ b/spec/generators/new_api_version_generator_spec.rb
@@ -0,0 +1,476 @@
+require 'spec_helper'
+require 'generator_spec/test_case'
+
+describe Versionist::NewApiVersionGenerator do
+ include GeneratorSpec::TestCase
+ include Versionist::InflectorFixes
+
+ destination File.expand_path("../../tmp", __FILE__)
+
+ before :each do
+ prepare_destination
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers", __FILE__))
+ ::Dir.mkdir(::File.expand_path("../../tmp/config", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ end
+
+ {"v1" => "V1", "v2" => "V2", "v2.1" => "V2_1", "v20120119" => "Api::V20120119"}.each do |ver, mod|
+ context "#{ver} => #{mod}" do
+ context "verify_options" do
+ it "should raise an error if no versioning strategies are specified" do
+ lambda {
+ run_generator %W(#{ver} #{mod})
+ }.should raise_error(RuntimeError, /Must specify at least one versioning strategy option/)
+ end
+
+ it "should raise an error if header hash doesn't contain name and value keys" do
+ lambda {
+ run_generator %W(#{ver} #{mod} --header=name:Accept)
+ }.should raise_error(RuntimeError, /Must specify name and value for header versioning strategy/)
+
+ lambda {
+ run_generator %W(#{ver} #{mod} --header=value:v1)
+ }.should raise_error(RuntimeError, /Must specify name and value for header versioning strategy/)
+ end
+
+ it "should not raise an error if header hash has both name and value keys" do
+ lambda {
+ run_generator %W(#{ver} #{mod} --header=name:Accept value:"application/vnd.mycompany.com; version=2")
+ }.should_not raise_error
+ end
+
+ it "should raise an error if parameter hash doesn't contain name and value keys" do
+ lambda {
+ run_generator %W(#{ver} #{mod} --parameter=name:Accept)
+ }.should raise_error(RuntimeError, /Must specify name and value for parameter versioning strategy/)
+
+ lambda {
+ run_generator %W(#{ver} #{mod} --parameter=value:1)
+ }.should raise_error(RuntimeError, /Must specify name and value for parameter versioning strategy/)
+ end
+
+ it "should not raise an error if parameter hash has both name and value keys" do
+ lambda {
+ run_generator %W(#{ver} #{mod} --parameter=name:version value:1)
+ }.should_not raise_error
+ end
+
+ it "should raise an error if path hash doesn't contain value key" do
+ lambda {
+ run_generator %W(#{ver} #{mod} --path=foo:bar)
+ }.should raise_error(RuntimeError, /Must specify value for path versioning strategy/)
+ end
+
+ it "should not raise an error if path hash has value key" do
+ lambda {
+ run_generator %W(#{ver} #{mod} --path=value:v1)
+ }.should_not raise_error
+ end
+ end
+
+ context "api version exists" do
+ before :each do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => {:name => \"Accept\", :value => \"application/vnd.mycompany.com-v1\"}) do\n end\nend"}
+ end
+
+ after :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ end
+
+ it "should raise an error" do
+ lambda {
+ run_generator %W(#{ver} #{mod} --header=name:Accept value:"application/vnd.mycompany.com-v1")
+ }.should raise_error(RuntimeError, /API version already exists in config\/routes.rb/)
+ end
+ end
+
+ context "api version doesn't exist" do
+ before :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\nend"}
+ Versionist.configuration.configured_test_framework = nil
+ run_generator %W(#{ver} #{mod} --header=name:Accept value:application/vnd.mycompany.com-#{ver})
+ end
+
+ after :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ end
+
+ it "should add correct api_version to config/routes.rb" do
+ assert_file "config/routes.rb"
+ expected = <<-CONTENTS
+Test::Application.routes.draw do
+ api_version(:module => "#{module_name_for_route(mod)}", :header => {:name => "Accept", :value => "application/vnd.mycompany.com-#{ver}"}) do
+ end
+
+end
+ CONTENTS
+ # Rails 4 removed the trailing newline from the 'route' generator
+ # https://github.com/rails/rails/commit/7cdb12286639b38db2eb1e9fd0c8b2e6bc3b39dc
+ if Rails::VERSION::MAJOR < 4
+ assert_file "config/routes.rb", expected.chop
+ elsif Rails::VERSION::MAJOR == 4
+ assert_file "config/routes.rb", expected.gsub(/^$\n/, '').chop
+ end
+ end
+
+ it "should create a namespaced controller directory" do
+ assert_directory "app/controllers/#{module_name_for_path(mod)}"
+ end
+
+ it "should create a namespaced base controller" do
+ assert_file "app/controllers/#{module_name_for_path(mod)}/base_controller.rb", <<-CONTENTS
+class #{mod}::BaseController < ApplicationController
+end
+ CONTENTS
+ end
+
+ it "should create a namespaced presenters directory" do
+ assert_directory "app/presenters/#{module_name_for_path(mod)}"
+ end
+
+ it "should create a namespaced base presenter" do
+ assert_file "app/presenters/#{module_name_for_path(mod)}/base_presenter.rb", <<-CONTENTS
+class #{mod}::BasePresenter
+end
+ CONTENTS
+ end
+
+ it "should create a namespaced helpers directory" do
+ assert_directory "app/helpers/#{module_name_for_path(mod)}"
+ end
+
+ it "should create a documentation directory" do
+ assert_directory "public/docs/#{ver}"
+ end
+
+ it "should create a documentation index.html" do
+ assert_file "public/docs/#{ver}/index.html", <<-CONTENTS
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <title>Documentation for #{ver}</title>
+ <link href="#{ver}/style.css" media="screen" rel="stylesheet" type="text/css">
+ </head>
+ <body>
+ <div id="container">
+ <div id="operations">
+ <h3>API Operations</h3>
+ </div>
+ <div id="content">
+ <h1>Documentation for #{ver}</h1>
+ </div>
+ </div>
+ </body>
+</html>
+ CONTENTS
+ end
+
+ it "should create a documentation style.css" do
+ assert_file "public/docs/#{ver}/style.css", <<-CONTENTS
+body {margin: 0; background-color: #fff; color: #000; font-family: Arial,sans-serif;}
+content {margin-left: 200px;}
+content h1 {text-align: center;}
+operations {float: left; width: 200px; border-right: 1px solid #ccc;}
+operations h3 {text-align: center;}
+ CONTENTS
+ end
+
+ context "multiple versioning strategies" do
+ before :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\nend"}
+ Versionist.configuration.configured_test_framework = nil
+ run_generator %W(#{ver} #{mod} --header=name:Accept value:application/vnd.mycompany.com-#{ver} --parameter=name:version value:#{ver} --path=value:/#{ver})
+ end
+
+ after :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ end
+
+ it "should add all versioning strategies to api_version to config/routes.rb" do
+ assert_file "config/routes.rb"
+ expected = <<-CONTENTS
+Test::Application.routes.draw do
+ api_version(:module => "#{module_name_for_route(mod)}", :header => {:name => "Accept", :value => "application/vnd.mycompany.com-#{ver}"}, :parameter => {:name => "version", :value => "#{ver}"}, :path => {:value => "/#{ver}"}) do
+ end
+
+end
+ CONTENTS
+ # Rails 4 removed the trailing newline from the 'route' generator
+ # https://github.com/rails/rails/commit/7cdb12286639b38db2eb1e9fd0c8b2e6bc3b39dc
+ if Rails::VERSION::MAJOR < 4
+ assert_file "config/routes.rb", expected.chop
+ elsif Rails::VERSION::MAJOR == 4
+ assert_file "config/routes.rb", expected.gsub(/^$\n/, '').chop
+ end
+ end
+ end
+
+ context ":defaults hash" do
+ before :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\nend"}
+ Versionist.configuration.configured_test_framework = nil
+ run_generator %W(#{ver} #{mod} --header=name:Accept value:application/vnd.mycompany.com-#{ver} --defaults=format:json)
+ end
+
+ after :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ end
+
+ it "should add :defaults hash to api_version to config/routes.rb" do
+ assert_file "config/routes.rb"
+ expected = <<-CONTENTS
+Test::Application.routes.draw do
+ api_version(:module => "#{module_name_for_route(mod)}", :header => {:name => "Accept", :value => "application/vnd.mycompany.com-#{ver}"}, :defaults => {:format => "json"}) do
+ end
+
+end
+ CONTENTS
+ # Rails 4 removed the trailing newline from the 'route' generator
+ # https://github.com/rails/rails/commit/7cdb12286639b38db2eb1e9fd0c8b2e6bc3b39dc
+ if Rails::VERSION::MAJOR < 4
+ assert_file "config/routes.rb", expected.chop
+ elsif Rails::VERSION::MAJOR == 4
+ assert_file "config/routes.rb", expected.gsub(/^$\n/, '').chop
+ end
+ end
+ end
+
+ context ":default" do
+ before :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\nend"}
+ Versionist.configuration.configured_test_framework = nil
+ run_generator %W(#{ver} #{mod} --header=name:Accept value:application/vnd.mycompany.com-#{ver} --default)
+ end
+
+ after :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ end
+
+ it "should add :default to api_version to config/routes.rb" do
+ assert_file "config/routes.rb"
+ expected = <<-CONTENTS
+Test::Application.routes.draw do
+ api_version(:module => "#{module_name_for_route(mod)}", :header => {:name => "Accept", :value => "application/vnd.mycompany.com-#{ver}"}, :default => true) do
+ end
+
+end
+ CONTENTS
+ # Rails 4 removed the trailing newline from the 'route' generator
+ # https://github.com/rails/rails/commit/7cdb12286639b38db2eb1e9fd0c8b2e6bc3b39dc
+ if Rails::VERSION::MAJOR < 4
+ assert_file "config/routes.rb", expected.chop
+ elsif Rails::VERSION::MAJOR == 4
+ assert_file "config/routes.rb", expected.gsub(/^$\n/, '').chop
+ end
+ end
+ end
+
+ context "test_framework: test_unit" do
+ before :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ Versionist.configuration.configured_test_framework = :test_unit
+ run_generator %W(#{ver} #{mod} --header=name:Accept value:application/vnd.mycompany.com-#{ver})
+ end
+
+ it "should create a namespaced test directory" do
+ assert_directory "test/#{test_path}/#{module_name_for_path(mod)}"
+ end
+
+ if older_than_rails_5?
+ it "should create a namespaced base controller test" do
+ assert_file "test/#{test_path}/#{module_name_for_path(mod)}/base_controller_test.rb", <<-CONTENTS
+require 'test_helper'
+
+class #{mod}::BaseControllerTest < ActionController::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ CONTENTS
+ end
+ else
+ it "should create a namespaced base controller test" do
+ assert_file "test/#{test_path}/#{module_name_for_path(mod)}/base_controller_test_rails_5.rb", <<-CONTENTS
+require 'test_helper'
+
+class #{mod}::BaseControllerTest < ActionDispatch::IntegrationTest
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ CONTENTS
+ end
+ end
+
+ if older_than_rails_5?
+ it "should create a namespaced base controller integration test" do
+ assert_file "test/integration/#{module_name_for_path(mod)}/base_controller_test.rb", <<-CONTENTS
+require 'test_helper'
+
+class #{mod}::BaseControllerTest < ActionDispatch::IntegrationTest
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ CONTENTS
+ end
+ end
+
+ it "should create a namespaced test/presenters directory" do
+ assert_directory "test/presenters/#{module_name_for_path(mod)}"
+ end
+
+ if older_than_rails_5?
+ it "should create a namespaced base presenter test" do
+ assert_file "test/presenters/#{module_name_for_path(mod)}/base_presenter_test.rb", <<-CONTENTS
+require 'test_helper'
+
+class #{mod}::BasePresenterTest < Test::Unit::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ CONTENTS
+ end
+ else
+ it "should create a namespaced base presenter test" do
+ assert_file "test/presenters/#{module_name_for_path(mod)}/base_presenter_test_rails_5.rb", <<-CONTENTS
+require 'test_helper'
+
+class #{mod}::BasePresenterTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ CONTENTS
+ end
+ end
+
+ it "should create a namespaced test/helpers directory" do
+ assert_directory "test/helpers/#{module_name_for_path(mod)}"
+ end
+ end
+
+ context "test_framework: rspec" do
+ before :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ Versionist.configuration.configured_test_framework = :rspec
+ end
+
+ context "directories" do
+ before :each do
+ run_generator %W(#{ver} #{mod} --header=name:Accept value:application/vnd.mycompany.com-#{ver})
+ end
+
+ it "should create a namespaced spec/controllers directory" do
+ assert_directory "spec/controllers/#{module_name_for_path(mod)}"
+ end
+
+ it "should create a namespaced spec/presenters directory" do
+ assert_directory "spec/presenters/#{module_name_for_path(mod)}"
+ end
+
+ it "should create a namespaced spec/helpers directory" do
+ assert_directory "spec/helpers/#{module_name_for_path(mod)}"
+ end
+ end
+
+ context "rspec < 3" do
+ before :each do
+ run_generator %W(#{ver} #{mod} --header=name:Accept value:application/vnd.mycompany.com-#{ver})
+ end
+
+ it "should create a namespaced base request spec" do
+ assert_file "spec/requests/#{module_name_for_path(mod)}/base_controller_spec.rb", <<-CONTENTS
+require 'spec_helper'
+
+describe #{mod}::BaseController do
+
+end
+ CONTENTS
+ end
+
+ it "should create a namespaced base controller spec" do
+ assert_file "spec/controllers/#{module_name_for_path(mod)}/base_controller_spec.rb", <<-CONTENTS
+require 'spec_helper'
+
+describe #{mod}::BaseController do
+
+end
+ CONTENTS
+ end
+
+ it "should create a namespaced base presenter spec" do
+ assert_file "spec/presenters/#{module_name_for_path(mod)}/base_presenter_spec.rb", <<-CONTENTS
+require 'spec_helper'
+
+describe #{mod}::BasePresenter do
+
+end
+ CONTENTS
+ end
+ end
+
+ context "rspec >= 3" do
+ before :each do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/spec/rails_helper.rb", __FILE__))
+ run_generator %W(#{ver} #{mod} --header=name:Accept value:application/vnd.mycompany.com-#{ver})
+ end
+
+ after :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/spec/rails_helper.rb", __FILE__))
+ end
+
+ it "should create a namespaced base request spec" do
+ assert_file "spec/requests/#{module_name_for_path(mod)}/base_controller_spec.rb", <<-CONTENTS
+require 'rails_helper'
+
+describe #{mod}::BaseController do
+
+end
+ CONTENTS
+ end
+
+ it "should create a namespaced base controller spec" do
+ assert_file "spec/controllers/#{module_name_for_path(mod)}/base_controller_spec.rb", <<-CONTENTS
+require 'rails_helper'
+
+describe #{mod}::BaseController do
+
+end
+ CONTENTS
+ end
+
+ it "should create a namespaced base presenter spec" do
+ assert_file "spec/presenters/#{module_name_for_path(mod)}/base_presenter_spec.rb", <<-CONTENTS
+require 'rails_helper'
+
+describe #{mod}::BasePresenter do
+
+end
+ CONTENTS
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/generators/new_controller_generator_spec.rb b/spec/generators/new_controller_generator_spec.rb
new file mode 100644
index 0000000..c7b7b59
--- /dev/null
+++ b/spec/generators/new_controller_generator_spec.rb
@@ -0,0 +1,265 @@
+require 'spec_helper'
+require 'generator_spec/test_case'
+
+describe Versionist::NewControllerGenerator do
+ include GeneratorSpec::TestCase
+ include Versionist::InflectorFixes
+
+ destination File.expand_path("../../tmp", __FILE__)
+
+ before :each do
+ prepare_destination
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers", __FILE__))
+ ::Dir.mkdir(::File.expand_path("../../tmp/config", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ end
+
+ context "controller" do
+ context "api version doesn't exist" do
+ it "should raise an error if the api version doesn't exist yet" do
+ lambda {
+ run_generator %w(v1 V1)
+ }.should raise_error(RuntimeError, /API module namespace V1 doesn't exist. Please run \'rails generate versionist:new_api_version\' generator first/)
+ end
+ end
+
+ context "ruby hash syntaxes" do
+ context "< 1.9" do
+ it "should not raise an error if api version exists" do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path("V1")}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route("V1")}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-v1\") do\n end\nend"}
+ Versionist.configuration.configured_test_framework = nil
+ lambda {
+ run_generator ["foo", "V1"]
+ }.should_not raise_error#(RuntimeError, /API version doesn't exist in config\/routes.rb. Please run \'rails generate versionist:new_api_version\' generator first/)
+ end
+ end
+
+ context ">= 1.9" do
+ it "should not raise an error if api version exists" do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path("V1")}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(module: \"#{module_name_for_route("V1")}\", header: \"Accept\", value: \"application/vnd.mycompany.com-v1\") do\n end\nend"}
+ Versionist.configuration.configured_test_framework = nil
+ lambda {
+ run_generator ["foo", "V1"]
+ }.should_not raise_error#(RuntimeError, /API version doesn't exist in config\/routes.rb. Please run \'rails generate versionist:new_api_version\' generator first/)
+ end
+ end
+ end
+
+ context "api version exists" do
+ {"foo" => "V1", "bar" => "V2", "foos" => "V2_1", "bazs" => "Api::V3"}.each do |name, mod|
+ context "#{name} => #{mod}" do
+ before :each do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-v1\") do\n end\nend"}
+ Versionist.configuration.configured_test_framework = nil
+ run_generator [name, mod]
+ end
+
+ it "should create a namespaced controller" do
+ assert_directory "app/controllers/#{module_name_for_path(mod)}"
+ assert_file "app/controllers/#{module_name_for_path(mod)}/#{name.underscore}_controller.rb", "class #{mod}::#{name.camelize}Controller < #{mod}::BaseController\nend\n"
+ end
+
+ context "test_framework: test_unit" do
+ before :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-v1\") do\n end\nend"}
+ Versionist.configuration.configured_test_framework = :test_unit
+ run_generator [name, mod]
+ end
+
+ it "should create a namespaced test directory" do
+ assert_directory "test/#{test_path}/#{module_name_for_path(mod)}"
+ end
+
+ if older_than_rails_5?
+ it "should create a namespaced controller test" do
+ assert_file "test/#{test_path}/#{module_name_for_path(mod)}/#{name.underscore}_controller_test.rb", <<-CONTENTS
+require 'test_helper'
+
+class #{mod}::#{name.camelize}ControllerTest < ActionController::TestCase
+
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ CONTENTS
+ end
+ else
+ it "should create a namespaced controller test" do
+ assert_file "test/#{test_path}/#{module_name_for_path(mod)}/#{name.underscore}_controller_test_rails_5.rb", <<-CONTENTS
+require 'test_helper'
+
+class #{mod}::#{name.camelize}ControllerTest < ActionDispatch::IntegrationTest
+
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ CONTENTS
+ end
+ end
+
+ if older_than_rails_5?
+ it "should create a namespaced test/integration directory" do
+ assert_directory "test/integration/#{module_name_for_path(mod)}"
+ end
+
+ it "should create a namespaced controller integration test" do
+ assert_file "test/integration/#{module_name_for_path(mod)}/#{name.underscore}_controller_test.rb", <<-CONTENTS
+require 'test_helper'
+
+class #{mod}::#{name.camelize}ControllerTest < ActionDispatch::IntegrationTest
+
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ CONTENTS
+ end
+ end
+ end
+
+ context "test_framework: rspec" do
+ before :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-v1\") do\n end\nend"}
+ Versionist.configuration.configured_test_framework = :rspec
+ end
+
+ context "directories" do
+ before :each do
+ run_generator [name, mod]
+ end
+
+ it "should create a namespaced spec/controllers directory" do
+ assert_directory "spec/controllers/#{module_name_for_path(mod)}"
+ end
+
+ it "should create a namespaced spec/requests directory" do
+ assert_directory "spec/requests/#{module_name_for_path(mod)}"
+ end
+ end
+
+ context "rspec < 3" do
+ before :each do
+ run_generator [name, mod]
+ end
+
+ it "should create a namespaced controller spec" do
+ assert_file "spec/controllers/#{module_name_for_path(mod)}/#{name.underscore}_controller_spec.rb", <<-CONTENTS
+require 'spec_helper'
+
+describe #{mod}::#{name.camelize}Controller do
+
+end
+ CONTENTS
+ end
+
+ it "should create a namespaced request spec" do
+ assert_file "spec/requests/#{module_name_for_path(mod)}/#{name.underscore}_controller_spec.rb", <<-CONTENTS
+require 'spec_helper'
+
+describe #{mod}::#{name.camelize}Controller do
+
+end
+ CONTENTS
+ end
+ end
+
+ context "rspec >= 3" do
+ before :each do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/spec/rails_helper.rb", __FILE__))
+ run_generator [name, mod]
+ end
+
+ after :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/spec/rails_helper.rb", __FILE__))
+ end
+
+ it "should create a namespaced controller spec" do
+ assert_file "spec/controllers/#{module_name_for_path(mod)}/#{name.underscore}_controller_spec.rb", <<-CONTENTS
+require 'rails_helper'
+
+describe #{mod}::#{name.camelize}Controller do
+
+end
+ CONTENTS
+ end
+
+ it "should create a namespaced request spec" do
+ assert_file "spec/requests/#{module_name_for_path(mod)}/#{name.underscore}_controller_spec.rb", <<-CONTENTS
+require 'rails_helper'
+
+describe #{mod}::#{name.camelize}Controller do
+
+end
+ CONTENTS
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ context "routes" do
+ context "api version doesn't exist in config/routes.rb" do
+ before :each do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/v1", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\nend"}
+ end
+
+ it "should raise an error" do
+ lambda {
+ run_generator %w(v1 V1)
+ }.should raise_error(RuntimeError, /API version doesn't exist in config\/routes.rb. Please run \'rails generate versionist:new_api_version\' generator first/)
+ end
+ end
+
+ context "api version duplicated in config/routes.rb" do
+ before :each do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/v1", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"V1\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-v1\") do\n end\n\n api_version(:module => \"V1\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-v1\") do\n end\nend"}
+ end
+
+ it "should raise an error" do
+ lambda {
+ run_generator %w(v1 V1)
+ }.should raise_error(RuntimeError, /API version is duplicated in config\/routes.rb/)
+ end
+ end
+
+ context "api version exists" do
+ {"foo" => "V1", "bar" => "V2", "foos" => "V2_1", "bazs" => "Api::V3"}.each do |name, mod|
+ context "#{name} => #{mod}" do
+ before :each do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/controllers/#{module_name_for_path(mod)}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-v1\") do\n end\nend"}
+ run_generator [name, mod]
+ end
+
+ it "should add the new resource to the existing scope in routes.rb" do
+ assert_file "config/routes.rb"
+ expected = <<-CONTENTS
+Test::Application.routes.draw do
+ api_version(:module => "#{module_name_for_route(mod)}", :header => "Accept", :value => "application/vnd.mycompany.com-v1") do
+ resources :#{name}
+ end
+end
+ CONTENTS
+ assert_file "config/routes.rb", expected.chop
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/generators/new_presenter_generator_spec.rb b/spec/generators/new_presenter_generator_spec.rb
new file mode 100644
index 0000000..3ac891e
--- /dev/null
+++ b/spec/generators/new_presenter_generator_spec.rb
@@ -0,0 +1,157 @@
+require 'spec_helper'
+require 'generator_spec/test_case'
+
+describe Versionist::NewPresenterGenerator do
+ include GeneratorSpec::TestCase
+ include Versionist::InflectorFixes
+
+ destination File.expand_path("../../tmp", __FILE__)
+
+ before :each do
+ prepare_destination
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/presenters", __FILE__))
+ ::Dir.mkdir(::File.expand_path("../../tmp/config", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ end
+
+ context "api version doesn't exist" do
+ it "should raise an error if the api version doesn't exist yet" do
+ lambda {
+ run_generator %w(v1 V1)
+ }.should raise_error(RuntimeError, /API module namespace V1 doesn't exist. Please run \'rails generate versionist:new_api_version\' generator first/)
+ end
+ end
+
+ context "api version exists" do
+ {"foo" => "V1", "bar" => "V2", "foos" => "V2_1", "bazs" => "Api::V3"}.each do |name, mod|
+ context "#{name} => #{mod}" do
+ before :each do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-v1\") do\n end\nend"}
+ Versionist.configuration.configured_test_framework = nil
+ run_generator [name, mod]
+ end
+
+ it "should create a namespaced presenter" do
+ assert_directory "app/presenters/#{module_name_for_path(mod)}"
+ assert_file "app/presenters/#{module_name_for_path(mod)}/#{name.underscore}_presenter.rb", <<-CONTENTS
+class #{mod}::#{name.camelize}Presenter < #{mod}::BasePresenter
+
+ def initialize(#{name})
+ @#{name} = #{name}
+ end
+
+ def as_json(options={})
+ # fill me in...
+ end
+
+ def to_xml(options={}, &block)
+ xml = options[:builder] ||= Builder::XmlMarkup.new
+ # fill me in...
+ end
+end
+ CONTENTS
+ end
+
+ context "test_framework: test_unit" do
+ before :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-v1\") do\n end\nend"}
+ Versionist.configuration.configured_test_framework = :test_unit
+ run_generator [name, mod]
+ end
+
+ it "should create a namespaced test/presenters directory" do
+ assert_directory "test/presenters/#{module_name_for_path(mod)}"
+ end
+
+ if older_than_rails_5?
+ it "should create a namespaced presenter test" do
+ assert_file "test/presenters/#{module_name_for_path(mod)}/#{name.underscore}_presenter_test.rb", <<-CONTENTS
+require 'test_helper'
+
+class #{mod}::#{name.camelize}PresenterTest < Test::Unit::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ CONTENTS
+ end
+ else
+ it "should create a namespaced presenter test" do
+ assert_file "test/presenters/#{module_name_for_path(mod)}/#{name.underscore}_presenter_test_rails_5.rb", <<-CONTENTS
+require 'test_helper'
+
+class #{mod}::#{name.camelize}PresenterTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
+ CONTENTS
+ end
+ end
+ end
+
+ context "test_framework: rspec" do
+ before :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/config/routes.rb", __FILE__))
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/app/presenters/#{module_name_for_path(mod)}", __FILE__))
+ ::File.open(::File.expand_path("../../tmp/config/routes.rb", __FILE__), "w") {|f| f.write "Test::Application.routes.draw do\n api_version(:module => \"#{module_name_for_route(mod)}\", :header => \"Accept\", :value => \"application/vnd.mycompany.com-v1\") do\n end\nend"}
+ Versionist.configuration.configured_test_framework = :rspec
+ end
+
+ context "directories" do
+ before :each do
+ run_generator [name, mod]
+ end
+
+ it "should create a namespaced spec/presenters directory" do
+ assert_directory "spec/presenters/#{module_name_for_path(mod)}"
+ end
+ end
+
+ context "rspec < 3" do
+ before :each do
+ run_generator [name, mod]
+ end
+
+ it "should create a namespaced presenter spec" do
+ assert_file "spec/presenters/#{module_name_for_path(mod)}/#{name.underscore}_presenter_spec.rb", <<-CONTENTS
+require 'spec_helper'
+
+describe #{mod}::#{name.camelize}Presenter do
+
+end
+ CONTENTS
+ end
+ end
+
+ context "rspec >= 3" do
+ before :each do
+ ::FileUtils.mkdir_p(::File.expand_path("../../tmp/spec", __FILE__))
+ ::FileUtils.touch(::File.expand_path("../../tmp/spec/rails_helper.rb", __FILE__))
+ run_generator [name, mod]
+ end
+
+ after :each do
+ ::FileUtils.rm(::File.expand_path("../../tmp/spec/rails_helper.rb", __FILE__))
+ end
+
+ it "should create a namespaced presenter spec" do
+ assert_file "spec/presenters/#{module_name_for_path(mod)}/#{name.underscore}_presenter_spec.rb", <<-CONTENTS
+require 'rails_helper'
+
+describe #{mod}::#{name.camelize}Presenter do
+
+end
+ CONTENTS
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/middleware_spec.rb b/spec/middleware_spec.rb
new file mode 100644
index 0000000..40277be
--- /dev/null
+++ b/spec/middleware_spec.rb
@@ -0,0 +1,46 @@
+require 'spec_helper'
+require 'rack/test'
+
+describe Versionist::Middleware do
+ before :each do
+ Versionist.configuration.clear!
+ Versionist::VersioningStrategy::Header.new({:header => {:name => "Accept", :value => "application/vnd.mycompany.com-v2.3.0"}})
+ @app = lambda {|env| [200, {"Content-Type" => "text/plain"}, [env["HTTP_ACCEPT"]]]}
+ end
+
+ after :each do
+ Versionist.configuration.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
+
+ it "should not alter the header if the accept header is not present" do
+ request = Rack::MockRequest.env_for("/foos", :lint => true, :fatal => true)
+ status, headers, response = described_class.new(@app).call(request)
+ response[0].should be_nil
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..8b2a267
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,31 @@
+require 'rubygems'
+require 'bundler/setup'
+Bundler.setup(:default, :development) if defined?(Bundler)
+require "action_controller/railtie"
+require 'rspec'
+require 'rspec-rails'
+require 'simplecov'
+SimpleCov.start do
+ add_filter "spec"
+end
+require 'versionist'
+require 'fileutils'
+
+RSpec.configure do |config|
+ config.mock_with :rspec
+
+ config.after :each do
+ # delete spec/tmp/
+ tmp_dir = ::File.expand_path('../tmp', __FILE__)
+ ::FileUtils.rm_rf(tmp_dir)
+ end
+end
+
+def older_than_rails_5?
+ defined?(Rails) && Rails.version.to_i < 5
+end
+
+def test_path
+ return "test/functional" if older_than_rails_5?
+ "test/controllers"
+end
diff --git a/spec/test-api/app/controllers/api/v3/bars_controller.rb b/spec/test-api/app/controllers/api/v3/bars_controller.rb
new file mode 100644
index 0000000..63fb124
--- /dev/null
+++ b/spec/test-api/app/controllers/api/v3/bars_controller.rb
@@ -0,0 +1,9 @@
+class Api::V3::BarsController < ApplicationController
+ def index
+ respond_to do |format|
+ format.text { render :text => "v3" }
+ format.json { render :json => "v3" }
+ format.xml { render :xml => "v3" }
+ end
+ end
+end
diff --git a/spec/test-api/app/controllers/api/v3/foos_controller.rb b/spec/test-api/app/controllers/api/v3/foos_controller.rb
new file mode 100644
index 0000000..a36b6a7
--- /dev/null
+++ b/spec/test-api/app/controllers/api/v3/foos_controller.rb
@@ -0,0 +1,9 @@
+class Api::V3::FoosController < ApplicationController
+ def index
+ respond_to do |format|
+ format.text { render :text => "v3" }
+ format.json { render :json => "v3" }
+ format.xml { render :xml => "v3" }
+ end
+ end
+end
diff --git a/spec/test-api/app/controllers/application_controller.rb b/spec/test-api/app/controllers/application_controller.rb
new file mode 100644
index 0000000..3a8681f
--- /dev/null
+++ b/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
diff --git a/spec/test-api/app/controllers/not_default/foos_controller.rb b/spec/test-api/app/controllers/not_default/foos_controller.rb
new file mode 100644
index 0000000..c4e27db
--- /dev/null
+++ b/spec/test-api/app/controllers/not_default/foos_controller.rb
@@ -0,0 +1,9 @@
+class NotDefault::FoosController < ApplicationController
+ def index
+ respond_to do |format|
+ format.text { render :text => "not_default" }
+ format.json { render :json => "not_default" }
+ format.xml { render :xml => "not_default" }
+ end
+ end
+end
diff --git a/spec/test-api/app/controllers/v1/bars_controller.rb b/spec/test-api/app/controllers/v1/bars_controller.rb
new file mode 100644
index 0000000..b8effa7
--- /dev/null
+++ b/spec/test-api/app/controllers/v1/bars_controller.rb
@@ -0,0 +1,9 @@
+class V1::BarsController < ApplicationController
+ def index
+ respond_to do |format|
+ format.text { render :text => "v1" }
+ format.json { render :json => "v1" }
+ format.xml { render :xml => "v1" }
+ end
+ end
+end
diff --git a/spec/test-api/app/controllers/v1/foos_controller.rb b/spec/test-api/app/controllers/v1/foos_controller.rb
new file mode 100644
index 0000000..547f7e1
--- /dev/null
+++ b/spec/test-api/app/controllers/v1/foos_controller.rb
@@ -0,0 +1,9 @@
+class V1::FoosController < ApplicationController
+ def index
+ respond_to do |format|
+ format.text { render :text => "v1" }
+ format.json { render :json => "v1" }
+ format.xml { render :xml => "v1" }
+ end
+ end
+end
diff --git a/spec/test-api/app/controllers/v11/bars_controller.rb b/spec/test-api/app/controllers/v11/bars_controller.rb
new file mode 100644
index 0000000..b1e6e1c
--- /dev/null
+++ b/spec/test-api/app/controllers/v11/bars_controller.rb
@@ -0,0 +1,5 @@
+class V11::BarsController < ApplicationController
+ def index
+ render :text => "v11"
+ end
+end
diff --git a/spec/test-api/app/controllers/v11/foos_controller.rb b/spec/test-api/app/controllers/v11/foos_controller.rb
new file mode 100644
index 0000000..e5f3ab6
--- /dev/null
+++ b/spec/test-api/app/controllers/v11/foos_controller.rb
@@ -0,0 +1,9 @@
+class V11::FoosController < ApplicationController
+ def index
+ respond_to do |format|
+ format.text { render :text => "v11" }
+ format.json { render :json => "v11" }
+ format.xml { render :xml => "v11" }
+ end
+ end
+end
diff --git a/spec/test-api/app/controllers/v2/bars_controller.rb b/spec/test-api/app/controllers/v2/bars_controller.rb
new file mode 100644
index 0000000..e4178e1
--- /dev/null
+++ b/spec/test-api/app/controllers/v2/bars_controller.rb
@@ -0,0 +1,9 @@
+class V2::BarsController < ApplicationController
+ def index
+ respond_to do |format|
+ format.text { render :text => "v2" }
+ format.json { render :json => "v2" }
+ format.xml { render :xml => "v2" }
+ end
+ end
+end
diff --git a/spec/test-api/app/controllers/v2/foos_controller.rb b/spec/test-api/app/controllers/v2/foos_controller.rb
new file mode 100644
index 0000000..1bbc2ad
--- /dev/null
+++ b/spec/test-api/app/controllers/v2/foos_controller.rb
@@ -0,0 +1,9 @@
+class V2::FoosController < ApplicationController
+ def index
+ respond_to do |format|
+ format.text { render :text => "v2" }
+ format.json { render :json => "v2" }
+ format.xml { render :xml => "v2" }
+ end
+ end
+end
diff --git a/spec/test-api/app/controllers/v2_1/bars_controller.rb b/spec/test-api/app/controllers/v2_1/bars_controller.rb
new file mode 100644
index 0000000..4b32337
--- /dev/null
+++ b/spec/test-api/app/controllers/v2_1/bars_controller.rb
@@ -0,0 +1,9 @@
+class V2_1::BarsController < ApplicationController
+ def index
+ respond_to do |format|
+ format.text { render :text => "v2.1" }
+ format.json { render :json => "v2.1" }
+ format.xml { render :xml => "v2.1" }
+ end
+ end
+end
diff --git a/spec/test-api/app/controllers/v2_1/foos_controller.rb b/spec/test-api/app/controllers/v2_1/foos_controller.rb
new file mode 100644
index 0000000..6713fd2
--- /dev/null
+++ b/spec/test-api/app/controllers/v2_1/foos_controller.rb
@@ -0,0 +1,9 @@
+class V2_1::FoosController < ApplicationController
+ def index
+ respond_to do |format|
+ format.text { render :text => "v2.1" }
+ format.json { render :json => "v2.1" }
+ format.xml { render :xml => "v2.1" }
+ end
+ end
+end
diff --git a/spec/test-api/config/application.rb b/spec/test-api/config/application.rb
new file mode 100644
index 0000000..0e6ada3
--- /dev/null
+++ b/spec/test-api/config/application.rb
@@ -0,0 +1,18 @@
+require "action_controller/railtie"
+require 'versionist/railtie'
+
+module TestApi
+ class Application < Rails::Application
+ config.secret_token = "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!hi mom!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
+ config.secret_key_base = "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!hi mom!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
+ config.eager_load = true
+ config.root = File.expand_path("../../", __FILE__)
+ config.active_support.deprecation = :log
+ config.action_controller.logger = nil
+ config.logger = Logger.new(STDOUT)
+ config.log_level = :info
+ config.action_controller.logger = nil
+ config.middleware.delete Rails::Rack::Logger
+ config.action_dispatch.show_exceptions = false
+ end
+end
diff --git a/spec/versioning_strategy/base_spec.rb b/spec/versioning_strategy/base_spec.rb
new file mode 100644
index 0000000..1600e10
--- /dev/null
+++ b/spec/versioning_strategy/base_spec.rb
@@ -0,0 +1,77 @@
+require 'spec_helper'
+
+describe Versionist::VersioningStrategy::Base do
+ after :each do
+ Versionist.configuration.clear!
+ end
+
+ 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 set attributes" do
+ @base = Versionist::VersioningStrategy::Base.new({})
+ @base.config.should == {}
+
+ @base2 = Versionist::VersioningStrategy::Base.new({"module" => "V1"})
+ # symbolize_keys! should be called
+ @base2.config.should_not == {"module" => "V1"}
+ @base2.config.should == {:module => "V1"}
+ 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
+
+ it "should not add self to Versionist::Configuration.versioning_strategies more than once" 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
+ Versionist::VersioningStrategy::Base.new({})
+ Versionist.configuration.versioning_strategies.should_not be_empty
+ Versionist.configuration.versioning_strategies.size.should == 1
+ end
+
+ context "==" do
+ before :each do
+ @base = Versionist::VersioningStrategy::Base.new({:default => false})
+ @equal_base = Versionist::VersioningStrategy::Base.new({:default => false})
+ end
+
+ it "should return true if passed an equal object" do
+ (@base == @equal_base).should == true
+ end
+
+ it "should return false if passed nil" do
+ (@base == nil).should == false
+ end
+
+ it "should return false if passed an object that's not a Versionist::VersioningStrategy::Base" do
+ (@base == Array.new).should == false
+ end
+
+ it "should return false if passed an object that's not equal" do
+ @unequal_base = Versionist::VersioningStrategy::Base.new({})
+ (@base == @unequal_base).should == false
+ end
+
+ it "should find equal versioning strategies via Array.include?" do
+ @array = Array.new
+ @array << @base
+ @array.include?(@base).should == true
+ @array.include?(@equal_base).should == true
+ end
+ end
+end
diff --git a/spec/versioning_strategy/default_spec.rb b/spec/versioning_strategy/default_spec.rb
new file mode 100644
index 0000000..63459e1
--- /dev/null
+++ b/spec/versioning_strategy/default_spec.rb
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+describe Versionist::VersioningStrategy::Default do
+ before :each do
+ Versionist.configuration.clear!
+ end
+
+ after :each do
+ Versionist.configuration.clear!
+ end
+
+ it "should set attributes" do
+ @default = Versionist::VersioningStrategy::Default.new({:module => "V1", :header => {:name => "Accept", :value => "v1"}})
+ @default.module.should == "V1"
+ Versionist.configuration.default_version.should_not be_nil
+ Versionist.configuration.default_version.should == @default
+ end
+
+ it "should raise an error when attempting to set more than one :default version" do
+ Versionist.configuration.default_version.should be_nil
+ Versionist::VersioningStrategy::Default.new({:module => "V1", :default => true, :path => "foo"})
+ Versionist.configuration.default_version.should_not be_nil
+ lambda {
+ Versionist::VersioningStrategy::Default.new({:module => "V2", :default => true, :path => "bar"})
+ }.should raise_error(ArgumentError, /attempt to set more than one default api version/)
+ end
+
+ context "==" do
+ before :each do
+ @header = Versionist::VersioningStrategy::Header.new({:header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=1"}})
+ @equal_header = Versionist::VersioningStrategy::Header.new({:header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=1"}})
+ end
+
+ it "should return true if passed an equal object" do
+ (@header == @equal_header).should == true
+ end
+
+ it "should return false if passed an object that's not a Versionist::VersioningStrategy::Header" do
+ (@header == Array.new).should == false
+ end
+
+ it "should return false if passed an object that's not equal" do
+ @unequal_header = Versionist::VersioningStrategy::Header.new({:header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=2"}})
+ (@header == @unequal_header).should == false
+ end
+
+ it "should find equal versioning strategies via Array.include?" do
+ @array = Array.new
+ @array << @header
+ @array.include?(@header).should == true
+ @array.include?(@equal_header).should == true
+ end
+ end
+end
diff --git a/spec/versioning_strategy/header_spec.rb b/spec/versioning_strategy/header_spec.rb
new file mode 100644
index 0000000..4c11517
--- /dev/null
+++ b/spec/versioning_strategy/header_spec.rb
@@ -0,0 +1,73 @@
+require 'spec_helper'
+
+describe Versionist::VersioningStrategy::Header do
+ before :each do
+ Versionist.configuration.clear!
+ end
+
+ after :each do
+ Versionist.configuration.clear!
+ end
+
+ it "should raise an ArgumentError if :name is not specified" do
+ lambda {
+ Versionist::VersioningStrategy::Header.new({:header => {:foo => "foo"}})
+ }.should raise_error(ArgumentError, /you must specify :name in the :header configuration Hash/)
+ end
+
+ it "should raise an ArgumentError if :value is not specified" do
+ lambda {
+ Versionist::VersioningStrategy::Header.new({:header => {:name => "foo"}})
+ }.should raise_error(ArgumentError, /you must specify :value in the :header configuration Hash/)
+ end
+
+ it "should raise an ArgumentError if :name is version" do
+ lambda {
+ Versionist::VersioningStrategy::Header.new({:header => {:name => "version", :value => "1"}})
+ }.should raise_error(ArgumentError, /a header :name of 'version' will clash with the built in rack header "HTTP_VERSION". You must use a different header name/)
+ end
+
+ it "should add the version to Versionist::Configuration.header_versions" do
+ Versionist.configuration.header_versions.should be_empty
+ header_version = Versionist::VersioningStrategy::Header.new({:header => {:name => "Accept", :value => "application/vnd.mycompany.com-v2"}})
+ Versionist.configuration.header_versions.include?(header_version).should == true
+ end
+
+ it "should not add self to Versionist::Configuration.header_versions more than once" do
+ Versionist.configuration.header_versions.should be_empty
+ header_version = Versionist::VersioningStrategy::Header.new({:header => {:name => "Accept", :value => "application/vnd.mycompany.com-v2"}})
+ Versionist.configuration.header_versions.should_not be_empty
+ Versionist.configuration.header_versions.size.should == 1
+
+ header_version2 = Versionist::VersioningStrategy::Header.new({:header => {:name => "Accept", :value => "application/vnd.mycompany.com-v2"}})
+ Versionist.configuration.header_versions.should_not be_empty
+ Versionist.configuration.header_versions.size.should == 1
+ end
+
+ context "==" do
+ before :each do
+ @header = Versionist::VersioningStrategy::Header.new({:header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=1"}})
+ @equal_header = Versionist::VersioningStrategy::Header.new({:header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=1"}})
+ end
+
+ it "should return true if passed an equal object" do
+ (@header == @equal_header).should == true
+ end
+
+ it "should return false if passed an object that's not a Versionist::VersioningStrategy::Header" do
+ (@header == Array.new).should == false
+ end
+
+ it "should return false if passed an object that's not equal" do
+ @unequal_header = Versionist::VersioningStrategy::Header.new({:header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=2"}})
+ (@header == @unequal_header).should == false
+ end
+
+ it "should find equal versioning strategies via Array.include?" do
+ @array = Array.new
+ @array << @header
+ @array.include?(@header).should == true
+ @array.include?(@equal_header).should == true
+ end
+ end
+end
diff --git a/spec/versioning_strategy/parameter_spec.rb b/spec/versioning_strategy/parameter_spec.rb
new file mode 100644
index 0000000..5900b73
--- /dev/null
+++ b/spec/versioning_strategy/parameter_spec.rb
@@ -0,0 +1,67 @@
+require 'spec_helper'
+
+describe Versionist::VersioningStrategy::Parameter do
+ before :each do
+ Versionist.configuration.clear!
+ end
+
+ after :each do
+ Versionist.configuration.clear!
+ end
+
+ it "should raise an ArgumentError if :name is not specified" do
+ lambda {
+ Versionist::VersioningStrategy::Parameter.new({:parameter => {:value => "v1"}})
+ }.should raise_error(ArgumentError, /you must specify :name in the :parameter configuration Hash/)
+ end
+
+ it "should raise an ArgumentError if :value is not specified" do
+ lambda {
+ Versionist::VersioningStrategy::Parameter.new({:parameter => {:name => "version"}})
+ }.should raise_error(ArgumentError, /you must specify :value in the :parameter configuration Hash/)
+ end
+
+ it "should add the version to Versionist::Configuration.parameter_versions" do
+ Versionist.configuration.parameter_versions.should be_empty
+ parmeter_version = Versionist::VersioningStrategy::Parameter.new({:parameter => {:name => "version", :value => "3"}})
+ Versionist.configuration.parameter_versions.include?(parmeter_version).should == true
+ end
+
+ it "should not add self to Versionist::Configuration.parameter_versions more than once" do
+ Versionist.configuration.parameter_versions.should be_empty
+ parameter_version = Versionist::VersioningStrategy::Parameter.new({:parameter => {:name => "version", :value => "v2"}})
+ Versionist.configuration.parameter_versions.should_not be_empty
+ Versionist.configuration.parameter_versions.size.should == 1
+
+ parameter_version2 = Versionist::VersioningStrategy::Parameter.new({:parameter => {:name => "version", :value => "v2"}})
+ Versionist.configuration.parameter_versions.should_not be_empty
+ Versionist.configuration.parameter_versions.size.should == 1
+ end
+
+ context "==" do
+ before :each do
+ @parameter = Versionist::VersioningStrategy::Parameter.new({:parameter => {:name => "version", :value => "1"}})
+ @equal_parameter = Versionist::VersioningStrategy::Parameter.new({:parameter => {:name => "version", :value => "1"}})
+ end
+
+ it "should return true if passed an equal object" do
+ (@parameter == @equal_parameter).should == true
+ end
+
+ it "should return false if passed an object that's not a Versionist::VersioningStrategy::Parameter" do
+ (@parameter == Array.new).should == false
+ end
+
+ it "should return false if passed an object that's not equal" do
+ @unequal_parameter = Versionist::VersioningStrategy::Parameter.new({:parameter => {:name => "ver", :value => "1"}})
+ (@parameter == @unequal_parameter).should == false
+ end
+
+ it "should find equal versioning strategies via Array.include?" do
+ @array = Array.new
+ @array << @parameter
+ @array.include?(@parameter).should == true
+ @array.include?(@equal_parameter).should == true
+ end
+ end
+end
diff --git a/spec/versioning_strategy/path_spec.rb b/spec/versioning_strategy/path_spec.rb
new file mode 100644
index 0000000..02dd1b8
--- /dev/null
+++ b/spec/versioning_strategy/path_spec.rb
@@ -0,0 +1,50 @@
+require 'spec_helper'
+
+describe Versionist::VersioningStrategy::Path do
+ before :each do
+ Versionist.configuration.clear!
+ end
+
+ after :each do
+ Versionist.configuration.clear!
+ end
+
+ it "should raise an ArgumentError if :value is not specified" do
+ lambda {
+ Versionist::VersioningStrategy::Path.new({:path => {}})
+ }.should raise_error(ArgumentError, /you must specify :value in the :path configuration Hash/)
+ end
+
+ it "should add the version to Versionist::Configuration.path_versions" do
+ Versionist.configuration.path_versions.should be_empty
+ path_version = Versionist::VersioningStrategy::Path.new({:path => {:value => "v1"}})
+ Versionist.configuration.path_versions.include?(path_version).should == true
+ end
+
+ context "==" do
+ before :each do
+ @path = Versionist::VersioningStrategy::Path.new({:path => {:value => "/v1"}})
+ @equal_path = Versionist::VersioningStrategy::Path.new({:path => {:value => "/v1"}})
+ end
+
+ it "should return true if passed an equal object" do
+ (@path == @equal_path).should == true
+ end
+
+ it "should return false if passed an object that's not a Versionist::VersioningStrategy::Path" do
+ (@path == Array.new).should == false
+ end
+
+ it "should return false if passed an object that's not equal" do
+ @unequal_path = Versionist::VersioningStrategy::Path.new({:path => {:value => "v2"}})
+ (@path == @unequal_path).should == false
+ end
+
+ it "should find equal versioning strategies via Array.include?" do
+ @array = Array.new
+ @array << @path
+ @array.include?(@path).should == true
+ @array.include?(@equal_path).should == true
+ end
+ end
+end
diff --git a/versionist.gemspec b/versionist.gemspec
index 364d409..866ec00 100644
--- a/versionist.gemspec
+++ b/versionist.gemspec
@@ -1,40 +1,26 @@
-#########################################################
-# This file has been automatically generated by gem2tgz #
-#########################################################
# -*- encoding: utf-8 -*-
-# stub: versionist 2.0.1 ruby lib
-Gem::Specification.new do |s|
- s.name = "versionist".freeze
- s.version = "2.0.1"
+lib = File.expand_path('../lib/', __FILE__)
+$:.unshift lib unless $:.include?(lib)
+
+require 'versionist/version'
- s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6".freeze) if s.respond_to? :required_rubygems_version=
- s.require_paths = ["lib".freeze]
- s.authors = ["Brian Ploetz".freeze]
- s.date = "2019-07-22"
- s.description = "A plugin for versioning Rails based RESTful APIs.".freeze
- s.files = ["lib/generators/versionist/copy_api_version/USAGE".freeze, "lib/generators/versionist/copy_api_version/copy_api_version_generator.rb".freeze, "lib/generators/versionist/inflector_fixes.rb".freeze, "lib/generators/versionist/new_api_version/USAGE".freeze, "lib/generators/versionist/new_api_version/new_api_version_generator.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_controller.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_controller_functional_test.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_controller_functional_test_rails_5.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_controller_integration_test.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_controller_spec.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_presenter.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_presenter_spec.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_presenter_test.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_presenter_test_rails_5.rb".freeze, "lib/generators/versionist/new_api_version/templates/docs_index.rb".freeze, "lib/generators/versionist/new_api_version/templates/docs_style.rb".freeze, "lib/generators/versionist/new_controller/USAGE".freeze, "lib/generators/versionist/new_controller/new_controller_generator.rb".freeze, "lib/generators/versionist/new_controller/templates/new_controller.rb".freeze, "lib/generators/versionist/new_controller/templates/new_controller_functional_test.rb".freeze, "lib/generators/versionist/new_controller/templates/new_controller_functional_test_rails_5.rb".freeze, "lib/generators/versionist/new_controller/templates/new_controller_integration_test.rb".freeze, "lib/generators/versionist/new_controller/templates/new_controller_spec.rb".freeze, "lib/generators/versionist/new_presenter/USAGE".freeze, "lib/generators/versionist/new_presenter/new_presenter_generator.rb".freeze, "lib/generators/versionist/new_presenter/templates/new_presenter.rb".freeze, "lib/generators/versionist/new_presenter/templates/new_presenter_spec.rb".freeze, "lib/generators/versionist/new_presenter/templates/new_presenter_test.rb".freeze, "lib/generators/versionist/new_presenter/templates/new_presenter_test_rails_5.rb".freeze, "lib/generators/versionist/rspec_helper.rb".freeze, "lib/versionist.rb".freeze, "lib/versionist/configuration.rb".freeze, "lib/versionist/middleware.rb".freeze, "lib/versionist/railtie.rb".freeze, "lib/versionist/routing.rb".freeze, "lib/versionist/version.rb".freeze, "lib/versionist/versioning_strategy.rb".freeze, "lib/versionist/versioning_strategy/base.rb".freeze, "lib/versionist/versioning_strategy/default.rb".freeze, "lib/versionist/versioning_strategy/header.rb".freeze, "lib/versionist/versioning_strategy/parameter.rb".freeze, "lib/versionist/versioning_strategy/path.rb".freeze]
- s.homepage = "https://github.com/bploetz/versionist".freeze
- s.licenses = ["MIT".freeze]
- s.rdoc_options = ["--charset=UTF-8".freeze]
- s.rubygems_version = "2.5.2.1".freeze
- s.summary = "versionist-2.0.1".freeze
+Gem::Specification.new do |s|
+ s.name = 'versionist'
+ s.homepage = 'https://github.com/bploetz/versionist'
+ s.version = Versionist::VERSION
+ s.platform = Gem::Platform::RUBY
+ s.authors = ['Brian Ploetz']
+ s.summary = "versionist-#{Versionist::VERSION}"
+ s.description = 'A plugin for versioning Rails based RESTful APIs.'
+ s.license = 'MIT'
+ s.files = Dir['lib/**/*']
+ s.rdoc_options = ['--charset=UTF-8']
+ s.require_paths = ['lib']
+ s.required_rubygems_version = '>= 1.3.6'
- if s.respond_to? :specification_version then
- s.specification_version = 4
+ s.add_dependency 'railties', '>= 3'
+ s.add_dependency 'activesupport', '>= 3'
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
- s.add_runtime_dependency(%q<activesupport>.freeze, [">= 3"])
- s.add_runtime_dependency(%q<railties>.freeze, [">= 3"])
- s.add_runtime_dependency(%q<yard>.freeze, ["~> 0.9.20"])
- else
- s.add_dependency(%q<activesupport>.freeze, [">= 3"])
- s.add_dependency(%q<railties>.freeze, [">= 3"])
- s.add_dependency(%q<yard>.freeze, ["~> 0.9.20"])
- end
- else
- s.add_dependency(%q<activesupport>.freeze, [">= 3"])
- s.add_dependency(%q<railties>.freeze, [">= 3"])
- s.add_dependency(%q<yard>.freeze, ["~> 0.9.20"])
- end
+ s.add_dependency('yard', "~> 0.9.20")
end
Debdiff
File lists identical (after any substitutions)
No differences were encountered in the control files