apipie-rails 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +12 -48
  3. data/.github/workflows/rubocop-challenger.yml +2 -2
  4. data/.github/workflows/rubocop.yml +2 -4
  5. data/.rubocop.yml +39 -38
  6. data/.rubocop_todo.yml +55 -65
  7. data/.vscode/settings.json +3 -0
  8. data/CHANGELOG.md +19 -2
  9. data/Gemfile +20 -0
  10. data/README.rst +12 -9
  11. data/app/controllers/apipie/apipies_controller.rb +3 -17
  12. data/gemfiles/Gemfile.tools +9 -0
  13. data/lib/apipie/application.rb +18 -7
  14. data/lib/apipie/dsl_definition.rb +6 -5
  15. data/lib/apipie/errors.rb +14 -0
  16. data/lib/apipie/extractor/collector.rb +1 -1
  17. data/lib/apipie/extractor/recorder.rb +1 -1
  18. data/lib/apipie/extractor.rb +6 -3
  19. data/lib/apipie/generator/swagger/config.rb +3 -1
  20. data/lib/apipie/generator/swagger/method_description/api_schema_service.rb +6 -3
  21. data/lib/apipie/generator/swagger/warning.rb +1 -1
  22. data/lib/apipie/resource_description.rb +28 -3
  23. data/lib/apipie/validator.rb +20 -6
  24. data/lib/apipie/version.rb +1 -1
  25. data/spec/controllers/api/v2/architectures_controller_spec.rb +10 -3
  26. data/spec/controllers/api/v2/empty_middle_controller_spec.rb +23 -0
  27. data/spec/controllers/api/v2/nested/resources_controller_spec.rb +16 -0
  28. data/spec/controllers/api/v2/sub/footguns_controller_spec.rb +19 -0
  29. data/spec/controllers/users_controller_spec.rb +10 -0
  30. data/spec/dummy/app/controllers/api/v2/base_controller.rb +6 -0
  31. data/spec/dummy/app/controllers/api/v2/empty_middle_controller.rb +14 -0
  32. data/spec/dummy/app/controllers/api/v2/nested/resources_controller.rb +2 -2
  33. data/spec/dummy/app/controllers/api/v2/sub/footguns_controller.rb +30 -0
  34. data/spec/dummy/app/controllers/users_controller.rb +6 -0
  35. data/spec/dummy/config/routes.rb +1 -0
  36. data/spec/lib/apipie/apipies_controller_spec.rb +63 -19
  37. data/spec/lib/apipie/extractor/collector_spec.rb +57 -0
  38. data/spec/lib/apipie/generator/swagger/method_description/api_schema_service_spec.rb +13 -0
  39. data/spec/test_engine/memes_controller_spec.rb +1 -1
  40. metadata +11 -9
  41. data/gemfiles/Gemfile.rails50 +0 -10
  42. data/gemfiles/Gemfile.rails51 +0 -10
  43. data/gemfiles/Gemfile.rails52 +0 -10
  44. data/gemfiles/Gemfile.rails60 +0 -17
  45. data/gemfiles/Gemfile.rails61 +0 -17
  46. data/gemfiles/Gemfile.rails70 +0 -17
@@ -241,9 +241,11 @@ module Apipie
241
241
  method_params = self.class._apipie_get_method_params(action_name)
242
242
 
243
243
  if Apipie.configuration.validate_presence?
244
- method_params.each do |_, param|
245
- # check if required parameters are present
246
- raise ParamMissing.new(param) if param.required && !params.key?(param.name)
244
+ Validator::BaseValidator.raise_if_missing_params do |missing|
245
+ method_params.each do |_, param|
246
+ # check if required parameters are present
247
+ missing << param if param.required && !params.key?(param.name)
248
+ end
247
249
  end
248
250
  end
249
251
 
@@ -259,7 +261,7 @@ module Apipie
259
261
  if Apipie.configuration.validate_key?
260
262
  params.reject{|k,_| %w[format controller action].include?(k.to_s) }.each_pair do |param, _|
261
263
  # params allowed
262
- if method_params.select {|_,p| p.name.to_s == param.to_s}.empty?
264
+ if method_params.none? {|_,p| p.name.to_s == param.to_s}
263
265
  self.class._apipie_handle_validate_key_error params, param
