apipie-rails 0.5.19 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +57 -0
  3. data/CHANGELOG.md +40 -0
  4. data/README.rst +25 -5
  5. data/apipie-rails.gemspec +3 -2
  6. data/app/controllers/apipie/apipies_controller.rb +1 -1
  7. data/app/public/apipie/javascripts/bundled/bootstrap-collapse.js +70 -41
  8. data/app/public/apipie/javascripts/bundled/bootstrap.js +1033 -479
  9. data/app/public/apipie/javascripts/bundled/jquery.js +5 -5
  10. data/app/public/apipie/stylesheets/bundled/bootstrap-responsive.min.css +9 -12
  11. data/app/public/apipie/stylesheets/bundled/bootstrap.min.css +9 -689
  12. data/config/locales/ko.yml +31 -0
  13. data/gemfiles/Gemfile.rails50 +10 -0
  14. data/gemfiles/Gemfile.rails51 +10 -0
  15. data/gemfiles/Gemfile.rails52 +10 -0
  16. data/gemfiles/Gemfile.rails60 +17 -0
  17. data/gemfiles/Gemfile.rails61 +17 -0
  18. data/lib/apipie/configuration.rb +8 -3
  19. data/lib/apipie/dsl_definition.rb +12 -1
  20. data/lib/apipie/extractor/recorder.rb +3 -2
  21. data/lib/apipie/param_description.rb +8 -4
  22. data/lib/apipie/static_dispatcher.rb +3 -1
  23. data/lib/apipie/swagger_generator.rb +7 -1
  24. data/lib/apipie/validator.rb +1 -1
  25. data/lib/apipie/version.rb +1 -1
  26. data/lib/apipie-rails.rb +0 -4
  27. data/rel-eng/gem_release.ipynb +41 -9
  28. data/spec/controllers/apipies_controller_spec.rb +25 -0
  29. data/spec/controllers/users_controller_spec.rb +23 -0
  30. data/spec/dummy/app/controllers/users_controller.rb +6 -0
  31. data/spec/dummy/config/application.rb +0 -3
  32. data/spec/dummy/config/environments/development.rb +0 -3
  33. data/spec/dummy/config/environments/production.rb +0 -3
  34. data/spec/dummy/config/environments/test.rb +0 -5
  35. data/spec/lib/file_handler_spec.rb +7 -0
  36. data/spec/lib/param_description_spec.rb +68 -0
  37. data/spec/lib/swagger/rake_swagger_spec.rb +15 -0
  38. data/spec/lib/swagger/response_validation_spec.rb +17 -17
  39. data/spec/spec_helper.rb +7 -1
  40. data/spec/support/rails-42-ruby-26.rb +15 -0
  41. metadata +30 -97
  42. data/.travis.yml +0 -41
  43. data/Gemfile +0 -1
  44. data/Gemfile.rails41 +0 -7
  45. data/Gemfile.rails42 +0 -14
  46. data/Gemfile.rails50 +0 -9
  47. data/Gemfile.rails51 +0 -9
  48. data/Gemfile.rails60 +0 -10
  49. data/Gemfile.rails61 +0 -10
