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.
- checksums.yaml +17 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +27 -0
- data/APACHE-LICENSE-2.0 +202 -0
- data/CHANGELOG.md +469 -0
- data/Gemfile +1 -0
- data/Gemfile.rails32 +6 -0
- data/Gemfile.rails41 +6 -0
- data/Gemfile.rails42 +11 -0
- data/Gemfile.rails50 +6 -0
- data/Gemfile.rails51 +7 -0
- data/MIT-LICENSE +20 -0
- data/NOTICE +4 -0
- data/PROPOSAL_FOR_RESPONSE_DESCRIPTIONS.md +244 -0
- data/README.rst +1874 -0
- data/Rakefile +13 -0
- data/apipierails3.gemspec +27 -0
- data/app/controllers/apipie/apipies_controller.rb +199 -0
- data/app/helpers/apipie_helper.rb +10 -0
- data/app/public/apipie/javascripts/apipie.js +6 -0
- data/app/public/apipie/javascripts/bundled/bootstrap-collapse.js +138 -0
- data/app/public/apipie/javascripts/bundled/bootstrap.js +1726 -0
- data/app/public/apipie/javascripts/bundled/jquery.js +5 -0
- data/app/public/apipie/javascripts/bundled/prettify.js +28 -0
- data/app/public/apipie/stylesheets/application.css +7 -0
- data/app/public/apipie/stylesheets/bundled/bootstrap-responsive.min.css +12 -0
- data/app/public/apipie/stylesheets/bundled/bootstrap.min.css +689 -0
- data/app/public/apipie/stylesheets/bundled/prettify.css +30 -0
- data/app/views/apipie/apipies/_disqus.html.erb +13 -0
- data/app/views/apipie/apipies/_errors.html.erb +23 -0
- data/app/views/apipie/apipies/_headers.html.erb +26 -0
- data/app/views/apipie/apipies/_languages.erb +6 -0
- data/app/views/apipie/apipies/_metadata.erb +1 -0
- data/app/views/apipie/apipies/_method_detail.erb +61 -0
- data/app/views/apipie/apipies/_params.html.erb +42 -0
- data/app/views/apipie/apipies/_params_plain.html.erb +20 -0
- data/app/views/apipie/apipies/apipie_404.html.erb +17 -0
- data/app/views/apipie/apipies/apipie_checksum.json.erb +1 -0
- data/app/views/apipie/apipies/getting_started.html.erb +6 -0
- data/app/views/apipie/apipies/index.html.erb +56 -0
- data/app/views/apipie/apipies/method.html.erb +41 -0
- data/app/views/apipie/apipies/plain.html.erb +77 -0
- data/app/views/apipie/apipies/resource.html.erb +80 -0
- data/app/views/apipie/apipies/static.html.erb +103 -0
- data/app/views/layouts/apipie/apipie.html.erb +27 -0
- data/config/locales/de.yml +28 -0
- data/config/locales/en.yml +32 -0
- data/config/locales/es.yml +28 -0
- data/config/locales/fr.yml +31 -0
- data/config/locales/it.yml +31 -0
- data/config/locales/ja.yml +31 -0
- data/config/locales/pl.yml +28 -0
- data/config/locales/pt-BR.yml +28 -0
- data/config/locales/ru.yml +28 -0
- data/config/locales/tr.yml +28 -0
- data/config/locales/zh-CN.yml +28 -0
- data/config/locales/zh-TW.yml +28 -0
- data/images/screenshot-1.png +0 -0
- data/images/screenshot-2.png +0 -0
- data/lib/apipie/apipie_module.rb +83 -0
- data/lib/apipie/application.rb +462 -0
- data/lib/apipie/configuration.rb +186 -0
- data/lib/apipie/dsl_definition.rb +607 -0
- data/lib/apipie/error_description.rb +44 -0
- data/lib/apipie/errors.rb +86 -0
- data/lib/apipie/extractor.rb +177 -0
- data/lib/apipie/extractor/collector.rb +117 -0
- data/lib/apipie/extractor/recorder.rb +166 -0
- data/lib/apipie/extractor/writer.rb +454 -0
- data/lib/apipie/helpers.rb +73 -0
- data/lib/apipie/markup.rb +48 -0
- data/lib/apipie/method_description.rb +273 -0
- data/lib/apipie/middleware/checksum_in_headers.rb +35 -0
- data/lib/apipie/param_description.rb +280 -0
- data/lib/apipie/railtie.rb +9 -0
- data/lib/apipie/resource_description.rb +124 -0
- data/lib/apipie/response_description.rb +131 -0
- data/lib/apipie/response_description_adapter.rb +200 -0
- data/lib/apipie/routes_formatter.rb +33 -0
- data/lib/apipie/routing.rb +16 -0
- data/lib/apipie/rspec/response_validation_helper.rb +192 -0
- data/lib/apipie/see_description.rb +39 -0
- data/lib/apipie/static_dispatcher.rb +69 -0
- data/lib/apipie/swagger_generator.rb +707 -0
- data/lib/apipie/tag_list_description.rb +11 -0
- data/lib/apipie/validator.rb +526 -0
- data/lib/apipie/version.rb +3 -0
- data/lib/apipierails3.rb +25 -0
- data/lib/generators/apipie/install/README +6 -0
- data/lib/generators/apipie/install/install_generator.rb +25 -0
- data/lib/generators/apipie/install/templates/initializer.rb.erb +7 -0
- data/lib/generators/apipie/views_generator.rb +11 -0
- data/lib/tasks/apipie.rake +345 -0
- data/rel-eng/packages/.readme +3 -0
- data/rel-eng/packages/rubygem-apipie-rails +1 -0
- data/rel-eng/tito.props +5 -0
- data/spec/controllers/api/v1/architectures_controller_spec.rb +29 -0
- data/spec/controllers/api/v2/architectures_controller_spec.rb +12 -0
- data/spec/controllers/api/v2/nested/resources_controller_spec.rb +11 -0
- data/spec/controllers/apipies_controller_spec.rb +273 -0
- data/spec/controllers/concerns_controller_spec.rb +42 -0
- data/spec/controllers/extended_controller_spec.rb +11 -0
- data/spec/controllers/users_controller_spec.rb +740 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/api/base_controller.rb +4 -0
- data/spec/dummy/app/controllers/api/v1/architectures_controller.rb +43 -0
- data/spec/dummy/app/controllers/api/v1/base_controller.rb +11 -0
- data/spec/dummy/app/controllers/api/v2/architectures_controller.rb +30 -0
- data/spec/dummy/app/controllers/api/v2/base_controller.rb +11 -0
- data/spec/dummy/app/controllers/api/v2/nested/architectures_controller.rb +32 -0
- data/spec/dummy/app/controllers/api/v2/nested/resources_controller.rb +33 -0
- data/spec/dummy/app/controllers/application_controller.rb +18 -0
- data/spec/dummy/app/controllers/concerns/extending_concern.rb +11 -0
- data/spec/dummy/app/controllers/concerns/sample_controller.rb +41 -0
- data/spec/dummy/app/controllers/concerns_controller.rb +8 -0
- data/spec/dummy/app/controllers/extended_controller.rb +14 -0
- data/spec/dummy/app/controllers/files_controller.rb +5 -0
- data/spec/dummy/app/controllers/overridden_concerns_controller.rb +31 -0
- data/spec/dummy/app/controllers/pets_controller.rb +408 -0
- data/spec/dummy/app/controllers/pets_using_auto_views_controller.rb +73 -0
- data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +95 -0
- data/spec/dummy/app/controllers/tagged_cats_controller.rb +32 -0
- data/spec/dummy/app/controllers/tagged_dogs_controller.rb +15 -0
- data/spec/dummy/app/controllers/twitter_example_controller.rb +307 -0
- data/spec/dummy/app/controllers/users_controller.rb +297 -0
- data/spec/dummy/app/views/layouts/application.html.erb +21 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +49 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +21 -0
- data/spec/dummy/config/environment.rb +8 -0
- data/spec/dummy/config/environments/development.rb +28 -0
- data/spec/dummy/config/environments/production.rb +52 -0
- data/spec/dummy/config/environments/test.rb +38 -0
- data/spec/dummy/config/initializers/apipie.rb +110 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +8 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +51 -0
- data/spec/dummy/db/.gitkeep +0 -0
- data/spec/dummy/doc/apipie_examples.json +1 -0
- data/spec/dummy/doc/users/desc_from_file.md +1 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/lib/application_spec.rb +49 -0
- data/spec/lib/extractor/extractor_spec.rb +9 -0
- data/spec/lib/extractor/middleware_spec.rb +44 -0
- data/spec/lib/extractor/writer_spec.rb +110 -0
- data/spec/lib/file_handler_spec.rb +18 -0
- data/spec/lib/method_description_spec.rb +98 -0
- data/spec/lib/param_description_spec.rb +345 -0
- data/spec/lib/param_group_spec.rb +60 -0
- data/spec/lib/rake_spec.rb +71 -0
- data/spec/lib/resource_description_spec.rb +48 -0
- data/spec/lib/swagger/openapi_2_0_schema.json +1607 -0
- data/spec/lib/swagger/rake_swagger_spec.rb +139 -0
- data/spec/lib/swagger/response_validation_spec.rb +104 -0
- data/spec/lib/swagger/swagger_dsl_spec.rb +658 -0
- data/spec/lib/validator_spec.rb +113 -0
- data/spec/lib/validators/array_validator_spec.rb +85 -0
- data/spec/spec_helper.rb +109 -0
- data/spec/support/rake.rb +21 -0
- metadata +415 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Api::V2::ArchitecturesController do
|
|
4
|
+
describe "resource description" do
|
|
5
|
+
subject { Apipie.get_resource_description(Api::V2::ArchitecturesController, "2.0") }
|
|
6
|
+
|
|
7
|
+
it "should be version 2.0" do
|
|
8
|
+
expect(subject._version).to eq('2.0')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Api::V2::Nested::ResourcesController do
|
|
4
|
+
describe "resource id" do
|
|
5
|
+
subject { Apipie.get_resource_name(Api::V2::Nested::ResourcesController) }
|
|
6
|
+
|
|
7
|
+
it "should have resource_id set" do
|
|
8
|
+
expect(subject).to eq("resource")
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
require "json-schema"
|
|
4
|
+
|
|
5
|
+
describe Apipie::ApipiesController do
|
|
6
|
+
|
|
7
|
+
describe "GET index" do
|
|
8
|
+
|
|
9
|
+
it "succeeds on index" do
|
|
10
|
+
get :index
|
|
11
|
+
|
|
12
|
+
assert_response :success
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "succeeds on version details" do
|
|
16
|
+
get :index, :params => { :version => "2.0" }
|
|
17
|
+
|
|
18
|
+
assert_response :success
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "returns not_found on wrong version" do
|
|
22
|
+
get :index, :params => { :version => "wrong_version" }
|
|
23
|
+
|
|
24
|
+
assert_response :not_found
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "succeeds on resource details" do
|
|
28
|
+
get :index, :params => { :version => "2.0", :resource => "architectures" }
|
|
29
|
+
|
|
30
|
+
assert_response :success
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "returns not_found on wrong resource" do
|
|
34
|
+
get :index, :params => { :version => "2.0", :resource => "wrong_resource" }
|
|
35
|
+
|
|
36
|
+
assert_response :not_found
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "succeeds on method details" do
|
|
40
|
+
get :index, :params => { :version => "2.0", :resource => "architectures", :method => "index" }
|
|
41
|
+
|
|
42
|
+
assert_response :success
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "returns not_found on wrong method" do
|
|
46
|
+
get :index, :params => { :version => "2.0", :resource => "architectures", :method => "wrong_method" }
|
|
47
|
+
|
|
48
|
+
assert_response :not_found
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe "reload_controllers" do
|
|
53
|
+
|
|
54
|
+
RSpec::Matchers.define :reload_documentation do
|
|
55
|
+
match do |actual|
|
|
56
|
+
expect(Apipie).to receive(:reload_documentation)
|
|
57
|
+
get :index
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
match_when_negated do |actual|
|
|
61
|
+
expect(Apipie).not_to receive(:reload_documentation)
|
|
62
|
+
get :index
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
failure_message { "the documentation expected to be reloaded but it was not" }
|
|
66
|
+
failure_message_when_negated { "the documentation expected not to be reloaded but it was" }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
before do
|
|
70
|
+
Apipie.configuration.api_controllers_matcher = File.join(Rails.root, "app", "controllers", "**","*.rb")
|
|
71
|
+
if Apipie.configuration.send :instance_variable_defined?, "@reload_controllers"
|
|
72
|
+
Apipie.configuration.send :remove_instance_variable, "@reload_controllers"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context "it's not specified explicitly" do
|
|
77
|
+
context "and it's in development environment" do
|
|
78
|
+
before do
|
|
79
|
+
allow(Rails).to receive_messages(:env => double(:development? => true))
|
|
80
|
+
end
|
|
81
|
+
it { is_expected.to reload_documentation }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
context "and it's not development environment" do
|
|
85
|
+
it { is_expected.not_to reload_documentation }
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
context "it's explicitly enabled" do
|
|
91
|
+
before do
|
|
92
|
+
Apipie.configuration.reload_controllers = true
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context "and it's in development environment" do
|
|
96
|
+
before do
|
|
97
|
+
allow(Rails).to receive_messages(:env => double(:development? => true))
|
|
98
|
+
end
|
|
99
|
+
it { is_expected.to reload_documentation }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context "and it's not development environment" do
|
|
103
|
+
it { is_expected.to reload_documentation }
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context "it's explicitly enabled" do
|
|
108
|
+
before do
|
|
109
|
+
Apipie.configuration.reload_controllers = false
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context "and it's in development environment" do
|
|
113
|
+
before do
|
|
114
|
+
allow(Rails).to receive_messages(:env => double(:development? => true))
|
|
115
|
+
end
|
|
116
|
+
it { is_expected.not_to reload_documentation }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
context "and it's not development environment" do
|
|
120
|
+
it { is_expected.not_to reload_documentation }
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context "api_controllers_matcher is specified" do
|
|
125
|
+
before do
|
|
126
|
+
Apipie.configuration.reload_controllers = true
|
|
127
|
+
Apipie.configuration.api_controllers_matcher = nil
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it { is_expected.not_to reload_documentation }
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
describe "GET index as swagger" do
|
|
135
|
+
|
|
136
|
+
let(:swagger_schema) do
|
|
137
|
+
File.read(File.join(File.dirname(__FILE__),"../lib/swagger/openapi_2_0_schema.json"))
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "outputs swagger when format is json and type is swagger" do
|
|
141
|
+
get :index, :params => { :format => "json", :type => "swagger"}
|
|
142
|
+
|
|
143
|
+
assert_response :success
|
|
144
|
+
expect(response.body).to match(/"swagger":"2.0"/)
|
|
145
|
+
# puts response.body
|
|
146
|
+
|
|
147
|
+
expect(JSON::Validator.validate(swagger_schema, response.body)).to be_truthy
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "does not output swagger when format is not json even if type is swagger" do
|
|
151
|
+
get :index, :params => { :type => "swagger"}
|
|
152
|
+
|
|
153
|
+
assert_response :success
|
|
154
|
+
expect(response.body).not_to match(/"swagger":"2.0"/)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it "does not output swagger when format is json even but type is not swagger" do
|
|
158
|
+
get :index, :params => { :format => "json"}
|
|
159
|
+
|
|
160
|
+
assert_response :success
|
|
161
|
+
expect(response.body).not_to match(/"swagger":"2.0"/)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
describe "authenticate user" do
|
|
167
|
+
it "authenticate user if an authentication method is setted" do
|
|
168
|
+
test = false
|
|
169
|
+
Apipie.configuration.authenticate = Proc.new do
|
|
170
|
+
test = true
|
|
171
|
+
end
|
|
172
|
+
get :index
|
|
173
|
+
expect(test).to eq(true)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
describe "authorize document" do
|
|
178
|
+
it "if an authroize method is set" do
|
|
179
|
+
test = false
|
|
180
|
+
Apipie.configuration.authorize = Proc.new do |controller, method, doc|
|
|
181
|
+
test = true
|
|
182
|
+
true
|
|
183
|
+
end
|
|
184
|
+
get :index
|
|
185
|
+
expect(test).to eq(true)
|
|
186
|
+
end
|
|
187
|
+
it "remove all resources" do
|
|
188
|
+
Apipie.configuration.authorize = Proc.new do |&args|
|
|
189
|
+
false
|
|
190
|
+
end
|
|
191
|
+
get :index
|
|
192
|
+
expect(assigns(:doc)[:resources]).to eq({})
|
|
193
|
+
end
|
|
194
|
+
it "remove all methods" do
|
|
195
|
+
Apipie.configuration.authorize = Proc.new do |controller, method, doc|
|
|
196
|
+
!method
|
|
197
|
+
end
|
|
198
|
+
get :index
|
|
199
|
+
expect(assigns(:doc)[:resources]["concern_resources"][:methods]).to eq([])
|
|
200
|
+
expect(assigns(:doc)[:resources]["twitter_example"][:methods]).to eq([])
|
|
201
|
+
expect(assigns(:doc)[:resources]["users"][:methods]).to eq([])
|
|
202
|
+
end
|
|
203
|
+
it "remove specific method" do
|
|
204
|
+
Apipie.configuration.authorize = nil
|
|
205
|
+
get :index
|
|
206
|
+
|
|
207
|
+
users_methods = assigns(:doc)[:resources]["users"][:methods].size
|
|
208
|
+
twitter_example_methods = assigns(:doc)[:resources]["twitter_example"][:methods].size
|
|
209
|
+
|
|
210
|
+
Apipie.configuration.authorize = Proc.new do |controller, method, doc|
|
|
211
|
+
controller == "users" ? method != "index" : true
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
get :index
|
|
215
|
+
|
|
216
|
+
expect(assigns(:doc)[:resources]["users"][:methods].size).to eq(users_methods - 1)
|
|
217
|
+
expect(assigns(:doc)[:resources]["twitter_example"][:methods].size).to eq(twitter_example_methods)
|
|
218
|
+
end
|
|
219
|
+
it "does not allow access to swagger when authorization is set" do
|
|
220
|
+
get :index, :params => { :format => "json", :type => "swagger"}
|
|
221
|
+
|
|
222
|
+
assert_response :forbidden
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
describe "documentation cache" do
|
|
227
|
+
|
|
228
|
+
let(:cache_dir) { File.join(Rails.root, "tmp", "apipie-cache") }
|
|
229
|
+
|
|
230
|
+
before do
|
|
231
|
+
FileUtils.rm_r(cache_dir) if File.exists?(cache_dir)
|
|
232
|
+
FileUtils.mkdir_p(File.join(cache_dir, "apidoc", "v1", "resource"))
|
|
233
|
+
File.open(File.join(cache_dir, "apidoc", "v1.html"), "w") { |f| f << "apidoc.html cache v1" }
|
|
234
|
+
File.open(File.join(cache_dir, "apidoc", "v2.html"), "w") { |f| f << "apidoc.html cache v2" }
|
|
235
|
+
File.open(File.join(cache_dir, "apidoc", "v1.json"), "w") { |f| f << "apidoc.json cache" }
|
|
236
|
+
File.open(File.join(cache_dir, "apidoc", "v1", "resource.html"), "w") { |f| f << "resource.html cache" }
|
|
237
|
+
File.open(File.join(cache_dir, "apidoc", "v1", "resource", "method.html"), "w") { |f| f << "method.html cache" }
|
|
238
|
+
|
|
239
|
+
Apipie.configuration.use_cache = true
|
|
240
|
+
@orig_cache_dir = Apipie.configuration.cache_dir
|
|
241
|
+
Apipie.configuration.cache_dir = cache_dir
|
|
242
|
+
@orig_version = Apipie.configuration.default_version
|
|
243
|
+
Apipie.configuration.default_version = 'v1'
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
after do
|
|
247
|
+
Apipie.configuration.use_cache = false
|
|
248
|
+
Apipie.configuration.default_version = @orig_version
|
|
249
|
+
Apipie.configuration.cache_dir = @orig_cache_dir
|
|
250
|
+
# FileUtils.rm_r(cache_dir) if File.exists?(cache_dir)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
it "uses the file in cache dir instead of generating the content on runtime" do
|
|
254
|
+
get :index
|
|
255
|
+
expect(response.body).to eq("apidoc.html cache v1")
|
|
256
|
+
get :index, :params => { :version => 'v1' }
|
|
257
|
+
expect(response.body).to eq("apidoc.html cache v1")
|
|
258
|
+
get :index, :params => { :version => 'v2' }
|
|
259
|
+
expect(response.body).to eq("apidoc.html cache v2")
|
|
260
|
+
get :index, :params => { :version => 'v1', :format => "html" }
|
|
261
|
+
expect(response.body).to eq("apidoc.html cache v1")
|
|
262
|
+
get :index, :params => { :version => 'v1', :format => "json" }
|
|
263
|
+
expect(response.body).to eq("apidoc.json cache")
|
|
264
|
+
get :index, :params => { :version => 'v1', :format => "html", :resource => "resource" }
|
|
265
|
+
expect(response.body).to eq("resource.html cache")
|
|
266
|
+
get :index, :params => { :version => 'v1', :format => "html", :resource => "resource", :method => "method" }
|
|
267
|
+
expect(response.body).to eq("method.html cache")
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe ConcernsController do
|
|
4
|
+
|
|
5
|
+
it "displays is every controller the concern is included" do
|
|
6
|
+
expect(Apipie["concern_resources#index"]).to be
|
|
7
|
+
expect(Apipie["concern_resources#show"]).to be
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should reply to valid request" do
|
|
11
|
+
get :show, :params => { :id => '5' }, :session => { :user_id => "secret_hash" }
|
|
12
|
+
assert_response :success
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should pass if required parameter is missing" do
|
|
16
|
+
expect { get :show, :params => { :id => '5' } }.not_to raise_error
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "peserved the order of methods being defined in file" do
|
|
20
|
+
doc_methods = Apipie.get_resource_description('concern_resources')._methods.keys
|
|
21
|
+
expect(doc_methods).to eq([:index, :show, :create, :update, :custom])
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "replaces a placeholder doc specified in concern with a real path" do
|
|
25
|
+
path = Apipie["concern_resources#index"].apis.first.path
|
|
26
|
+
expect(path).to eq('/api/concerns')
|
|
27
|
+
|
|
28
|
+
path = Apipie["concern_resources#show"].apis.first.path
|
|
29
|
+
expect(path).to eq('/concern_resources/:id')
|
|
30
|
+
|
|
31
|
+
path = Apipie["concern_resources#custom"].apis.first.path
|
|
32
|
+
expect(path).to eq('/concern_resources/custom')
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "replaces placeholders in param names and descriptions" do
|
|
36
|
+
create_desc = Apipie["concern_resources#create"].params[:user]
|
|
37
|
+
name_param, concern_type_param = create_desc.validator.params_ordered
|
|
38
|
+
expect(name_param.desc).to include "Name of a user"
|
|
39
|
+
expect(concern_type_param.name).to eq(:user_type)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe ExtendedController do
|
|
4
|
+
|
|
5
|
+
it 'should include params from both original controller and extending concern' do
|
|
6
|
+
expect(Apipie["extended#create"].params.keys).to eq [:oauth, :user, :admin]
|
|
7
|
+
user_param = Apipie["extended#create"].params[:user]
|
|
8
|
+
expect(user_param.validator.params_ordered.map(&:name)).to eq [:name, :password, :from_concern]
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
@@ -0,0 +1,740 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
def compare_hashes(h1, h2)
|
|
4
|
+
if h1.is_a? String
|
|
5
|
+
expect(h1).to eq(h2)
|
|
6
|
+
else
|
|
7
|
+
h1.each do |key, val|
|
|
8
|
+
if val.is_a? Hash
|
|
9
|
+
compare_hashes val, h2[key]
|
|
10
|
+
elsif val.is_a? Array
|
|
11
|
+
val.each_with_index do |v, i|
|
|
12
|
+
compare_hashes val[i], h2[key][i]
|
|
13
|
+
end
|
|
14
|
+
else
|
|
15
|
+
expect(val).to eq(h2[key])
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe UsersController do
|
|
22
|
+
|
|
23
|
+
let(:dsl_data) { ActionController::Base.send(:_apipie_dsl_data_init) }
|
|
24
|
+
|
|
25
|
+
describe "resource description" do
|
|
26
|
+
subject do
|
|
27
|
+
Apipie.get_resource_description(UsersController, Apipie.configuration.default_version)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should contain all resource methods" do
|
|
31
|
+
methods = subject._methods
|
|
32
|
+
expect(methods.keys).to include(:show)
|
|
33
|
+
expect(methods.keys).to include(:create_route)
|
|
34
|
+
expect(methods.keys).to include(:index)
|
|
35
|
+
expect(methods.keys).to include(:create)
|
|
36
|
+
expect(methods.keys).to include(:update)
|
|
37
|
+
expect(methods.keys).to include(:two_urls)
|
|
38
|
+
expect(methods.keys).to include(:action_with_headers)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should contain info about resource" do
|
|
42
|
+
expect(subject._short_description).to eq('Site members')
|
|
43
|
+
expect(subject._id).to eq('users')
|
|
44
|
+
expect(subject._path).to eq('/users')
|
|
45
|
+
expect(subject._version).to eq('development')
|
|
46
|
+
expect(subject._name).to eq('Users')
|
|
47
|
+
expect(subject._formats).to eq(['json'])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should contain params defined on resource level" do
|
|
51
|
+
expect(subject._params_args.count).to eq(2)
|
|
52
|
+
name, type, options = subject._params_args.first
|
|
53
|
+
expect(name).to eq(:id)
|
|
54
|
+
expect(type).to eq(Fixnum)
|
|
55
|
+
expect(options).to eq({:required=>false, :desc=>"User ID"})
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe "validators" do
|
|
60
|
+
|
|
61
|
+
context "validations are disabled" do
|
|
62
|
+
before do
|
|
63
|
+
Apipie.configuration.validate = false
|
|
64
|
+
Apipie.configuration.validate_value = true
|
|
65
|
+
Apipie.configuration.validate_presence = true
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should reply to valid request" do
|
|
69
|
+
get :show, :params => { :id => '5', :session => "secret_hash" }
|
|
70
|
+
assert_response :success
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should pass if required parameter is missing" do
|
|
74
|
+
expect { get :show, :params => { :id => 5 } }.not_to raise_error
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
context "validations are enabled" do
|
|
80
|
+
def reload_controllers
|
|
81
|
+
controllers_dirname = File.expand_path('../dummy/app/controllers', File.dirname(__FILE__))
|
|
82
|
+
Dir.glob("#{controllers_dirname}/**/*") { |file| load(file) if File.file?(file) }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
shared_examples "validates correctly" do
|
|
86
|
+
|
|
87
|
+
context "only presence validations are enabled" do
|
|
88
|
+
before do
|
|
89
|
+
Apipie.configuration.validate_value = false
|
|
90
|
+
Apipie.configuration.validate_presence = true
|
|
91
|
+
Apipie.configuration.validate_key = false
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "should reply to valid request" do
|
|
95
|
+
expect { get :show, :params => { :id => 5, :session => "secret_hash" }}.not_to raise_error
|
|
96
|
+
assert_response :success
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "should fail if required parameter is missing" do
|
|
100
|
+
expect { get :show, :params => { :id => 5 }}.to raise_error(Apipie::ParamMissing, /session_parameter_is_required/)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "should pass if required parameter has wrong type" do
|
|
104
|
+
expect { get :show, :params => { :id => 5 , :session => "secret_hash" }}.not_to raise_error
|
|
105
|
+
expect { get :show, :params => { :id => "ten" , :session => "secret_hash" }}.not_to raise_error
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
context "key validations are enabled" do
|
|
111
|
+
before do
|
|
112
|
+
Apipie.configuration.validate_value = false
|
|
113
|
+
Apipie.configuration.validate_presence = true
|
|
114
|
+
Apipie.configuration.validate_key = true
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "should reply to valid request" do
|
|
118
|
+
expect { get :show, :params => { :id => 5, :session => 'secret_hash' }}.not_to raise_error
|
|
119
|
+
assert_response :success
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "should fail if extra parameter is passed in" do
|
|
123
|
+
expect { get :show, :params => { :id => 5 , :badparam => 'badfoo', :session => "secret_hash" }}.to raise_error(Apipie::UnknownParam, /\bbadparam\b/)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context "presence and value validations are enabled" do
|
|
128
|
+
before do
|
|
129
|
+
Apipie.configuration.validate_value = true
|
|
130
|
+
Apipie.configuration.validate_presence = true
|
|
131
|
+
Apipie.configuration.validate_key = false
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it "should reply to valid request" do
|
|
135
|
+
get :show, :params => { :id => '5', :session => "secret_hash" }
|
|
136
|
+
assert_response :success
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "should work with nil value for a required hash param" do
|
|
140
|
+
expect {
|
|
141
|
+
get :show, :params => { :id => '5', :session => "secret_hash", :hash_param => {:dummy_hash => nil} }
|
|
142
|
+
}.to raise_error(Apipie::ParamInvalid, /dummy_hash/)
|
|
143
|
+
assert_response :success
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "should fail if required parameter is missing" do
|
|
147
|
+
expect { get :show, :params => { :id => 5 }}.to raise_error(Apipie::ParamMissing, /session_parameter_is_required/)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "should work with custom Type validator" do
|
|
151
|
+
expect {
|
|
152
|
+
get :show,
|
|
153
|
+
:params => { :id => "not a number", :session => "secret_hash" }
|
|
154
|
+
}.to raise_error(Apipie::ParamError, /id/) # old-style error rather than ParamInvalid
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it "should work with Regexp validator" do
|
|
158
|
+
get :show, :params => { :id => 5, :session => "secret_hash", :regexp_param => "24 years" }
|
|
159
|
+
assert_response :success
|
|
160
|
+
|
|
161
|
+
expect {
|
|
162
|
+
get :show, :params => { :id => 5,
|
|
163
|
+
:session => "secret_hash",
|
|
164
|
+
:regexp_param => "ten years" }
|
|
165
|
+
}.to raise_error(Apipie::ParamInvalid, /regexp_param/)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "should work with Array validator" do
|
|
169
|
+
get :show, :params => { :id => 5, :session => "secret_hash", :array_param => "one" }
|
|
170
|
+
assert_response :success
|
|
171
|
+
get :show, :params => { :id => 5, :session => "secret_hash", :array_param => "two" }
|
|
172
|
+
assert_response :success
|
|
173
|
+
get :show, :params => { :id => 5, :session => "secret_hash", :array_param => '1' }
|
|
174
|
+
assert_response :success
|
|
175
|
+
|
|
176
|
+
expect {
|
|
177
|
+
get :show, :params => { :id => 5,
|
|
178
|
+
:session => "secret_hash",
|
|
179
|
+
:array_param => "blabla" }
|
|
180
|
+
}.to raise_error(Apipie::ParamInvalid, /array_param/)
|
|
181
|
+
|
|
182
|
+
expect {
|
|
183
|
+
get :show, :params => {
|
|
184
|
+
:id => 5,
|
|
185
|
+
:session => "secret_hash",
|
|
186
|
+
:array_param => 3 }
|
|
187
|
+
}.to raise_error(Apipie::ParamInvalid, /array_param/)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "should work with Proc validator" do
|
|
191
|
+
expect {
|
|
192
|
+
get :show,
|
|
193
|
+
:params => {
|
|
194
|
+
:id => 5,
|
|
195
|
+
:session => "secret_hash",
|
|
196
|
+
:proc_param => "asdgsag" }
|
|
197
|
+
}.to raise_error(Apipie::ParamInvalid, /proc_param/)
|
|
198
|
+
|
|
199
|
+
get :show,
|
|
200
|
+
:params => {
|
|
201
|
+
:id => 5,
|
|
202
|
+
:session => "secret_hash",
|
|
203
|
+
:proc_param => "param value"}
|
|
204
|
+
assert_response :success
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it "should work with Hash validator" do
|
|
208
|
+
post :create, params: { :user => { :name => "root", :pass => "12345", :membership => "standard" } }
|
|
209
|
+
assert_response :success
|
|
210
|
+
|
|
211
|
+
a = Apipie[UsersController, :create]
|
|
212
|
+
param = a.params_ordered.select {|p| p.name == :user }
|
|
213
|
+
expect(param.count).to eq(1)
|
|
214
|
+
expect(param.first.validator.class).to eq(Apipie::Validator::HashValidator)
|
|
215
|
+
hash_params = param.first.validator.params_ordered
|
|
216
|
+
expect(hash_params.count).to eq(4)
|
|
217
|
+
hash_params[0].name == :name
|
|
218
|
+
hash_params[1].name == :pass
|
|
219
|
+
hash_params[2].name == :membership
|
|
220
|
+
|
|
221
|
+
expect {
|
|
222
|
+
post :create, :params => { :user => { :name => "root", :pass => "12345", :membership => "____" } }
|
|
223
|
+
}.to raise_error(Apipie::ParamInvalid, /membership/)
|
|
224
|
+
|
|
225
|
+
expect {
|
|
226
|
+
post :create, :params => { :user => { :name => "root" } }
|
|
227
|
+
}.to raise_error(Apipie::ParamMissing, /pass/)
|
|
228
|
+
|
|
229
|
+
expect {
|
|
230
|
+
post :create, :params => { :user => "a string is not a hash" }
|
|
231
|
+
}.to raise_error(Apipie::ParamInvalid, /user/)
|
|
232
|
+
|
|
233
|
+
post :create, :params => { :user => { :name => "root", :pass => "pwd" } }
|
|
234
|
+
assert_response :success
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it "should support Hash validator without specifying keys" do
|
|
238
|
+
params = Apipie[UsersController, :create].to_json[:params]
|
|
239
|
+
expect(params).to include(:name => "facts",
|
|
240
|
+
:full_name => "facts",
|
|
241
|
+
:validator => "Must be a Hash",
|
|
242
|
+
:description => "\n<p>Additional optional facts about the user</p>\n",
|
|
243
|
+
:required => false,
|
|
244
|
+
:allow_nil => true,
|
|
245
|
+
:allow_blank => false,
|
|
246
|
+
:metadata => nil,
|
|
247
|
+
:show => true,
|
|
248
|
+
:expected_type => "hash",
|
|
249
|
+
:validations => [])
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
it "should allow nil when allow_nil is set to true" do
|
|
253
|
+
post :create,
|
|
254
|
+
:params => {
|
|
255
|
+
:user => {
|
|
256
|
+
:name => "root",
|
|
257
|
+
:pass => "12345",
|
|
258
|
+
:membership => "standard",
|
|
259
|
+
},
|
|
260
|
+
:facts => { :test => 'test' }
|
|
261
|
+
}
|
|
262
|
+
assert_response :success
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
it "should allow blank when allow_blank is set to true" do
|
|
266
|
+
post :create,
|
|
267
|
+
:params => {
|
|
268
|
+
:user => {
|
|
269
|
+
:name => "root",
|
|
270
|
+
:pass => "12345",
|
|
271
|
+
:membership => "standard"
|
|
272
|
+
},
|
|
273
|
+
:age => ""
|
|
274
|
+
}
|
|
275
|
+
assert_response :success
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
describe "nested elements" do
|
|
279
|
+
|
|
280
|
+
context "with valid input" do
|
|
281
|
+
it "should succeed" do
|
|
282
|
+
put :update,
|
|
283
|
+
:params => {
|
|
284
|
+
:id => 5,
|
|
285
|
+
:user => {
|
|
286
|
+
:name => "root",
|
|
287
|
+
:pass => "12345"
|
|
288
|
+
},
|
|
289
|
+
:comments => [
|
|
290
|
+
{
|
|
291
|
+
:comment => 'comment1'
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
:comment => 'comment2'
|
|
295
|
+
}
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
assert_response :success
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
context "with bad input" do
|
|
303
|
+
it "should raise an error" do
|
|
304
|
+
expect{
|
|
305
|
+
put :update,
|
|
306
|
+
:params => {
|
|
307
|
+
:id => 5,
|
|
308
|
+
:user => {
|
|
309
|
+
:name => "root",
|
|
310
|
+
:pass => "12345"
|
|
311
|
+
},
|
|
312
|
+
:comments => [
|
|
313
|
+
{
|
|
314
|
+
:comment => {:bad_input => 4}
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
:comment => {:bad_input => 5}
|
|
318
|
+
}
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
}.to raise_error(Apipie::ParamInvalid)
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
it "should work with empty array" do
|
|
325
|
+
put :update,
|
|
326
|
+
:params => {
|
|
327
|
+
:id => 5,
|
|
328
|
+
:user => {
|
|
329
|
+
:name => "root",
|
|
330
|
+
:pass => "12345"
|
|
331
|
+
},
|
|
332
|
+
:comments => [
|
|
333
|
+
]
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
assert_response :success
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
context "using configuration.validate = true" do
|
|
344
|
+
before :all do
|
|
345
|
+
Apipie.configuration.validate = true
|
|
346
|
+
reload_controllers
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
it_behaves_like "validates correctly"
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
context "using configuration.validate = :implicitly" do
|
|
353
|
+
before :all do
|
|
354
|
+
Apipie.configuration.validate = :implicitly
|
|
355
|
+
reload_controllers
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
it_behaves_like "validates correctly"
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
context "using configuration.validate = :explicitly" do
|
|
362
|
+
before :all do
|
|
363
|
+
Apipie.configuration.validate = :explicitly
|
|
364
|
+
reload_controllers
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
it_behaves_like "validates correctly"
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
describe "method description" do
|
|
374
|
+
|
|
375
|
+
it "should contain basic info about method" do
|
|
376
|
+
a = Apipie[UsersController, :create]
|
|
377
|
+
expect(a.apis.count).to eq(1)
|
|
378
|
+
expect(a.formats).to eq(['json'])
|
|
379
|
+
api = a.apis.first
|
|
380
|
+
expect(api.short_description).to eq("Create user")
|
|
381
|
+
expect(api.path).to eq("/users")
|
|
382
|
+
expect(api.http_method).to eq("POST")
|
|
383
|
+
|
|
384
|
+
b = Apipie.get_method_description(UsersController, :show)
|
|
385
|
+
expect(b).to eq(Apipie[UsersController, :show])
|
|
386
|
+
expect(b.method).to eq('show')
|
|
387
|
+
expect(b.resource._id).to eq('users')
|
|
388
|
+
|
|
389
|
+
expect(b.apis.count).to eq(1)
|
|
390
|
+
expect(b.formats).to eq(['json', 'jsonp'])
|
|
391
|
+
api = b.apis.first
|
|
392
|
+
expect(api.short_description).to eq("Show user profile")
|
|
393
|
+
expect(api.path).to eq("/users/:id")
|
|
394
|
+
expect(api.http_method).to eq("GET")
|
|
395
|
+
expect(b.full_description.length).to be > 400
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
context "Usign routes.rb" do
|
|
399
|
+
it "should contain basic info about method" do
|
|
400
|
+
a = Apipie[UsersController, :create_route]
|
|
401
|
+
expect(a.apis.count).to eq(1)
|
|
402
|
+
expect(a.formats).to eq(['json'])
|
|
403
|
+
api = a.apis.first
|
|
404
|
+
expect(api.short_description).to eq("Create user")
|
|
405
|
+
expect(api.path).to eq("/api/users/create_route")
|
|
406
|
+
expect(api.from_routes).to be_truthy
|
|
407
|
+
expect(api.http_method).to eq("POST")
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
context "contain :see option" do
|
|
412
|
+
|
|
413
|
+
context "the key is valid" do
|
|
414
|
+
it "should contain reference to another method" do
|
|
415
|
+
api = Apipie[UsersController, :see_another]
|
|
416
|
+
expect(api.show).to be false
|
|
417
|
+
see = api.see.first
|
|
418
|
+
expect(see.see_url).to eql Apipie[UsersController, :create].doc_url
|
|
419
|
+
expect(see.link).to eql 'development#users#create'
|
|
420
|
+
expect(see.description).to eql 'development#users#create'
|
|
421
|
+
|
|
422
|
+
see_with_desc = api.see.last
|
|
423
|
+
expect(see_with_desc.see_url).to eql Apipie[UsersController, :index].doc_url
|
|
424
|
+
expect(see_with_desc.link).to eql 'development#users#index'
|
|
425
|
+
expect(see_with_desc.description).to eql 'very interesting method reference'
|
|
426
|
+
|
|
427
|
+
expect(Apipie['development#users#see_another']).to eql Apipie[UsersController, :see_another]
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
context "the key is not valid" do
|
|
432
|
+
it "should raise exception" do
|
|
433
|
+
api = Apipie[UsersController, :see_another]
|
|
434
|
+
api.instance_variable_set :@see, [Apipie::SeeDescription.new(['doesnot#exist'])]
|
|
435
|
+
expect {
|
|
436
|
+
api.see.first.see_url
|
|
437
|
+
}.to raise_error(ArgumentError, /does not exist/)
|
|
438
|
+
api.instance_variable_set :@see, []
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
it "should contain possible errors description" do
|
|
444
|
+
a = Apipie.get_method_description(UsersController, :show)
|
|
445
|
+
|
|
446
|
+
expect(a.errors[0].code).to eq(500)
|
|
447
|
+
expect(a.errors[0].description).to include("crashed")
|
|
448
|
+
expect(a.errors[1].code).to eq(401)
|
|
449
|
+
expect(a.errors[1].description).to eq("Unauthorized")
|
|
450
|
+
expect(a.errors[2].code).to eq(404)
|
|
451
|
+
expect(a.errors[2].description).to eq("Not Found")
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
it 'should recognize Rack symbols as error codes' do
|
|
455
|
+
a = Apipie.get_method_description(UsersController, :create)
|
|
456
|
+
|
|
457
|
+
error = a.errors.find { |e| e.code == 422 }
|
|
458
|
+
expect(error).to be
|
|
459
|
+
expect(error.description).to include("Unprocessable Entity")
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
it "should contain all params description" do
|
|
463
|
+
a = Apipie.get_method_description(UsersController, :show)
|
|
464
|
+
expect(a.params.count).to eq(12)
|
|
465
|
+
expect(a.instance_variable_get('@params_ordered').count).to eq(10)
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
context 'headers' do
|
|
469
|
+
context 'for methods' do
|
|
470
|
+
let(:expected_required_header) do
|
|
471
|
+
{
|
|
472
|
+
name: :RequredHeaderName,
|
|
473
|
+
description: 'Required header description',
|
|
474
|
+
options: {
|
|
475
|
+
required: true
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
let(:expected_optional_header) do
|
|
481
|
+
{
|
|
482
|
+
name: :OptionalHeaderName,
|
|
483
|
+
description: 'Optional header description',
|
|
484
|
+
options: {
|
|
485
|
+
required: false,
|
|
486
|
+
type: "string"
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
it 'contains all headers description in method doc' do
|
|
492
|
+
headers = Apipie.get_method_description(UsersController, :action_with_headers).headers
|
|
493
|
+
expect(headers).to be_an(Array)
|
|
494
|
+
|
|
495
|
+
compare_hashes headers[0], expected_required_header
|
|
496
|
+
compare_hashes headers[1], expected_optional_header
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
context 'for resource' do
|
|
501
|
+
let(:expected_resource_header) do
|
|
502
|
+
{
|
|
503
|
+
name: :CommonHeader,
|
|
504
|
+
description: 'Common header description',
|
|
505
|
+
options: {
|
|
506
|
+
required: true
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
it 'contains all headers description in resource doc' do
|
|
512
|
+
headers = Apipie.get_resource_description(UsersController)._headers
|
|
513
|
+
expect(headers).to be_an(Array)
|
|
514
|
+
|
|
515
|
+
compare_hashes headers[0], expected_resource_header
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
it "should contain all api method description" do
|
|
521
|
+
method_description = Apipie[UsersController, :two_urls]
|
|
522
|
+
expect(method_description.class).to be(Apipie::MethodDescription)
|
|
523
|
+
expect(method_description.apis.count).to eq(2)
|
|
524
|
+
a1, a2 = method_description.apis
|
|
525
|
+
|
|
526
|
+
expect(a1.short_description).to eq('Get company users')
|
|
527
|
+
expect(a1.path).to eq('/company_users')
|
|
528
|
+
expect(a1.http_method).to eq('GET')
|
|
529
|
+
|
|
530
|
+
expect(a2.short_description).to eq('Get users working in given company')
|
|
531
|
+
expect(a2.path).to eq('/company/:id/users')
|
|
532
|
+
expect(a2.http_method).to eq('GET')
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
it "should be described by valid json" do
|
|
536
|
+
json = Apipie[UsersController, :two_urls].to_json
|
|
537
|
+
expected_hash = {
|
|
538
|
+
:errors => [{:code=>404, :description=>"Missing", :metadata => {:some => "metadata"}},
|
|
539
|
+
{:code=>500, :description=>"Server crashed for some <%= reason %>"}],
|
|
540
|
+
:examples => [],
|
|
541
|
+
:doc_url => "#{Apipie.configuration.doc_base_url}/development/users/two_urls",
|
|
542
|
+
:formats=>["json"],
|
|
543
|
+
:full_description => '',
|
|
544
|
+
:params => [{:full_name=>"oauth",
|
|
545
|
+
:required=>false,
|
|
546
|
+
:allow_nil => false,
|
|
547
|
+
:allow_blank => false,
|
|
548
|
+
:validator=>"Must be a String",
|
|
549
|
+
:description=>"\n<p>Authorization</p>\n",
|
|
550
|
+
:name=>"oauth",
|
|
551
|
+
:show=>true,
|
|
552
|
+
:expected_type=>"string"},
|
|
553
|
+
{:validator=>"Must be a Hash",
|
|
554
|
+
:description=>"\n<p>Deprecated parameter not documented</p>\n",
|
|
555
|
+
:expected_type=>"hash",
|
|
556
|
+
:allow_nil=>false,
|
|
557
|
+
:allow_blank => false,
|
|
558
|
+
:name=>"legacy_param",
|
|
559
|
+
:required=>false,
|
|
560
|
+
:full_name=>"legacy_param",
|
|
561
|
+
:show=>false,
|
|
562
|
+
:params=>
|
|
563
|
+
[{:validator=>"Must be a Hash",
|
|
564
|
+
:description=>"\n<p>Param description for all methods</p>\n",
|
|
565
|
+
:expected_type=>"hash",
|
|
566
|
+
:allow_nil=>false,
|
|
567
|
+
:allow_blank => false,
|
|
568
|
+
:name=>"resource_param",
|
|
569
|
+
:required=>false,
|
|
570
|
+
:full_name=>"resource_param",
|
|
571
|
+
:show=>true,
|
|
572
|
+
:params=>
|
|
573
|
+
[{:required=>true,
|
|
574
|
+
:allow_nil => false,
|
|
575
|
+
:allow_blank => false,
|
|
576
|
+
:validator=>"Must be a String",
|
|
577
|
+
:description=>"\n<p>Username for login</p>\n",
|
|
578
|
+
:name=>"ausername", :full_name=>"resource_param[ausername]",
|
|
579
|
+
:show=>true,
|
|
580
|
+
:expected_type=>"string"},
|
|
581
|
+
{:required=>true,
|
|
582
|
+
:allow_nil => false,
|
|
583
|
+
:allow_blank => false,
|
|
584
|
+
:validator=>"Must be a String",
|
|
585
|
+
:description=>"\n<p>Password for login</p>\n",
|
|
586
|
+
:name=>"apassword", :full_name=>"resource_param[apassword]",
|
|
587
|
+
:show=>true,
|
|
588
|
+
:expected_type=>"string"}
|
|
589
|
+
]}
|
|
590
|
+
]
|
|
591
|
+
},
|
|
592
|
+
{:required=>false, :validator=>"Parameter has to be Integer.",
|
|
593
|
+
:allow_nil => false,
|
|
594
|
+
:allow_blank => false,
|
|
595
|
+
:description=>"\n<p>Company ID</p>\n",
|
|
596
|
+
:name=>"id", :full_name=>"id",
|
|
597
|
+
:show=>true,
|
|
598
|
+
:expected_type=>"numeric"},
|
|
599
|
+
],
|
|
600
|
+
:name => 'two_urls',
|
|
601
|
+
:show => true,
|
|
602
|
+
:apis => [
|
|
603
|
+
{
|
|
604
|
+
:http_method => 'GET',
|
|
605
|
+
:short_description => 'Get company users',
|
|
606
|
+
:api_url => "#{Apipie.api_base_url}/company_users"
|
|
607
|
+
},{
|
|
608
|
+
:http_method => 'GET',
|
|
609
|
+
:short_description => 'Get users working in given company',
|
|
610
|
+
:api_url =>"#{Apipie.api_base_url}/company/:id/users"
|
|
611
|
+
}
|
|
612
|
+
]
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
compare_hashes json, expected_hash
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
describe "examples" do
|
|
621
|
+
|
|
622
|
+
it "should be able to load examples from yml file" do
|
|
623
|
+
expect(Apipie.get_method_description(UsersController, :show).examples).to eq [<<EOS1, <<EOS2].map(&:chomp)
|
|
624
|
+
GET /users/14?verbose=true
|
|
625
|
+
200
|
|
626
|
+
{
|
|
627
|
+
"name": "Test User"
|
|
628
|
+
}
|
|
629
|
+
EOS1
|
|
630
|
+
GET /users/15
|
|
631
|
+
404
|
|
632
|
+
EOS2
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
describe "document" do
|
|
636
|
+
it "should be able to load document from markup file" do
|
|
637
|
+
expect(Apipie.get_method_description(UsersController, :desc_from_file).full_description).to include("description from document")
|
|
638
|
+
end
|
|
639
|
+
end
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
describe "param description" do
|
|
643
|
+
|
|
644
|
+
it "should contain all specified information" do
|
|
645
|
+
a = Apipie.get_method_description(UsersController, :show)
|
|
646
|
+
|
|
647
|
+
param = a.params[:session]
|
|
648
|
+
expect(param.required).to eq(true)
|
|
649
|
+
expect(param.desc).to eq("\n<p>user is logged in</p>\n")
|
|
650
|
+
expect(param.validator.class).to be(Apipie::Validator::TypeValidator)
|
|
651
|
+
expect(param.validator.instance_variable_get("@type")).to eq(String)
|
|
652
|
+
|
|
653
|
+
param = a.params[:id]
|
|
654
|
+
expect(param.required).to eq(true)
|
|
655
|
+
expect(param.desc).to eq("\n<p>user id</p>\n")
|
|
656
|
+
expect(param.validator.class).to be(Apipie::Validator::IntegerValidator)
|
|
657
|
+
expect(param.validator.instance_variable_get("@type")).to eq(Integer)
|
|
658
|
+
|
|
659
|
+
param = a.params[:regexp_param]
|
|
660
|
+
expect(param.desc).to eq("\n<p>regexp param</p>\n")
|
|
661
|
+
expect(param.required).to eq(false)
|
|
662
|
+
expect(param.validator.class).to be(Apipie::Validator::RegexpValidator)
|
|
663
|
+
expect(param.validator.instance_variable_get("@regexp")).to eq(/^[0-9]* years/)
|
|
664
|
+
|
|
665
|
+
param = a.params[:array_param]
|
|
666
|
+
expect(param.desc).to eq("\n<p>array validator</p>\n")
|
|
667
|
+
expect(param.validator.class).to be(Apipie::Validator::EnumValidator)
|
|
668
|
+
expect(param.validator.instance_variable_get("@array")).to eq(["100", "one", "two", "1", "2"])
|
|
669
|
+
|
|
670
|
+
param = a.params[:proc_param]
|
|
671
|
+
expect(param.desc).to eq("\n<p>proc validator</p>\n")
|
|
672
|
+
expect(param.validator.class).to be(Apipie::Validator::ProcValidator)
|
|
673
|
+
|
|
674
|
+
param = a.params[:briefer_dsl]
|
|
675
|
+
expect(param.desc).to eq("\n<p>You dont need :desc => from now</p>\n")
|
|
676
|
+
expect(param.validator.class).to be(Apipie::Validator::TypeValidator)
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
describe "ignored option" do
|
|
682
|
+
class IgnoredController < ApplicationController; end
|
|
683
|
+
|
|
684
|
+
after do
|
|
685
|
+
Apipie.configuration.ignored = %w[]
|
|
686
|
+
end
|
|
687
|
+
|
|
688
|
+
describe "ignored action" do
|
|
689
|
+
before do
|
|
690
|
+
Apipie.configuration.ignored = %w[UsersController#ignore]
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
it "skips the listed actions from the documentation" do
|
|
694
|
+
Apipie.define_method_description(UsersController, :ignore, dsl_data)
|
|
695
|
+
expect(Apipie.get_method_description(UsersController, :ignore)).to be_nil
|
|
696
|
+
|
|
697
|
+
Apipie.define_method_description(UsersController, :dont_ignore, dsl_data)
|
|
698
|
+
expect(Apipie.get_method_description(UsersController, :dont_ignore)).not_to be_nil
|
|
699
|
+
end
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
describe "ignored controller" do
|
|
703
|
+
before do
|
|
704
|
+
Apipie.configuration.ignored = %w[IgnoredController]
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
it "skips the listed controller from the documentation" do
|
|
708
|
+
Apipie.define_method_description(IgnoredController, :ignore, dsl_data)
|
|
709
|
+
expect(Apipie.get_method_description(IgnoredController, :ignore)).to be_nil
|
|
710
|
+
Apipie.define_method_description(IgnoredController, :ignore, dsl_data)
|
|
711
|
+
expect(Apipie.get_method_description(IgnoredController, :ignore)).to be_nil
|
|
712
|
+
end
|
|
713
|
+
end
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
describe "Parameter processing / extraction" do
|
|
717
|
+
before do
|
|
718
|
+
Apipie.configuration.validate = true
|
|
719
|
+
Apipie.configuration.process_params = true
|
|
720
|
+
controllers_dirname = File.expand_path('../dummy/app/controllers', File.dirname(__FILE__))
|
|
721
|
+
Dir.glob("#{controllers_dirname}/**/*") { |file| load(file) if File.file?(file) }
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
it "process correctly the parameters" do
|
|
725
|
+
post :create, :params => {:user => {:name => 'dummy', :pass => 'dummy', :membership => 'standard' }, :facts => {:test => 'test'}}
|
|
726
|
+
|
|
727
|
+
expect(assigns(:api_params).with_indifferent_access).to eq({:user => {:name=>"dummy", :pass=>"dummy", :membership=>"standard"}, :facts => {:test => 'test'}}.with_indifferent_access)
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
it "ignore not described parameters" do
|
|
731
|
+
post :create, :params => {:user => {:name => 'dummy', :pass => 'dummy', :membership => 'standard', :id => 0}}
|
|
732
|
+
|
|
733
|
+
expect(assigns(:api_params).with_indifferent_access).to eq({:user => {:name=>"dummy", :pass=>"dummy", :membership=>"standard"}}.with_indifferent_access)
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
after do
|
|
737
|
+
Apipie.configuration.process_params = false
|
|
738
|
+
end
|
|
739
|
+
end
|
|
740
|
+
end
|