-
Notifications
You must be signed in to change notification settings - Fork 64
/
hanami.rb
110 lines (84 loc) · 3 KB
/
hanami.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
# frozen_string_literal: true
require 'dry/inflector'
require 'hanami'
# https://github.com/hanami/router/blob/97f75b8529574bd4ff23165460e82a6587bc323c/lib/hanami/router/inspector.rb#L13
class Inspector
attr_accessor :routes, :inflector
def initialize(routes: [])
@routes = routes
@inflector = Dry::Inflector.new
end
def add_route(route)
routes.push(route)
end
def call(verb, path)
route = routes.find { |r| r.http_method == verb && r.path == path }
if route.to.is_a?(Proc)
{
tags: [],
summary: "#{verb} #{path}",
}
else
data = route.to.split('.')
{
tags: [inflector.classify(data[0])],
summary: data[1],
}
end
end
end
InspectorAnalyzer = Inspector.new
# Add default parameter to load inspector before test cases run
module InspectorAnalyzerPrepender
def router(inspector: InspectorAnalyzer)
super
end
end
Hanami::Slice::ClassMethods.prepend(InspectorAnalyzerPrepender)
# Extractor for hanami
class << RSpec::OpenAPI::Extractors::Hanami = Object.new
# @param [ActionDispatch::Request] request
# @param [RSpec::Core::Example] example
# @return Array
def request_attributes(request, example)
route = Hanami.app.router.recognize(Rack::MockRequest.env_for(request.path, method: request.method))
return RSpec::OpenAPI::Extractors::Rack.request_attributes(request, example) unless route.routable?
metadata = example.metadata[:openapi] || {}
summary = metadata[:summary] || RSpec::OpenAPI.summary_builder.call(example)
tags = metadata[:tags] || RSpec::OpenAPI.tags_builder.call(example)
operation_id = metadata[:operation_id]
required_request_params = metadata[:required_request_params] || []
security = metadata[:security]
description = metadata[:description] || RSpec::OpenAPI.description_builder.call(example)
deprecated = metadata[:deprecated]
path = request.path
raw_path_params = route.params
result = InspectorAnalyzer.call(request.method, add_id(path, route))
summary ||= result[:summary]
tags ||= result[:tags]
path = add_openapi_id(path, route)
raw_path_params = raw_path_params.slice(*(raw_path_params.keys - RSpec::OpenAPI.ignored_path_params))
[path, summary, tags, operation_id, required_request_params, raw_path_params, description, security, deprecated]
end
# @param [RSpec::ExampleGroups::*] context
def request_response(context)
request = ActionDispatch::Request.new(context.last_request.env)
request.body.rewind if request.body.respond_to?(:rewind)
response = ActionDispatch::TestResponse.new(*context.last_response.to_a)
[request, response]
end
def add_id(path, route)
return path if route.params.empty?
route.params.each_pair do |key, value|
path = path.sub("/#{value}", "/:#{key}")
end
path
end
def add_openapi_id(path, route)
return path if route.params.empty?
route.params.each_pair do |key, value|
path = path.sub("/#{value}", "/{#{key}}")
end
path
end
end