@@ -0,0 +1,31 @@
1
+ ko:
2
+ apipie:
3
+ resources: 리소스
4
+ resource: 리소스
5
+ description: 설명
6
+ no_docs_found: 문서를 찾을 수 없습니다.
7
+ no_docs_found_descr: 해당 API에 대한 문서를 찾을 수 없습니다.
8
+ follow_instructions_html: 해당 컨트롤러의 설명을 %{href}를 따르세요.
9
+ follow_instructions_href: 자세한 설명
10
+ oops: 이런!!
11
+ resource_not_found_html: "%{resource} 리소스를 찾을 수 없습니다."
12
+ method_not_found_html: "%{resource} 리소스에 대한 %{method} 메소드를 찾을 수 없습니다."
13
+ goto_homepage_html: "%{href}로 시도해보세요."
14
+ goto_homepage_href: "%{app_name} API 문서 페이지"
15
+ required: 필수
16
+ optional: 옵션
17
+ nil_allowed: nil 허용
18
+ param_name: Param 이름
19
+ params: Params
20
+ examples: 예시
21
+ metadata: Metadata
22
+ errors: 에러
23
+ error_code: 코드
24
+ error_description: 설명
25
+ error_metadata: Metadata
26
+ supported_formats: 지원 포멧
27
+ enable_javascript_html: "%{comments_href}를 보기 위해서 JavaScript를 허용해주세요."
28
+ comments_powered_by_disqus: comments powered by %{disqus}
29
+ api_documentation: API 문서
30
+ headers: 헤더
31
+ header_name: 헤더 이름
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: '..'
4
+
5
+ gem 'actionpack', '~> 5.0.0'
6
+ gem 'activesupport', '~> 5.0.0'
7
+ gem 'mime-types', '~> 2.99.3'
8
+ gem 'rails-controller-testing'
9
+
10
+ gem 'test_engine', path: '../spec/dummy/components/test_engine', group: :test
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: '..'
4
+
5
+ gem 'actionpack', '~> 5.1.0'
6
+ gem 'activesupport', '~> 5.1.0'
7
+ gem 'mime-types', '~> 2.99.3'
8
+ gem 'rails-controller-testing'
9
+
10
+ gem 'test_engine', path: '../spec/dummy/components/test_engine', group: :test
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: '..'
4
+
5
+ gem 'actionpack', '~> 5.2.6'
6
+ gem 'activesupport', '~> 5.2.6'
7
+ gem 'mime-types', '~> 2.99.3'
8
+ gem 'rails-controller-testing'
9
+
10
+ gem 'test_engine', path: '../spec/dummy/components/test_engine', group: :test
@@ -0,0 +1,17 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: '..'
4
+
5
+ gem 'actionpack', '~> 6.0.4'
6
+ gem 'activesupport', '~> 6.0.4'
7
+ gem 'mime-types', '~> 3.0'
8
+ gem 'rails-controller-testing'
9
+ gem 'rspec-rails', '~> 5.0'
10
+
11
+ # net-smtp not included by default in Ruby 3.1
12
+ # Will be fixed by https://github.com/mikel/mail/pull/1439
13
+ if Gem.ruby_version >= Gem::Version.new("3.1.0")
14
+ gem 'net-smtp', require: false
15
+ end
16
+
17
+ gem 'test_engine', path: '../spec/dummy/components/test_engine', group: :test
@@ -0,0 +1,17 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: '..'
4
+
5
+ gem 'actionpack', '~> 6.1.5'
6
+ gem 'activesupport', '~> 6.1.5'
7
+ gem 'mime-types', '~> 3.0'
8
+ gem 'rails-controller-testing'
9
+ gem 'rspec-rails', '~> 5.0'
10
+
11
+ # net-smtp not included by default in Ruby 3.1
12
+ # Will be fixed by https://github.com/mikel/mail/pull/1439
13
+ if Gem.ruby_version >= Gem::Version.new("3.1.0")
14
+ gem 'net-smtp', require: false
15
+ end
16
+
17
+ gem 'test_engine', path: '../spec/dummy/components/test_engine', group: :test
@@ -5,13 +5,14 @@ module Apipie
5
5
  :markup, :disqus_shortname,
6
6
  :api_base_url, :doc_base_url, :required_by_default, :layout,
7
7
  :default_version, :debug, :version_in_url, :namespaced_resources,
8
- :validate, :validate_value, :validate_presence, :validate_key, :authenticate, :doc_path,
8
+ :validate, :validate_value, :validate_presence, :validate_key, :action_on_non_validated_keys, :authenticate, :doc_path,
9
9
  :show_all_examples, :process_params, :update_checksum, :checksum_path,
10
10
  :link_extension, :record, :languages, :translate, :locale, :default_locale,
11
- :persist_show_in_doc, :authorize,
11
+ :persist_show_in_doc, :authorize, :ignore_allow_blank_false,
12
12
  :swagger_include_warning_tags, :swagger_content_type_input, :swagger_json_input_uses_refs,
13
13
  :swagger_suppress_warnings, :swagger_api_host, :swagger_generate_x_computed_id_field,
14
- :swagger_allow_additional_properties_in_response, :swagger_responses_use_refs
14
+ :swagger_allow_additional_properties_in_response, :swagger_responses_use_refs,
15
+ :swagger_security_definitions, :swagger_global_security
15
16
 
16
17
  alias_method :validate?, :validate
17
18
  alias_method :required_by_default?, :required_by_default
