apipie-rails 0.3.6 → 0.5.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +23 -7
  3. data/CHANGELOG.md +147 -2
  4. data/Gemfile +1 -0
  5. data/Gemfile.rails41 +2 -0
  6. data/Gemfile.rails42 +10 -1
  7. data/Gemfile.rails50 +9 -0
  8. data/Gemfile.rails51 +9 -0
  9. data/Gemfile.rails60 +14 -0
  10. data/PROPOSAL_FOR_RESPONSE_DESCRIPTIONS.md +244 -0
  11. data/README.rst +570 -17
  12. data/apipie-rails.gemspec +3 -3
  13. data/app/controllers/apipie/apipies_controller.rb +48 -17
  14. data/app/views/apipie/apipies/_method_detail.erb +21 -0
  15. data/app/views/apipie/apipies/_params.html.erb +4 -2
  16. data/app/views/apipie/apipies/index.html.erb +5 -1
  17. data/app/views/apipie/apipies/resource.html.erb +3 -0
  18. data/app/views/layouts/apipie/apipie.html.erb +1 -1
  19. data/config/locales/en.yml +1 -0
  20. data/config/locales/fr.yml +31 -0
  21. data/config/locales/it.yml +31 -0
  22. data/config/locales/ja.yml +31 -0
  23. data/lib/apipie/apipie_module.rb +22 -4
  24. data/lib/apipie/application.rb +55 -28
  25. data/lib/apipie/configuration.rb +19 -3
  26. data/lib/apipie/core_ext/route.rb +9 -0
  27. data/lib/apipie/dsl_definition.rb +151 -10
  28. data/lib/apipie/error_description.rb +9 -2
  29. data/lib/apipie/errors.rb +34 -0
  30. data/lib/apipie/extractor/collector.rb +4 -0
  31. data/lib/apipie/extractor/recorder.rb +13 -12
  32. data/lib/apipie/extractor/writer.rb +83 -55
  33. data/lib/apipie/extractor.rb +10 -4
  34. data/lib/apipie/method_description.rb +51 -4
  35. data/lib/apipie/param_description.rb +56 -2
  36. data/lib/apipie/resource_description.rb +10 -3
  37. data/lib/apipie/response_description.rb +131 -0
  38. data/lib/apipie/response_description_adapter.rb +200 -0
  39. data/lib/apipie/routes_formatter.rb +1 -1
  40. data/lib/apipie/rspec/response_validation_helper.rb +194 -0
  41. data/lib/apipie/static_dispatcher.rb +3 -2
  42. data/lib/apipie/swagger_generator.rb +708 -0
  43. data/lib/apipie/tag_list_description.rb +11 -0
  44. data/lib/apipie/validator.rb +69 -8
  45. data/lib/apipie/version.rb +1 -1
  46. data/lib/apipie-rails.rb +7 -0
  47. data/lib/tasks/apipie.rake +103 -8
  48. data/spec/controllers/apipies_controller_spec.rb +52 -12
  49. data/spec/controllers/concerns_controller_spec.rb +2 -2
  50. data/spec/controllers/extended_controller_spec.rb +14 -0
  51. data/spec/controllers/memes_controller_spec.rb +10 -0
  52. data/spec/controllers/users_controller_spec.rb +115 -75
  53. data/spec/dummy/app/controllers/application_controller.rb +5 -1
  54. data/spec/dummy/app/controllers/concerns/extending_concern.rb +12 -0
  55. data/spec/dummy/app/controllers/concerns/sample_controller.rb +5 -5
  56. data/spec/dummy/app/controllers/extended_controller.rb +14 -0
  57. data/spec/dummy/app/controllers/pets_controller.rb +408 -0
  58. data/spec/dummy/app/controllers/pets_using_auto_views_controller.rb +73 -0
  59. data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +95 -0
  60. data/spec/dummy/app/controllers/tagged_cats_controller.rb +32 -0
  61. data/spec/dummy/app/controllers/tagged_dogs_controller.rb +15 -0
  62. data/spec/dummy/app/controllers/twitter_example_controller.rb +5 -0
  63. data/spec/dummy/app/controllers/users_controller.rb +19 -11
  64. data/spec/dummy/components/test_engine/Gemfile +6 -0
  65. data/spec/dummy/components/test_engine/app/controllers/test_engine/application_controller.rb +4 -0
  66. data/spec/dummy/components/test_engine/app/controllers/test_engine/memes_controller.rb +37 -0
  67. data/spec/dummy/components/test_engine/config/routes.rb +3 -0
  68. data/spec/dummy/components/test_engine/db/.gitkeep +0 -0
  69. data/spec/dummy/components/test_engine/lib/test_engine.rb +7 -0
  70. data/spec/dummy/components/test_engine/test_engine.gemspec +11 -0
  71. data/spec/dummy/config/application.rb +5 -0
  72. data/spec/dummy/config/environments/development.rb +3 -0
  73. data/spec/dummy/config/environments/production.rb +3 -0
  74. data/spec/dummy/config/environments/test.rb +3 -0
  75. data/spec/dummy/config/initializers/apipie.rb +3 -1
  76. data/spec/dummy/config/routes.rb +24 -1
  77. data/spec/lib/extractor/writer_spec.rb +32 -4
  78. data/spec/lib/file_handler_spec.rb +18 -0
  79. data/spec/lib/method_description_spec.rb +34 -0
  80. data/spec/lib/swagger/openapi_2_0_schema.json +1607 -0
  81. data/spec/lib/swagger/rake_swagger_spec.rb +139 -0
  82. data/spec/lib/swagger/response_validation_spec.rb +104 -0
  83. data/spec/lib/swagger/swagger_dsl_spec.rb +658 -0
  84. data/spec/lib/validator_spec.rb +58 -0
  85. data/spec/lib/validators/array_validator_spec.rb +28 -8
  86. data/spec/spec_helper.rb +68 -0
  87. metadata +75 -23
  88. data/Gemfile +0 -7
  89. data/Gemfile.rails32 +0 -6
  90. data/Gemfile.rails40 +0 -5
  91. data/lib/apipie/client/generator.rb +0 -135
