versioncake 2.5.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +6 -14
  2. data/.rspec +2 -0
  3. data/.travis.yml +4 -0
  4. data/Appraisals +12 -0
  5. data/CHANGELOG.md +18 -1
  6. data/CONTRIBUTING.md +2 -2
  7. data/Gemfile.lock +96 -44
  8. data/README.md +79 -29
  9. data/RELEASE.md +1 -1
  10. data/Rakefile +3 -7
  11. data/gemfiles/rails3.2.gemfile +2 -1
  12. data/gemfiles/rails3.2.gemfile.lock +34 -10
  13. data/gemfiles/rails4.0.gemfile +2 -1
  14. data/gemfiles/rails4.0.gemfile.lock +31 -7
  15. data/gemfiles/rails4.1.gemfile +1 -1
  16. data/gemfiles/rails4.1.gemfile.lock +28 -8
  17. data/gemfiles/rails4.2.gemfile +9 -0
  18. data/gemfiles/rails4.2.gemfile.lock +133 -0
  19. data/lib/generators/templates/versioncake.rb +40 -0
  20. data/lib/generators/versioncake/install_generator.rb +12 -0
  21. data/lib/versioncake.rb +24 -3
  22. data/lib/versioncake/configuration.rb +19 -2
  23. data/lib/versioncake/controller_additions.rb +35 -23
  24. data/lib/versioncake/engine.rb +7 -0
  25. data/lib/versioncake/exceptions.rb +4 -0
  26. data/lib/versioncake/rack/middleware.rb +20 -0
  27. data/lib/versioncake/strategies/extraction_strategy.rb +8 -3
  28. data/lib/versioncake/strategies/http_accept_parameter_strategy.rb +2 -2
  29. data/lib/versioncake/strategies/http_header_strategy.rb +2 -2
  30. data/lib/versioncake/strategies/path_parameter_strategy.rb +6 -2
  31. data/lib/versioncake/strategies/query_parameter_strategy.rb +2 -2
  32. data/lib/versioncake/strategies/request_parameter_strategy.rb +2 -2
  33. data/lib/versioncake/test_helpers.rb +14 -0
  34. data/lib/versioncake/version.rb +1 -1
  35. data/lib/versioncake/version_checker.rb +28 -0
  36. data/lib/versioncake/version_context.rb +20 -0
  37. data/lib/versioncake/version_context_service.rb +47 -0
  38. data/lib/versioncake/versioned_request.rb +22 -33
  39. data/lib/versioncake/versioned_resource.rb +14 -0
  40. data/lib/versioncake/view_additions.rb +7 -7
  41. data/{test → spec}/fixtures/partials/_versioned.erb +0 -0
  42. data/{test → spec}/fixtures/partials/_versioned.v1.erb +0 -0
  43. data/{test → spec}/fixtures/partials/_versioned.v2.erb +0 -0
  44. data/{test → spec}/fixtures/partials/_versioned.v3.erb +0 -0
  45. data/{test → spec}/fixtures/partials/another_versioned_partial.erb +0 -0
  46. data/{test → spec}/fixtures/partials/another_versioned_partial.v1.erb +0 -0
  47. data/{test → spec}/fixtures/templates/unversioned.html.erb +0 -0
  48. data/{test → spec}/fixtures/templates/v1_extension_scheme.v3.html.erb +0 -0
  49. data/{test → spec}/fixtures/templates/v1_extension_scheme.v6.json +0 -0
  50. data/{test → spec}/fixtures/templates/versioned.html.erb +0 -0
  51. data/{test → spec}/fixtures/templates/versioned.html.v1.erb +0 -0
  52. data/{test → spec}/fixtures/templates/versioned.html.v2.erb +0 -0
  53. data/{test → spec}/fixtures/templates/versioned.html.v3.erb +0 -0
  54. data/spec/fixtures/test_cases.yml +45 -0
  55. data/spec/integration/controller/renders_controller_spec.rb +73 -0
  56. data/spec/integration/controller/unversioned_controller_spec.rb +12 -0
  57. data/spec/integration/rack/middleware_regression_spec.rb +41 -0
  58. data/spec/integration/view/render_spec.rb +33 -0
  59. data/spec/integration/view/view_additions_spec.rb +51 -0
  60. data/spec/rails_helper.rb +41 -0
  61. data/spec/spec_helper.rb +25 -0
  62. data/spec/test_app/Rakefile +7 -0
  63. data/{test → spec/test_app}/app/controllers/renders_controller.rb +0 -0
  64. data/spec/test_app/app/controllers/unversioned_controller.rb +6 -0
  65. data/spec/test_app/app/views/renders/index.html.erb +1 -0
  66. data/{test → spec/test_app}/app/views/renders/index.html.v1.erb +0 -0
  67. data/{test → spec/test_app}/app/views/renders/index.html.v2.erb +0 -0
  68. data/spec/test_app/app/views/unversioned/index.html.erb +1 -0
  69. data/spec/test_app/config.ru +4 -0
  70. data/{test → spec/test_app}/config/application.rb +4 -6
  71. data/spec/test_app/config/boot.rb +5 -0
  72. data/spec/test_app/config/environment.rb +5 -0
  73. data/spec/test_app/config/initializers/versioncake.rb +45 -0
  74. data/spec/test_app/config/routes.rb +4 -0
  75. data/spec/test_app/script/rails +4 -0
  76. data/spec/unit/cli_spec.rb +36 -0
  77. data/spec/unit/configuration_spec.rb +61 -0
  78. data/spec/unit/strategies/extraction_strategy_spec.rb +71 -0
  79. data/spec/unit/strategies/http_accept_parameter_strategy_spec.rb +20 -0
  80. data/spec/unit/strategies/http_header_strategy_spec.rb +19 -0
  81. data/spec/unit/strategies/path_parameter_strategy_spec.rb +18 -0
  82. data/spec/unit/strategies/query_parameter_strategy_spec.rb +24 -0
  83. data/spec/unit/strategies/request_parameter_strategy_spec.rb +19 -0
  84. data/spec/unit/version_checker_spec.rb +60 -0
  85. data/spec/unit/version_context_service_spec.rb +84 -0
  86. data/spec/unit/version_context_spec.rb +46 -0
  87. data/spec/unit/versioned_request_spec.rb +35 -0
  88. data/spec/unit/versioned_resource_spec.rb +12 -0
  89. data/versioncake.gemspec +5 -2
  90. metadata +91 -70
  91. data/lib/versioncake/railtie.rb +0 -7
  92. data/test/app/views/renders/index.html.erb +0 -1
  93. data/test/config.ru +0 -0
  94. data/test/config/routes.rb +0 -3
  95. data/test/fixtures/test_cases.yml +0 -70
  96. data/test/functional/custom_strategy_controller_test.rb +0 -16
  97. data/test/functional/multiple_strategy_controller_test.rb +0 -24
  98. data/test/functional/renders_controller_test.rb +0 -71
  99. data/test/functional/strategy_controller_test.rb +0 -38
  100. data/test/script/rails +0 -0
  101. data/test/template/render_test.rb +0 -34
  102. data/test/test_helper.rb +0 -21
  103. data/test/unit/cli_test.rb +0 -48
  104. data/test/unit/configuration_test.rb +0 -45
  105. data/test/unit/strategies/extraction_strategy_test.rb +0 -70
  106. data/test/unit/strategies/http_accept_parameter_strategy_test.rb +0 -17
  107. data/test/unit/strategies/http_header_strategy_test.rb +0 -17
  108. data/test/unit/strategies/path_parameter_strategy_test.rb +0 -17
  109. data/test/unit/strategies/query_parameter_strategy_test.rb +0 -22
  110. data/test/unit/strategies/request_parameter_strategy_test.rb +0 -17
  111. data/test/unit/versioned_request_test.rb +0 -44
  112. data/test/unit/view_additions_test.rb +0 -35
