rspec-apidoc 0.1.0 → 0.2.0
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 +4 -4
- data/README.md +6 -1
- data/lib/rspec/apidoc/static/template.html.erb +30 -9
- data/lib/rspec/apidoc.rb +24 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8700f45112bb1c1a6a8ca9770020b00c5e1887e673e4353b305ecc66f89f5d70
|
4
|
+
data.tar.gz: 9ce1fb0139b48f53dce57b0f51728ddcbf58546b64c99105437dc9b637bdf5ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 617d0a747bb1977de943ec794fde2c4975bc5058d93c5e6cdd1ae88a8075e24c20db6b187b3d8fb59661961974555305c50ace0558662697103bb60c3feab20c
|
7
|
+
data.tar.gz: 0c82c4f051092f3517279e1c5d4ca0cd4e7eaae8471dfe81b8240bad3517d0d023965e129cf0fb169d6df5b372cd23d7fa8d8b4b88f695ccceef35a85b1bac2e
|
data/README.md
CHANGED
@@ -47,12 +47,17 @@ RSpec.configure do |config|
|
|
47
47
|
|
48
48
|
config.apidoc_title = 'YOUR.APP API Documentation'
|
49
49
|
config.apidoc_description = \
|
50
|
-
'A longer intro to add before the examples:
|
50
|
+
'A longer intro to add before the examples: authentication, status codes...'
|
51
51
|
|
52
52
|
config.apidoc_host = 'https://api.YOUR.APP'
|
53
53
|
# Optionally specify the output file path.
|
54
54
|
config.apidoc_output_filename = 'apidoc.html'
|
55
55
|
|
56
|
+
# Customize the authentication header
|
57
|
+
config.apidoc_auth_header = lambda do |headers|
|
58
|
+
'"Authorization: Bearer $AUTH_TOKEN"' if headers['Authorization']
|
59
|
+
end
|
60
|
+
|
56
61
|
# You can add it to any example based on the metadata.
|
57
62
|
config.after(:each, type: :request) do |example|
|
58
63
|
RSpec::Apidoc.add(self, example)
|
@@ -90,10 +90,14 @@
|
|
90
90
|
</div>
|
91
91
|
|
92
92
|
<% examples.each do |controller, items| %>
|
93
|
-
<% items.sort.
|
93
|
+
<% items.sort.each_with_index do |(action, action_items), mindex| %>
|
94
94
|
<% action_items.each_with_index do |item, index| %>
|
95
|
-
<div class="example">
|
96
|
-
<% if
|
95
|
+
<div class="example" id="<%= controller %>-<%= action %>-<%= mindex + index %>">
|
96
|
+
<% if mindex == 0 %>
|
97
|
+
<%= item[:controller_comment] %>
|
98
|
+
<% end %>
|
99
|
+
|
100
|
+
<% if mindex == 0 && index == 0 %>
|
97
101
|
<div class="example-doc" id="<%= controller %>-<%= action %>">
|
98
102
|
<%= item[:action_comment] || ( item[:method] + ' ' + controller ) %>
|
99
103
|
</div>
|
@@ -104,11 +108,20 @@
|
|
104
108
|
<div class="request">
|
105
109
|
<span>Request</span>
|
106
110
|
<pre>
|
107
|
-
$ curl '<%= host %><%= item[:path] %><%= ('?' + item[:query]) if item[:query] != '' %>' \
|
108
|
-
|
109
|
-
-H
|
110
|
-
|
111
|
+
$ curl -X <%= item[:method] %> '<%= host %><%= item[:path] %><%= ('?' + item[:query]) if item[:query] != '' %>' \
|
112
|
+
<%- if item[:auth_header] -%>
|
113
|
+
-H <%= item[:auth_header] %> <%- if item[:content_type] %>\<% end %>
|
114
|
+
<%- end -%>
|
115
|
+
<%- if item[:content_type] -%>
|
116
|
+
-H 'Content-Type: <%= item[:content_type] %>' <%- if item[:request_body] %>\<% end %>
|
117
|
+
<%- end -%>
|
118
|
+
<%- if item[:request_body] != '' -%>
|
119
|
+
-d - << EOF
|
120
|
+
<% if item[:request_body].is_a?(String) -%>
|
121
|
+
<%=h item[:request_body] -%>
|
122
|
+
<% else %>
|
111
123
|
<%=h JSON.pretty_generate(item[:request_body]) %>
|
124
|
+
<%- end %>
|
112
125
|
EOF
|
113
126
|
<% end %>
|
114
127
|
</pre>
|
@@ -116,9 +129,14 @@ EOF
|
|
116
129
|
<div class="response">
|
117
130
|
<span>Response</span>
|
118
131
|
<pre>
|
119
|
-
< Content-Type: <%= item[:response_content_type]
|
132
|
+
< Content-Type: <%= item[:response_content_type] -%>
|
120
133
|
< Status: <%= item[:status] %>
|
121
|
-
|
134
|
+
|
135
|
+
<% if item[:response_body].is_a?(String) -%>
|
136
|
+
<%=h item[:response_body] -%>
|
137
|
+
<% else %>
|
138
|
+
<%=h JSON.pretty_generate(item[:response_body]) -%>
|
139
|
+
<%- end -%>
|
122
140
|
</pre>
|
123
141
|
</div>
|
124
142
|
</div>
|
@@ -135,6 +153,9 @@ EOF
|
|
135
153
|
</div>
|
136
154
|
<div class="footer">
|
137
155
|
© <%= Date.current.year %> <%= title %>
|
156
|
+
<p>
|
157
|
+
<small>Latest update at <%= DateTime.current.to_s %></small>
|
158
|
+
</p>
|
138
159
|
</div>
|
139
160
|
</body>
|
140
161
|
</html>
|
data/lib/rspec/apidoc.rb
CHANGED
@@ -13,6 +13,7 @@ module RSpec
|
|
13
13
|
config.add_setting(:apidoc_title)
|
14
14
|
config.add_setting(:apidoc_description)
|
15
15
|
config.add_setting(:apidoc_host)
|
16
|
+
config.add_setting(:apidoc_auth_header, default: ->(headers) {})
|
16
17
|
config.add_setting(
|
17
18
|
:apidoc_template_path,
|
18
19
|
default: File.expand_path('apidoc/static/template.html.erb', __dir__)
|
@@ -65,6 +66,14 @@ module RSpec
|
|
65
66
|
RSpec.configuration.apidoc_host
|
66
67
|
end
|
67
68
|
|
69
|
+
# Returns the API authentication header callback result
|
70
|
+
#
|
71
|
+
# @param headers [ActionDispatch::Http::Headers] object
|
72
|
+
# @return [Object]
|
73
|
+
def self.auth_header(headers)
|
74
|
+
RSpec.configuration.apidoc_auth_header.call(headers)
|
75
|
+
end
|
76
|
+
|
68
77
|
# Returns the collected examples, sorted
|
69
78
|
#
|
70
79
|
# @return [Array] a list of [Hash] items
|
@@ -82,15 +91,22 @@ module RSpec
|
|
82
91
|
response_body = parse_json_safely(spec.response.body)
|
83
92
|
|
84
93
|
if spec.request.controller_instance
|
85
|
-
|
86
|
-
|
87
|
-
).comment
|
94
|
+
action_name = spec.request.controller_instance.action_name
|
95
|
+
action_method = spec.request.controller_instance.method(action_name)
|
88
96
|
# Remove any `@param` or `@return` lines
|
89
|
-
action_comment =
|
97
|
+
action_comment = action_method.comment
|
98
|
+
.gsub(/^#(\s+)?$/, "\n").gsub(/^#(\s+)?/, '').gsub(/^@.*$/, '')
|
90
99
|
controller_class = spec.request.controller_class
|
91
|
-
|
100
|
+
controller_comment = nil
|
101
|
+
|
102
|
+
if action_method.respond_to?(:class_comment)
|
103
|
+
controller_comment = action_method.class_comment.gsub(
|
104
|
+
/.*frozen_string_literal:.*/, ''
|
105
|
+
).gsub(/^#(\s+)?$/, "\n").gsub(/^#(\s+)?/, '').gsub(/^@.*$/, '')
|
106
|
+
end
|
92
107
|
else
|
93
108
|
action_comment = nil
|
109
|
+
controller_comment = nil
|
94
110
|
controller_class = spec.request.path
|
95
111
|
action_name = spec.request.method
|
96
112
|
end
|
@@ -99,10 +115,12 @@ module RSpec
|
|
99
115
|
description: example.metadata[:full_description],
|
100
116
|
|
101
117
|
controller_class: controller_class,
|
118
|
+
controller_comment: controller_comment,
|
102
119
|
action_name: action_name,
|
103
120
|
action_comment: action_comment,
|
104
121
|
|
105
122
|
content_type: spec.request.content_type,
|
123
|
+
auth_header: auth_header(spec.request.headers),
|
106
124
|
method: spec.request.method,
|
107
125
|
path: spec.request.path,
|
108
126
|
query: spec.request.query_parameters.to_param,
|
@@ -145,7 +163,7 @@ module RSpec
|
|
145
163
|
def close(_notification)
|
146
164
|
return if examples.empty?
|
147
165
|
|
148
|
-
erb = ERB.new(File.read(template_path))
|
166
|
+
erb = ERB.new(File.read(template_path), trim_mode: '-')
|
149
167
|
File.write(output_filename, erb.result(self.binding))
|
150
168
|
end
|
151
169
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-apidoc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stas Suscov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: method_source
|