apipierails3 0.0.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 (171) hide show
  1. checksums.yaml +17 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +27 -0
  5. data/APACHE-LICENSE-2.0 +202 -0
  6. data/CHANGELOG.md +469 -0
  7. data/Gemfile +1 -0
  8. data/Gemfile.rails32 +6 -0
  9. data/Gemfile.rails41 +6 -0
  10. data/Gemfile.rails42 +11 -0
  11. data/Gemfile.rails50 +6 -0
  12. data/Gemfile.rails51 +7 -0
  13. data/MIT-LICENSE +20 -0
  14. data/NOTICE +4 -0
  15. data/PROPOSAL_FOR_RESPONSE_DESCRIPTIONS.md +244 -0
  16. data/README.rst +1874 -0
  17. data/Rakefile +13 -0
  18. data/apipierails3.gemspec +27 -0
  19. data/app/controllers/apipie/apipies_controller.rb +199 -0
  20. data/app/helpers/apipie_helper.rb +10 -0
  21. data/app/public/apipie/javascripts/apipie.js +6 -0
  22. data/app/public/apipie/javascripts/bundled/bootstrap-collapse.js +138 -0
  23. data/app/public/apipie/javascripts/bundled/bootstrap.js +1726 -0
  24. data/app/public/apipie/javascripts/bundled/jquery.js +5 -0
  25. data/app/public/apipie/javascripts/bundled/prettify.js +28 -0
  26. data/app/public/apipie/stylesheets/application.css +7 -0
  27. data/app/public/apipie/stylesheets/bundled/bootstrap-responsive.min.css +12 -0
  28. data/app/public/apipie/stylesheets/bundled/bootstrap.min.css +689 -0
  29. data/app/public/apipie/stylesheets/bundled/prettify.css +30 -0
  30. data/app/views/apipie/apipies/_disqus.html.erb +13 -0
  31. data/app/views/apipie/apipies/_errors.html.erb +23 -0
  32. data/app/views/apipie/apipies/_headers.html.erb +26 -0
  33. data/app/views/apipie/apipies/_languages.erb +6 -0
  34. data/app/views/apipie/apipies/_metadata.erb +1 -0
  35. data/app/views/apipie/apipies/_method_detail.erb +61 -0
  36. data/app/views/apipie/apipies/_params.html.erb +42 -0
  37. data/app/views/apipie/apipies/_params_plain.html.erb +20 -0
  38. data/app/views/apipie/apipies/apipie_404.html.erb +17 -0
  39. data/app/views/apipie/apipies/apipie_checksum.json.erb +1 -0
  40. data/app/views/apipie/apipies/getting_started.html.erb +6 -0
  41. data/app/views/apipie/apipies/index.html.erb +56 -0
  42. data/app/views/apipie/apipies/method.html.erb +41 -0
  43. data/app/views/apipie/apipies/plain.html.erb +77 -0
  44. data/app/views/apipie/apipies/resource.html.erb +80 -0
  45. data/app/views/apipie/apipies/static.html.erb +103 -0
  46. data/app/views/layouts/apipie/apipie.html.erb +27 -0
  47. data/config/locales/de.yml +28 -0
  48. data/config/locales/en.yml +32 -0
  49. data/config/locales/es.yml +28 -0
  50. data/config/locales/fr.yml +31 -0
  51. data/config/locales/it.yml +31 -0
  52. data/config/locales/ja.yml +31 -0
  53. data/config/locales/pl.yml +28 -0
  54. data/config/locales/pt-BR.yml +28 -0
  55. data/config/locales/ru.yml +28 -0
  56. data/config/locales/tr.yml +28 -0
  57. data/config/locales/zh-CN.yml +28 -0
  58. data/config/locales/zh-TW.yml +28 -0
  59. data/images/screenshot-1.png +0 -0
  60. data/images/screenshot-2.png +0 -0
  61. data/lib/apipie/apipie_module.rb +83 -0
  62. data/lib/apipie/application.rb +462 -0
  63. data/lib/apipie/configuration.rb +186 -0
  64. data/lib/apipie/dsl_definition.rb +607 -0
  65. data/lib/apipie/error_description.rb +44 -0
  66. data/lib/apipie/errors.rb +86 -0
  67. data/lib/apipie/extractor.rb +177 -0
  68. data/lib/apipie/extractor/collector.rb +117 -0
  69. data/lib/apipie/extractor/recorder.rb +166 -0
  70. data/lib/apipie/extractor/writer.rb +454 -0
  71. data/lib/apipie/helpers.rb +73 -0
  72. data/lib/apipie/markup.rb +48 -0
  73. data/lib/apipie/method_description.rb +273 -0
  74. data/lib/apipie/middleware/checksum_in_headers.rb +35 -0
  75. data/lib/apipie/param_description.rb +280 -0
  76. data/lib/apipie/railtie.rb +9 -0
  77. data/lib/apipie/resource_description.rb +124 -0
  78. data/lib/apipie/response_description.rb +131 -0
  79. data/lib/apipie/response_description_adapter.rb +200 -0
  80. data/lib/apipie/routes_formatter.rb +33 -0
  81. data/lib/apipie/routing.rb +16 -0
  82. data/lib/apipie/rspec/response_validation_helper.rb +192 -0
  83. data/lib/apipie/see_description.rb +39 -0
  84. data/lib/apipie/static_dispatcher.rb +69 -0
  85. data/lib/apipie/swagger_generator.rb +707 -0
  86. data/lib/apipie/tag_list_description.rb +11 -0
  87. data/lib/apipie/validator.rb +526 -0
  88. data/lib/apipie/version.rb +3 -0
  89. data/lib/apipierails3.rb +25 -0
  90. data/lib/generators/apipie/install/README +6 -0
  91. data/lib/generators/apipie/install/install_generator.rb +25 -0
  92. data/lib/generators/apipie/install/templates/initializer.rb.erb +7 -0
  93. data/lib/generators/apipie/views_generator.rb +11 -0
  94. data/lib/tasks/apipie.rake +345 -0
  95. data/rel-eng/packages/.readme +3 -0
  96. data/rel-eng/packages/rubygem-apipie-rails +1 -0
  97. data/rel-eng/tito.props +5 -0
  98. data/spec/controllers/api/v1/architectures_controller_spec.rb +29 -0
  99. data/spec/controllers/api/v2/architectures_controller_spec.rb +12 -0
  100. data/spec/controllers/api/v2/nested/resources_controller_spec.rb +11 -0
  101. data/spec/controllers/apipies_controller_spec.rb +273 -0
  102. data/spec/controllers/concerns_controller_spec.rb +42 -0
  103. data/spec/controllers/extended_controller_spec.rb +11 -0
  104. data/spec/controllers/users_controller_spec.rb +740 -0
  105. data/spec/dummy/Rakefile +7 -0
  106. data/spec/dummy/app/controllers/api/base_controller.rb +4 -0
  107. data/spec/dummy/app/controllers/api/v1/architectures_controller.rb +43 -0
  108. data/spec/dummy/app/controllers/api/v1/base_controller.rb +11 -0
  109. data/spec/dummy/app/controllers/api/v2/architectures_controller.rb +30 -0
  110. data/spec/dummy/app/controllers/api/v2/base_controller.rb +11 -0
  111. data/spec/dummy/app/controllers/api/v2/nested/architectures_controller.rb +32 -0
  112. data/spec/dummy/app/controllers/api/v2/nested/resources_controller.rb +33 -0
  113. data/spec/dummy/app/controllers/application_controller.rb +18 -0
  114. data/spec/dummy/app/controllers/concerns/extending_concern.rb +11 -0
  115. data/spec/dummy/app/controllers/concerns/sample_controller.rb +41 -0
  116. data/spec/dummy/app/controllers/concerns_controller.rb +8 -0
  117. data/spec/dummy/app/controllers/extended_controller.rb +14 -0
  118. data/spec/dummy/app/controllers/files_controller.rb +5 -0
  119. data/spec/dummy/app/controllers/overridden_concerns_controller.rb +31 -0
  120. data/spec/dummy/app/controllers/pets_controller.rb +408 -0
  121. data/spec/dummy/app/controllers/pets_using_auto_views_controller.rb +73 -0
  122. data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +95 -0
  123. data/spec/dummy/app/controllers/tagged_cats_controller.rb +32 -0
  124. data/spec/dummy/app/controllers/tagged_dogs_controller.rb +15 -0
  125. data/spec/dummy/app/controllers/twitter_example_controller.rb +307 -0
  126. data/spec/dummy/app/controllers/users_controller.rb +297 -0
  127. data/spec/dummy/app/views/layouts/application.html.erb +21 -0
  128. data/spec/dummy/config.ru +4 -0
  129. data/spec/dummy/config/application.rb +49 -0
  130. data/spec/dummy/config/boot.rb +10 -0
  131. data/spec/dummy/config/database.yml +21 -0
  132. data/spec/dummy/config/environment.rb +8 -0
  133. data/spec/dummy/config/environments/development.rb +28 -0
  134. data/spec/dummy/config/environments/production.rb +52 -0
  135. data/spec/dummy/config/environments/test.rb +38 -0
  136. data/spec/dummy/config/initializers/apipie.rb +110 -0
  137. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  138. data/spec/dummy/config/initializers/inflections.rb +10 -0
  139. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  140. data/spec/dummy/config/initializers/secret_token.rb +8 -0
  141. data/spec/dummy/config/initializers/session_store.rb +8 -0
  142. data/spec/dummy/config/locales/en.yml +5 -0
  143. data/spec/dummy/config/routes.rb +51 -0
  144. data/spec/dummy/db/.gitkeep +0 -0
  145. data/spec/dummy/doc/apipie_examples.json +1 -0
  146. data/spec/dummy/doc/users/desc_from_file.md +1 -0
  147. data/spec/dummy/public/404.html +26 -0
  148. data/spec/dummy/public/422.html +26 -0
  149. data/spec/dummy/public/500.html +26 -0
  150. data/spec/dummy/public/favicon.ico +0 -0
  151. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  152. data/spec/dummy/script/rails +6 -0
  153. data/spec/lib/application_spec.rb +49 -0
  154. data/spec/lib/extractor/extractor_spec.rb +9 -0
  155. data/spec/lib/extractor/middleware_spec.rb +44 -0
  156. data/spec/lib/extractor/writer_spec.rb +110 -0
  157. data/spec/lib/file_handler_spec.rb +18 -0
  158. data/spec/lib/method_description_spec.rb +98 -0
  159. data/spec/lib/param_description_spec.rb +345 -0
  160. data/spec/lib/param_group_spec.rb +60 -0
  161. data/spec/lib/rake_spec.rb +71 -0
  162. data/spec/lib/resource_description_spec.rb +48 -0
  163. data/spec/lib/swagger/openapi_2_0_schema.json +1607 -0
  164. data/spec/lib/swagger/rake_swagger_spec.rb +139 -0
  165. data/spec/lib/swagger/response_validation_spec.rb +104 -0
  166. data/spec/lib/swagger/swagger_dsl_spec.rb +658 -0
  167. data/spec/lib/validator_spec.rb +113 -0
  168. data/spec/lib/validators/array_validator_spec.rb +85 -0
  169. data/spec/spec_helper.rb +109 -0
  170. data/spec/support/rake.rb +21 -0
  171. metadata +415 -0