@@ -152,6 +153,7 @@ module Apipie
152
153
  @validate_value = true
153
154
  @validate_presence = true
154
155
  @validate_key = false
156
+ @action_on_non_validated_keys = :raise
155
157
  @required_by_default = false
156
158
  @api_base_url = HashWithIndifferentAccess.new
157
159
  @doc_base_url = "/apipie"
@@ -159,6 +161,7 @@ module Apipie
159
161
  @disqus_shortname = nil
160
162
  @default_version = "1.0"
161
163
  @debug = false
164
+ @ignore_allow_blank_false = false
162
165
  @version_in_url = true
163
166
  @namespaced_resources = false
164
167
  @doc_path = "doc"
@@ -181,6 +184,8 @@ module Apipie
181
184
  @swagger_generate_x_computed_id_field = false
182
185
  @swagger_allow_additional_properties_in_response = false
183
186
  @swagger_responses_use_refs = true
187
+ @swagger_security_definitions = {}
188
+ @swagger_global_security = []
184
189
  end
185
190
  end
186
191
  end
@@ -262,7 +262,9 @@ module Apipie
262
262
  if Apipie.configuration.validate_key?
263
263
  params.reject{|k,_| %w[format controller action].include?(k.to_s) }.each_pair do |param, _|
264
264
  # params allowed
265
- raise UnknownParam.new(param) if method_params.select {|_,p| p.name.to_s == param.to_s}.empty?
265
+ if method_params.select {|_,p| p.name.to_s == param.to_s}.empty?
266
+ self.class._apipie_handle_validate_key_error params, param
267
+ end
266
268
  end
267
269
  end
268
270
 
@@ -290,6 +292,15 @@ module Apipie
290
292
  end
291
293
  end
292
294
 
295
+ def _apipie_handle_validate_key_error params, param
296
+ if Apipie.configuration.action_on_non_validated_keys == :raise
297
+ raise UnknownParam, param
298
+ elsif Apipie.configuration.action_on_non_validated_keys == :skip
299
+ params.delete(param)
300
+ Rails.logger.warn(UnknownParam.new(param).to_s)
301
+ end
302
+ end
303
+
293
304
  def _apipie_save_method_params(method, params)
294
305
  @method_params ||= {}
295
306
  @method_params[method] = params
@@ -150,8 +150,8 @@ module Apipie
150
150
  end
151
151
 
152
152
  module FunctionalTestRecording
153
- def process(*args) # action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
154
- ret = super(*args)
153
+ def process(*) # action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
154
+ ret = super
155
155
  if Apipie.configuration.record
156
156
  Apipie::Extractor.call_recorder.analyze_functional_test(self)
157
157
  Apipie::Extractor.call_finished
@@ -160,6 +160,7 @@ module Apipie
160
160
  ensure
161
161
  Apipie::Extractor.clean_call_recorder
162
162
  end
163
+ ruby2_keywords :process if respond_to?(:ruby2_keywords, true)
163
164
  end
164
165
  end
165
166
  end
@@ -114,16 +114,20 @@ module Apipie
114
114
  end
115
115
 
116
116
  def validate(value)
117
- return true if @allow_nil && value.nil?
118
- return true if @allow_blank && value.blank?
117
+ return true if allow_nil && value.nil?
118
+ return true if allow_blank && value.blank?
119
119
  value = normalized_value(value)
120
- if (!@allow_nil && value.nil?) || !@validator.valid?(value)
121
- error = @validator.error
120
+ if (!allow_nil && value.nil?) || (blank_forbidden? && value.blank?) || !validator.valid?(value)
121
+ error = validator.error
122
122
  error = ParamError.new(error) unless error.is_a? StandardError
123
123
  raise error
124
124
  end
125
125
  end
126
126
 
127
+ def blank_forbidden?
128
+ !Apipie.configuration.ignore_allow_blank_false && !allow_blank && !validator.is_a?(Validator::BooleanValidator)
129
+ end
130
+
127
131
  def process_value(value)
128
132
  value = normalized_value(value)
129
133
  if @validator.respond_to?(:process_value)
@@ -9,7 +9,9 @@ module Apipie
9
9
 
10
10
  def match?(path)
11
11
  # Replace all null bytes