264
266
  end
265
267
  end
@@ -285,7 +287,6 @@ module Apipie
285
287
  old_method.bind(self).call(*args)
286
288
  end
287
289
  end
288
-
289
290
  end
290
291
  end
291
292
 
data/lib/apipie/errors.rb CHANGED
@@ -24,6 +24,20 @@ module Apipie
24
24
  end
25
25
  end
26
26
 
27
+ class ParamMultipleMissing < ParamError
28
+ attr_accessor :params
29
+
30
+ def initialize(params)
31
+ @params = params
32
+ end
33
+
34
+ def to_s
35
+ params.map do |param|
36
+ ParamMissing.new(param).to_s
37
+ end.join("\n")
38
+ end
39
+ end
40
+
27
41
  class ParamMissing < DefinedParamError
28
42
  def to_s
29
43
  unless @param.options[:missing_message].nil?
@@ -19,7 +19,7 @@ module Apipie
19
19
  def ignore_call?(record)
20
20
  return true unless record[:controller]
21
21
  return true if @ignored.include?(record[:controller].name)
22
- return true if @ignored.include?("#{Apipie.resource_id(record[:controller].name)}##{record[:action]}")
22
+ return true if @ignored.include?("#{Apipie.get_resource_id(record[:controller].name)}##{record[:action]}")
23
23
  return true unless @api_controllers_paths.include?(controller_full_path(record[:controller]))
24
24
  end
25
25
 
@@ -48,7 +48,7 @@ module Apipie
48
48
  else
49
49
  @query = request.query_string
50
50
  end
51
- if response.content_type != 'application/pdf'
51
+ if response.media_type != 'application/pdf'
52
52
  @response_data = parse_data(response.body)
53
53
  end
54
54
  @code = response.code
@@ -15,10 +15,13 @@ class Apipie::Railtie
15
15
  end
16
16
  end
17
17
  end
18
- app.middleware.use ::Apipie::Extractor::Recorder::Middleware
19
18
 
20
- ActionController::TestCase.send(:prepend, Apipie::Extractor::Recorder::FunctionalTestRecording)
21
- ActionController::TestCase::Behavior.send(:prepend, Apipie::Extractor::Recorder::FunctionalTestRecording)
19
+ if Apipie.configuration.record
20
+ app.middleware.use ::Apipie::Extractor::Recorder::Middleware
21
+
22
+ ActionController::TestCase.send(:prepend, Apipie::Extractor::Recorder::FunctionalTestRecording)
23
+ ActionController::TestCase::Behavior.send(:prepend, Apipie::Extractor::Recorder::FunctionalTestRecording)
24
+ end
22
25
  end
23
26
  end
24
27
 
@@ -10,7 +10,7 @@ module Apipie
10
10
  :json_input_uses_refs, :suppress_warnings, :api_host,
11
11
  :generate_x_computed_id_field, :allow_additional_properties_in_response,
12
12
  :responses_use_refs, :schemes, :security_definitions,
13
- :global_security].freeze
13
+ :global_security, :skip_default_tags].freeze
14
14
 
15
15
  attr_accessor(*CONFIG_ATTRIBUTES)
16
16
 
@@ -43,6 +43,7 @@ module Apipie
43
43
  alias include_warning_tags? include_warning_tags
44
44
  alias json_input_uses_refs? json_input_uses_refs
45
45
  alias responses_use_refs? responses_use_refs
46
+ alias skip_default_tags? skip_default_tags
46
47
  alias generate_x_computed_id_field? generate_x_computed_id_field
47
48
  alias swagger_include_warning_tags? swagger_include_warning_tags
48
49
  alias swagger_json_input_uses_refs? swagger_json_input_uses_refs
@@ -61,6 +62,7 @@ module Apipie
61
62
  @schemes = [:https]
62
63
  @security_definitions = {}
63
64
  @global_security = []
65
+ @skip_default_tags = false
64
66
  end
65
67
 
66
68
  def self.deprecated_methods
@@ -47,9 +47,12 @@ class Apipie::Generator::Swagger::MethodDescription::ApiSchemaService
47
47
  end