@@ -0,0 +1,14 @@
1
+ module VersionCake
2
+ class VersionedResource
3
+ attr_reader :uri, :supported_versions, :deprecated_versions, :obsolete_versions
4
+
5
+ def initialize(uri, obsolete_versions, deprecated_versions, supported_versions)
6
+ @uri, @supported_versions, @deprecated_versions, @obsolete_versions =
7
+ uri, supported_versions, deprecated_versions, obsolete_versions
8
+ end
9
+
10
+ def latest_version
11
+ @supported_versions.last
12
+ end
13
+ end
14
+ end
@@ -3,17 +3,17 @@ require 'action_view'
3
3
  # register an addition detail for the lookup context to understand,
4
4
  # this will allow us to have the versions available upon lookup in
5
5
  # the resolver.
6
- ActionView::LookupContext.register_detail(:versions){ VersionCake::Railtie.config.versioncake.supported_versions }
6
+ ActionView::LookupContext.register_detail(:versions){ [] }
7
7
 
8
8
  ActionView::PathResolver.class_eval do
9
9
  # not sure why we are doing this yet, but looks like a good idea
10
- if ActionPack::VERSION::MAJOR >= 4 && ActionPack::VERSION::MINOR >= 1
10
+ if ActionPack::VERSION::MAJOR >= 4 && ActionPack::VERSION::MINOR >= 1 || ActionPack::VERSION::MAJOR >= 5
11
11
  ActionView::PathResolver::EXTENSIONS.replace({
12
- :locale => ".",
13
- :formats => ".",
14
- :versions => ".",
15
- :variants => "+",
16
- :handlers => "."
12
+ locale: ".",
13
+ formats: ".",
14
+ versions: ".",
15
+ variants: "+",
16
+ handlers: "."
17
17
  })
