rspec-api-documentation 1.1.1.alpha
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 +7 -0
- data/lib/rspec_api_documentation.rb +63 -0
- data/lib/rspec_api_documentation/api_documentation.rb +38 -0
- data/lib/rspec_api_documentation/api_formatter.rb +45 -0
- data/lib/rspec_api_documentation/client_base.rb +82 -0
- data/lib/rspec_api_documentation/configuration.rb +84 -0
- data/lib/rspec_api_documentation/curl.rb +61 -0
- data/lib/rspec_api_documentation/dsl.rb +17 -0
- data/lib/rspec_api_documentation/dsl/callback.rb +25 -0
- data/lib/rspec_api_documentation/dsl/endpoint.rb +134 -0
- data/lib/rspec_api_documentation/dsl/resource.rb +83 -0
- data/lib/rspec_api_documentation/example.rb +49 -0
- data/lib/rspec_api_documentation/headers.rb +32 -0
- data/lib/rspec_api_documentation/index.rb +7 -0
- data/lib/rspec_api_documentation/oauth2_mac_client.rb +70 -0
- data/lib/rspec_api_documentation/rack_test_client.rb +58 -0
- data/lib/rspec_api_documentation/railtie.rb +7 -0
- data/lib/rspec_api_documentation/test_server.rb +31 -0
- data/lib/rspec_api_documentation/views/html_example.rb +16 -0
- data/lib/rspec_api_documentation/views/html_index.rb +14 -0
- data/lib/rspec_api_documentation/views/markup_example.rb +58 -0
- data/lib/rspec_api_documentation/views/markup_index.rb +21 -0
- data/lib/rspec_api_documentation/views/textile_example.rb +16 -0
- data/lib/rspec_api_documentation/views/textile_index.rb +14 -0
- data/lib/rspec_api_documentation/writers/combined_json_writer.rb +20 -0
- data/lib/rspec_api_documentation/writers/combined_text_writer.rb +106 -0
- data/lib/rspec_api_documentation/writers/formatter.rb +11 -0
- data/lib/rspec_api_documentation/writers/general_markup_writer.rb +42 -0
- data/lib/rspec_api_documentation/writers/html_writer.rb +21 -0
- data/lib/rspec_api_documentation/writers/index_writer.rb +16 -0
- data/lib/rspec_api_documentation/writers/json_iodocs_writer.rb +111 -0
- data/lib/rspec_api_documentation/writers/json_writer.rb +111 -0
- data/lib/rspec_api_documentation/writers/textile_writer.rb +21 -0
- data/lib/tasks/docs.rake +7 -0
- data/templates/rspec_api_documentation/html_example.mustache +106 -0
- data/templates/rspec_api_documentation/html_index.mustache +34 -0
- data/templates/rspec_api_documentation/textile_example.mustache +68 -0
- data/templates/rspec_api_documentation/textile_index.mustache +10 -0
- metadata +267 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
module RspecApiDocumentation
|
2
|
+
module Views
|
3
|
+
class TextileExample < MarkupExample
|
4
|
+
EXTENSION = 'textile'
|
5
|
+
|
6
|
+
def initialize(example, configuration)
|
7
|
+
super
|
8
|
+
self.template_name = "rspec_api_documentation/textile_example"
|
9
|
+
end
|
10
|
+
|
11
|
+
def extension
|
12
|
+
EXTENSION
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module RspecApiDocumentation
|
2
|
+
module Views
|
3
|
+
class TextileIndex < MarkupIndex
|
4
|
+
def initialize(index, configuration)
|
5
|
+
super
|
6
|
+
self.template_name = "rspec_api_documentation/textile_index"
|
7
|
+
end
|
8
|
+
|
9
|
+
def examples
|
10
|
+
@index.examples.map { |example| TextileExample.new(example, @configuration) }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rspec_api_documentation/writers/json_writer'
|
2
|
+
|
3
|
+
module RspecApiDocumentation
|
4
|
+
module Writers
|
5
|
+
class CombinedJsonWriter
|
6
|
+
def self.write(index, configuration)
|
7
|
+
File.open(configuration.docs_dir.join("combined.json"), "w+") do |f|
|
8
|
+
examples = []
|
9
|
+
index.examples.each do |rspec_example|
|
10
|
+
examples << Formatter.to_json(JsonExample.new(rspec_example, configuration))
|
11
|
+
end
|
12
|
+
|
13
|
+
f.write "["
|
14
|
+
f.write examples.join(",")
|
15
|
+
f.write "]"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module RspecApiDocumentation
|
2
|
+
module Writers
|
3
|
+
class CombinedTextWriter
|
4
|
+
def self.write(index, configuration)
|
5
|
+
index.examples.each do |rspec_example|
|
6
|
+
example = CombinedTextExample.new(rspec_example)
|
7
|
+
FileUtils.mkdir_p(configuration.docs_dir.join(example.resource_name))
|
8
|
+
File.open(configuration.docs_dir.join(example.resource_name, "index.txt"), "a+") do |f|
|
9
|
+
f.print example.description
|
10
|
+
f.print example.parameters
|
11
|
+
|
12
|
+
example.requests.each_with_index do |(request, response), i|
|
13
|
+
f.puts "Request:"
|
14
|
+
f.puts request
|
15
|
+
f.puts
|
16
|
+
f.puts "Response:"
|
17
|
+
f.puts response
|
18
|
+
|
19
|
+
if i + 1 < example.requests.count
|
20
|
+
f.puts
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
unless rspec_example == index.examples.last
|
25
|
+
f.puts
|
26
|
+
f.puts
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.format_hash(hash, separator="=")
|
33
|
+
hash.sort_by { |k, v| k }.inject("") do |out, (k, v)|
|
34
|
+
out << " #{k}#{separator}#{v}\n"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class CombinedTextExample
|
40
|
+
attr_reader :example
|
41
|
+
|
42
|
+
def initialize(example)
|
43
|
+
@example = example
|
44
|
+
end
|
45
|
+
|
46
|
+
def resource_name
|
47
|
+
example.resource_name.downcase.gsub(/\s+/, '_')
|
48
|
+
end
|
49
|
+
|
50
|
+
def description
|
51
|
+
example.description + "\n" + "-" * example.description.length + "\n\n"
|
52
|
+
end
|
53
|
+
|
54
|
+
def parameters
|
55
|
+
return "" unless example.metadata[:parameters]
|
56
|
+
"Parameters:\n" + example.metadata[:parameters].inject("") do |out, parameter|
|
57
|
+
out << " * #{parameter[:name]} - #{parameter[:description]}\n"
|
58
|
+
end + "\n"
|
59
|
+
end
|
60
|
+
|
61
|
+
def requests
|
62
|
+
return [] unless example.metadata[:requests]
|
63
|
+
example.metadata[:requests].map do |request|
|
64
|
+
[format_request(request), format_response(request)]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
def format_request(request)
|
70
|
+
[
|
71
|
+
[
|
72
|
+
" #{request[:request_method]} #{request[:request_path]}",
|
73
|
+
format_hash(request[:request_headers], ": ")
|
74
|
+
],
|
75
|
+
[
|
76
|
+
format_string(request[:request_body]) || format_hash(request[:request_query_parameters])
|
77
|
+
]
|
78
|
+
].map { |x| x.compact.join("\n") }.reject(&:blank?).join("\n\n") + "\n"
|
79
|
+
end
|
80
|
+
|
81
|
+
def format_response(request)
|
82
|
+
[
|
83
|
+
[
|
84
|
+
" Status: #{request[:response_status]} #{request[:response_status_text]}",
|
85
|
+
format_hash(request[:response_headers], ": ")
|
86
|
+
],
|
87
|
+
[
|
88
|
+
format_string(request[:response_body])
|
89
|
+
]
|
90
|
+
].map { |x| x.compact.join("\n") }.reject(&:blank?).join("\n\n") + "\n"
|
91
|
+
end
|
92
|
+
|
93
|
+
def format_string(string)
|
94
|
+
return unless string
|
95
|
+
string.split("\n").map { |line| " #{line}" }.join("\n")
|
96
|
+
end
|
97
|
+
|
98
|
+
def format_hash(hash, separator="=")
|
99
|
+
return unless hash
|
100
|
+
hash.sort_by { |k, v| k }.map do |k, v|
|
101
|
+
" #{k}#{separator}#{v}"
|
102
|
+
end.join("\n")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module RspecApiDocumentation
|
2
|
+
module Writers
|
3
|
+
class GeneralMarkupWriter
|
4
|
+
attr_accessor :index, :configuration
|
5
|
+
|
6
|
+
INDEX_FILE_NAME = 'index'
|
7
|
+
|
8
|
+
def initialize(index, configuration)
|
9
|
+
self.index = index
|
10
|
+
self.configuration = configuration
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.write(index, configuration)
|
14
|
+
writer = new(index, configuration)
|
15
|
+
writer.write
|
16
|
+
end
|
17
|
+
|
18
|
+
def write
|
19
|
+
File.open(configuration.docs_dir.join(index_file_name + '.' + extension), "w+") do |f|
|
20
|
+
f.write markup_index_class.new(index, configuration).render
|
21
|
+
end
|
22
|
+
|
23
|
+
index.examples.each do |example|
|
24
|
+
markup_example = markup_example_class.new(example, configuration)
|
25
|
+
FileUtils.mkdir_p(configuration.docs_dir.join(markup_example.dirname))
|
26
|
+
|
27
|
+
File.open(configuration.docs_dir.join(markup_example.dirname, markup_example.filename), "w+") do |f|
|
28
|
+
f.write markup_example.render
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def index_file_name
|
34
|
+
INDEX_FILE_NAME
|
35
|
+
end
|
36
|
+
|
37
|
+
def extension
|
38
|
+
raise 'Parent class. This method should not be called.'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RspecApiDocumentation
|
2
|
+
module Writers
|
3
|
+
class HtmlWriter < GeneralMarkupWriter
|
4
|
+
attr_accessor :index, :configuration
|
5
|
+
|
6
|
+
EXTENSION = 'html'
|
7
|
+
|
8
|
+
def markup_index_class
|
9
|
+
RspecApiDocumentation::Views::HtmlIndex
|
10
|
+
end
|
11
|
+
|
12
|
+
def markup_example_class
|
13
|
+
RspecApiDocumentation::Views::HtmlExample
|
14
|
+
end
|
15
|
+
|
16
|
+
def extension
|
17
|
+
EXTENSION
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "active_support/core_ext/enumerable"
|
2
|
+
|
3
|
+
module RspecApiDocumentation
|
4
|
+
module Writers
|
5
|
+
module IndexWriter
|
6
|
+
def sections(examples, configuration)
|
7
|
+
resources = examples.group_by(&:resource_name).inject([]) do |arr, (resource_name, examples)|
|
8
|
+
ordered_examples = configuration.keep_source_order ? examples : examples.sort_by(&:description)
|
9
|
+
arr.push(:resource_name => resource_name, :examples => ordered_examples)
|
10
|
+
end
|
11
|
+
configuration.keep_source_order ? resources : resources.sort_by { |resource| resource[:resource_name] }
|
12
|
+
end
|
13
|
+
module_function :sections
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'rspec_api_documentation/writers/formatter'
|
2
|
+
|
3
|
+
module RspecApiDocumentation
|
4
|
+
module Writers
|
5
|
+
class JsonIodocsWriter
|
6
|
+
attr_accessor :index, :configuration, :api_key
|
7
|
+
delegate :docs_dir, :to => :configuration
|
8
|
+
|
9
|
+
def initialize(index, configuration)
|
10
|
+
self.index = index
|
11
|
+
self.configuration = configuration
|
12
|
+
self.api_key = configuration.api_name.parameterize
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.write(index, configuration)
|
16
|
+
writer = new(index, configuration)
|
17
|
+
writer.write
|
18
|
+
end
|
19
|
+
|
20
|
+
def write
|
21
|
+
File.open(docs_dir.join("apiconfig.json"), "w+") do |file|
|
22
|
+
file.write Formatter.to_json(ApiConfig.new(configuration))
|
23
|
+
end
|
24
|
+
File.open(docs_dir.join("#{api_key}.json"), "w+") do |file|
|
25
|
+
file.write Formatter.to_json(JsonIndex.new(index, configuration))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class JsonIndex
|
31
|
+
def initialize(index, configuration)
|
32
|
+
@index = index
|
33
|
+
@configuration = configuration
|
34
|
+
end
|
35
|
+
|
36
|
+
def sections
|
37
|
+
IndexWriter.sections(examples, @configuration)
|
38
|
+
end
|
39
|
+
|
40
|
+
def examples
|
41
|
+
@index.examples.map { |example| JsonExample.new(example, @configuration) }
|
42
|
+
end
|
43
|
+
|
44
|
+
def as_json(opts = nil)
|
45
|
+
sections.inject({:endpoints => []}) do |h, section|
|
46
|
+
h[:endpoints].push(
|
47
|
+
:name => section[:resource_name],
|
48
|
+
:methods => section[:examples].map do |example|
|
49
|
+
example.as_json(opts)
|
50
|
+
end
|
51
|
+
)
|
52
|
+
h
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class JsonExample
|
58
|
+
def initialize(example, configuration)
|
59
|
+
@example = example
|
60
|
+
end
|
61
|
+
|
62
|
+
def method_missing(method, *args, &block)
|
63
|
+
@example.send(method, *args, &block)
|
64
|
+
end
|
65
|
+
|
66
|
+
def parameters
|
67
|
+
params = []
|
68
|
+
if @example.respond_to?(:parameters)
|
69
|
+
@example.parameters.map do |param|
|
70
|
+
params << {
|
71
|
+
"Name" => param[:name],
|
72
|
+
"Description" => param[:description],
|
73
|
+
"Default" => "",
|
74
|
+
"Required" => param[:required] ? "Y" : "N"
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
params
|
79
|
+
end
|
80
|
+
|
81
|
+
def as_json(opts = nil)
|
82
|
+
{
|
83
|
+
:MethodName => description,
|
84
|
+
:Synopsis => explanation,
|
85
|
+
:HTTPMethod => http_method,
|
86
|
+
:URI => (requests.first[:request_path] rescue ""),
|
87
|
+
:RequiresOAuth => "N",
|
88
|
+
:parameters => parameters
|
89
|
+
}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class ApiConfig
|
94
|
+
def initialize(configuration)
|
95
|
+
@configuration = configuration
|
96
|
+
@api_key = configuration.api_name.parameterize
|
97
|
+
end
|
98
|
+
|
99
|
+
def as_json(opts = nil)
|
100
|
+
{
|
101
|
+
@api_key.to_sym => {
|
102
|
+
:name => @configuration.api_name,
|
103
|
+
:protocol => @configuration.io_docs_protocol,
|
104
|
+
:publicPath => "",
|
105
|
+
:baseURL => @configuration.curl_host
|
106
|
+
}
|
107
|
+
}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'rspec_api_documentation/writers/formatter'
|
2
|
+
|
3
|
+
module RspecApiDocumentation
|
4
|
+
module Writers
|
5
|
+
class JsonWriter
|
6
|
+
attr_accessor :index, :configuration
|
7
|
+
delegate :docs_dir, :to => :configuration
|
8
|
+
|
9
|
+
def initialize(index, configuration)
|
10
|
+
self.index = index
|
11
|
+
self.configuration = configuration
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.write(index, configuration)
|
15
|
+
writer = new(index, configuration)
|
16
|
+
writer.write
|
17
|
+
end
|
18
|
+
|
19
|
+
def write
|
20
|
+
File.open(docs_dir.join("index.json"), "w+") do |f|
|
21
|
+
f.write Formatter.to_json(JsonIndex.new(index, configuration))
|
22
|
+
end
|
23
|
+
index.examples.each do |example|
|
24
|
+
json_example = JsonExample.new(example, configuration)
|
25
|
+
FileUtils.mkdir_p(docs_dir.join(json_example.dirname))
|
26
|
+
File.open(docs_dir.join(json_example.dirname, json_example.filename), "w+") do |f|
|
27
|
+
f.write Formatter.to_json(json_example)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class JsonIndex
|
34
|
+
def initialize(index, configuration)
|
35
|
+
@index = index
|
36
|
+
@configuration = configuration
|
37
|
+
end
|
38
|
+
|
39
|
+
def sections
|
40
|
+
IndexWriter.sections(examples, @configuration)
|
41
|
+
end
|
42
|
+
|
43
|
+
def examples
|
44
|
+
@index.examples.map { |example| JsonExample.new(example, @configuration) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def as_json(opts = nil)
|
48
|
+
sections.inject({:resources => []}) do |h, section|
|
49
|
+
h[:resources].push(
|
50
|
+
:name => section[:resource_name],
|
51
|
+
:examples => section[:examples].map { |example|
|
52
|
+
{
|
53
|
+
:description => example.description,
|
54
|
+
:link => "#{example.dirname}/#{example.filename}",
|
55
|
+
:groups => example.metadata[:document]
|
56
|
+
}
|
57
|
+
}
|
58
|
+
)
|
59
|
+
h
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class JsonExample
|
65
|
+
def initialize(example, configuration)
|
66
|
+
@example = example
|
67
|
+
@host = configuration.curl_host
|
68
|
+
end
|
69
|
+
|
70
|
+
def method_missing(method, *args, &block)
|
71
|
+
@example.send(method, *args, &block)
|
72
|
+
end
|
73
|
+
|
74
|
+
def respond_to?(method, include_private = false)
|
75
|
+
super || @example.respond_to?(method, include_private)
|
76
|
+
end
|
77
|
+
|
78
|
+
def dirname
|
79
|
+
resource_name.downcase.gsub(/\s+/, '_')
|
80
|
+
end
|
81
|
+
|
82
|
+
def filename
|
83
|
+
basename = description.downcase.gsub(/\s+/, '_').gsub(/[^a-z_]/, '')
|
84
|
+
"#{basename}.json"
|
85
|
+
end
|
86
|
+
|
87
|
+
def as_json(opts = nil)
|
88
|
+
{
|
89
|
+
:resource => resource_name,
|
90
|
+
:http_method => http_method,
|
91
|
+
:route => route,
|
92
|
+
:description => description,
|
93
|
+
:explanation => explanation,
|
94
|
+
:parameters => respond_to?(:parameters) ? parameters : [],
|
95
|
+
:requests => requests
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
def requests
|
100
|
+
super.map do |hash|
|
101
|
+
if @host
|
102
|
+
hash[:curl] = hash[:curl].output(@host) if hash[:curl].is_a? RspecApiDocumentation::Curl
|
103
|
+
else
|
104
|
+
hash[:curl] = nil
|
105
|
+
end
|
106
|
+
hash
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|