48
48
 
49
49
  def tags
50
- [@method_description.resource._id] +
51
- warning_tags +
52
- @method_description.tag_list.tags
50
+ tags = if Apipie.configuration.generator.swagger.skip_default_tags?
51
+ []
52
+ else
53
+ [@method_description.resource._id]
54
+ end
55
+ tags + warning_tags + @method_description.tag_list.tags
53
56
  end
54
57
 
55
58
  def warning_tags
@@ -59,7 +59,7 @@ class Apipie::Generator::Swagger::Warning
59
59
  #
60
60
  # @return [Apipie::Generator::Swagger::Warning]
61
61
  def self.for_code(code, method_id, message_attributes = {})
62
- if !CODES.values.include?(code)
62
+ if !CODES.value?(code)
63
63
  raise ArgumentError, 'Unknown warning code'
64
64
  end
65
65
 
@@ -26,7 +26,9 @@ module Apipie
26
26
  @controller = controller
27
27
  @_id = id
28
28
  @_version = version || Apipie.configuration.default_version
29
- @_parent = Apipie.get_resource_description(controller.superclass, version)
29
+ @_parent = Apipie.value_from_parents(controller.superclass, version) do |parent, ver|
30
+ Apipie.get_resource_description(parent, ver)
31
+ end
30
32
 
31
33
  update_from_dsl_data(dsl_data) if dsl_data
32
34
  end
@@ -60,7 +62,16 @@ module Apipie
60
62
  end
61
63
 
62
64
  def name
63
- @name ||= @_resource_name.presence || @_id.split('-').map(&:capitalize).join('::')
65
+ @name ||= case resource_name
66
+ when Proc
67
+ resource_name.call(controller)
68
+ when Symbol
69
+ controller.public_send(resource_name)
70
+ when String
71
+ resource_name
72
+ else
73
+ default_name
74
+ end
64
75
  end
65
76
  alias _name name
66
77
 
@@ -90,7 +101,9 @@ module Apipie
90
101
  Apipie.full_url crumbs.join('/')
91
102
  end
92
103
 
93
- def api_url; "#{Apipie.api_base_url(_version)}#{@_path}"; end
104
+ def api_url
105
+ "#{Apipie.api_base_url(_version)}#{@_path}"
106
+ end
94
107
 
95
108
  def valid_method_name?(method_name)
96
109
  @_methods.keys.map(&:to_s).include?(method_name.to_s)
@@ -123,5 +136,17 @@ module Apipie
123
136
  }
124
137
  end
125
138
 
139
+ protected
140
+
141
+ def resource_name
142
+ @_resource_name.presence || @_parent&.resource_name
143
+ end
144
+
145
+ private
146
+
147
+ def default_name
148
+ @_id.split('-').map(&:capitalize).join('::')
149
+ end
150
+
126
151
  end
127
152
  end
@@ -38,6 +38,16 @@ module Apipie
38
38
  return nil
39
39
  end
40
40
 
41
+ def self.raise_if_missing_params
42
+ missing_params = []
43
+ yield missing_params
44
+ if missing_params.size > 1
45
+ raise ParamMultipleMissing.new(missing_params)
46
+ elsif missing_params.size == 1
47
+ raise ParamMissing.new(missing_params.first)
48
+ end
49
+ end
50
+
41
51
  # check if value is valid
42
52
  def valid?(value)
43
53
  if self.validate(value)
@@ -345,14 +355,18 @@ module Apipie
345
355
 
346
356
  def validate(value)
347
357
  return false if !value.is_a? Hash
348
- @hash_params&.each do |k, p|
349
- if Apipie.configuration.validate_presence?
350
- raise ParamMissing.new(p) if p.required && !value.key?(k)
351
- end
352
- if Apipie.configuration.validate_value?
353
- p.validate(value[k]) if value.key?(k)
358
+
359
+ BaseValidator.raise_if_missing_params do |missing|
360
+ @hash_params&.each do |k, p|
361
+ if Apipie.configuration.validate_presence?
362
+ missing << p if p.required && !value.key?(k)
363
+ end
364
+ if Apipie.configuration.validate_value?
365
+ p.validate(value[k]) if value.key?(k)
366
+ end
354
367
  end
