-
Notifications
You must be signed in to change notification settings - Fork 66
/
validator.rb
141 lines (119 loc) · 4.15 KB
/
validator.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
require 'action_controller'
require 'action_dispatch'
require 'apivore/rails_shim'
module Apivore
class Validator
include ::ActionDispatch::Integration::Runner
attr_reader :method, :path, :expected_response_code, :params
def initialize(method, path, expected_response_code, params = {})
@method = method.to_s
@path = path.to_s
@params = params
@expected_response_code = expected_response_code.to_i
end
def matches?(swagger_checker)
pre_checks(swagger_checker)
unless has_errors?
send(
method,
*RailsShim.action_dispatch_request_args(
full_path(swagger_checker),
params: params['_data'] || {},
headers: params['_headers'] || {}
)
)
swagger_checker.response = response
post_checks(swagger_checker)
if has_errors? && response.body.length > 0
errors << "\nResponse body:\n #{JSON.pretty_generate(JSON.parse(response.body))}"
end
swagger_checker.remove_tested_end_point_response(
path, method, expected_response_code
)
end
!has_errors?
end
def full_path(swagger_checker)
apivore_build_path(swagger_checker.base_path + path, params)
end
def apivore_build_path(path, data)
path.scan(/\{([^\}]*)\}/).each do |param|
key = param.first
if data && data[key]
path = path.gsub "{#{key}}", data[key].to_s
else
raise URI::InvalidURIError, "No substitution data found for {#{key}}"\
" to test the path #{path}.", caller
end
end
path + (data['_query_string'] ? "?#{data['_query_string']}" : '')
end
def pre_checks(swagger_checker)
check_request_path(swagger_checker)
end
def post_checks(swagger_checker)
check_status_code
check_response_is_valid(swagger_checker) unless has_errors?
end
def check_request_path(swagger_checker)
if !swagger_checker.has_path?(path)
errors << "Swagger doc: #{swagger_checker.swagger_path} does not have"\
" a documented path for #{path}"
elsif !swagger_checker.has_method_at_path?(path, method)
errors << "Swagger doc: #{swagger_checker.swagger_path} does not have"\
" a documented path for #{method} #{path}"
elsif !swagger_checker.has_response_code_for_path?(path, method, expected_response_code)
errors << "Swagger doc: #{swagger_checker.swagger_path} does not have"\
" a documented response code of #{expected_response_code} at path"\
" #{method} #{path}. "\
"\n Available response codes: #{swagger_checker.response_codes_for_path(path, method)}"
elsif method == "get" && swagger_checker.fragment(path, method, expected_response_code).nil?
errors << "Swagger doc: #{swagger_checker.swagger_path} missing"\
" response model for get request with #{path} for code"\
" #{expected_response_code}"
end
end
def check_status_code
if response.status != expected_response_code
errors << "Path #{path} did not respond with expected status code."\
" Expected #{expected_response_code} got #{response.status}"\
end
end
def check_response_is_valid(swagger_checker)
swagger_errors = swagger_checker.has_matching_document_for(
path, method, response.status, response_body
)
unless swagger_errors.empty?
errors.concat(
swagger_errors.map do |e|
e.sub("'#", "'#{full_path(swagger_checker)}#").gsub(
/^The property|in schema.*$/,''
)
end
)
end
end
def response_body
JSON.parse(response.body) unless response.body.blank?
end
def has_errors?
!errors.empty?
end
def failure_message
errors.join(" ")
end
def errors
@errors ||= []
end
def description
"validate that #{method} #{path} returns #{expected_response_code}"
end
# Required by ActionDispatch::Integration::Runner
def app
::Rails.application
end
# Required by rails
def reset_template_assertion
end
end
end