12
- path = ::Rack::Utils.unescape(path || '').gsub(/\x0/, '')
12
+ path = ::Rack::Utils.unescape(path || '')
13
+ .encode(Encoding::UTF_8, invalid: :replace, replace: '')
14
+ .gsub(/\x0/, '')
13
15
 
14
16
  full_path = path.empty? ? @root : File.join(@root, path)
15
17
  paths = "#{full_path}#{ext}"
@@ -74,6 +74,8 @@ module Apipie
74
74
  paths: {},
75
75
  definitions: {},
76
76
  tags: [],
77
+ securityDefinitions: Apipie.configuration.swagger_security_definitions,
78
+ security: Apipie.configuration.swagger_global_security
77
79
  }
78
80
 
79
81
  if Apipie.configuration.swagger_api_host
@@ -476,6 +478,9 @@ module Apipie
476
478
 
477
479
  if swagger_def[:type] == "array"
478
480
  swagger_def[:items] = {type: "string"}
481
+ enum = param_desc.options.fetch(:in, [])
482
+
483
+ swagger_def[:items][:enum] = enum if enum.any?
479
484
  end
480
485
 
481
486
  if swagger_def[:type] == "enum"
@@ -504,7 +509,8 @@ module Apipie
504
509
  end
505
510
 
506
511
  if !in_schema
507
- swagger_def[:in] = param_desc.options.fetch(:in, @default_value_for_param_in)
512
+ # the "name" and "in" keys can only be set on root parameters (non-nested)
513
+ swagger_def[:in] = @default_value_for_param_in if name.present?
508
514
  swagger_def[:required] = param_desc.required if param_desc.required
509
515
  end
510
516
 
@@ -3,7 +3,7 @@ module Apipie
3
3
 
4
4
  module Validator
5
5
 
6
- # to create new validator, inherit from Apipie::Validator::Base
6
+ # to create new validator, inherit from Apipie::Validator::BaseValidator
7
7
  # and implement class method build and instance method validate
8
8
  class BaseValidator
9
9
 
@@ -1,3 +1,3 @@
1
1
  module Apipie
2
- VERSION = "0.5.19"
2
+ VERSION = "0.7.2"
3
3
  end
data/lib/apipie-rails.rb CHANGED
@@ -23,7 +23,3 @@ require "apipie/railtie"
23
23
  require 'apipie/extractor'
24
24
  require "apipie/version"
25
25
  require "apipie/swagger_generator"
26
-
27
- if Rails.version.start_with?("3.0")
28
- warn 'Warning: apipie-rails is not going to support Rails 3.0 anymore in future versions'
29
- end
@@ -10,7 +10,8 @@
10
10
  "- push access to https://github.com/Apipie/apipie-rails\n",
11
11
  "- push access to rubygems.org for apipie-rails\n",
12
12
  "- sudo yum install python-slugify asciidoc\n",
13
- "- ensure neither the `git push` or `gem push` don't require interractive auth. If you can't use api key or ssh key to auth skip these steps and run them form the shell manually \n",
13
+ "- ensure neither the `git push` or `gem push` don't require interractive auth. If you can't use api key or ssh key to auth skip these steps and run them form the shell manually\n",
14
+ "- ensure all checks have passed on the branch you're about to release\n",
14
15
  "\n",
15
16
  "### Release process\n",
16
17
  "- Follow the steps with `<Shift>+<Enter>` or `<Ctrl>+<Enter>,<Down>`\n",
@@ -19,6 +20,15 @@
19
20
  "### Release settings"
20
21
  ]
21
22
  },
23
+ {
24
+ "cell_type": "code",
25
+ "execution_count": null,
26
+ "metadata": {},
27
+ "outputs": [],
28
+ "source": [
29
+ "%autosave 0"
30
+ ]
31
+ },
22
32
  {
23
33
  "cell_type": "code",
24
34
  "execution_count": null,
@@ -41,10 +51,14 @@
41
51
  "metadata": {},
42
52
  "outputs": [],
43
53
  "source": [
44
- "NEW_VERSION = '0.5.19'\n",
45
- "LAST_VERSION = '0.5.18'\n",
54
+ "NEW_VERSION = '0.5.20'\n",
55
+ "LAST_VERSION = '0.5.19'\n",
46
56
  "GIT_REMOTE_UPSTREAM = 'origin'\n",
47
- "WORK_BRANCH = 'master'\n"
57
+ "STABLE_RELEASE = False\n",
58
+ "WORK_BRANCH = 'stable' if STABLE_RELEASE else 'master'\n",
59
+ "# Array of strings, e.g. [\"21cbsc214g3\", \"21casc214g3\"]\n",
60
+ "CHERRY_PICKS = []\n",
61
+ "GEMFILE='Gemfile.rails61'"
48
62
  ]
49
63
  },