355
368
  end
369
+
356
370
  return true
357
371
  end
358
372
 
@@ -1,3 +1,3 @@
1
1
  module Apipie
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.1"
3
3
  end
@@ -1,12 +1,19 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Api::V2::ArchitecturesController do
4
+ let(:resource_description) { Apipie.get_resource_description(described_class, "2.0") }
5
+
4
6
  describe "resource description" do
5
- subject { Apipie.get_resource_description(Api::V2::ArchitecturesController, "2.0") }
7
+ describe 'version' do
8
+ subject { resource_description._version }
6
9
 
7
- it "should be version 2.0" do
8
- expect(subject._version).to eq('2.0')
10
+ it { is_expected.to eq('2.0') }
9
11
  end
10
12
 
13
+ describe 'name' do
14
+ subject { resource_description.name }
15
+
16
+ it { is_expected.to eq('Architectures') }
17
+ end
11
18
  end
12
19
  end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Api::V2::EmptyMiddleController do
4
+ let(:resource_description) { Apipie.get_resource_description(described_class, '2.0') }
5
+
6
+ describe 'resource description' do
7
+ subject { resource_description }
8
+
9
+ context 'when namespaced resources are enabled' do
10
+ before { Apipie.configuration.namespaced_resources = true }
11
+ after { Apipie.configuration.namespaced_resources = false }
12
+
13
+ # we don't actually expect the resource description to be nil, but resource IDs
14
+ # are computed at file load time, and altering the value of namespaced_resources
15
+ # after the fact doesn't change the resource ID, so it can't be found
16
+ it { is_expected.to be_nil }
17
+ end
18
+
19
+ context 'when namespaced resources are disabled' do
20
+ it { is_expected.to be_nil }
21
+ end
22
+ end
23
+ end
@@ -1,6 +1,22 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Api::V2::Nested::ResourcesController do
4
+ let(:resource_description) { Apipie.get_resource_description(described_class, "2.0") }
5
+
6
+ describe "resource description" do
7
+ describe 'version' do
8
+ subject { resource_description._version }
9
+
10
+ it { is_expected.to eq('2.0') }
11
+ end
12
+
13
+ describe 'name' do
14
+ subject { resource_description.name }
15
+
16
+ it { is_expected.to eq('Rsrcs') }
17
+ end
18
+ end
19
+
4
20
  describe '.get_resource_id' do
5
21
  subject { Apipie.get_resource_id(Api::V2::Nested::ResourcesController) }
6
22
 
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Api::V2::Sub::FootgunsController do
4
+ let(:resource_description) { Apipie.get_resource_description(described_class, '2.0') }
5
+
6
+ describe 'resource description' do
7
+ describe 'version' do
8
+ subject { resource_description._version }
9
+
10
+ it { is_expected.to eq('2.0') }
11
+ end
12
+
13
+ describe 'name' do
14
+ subject { resource_description.name }
15
+
16
+ it { is_expected.to eq('snugtooF') }
17
+ end
18
+ end
19
+ end
@@ -37,6 +37,7 @@ describe UsersController do
37
37
  expect(methods.keys).to include(:update)
38
38
  expect(methods.keys).to include(:two_urls)
39
39
  expect(methods.keys).to include(:action_with_headers)
40
+ expect(methods.keys).to include(:multiple_required_params)
40
41
  end
41
42
 
42
43
  it "should contain info about resource" do
@@ -101,6 +102,10 @@ describe UsersController do
101
102
  expect { get :show, :params => { :id => 5 }}.to raise_error(Apipie::ParamMissing, /session_parameter_is_required/)
102
103
  end
103
104
 
105
+ it "should fail if multiple required parameters are missing" do
106
+ expect { get :multiple_required_params }.to raise_error(Apipie::ParamMultipleMissing, /required_param1.*\n.*required_param2|required_param2.*\n.*required_parameter1/)
107
+ end
108
+
104
109
  it "should pass if required parameter has wrong type" do
105
110
  expect { get :show, :params => { :id => 5 , :session => "secret_hash" }}.not_to raise_error
