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,139 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require "json-schema"
|
|
3
|
+
|
|
4
|
+
require File.expand_path("../../../dummy/app/controllers/twitter_example_controller.rb", __FILE__)
|
|
5
|
+
require File.expand_path("../../../dummy/app/controllers/users_controller.rb", __FILE__)
|
|
6
|
+
require File.expand_path("../../../dummy/app/controllers/pets_controller.rb", __FILE__)
|
|
7
|
+
|
|
8
|
+
describe 'rake tasks' do
|
|
9
|
+
include_context "rake"
|
|
10
|
+
|
|
11
|
+
let(:doc_path) { "user_specified_doc_path" }
|
|
12
|
+
|
|
13
|
+
before do
|
|
14
|
+
Apipie.configuration.doc_path = doc_path
|
|
15
|
+
Apipie.configuration.swagger_suppress_warnings = true
|
|
16
|
+
allow(Apipie).to receive(:reload_documentation)
|
|
17
|
+
subject.invoke(*task_args)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe 'static swagger specification files' do
|
|
21
|
+
|
|
22
|
+
after do
|
|
23
|
+
Dir["#{doc_output}*"].each { |static_file| FileUtils.rm_rf(static_file) }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
let(:swagger_schema) do
|
|
27
|
+
File.read(File.join(File.dirname(__FILE__),"openapi_2_0_schema.json"))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
let(:apidoc_swagger_json) do
|
|
31
|
+
# note: the filename ends with '_tmp' because this suffix is passed as a parameter to the rake task
|
|
32
|
+
File.read("#{doc_output}/schema_swagger_tmp.json")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
let(:apidoc_swagger) do
|
|
36
|
+
JSON.parse(apidoc_swagger_json)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
let(:doc_output) do
|
|
40
|
+
File.join(::Rails.root, doc_path, 'apidoc')
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
let(:ref_output) do
|
|
44
|
+
File.join(::Rails.root, doc_path, 'apidoc_ref')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def expect_param_def(http_method, path, param_name, field, value)
|
|
49
|
+
params = apidoc_swagger["paths"][path][http_method]["parameters"]
|
|
50
|
+
param = params.select {|p| p if p["name"]==param_name}[0]
|
|
51
|
+
expect(param[field]).to eq(value)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def expect_tags_def(http_method, path, value)
|
|
55
|
+
params = apidoc_swagger["paths"][path][http_method]["tags"]
|
|
56
|
+
expect(params).to eq(value)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def body_param_def(http_method, path, param_name)
|
|
60
|
+
params = apidoc_swagger["paths"][path][http_method]["parameters"]
|
|
61
|
+
body = params.select {|p| p if p["name"]=="body"}[0]
|
|
62
|
+
schema_properties = body["schema"]["properties"]
|
|
63
|
+
# print JSON.pretty_generate(schema_properties)
|
|
64
|
+
param = (schema_properties.select {|k,v| v if k == param_name })[param_name]
|
|
65
|
+
# print JSON.pretty_generate(param)
|
|
66
|
+
param
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def expect_body_param_def(http_method, path, param_name, field, value)
|
|
70
|
+
param = body_param_def(http_method, path, param_name)
|
|
71
|
+
expect(param[field]).to eq(value)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
describe 'apipie:static_swagger_json[development,json,_tmp]' do
|
|
76
|
+
it "generates static swagger files for the default version of apipie docs" do
|
|
77
|
+
# print apidoc_swagger_json
|
|
78
|
+
|
|
79
|
+
expect(apidoc_swagger["info"]["title"]).to eq("Test app (params in:body)")
|
|
80
|
+
expect(apidoc_swagger["info"]["version"]).to eq("#{Apipie.configuration.default_version}")
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "includes expected values in the generated swagger file" do
|
|
84
|
+
expect_param_def("get", "/twitter_example/{id}", "screen_name", "in", "query")
|
|
85
|
+
expect_param_def("put", "/users/{id}", "id", "in", "path")
|
|
86
|
+
expect_body_param_def("put", "/users/{id}", "oauth", "type", "string")
|
|
87
|
+
expect_body_param_def("put", "/users/{id}", "user", "type", "object")
|
|
88
|
+
|
|
89
|
+
user = body_param_def("put", "/users/{id}", "user")
|
|
90
|
+
expect(user["properties"]["name"]["type"]).to eq("string")
|
|
91
|
+
|
|
92
|
+
expect_param_def("get", "/users/by_department", "department", "in", "query")
|
|
93
|
+
expect_param_def("get", "/users/by_department", "department", "enum",
|
|
94
|
+
["finance", "operations", "sales", "marketing", "HR"])
|
|
95
|
+
|
|
96
|
+
expect_tags_def("get", "/twitter_example/{id}/followers", %w[twitter_example following index search])
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "generates a valid swagger file" do
|
|
100
|
+
# print apidoc_swagger_json
|
|
101
|
+
expect(JSON::Validator.validate(swagger_schema, apidoc_swagger_json)).to be_truthy
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
describe 'apipie:static_swagger_json[development,form_data,_tmp]' do
|
|
106
|
+
it "generates static swagger files for the default version of apipie docs" do
|
|
107
|
+
# print apidoc_swagger_json
|
|
108
|
+
|
|
109
|
+
expect(apidoc_swagger["info"]["title"]).to eq("Test app (params in:formData)")
|
|
110
|
+
expect(apidoc_swagger["info"]["version"]).to eq("#{Apipie.configuration.default_version}")
|
|
111
|
+
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "includes expected values in the generated swagger file" do
|
|
115
|
+
expect_param_def("get", "/twitter_example/{id}", "screen_name", "in", "query")
|
|
116
|
+
expect_param_def("put", "/users/{id}", "id", "in", "path")
|
|
117
|
+
expect_param_def("put", "/users/{id}", "oauth", "in", "formData")
|
|
118
|
+
expect_param_def("get", "/users/by_department", "department", "in", "query")
|
|
119
|
+
expect_param_def("get", "/users/by_department", "department", "enum",
|
|
120
|
+
["finance", "operations", "sales", "marketing", "HR"])
|
|
121
|
+
|
|
122
|
+
expect_tags_def("get", "/twitter_example/{id}/followers", %w[twitter_example following index search])
|
|
123
|
+
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "generates a valid swagger file" do
|
|
127
|
+
# print apidoc_swagger_json
|
|
128
|
+
expect(JSON::Validator.validate(swagger_schema, apidoc_swagger_json)).to be_truthy
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
describe 'apipie:did_swagger_change[development,form_data,_tmp]' do
|
|
133
|
+
it "keeps a reference file" do
|
|
134
|
+
expect(Pathname(ref_output).children.count).to eq(2) # one file for each language
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'rack/utils'
|
|
3
|
+
require 'rspec/expectations'
|
|
4
|
+
require 'apipie/rspec/response_validation_helper'
|
|
5
|
+
require "json-schema"
|
|
6
|
+
|
|
7
|
+
RSpec.describe PetsController, :type => :controller do
|
|
8
|
+
before :each do
|
|
9
|
+
Apipie.configuration.swagger_allow_additional_properties_in_response = false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "does not raise error when rendered output matches the described response" do
|
|
13
|
+
response = get :return_and_validate_expected_response, {format: :json}
|
|
14
|
+
expect(response).to match_declared_responses
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "does not raise error when rendered output (array) matches the described response" do
|
|
18
|
+
response = get :return_and_validate_expected_array_response, {format: :json}
|
|
19
|
+
expect(response).to match_declared_responses
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "does not raises error when rendered output includes null in the response" do
|
|
23
|
+
response = get :return_and_validate_expected_response_with_null, {format: :json}
|
|
24
|
+
expect(response).to match_declared_responses
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "does not raise error when rendered output includes null (instead of an object) in the response" do
|
|
28
|
+
response = get :return_and_validate_expected_response_with_null_object, {format: :json}
|
|
29
|
+
expect(response).to match_declared_responses
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "raises error when a response field has the wrong type" do
|
|
33
|
+
response = get :return_and_validate_type_mismatch, {format: :json}
|
|
34
|
+
expect(response).not_to match_declared_responses
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "raises error when a response has a missing field" do
|
|
38
|
+
response = get :return_and_validate_missing_field, {format: :json}
|
|
39
|
+
expect(response).not_to match_declared_responses
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "raises error when a response has an extra property and 'swagger_allow_additional_properties_in_response' is false" do
|
|
43
|
+
response = get :return_and_validate_extra_property, {format: :json}
|
|
44
|
+
expect(response).not_to match_declared_responses
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "raises error when a response has is array instead of object" do
|
|
48
|
+
# note: this action returns HTTP 201, not HTTP 200!
|
|
49
|
+
response = get :return_and_validate_unexpected_array_response, {format: :json}
|
|
50
|
+
expect(response).not_to match_declared_responses
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "does not raise error when a response has an extra property and 'swagger_allow_additional_properties_in_response' is true" do
|
|
54
|
+
Apipie.configuration.swagger_allow_additional_properties_in_response = true
|
|
55
|
+
response = get :return_and_validate_extra_property, {format: :json}
|
|
56
|
+
expect(response).to match_declared_responses
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "does not raise error when a response has an extra field and 'additional_properties' is specified in the response" do
|
|
60
|
+
Apipie.configuration.swagger_allow_additional_properties_in_response = false
|
|
61
|
+
response = get :return_and_validate_allowed_extra_property, {format: :json}
|
|
62
|
+
expect(response).to match_declared_responses
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "raises error when a response sub-object has an extra field and 'additional_properties' is not specified on it, but specified on the top level of the response" do
|
|
66
|
+
Apipie.configuration.swagger_allow_additional_properties_in_response = false
|
|
67
|
+
response = get :sub_object_invalid_extra_property, {format: :json}
|
|
68
|
+
expect(response).not_to match_declared_responses
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "does not rais error when a response sub-object has an extra field and 'additional_properties' is specified on it" do
|
|
72
|
+
Apipie.configuration.swagger_allow_additional_properties_in_response = false
|
|
73
|
+
response = get :sub_object_allowed_extra_property, {format: :json}
|
|
74
|
+
expect(response).to match_declared_responses
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe "auto validation" do
|
|
78
|
+
auto_validate_rendered_views
|
|
79
|
+
it "raises exception when a response field has the wrong type and auto validation is turned on" do
|
|
80
|
+
expect { get :return_and_validate_type_mismatch, {format: :json} }.to raise_error(Apipie::ResponseDoesNotMatchSwaggerSchema)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "does not raise an exception when calling an undocumented method" do
|
|
84
|
+
expect { get :undocumented_method, {format: :json} }.not_to raise_error
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
describe "with array field" do
|
|
91
|
+
it "no error for valid response" do
|
|
92
|
+
response = get :returns_response_with_valid_array, {format: :json}
|
|
93
|
+
expect(response).to match_declared_responses
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "error if type of element in the array is wrong" do
|
|
97
|
+
response = get :returns_response_with_invalid_array, {format: :json}
|
|
98
|
+
expect(response).not_to match_declared_responses
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
end
|
|
@@ -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
|