50
64
  {
@@ -85,7 +99,25 @@
85
99
  "cell_type": "markdown",
86
100
  "metadata": {},
87
101
  "source": [
88
- "### Run tests localy"
102
+ "### Cherry picks for stable release"
103
+ ]
104
+ },
105
+ {
106
+ "cell_type": "code",
107
+ "execution_count": null,
108
+ "metadata": {},
109
+ "outputs": [],
110
+ "source": [
111
+ "if STABLE_RELEASE:\n",
112
+ " for cp in CHERRY_PICKS:\n",
113
+ " ! git cherry-pick -x {cp}"
114
+ ]
115
+ },
116
+ {
117
+ "cell_type": "markdown",
118
+ "metadata": {},
119
+ "source": [
120
+ "### Run tests localy if your setup allows, otherwise ensure the HEAD is green"
89
121
  ]
90
122
  },
91
123
  {
@@ -94,7 +126,7 @@
94
126
  "metadata": {},
95
127
  "outputs": [],
96
128
  "source": [
97
- "! bundle update"
129
+ "! BUNDLE_GEMFILE=gemfiles/{GEMFILE} bundle update"
98
130
  ]
99
131
  },
100
132
  {
@@ -105,7 +137,7 @@
105
137
  },
106
138
  "outputs": [],
107
139
  "source": [
108
- "! bundle exec rake"
140
+ "! BUNDLE_GEMFILE=gemfiles/{GEMFILE} bundle exec rspec"
109
141
  ]
110
142
  },
111
143
  {
@@ -249,7 +281,7 @@
249
281
  "metadata": {},
250
282
  "outputs": [],
251
283
  "source": [
252
- "! git tag v{NEW_VERSION}"
284
+ "! git tag {NEW_VERSION}"
253
285
  ]
254
286
  },
255
287
  {
@@ -265,7 +297,7 @@
265
297
  "metadata": {},
266
298
  "outputs": [],
267
299
  "source": [
268
- "! rake build"
300
+ "! BUNDLE_GEMFILE=gemfiles/{GEMFILE} bundle exec rake build"
269
301
  ]
270
302
  },
