rspec_api_documentation 0.3.1 → 0.4.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.rb +3 -0
- data/lib/rspec_api_documentation/configuration.rb +3 -0
- data/lib/rspec_api_documentation/curl.rb +52 -0
- data/lib/rspec_api_documentation/dsl.rb +84 -80
- data/lib/rspec_api_documentation/html_writer.rb +16 -0
- data/lib/rspec_api_documentation/json_writer.rb +18 -5
- data/lib/rspec_api_documentation/test_client.rb +3 -1
- metadata +36 -24
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'active_support'
|
2
|
+
require 'cgi'
|
3
|
+
require 'json'
|
2
4
|
|
3
5
|
module RspecApiDocumentation
|
4
6
|
extend ActiveSupport::Autoload
|
@@ -21,6 +23,7 @@ module RspecApiDocumentation
|
|
21
23
|
autoload :HtmlWriter
|
22
24
|
autoload :JsonWriter
|
23
25
|
autoload :IndexWriter
|
26
|
+
autoload :Curl
|
24
27
|
|
25
28
|
def self.configuration
|
26
29
|
@configuration ||= Configuration.new
|
@@ -46,6 +46,7 @@ module RspecApiDocumentation
|
|
46
46
|
add_setting :template_path, :default => File.expand_path("../../../templates", __FILE__)
|
47
47
|
add_setting :filter, :default => :all
|
48
48
|
add_setting :exclusion_filter, :default => nil
|
49
|
+
add_setting :url_prefix, :default => ""
|
49
50
|
add_setting :app, :default => lambda { |config|
|
50
51
|
if defined?(Rails)
|
51
52
|
Rails.application
|
@@ -54,6 +55,8 @@ module RspecApiDocumentation
|
|
54
55
|
end
|
55
56
|
}
|
56
57
|
|
58
|
+
add_setting :curl_host, :default => nil
|
59
|
+
|
57
60
|
def settings
|
58
61
|
@settings ||= {}
|
59
62
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'active_support/core_ext/object/to_query'
|
2
|
+
|
3
|
+
module RspecApiDocumentation
|
4
|
+
class Curl < Struct.new(:method, :path, :data, :headers)
|
5
|
+
attr_accessor :host
|
6
|
+
|
7
|
+
def output(config_host)
|
8
|
+
self.host = config_host
|
9
|
+
send(method.downcase)
|
10
|
+
end
|
11
|
+
|
12
|
+
def post
|
13
|
+
"curl #{url} #{post_data} -X POST #{headers}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def get
|
17
|
+
"curl #{url}#{get_data} -X GET #{headers}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def put
|
21
|
+
"curl #{url} #{post_data} -X PUT #{headers}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete
|
25
|
+
"curl #{url} -X DELETE #{headers}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def url
|
29
|
+
"#{host}#{path}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def headers
|
33
|
+
super.map do |k, v|
|
34
|
+
"-H \"#{format_header(k, v)}\""
|
35
|
+
end.join(" ")
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_data
|
39
|
+
"?#{data}" unless data.blank?
|
40
|
+
end
|
41
|
+
|
42
|
+
def post_data
|
43
|
+
"-d \"#{data}\""
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def format_header(header, value)
|
48
|
+
formatted_header = header.gsub(/^HTTP_/, '').titleize.split.join("-")
|
49
|
+
"#{formatted_header}: #{value}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require 'rack/test
|
2
|
-
require 'rack'
|
1
|
+
require 'rack/test'
|
3
2
|
require 'webmock'
|
4
3
|
|
5
4
|
module RspecApiDocumentation
|
@@ -83,110 +82,115 @@ module RspecApiDocumentation
|
|
83
82
|
end
|
84
83
|
end
|
85
84
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
85
|
+
def client
|
86
|
+
@client ||= TestClient.new(self)
|
87
|
+
end
|
90
88
|
|
91
|
-
|
92
|
-
|
93
|
-
|
89
|
+
def destination
|
90
|
+
@destination ||= TestServer.new(self)
|
91
|
+
end
|
94
92
|
|
95
|
-
|
96
|
-
|
97
|
-
|
93
|
+
def callback_url
|
94
|
+
raise "You must define callback_url"
|
95
|
+
end
|
98
96
|
|
99
|
-
|
100
|
-
|
101
|
-
params_or_body = nil
|
102
|
-
path_or_query = path
|
97
|
+
def do_request(extra_params = {})
|
98
|
+
@extra_params = extra_params
|
103
99
|
|
104
|
-
|
105
|
-
|
106
|
-
else
|
107
|
-
params_or_body = respond_to?(:raw_post) ? raw_post : params
|
108
|
-
end
|
100
|
+
params_or_body = nil
|
101
|
+
path_or_query = path
|
109
102
|
|
110
|
-
|
103
|
+
if method == :get && !query_string.blank?
|
104
|
+
path_or_query = path + "?#{query_string}"
|
105
|
+
else
|
106
|
+
params_or_body = respond_to?(:raw_post) ? raw_post : params
|
111
107
|
end
|
112
108
|
|
113
|
-
|
114
|
-
|
115
|
-
param.map! { |a| CGI.escape(a.to_s) }
|
116
|
-
param.join("=")
|
117
|
-
end
|
118
|
-
query.join("&")
|
119
|
-
end
|
109
|
+
client.send(method, path_or_query, params_or_body)
|
110
|
+
end
|
120
111
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
end
|
126
|
-
parameters.merge!(extra_params)
|
127
|
-
parameters
|
112
|
+
def query_string
|
113
|
+
query = params.to_a.map do |param|
|
114
|
+
param.map! { |a| CGI.escape(a.to_s) }
|
115
|
+
param.join("=")
|
128
116
|
end
|
117
|
+
query.join("&")
|
118
|
+
end
|
129
119
|
|
130
|
-
|
131
|
-
|
120
|
+
def params
|
121
|
+
return unless example.metadata[:parameters]
|
122
|
+
parameters = example.metadata[:parameters].inject({}) do |hash, param|
|
123
|
+
set_param(hash, param)
|
132
124
|
end
|
125
|
+
parameters.merge!(extra_params)
|
126
|
+
parameters
|
127
|
+
end
|
133
128
|
|
134
|
-
|
135
|
-
|
136
|
-
|
129
|
+
def method
|
130
|
+
example.metadata[:method]
|
131
|
+
end
|
137
132
|
|
138
|
-
|
139
|
-
|
140
|
-
|
133
|
+
def in_path?(param)
|
134
|
+
path_params.include?(param)
|
135
|
+
end
|
141
136
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
137
|
+
def path_params
|
138
|
+
example.metadata[:path].scan(/:(\w+)/).flatten
|
139
|
+
end
|
140
|
+
|
141
|
+
def path
|
142
|
+
example.metadata[:path].gsub(/:(\w+)/) do |match|
|
143
|
+
if extra_params.keys.include?($1)
|
144
|
+
delete_extra_param($1)
|
145
|
+
elsif respond_to?($1)
|
146
|
+
send($1)
|
147
|
+
else
|
148
|
+
match
|
149
149
|
end
|
150
150
|
end
|
151
|
+
end
|
151
152
|
|
152
|
-
|
153
|
-
|
154
|
-
|
153
|
+
def app
|
154
|
+
RspecApiDocumentation.configuration.app
|
155
|
+
end
|
155
156
|
|
156
|
-
|
157
|
-
|
158
|
-
|
157
|
+
def explanation(text)
|
158
|
+
example.metadata[:explanation] = text
|
159
|
+
end
|
159
160
|
|
160
|
-
|
161
|
-
|
162
|
-
|
161
|
+
def status
|
162
|
+
last_response.status
|
163
|
+
end
|
163
164
|
|
164
|
-
|
165
|
-
|
166
|
-
|
165
|
+
def response_body
|
166
|
+
last_response.body
|
167
|
+
end
|
167
168
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
end
|
169
|
+
private
|
170
|
+
def extra_params
|
171
|
+
return {} if @extra_params.nil?
|
172
|
+
@extra_params.inject({}) do |h, (k, v)|
|
173
|
+
h[k.to_s] = v
|
174
|
+
h
|
175
175
|
end
|
176
|
+
end
|
176
177
|
|
177
|
-
|
178
|
-
|
179
|
-
|
178
|
+
def delete_extra_param(key)
|
179
|
+
@extra_params.delete(key.to_sym) || @extra_params.delete(key.to_s)
|
180
|
+
end
|
180
181
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
else
|
185
|
-
hash[key] = send(key)
|
186
|
-
end
|
182
|
+
def set_param(hash, param)
|
183
|
+
key = param[:name]
|
184
|
+
return hash if !respond_to?(key) || in_path?(key)
|
187
185
|
|
188
|
-
|
186
|
+
if param[:scope]
|
187
|
+
hash[param[:scope].to_s] ||= {}
|
188
|
+
hash[param[:scope].to_s][key] = send(key)
|
189
|
+
else
|
190
|
+
hash[key] = send(key)
|
189
191
|
end
|
192
|
+
|
193
|
+
hash
|
190
194
|
end
|
191
195
|
end
|
192
196
|
end
|
@@ -49,6 +49,7 @@ module RspecApiDocumentation
|
|
49
49
|
|
50
50
|
def initialize(example, configuration)
|
51
51
|
@example = example
|
52
|
+
@host = configuration.curl_host
|
52
53
|
self.template_path = configuration.template_path
|
53
54
|
end
|
54
55
|
|
@@ -68,5 +69,20 @@ module RspecApiDocumentation
|
|
68
69
|
basename = description.downcase.gsub(/\s+/, '_').gsub(/[^a-z_]/, '')
|
69
70
|
"#{basename}.html"
|
70
71
|
end
|
72
|
+
|
73
|
+
def requests
|
74
|
+
super.map do |hash|
|
75
|
+
if @host
|
76
|
+
hash[:curl] = hash[:curl].output(@host) if hash[:curl].is_a? RspecApiDocumentation::Curl
|
77
|
+
else
|
78
|
+
hash[:curl] = nil
|
79
|
+
end
|
80
|
+
hash
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def url_prefix
|
85
|
+
configuration.url_prefix
|
86
|
+
end
|
71
87
|
end
|
72
88
|
end
|
@@ -15,10 +15,10 @@ module RspecApiDocumentation
|
|
15
15
|
|
16
16
|
def write
|
17
17
|
File.open(docs_dir.join("index.json"), "w+") do |f|
|
18
|
-
f.write JsonIndex.new(index).to_json
|
18
|
+
f.write JsonIndex.new(index, configuration).to_json
|
19
19
|
end
|
20
20
|
index.examples.each do |example|
|
21
|
-
json_example = JsonExample.new(example)
|
21
|
+
json_example = JsonExample.new(example, configuration)
|
22
22
|
FileUtils.mkdir_p(docs_dir.join(json_example.dirname))
|
23
23
|
File.open(docs_dir.join(json_example.dirname, json_example.filename), "w+") do |f|
|
24
24
|
f.write json_example.to_json
|
@@ -28,8 +28,9 @@ module RspecApiDocumentation
|
|
28
28
|
end
|
29
29
|
|
30
30
|
class JsonIndex
|
31
|
-
def initialize(index)
|
31
|
+
def initialize(index, configuration)
|
32
32
|
@index = index
|
33
|
+
@configuration = configuration
|
33
34
|
end
|
34
35
|
|
35
36
|
def sections
|
@@ -37,7 +38,7 @@ module RspecApiDocumentation
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def examples
|
40
|
-
@index.examples.map { |example| JsonExample.new(example) }
|
41
|
+
@index.examples.map { |example| JsonExample.new(example, @configuration) }
|
41
42
|
end
|
42
43
|
|
43
44
|
def to_json
|
@@ -59,8 +60,9 @@ module RspecApiDocumentation
|
|
59
60
|
class JsonExample
|
60
61
|
delegate :method, :to => :@example
|
61
62
|
|
62
|
-
def initialize(example)
|
63
|
+
def initialize(example, configuration)
|
63
64
|
@example = example
|
65
|
+
@host = configuration.curl_host
|
64
66
|
end
|
65
67
|
|
66
68
|
def method_missing(method, *args, &block)
|
@@ -89,5 +91,16 @@ module RspecApiDocumentation
|
|
89
91
|
:requests => requests
|
90
92
|
}.to_json
|
91
93
|
end
|
94
|
+
|
95
|
+
def requests
|
96
|
+
super.map do |hash|
|
97
|
+
if @host
|
98
|
+
hash[:curl] = hash[:curl].output(@host) if hash[:curl].is_a? RspecApiDocumentation::Curl
|
99
|
+
else
|
100
|
+
hash[:curl] = nil
|
101
|
+
end
|
102
|
+
hash
|
103
|
+
end
|
104
|
+
end
|
92
105
|
end
|
93
106
|
end
|
@@ -26,9 +26,10 @@ module RspecApiDocumentation
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def last_headers
|
29
|
-
session.last_request.env.select do |k, v|
|
29
|
+
headers = session.last_request.env.select do |k, v|
|
30
30
|
k =~ /^(HTTP_|CONTENT_TYPE)/
|
31
31
|
end
|
32
|
+
Hash[headers]
|
32
33
|
end
|
33
34
|
|
34
35
|
def last_query_string
|
@@ -80,6 +81,7 @@ module RspecApiDocumentation
|
|
80
81
|
request_metadata[:response_status_text] = Rack::Utils::HTTP_STATUS_CODES[last_response.status]
|
81
82
|
request_metadata[:response_body] = prettify_json(last_response.body)
|
82
83
|
request_metadata[:response_headers] = format_headers(last_response.headers)
|
84
|
+
request_metadata[:curl] = Curl.new(method.to_s, action, request_body, last_headers)
|
83
85
|
|
84
86
|
metadata[:requests] ||= []
|
85
87
|
metadata[:requests] << request_metadata
|
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.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,77 +11,88 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-
|
14
|
+
date: 2012-02-03 00:00:00.000000000Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rspec
|
18
|
-
requirement: &
|
18
|
+
requirement: &70173877407600 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
21
|
- - ! '>='
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
23
|
+
version: 2.6.0
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
|
-
version_requirements: *
|
26
|
+
version_requirements: *70173877407600
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activesupport
|
29
|
-
requirement: &
|
29
|
+
requirement: &70173877407120 !ruby/object:Gem::Requirement
|
30
30
|
none: false
|
31
31
|
requirements:
|
32
32
|
- - ! '>='
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
34
|
+
version: 3.0.0
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
|
-
version_requirements: *
|
37
|
+
version_requirements: *70173877407120
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
39
|
name: i18n
|
40
|
-
requirement: &
|
40
|
+
requirement: &70173877406600 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
45
|
+
version: 0.1.0
|
46
46
|
type: :runtime
|
47
47
|
prerelease: false
|
48
|
-
version_requirements: *
|
48
|
+
version_requirements: *70173877406600
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
50
|
name: rack-test
|
51
|
-
requirement: &
|
51
|
+
requirement: &70173877406140 !ruby/object:Gem::Requirement
|
52
52
|
none: false
|
53
53
|
requirements:
|
54
54
|
- - ! '>='
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version:
|
56
|
+
version: 0.5.5
|
57
57
|
type: :runtime
|
58
58
|
prerelease: false
|
59
|
-
version_requirements: *
|
59
|
+
version_requirements: *70173877406140
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
61
|
name: mustache
|
62
|
-
requirement: &
|
62
|
+
requirement: &70173877405680 !ruby/object:Gem::Requirement
|
63
63
|
none: false
|
64
64
|
requirements:
|
65
65
|
- - ! '>='
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version:
|
67
|
+
version: 0.99.0
|
68
68
|
type: :runtime
|
69
69
|
prerelease: false
|
70
|
-
version_requirements: *
|
70
|
+
version_requirements: *70173877405680
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
72
|
name: webmock
|
73
|
-
requirement: &
|
73
|
+
requirement: &70173877405220 !ruby/object:Gem::Requirement
|
74
74
|
none: false
|
75
75
|
requirements:
|
76
76
|
- - ! '>='
|
77
77
|
- !ruby/object:Gem::Version
|
78
|
-
version:
|
78
|
+
version: 1.7.0
|
79
|
+
type: :runtime
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: *70173877405220
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: json
|
84
|
+
requirement: &70173877404740 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.4.0
|
79
90
|
type: :runtime
|
80
91
|
prerelease: false
|
81
|
-
version_requirements: *
|
92
|
+
version_requirements: *70173877404740
|
82
93
|
- !ruby/object:Gem::Dependency
|
83
94
|
name: fakefs
|
84
|
-
requirement: &
|
95
|
+
requirement: &70173877404360 !ruby/object:Gem::Requirement
|
85
96
|
none: false
|
86
97
|
requirements:
|
87
98
|
- - ! '>='
|
@@ -89,10 +100,10 @@ dependencies:
|
|
89
100
|
version: '0'
|
90
101
|
type: :development
|
91
102
|
prerelease: false
|
92
|
-
version_requirements: *
|
103
|
+
version_requirements: *70173877404360
|
93
104
|
- !ruby/object:Gem::Dependency
|
94
105
|
name: sinatra
|
95
|
-
requirement: &
|
106
|
+
requirement: &70173877403900 !ruby/object:Gem::Requirement
|
96
107
|
none: false
|
97
108
|
requirements:
|
98
109
|
- - ! '>='
|
@@ -100,7 +111,7 @@ dependencies:
|
|
100
111
|
version: '0'
|
101
112
|
type: :development
|
102
113
|
prerelease: false
|
103
|
-
version_requirements: *
|
114
|
+
version_requirements: *70173877403900
|
104
115
|
description: Generate API docs from your test suite
|
105
116
|
email:
|
106
117
|
- chris@smartlogicsolutions.com
|
@@ -113,6 +124,7 @@ files:
|
|
113
124
|
- lib/rspec_api_documentation/api_documentation.rb
|
114
125
|
- lib/rspec_api_documentation/api_formatter.rb
|
115
126
|
- lib/rspec_api_documentation/configuration.rb
|
127
|
+
- lib/rspec_api_documentation/curl.rb
|
116
128
|
- lib/rspec_api_documentation/dsl.rb
|
117
129
|
- lib/rspec_api_documentation/example.rb
|
118
130
|
- lib/rspec_api_documentation/html_writer.rb
|