106
111
  expect { get :show, :params => { :id => "ten" , :session => "secret_hash" }}.not_to raise_error
@@ -246,6 +251,11 @@ describe UsersController do
246
251
  post :create, :params => { :user => { :name => "root", :pass => "12345", :membership => "____" } }
247
252
  }.to raise_error(Apipie::ParamInvalid, /membership/)
248
253
 
254
+ # Should include both pass and name
255
+ expect {
256
+ post :create, :params => { :user => { :membership => "standard" } }
257
+ }.to raise_error(Apipie::ParamMultipleMissing, /pass.*\n.*name|name.*\n.*pass/)
258
+
249
259
  expect {
250
260
  post :create, :params => { :user => { :name => "root" } }
251
261
  }.to raise_error(Apipie::ParamMissing, /pass/)
@@ -5,6 +5,12 @@ module Api
5
5
  api_version '2.0'
6
6
  app_info 'Version 2.0 description'
7
7
  api_base_url '/api/v2'
8
+
9
+ name :reversed_name
10
+ end
11
+
12
+ def self.reversed_name
13
+ controller_name.capitalize.reverse
8
14
  end
9
15
  end
10
16
  end
@@ -0,0 +1,14 @@
1
+ module Api
2
+ module V2
3
+ class EmptyMiddleController < V2::BaseController
4
+ # This is an empty controller, used to test cases where controllers
5
+ # may inherit from a middle controler that does not define a resource_description,
6
+ # but the middle controller's parent does.
7
+
8
+ def inconsequential_method
9
+ # This method is here to ensure that the controller is not empty.
10
+ # It triggers method_added, which is used to add the resource description.
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,8 +1,8 @@
1
1
  module Api
2
2
  module V2
3
3
  class Nested::ResourcesController < V2::BaseController
4
- resource_description do
5
- name 'Resources'
4
+ resource_description do
5
+ name ->(controller) { controller.controller_name.delete('aeiou').capitalize }
6
6
  resource_id "resource"
7
7
  end
8
8
  api :GET, "/nested/resources/", "List all nested resources."
@@ -0,0 +1,30 @@
1
+ module Api
2
+ module V2
3
+ module Sub
4
+ class FootgunsController < V2::EmptyMiddleController
5
+ resource_description do
6
+ short 'Footguns are bad'
7
+ end
8
+
9
+ api :GET, '/footguns/', 'List all footguns.'
10
+ def index; end
11
+
12
+ api :GET, '/footguns/:id/', 'Show a footgun.'
13
+ def show; end
14
+
15
+ api :POST, '/footguns/', 'Create a footgun.'
16
+ def create; end
17
+
18
+ api :PUT, '/footguns/:id/', 'Update a footgun.'
19
+ param :footgun, Hash, :required => true do
20
+ param :name, String
21
+ end
22
+ def update; end
23
+
24
+ api! 'Delete a footgun.'
25
+ api_version '2.0' # forces removal of the method description
26
+ def destroy; end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -301,4 +301,10 @@ class UsersController < ApplicationController
301
301
  header :HeaderNameWithDefaultValue, 'Header with default value', required: true, default: 'default value'
302
302
  def action_with_headers
303
303
  end
304
+
305
+ api :GET, '/users/multiple_required_params'
306
+ param :required_param1, String, required: true
307
+ param :required_param2, String, required: true
308
+ def multiple_required_params
309
+ end
304
310
  end
@@ -8,6 +8,7 @@ Dummy::Application.routes.draw do
8
8
  resources :users do
9
9
  collection do
10
10
  post :create_route
11
+ get :multiple_required_params
11
12
  end
12
13
  end
13
14
  resources :concerns, :only => [:index, :show]
@@ -258,12 +258,12 @@ describe Apipie::ApipiesController, type: :controller do
258
258
 
259
259
  before do
260
260
  FileUtils.rm_r(cache_dir) if File.exist?(cache_dir)
261
- FileUtils.mkdir_p(File.join(cache_dir, "apidoc", "v1", "resource"))
261
+ FileUtils.mkdir_p(File.join(cache_dir, "apidoc", "v1", "resource-with-namespace"))
262
262
  File.open(File.join(cache_dir, "apidoc", "v1.html"), "w") { |f| f << "apidoc.html cache v1" }