271
303
  {
@@ -47,6 +47,31 @@ describe Apipie::ApipiesController do
47
47
 
48
48
  assert_response :not_found
49
49
  end
50
+
51
+ it "succeeds on method details with a supported language" do
52
+ allow(Apipie.configuration).to receive(:languages).and_return(%w[en es])
53
+
54
+ get :index, :params => { :version => "2.0", :resource => "architectures", :method => "index.es" }
55
+
56
+ assert_response :success
57
+ end
58
+
59
+ it "succeeds on method details with the default language" do
60
+ allow(Apipie.configuration).to receive(:default_locale).and_return("en")
61
+ allow(Apipie.configuration).to receive(:languages).and_return([])
62
+
63
+ get :index, :params => { :version => "2.0", :resource => "architectures", :method => "index.en" }
64
+
65
+ assert_response :success
66
+ end
67
+
68
+ it "returns not_found on a method with an unsupported language" do
69
+ allow(Apipie.configuration).to receive(:languages).and_return(%w[en es])
70
+
71
+ get :index, :params => { :version => "2.0", :resource => "architectures", :method => "index.jp" }
72
+
73
+ assert_response :not_found
74
+ end
50
75
  end
51
76
 
52
77
  describe "reload_controllers" do
@@ -124,6 +124,29 @@ describe UsersController do
124
124
  end
125
125
  end
126
126
 
127
+ context "key validations are enabled and skip on non-validated keys" do
128
+ before do
129
+ Apipie.configuration.validate_value = false
130
+ Apipie.configuration.validate_presence = true
131
+ Apipie.configuration.validate_key = true
132
+ Apipie.configuration.action_on_non_validated_keys = :skip
133
+ end
134
+
135
+ it "should reply to valid request" do
136
+ expect { get :show, :params => { :id => 5, :session => 'secret_hash' }}.not_to raise_error
137
+ assert_response :success
138
+ end
139
+
140
+ it "should delete the param and not fail if an extra parameter is passed." do
141
+ expect { get :show, :params => { :id => 5 , :badparam => 'badfoo', :session => "secret_hash" }}.not_to raise_error
142
+ expect(controller.params.as_json).to eq({"session"=>"secret_hash", "id"=>"5", "controller"=>"users", "action"=>"show"})
143
+ end
144
+
145
+ after do
146
+ Apipie.configuration.action_on_non_validated_keys = :raise
147
+ end
148
+ end
149
+
127
150
  context "presence and value validations are enabled" do
128
151
  before do
129
152
  Apipie.configuration.validate_value = true
@@ -274,6 +274,12 @@ class UsersController < ApplicationController
274
274
  render :plain => 'nothing to see here'
275
275
  end
276
276
 
277
+ api :GET, '/users/in_departments', 'show users from specific departments'
278
+ param :departments, Array, in: ["finance", "operations", "sales", "marketing", "HR"], default_value: ['sales']
279
+ def get_in_departments
280
+ render :plain => 'nothing to see here'
281
+ end
282
+
277
283
  api :GET, '/users/desc_from_file', 'desc from file'
278
284
  document 'users/desc_from_file.md'
279
285
  def desc_from_file
@@ -1,10 +1,7 @@
1
1
  require File.expand_path('../boot', __FILE__)
2
2
 
3
- require "active_model/railtie"
4
- require "active_record/railtie"
5
3
  require "action_controller/railtie"
6
4
  require "action_view/railtie"
7
- require "action_mailer/railtie"
8
5
 
9
6
  Bundler.require
10
7
  require "apipie-rails"
@@ -13,9 +13,6 @@ Dummy::Application.configure do
13
13
  config.consider_all_requests_local = true
14
14
  config.action_controller.perform_caching = false
15
15
 
16
- # Don't care if the mailer can't send
17
- config.action_mailer.raise_delivery_errors = false
18
-
19
16
  # Print deprecation notices to the Rails logger
20
17
  config.active_support.deprecation = :log
21
18
 
@@ -34,9 +34,6 @@ Dummy::Application.configure do
34
34
  # Enable serving of images, stylesheets, and javascripts from an asset server
35
35
  # config.action_controller.asset_host = "http://assets.example.com"
36
36
 
37
- # Disable delivery errors, bad email addresses will be ignored
38
- # config.action_mailer.raise_delivery_errors = false
39
-
40
37
  # Enable threaded mode
41
38
  # config.threadsafe!
42
39
 
@@ -20,11 +20,6 @@ Dummy::Application.configure do
20
20
  # Disable request forgery protection in test environment
21
21
  config.action_controller.allow_forgery_protection = false
22
22
 
23
- # Tell Action Mailer not to deliver emails to the real world.
24
- # The :test delivery method accumulates sent emails in the
25
- # ActionMailer::Base.deliveries array.
26
- config.action_mailer.delivery_method = :test
27
-
28
23
  # Use SQL instead of Active Record's schema dumper when creating the test database.
29
24
  # This is necessary if your schema can't be completely dumped by the schema dumper,
30
25
  # like if you have constraints or database-specific column types
@@ -14,5 +14,12 @@ describe Apipie::FileHandler do
14
14
  it { expect(file_handler.match? path).to be_falsy }
15
15
  it { expect { file_handler.match? path }.to_not raise_error }
16
16
  end
17
+
18
+ context 'when the path contans an invalid byte sequence in UTF-8' do
19
+ let(:path) { "%B6" }
20
+
21
+ it { expect(file_handler.match? path).to be_falsy }
22
+ it { expect { file_handler.match? path }.to_not raise_error }
23
+ end
17
24
  end
18
25
  end
@@ -113,6 +113,74 @@ describe Apipie::ParamDescription do
113
113
 
114
114
  end
115
115
 
116
+ describe 'validate' do
117
+ context 'when allow_blank is ignored, as it was before 0.7.0' do
118
+ before do
119
+ Apipie.configuration.ignore_allow_blank_false = true
120
+ end
121
+
122
+ context 'when the parameter is a boolean' do
123
+ it "should not throw an exception when passed false" do
124
+ expect { Apipie::ParamDescription.new(method_desc, :param, :boolean).validate(false) }.to_not raise_error
125
+ end
126
+
127
+ it "should throw an exception when passed an empty value" do
128
+ expect { Apipie::ParamDescription.new(method_desc, :param, :boolean).validate('') }.to raise_error(Apipie::ParamInvalid)
129
+ end
130
+ end
131
+
132
+ context 'when the parameter is a string' do
133
+ context 'when allow_blank is specified as true' do
134
+ it "should throw an exception when passed an empty value" do
135
+ expect { Apipie::ParamDescription.new(method_desc, :param, String, allow_blank: true).validate('') }.to_not raise_error
136
+ end
137
+ end
138
+ context 'when allow_blank is specified as false' do
139
+ it "should throw an exception when passed an empty value" do
140
+ expect { Apipie::ParamDescription.new(method_desc, :param, String, allow_blank: false).validate('') }.to_not raise_error
141
+ end
142
+ end
143
+ context 'when allow_blank is not specified' do
144
+ it "should throw an exception when passed an empty value" do
145
+ expect { Apipie::ParamDescription.new(method_desc, :param, String).validate('') }.to_not raise_error
146
+ end
147
+ end
148
+ end
149
+
150
+ after do
151
+ Apipie.configuration.ignore_allow_blank_false = false
152
+ end
153
+ end
154
+
155
+ context 'when the parameter is a boolean' do
156
+ it "should not throw an exception when passed false" do
157
+ expect { Apipie::ParamDescription.new(method_desc, :param, :boolean).validate(false) }.to_not raise_error
158
+ end
159
+
160
+ it "should throw an exception when passed an empty value" do
161
+ expect { Apipie::ParamDescription.new(method_desc, :param, :boolean).validate('') }.to raise_error(Apipie::ParamInvalid)
162
+ end
163
+ end
164
+
165
+ context 'when the parameter is a string' do
166
+ context 'when allow_blank is specified as true' do
167
+ it "should throw an exception when passed an empty value" do
168
+ expect { Apipie::ParamDescription.new(method_desc, :param, String, allow_blank: true).validate('') }.to_not raise_error
169
+ end
170
+ end
171
+ context 'when allow_blank is specified as false' do
172
+ it "should throw an exception when passed an empty value" do
173
+ expect { Apipie::ParamDescription.new(method_desc, :param, String, allow_blank: false).validate('') }.to raise_error(Apipie::ParamInvalid)
174
+ end
175
+ end
176
+ context 'when allow_blank is not specified' do
177
+ it "should throw an exception when passed an empty value" do
178
+ expect { Apipie::ParamDescription.new(method_desc, :param, String).validate('') }.to raise_error(Apipie::ParamInvalid)
179
+ end
180
+ end
181
+ end
182
+ end
183
+
116
184
  describe "concern substitution" do
117
185
 
118
186
  let(:concern_dsl_data) { dsl_data.merge(:from_concern => true) }
@@ -51,6 +51,17 @@ describe 'rake tasks' do
51
51
  expect(param[field]).to eq(value)
52
52
  end
53
53
 
54
+ def expect_array_param_def(http_method, path, param_name, value)
55
+ params = apidoc_swagger["paths"][path][http_method]["parameters"]
56
+ param = params.select { |p| p if p["name"] == param_name }[0]
57
+
58
+ expect(param['type']).to eq('array')
59
+ expect(param['items']).to eq(
60
+ 'type' => 'string',
61
+ 'enum' => value
62
+ )
63
+ end
64
+
54
65
  def expect_tags_def(http_method, path, value)
55
66
  params = apidoc_swagger["paths"][path][http_method]["tags"]
56
67
  expect(params).to eq(value)
@@ -119,6 +130,10 @@ describe 'rake tasks' do
119
130
  expect_param_def("get", "/users/by_department", "department", "enum",
120
131
  ["finance", "operations", "sales", "marketing", "HR"])
121
132
 
133
+ expect_param_def("get", "/users/in_departments", "departments", "in", "query")
134
+ expect_array_param_def("get", "/users/in_departments", "departments",
135
+ ["finance", "operations", "sales", "marketing", "HR"])
136
+
122
137
  expect_tags_def("get", "/twitter_example/{id}/followers", %w[twitter_example following index search])
123
138
 
124
139
  end