rspec_api_documentation 0.4.4 → 0.5.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.
- data/lib/rspec_api_documentation/client_base.rb +79 -0
- data/lib/rspec_api_documentation/configuration.rb +1 -0
- data/lib/rspec_api_documentation/dsl.rb +7 -13
- data/lib/rspec_api_documentation/example.rb +1 -1
- data/lib/rspec_api_documentation/headers.rb +23 -0
- data/lib/rspec_api_documentation/html_writer.rb +1 -1
- data/lib/rspec_api_documentation/index_writer.rb +6 -3
- data/lib/rspec_api_documentation/json_writer.rb +1 -1
- data/lib/rspec_api_documentation/oauth2_mac_client.rb +52 -0
- data/lib/rspec_api_documentation/rack_test_client.rb +51 -0
- data/lib/rspec_api_documentation/syntax.rb +33 -0
- data/lib/rspec_api_documentation/test_server.rb +17 -29
- data/lib/rspec_api_documentation.rb +6 -1
- data/templates/rspec_api_documentation/html_example.mustache +5 -4
- metadata +45 -41
- data/lib/rspec_api_documentation/test_client.rb +0 -130
@@ -0,0 +1,79 @@
|
|
1
|
+
module RspecApiDocumentation
|
2
|
+
class ClientBase < Struct.new(:context, :options)
|
3
|
+
include Headers
|
4
|
+
include Syntax
|
5
|
+
|
6
|
+
delegate :example, :app, :to => :context
|
7
|
+
delegate :metadata, :to => :example
|
8
|
+
|
9
|
+
def get(*args)
|
10
|
+
process :get, *args
|
11
|
+
end
|
12
|
+
|
13
|
+
def post(*args)
|
14
|
+
process :post, *args
|
15
|
+
end
|
16
|
+
|
17
|
+
def put(*args)
|
18
|
+
process :put, *args
|
19
|
+
end
|
20
|
+
|
21
|
+
def delete(*args)
|
22
|
+
process :delete, *args
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def process(method, path, params = {})
|
28
|
+
do_request(method, path, params)
|
29
|
+
document_example(method.to_s.upcase, path, params)
|
30
|
+
end
|
31
|
+
|
32
|
+
def document_example(method, path, params)
|
33
|
+
return unless metadata[:document]
|
34
|
+
|
35
|
+
input = last_request.env["rack.input"]
|
36
|
+
input.rewind
|
37
|
+
request_body = input.read
|
38
|
+
|
39
|
+
request_metadata = {}
|
40
|
+
|
41
|
+
request_metadata[:request_method] = method
|
42
|
+
request_metadata[:request_path] = path
|
43
|
+
request_metadata[:request_body] = highlight_syntax(request_body, content_type, true)
|
44
|
+
request_metadata[:request_headers] = format_headers(request_headers)
|
45
|
+
request_metadata[:request_query_parameters] = format_query_hash(query_hash)
|
46
|
+
request_metadata[:response_status] = status
|
47
|
+
request_metadata[:response_status_text] = Rack::Utils::HTTP_STATUS_CODES[status]
|
48
|
+
request_metadata[:response_body] = highlight_syntax(response_body, response_headers['Content-Type'])
|
49
|
+
request_metadata[:response_headers] = format_headers(response_headers)
|
50
|
+
request_metadata[:curl] = Curl.new(method, path, request_body, request_headers)
|
51
|
+
|
52
|
+
metadata[:requests] ||= []
|
53
|
+
metadata[:requests] << request_metadata
|
54
|
+
end
|
55
|
+
|
56
|
+
def query_hash
|
57
|
+
strings = query_string.split("&")
|
58
|
+
arrays = strings.map do |segment|
|
59
|
+
segment.split("=")
|
60
|
+
end
|
61
|
+
Hash[arrays]
|
62
|
+
end
|
63
|
+
|
64
|
+
def format_query_hash(query_hash)
|
65
|
+
return if query_hash.blank?
|
66
|
+
query_hash.map do |key, value|
|
67
|
+
"#{key}: #{CGI.unescape(value)}"
|
68
|
+
end.join("\n")
|
69
|
+
end
|
70
|
+
|
71
|
+
def headers(method, path, params)
|
72
|
+
if options && options[:headers]
|
73
|
+
options[:headers]
|
74
|
+
else
|
75
|
+
{}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -6,12 +6,15 @@ module RspecApiDocumentation
|
|
6
6
|
module DSL
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
|
+
delegate :response_headers, :status, :response_body, :to => :client
|
10
|
+
delegate :request_method, :request_headers, :request_body, :to => :destination
|
11
|
+
|
9
12
|
module ClassMethods
|
10
13
|
def self.define_action(method)
|
11
14
|
define_method method do |*args, &block|
|
12
15
|
options = if args.last.is_a?(Hash) then args.pop else {} end
|
13
16
|
options[:method] = method
|
14
|
-
options[:
|
17
|
+
options[:route] = args.first
|
15
18
|
args.push(options)
|
16
19
|
args[0] = "#{method.to_s.upcase} #{args[0]}"
|
17
20
|
context(*args, &block)
|
@@ -89,7 +92,7 @@ module RspecApiDocumentation
|
|
89
92
|
end
|
90
93
|
|
91
94
|
def client
|
92
|
-
@client ||=
|
95
|
+
@client ||= RackTestClient.new(self)
|
93
96
|
end
|
94
97
|
|
95
98
|
def destination
|
@@ -150,11 +153,11 @@ module RspecApiDocumentation
|
|
150
153
|
end
|
151
154
|
|
152
155
|
def path_params
|
153
|
-
example.metadata[:
|
156
|
+
example.metadata[:route].scan(/:(\w+)/).flatten
|
154
157
|
end
|
155
158
|
|
156
159
|
def path
|
157
|
-
example.metadata[:
|
160
|
+
example.metadata[:route].gsub(/:(\w+)/) do |match|
|
158
161
|
if extra_params.keys.include?($1)
|
159
162
|
delete_extra_param($1)
|
160
163
|
elsif respond_to?($1)
|
@@ -173,14 +176,6 @@ module RspecApiDocumentation
|
|
173
176
|
example.metadata[:explanation] = text
|
174
177
|
end
|
175
178
|
|
176
|
-
def status
|
177
|
-
client.last_response.status
|
178
|
-
end
|
179
|
-
|
180
|
-
def response_body
|
181
|
-
client.last_response.body
|
182
|
-
end
|
183
|
-
|
184
179
|
private
|
185
180
|
def extra_params
|
186
181
|
return {} if @extra_params.nil?
|
@@ -220,5 +215,4 @@ def self.resource(*args, &block)
|
|
220
215
|
end
|
221
216
|
|
222
217
|
RSpec.configuration.include RspecApiDocumentation::DSL, :api_docs_dsl => true
|
223
|
-
RSpec.configuration.include Rack::Test::Methods, :api_docs_dsl => true
|
224
218
|
RSpec.configuration.backtrace_clean_patterns << %r{lib/rspec_api_documentation/dsl\.rb}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RspecApiDocumentation
|
2
|
+
module Headers
|
3
|
+
private
|
4
|
+
|
5
|
+
def env_to_headers(env)
|
6
|
+
headers = {}
|
7
|
+
env.each do |key, value|
|
8
|
+
# HTTP_ACCEPT_CHARSET => Accept-Charset
|
9
|
+
if key =~ /^(HTTP_|CONTENT_TYPE)/
|
10
|
+
header = key.gsub(/^HTTP_/, '').titleize.split.join("-")
|
11
|
+
headers[header] = value
|
12
|
+
end
|
13
|
+
end
|
14
|
+
headers
|
15
|
+
end
|
16
|
+
|
17
|
+
def format_headers(headers)
|
18
|
+
headers.map do |key, value|
|
19
|
+
"#{key}: #{value}"
|
20
|
+
end.join("\n")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,10 +1,13 @@
|
|
1
|
+
require "active_support/core_ext/enumerable"
|
2
|
+
|
1
3
|
module RspecApiDocumentation
|
2
4
|
module IndexWriter
|
3
|
-
def sections(examples)
|
5
|
+
def sections(examples, configuration)
|
4
6
|
resources = examples.group_by(&:resource_name).inject([]) do |arr, (resource_name, examples)|
|
5
|
-
|
7
|
+
ordered_examples = configuration.keep_source_order ? examples : examples.sort_by(&:description)
|
8
|
+
arr.push(:resource_name => resource_name, :examples => ordered_examples)
|
6
9
|
end
|
7
|
-
resources.sort_by { |resource| resource[:resource_name] }
|
10
|
+
configuration.keep_source_order ? resources : resources.sort_by { |resource| resource[:resource_name] }
|
8
11
|
end
|
9
12
|
module_function :sections
|
10
13
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module RspecApiDocumentation
|
2
|
+
class OAuth2MACClient < ClientBase
|
3
|
+
include WebMock::API
|
4
|
+
attr_accessor :last_response, :last_request
|
5
|
+
private :last_response, :last_request
|
6
|
+
|
7
|
+
def request_headers
|
8
|
+
env_to_headers(last_request.env)
|
9
|
+
end
|
10
|
+
|
11
|
+
def response_headers
|
12
|
+
last_response.headers
|
13
|
+
end
|
14
|
+
|
15
|
+
def query_string
|
16
|
+
last_request.env["QUERY_STRING"]
|
17
|
+
end
|
18
|
+
|
19
|
+
def status
|
20
|
+
last_response.status
|
21
|
+
end
|
22
|
+
|
23
|
+
def response_body
|
24
|
+
last_response.body
|
25
|
+
end
|
26
|
+
|
27
|
+
def content_type
|
28
|
+
last_request.content_type
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def do_request(method, path, params)
|
34
|
+
self.last_response = access_token.send(method, "http://example.com#{path}", :body => params, :header => headers(method, path, params))
|
35
|
+
end
|
36
|
+
|
37
|
+
class ProxyApp < Struct.new(:client, :app)
|
38
|
+
def call(env)
|
39
|
+
client.last_request = Struct.new(:env, :content_type).new(env, env["CONTENT_TYPE"])
|
40
|
+
app.call(env.merge("SCRIPT_NAME" => ""))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def access_token
|
45
|
+
@access_token ||= begin
|
46
|
+
app = ProxyApp.new(self, context.app)
|
47
|
+
stub_request(:any, %r{http://example\.com}).to_rack(app)
|
48
|
+
Rack::OAuth2::Client.new(options.merge(:host => "example.com", :scheme => "http")).access_token!
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "coderay"
|
2
|
+
|
3
|
+
module RspecApiDocumentation
|
4
|
+
class RackTestClient < ClientBase
|
5
|
+
|
6
|
+
delegate :last_request, :last_response, :to => :rack_test_session
|
7
|
+
private :last_request, :last_response
|
8
|
+
|
9
|
+
def request_headers
|
10
|
+
env_to_headers(last_request.env)
|
11
|
+
end
|
12
|
+
|
13
|
+
def response_headers
|
14
|
+
last_response.headers
|
15
|
+
end
|
16
|
+
|
17
|
+
def query_string
|
18
|
+
last_request.env["QUERY_STRING"]
|
19
|
+
end
|
20
|
+
|
21
|
+
def status
|
22
|
+
last_response.status
|
23
|
+
end
|
24
|
+
|
25
|
+
def response_body
|
26
|
+
last_response.body
|
27
|
+
end
|
28
|
+
|
29
|
+
def content_type
|
30
|
+
last_request.content_type
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def do_request(method, path, params)
|
36
|
+
rack_test_session.send(method, path, params, headers(method, path, params))
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def rack_test_session
|
42
|
+
@rack_test_session ||= Struct.new(:app) do
|
43
|
+
begin
|
44
|
+
include Rack::Test::Methods
|
45
|
+
rescue LoadError
|
46
|
+
raise "#{self.class.name} requires Rack::Test >= 0.5.5. Please add it to your test dependencies."
|
47
|
+
end
|
48
|
+
end.new(app)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "coderay"
|
2
|
+
|
3
|
+
module RspecApiDocumentation
|
4
|
+
module Syntax
|
5
|
+
private
|
6
|
+
|
7
|
+
def highlight_syntax(body, content_type, is_query_string = false)
|
8
|
+
return if body.blank?
|
9
|
+
begin
|
10
|
+
case content_type
|
11
|
+
when /json/
|
12
|
+
CodeRay.scan(JSON.pretty_generate(JSON.parse(body)), :json).div
|
13
|
+
when /html/
|
14
|
+
CodeRay.scan(body, :html).div
|
15
|
+
when /javascript/
|
16
|
+
CodeRay.scan(body, :java_script).div
|
17
|
+
when /xml/
|
18
|
+
CodeRay.scan(body, :xml).div
|
19
|
+
else
|
20
|
+
body = prettify_request_body(body) if is_query_string
|
21
|
+
"<pre>#{body}</pre>"
|
22
|
+
end
|
23
|
+
rescue Exception => e
|
24
|
+
"<pre>#{e.inspect}</pre>"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def prettify_request_body(string)
|
29
|
+
return if string.blank?
|
30
|
+
CGI.unescape(string.split("&").join("\n"))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,44 +1,32 @@
|
|
1
1
|
module RspecApiDocumentation
|
2
|
-
class TestServer < Struct.new(:
|
3
|
-
|
2
|
+
class TestServer < Struct.new(:context)
|
3
|
+
include Headers
|
4
|
+
include Syntax
|
5
|
+
|
6
|
+
delegate :example, :to => :context
|
4
7
|
delegate :metadata, :to => :example
|
5
8
|
|
9
|
+
attr_reader :request_method, :request_headers, :request_body
|
10
|
+
|
6
11
|
def call(env)
|
7
|
-
env["rack.input"]
|
12
|
+
input = env["rack.input"]
|
13
|
+
input.rewind
|
14
|
+
|
15
|
+
@request_method = env["REQUEST_METHOD"]
|
16
|
+
@request_headers = env_to_headers(env)
|
17
|
+
@request_body = input.read
|
8
18
|
|
9
19
|
request_metadata = {}
|
10
20
|
|
11
|
-
request_metadata[:
|
12
|
-
request_metadata[:
|
13
|
-
request_metadata[:request_body] =
|
14
|
-
request_metadata[:request_headers] =
|
21
|
+
request_metadata[:request_method] = request_method
|
22
|
+
request_metadata[:request_path] = env["PATH_INFO"]
|
23
|
+
request_metadata[:request_body] = highlight_syntax(request_body, request_headers["Content-Type"], true)
|
24
|
+
request_metadata[:request_headers] = format_headers(@request_headers)
|
15
25
|
|
16
26
|
metadata[:requests] ||= []
|
17
27
|
metadata[:requests] << request_metadata
|
18
28
|
|
19
29
|
return [200, {}, [""]]
|
20
30
|
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def headers(env)
|
25
|
-
env.
|
26
|
-
select do |k, v|
|
27
|
-
k =~ /^(HTTP_|CONTENT_TYPE)/
|
28
|
-
end.
|
29
|
-
map do |key, value|
|
30
|
-
# HTTP_ACCEPT_CHARSET => Accept-Charset
|
31
|
-
formatted_key = key.gsub(/^HTTP_/, '').titleize.split.join("-")
|
32
|
-
"#{formatted_key}: #{value}"
|
33
|
-
end.join("\n")
|
34
|
-
end
|
35
|
-
|
36
|
-
def prettify_json(json)
|
37
|
-
begin
|
38
|
-
JSON.pretty_generate(JSON.parse(json))
|
39
|
-
rescue
|
40
|
-
nil
|
41
|
-
end
|
42
|
-
end
|
43
31
|
end
|
44
32
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support'
|
2
|
+
require 'active_support/inflector'
|
2
3
|
require 'cgi'
|
3
4
|
require 'json'
|
4
5
|
|
@@ -15,10 +16,14 @@ module RspecApiDocumentation
|
|
15
16
|
autoload :Example
|
16
17
|
autoload :ExampleGroup
|
17
18
|
autoload :Index
|
18
|
-
autoload :
|
19
|
+
autoload :ClientBase
|
20
|
+
autoload :Headers
|
21
|
+
autoload :Syntax
|
19
22
|
end
|
20
23
|
|
21
24
|
autoload :DSL
|
25
|
+
autoload :RackTestClient
|
26
|
+
autoload :OAuth2MACClient, "rspec_api_documentation/oauth2_mac_client"
|
22
27
|
autoload :TestServer
|
23
28
|
autoload :HtmlWriter
|
24
29
|
autoload :JsonWriter
|
@@ -22,6 +22,7 @@
|
|
22
22
|
|
23
23
|
<div class="article">
|
24
24
|
<h2>{{ description }}</h2>
|
25
|
+
<h3>{{ http_method }} {{ route }}</h3>
|
25
26
|
{{# explanation }}
|
26
27
|
<p class="explanation">
|
27
28
|
{{ explanation }}
|
@@ -57,18 +58,18 @@
|
|
57
58
|
<h4>Headers</h4>
|
58
59
|
<pre class="request headers">{{ request_headers }}</pre>
|
59
60
|
<h4>Route</h4>
|
60
|
-
<pre class="request route highlight">{{
|
61
|
+
<pre class="request route highlight">{{ request_method }} {{ request_path }}</pre>
|
61
62
|
{{# request_query_parameters }}
|
62
63
|
<h4>Query Parameters</h4>
|
63
64
|
<pre class="request query_parameters highlight">{{ request_query_parameters }}</pre>
|
64
65
|
{{/ request_query_parameters }}
|
65
66
|
{{# request_body }}
|
66
67
|
<h4>Body</h4>
|
67
|
-
<
|
68
|
+
<div class="request body">{{{ request_body }}}</div>
|
68
69
|
{{/ request_body }}
|
69
70
|
|
70
71
|
{{# curl }}
|
71
|
-
<h4>
|
72
|
+
<h4>cURL</h4>
|
72
73
|
<pre class="request">{{ curl }}</pre>
|
73
74
|
{{/ curl }}
|
74
75
|
|
@@ -80,7 +81,7 @@
|
|
80
81
|
<pre class="response status">{{ response_status }} {{ response_status_text}}</pre>
|
81
82
|
{{# response_body }}
|
82
83
|
<h4>Body</h4>
|
83
|
-
<
|
84
|
+
<div class="response body">{{{ response_body }}}</div>
|
84
85
|
{{/ response_body }}
|
85
86
|
{{/ response_status }}
|
86
87
|
{{/ requests }}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec_api_documentation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,11 +11,11 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-04-
|
14
|
+
date: 2012-04-24 00:00:00.000000000Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rspec
|
18
|
-
requirement: &
|
18
|
+
requirement: &70224876720480 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
21
|
- - ! '>='
|
@@ -23,10 +23,10 @@ dependencies:
|
|
23
23
|
version: 2.6.0
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
|
-
version_requirements: *
|
26
|
+
version_requirements: *70224876720480
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activesupport
|
29
|
-
requirement: &
|
29
|
+
requirement: &70224876719900 !ruby/object:Gem::Requirement
|
30
30
|
none: false
|
31
31
|
requirements:
|
32
32
|
- - ! '>='
|
@@ -34,10 +34,10 @@ dependencies:
|
|
34
34
|
version: 3.0.0
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
|
-
version_requirements: *
|
37
|
+
version_requirements: *70224876719900
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
39
|
name: i18n
|
40
|
-
requirement: &
|
40
|
+
requirement: &70224876719320 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
43
|
- - ! '>='
|
@@ -45,54 +45,54 @@ dependencies:
|
|
45
45
|
version: 0.1.0
|
46
46
|
type: :runtime
|
47
47
|
prerelease: false
|
48
|
-
version_requirements: *
|
48
|
+
version_requirements: *70224876719320
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
|
-
name:
|
51
|
-
requirement: &
|
50
|
+
name: mustache
|
51
|
+
requirement: &70224876718740 !ruby/object:Gem::Requirement
|
52
52
|
none: false
|
53
53
|
requirements:
|
54
54
|
- - ! '>='
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: 0.
|
56
|
+
version: 0.99.0
|
57
57
|
type: :runtime
|
58
58
|
prerelease: false
|
59
|
-
version_requirements: *
|
59
|
+
version_requirements: *70224876718740
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
|
-
name:
|
62
|
-
requirement: &
|
61
|
+
name: webmock
|
62
|
+
requirement: &70224876718160 !ruby/object:Gem::Requirement
|
63
63
|
none: false
|
64
64
|
requirements:
|
65
65
|
- - ! '>='
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version:
|
67
|
+
version: 1.7.0
|
68
68
|
type: :runtime
|
69
69
|
prerelease: false
|
70
|
-
version_requirements: *
|
70
|
+
version_requirements: *70224876718160
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
|
-
name:
|
73
|
-
requirement: &
|
72
|
+
name: json
|
73
|
+
requirement: &70224876717600 !ruby/object:Gem::Requirement
|
74
74
|
none: false
|
75
75
|
requirements:
|
76
76
|
- - ! '>='
|
77
77
|
- !ruby/object:Gem::Version
|
78
|
-
version: 1.
|
78
|
+
version: 1.4.0
|
79
79
|
type: :runtime
|
80
80
|
prerelease: false
|
81
|
-
version_requirements: *
|
81
|
+
version_requirements: *70224876717600
|
82
82
|
- !ruby/object:Gem::Dependency
|
83
|
-
name:
|
84
|
-
requirement: &
|
83
|
+
name: coderay
|
84
|
+
requirement: &70224876715300 !ruby/object:Gem::Requirement
|
85
85
|
none: false
|
86
86
|
requirements:
|
87
87
|
- - ! '>='
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 1.
|
89
|
+
version: 1.0.7.rc1
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
|
-
version_requirements: *
|
92
|
+
version_requirements: *70224876715300
|
93
93
|
- !ruby/object:Gem::Dependency
|
94
94
|
name: fakefs
|
95
|
-
requirement: &
|
95
|
+
requirement: &70224876714800 !ruby/object:Gem::Requirement
|
96
96
|
none: false
|
97
97
|
requirements:
|
98
98
|
- - ! '>='
|
@@ -100,10 +100,10 @@ dependencies:
|
|
100
100
|
version: '0'
|
101
101
|
type: :development
|
102
102
|
prerelease: false
|
103
|
-
version_requirements: *
|
103
|
+
version_requirements: *70224876714800
|
104
104
|
- !ruby/object:Gem::Dependency
|
105
105
|
name: sinatra
|
106
|
-
requirement: &
|
106
|
+
requirement: &70224876714220 !ruby/object:Gem::Requirement
|
107
107
|
none: false
|
108
108
|
requirements:
|
109
109
|
- - ! '>='
|
@@ -111,10 +111,10 @@ dependencies:
|
|
111
111
|
version: '0'
|
112
112
|
type: :development
|
113
113
|
prerelease: false
|
114
|
-
version_requirements: *
|
114
|
+
version_requirements: *70224876714220
|
115
115
|
- !ruby/object:Gem::Dependency
|
116
|
-
name:
|
117
|
-
requirement: &
|
116
|
+
name: aruba
|
117
|
+
requirement: &70224876713680 !ruby/object:Gem::Requirement
|
118
118
|
none: false
|
119
119
|
requirements:
|
120
120
|
- - ! '>='
|
@@ -122,10 +122,10 @@ dependencies:
|
|
122
122
|
version: '0'
|
123
123
|
type: :development
|
124
124
|
prerelease: false
|
125
|
-
version_requirements: *
|
125
|
+
version_requirements: *70224876713680
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
|
-
name:
|
128
|
-
requirement: &
|
127
|
+
name: capybara
|
128
|
+
requirement: &70224876713140 !ruby/object:Gem::Requirement
|
129
129
|
none: false
|
130
130
|
requirements:
|
131
131
|
- - ! '>='
|
@@ -133,10 +133,10 @@ dependencies:
|
|
133
133
|
version: '0'
|
134
134
|
type: :development
|
135
135
|
prerelease: false
|
136
|
-
version_requirements: *
|
136
|
+
version_requirements: *70224876713140
|
137
137
|
- !ruby/object:Gem::Dependency
|
138
|
-
name:
|
139
|
-
requirement: &
|
138
|
+
name: rake
|
139
|
+
requirement: &70224876712660 !ruby/object:Gem::Requirement
|
140
140
|
none: false
|
141
141
|
requirements:
|
142
142
|
- - ! '>='
|
@@ -144,10 +144,10 @@ dependencies:
|
|
144
144
|
version: '0'
|
145
145
|
type: :development
|
146
146
|
prerelease: false
|
147
|
-
version_requirements: *
|
147
|
+
version_requirements: *70224876712660
|
148
148
|
- !ruby/object:Gem::Dependency
|
149
|
-
name:
|
150
|
-
requirement: &
|
149
|
+
name: rack-oauth2
|
150
|
+
requirement: &70224876712240 !ruby/object:Gem::Requirement
|
151
151
|
none: false
|
152
152
|
requirements:
|
153
153
|
- - ! '>='
|
@@ -155,7 +155,7 @@ dependencies:
|
|
155
155
|
version: '0'
|
156
156
|
type: :development
|
157
157
|
prerelease: false
|
158
|
-
version_requirements: *
|
158
|
+
version_requirements: *70224876712240
|
159
159
|
description: Generate API docs from your test suite
|
160
160
|
email:
|
161
161
|
- chris@smartlogicsolutions.com
|
@@ -167,16 +167,20 @@ extra_rdoc_files: []
|
|
167
167
|
files:
|
168
168
|
- lib/rspec_api_documentation/api_documentation.rb
|
169
169
|
- lib/rspec_api_documentation/api_formatter.rb
|
170
|
+
- lib/rspec_api_documentation/client_base.rb
|
170
171
|
- lib/rspec_api_documentation/configuration.rb
|
171
172
|
- lib/rspec_api_documentation/curl.rb
|
172
173
|
- lib/rspec_api_documentation/dsl.rb
|
173
174
|
- lib/rspec_api_documentation/example.rb
|
175
|
+
- lib/rspec_api_documentation/headers.rb
|
174
176
|
- lib/rspec_api_documentation/html_writer.rb
|
175
177
|
- lib/rspec_api_documentation/index.rb
|
176
178
|
- lib/rspec_api_documentation/index_writer.rb
|
177
179
|
- lib/rspec_api_documentation/json_writer.rb
|
180
|
+
- lib/rspec_api_documentation/oauth2_mac_client.rb
|
181
|
+
- lib/rspec_api_documentation/rack_test_client.rb
|
178
182
|
- lib/rspec_api_documentation/railtie.rb
|
179
|
-
- lib/rspec_api_documentation/
|
183
|
+
- lib/rspec_api_documentation/syntax.rb
|
180
184
|
- lib/rspec_api_documentation/test_server.rb
|
181
185
|
- lib/rspec_api_documentation.rb
|
182
186
|
- lib/tasks/docs.rake
|
@@ -1,130 +0,0 @@
|
|
1
|
-
module RspecApiDocumentation
|
2
|
-
class TestClient < Struct.new(:session, :options)
|
3
|
-
attr_accessor :user
|
4
|
-
|
5
|
-
delegate :example, :last_response, :last_request, :to => :session
|
6
|
-
delegate :metadata, :to => :example
|
7
|
-
|
8
|
-
def get(*args)
|
9
|
-
process :get, *args
|
10
|
-
end
|
11
|
-
|
12
|
-
def post(*args)
|
13
|
-
process :post, *args
|
14
|
-
end
|
15
|
-
|
16
|
-
def put(*args)
|
17
|
-
process :put, *args
|
18
|
-
end
|
19
|
-
|
20
|
-
def delete(*args)
|
21
|
-
process :delete, *args
|
22
|
-
end
|
23
|
-
|
24
|
-
def sign_in(user)
|
25
|
-
@user = user
|
26
|
-
end
|
27
|
-
|
28
|
-
def last_headers
|
29
|
-
headers = last_request.env.select do |k, v|
|
30
|
-
k =~ /^(HTTP_|CONTENT_TYPE)/
|
31
|
-
end
|
32
|
-
Hash[headers]
|
33
|
-
end
|
34
|
-
|
35
|
-
def last_query_string
|
36
|
-
last_request.env["QUERY_STRING"]
|
37
|
-
end
|
38
|
-
|
39
|
-
def last_query_hash
|
40
|
-
strings = last_query_string.split("&")
|
41
|
-
arrays = strings.map do |segment|
|
42
|
-
segment.split("=")
|
43
|
-
end
|
44
|
-
Hash[arrays]
|
45
|
-
end
|
46
|
-
|
47
|
-
def headers(method, action, params)
|
48
|
-
if options && options[:headers]
|
49
|
-
options[:headers]
|
50
|
-
else
|
51
|
-
{}
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
def process(method, action, params = {})
|
57
|
-
session.send(method, action, params, headers(method, action, params))
|
58
|
-
|
59
|
-
document_example(method, action, params)
|
60
|
-
end
|
61
|
-
|
62
|
-
def document_example(method, action, params)
|
63
|
-
return unless metadata[:document]
|
64
|
-
|
65
|
-
input = last_request.env["rack.input"]
|
66
|
-
input.rewind
|
67
|
-
request_body = input.read
|
68
|
-
|
69
|
-
request_metadata = {}
|
70
|
-
|
71
|
-
request_metadata[:method] = method.to_s.upcase
|
72
|
-
request_metadata[:route] = action
|
73
|
-
if is_json?(request_body)
|
74
|
-
request_metadata[:request_body] = prettify_json(request_body)
|
75
|
-
else
|
76
|
-
request_metadata[:request_body] = prettify_request_body(request_body)
|
77
|
-
end
|
78
|
-
request_metadata[:request_headers] = format_headers(last_headers)
|
79
|
-
request_metadata[:request_query_parameters] = format_query_hash(last_query_hash)
|
80
|
-
request_metadata[:response_status] = last_response.status
|
81
|
-
request_metadata[:response_status_text] = Rack::Utils::HTTP_STATUS_CODES[last_response.status]
|
82
|
-
if is_json?(request_body)
|
83
|
-
request_metadata[:response_body] = prettify_json(last_response.body)
|
84
|
-
else
|
85
|
-
request_metadata[:response_body] = last_response.body
|
86
|
-
end
|
87
|
-
request_metadata[:response_headers] = format_headers(last_response.headers)
|
88
|
-
request_metadata[:curl] = Curl.new(method.to_s, action, request_body, last_headers)
|
89
|
-
|
90
|
-
metadata[:requests] ||= []
|
91
|
-
metadata[:requests] << request_metadata
|
92
|
-
end
|
93
|
-
|
94
|
-
def format_headers(headers)
|
95
|
-
headers.map do |key, value|
|
96
|
-
# HTTP_ACCEPT_CHARSET => Accept-Charset
|
97
|
-
formatted_key = key.gsub(/^HTTP_/, '').titleize.split.join("-")
|
98
|
-
"#{formatted_key}: #{value}"
|
99
|
-
end.join("\n")
|
100
|
-
end
|
101
|
-
|
102
|
-
def format_query_hash(query_hash)
|
103
|
-
return if query_hash.blank?
|
104
|
-
query_hash.map do |key, value|
|
105
|
-
"#{key}: #{CGI.unescape(value)}"
|
106
|
-
end.join("\n")
|
107
|
-
end
|
108
|
-
|
109
|
-
def prettify_json(json)
|
110
|
-
begin
|
111
|
-
JSON.pretty_generate(JSON.parse(json))
|
112
|
-
rescue
|
113
|
-
nil
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def prettify_request_body(string)
|
118
|
-
return if string.blank?
|
119
|
-
CGI.unescape(string.split("&").join("\n"))
|
120
|
-
end
|
121
|
-
|
122
|
-
def is_json?(string)
|
123
|
-
begin
|
124
|
-
JSON.parse(string)
|
125
|
-
rescue
|
126
|
-
false
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|