@@ -0,0 +1,9 @@
1
+ require "spec_helper"
2
+
3
+ describe Apipie::Extractor do
4
+ it 'handles routes without (.:format)' do
5
+ Apipie::Extractor.apis_from_routes.each do |(controller, action), apis|
6
+ apis.each { |api| expect(api[:path]).not_to be_nil }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,44 @@
1
+ require "spec_helper"
2
+
3
+ describe Apipie::Extractor::Recorder::Middleware do
4
+ let(:app) { lambda { |env| [200, env, "app"] } }
5
+ let(:stack) { Apipie::Extractor::Recorder::Middleware.new(app) }
6
+ let(:request) { Rack::MockRequest.new(stack) }
7
+ let(:response) { request.get('/') }
8
+
9
+ it 'correctly process request without recording' do
10
+ expect(stack).not_to receive(:analyze)
11
+ response
12
+ end
13
+
14
+ it "analyze request if recording is set" do
15
+ Apipie.configuration.record = true
16
+ expect(Apipie::Extractor.call_recorder).to receive(:analyse_env)
17
+ expect(Apipie::Extractor.call_recorder).to receive(:analyse_response)
18
+ expect(Apipie::Extractor).to receive(:clean_call_recorder)
19
+ response
20
+ end
21
+
22
+ describe 'with a multipart post' do
23
+ let(:form_hash) do
24
+ {
25
+ 'stringbody' => 'this is a string body',
26
+ 'filebody' => {:head => 'X-Fake-Header: fake1\r\n'},
27
+ 'files' => {
28
+ '0' => {:head => 'X-Fake-Header: fake2\r\n'}
29
+ }
30
+ }
31
+ end
32
+
33
+ let(:response) do
34
+ request.post('/', 'rack.request.form_hash' => form_hash)
35
+ end
36
+
37
+ it 'reformats form parts' do
38
+ Apipie.configuration.record = true
39
+ # expect reformat_multipart_data to invoke content_disposition
40
+ expect(Apipie::Extractor.call_recorder).to receive(:content_disposition)
41
+ response
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,110 @@
1
+ require "spec_helper"
2
+
3
+ describe Apipie::Extractor::Writer do
4
+
5
+ let(:collector) { double "collector" }
6
+ let(:writer_class) { Apipie::Extractor::Writer }
7
+ let(:writer) { writer_class.new(collector) }
8
+ let(:test_examples_file) { File.join(Rails.root, "doc", "apipie_examples_test.json") }
9
+ let(:records) { {
10
+ "concern_resources#show" =>
11
+ [{
12
+ :controller=>ConcernsController,
13
+ :action=>"show",
14
+ :verb=>:GET,
15
+ :path=>"/api/concerns/5",
16
+ :params=>{},
17
+ :query=>"session=secret_hash",
18
+ :request_data=>nil,
19
+ :response_data=>"OK {\"session\"=>\"secret_hash\", \"id\"=>\"5\", \"controller\"=>\"concerns\", \"action\"=>\"show\"}",
20
+ :code=>"200"
21
+ }, {
22
+ :controller=>ConcernsController,
23
+ :action=>"show",
24
+ :verb=>:GET,
25
+ :path=>"/api/concerns/5",
26
+ :params=>{},
27
+ :query=>"",
28
+ :request_data=>nil,
29
+ :response_data=>"OK {\"id\"=>\"5\", \"controller\"=>\"concerns\", \"action\"=>\"show\"}",
30
+ :code=>"200"
31
+ }]
32
+ }
33
+ }
34
+ let(:loaded_records) { {
35
+ "concern_resources#show" =>
36
+ [{
37
+ "verb"=>:GET,
38
+ "path"=>"/api/concerns/5",
39
+ "versions"=>["development"],
40
+ "query"=>"session=secret_hash",
41
+ "request_data"=>nil,
42
+ "response_data"=>"OK {\"session\"=>\"secret_hash\", \"id\"=>\"5\", \"controller\"=>\"concerns\", \"action\"=>\"show\"}",
43
+ "code"=>"200",
44
+ "show_in_doc"=>1,
45
+ "recorded"=>true
46
+ }, {
47
+ "verb"=>:GET,
48
+ "path"=>"/api/concerns/5",
49
+ "versions"=>["development"],
50
+ "query"=>"",
51
+ "request_data"=>nil,
52
+ "response_data"=>"OK {\"id\"=>\"5\", \"controller\"=>\"concerns\", \"action\"=>\"show\"}",
53
+ "code"=>"200",
54
+ "show_in_doc"=>0,
55
+ "recorded"=>true
56
+ }]
57
+ }
58
+ }
59
+
60
+ context 'with doc_path overriden in configuration' do
61
+ around(:each) do |example|
62
+ standard_path = Apipie.configuration.doc_path
63
+ Apipie.configuration.doc_path = 'user_specified_doc_path'
64
+ example.run
65
+ Apipie.configuration.doc_path = standard_path
66
+ end
67
+
68
+ it 'should use the doc_path specified in configuration' do
69
+ expect(writer_class.examples_file).to eql(File.join(Rails.root, 'user_specified_doc_path', 'apipie_examples.json'))
70
+ end
71
+ end
72
+
73
+ context 'when compressing examples' do
74
+ around(:each) do |example|
75
+ Apipie.configuration.compress_examples = true
76
+ example.run
77
+ FileUtils.rm(writer_class.examples_file) if File.exist?(writer_class.examples_file)
78
+ Apipie.configuration.compress_examples = nil
79
+ end
80
+
81
+ it 'should write to a compressed file' do
82
+ expect(writer_class.examples_file).to match(/\.gz$/)
83
+ writer_class.write_recorded_examples(records)
84
+ expect(File.exist?(writer_class.examples_file))
85
+ end
86
+
87
+ it 'should read from a compressed file' do
88
+ writer_class.write_recorded_examples(records)
89
+ expected_string = writer_class.send(:serialize_examples, records)
90
+ expect(writer_class.load_recorded_examples)
91
+ .to eql(writer_class.send(:deserialize_examples, expected_string))
92
+ end
93
+ end
94
+
95
+ describe "storing of examples" do
96
+ before do
97
+ allow(writer_class).to receive(:examples_file) { test_examples_file }
98
+ expect(collector).to receive(:records).and_return(records)
99
+ end
100
+
101
+ it "should read and write examples" do
102
+ writer.write_examples
103
+ expect(writer.send(:load_recorded_examples)).to eql(loaded_records)
104
+ end
105
+
106
+ after do
107
+ File.unlink(test_examples_file) if File.exists?(test_examples_file)
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe Apipie::FileHandler do
4
+
5
+ describe "match?" do
6
+ let(:file_handler) { Apipie::FileHandler.new File.dirname(__FILE__) }
7
+
8
+ it { expect(file_handler.match? 'file_handler_spec.rb').to be_truthy }
9
+ it { expect(file_handler.match? 'foo.bar').to be_falsy }
10
+
11
+ context 'path contains null bytes' do
12
+ let(:path) { "foo%00.bar" }
13
+
14
+ it { expect(file_handler.match? path).to be_falsy }
15
+ it { expect { file_handler.match? path }.to_not raise_error }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,98 @@
1
+ require "spec_helper"
2
+
3
+ describe Apipie::MethodDescription do
4
+
5
+ let(:dsl_data) { ActionController::Base.send(:_apipie_dsl_data_init) }
6
+
7
+ describe "metadata" do
8
+
9
+ before(:each) do
10
+ @resource = Apipie::ResourceDescription.new(ApplicationController, "dummy")
11
+ end
12
+
13
+ it "should return nil when no metadata is provided" do
14
+ method = Apipie::MethodDescription.new(:a, @resource, dsl_data)
15
+ expect(method.to_json[:metadata]).to eq(nil)
16
+ end
17
+
18
+ it "should return the metadata" do
19
+ meta = {
20
+ :lenght => 32,
21
+ :weight => '830g'
22
+ }
23
+ method = Apipie::MethodDescription.new(:a, @resource, dsl_data.update(:meta => meta))
24
+ expect(method.to_json[:metadata]).to eq(meta)
25
+ end
26
+
27
+ end
28
+
29
+ describe "deprecated flag" do
30
+ before(:each) do
31
+ @resource = Apipie::ResourceDescription.new(ApplicationController, "dummy")
32
+ end
33
+
34
+ it "should return the deprecated flag when provided" do
35
+ dsl_data[:api_args] = [[:GET, "/foo/bar", "description", {:deprecated => true}]]
36
+ method = Apipie::MethodDescription.new(:a, @resource, dsl_data)
37
+ expect(method.method_apis_to_json.first[:deprecated]).to eq(true)
38
+ end
39
+
40
+ it "should return the deprecated flag if resource is deprecated" do
41
+ @resource.instance_variable_set("@_deprecated", true)
42
+ dsl_data[:api_args] = [[:GET, "/foo/bar", "description", {}]]
43
+ method = Apipie::MethodDescription.new(:a, @resource, dsl_data)
44
+ expect(method.method_apis_to_json.first[:deprecated]).to eq(true)
45
+ end
46
+ end
47
+
48
+ describe "params descriptions" do
49
+
50
+ before(:each) do
51
+ @resource = Apipie::ResourceDescription.new(ApplicationController, "dummy")
52
+ dsl_data[:params] = [[:a, String, nil, {}, nil],
53
+ [:b, String, nil, {}, nil],
54
+ [:c, String, nil, {}, nil]]
55
+ @method = Apipie::MethodDescription.new(:a, @resource, dsl_data)
56
+ @resource.add_method_description @method
57
+ end
58
+
59
+ it "should be ordered" do
60
+ expect(@method.params.keys).to eq([:a, :b, :c])
61
+ expect(@method.to_json[:params].map{|h| h[:name]}).to eq(['a', 'b', 'c'])
62
+ end
63
+
64
+ it "should be still ordered" do
65
+ expect(@method.params.keys).to eq([:a, :b, :c])
66
+ expect(@method.to_json[:params].map{|h| h[:name]}).to eq(['a', 'b', 'c'])
67
+ end
68
+
69
+ end
70
+
71
+ describe "response-only properties" do
72
+ before(:each) do
73
+ @resource = Apipie::ResourceDescription.new(ApplicationController, "dummy")
74
+ dsl_data[:params] = [[:a, String, nil, {:only_in => :request}, nil],
75
+ [:b, String, nil, {:only_in => :response}, nil],
76
+ [:c, String, nil, {}, nil]]
77
+ @method = Apipie::MethodDescription.new(:a, @resource, dsl_data)
78
+ @resource.add_method_description @method
79
+ end
80
+
81
+ it "should ignore response-only parameters" do
82
+ expect(@method.params.keys).to eq([:a, :c])
83
+ expect(@method.to_json[:params].map{|h| h[:name]}).to eq(['a', 'c'])
84
+ end
85
+ end
86
+
87
+
88
+ describe "'returns' properties" do
89
+ it "should raise an error if both :param_group and :array_of are specified in 'returns'" do
90
+ @resource = Apipie::ResourceDescription.new(ApplicationController, "dummy")
91
+ dsl_data[:returns] = { 200 => [{:param_group => 'pet', :array_of => 'pet'}, nil, nil] }
92
+
93
+ expect {Apipie::MethodDescription.new(:a, @resource, dsl_data)}.to raise_error(Apipie::ReturnsMultipleDefinitionError)
94
+ end
95
+ end
96
+
97
+
98
+ end
@@ -0,0 +1,345 @@
1
+ require "spec_helper"
2
+
3
+ describe Apipie::ParamDescription do
4
+
5
+ let(:dsl_data) { ActionController::Base.send(:_apipie_dsl_data_init) }
6
+
7
+ let(:resource_desc) do
8
+ Apipie::ResourceDescription.new(UsersController, "users")
9
+ end
10
+
11
+ let(:method_desc) do
12
+ Apipie::MethodDescription.new(:show, resource_desc, dsl_data)
13
+ end
14
+
15
+ describe "metadata" do
16
+
17
+ it "should return nil when no metadata is provided" do
18
+ param = Apipie::ParamDescription.new(method_desc, :some_param, String)
19
+ expect(param.to_json[:metadata]).to eq(nil)
20
+ end
21
+
22
+ it "should return the metadata" do
23
+ meta = {
24
+ :lenght => 32,
25
+ :weight => '830g'
26
+ }
27
+ param = Apipie::ParamDescription.new(method_desc, :some_param, String, :meta => meta)
28
+ expect(param.to_json[:metadata]).to eq(meta)
29
+ end
30
+
31
+ end
32
+
33
+ describe "show option" do
34
+
35
+ it "should return true when show option is not provided" do
36
+ param = Apipie::ParamDescription.new(method_desc, :some_param, String)
37
+ expect(param.to_json[:show]).to eq(true)
38
+ end
39
+
40
+ it "should return the show option" do
41
+ param = Apipie::ParamDescription.new(method_desc, :some_param, String, :show => true)
42
+ expect(param.to_json[:show]).to eq(true)
43
+
44
+ param = Apipie::ParamDescription.new(method_desc, :some_param, String, :show => false)
45
+ expect(param.to_json[:show]).to eq(false)
46
+ end
47
+
48
+ end
49
+
50
+ describe "full_name" do
51
+ context "with no nested parameters" do
52
+
53
+ it "should return name" do
54
+ param = Apipie::ParamDescription.new(method_desc, :some_param, String)
55
+ expect(param.to_json[:full_name]).to eq('some_param')
56
+ end
57
+
58
+ end
59
+
60
+ context "with nested parameters" do
61
+
62
+ it "should return the parameter's name nested in the parents name" do
63
+ parent_param = Apipie::ParamDescription.new(method_desc, :parent, String)
64
+ nested_param = Apipie::ParamDescription.new(method_desc, :nested, String, :parent => parent_param)
65
+
66
+ expect(nested_param.to_json[:full_name]).to eq('parent[nested]')
67
+ end
68
+
69
+ context "with the parent parameter set to not show" do
70
+
71
+ it "should return just the parameter's name" do
72
+ parent_param = Apipie::ParamDescription.new(method_desc, :parent, String, :show => false)
73
+ nested_param = Apipie::ParamDescription.new(method_desc, :nested, String, :parent => parent_param)
74
+
75
+ expect(nested_param.to_json[:full_name]).to eq('nested')
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "manual validation text" do
83
+ it "should allow manual text" do
84
+ param = Apipie::ParamDescription.new(method_desc, :hidden_param, nil, :validations => "must be foo")
85
+
86
+ expect(param.validations).to include("\n<p>must be foo</p>\n")
87
+ end
88
+
89
+ it "should allow multiple items" do
90
+ param = Apipie::ParamDescription.new(method_desc, :hidden_param, nil, :validations => ["> 0", "< 5"])
91
+
92
+ expect(param.validations).to include("\n<p>&gt; 0</p>\n")
93
+ expect(param.validations).to include("\n<p>&lt; 5</p>\n")
94
+ end
95
+ end
96
+
97
+ describe "validator selection" do
98
+
99
+ it "should allow nil validator" do
100
+ param = Apipie::ParamDescription.new(method_desc, :hidden_param, nil)
101
+ expect(param.validator).to be_nil
102
+ end
103
+
104
+ it "should throw exception on unknown validator" do
105
+ expect { Apipie::ParamDescription.new(method_desc, :param, :unknown) }.to raise_error(RuntimeError, /Validator.*not found/)
106
+ end
107
+
108
+ it "should pick type validator" do
109
+ expect(Apipie::Validator::BaseValidator).to receive(:find).and_return(:validator_instance)
110
+ param = Apipie::ParamDescription.new(method_desc, :param, String)
111
+ expect(param.validator).to eq(:validator_instance)
112
+ end
113
+
114
+ end
115
+
116
+ describe "concern substitution" do
117
+
118
+ let(:concern_dsl_data) { dsl_data.merge(:from_concern => true) }
119
+
120
+ let(:concern_resource_desc) do
121
+ Apipie::ResourceDescription.new(ConcernsController, "concerns")
122
+ end
123
+
124
+ let(:concern_method_desc) do
125
+ Apipie::MethodDescription.new(:show, concern_resource_desc, concern_dsl_data)
126
+ end
127
+
128
+ it "should replace string parameter name with colon prefix" do
129
+ param = Apipie::ParamDescription.new(concern_method_desc, ":string_subst", String)
130
+ expect(param.name).to eq("string")
131
+ end
132
+
133
+ it "should replace symbol parameter name" do
134
+ param = Apipie::ParamDescription.new(concern_method_desc, :concern, String)
135
+ expect(param.name).to eq(:user)
136
+ end
137
+
138
+ it "should keep original value for strings without colon prefixes" do
139
+ param = Apipie::ParamDescription.new(concern_method_desc, "string_subst", String)
140
+ expect(param.name).to eq("string_subst")
141
+ end
142
+
143
+ it "should keep the original value when a string can't be replaced" do
144
+ param = Apipie::ParamDescription.new(concern_method_desc, ":param", String)
145
+ expect(param.name).to eq(":param")
146
+ end
147
+
148
+ it "should keep the original value when a symbol can't be replaced" do
149
+ param = Apipie::ParamDescription.new(concern_method_desc, :param, String)
150
+ expect(param.name).to eq(:param)
151
+ end
152
+ end
153
+
154
+
155
+ describe "required_by_default config option" do
156
+ context "parameters required by default" do
157
+
158
+ before { Apipie.configuration.required_by_default = true }
159
+
160
+ it "should set param as required by default" do
161
+ param = Apipie::ParamDescription.new(method_desc, :required_by_default, String)
162
+ expect(param.required).to be true
163
+ end
164
+
165
+ it "should be possible to set param as optional" do
166
+ param = Apipie::ParamDescription.new(method_desc, :optional, String, :required => false)
167
+ expect(param.required).to be false
168
+ end
169
+
170
+ end
171
+
172
+ context "parameters optional by default" do
173
+
174
+ before { Apipie.configuration.required_by_default = false }
175
+
176
+ it "should set param as optional by default" do
177
+ param = Apipie::ParamDescription.new(method_desc, :optional_by_default, String)
178
+ expect(param.required).to be false
179
+ end
180
+
181
+ it "should be possible to set param as required" do
182
+ param = Apipie::ParamDescription.new(method_desc, :required, String, 'description','required' => true)
183
+ expect(param.required).to be true
184
+ end
185
+
186
+ end
187
+
188
+ end
189
+
190
+ describe "required params on given actions" do
191
+ let(:method_desc) do
192
+ Apipie::MethodDescription.new(:create, resource_desc, dsl_data)
193
+ end
194
+
195
+ context "when the param is required for current action" do
196
+ it "should set param as required" do
197
+ param = Apipie::ParamDescription.new(method_desc, :required, String, 'description','required' => :create)
198
+ expect(param.required).to be true
199
+ end
200
+ end
201
+
202
+ context "when the param is required for multiple actions" do
203
+ it "should set param as required if it match current action" do
204
+ param = Apipie::ParamDescription.new(method_desc, :required, String, 'description','required' => [:update, :create])
205
+ expect(param.required).to be true
206
+ end
207
+ end
208
+
209
+ context "when the param is not required for current action" do
210
+ it "should set param as not required" do
211
+ param = Apipie::ParamDescription.new(method_desc, :required, String, 'description','required' => :update)
212
+ expect(param.required).to be false
213
+ end
214
+ end
215
+ end
216
+
217
+ describe "required params in action aware validator" do
218
+
219
+ subject { method_description.params[:user].validator.params_ordered }
220
+
221
+ let(:required) do
222
+ subject.find_all(&:required).map(&:name)
223
+ end
224
+
225
+ let(:allowed_nil) do
226
+ subject.find_all(&:allow_nil).map(&:name)
227
+ end
228
+
229
+ context "with resource creation" do
230
+
231
+ let(:method_description) do
232
+ Apipie.get_method_description(UsersController, :create)
233
+ end
234
+
235
+ it "makes the param required" do
236
+ expect(required).to include :name
237
+ expect(required).to include :pass
238
+ end
239
+
240
+ it "doesn't allow nil" do
241
+ expect(allowed_nil).not_to include :name
242
+ expect(allowed_nil).not_to include :pass
243
+ end
244
+ end
245
+
246
+ context "with resource update" do
247
+
248
+ let(:method_description) do
249
+ Apipie.get_method_description(UsersController, :update)
250
+ end
251
+
252
+ it "doesn't make the param required" do
253
+ expect(required).not_to include :name
254
+ expect(required).not_to include :pass
255
+ end
256
+
257
+ it "doesn't allow nil" do
258
+ expect(allowed_nil).not_to include :name
259
+ expect(allowed_nil).not_to include :pass
260
+ end
261
+
262
+ it "doesn't touch params with explicitly set allow_nil" do
263
+ expect(allowed_nil).not_to include :membership
264
+ end
265
+ end
266
+
267
+ context "with explicitly setting action type in param group" do
268
+ let(:method_description) do
269
+ Apipie.get_method_description(UsersController, :admin_create)
270
+ end
271
+
272
+ it "makes the param required" do
273
+ expect(required).to include :name
274
+ expect(required).to include :pass
275
+ end
276
+
277
+ it "doesn't allow nil" do
278
+ expect(allowed_nil).not_to include :name
279
+ expect(allowed_nil).not_to include :pass
280
+ end
281
+ end
282
+ end
283
+
284
+
285
+ describe 'sub params' do
286
+
287
+ context 'with HashValidator' do
288
+
289
+ subject do
290
+ Apipie::ParamDescription.new(method_desc, :param, Hash) do
291
+ param :answer, Fixnum
292
+ end
293
+ end
294
+
295
+ it "should include the nested params in the json" do
296
+ sub_params = subject.to_json[:params]
297
+ expect(sub_params.size).to eq(1)
298
+ sub_param = sub_params.first
299
+ expect(sub_param[:name]).to eq("answer")
300
+ expect(sub_param[:full_name]).to eq("param[answer]")
301
+ end
302
+
303
+ end
304
+
305
+ context 'with NestedValidator' do
306
+
307
+ subject do
308
+ Apipie::ParamDescription.new(method_desc, :param, Array) do
309
+ param :answer, Fixnum
310
+ end
311
+ end
312
+
313
+ it "should include the nested params in the json" do
314
+ sub_params = subject.to_json[:params]
315
+ expect(sub_params.size).to eq(1)
316
+ sub_param = sub_params.first
317
+ expect(sub_param[:name]).to eq("answer")
318
+ expect(sub_param[:full_name]).to eq("param[answer]")
319
+ end
320
+
321
+ end
322
+
323
+ context 'with flat validator' do
324
+
325
+ subject do
326
+ Apipie::ParamDescription.new(method_desc, :param, String)
327
+ end
328
+
329
+ it "should include the nested params in the json" do
330
+ expect(subject.to_json[:params]).to be_nil
331
+ end
332
+
333
+ end
334
+
335
+ end
336
+
337
+ describe "Array with classes" do
338
+ it "should be valid for objects included in class array" do
339
+ param = Apipie::ParamDescription.new(method_desc, :param, [Fixnum, String])
340
+ expect { param.validate("1") }.not_to raise_error
341
+ expect { param.validate(Fixnum) }.to raise_error(Apipie::ParamInvalid)
342
+ end
343
+ end
344
+
345
+ end