apipierails3 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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