263
263
  File.open(File.join(cache_dir, "apidoc", "v2.html"), "w") { |f| f << "apidoc.html cache v2" }
264
264
  File.open(File.join(cache_dir, "apidoc", "v1.json"), "w") { |f| f << "apidoc.json cache" }
265
- File.open(File.join(cache_dir, "apidoc", "v1", "resource.html"), "w") { |f| f << "resource.html cache" }
266
- File.open(File.join(cache_dir, "apidoc", "v1", "resource", "method.html"), "w") { |f| f << "method.html cache" }
265
+ File.open(File.join(cache_dir, "apidoc", "v1", "resource-with-namespace.html"), "w") { |f| f << "resource-with-namespace.html cache" }
266
+ File.open(File.join(cache_dir, "apidoc", "v1", "resource-with-namespace", "method.html"), "w") { |f| f << "method.html cache" }
267
267
 
268
268
  Apipie.configuration.use_cache = true
269
269
  @orig_cache_dir = Apipie.configuration.cache_dir
@@ -279,24 +279,68 @@ describe Apipie::ApipiesController, type: :controller do
279
279
  # FileUtils.rm_r(cache_dir) if File.exist?(cache_dir)
280
280
  end
281
281
 
282
- it "uses the file in cache dir instead of generating the content on runtime" do
283
- get :index
284
- expect(response.body).to eq("apidoc.html cache v1")
285
- get :index, :params => { :version => 'v1' }
286
- expect(response.body).to eq("apidoc.html cache v1")
287
- get :index, :params => { :version => 'v2' }
288
- expect(response.body).to eq("apidoc.html cache v2")
289
- get :index, :params => { :version => 'v1', :format => "html" }
290
- expect(response.body).to eq("apidoc.html cache v1")
291
- get :index, :params => { :version => 'v1', :format => "json" }
292
- expect(response.body).to eq("apidoc.json cache")
293
- get :index, :params => { :version => 'v1', :format => "html", :resource => "resource" }
294
- expect(response.body).to eq("resource.html cache")
295
- get :index, :params => { :version => 'v1', :format => "html", :resource => "resource", :method => "method" }
296
- expect(response.body).to eq("method.html cache")
282
+ context 'when the file exists' do
283
+ it "uses the file in cache dir instead of generating the content on runtime" do
284
+ get :index
285
+ expect(response.body).to eq("apidoc.html cache v1")
286
+
287
+ get :index, :params => { :version => 'v1' }
288
+ expect(response.body).to eq("apidoc.html cache v1")
289
+
290
+ get :index, :params => { :version => 'v2' }
291
+ expect(response.body).to eq("apidoc.html cache v2")
292
+
293
+ get :index, :params => { :version => 'v1', :format => "html" }
294
+ expect(response.body).to eq("apidoc.html cache v1")
295
+
296
+ get :index, :params => { :version => 'v1', :format => "json" }
297
+ expect(response.body).to eq("apidoc.json cache")
298
+
299
+ get :index, :params => { :version => 'v1', :format => "html", :resource => "resource-with-namespace" }
300
+ expect(response.body).to eq("resource-with-namespace.html cache")
301
+
302
+ get :index, :params => { :version => 'v1', :format => "html", :resource => "resource-with-namespace", :method => "method" }
303
+ expect(response.body).to eq("method.html cache")
304
+ end
297
305
  end
298
306
 
299
- end
307
+ context 'when the file does not exist' do
308
+ it 'returns a not found' do
309
+ get :index, :params => { :version => 'v3-does-not-exist' }
310
+ expect(response).to have_http_status(:not_found)
311
+ end
312
+ end
313
+
314
+ context 'preventing path traversal' do
315
+ context 'when resource contains ..' do
316
+ it "returns a not found" do
317
+ get :index, :params => { :version => 'v1', :format => "html", :resource => "../resource-with-namespace", :method => "method" }
318
+ expect(response).to have_http_status(:not_found)
319
+ end
320
+ end
300
321
 
