rspec_api_documentation 0.4.4 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -56,6 +56,7 @@ module RspecApiDocumentation
56
56
  }
57
57
 
58
58
  add_setting :curl_host, :default => nil
59
+ add_setting :keep_source_order, :default => false
59
60
 
60
61
  def settings
61
62
  @settings ||= {}
@@ -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[:path] = args.first
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 ||= TestClient.new(self)
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[:path].scan(/:(\w+)/).flatten
156
+ example.metadata[:route].scan(/:(\w+)/).flatten
154
157
  end
155
158
 
156
159
  def path
157
- example.metadata[:path].gsub(/:(\w+)/) do |match|
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}
@@ -20,7 +20,7 @@ module RspecApiDocumentation
20
20
  end
21
21
 
22
22
  def http_method
23
- metadata[:method]
23
+ metadata[:method].to_s.upcase
24
24
  end
25
25
 
26
26
  def should_document?
@@ -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
@@ -36,7 +36,7 @@ module RspecApiDocumentation
36
36
  end
37
37
 
38
38
  def sections
39
- IndexWriter.sections(examples)
39
+ IndexWriter.sections(examples, @configuration)
40
40
  end
41
41
 
42
42
  def examples
@@ -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
- arr << { :resource_name => resource_name, :examples => examples.sort_by(&:description) }
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
@@ -34,7 +34,7 @@ module RspecApiDocumentation
34
34
  end
35
35
 
36
36
  def sections
37
- IndexWriter.sections(examples)
37
+ IndexWriter.sections(examples, @configuration)
38
38
  end
39
39
 
40
40
  def examples
@@ -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(:session)
3
- delegate :example, :last_request, :last_response, :to => :session
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"].rewind
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[:method] = env["REQUEST_METHOD"]
12
- request_metadata[:route] = env["PATH_INFO"]
13
- request_metadata[:request_body] = prettify_json(env["rack.input"].read)
14
- request_metadata[:request_headers] = headers(env)
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 :TestClient
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">{{ http_method }} {{ route }}</pre>
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
- <pre class="request highlight">{{ request_body }}</pre>
68
+ <div class="request body">{{{ request_body }}}</div>
68
69
  {{/ request_body }}
69
70
 
70
71
  {{# curl }}
71
- <h4>Curl</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
- <pre class="response body highlight">{{ response_body }}</pre>
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.4
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-03 00:00:00.000000000Z
14
+ date: 2012-04-24 00:00:00.000000000Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rspec
18
- requirement: &70121277388400 !ruby/object:Gem::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: *70121277388400
26
+ version_requirements: *70224876720480
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
- requirement: &70121277387560 !ruby/object:Gem::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: *70121277387560
37
+ version_requirements: *70224876719900
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: i18n
40
- requirement: &70121277386040 !ruby/object:Gem::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: *70121277386040
48
+ version_requirements: *70224876719320
49
49
  - !ruby/object:Gem::Dependency
50
- name: rack-test
51
- requirement: &70121277384380 !ruby/object:Gem::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.5.5
56
+ version: 0.99.0
57
57
  type: :runtime
58
58
  prerelease: false
59
- version_requirements: *70121277384380
59
+ version_requirements: *70224876718740
60
60
  - !ruby/object:Gem::Dependency
61
- name: mustache
62
- requirement: &70121277383220 !ruby/object:Gem::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: 0.99.0
67
+ version: 1.7.0
68
68
  type: :runtime
69
69
  prerelease: false
70
- version_requirements: *70121277383220
70
+ version_requirements: *70224876718160
71
71
  - !ruby/object:Gem::Dependency
72
- name: webmock
73
- requirement: &70121277382640 !ruby/object:Gem::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.7.0
78
+ version: 1.4.0
79
79
  type: :runtime
80
80
  prerelease: false
81
- version_requirements: *70121277382640
81
+ version_requirements: *70224876717600
82
82
  - !ruby/object:Gem::Dependency
83
- name: json
84
- requirement: &70121277370000 !ruby/object:Gem::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.4.0
89
+ version: 1.0.7.rc1
90
90
  type: :runtime
91
91
  prerelease: false
92
- version_requirements: *70121277370000
92
+ version_requirements: *70224876715300
93
93
  - !ruby/object:Gem::Dependency
94
94
  name: fakefs
95
- requirement: &70121277369620 !ruby/object:Gem::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: *70121277369620
103
+ version_requirements: *70224876714800
104
104
  - !ruby/object:Gem::Dependency
105
105
  name: sinatra
106
- requirement: &70121277369140 !ruby/object:Gem::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: *70121277369140
114
+ version_requirements: *70224876714220
115
115
  - !ruby/object:Gem::Dependency
116
- name: builder
117
- requirement: &70121277368700 !ruby/object:Gem::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: *70121277368700
125
+ version_requirements: *70224876713680
126
126
  - !ruby/object:Gem::Dependency
127
- name: aruba
128
- requirement: &70121277368240 !ruby/object:Gem::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: *70121277368240
136
+ version_requirements: *70224876713140
137
137
  - !ruby/object:Gem::Dependency
138
- name: capybara
139
- requirement: &70121277367700 !ruby/object:Gem::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: *70121277367700
147
+ version_requirements: *70224876712660
148
148
  - !ruby/object:Gem::Dependency
149
- name: rake
150
- requirement: &70121277367180 !ruby/object:Gem::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: *70121277367180
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/test_client.rb
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