@@ -0,0 +1,658 @@
1
+ require 'spec_helper'
2
+ require 'rack/utils'
3
+ require 'rspec/expectations'
4
+
5
+ describe "Swagger Responses" do
6
+ let(:desc) { Apipie.get_resource_description(controller_class, Apipie.configuration.default_version) }
7
+
8
+ let(:swagger) {
9
+ Apipie.configuration.swagger_suppress_warnings = true
10
+ Apipie.to_swagger_json(Apipie.configuration.default_version, controller_class.to_s.underscore.sub("_controller", ""))
11
+ }
12
+
13
+ let(:controller_class ) { described_class }
14
+
15
+ def get_ref(ref)
16
+ name = ref.split('#/definitions/')[1].to_sym
17
+ swagger[:definitions][name]
18
+ end
19
+
20
+ def resolve_refs(schema)
21
+ if schema['$ref']
22
+ return get_ref(schema['$ref'])
23
+ end
24
+ schema
25
+ end
26
+
27
+ def swagger_response_for(path, code=200, method='get')
28
+ response = swagger[:paths][path][method][:responses][code]
29
+ response[:schema] = resolve_refs(response[:schema])
30
+ response
31
+ end
32
+
33
+ def swagger_params_for(path, method='get')
34
+ swagger[:paths][path][method][:parameters]
35
+ end
36
+
37
+ def swagger_param_by_name(param_name, path, method='get')
38
+ params = swagger_params_for(path, method)
39
+ matching = params.select{|p| p[:name] == param_name }
40
+ raise "multiple params named [#{param_name}] in swagger definition for [#{method } #{path}]" if matching.length > 1
41
+
42
+ nil if matching.length == 0
43
+
44
+ matching[0]
45
+ end
46
+
47
+
48
+
49
+
50
+ #
51
+ # Matcher to validate the hierarchy of fields described in an internal 'returns' object (without checking their type)
52
+ #
53
+ # For example, code such as:
54
+ # returns_obj = Apipie.get_resource_description(...)._methods.returns.detect{|e| e.code=200})
55
+ # expect(returns_obj).to match_param_structure([:pet_name, :animal_type, :pet_measurements => [:weight, :height]])
56
+ #
57
+ # will verify that the payload structure described for the response of return code 200 is:
58
+ # {
59
+ # "pet_name": <any>,
60
+ # "animal_type": <any>,
61
+ # "pet_measurements": {
62
+ # "weight": <any>,
63
+ # "height": <any>
64
+ # }
65
+ # }
66
+ #
67
+ #
68
+ RSpec::Matchers.define :match_field_structure do |expected|
69
+ @last_message = nil
70
+
71
+ match do |actual|
72
+ deep_match?(actual, expected)
73
+ end
74
+
75
+ def deep_match?(actual, expected, breadcrumb=[])
76
+ pending_params = actual.params_ordered.dup
77
+ expected.each do |expected_param|
78
+ expected_param_name = expected_param.is_a?(Hash) ? expected_param.keys.first : expected_param
79
+ actual_param = pending_params.find { |param| param.name.to_s == expected_param_name.to_s }
80
+ unless actual_param
81
+ @fail_message = "Couldn't find #{expected_param_name.inspect} among #{pending_params.map(&:name)} in #{breadcrumb.join('.')}"
82
+ return false
83
+ else
84
+ pending_params.delete_if { |p| p.object_id == actual_param.object_id }
85
+ end
86
+
87
+ return false unless fields_match?(actual_param, expected_param_name, breadcrumb)
88
+ if expected_param.is_a? Hash
89
+ return false unless deep_match?(actual_param.validator, expected_param.values[0], breadcrumb + [expected_param.keys.first])
90
+ end
91
+ end
92
+
93
+ unless pending_params.empty?
94
+ @fail_message = "Unexpected properties #{pending_params.map(&:name)} in #{breadcrumb.join('.')}"
95
+ return false
96
+ end
97
+ true
98
+ end
99
+
100
+ def fields_match?(param, expected_name, breadcrumb)
101
+ return false unless have_field?(param, expected_name, breadcrumb)
102
+ @fail_message = "expected #{(breadcrumb + [param.name]).join('.')} to eq #{(breadcrumb + [expected_name]).join('.')}"
103
+ param.name.to_s == expected_name.to_s
104
+ end
105
+
106
+ def have_field?(field, expected_name, breadcrumb)
107
+ @fail_message = "expected property #{(breadcrumb+[expected_name]).join('.')}"
108
+ !field.nil?
109
+ end
110
+
111
+ failure_message do |actual|
112
+ @fail_message
113
+ end
114
+ end
115
+
116
+
117
+ describe PetsController do
118
+
119
+
120
+ describe "PetsController#index" do
121
+ subject do
122
+ desc._methods[:index]
123
+ end
124
+
125
+ it "should return code 200 with array of entries of the format {'pet_name', 'animal_type'}" do
126
+ returns_obj = subject.returns.detect{|e| e.code == 200 }
127
+
128
+ puts returns_obj.to_json
129
+ expect(returns_obj.code).to eq(200)
130
+ expect(returns_obj.is_array?).to eq(true)
131
+
132
+ expect(returns_obj).to match_field_structure([:pet_name, :animal_type])
133
+ end
134
+
135
+ it 'should have the response described in the swagger' do
136
+ response = swagger_response_for('/pets')
137
+ expect(response[:description]).to eq("list of pets")
138
+
139
+ schema = response[:schema]
140
+ expect(schema[:type]).to eq("array")
141
+
142
+ a_schema = resolve_refs(schema[:items])
143
+ expect(a_schema).to have_field(:pet_name, 'string', {:description => 'Name of pet', :required => false})
144
+ expect(a_schema).to have_field(:animal_type, 'string', {:description => 'Type of pet', :enum => ['dog','cat','iguana','kangaroo']})
145
+ end
146
+
147
+
148
+ it "should return code 401 with a String description field" do
149
+ returns_obj = subject.returns.detect{|e| e.code == 404 }
150
+
151
+ expect(returns_obj.code).to eq(404)
152
+ expect(returns_obj.is_array?).to eq(false)
153
+
154
+ expect(returns_obj).to match_field_structure([:error_message])
155
+ end
156
+
157
+
158
+ it "should return code 401 with a :reason field (defined in the superclass)" do
159
+ returns_obj = subject.returns.detect{|e| e.code == 401 }
160
+
161
+ expect(returns_obj.code).to eq(401)
162
+ expect(returns_obj.is_array?).to eq(false)
163
+
164
+ expect(returns_obj).to match_field_structure([:reason])
165
+ end
166
+
167
+ it 'should have the 404 response described in the swagger' do
168
+ response = swagger_response_for('/pets', 404)
169
+ expect(response[:description]).to eq("Not Found")
170
+
171
+ schema = response[:schema]
172
+ expect(schema[:type]).to eq("object")
173
+
174
+ expect(schema).to have_field(:error_message, 'string', {:description => 'description of the error', :required => true})
175
+ end
176
+
177
+ end
178
+
179
+ describe "PetsController#show_plain_response_with_tags" do
180
+ subject do
181
+ desc._methods[:show_plain_response_with_tags]
182
+ end
183
+
184
+ it "should return tags with 'Dogs', 'Cats', and 'LivingBeings'" do
185
+ returns_obj = subject.tag_list
186
+ puts returns_obj.inspect
187
+
188
+ expect(returns_obj.tags).to eq(%w[Dogs Cats LivingBeings])
189
+ end
190
+ end
191
+
192
+ describe "PetsController#show_as_properties" do
193
+ subject do
194
+ desc._methods[:show_as_properties]
195
+ end
196
+
197
+ it "should return code 200 with 'pet_name' and 'animal_type'" do
198
+ returns_obj = subject.returns.detect{|e| e.code == 200 }
199
+
200
+ puts returns_obj.to_json
201
+ expect(returns_obj.code).to eq(200)
202
+ expect(returns_obj.is_array?).to eq(false)
203
+
204
+ expect(returns_obj).to match_field_structure([:pet_name, :animal_type])
205
+ end
206
+
207
+ it 'should have the response described in the swagger' do
208
+ response = swagger_response_for('/pets/{id}/as_properties')
209
+ expect(response[:description]).to eq("OK")
210
+
211
+ schema = response[:schema]
212
+ expect(schema).to have_field(:pet_name, 'string', {:description => 'Name of pet', :required => false})
213
+ expect(schema).to have_field(:animal_type, 'string', {:description => 'Type of pet', :enum => ['dog','cat','iguana','kangaroo']})
214
+ end
215
+
216
+ it 'should have the 404 response description overridden' do
217
+ returns_obj = subject.returns.detect{|e| e.code == 404 }
218
+
219
+ # puts returns_obj.to_json
220
+ expect(returns_obj.code).to eq(404)
221
+ expect(returns_obj.is_array?).to eq(false)
222
+
223
+ expect(returns_obj).to match_field_structure([:another_error_message])
224
+ end
225
+ end
226
+
227
+ describe "PetsController#show_as_param_group_of_properties" do
228
+ subject do
229
+ desc._methods[:show_as_param_group_of_properties]
230
+ end
231
+
232
+ it "should return code 200 with 'pet_name' and 'animal_type'" do
233
+ returns_obj = subject.returns.detect{|e| e.code == 200 }
234
+
235
+ puts returns_obj.to_json
236
+ expect(returns_obj.code).to eq(200)
237
+ expect(returns_obj.is_array?).to eq(false)
238
+
239
+ expect(returns_obj).to match_field_structure([:pet_name, :animal_type])
240
+ expect(returns_obj.params_ordered[0].is_required?).to be_falsey
241
+ expect(returns_obj.params_ordered[1].is_required?).to be_truthy
242
+ end
243
+
244
+ it 'should have the response described in the swagger' do
245
+ response = swagger_response_for('/pets/{id}/as_param_group_of_properties')
246
+ expect(response[:description]).to eq("The pet")
247
+
248
+ schema = response[:schema]
249
+ expect(schema).to have_field(:pet_name, 'string', {:description => 'Name of pet', :required => false})
250
+ expect(schema).to have_field(:animal_type, 'string', {:description => 'Type of pet', :enum => ['dog','cat','iguana','kangaroo']})
251
+ end
252
+ end
253
+
254
+ describe "PetsController#show_pet_by_id" do
255
+ subject do
256
+ desc._methods[:show_pet_by_id]
257
+ end
258
+
259
+ it "should have only oauth (from ApplicationController), common_param (from resource) and pet_id as an input parameters" do
260
+ params_obj = subject.params_ordered
261
+
262
+ expect(params_obj[0].name).to eq(:oauth)
263
+ expect(params_obj[1].name).to eq(:common_param)
264
+ expect(params_obj[2].name).to eq(:pet_id)
265
+ end
266
+
267
+ it "should return code 200 with 'pet_id', pet_name' and 'animal_type'" do
268
+ returns_obj = subject.returns.detect{|e| e.code == 200 }
269
+
270
+ puts returns_obj.to_json
271
+ expect(returns_obj.code).to eq(200)
272
+ expect(returns_obj.is_array?).to eq(false)
273
+
274
+ # note that the response is expected NOT to return the parameters marked ':only_in => :request'
275
+ expect(returns_obj).to match_field_structure([:pet_id, :pet_name, :animal_type])
276
+ end
277
+
278
+ it 'should have the response described in the swagger' do
279
+ response = swagger_response_for('/pets/pet_by_id')
280
+ expect(response[:description]).to eq("OK")
281
+
282
+ schema = response[:schema]
283
+ expect(schema).to have_field(:pet_id, 'number', {:description => 'id of pet'})
284
+ expect(schema).to have_field(:pet_name, 'string', {:description => 'Name of pet', :required => false})
285
+ expect(schema).to have_field(:animal_type, 'string', {:description => 'Type of pet', :enum => ['dog','cat','iguana','kangaroo']})
286
+ expect(schema).not_to have_field(:partial_match_allowed, 'boolean', {:required => false})
287
+ end
288
+
289
+ it "creates a swagger definition with all input parameters" do
290
+ # a parameter defined for this method
291
+ expect(swagger_param_by_name(:pet_id, '/pets/pet_by_id')[:type]).to eq('number')
292
+
293
+ # a parameter defined for the resource
294
+ expect(swagger_param_by_name(:common_param, '/pets/pet_by_id')[:type]).to eq('number')
295
+
296
+ # a parameter defined in the controller's superclass
297
+ expect(swagger_param_by_name(:oauth, '/pets/pet_by_id')[:type]).to eq('string')
298
+ end
299
+
300
+ end
301
+
302
+ describe "PetsController#get_vote_by_owner_name" do
303
+ subject do
304
+ desc._methods[:get_vote_by_owner_name]
305
+ end
306
+
307
+ it "should return code 200 with 'owner_name' and 'vote'" do
308
+ returns_obj = subject.returns.detect{|e| e.code == 200 }
309
+
310
+ puts returns_obj.to_json
311
+ expect(returns_obj.code).to eq(200)
312
+ expect(returns_obj.is_array?).to eq(false)
313
+
314
+ expect(returns_obj).to match_field_structure([:owner_name, :vote])
315
+ end
316
+
317
+ it 'should have the response described in the swagger' do
318
+ response = swagger_response_for('/pets/by_owner_name/did_vote')
319
+ expect(response[:description]).to eq("OK")
320
+
321
+ schema = response[:schema]
322
+ expect(schema).to have_field(:owner_name, 'string', {:required => false}) # optional because defined using 'param', not 'property'
323
+ expect(schema).to have_field(:vote, 'boolean')
324
+ end
325
+ end
326
+
327
+ describe "PetsController#show_extra_info" do
328
+ subject do
329
+ desc._methods[:show_extra_info]
330
+ end
331
+
332
+ it "should return code 201 with 'pet_name' and 'animal_type'" do
333
+ returns_obj = subject.returns.detect{|e| e.code == 201 }
334
+
335
+ puts returns_obj.to_json
336
+ expect(returns_obj.code).to eq(201)
337
+ expect(returns_obj.is_array?).to eq(false)
338
+
339
+ expect(returns_obj).to match_field_structure([:pet_name, :animal_type])
340
+ end
341
+ it 'should have the 201 response described in the swagger' do
342
+ response = swagger_response_for('/pets/{id}/extra_info', 201)
343
+ expect(response[:description]).to eq("Found a pet")
344
+
345
+ schema = response[:schema]
346
+ expect(schema).to have_field(:pet_name, 'string', {:required => false})
347
+ expect(schema).to have_field(:animal_type, 'string')
348
+ end
349
+
350
+ it "should return code 202 with spread out 'pet' and encapsulated 'pet_measurements'" do
351
+ returns_obj = subject.returns.detect{|e| e.code == 202 }
352
+
353
+ puts returns_obj.to_json
354
+ expect(returns_obj.code).to eq(202)
355
+ expect(returns_obj.is_array?).to eq(false)
356
+
357
+ expect(returns_obj).to match_field_structure([:pet_name,
358
+ :animal_type,
359
+ {:pet_measurements => [:weight, :height, :num_legs]}
360
+ ])
361
+ end
362
+ it 'should have the 202 response described in the swagger' do
363
+ response = swagger_response_for('/pets/{id}/extra_info', 202)
364
+ expect(response[:description]).to eq('Accepted')
365
+
366
+ schema = response[:schema]
367
+ expect(schema).to have_field(:pet_name, 'string', {:required => false})
368
+ expect(schema).to have_field(:animal_type, 'string')
369
+ expect(schema).to have_field(:pet_measurements, 'object')
370
+
371
+ pm_schema = schema[:properties][:pet_measurements]
372
+ expect(pm_schema).to have_field(:weight, 'number', {:description => "Weight in pounds"})
373
+ expect(pm_schema).to have_field(:height, 'number', {:description => "Height in inches"})
374
+ expect(pm_schema).to have_field(:num_legs, 'number', {:description => "Number of legs", :required => false})
375
+ end
376
+
377
+ it "should return code 203 with spread out 'pet', encapsulated 'pet_measurements' and encapsulated 'pet_history'" do
378
+ returns_obj = subject.returns.detect{|e| e.code == 203 }
379
+
380
+ puts returns_obj.to_json
381
+ expect(returns_obj.code).to eq(203)
382
+ expect(returns_obj.is_array?).to eq(false)
383
+
384
+ expect(returns_obj).to match_field_structure([:pet_name,
385
+ :animal_type,
386
+ {:pet_measurements => [:weight, :height,:num_legs]},
387
+ {:pet_history => [:did_visit_vet, :avg_meals_per_day]},
388
+ {:additional_histories => [:did_visit_vet, :avg_meals_per_day]}
389
+ ])
390
+ end
391
+ it 'should have the 203 response described in the swagger' do
392
+ response = swagger_response_for('/pets/{id}/extra_info', 203)
393
+ expect(response[:description]).to eq('Non-Authoritative Information')
394
+
395
+ schema = response[:schema]
396
+ expect(schema).to have_field(:pet_name, 'string', {:required => false})
397
+ expect(schema).to have_field(:animal_type, 'string')
398
+ expect(schema).to have_field(:pet_measurements, 'object')
399
+ expect(schema).to have_field(:pet_history, 'object')
400
+ expect(schema).to have_field(:additional_histories, 'array')
401
+
402
+ pm_schema = schema[:properties][:pet_measurements]
403
+ expect(pm_schema).to have_field(:weight, 'number', {:description => "Weight in pounds"})
404
+ expect(pm_schema).to have_field(:height, 'number', {:description => "Height in inches"})
405
+ expect(pm_schema).to have_field(:num_legs, 'number', {:description => "Number of legs", :required => false})
406
+
407
+ ph_schema = schema[:properties][:pet_history]
408
+ expect(ph_schema).to have_field(:did_visit_vet, 'boolean')
409
+ expect(ph_schema).to have_field(:avg_meals_per_day, 'number')
410
+
411
+ pa_schema = schema[:properties][:additional_histories]
412
+ expect(pa_schema[:type]).to eq('array')
413
+ pai_schema = schema[:properties][:additional_histories][:items]
414
+ expect(pai_schema).to have_field(:did_visit_vet, 'boolean')
415
+ expect(pai_schema).to have_field(:avg_meals_per_day, 'number')
416
+ end
417
+
418
+ it "should return code 204 with array of integer" do
419
+ returns_obj = subject.returns.detect{|e| e.code == 204 }
420
+
421
+ puts returns_obj.to_json
422
+ expect(returns_obj.code).to eq(204)
423
+ expect(returns_obj.is_array?).to eq(false)
424
+
425
+ expect(returns_obj).to match_field_structure([:int_array, :enum_array])
426
+ end
427
+ it 'should have the 204 response described in the swagger' do
428
+ response = swagger_response_for('/pets/{id}/extra_info', 204)
429
+
430
+ schema = response[:schema]
431
+ expect(schema).to have_field(:int_array, 'array', {items: {type: 'number'}})
432
+ expect(schema).to have_field(:enum_array, 'array', {items: {type: 'string', enum: ['v1','v2','v3']}})
433
+ end
434
+
435
+
436
+ it "should return code matching :unprocessable_entity (422) with spread out 'pet' and 'num_fleas'" do
437
+ returns_obj = subject.returns.detect{|e| e.code == 422 }
438
+
439
+ puts returns_obj.to_json
440
+ expect(returns_obj.code).to eq(422)
441
+
442
+ expect(returns_obj).to match_field_structure([:pet_name,
443
+ :animal_type,
444
+ :num_fleas
445
+ ])
446
+ end
447
+ it 'should have the 422 response described in the swagger' do
448
+ response = swagger_response_for('/pets/{id}/extra_info', 422)
449
+ expect(response[:description]).to eq('Fleas were discovered on the pet')
450
+
451
+ schema = response[:schema]
452
+ expect(schema).to have_field(:pet_name, 'string', {:required => false})
453
+ expect(schema).to have_field(:animal_type, 'string')
454
+ expect(schema).to have_field(:num_fleas, 'number')
455
+ end
456
+
457
+ end
458
+
459
+ end
460
+
461
+ #==============================================================================
462
+ # TaggedDogsController is a demonstration of how tags may be defined in a simple
463
+ # controller class without defining either the controller resource-description
464
+ # block or the controller's superclass's resource-description block.
465
+ #==============================================================================
466
+
467
+ describe TaggedDogsController do
468
+ describe "TaggedDogsController#show_as_properties" do
469
+ subject do
470
+ desc._methods[:show_as_properties]
471
+ end
472
+
473
+ it "should return tags with 'Dogs', and 'Wolves'" do
474
+ returns_obj = subject.tag_list
475
+ puts returns_obj.inspect
476
+
477
+ expect(returns_obj.tags).to eq(%w[Dogs Wolves])
478
+ end
479
+ end
480
+ end
481
+
482
+ #==============================================================================
483
+ # TaggedCatsController is a demonstration of how tags may be defined in the
484
+ # controller's resource description so that they may be automatically prefixed
485
+ # to a particular operation's tags.
486
+ #==============================================================================
487
+
488
+ describe TaggedCatsController do
489
+ describe "TaggedCatsController#show_as_properties" do
490
+ subject do
491
+ desc._methods[:show_as_properties]
492
+ end
493
+
494
+ it "should return tags with 'Dogs', 'Pets', and 'Animals'" do
495
+ returns_obj = subject.tag_list
496
+ puts returns_obj.inspect
497
+
498
+ expect(returns_obj.tags).to eq(%w[Dogs Pets Animals])
499
+ end
500
+ end
501
+
502
+ describe "TaggedCatsController#show_as_same_properties" do
503
+ subject do
504
+ desc._methods[:show_as_same_properties]
505
+ end
506
+
507
+ it "should return tags with 'Dogs', 'Pets', 'Puma', and 'Animals'" do
508
+ returns_obj = subject.tag_list
509
+ puts returns_obj.inspect
510
+
511
+ expect(returns_obj.tags).to eq(%w[Dogs Pets Puma Animals])
512
+ end
513
+ end
514
+ end
515
+
516
+ #==============================================================================
517
+ # PetsUsingSelfDescribingClassesController is a demonstration of how
518
+ # responses can be described using manual generation of a property description
519
+ # array
520
+ #==============================================================================
521
+
522
+
523
+ describe PetsUsingSelfDescribingClassesController do
524
+
525
+ describe "PetsController#pets_described_as_class" do
526
+ subject do
527
+ desc._methods[:pets_described_as_class]
528
+ end
529
+
530
+ it "should return code 200 with array of entries of the format {'pet_name', 'animal_type'}" do
531
+ returns_obj = subject.returns.detect{|e| e.code == 200 }
532
+
533
+ puts returns_obj.to_json
534
+ expect(returns_obj.code).to eq(200)
535
+ expect(returns_obj.is_array?).to eq(true)
536
+
537
+ expect(returns_obj).to match_field_structure([:pet_name, :animal_type])
538
+ end
539
+
540
+ it 'should have the response described in the swagger' do
541
+ response = swagger_response_for('/pets_described_as_class')
542
+ expect(response[:description]).to eq("list of pets")
543
+
544
+ schema = response[:schema]
545
+ expect(schema[:type]).to eq("array")
546
+
547
+ a_schema = schema[:items]
548
+ expect(a_schema).to have_field(:pet_name, 'string', {:description => 'Name of pet', :required => false})
549
+ expect(a_schema).to have_field(:animal_type, 'string', {:description => 'Type of pet', :enum => ['dog','cat','iguana','kangaroo']})
550
+ end
551
+ end
552
+
553
+
554
+ describe "PetsController#pets_with_measurements_described_as_class" do
555
+ subject do
556
+ desc._methods[:pets_with_measurements_described_as_class]
557
+ end
558
+
559
+ it "should return code 200 with spread out 'pet' and encapsulated 'pet_measurements'" do
560
+ returns_obj = subject.returns.detect{|e| e.code == 200 }
561
+
562
+ puts returns_obj.to_json
563
+ expect(returns_obj.code).to eq(200)
564
+ expect(returns_obj.is_array?).to eq(false)
565
+
566
+ expect(returns_obj).to match_field_structure([:pet_name,
567
+ :animal_type,
568
+ {:pet_measurements => [:weight, :height, :num_legs]}
569
+ ])
570
+ end
571
+ it 'should have the 200 response described in the swagger' do
572
+ response = swagger_response_for('/pets_with_measurements_described_as_class/{id}', 200)
573
+ expect(response[:description]).to eq('measurements of the pet')
574
+
575
+ schema = response[:schema]
576
+ expect(schema).to have_field(:pet_name, 'string', {:required => false})
577
+ expect(schema).to have_field(:animal_type, 'string')
578
+ expect(schema).to have_field(:pet_measurements, 'object')
579
+
580
+ pm_schema = schema[:properties][:pet_measurements]
581
+ expect(pm_schema).to have_field(:weight, 'number', {:description => "Weight in pounds"})
582
+ expect(pm_schema).to have_field(:height, 'number', {:description => "Height in inches"})
583
+ expect(pm_schema).to have_field(:num_legs, 'number', {:description => "Number of legs", :required => false})
584
+ end
585
+ end
586
+
587
+ describe "PetsController#pets_with_many_measurements_as_class" do
588
+ subject do
589
+ desc._methods[:pets_with_many_measurements_as_class]
590
+ end
591
+
592
+ it "should return code 200 with pet_name (string) and many_pet_measurements (array of objects)" do
593
+ returns_obj = subject.returns.detect{|e| e.code == 200 }
594
+
595
+ puts returns_obj.to_json
596
+ expect(returns_obj.code).to eq(200)
597
+ expect(returns_obj.is_array?).to eq(false)
598
+
599
+ expect(returns_obj).to match_field_structure([:pet_name,
600
+ {:many_pet_measurements => [:weight, :height]}
601
+ ])
602
+ end
603
+
604
+
605
+ it 'should have the 200 response described in the swagger' do
606
+ response = swagger_response_for('/pets_with_many_measurements_as_class/{id}', 200)
607
+ expect(response[:description]).to eq('measurements of the pet')
608
+
609
+ schema = response[:schema]
610
+ expect(schema).to have_field(:pet_name, 'string', {:required => false})
611
+ expect(schema).to have_field(:many_pet_measurements, 'array')
612
+
613
+ pm_schema = schema[:properties][:many_pet_measurements][:items]
614
+ expect(pm_schema).to have_field(:weight, 'number', {:description => "Weight in pounds"})
615
+ expect(pm_schema).to have_field(:height, 'number', {:description => "Height in inches"})
616
+ end
617
+ end
618
+
619
+ end
620
+
621
+
622
+ #=========================================================
623
+ # PetsUsingAutoViewsController is a demonstration of how
624
+ # responses can be described using logic
625
+ #=========================================================
626
+
627
+ describe PetsUsingAutoViewsController do
628
+
629
+ describe "PetsController#pet_described_using_automated_view" do
630
+ subject do
631
+ desc._methods[:pet_described_using_automated_view]
632
+ end
633
+
634
+ it "should return code 200 with array of entries of the format {'pet_name', 'animal_type'}" do
635
+ returns_obj = subject.returns.detect{|e| e.code == 200 }
636
+
637
+ expect(returns_obj.code).to eq(200)
638
+ expect(returns_obj.is_array?).to eq(false)
639
+
640
+ expect(returns_obj).to match_field_structure([:pet_name, :animal_type, :age])
641
+ end
642
+
643
+ it 'should have the response described in the swagger' do
644
+ response = swagger_response_for('/pet_described_using_automated_view/{id}')
645
+ expect(response[:description]).to eq("like Pet, but different")
646
+
647
+ schema = response[:schema]
648
+ expect(schema[:type]).to eq("object")
649
+
650
+ expect(schema).to have_field(:pet_name, 'string', {:required => true})
651
+ expect(schema).to have_field(:animal_type, 'string', {:required => true})
652
+ expect(schema).to have_field(:age, 'number', {:required => true})
653
+ end
654
+ end
655
+ end
656
+
657
+
658
+ end