18
18
 
19
19
  ActionView::PathResolver::DEFAULT_PATTERN.replace ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:versions,}{.:handlers,}"
@@ -0,0 +1,45 @@
1
+ # http_header_strategy
2
+ - request:
3
+ headers:
4
+ HTTP_ACCEPT: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=1"
5
+ response: "1"
6
+
7
+ - request:
8
+ headers:
9
+ HTTP_ACCEPT: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8;api_version=2"
10
+ response: "2"
11
+
12
+ # request_parameter_strategy
13
+ - request:
14
+ method: post
15
+ params:
16
+ api_version: "1"
17
+ response: "1"
18
+
19
+ - request:
20
+ method: post
21
+ params:
22
+ api_version: "2"
23
+ response: "2"
24
+
25
+ # query_parameter_strategy
26
+ - request:
27
+ params:
28
+ api_version: "1"
29
+ response: "1"
30
+
31
+ - request:
32
+ params:
33
+ api_version: "2"
34
+ response: "2"
35
+
36
+ # http_header_strategy
37
+ - request:
38
+ headers:
39
+ HTTP_API_VERSION: "1"
40
+ response: "1"
41
+
42
+ - request:
43
+ headers:
44
+ HTTP_API_VERSION: "2"
45
+ response: "2"
@@ -0,0 +1,73 @@
1
+ require './spec/rails_helper'
2
+
3
+ describe RendersController, type: :controller do
4
+ let(:request_options) { {} }
5
+ subject(:response_body) { get :index, request_options; response.body }
6
+
7
+ context '#index' do
8
+ render_views
9
+ before { set_request_version 'renders', request_version }
10
+ before { response_body }
11
+
12
+ context 'when requesting the non latest version' do
13
+ let(:request_version) { 1 }
14
+
15
+ it { expect(controller.request_version).to eq 1 }
16
+ it { expect(controller.is_latest_version?).to be_falsey }
17
+ it { expect(controller.is_deprecated_version?).to be_falsey }
18
+ it { expect(response_body).to eq 'template v1' }
19
+ end
20
+
21
+ context 'with explicity requesting the latest version' do
22
+ let(:request_version) { 5 }
23
+
24
+ it { expect(controller.request_version).to eq 5 }
25
+ it { expect(controller.is_latest_version?).to be_truthy }
26
+ it { expect(controller.is_deprecated_version?).to be_falsey }
27
+ it { expect(response_body).to eq 'template v2' }
28
+ end
29
+
30
+ context 'when requesting a deprecated version' do
31
+ let(:request_version) { 4 }
32
+
33
+ it { expect(controller.request_version).to eq 4 }
34
+ it { expect(controller.is_latest_version?).to be_falsey }
35
+ it { expect(controller.is_deprecated_version?).to be_truthy }
36
+ it { expect(response_body).to eq 'template v2' }
37
+ end
38
+
39
+ context '#set_version' do
40
+ let(:request_options) { { 'override_version' => 2 } }
41
+ let(:request_version) { 3 }
42
+
43
+ it { expect(controller.request_version).to eq 2 }
44
+ it { expect(response_body).to eq 'template v2' }
45
+ end
46
+ end
47
+
48
+ context 'errors' do
49
+ context 'with a version larger than the supported versions' do
50
+ before { set_version_context :version_too_high }
51
+
52
+ it { expect { response_body }.to raise_error VersionCake::UnsupportedVersionError }
53
+ end
54
+
55
+ context 'with a version lower than the supported versions' do
56
+ before { set_version_context :version_too_low }
57
+
58
+ it { expect { response_body }.to raise_error VersionCake::UnsupportedVersionError }
59
+ end
60
+
61
+ context 'with an invalid version' do
62
+ before { set_version_context :version_invalid }
63
+
64
+ it { expect { response_body }.to raise_error VersionCake::UnsupportedVersionError }
65
+ end
66
+
67
+ context 'with an obsolete version' do
68
+ before { set_version_context :obsolete }
69
+
70
+ it { expect { response_body }.to raise_error VersionCake::ObsoleteVersionError }
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,12 @@
1
+ require './spec/rails_helper'
2
+
3
+ describe UnversionedController, type: :controller do
4
+ subject(:response) { get :index }
5
+
6
+ context '#index' do
7
+ render_views
8
+
9
+ it { expect(response).to be_success }
10
+ it { expect(response.body).to eq 'unversioned index' }
11
+ end
12
+ end
@@ -0,0 +1,41 @@
1
+ require './spec/rails_helper'
2
+ require 'yaml'
3
+
4
+ describe VersionCake::Rack::Middleware do
5
+ let(:app) do
6
+ rack = Rack::Builder.new do
7
+ use VersionCake::Rack::Middleware
8
+ run lambda { |env| [ 200, {}, [ env['versioncake.context'].version ] ] }
9
+ end
10
+ Rack::MockRequest.new(rack)
11
+ end
12
+
13
+ test_cases = YAML.load(File.open('./spec/fixtures/test_cases.yml'))
14
+ test_cases.each do |test_case|
15
+ context 'for a test case' do
16
+
17
+
18
+ let(:data) { test_case['request'] || {} }
19
+ let(:method) { (data['method'] || 'get').to_sym }
20
+ let(:headers) { data['headers'] || {} }
21
+ let(:params) { data['params'] || {} }
22
+ let(:test_response) { test_case['response'] }
23
+
24
+ it "test yml test cases" do
25
+ begin
26
+ response = app.request(method, '/renders', headers.merge(params: params))
27
+ expect(response.body).to(eq(test_response), custom_message(headers, params, method, response.body, test_response))
28
+ rescue => e
29
+ raise custom_message(headers, params, method, response.body, test_response) + ", but it failed with an exception '#{e.message}'"
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def custom_message(headers, params, method, actual_response, expected_response)
36
+ data = []
37
+ data << "headers:#{headers}" if headers
38
+ data << "params:#{params}" if params
39
+ "Expected #{data.join(',')} with method #{method} to yield '#{expected_response}', but got '#{actual_response}'"
40
+ end
41
+ end
@@ -0,0 +1,33 @@
1
+ require './spec/rails_helper'
2
+
3
+ describe ActionView::Base do
4
+ let(:path) { ActionView::FileSystemResolver.new('./spec/fixtures') }
5
+ let(:view_paths) { ActionView::PathSet.new([path]) }
6
+ let(:view) { ActionView::Base.new(view_paths) }
7
+ let(:version_override) { nil }
8
+ subject { view.render(template: 'templates/versioned', versions: version_override) }
9
+
10
+ context 'with a 0 version' do
11
+ before { view.lookup_context.versions = [:v0] }
12
+
13
+ it { is_expected.to eq 'template' }
14
+ end
15
+
16
+ context 'with the version override set' do
17
+ let(:version_override) { :v1 }
18
+
19
+ it { is_expected.to eq 'template v1' }
20
+ end
21
+
22
+ context 'with an older version in the lookup context' do
23
+ before { view.lookup_context.versions = [:v2] }
24
+
25
+ it { is_expected.to eq 'template v2' }
26
+ end
27
+
28
+ context 'with a v4 requested, but only highest templates is v3' do
29
+ before { view.lookup_context.versions = [:v4,:v3,:v2,:v1] }
30
+
31
+ it { is_expected.to eq 'template v3' }
32
+ end
33
+ end
@@ -0,0 +1,51 @@
1
+ require './spec/rails_helper'
2
+
3
+ describe ActionView::PathResolver do
4
+ let(:resolver) { ActionView::PathResolver.new }
5
+
6
+ context '#extract_handler_and_format' do
7
+ subject(:template_format) do
8
+ _, format = resolver.extract_handler_and_format("application.#{template_extension}", nil)
9
+ format.to_s
10
+ end
11
+
12
+ context 'when only handler and format are present' do
13
+ let(:template_extension) { 'html.erb' }
14
+
15
+ it { expect(template_format).to eq 'text/html' }
16
+ end
17
+
18
+ context 'when handler, format and version are present' do
19
+ let(:template_extension) { 'json.v1.jbuilder' }
20
+
21
+ it { expect(template_format).to eq 'application/json' }
22
+ end
23
+
24
+ context 'when handler, format and locale are present' do
25
+ let(:template_extension) { 'en.json.jbuilder' }
26
+
27
+ it { expect(template_format).to eq 'application/json' }
28
+ end
29
+
30
+ context 'when handler, format, locale and version are present' do
31
+ let(:template_extension) { 'en.json.v1.jbuilder' }
32
+
33
+ it { expect(template_format).to eq 'application/json' }
34
+ end
35
+
36
+ context 'when in Rails >=4.1' do
37
+ before do
38
+ unless (ActionPack::VERSION::MAJOR == 4 && ActionPack::VERSION::MINOR >= 1) ||
39
+ ActionPack::VERSION::MAJOR > 5
40
+ skip('Template variants are only available in Rails >=4.1')
41
+ end
42
+ end
43
+
44
+ context 'when handler, format, variant and version are present' do
45
+ let(:template_extension) { 'application.json+tablet.v1.jbuilder' }
46
+
47
+ it { expect(template_format).to eq 'application/json' }
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,41 @@
1
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
2
+ ENV['RAILS_ENV'] ||= 'test'
3
+ require File.expand_path('../test_app/config/environment.rb', __FILE__)
4
+ require 'rails/all'
5
+
6
+ require 'rspec/rails'
7
+
8
+ # Requires supporting ruby files with custom matchers and macros, etc,
9
+ # in spec/support/ and its subdirectories.
10
+ # Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
11
+
12
+ RSpec.configure do |config|
13
+ # ## Mock Framework
14
+ #
15
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
16
+ #
17
+ # config.mock_with :mocha
18
+ # config.mock_with :flexmock
19
+ # config.mock_with :rr
20
+
21
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
22
+ # config.fixture_path = "#{::Rails.root}/spec/fixtures"
23
+
24
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
25
+ # examples within a transaction, remove the following line or assign false
26
+ # instead of true.
27
+ config.use_transactional_fixtures = false # false - no active record
28
+
29
+ # If true, the base class of anonymous controllers will be inferred
30
+ # automatically. This will be the default behavior in future versions of
31
+ # rspec-rails.
32
+ config.infer_base_class_for_anonymous_controllers = false
33
+
34
+ # Run specs in random order to surface order dependencies. If you find an
35
+ # order dependency and want to debug it, you can fix the order by providing
36
+ # the seed, which is printed after each run.
37
+ # --seed 1234
38
+ config.order = "random"
39
+
40
+ config.include VersionCake::TestHelpers, type: :controller
41
+ end
@@ -0,0 +1,25 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+ require 'versioncake'
4
+
5
+ # We have to occasionally require test-unit because it was removed as a core
6
+ # dependency, so have to explicitly disable it from running automatically
7
+ Test::Unit::AutoRunner.need_auto_run = false if defined?(Test::Unit::AutoRunner)
8
+
9
+ def capture_stdout(flag=true)
10
+ if flag
11
+ out = StringIO.new
12
+ $stdout = out
13
+ else
14
+ $stdout = STDOUT
15
+ end
16
+ end
17
+
18
+ # Turn off stdout for all specs
19
+ def quiet_stdout
20
+ around(:example) do |example|
21
+ capture_stdout true
22
+ example.run
23
+ capture_stdout false
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
3
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
+
5
+ require File.expand_path('../config/application', __FILE__)
6
+
7
+ RendersTest::Application.load_tasks
@@ -0,0 +1,6 @@
1
+ require "action_controller"
2
+ require "action_controller/base"
3
+
4
+ class UnversionedController < ActionController::Base
5
+ def index;end
6
+ end
@@ -0,0 +1 @@
1
+ base template
@@ -0,0 +1 @@
1
+ unversioned index
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run RendersTest::Application
@@ -1,6 +1,4 @@
1
- require "action_controller/railtie"
2
- require "active_support/railtie"
3
-
1
+ require 'rails/all'
4
2
  # Auto-require default libraries and those for the current Rails environment.
5
3
  Bundler.require :default, Rails.env
6
4
 
@@ -11,8 +9,8 @@ module RendersTest
11
9
  config.eager_load = false
12
10
 
13
11
  config.active_support.deprecation = :stderr
14
-
15
- config.versioncake.supported_version_numbers = (1..3)
16
- config.versioncake.extraction_strategy = [:http_header, :http_accept_parameter, :query_parameter, :request_parameter]
12
+ config.generators do |g|
13
+ g.test_framework :rspec
14
+ end
17
15
  end
18
16
  end