322
+ context 'when method contains ..' do
323
+ it "returns a not found" do
324
+ get :index, :params => { :version => 'v1', :format => "html", :resource => "resource-with-namespace", :method => "../method" }
325
+ expect(response).to have_http_status(:not_found)
326
+ end
327
+ end
328
+
329
+ context 'when version contains ..' do
330
+ it "returns a not found" do
331
+ get :index, :params => { :version => '../v1', :format => "html", :resource => "resource-with-namespace", :method => "method" }
332
+ expect(response).to have_http_status(:not_found)
333
+ end
334
+ end
335
+
336
+ context 'when format contains ..' do
337
+ it "returns a not found" do
338
+ get :index, :params => { :version => 'v1', :format => "../html", :resource => "resource-with-namespace", :method => "method" }
339
+ expect(response).to have_http_status(:not_found)
340
+ end
341
+ end
342
+ end
343
+
344
+ end
301
345
 
302
346
  end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Apipie::Extractor::Collector do
6
+ let(:recorder) { described_class.new }
7
+
8
+ describe '#ignore_call?' do
9
+ subject { recorder.ignore_call?(record) }
10
+
11
+ let(:record) { { controller: controller, action: action } }
12
+ let(:controller) { ActionController::Base }
13
+ let(:action) { nil }
14
+
15
+ context 'when controller is nil' do
16
+ let(:controller) { nil }
17
+
18
+ it { is_expected.to be true }
19
+ end
20
+
21
+ context 'when controller is ignored' do
22
+ before do
23
+ allow(Apipie.configuration).to receive(:ignored_by_recorder).and_return(['ActionController::Bas'])
24
+ end
25
+
26
+ it { is_expected.to be true }
27
+ end
28
+
29
+ context 'when resource#method is ignored' do
30
+ let(:action) { 'ignored_action' }
31
+
32
+ before do
33
+ allow(Apipie.configuration).to receive(:ignored_by_recorder).and_return(['ActionController::Bas#ignored_action'])
34
+ end
35
+
36
+ it { is_expected.to be true }
37
+ end
38
+
39
+ context 'when controller is not an API controller' do
40
+ before do
41
+ allow(Apipie::Extractor).to receive(:controller_path).with('action_controller/base').and_return('foo')
42
+ allow(Apipie).to receive(:api_controllers_paths).and_return([])
43
+ end
44
+
45
+ it { is_expected.to be true }
46
+ end
47
+
48
+ context 'when controller is an API controller' do
49
+ before do
50
+ allow(Apipie::Extractor).to receive(:controller_path).with('action_controller/base').and_return('foo')
51
+ allow(Apipie).to receive(:api_controllers_paths).and_return(['foo'])
52
+ end
53
+
54
+ it { is_expected.to be_falsey }
55
+ end
56
+ end
57
+ end
@@ -64,6 +64,19 @@ describe Apipie::Generator::Swagger::MethodDescription::ApiSchemaService do
64
64
  it { is_expected.to include(*tags) }
65
65
  end
66
66
 
67
+ context 'when Apipie.configuration.generator.swagger.skip_default_tags is enabled' do
68
+ before { Apipie.configuration.generator.swagger.skip_default_tags = true }
69
+ after { Apipie.configuration.generator.swagger.skip_default_tags = false }
70
+
71
+ it { is_expected.to be_empty }
72
+
73
+ context 'when tags are available' do
74
+ let(:tags) { ['Tag 1', 'Tag 2'] }
75
+
76
+ it { is_expected.to eq(tags) }
77
+ end
78
+ end
79
+
67
80
  context 'when Apipie.configuration.generator.swagger.include_warning_tags is enabled' do
68
81
  before { Apipie.configuration.generator.swagger.include_warning_tags = true }
69
82
 
@@ -4,7 +4,7 @@ describe TestEngine::MemesController do
4
4
 
5
5
  describe "#index" do
6
6
  it "should have the full mounted path of engine" do
7
- Apipie.routes_for_action(TestEngine::MemesController, :index, {}).first[:path].should eq("/test/memes")
7
+ expect(Apipie.routes_for_action(TestEngine::MemesController, :index, {}).first[:path]).to eq("/test/memes")
8
8
  end
9
9
  end
10
10
  end