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.
- checksums.yaml +5 -5
- data/.travis.yml +23 -7
- data/CHANGELOG.md +147 -2
- data/Gemfile +1 -0
- data/Gemfile.rails41 +2 -0
- data/Gemfile.rails42 +10 -1
- data/Gemfile.rails50 +9 -0
- data/Gemfile.rails51 +9 -0
- data/Gemfile.rails60 +14 -0
- data/PROPOSAL_FOR_RESPONSE_DESCRIPTIONS.md +244 -0
- data/README.rst +570 -17
- data/apipie-rails.gemspec +3 -3
- data/app/controllers/apipie/apipies_controller.rb +48 -17
- data/app/views/apipie/apipies/_method_detail.erb +21 -0
- data/app/views/apipie/apipies/_params.html.erb +4 -2
- data/app/views/apipie/apipies/index.html.erb +5 -1
- data/app/views/apipie/apipies/resource.html.erb +3 -0
- data/app/views/layouts/apipie/apipie.html.erb +1 -1
- data/config/locales/en.yml +1 -0
- data/config/locales/fr.yml +31 -0
- data/config/locales/it.yml +31 -0
- data/config/locales/ja.yml +31 -0
- data/lib/apipie/apipie_module.rb +22 -4
- data/lib/apipie/application.rb +55 -28
- data/lib/apipie/configuration.rb +19 -3
- data/lib/apipie/core_ext/route.rb +9 -0
- data/lib/apipie/dsl_definition.rb +151 -10
- data/lib/apipie/error_description.rb +9 -2
- data/lib/apipie/errors.rb +34 -0
- data/lib/apipie/extractor/collector.rb +4 -0
- data/lib/apipie/extractor/recorder.rb +13 -12
- data/lib/apipie/extractor/writer.rb +83 -55
- data/lib/apipie/extractor.rb +10 -4
- data/lib/apipie/method_description.rb +51 -4
- data/lib/apipie/param_description.rb +56 -2
- data/lib/apipie/resource_description.rb +10 -3
- data/lib/apipie/response_description.rb +131 -0
- data/lib/apipie/response_description_adapter.rb +200 -0
- data/lib/apipie/routes_formatter.rb +1 -1
- data/lib/apipie/rspec/response_validation_helper.rb +194 -0
- data/lib/apipie/static_dispatcher.rb +3 -2
- data/lib/apipie/swagger_generator.rb +708 -0
- data/lib/apipie/tag_list_description.rb +11 -0
- data/lib/apipie/validator.rb +69 -8
- data/lib/apipie/version.rb +1 -1
- data/lib/apipie-rails.rb +7 -0
- data/lib/tasks/apipie.rake +103 -8
- data/spec/controllers/apipies_controller_spec.rb +52 -12
- data/spec/controllers/concerns_controller_spec.rb +2 -2
- data/spec/controllers/extended_controller_spec.rb +14 -0
- data/spec/controllers/memes_controller_spec.rb +10 -0
- data/spec/controllers/users_controller_spec.rb +115 -75
- data/spec/dummy/app/controllers/application_controller.rb +5 -1
- data/spec/dummy/app/controllers/concerns/extending_concern.rb +12 -0
- data/spec/dummy/app/controllers/concerns/sample_controller.rb +5 -5
- data/spec/dummy/app/controllers/extended_controller.rb +14 -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 +5 -0
- data/spec/dummy/app/controllers/users_controller.rb +19 -11
- data/spec/dummy/components/test_engine/Gemfile +6 -0
- data/spec/dummy/components/test_engine/app/controllers/test_engine/application_controller.rb +4 -0
- data/spec/dummy/components/test_engine/app/controllers/test_engine/memes_controller.rb +37 -0
- data/spec/dummy/components/test_engine/config/routes.rb +3 -0
- data/spec/dummy/components/test_engine/db/.gitkeep +0 -0
- data/spec/dummy/components/test_engine/lib/test_engine.rb +7 -0
- data/spec/dummy/components/test_engine/test_engine.gemspec +11 -0
- data/spec/dummy/config/application.rb +5 -0
- data/spec/dummy/config/environments/development.rb +3 -0
- data/spec/dummy/config/environments/production.rb +3 -0
- data/spec/dummy/config/environments/test.rb +3 -0
- data/spec/dummy/config/initializers/apipie.rb +3 -1
- data/spec/dummy/config/routes.rb +24 -1
- data/spec/lib/extractor/writer_spec.rb +32 -4
- data/spec/lib/file_handler_spec.rb +18 -0
- data/spec/lib/method_description_spec.rb +34 -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 +58 -0
- data/spec/lib/validators/array_validator_spec.rb +28 -8
- data/spec/spec_helper.rb +68 -0
- metadata +75 -23
- data/Gemfile +0 -7
- data/Gemfile.rails32 +0 -6
- data/Gemfile.rails40 +0 -5
- data/lib/apipie/client/generator.rb +0 -135
@@ -0,0 +1,194 @@
|
|
1
|
+
#----------------------------------------------------------------------------------------------
|
2
|
+
# response_validation_helper.rb:
|
3
|
+
#
|
4
|
+
# this is an rspec utility to allow validation of responses against the swagger schema generated
|
5
|
+
# from the Apipie 'returns' definition for the call.
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# to use this file in a controller rspec you should
|
9
|
+
# require 'apipie/rspec/response_validation_helper' in the spec file
|
10
|
+
#
|
11
|
+
#
|
12
|
+
# this utility provides two mechanisms: matcher-based validation and auto-validation
|
13
|
+
#
|
14
|
+
# matcher-based: an rspec matcher allowing 'expect(response).to match_declared_responses'
|
15
|
+
# auto-validation: all responses returned from 'get', 'post', etc. are automatically tested
|
16
|
+
#
|
17
|
+
# ===================================
|
18
|
+
# Matcher-based validation - example
|
19
|
+
# ===================================
|
20
|
+
# Assume the file 'my_controller_spec.rb':
|
21
|
+
#
|
22
|
+
# require 'apipie/rspec/response_validation_helper'
|
23
|
+
#
|
24
|
+
# RSpec.describe MyController, :type => :controller, :show_in_doc => true do
|
25
|
+
#
|
26
|
+
# describe "GET stuff with response validation" do
|
27
|
+
# render_views # this makes sure the 'get' operation will actually
|
28
|
+
# # return the rendered view even though this is a Controller spec
|
29
|
+
#
|
30
|
+
# it "does something" do
|
31
|
+
# response = get :index, {format: :json}
|
32
|
+
#
|
33
|
+
# # the following expectation will fail if the returned object
|
34
|
+
# # does not match the 'returns' declaration in the Controller,
|
35
|
+
# # or if there is no 'returns' declaration for the returned
|
36
|
+
# # HTTP status code
|
37
|
+
# expect(response).to match_declared_responses
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
#
|
42
|
+
# ===================================
|
43
|
+
# Auto-validation
|
44
|
+
# ===================================
|
45
|
+
# To use auto-validation, at the beginning of the block in which you want to turn on validation:
|
46
|
+
# -) turn on view rendering (by stating 'render_views')
|
47
|
+
# -) turn on response validation by stating 'auto_validate_rendered_views'
|
48
|
+
#
|
49
|
+
# For example, assume the file 'my_controller_spec.rb':
|
50
|
+
#
|
51
|
+
# require 'apipie/rspec/response_validation_helper'
|
52
|
+
#
|
53
|
+
# RSpec.describe MyController, :type => :controller, :show_in_doc => true do
|
54
|
+
#
|
55
|
+
# describe "GET stuff with response validation" do
|
56
|
+
# render_views
|
57
|
+
# auto_validate_rendered_views
|
58
|
+
#
|
59
|
+
# it "does something" do
|
60
|
+
# get :index, {format: :json}
|
61
|
+
# end
|
62
|
+
# it "does something else" do
|
63
|
+
# get :another_index, {format: :json}
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# describe "GET stuff without response validation" do
|
68
|
+
# it "does something" do
|
69
|
+
# get :index, {format: :json}
|
70
|
+
# end
|
71
|
+
# it "does something else" do
|
72
|
+
# get :another_index, {format: :json}
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
#
|
77
|
+
# Once this is done, responses from http operations ('get', 'post', 'delete', etc.)
|
78
|
+
# will fail the test if the response structure does not match the 'returns' declaration
|
79
|
+
# on the method (for the actual HTTP status code), or if there is no 'returns' declaration
|
80
|
+
# for the HTTP status code.
|
81
|
+
#----------------------------------------------------------------------------------------------
|
82
|
+
|
83
|
+
|
84
|
+
#----------------------------------------------------------------------------------------------
|
85
|
+
# Response validation: core logic (used by auto-validation and manual-validation mechanisms)
|
86
|
+
#----------------------------------------------------------------------------------------------
|
87
|
+
class ActionController::Base
|
88
|
+
module Apipie::ControllerValidationHelpers
|
89
|
+
# this method is injected into ActionController::Base in order to
|
90
|
+
# get access to the names of the current controller, current action, as well as to the response
|
91
|
+
def schema_validation_errors_for_response
|
92
|
+
unprocessed_schema = Apipie::json_schema_for_method_response(controller_name, action_name, response.code, true)
|
93
|
+
|
94
|
+
if unprocessed_schema.nil?
|
95
|
+
err = "no schema defined for #{controller_name}##{action_name}[#{response.code}]"
|
96
|
+
return [nil, [err], RuntimeError.new(err)]
|
97
|
+
end
|
98
|
+
|
99
|
+
schema = JSON.parse(JSON(unprocessed_schema))
|
100
|
+
|
101
|
+
error_list = JSON::Validator.fully_validate(schema, response.body, :strict => false, :version => :draft4, :json => true)
|
102
|
+
|
103
|
+
error_object = Apipie::ResponseDoesNotMatchSwaggerSchema.new(controller_name, action_name, response.code, error_list, schema, response.body)
|
104
|
+
|
105
|
+
[schema, error_list, error_object]
|
106
|
+
rescue Apipie::NoDocumentedMethod
|
107
|
+
[nil, [], nil]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
include Apipie::ControllerValidationHelpers
|
112
|
+
end
|
113
|
+
|
114
|
+
module Apipie
|
115
|
+
def self.print_validation_errors(validation_errors, schema, response, error_object=nil)
|
116
|
+
Rails.logger.warn(validation_errors.to_s)
|
117
|
+
if Rails.env.test?
|
118
|
+
puts "schema validation errors:"
|
119
|
+
validation_errors.each { |e| puts "--> #{e.to_s}" }
|
120
|
+
puts "schema: #{schema.nil? ? '<none>' : JSON(schema)}"
|
121
|
+
puts "response: #{response.body}"
|
122
|
+
raise error_object if error_object
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
#---------------------------------
|
128
|
+
# Manual-validation (RSpec matcher)
|
129
|
+
#---------------------------------
|
130
|
+
RSpec::Matchers.define :match_declared_responses do
|
131
|
+
match do |actual|
|
132
|
+
(schema, validation_errors) = subject.send(:schema_validation_errors_for_response)
|
133
|
+
valid = (validation_errors == [])
|
134
|
+
Apipie::print_validation_errors(validation_errors, schema, response) unless valid
|
135
|
+
|
136
|
+
valid
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
#---------------------------------
|
142
|
+
# Auto-validation logic
|
143
|
+
#---------------------------------
|
144
|
+
module RSpec::Rails::ViewRendering
|
145
|
+
# Augment the RSpec DSL
|
146
|
+
module ClassMethods
|
147
|
+
def auto_validate_rendered_views
|
148
|
+
before do
|
149
|
+
@is_response_validation_on = true
|
150
|
+
end
|
151
|
+
|
152
|
+
after do
|
153
|
+
@is_response_validation_on = false
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
ActionController::TestCase::Behavior.instance_eval do
|
161
|
+
# instrument the 'process' method in ActionController::TestCase to enable response validation
|
162
|
+
module Apipie::ResponseValidationHelpers
|
163
|
+
@is_response_validation_on = false
|
164
|
+
def process(*args)
|
165
|
+
result = super(*args)
|
166
|
+
validate_response if @is_response_validation_on
|
167
|
+
|
168
|
+
result
|
169
|
+
end
|
170
|
+
|
171
|
+
def validate_response
|
172
|
+
controller.send(:validate_response_and_abort_with_info_if_errors)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
prepend Apipie::ResponseValidationHelpers
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
class ActionController::Base
|
181
|
+
module Apipie::ControllerValidationHelpers
|
182
|
+
def validate_response_and_abort_with_info_if_errors
|
183
|
+
|
184
|
+
(schema, validation_errors, error_object) = schema_validation_errors_for_response
|
185
|
+
|
186
|
+
valid = (validation_errors == [])
|
187
|
+
if !valid
|
188
|
+
Apipie::print_validation_errors(validation_errors, schema, response, error_object)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
|
@@ -8,9 +8,10 @@ module Apipie
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def match?(path)
|
11
|
-
|
11
|
+
# Replace all null bytes
|
12
|
+
path = ::Rack::Utils.unescape(path || '').gsub(/\x0/, '')
|
12
13
|
|
13
|
-
full_path = path.empty? ? @root : File.join(@root,
|
14
|
+
full_path = path.empty? ? @root : File.join(@root, path)
|
14
15
|
paths = "#{full_path}#{ext}"
|
15
16
|
|
16
17
|
matches = Dir[paths]
|