Skip to content

Commit 2f56cb8

Browse files
author
yld
authored
Merge pull request #2 from icidasset/fix-api-blueprint-format
More API Blueprint fixes
2 parents 96fbd74 + b2ec981 commit 2f56cb8

File tree

11 files changed

+111
-38
lines changed

11 files changed

+111
-38
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
doc
12
tmp
23
.rvmrc
34
.ruby-version

Gemfile.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ GEM
5757
multipart-post (>= 1.2, < 3)
5858
ffi (1.9.10)
5959
gherkin (3.2.0)
60-
hashdiff (0.2.3)
60+
hashdiff (0.3.7)
6161
httpclient (2.7.1)
6262
i18n (0.7.0)
6363
inch (0.7.0)
@@ -129,7 +129,7 @@ GEM
129129
tins (1.8.2)
130130
tzinfo (1.2.2)
131131
thread_safe (~> 0.1)
132-
webmock (1.22.6)
132+
webmock (3.3.0)
133133
addressable (>= 2.3.6)
134134
crack (>= 0.3.2)
135135
hashdiff
@@ -154,7 +154,7 @@ DEPENDENCIES
154154
rspec_api_documentation!
155155
sinatra (~> 1.4, >= 1.4.4)
156156
thin (~> 1.6, >= 1.6.3)
157-
webmock (~> 1.7)
157+
webmock (~> 3.3)
158158

159159
BUNDLED WITH
160160
1.16.1

lib/rspec_api_documentation/configuration.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ def self.add_setting(name, opts = {})
8181
add_setting :response_headers_to_include, :default => nil
8282
add_setting :html_embedded_css_file, :default => nil
8383

84+
# sorting
85+
add_setting :sort_routes, :default => false
86+
8487
# renamed to request_body_formatter. here for backwards compatibility
8588
add_setting :post_body_formatter, :default => nil
8689

lib/rspec_api_documentation/dsl/endpoint/params.rb

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,19 @@ def initialize(example_group, example, extra_params)
1313
end
1414

1515
def call
16-
parameters = example.metadata.fetch(:parameters, {}).inject({}) do |hash, param|
16+
set_param = -> hash, param {
1717
SetParam.new(self, hash, param).call
18-
end
19-
parameters.deep_merge!(extra_params)
20-
parameters
18+
}
19+
20+
example.metadata
21+
.fetch(:parameters, {})
22+
.inject({}, &set_param)
23+
.deep_merge(
24+
example.metadata
25+
.fetch(:attributes, {})
26+
.inject({}, &set_param)
27+
)
28+
.deep_merge(extra_params)
2129
end
2230

2331
private

lib/rspec_api_documentation/dsl/resource.rb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,25 @@ def self.define_action(method)
88
define_method method do |*args, &block|
99
options = args.extract_options!
1010
options[:method] = method
11+
1112
if metadata[:route_uri]
1213
options[:route] = metadata[:route_uri]
1314
options[:action_name] = args.first
15+
1416
else
1517
options[:route] = args.first
18+
options[:route_uri] = args[0].gsub(/\{.*\}/, "")
19+
options[:route_optionals] = (optionals = args[0].match(/(\{.*\})/) and optionals[-1])
20+
options[:route_name] = options[:route_name] || options[:route]
21+
options[:action_name] = options[:action_name] || method.to_s.upcase
22+
1623
end
24+
1725
options[:api_doc_dsl] = :endpoint
26+
1827
args.push(options)
1928
args[0] = "#{method.to_s.upcase} #{args[0]}"
29+
2030
context(*args, &block)
2131
end
2232
end
@@ -30,7 +40,7 @@ def self.define_action(method)
3040

3141
def callback(*args, &block)
3242
begin
33-
require 'webmock'
43+
require 'webmock/rspec'
3444
rescue LoadError
3545
raise "Callbacks require webmock to be installed"
3646
end
@@ -71,7 +81,13 @@ def header(name, value)
7181
end
7282

7383
def explanation(text)
74-
safe_metadata(:resource_explanation, text)
84+
if metadata[:method].present?
85+
safe_metadata(:method_explanation, text)
86+
elsif metadata[:route_uri].present?
87+
safe_metadata(:route_explanation, text)
88+
else
89+
safe_metadata(:resource_explanation, text)
90+
end
7591
end
7692

7793
private

lib/rspec_api_documentation/views/api_blueprint_index.rb

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,33 @@ def sections
1212
attrs = fields(:attributes, examples)
1313
params = fields(:parameters, examples)
1414

15-
methods = examples.group_by(&:http_method).map do |http_method, examples|
16-
{
17-
http_method: http_method,
18-
description: examples.first.respond_to?(:action_name) && examples.first.action_name,
19-
examples: examples
20-
}
21-
end
15+
methods = examples
16+
.group_by { |e| "#{e.http_method} - #{e.action_name}" }
17+
.map do |group, examples|
18+
first_example = examples.first
19+
20+
{
21+
http_method: first_example.try(:http_method),
22+
description: first_example.try(:action_name),
23+
explanation: first_example.try(:[], :metadata).try(:[], :method_explanation),
24+
examples: examples
25+
}
26+
end
2227

2328
{
2429
"has_attributes?".to_sym => attrs.size > 0,
2530
"has_parameters?".to_sym => params.size > 0,
2631
route: format_route(examples[0]),
2732
route_name: examples[0][:route_name],
33+
explanation: examples[0][:route_explanation],
2834
attributes: attrs,
2935
parameters: params,
3036
http_methods: methods
3137
}
3238
end
3339

3440
section.merge({
35-
routes: routes
41+
routes: @configuration.sort_routes ? routes.sort_by { |r| r[:route_name] } : routes
3642
})
3743
end
3844
end
@@ -60,11 +66,10 @@ def format_route(example)
6066
# with all of its properties, like name, description, required.
6167
# {
6268
# required: true,
63-
# example: "1",
6469
# type: "string",
6570
# name: "id",
6671
# description: "The id",
67-
# properties_description: "required, string"
72+
# properties_description: "string, required"
6873
# }
6974
def fields(property_name, examples)
7075
examples
@@ -74,8 +79,10 @@ def fields(property_name, examples)
7479
.uniq { |property| property[:name] }
7580
.map do |property|
7681
properties = []
77-
properties << "required" if property[:required]
7882
properties << property[:type] if property[:type]
83+
properties << "required" if property[:required] == true
84+
properties << "optional" if property[:required].blank?
85+
7986
if properties.count > 0
8087
property[:properties_description] = properties.join(", ")
8188
else

rspec_api_documentation.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
2626
s.add_development_dependency "rake", "~> 10.1"
2727
s.add_development_dependency "rack-test", "~> 0.6.2"
2828
s.add_development_dependency "rack-oauth2", "~> 1.2.2", ">= 1.0.7"
29-
s.add_development_dependency "webmock", "~> 1.7"
29+
s.add_development_dependency "webmock", "~> 3.3"
3030
s.add_development_dependency "rspec-its", "~> 1.0"
3131
s.add_development_dependency "faraday", "~> 0.9", ">= 0.9.0"
3232
s.add_development_dependency "thin", "~> 1.6", ">= 1.6.3"

spec/dsl_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,12 @@
130130
parameter :id, 'The ID of the resource.', :required => true, scope: :data
131131
parameter :note, "Any additional notes about your order."
132132

133+
attribute :tip, "The amount you want to tip", :required => true
134+
133135
let(:type) { "coffee" }
134136
let(:size) { "medium" }
135137
let(:data_id) { 2 }
138+
let(:tip) { 20 }
136139

137140
let(:id) { 1 }
138141

@@ -157,6 +160,10 @@
157160
expect(params['data']).to eq({'id' => 2})
158161
end
159162

163+
it "should set attributes as well" do
164+
expect(params["tip"]).to eq(tip())
165+
end
166+
160167
it "should allow extra parameters to be passed in" do
161168
expect(client).to receive(method).with(path, params.merge("extra" => true), nil)
162169
do_request(:extra => true)

spec/http_test_client_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
require 'capybara'
44
require 'capybara/server'
55
require 'sinatra/base'
6-
require 'webmock'
6+
require 'webmock/rspec'
77
require 'support/stub_app'
88

99
describe RspecApiDocumentation::HttpTestClient do
@@ -16,7 +16,7 @@
1616
Rack::Handler::Thin.run(app, :Port => port)
1717
end
1818

19-
server = Capybara::Server.new(StubApp.new, 8888)
19+
server = Capybara::Server.new(StubApp.new, 29876)
2020
server.boot
2121
end
2222

@@ -25,7 +25,7 @@
2525
end
2626

2727
let(:client_context) { |example| double(example: example, app_root: 'nowhere') }
28-
let(:target_host) { 'http://localhost:8888' }
28+
let(:target_host) { 'http://localhost:29876' }
2929
let(:test_client) { RspecApiDocumentation::HttpTestClient.new(client_context, {host: target_host}) }
3030

3131
subject { test_client }

spec/views/api_blueprint_index_spec.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@
6363

6464
let(:rspec_example_comments) do
6565
comment_group.route "/comments", "Comments Collection" do
66+
explanation "Route explanation"
67+
6668
get("/comments") do
69+
explanation "Method explanation"
6770
example_request 'Get all comments' do
6871
end
6972
end
@@ -98,6 +101,8 @@
98101
post_route = sections[1][:routes][1]
99102
post_route_with_optionals = sections[1][:routes][2]
100103

104+
expect(comments_route[:explanation]).to eq "Route explanation"
105+
101106
comments_examples = comments_route[:http_methods].map { |http_method| http_method[:examples] }.flatten
102107
expect(comments_examples.size).to eq 1
103108
expect(comments_route[:route]).to eq "/comments"
@@ -118,7 +123,7 @@
118123
example: "1",
119124
name: "id",
120125
description: "The id",
121-
properties_description: "required, string"
126+
properties_description: "string, required"
122127
}]
123128
expect(post_route[:has_attributes?]).to eq true
124129
expect(post_route[:attributes]).to eq [{
@@ -139,11 +144,11 @@
139144
example: "1",
140145
name: "id",
141146
description: "The id",
142-
properties_description: "required, string"
147+
properties_description: "string, required"
143148
}, {
144149
name: "option",
145150
description: nil,
146-
properties_description: nil
151+
properties_description: "optional"
147152
}]
148153
expect(post_route_with_optionals[:has_attributes?]).to eq false
149154
expect(post_route_with_optionals[:attributes]).to eq []
@@ -159,7 +164,7 @@
159164
required: false,
160165
name: "description",
161166
description: nil,
162-
properties_description: nil
167+
properties_description: "optional"
163168
}]
164169
end
165170
end

templates/rspec_api_documentation/api_blueprint_index.mustache

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
FORMAT: 1A
2+
23
# {{ api_name }}
4+
{{{ api_explanation }}}
5+
36
{{# sections }}
47

58
# Group {{ resource_name }}
@@ -16,34 +19,57 @@ FORMAT: 1A
1619
## {{ route_name }} [{{ route }}]
1720
{{# description }}
1821

19-
description: {{ description }}
22+
{{ description }}
2023
{{/ description }}
2124
{{# explanation }}
2225

23-
explanation: {{ explanation }}
26+
{{{ explanation }}}
2427
{{/ explanation }}
2528
{{# has_parameters? }}
2629

2730
+ Parameters
31+
2832
{{# parameters }}
29-
+ {{ name }}{{# example }}: {{ example }}{{/ example }}{{# properties_description }} ({{ properties_description }}){{/ properties_description }}{{# description }} - {{ description }}{{/ description }}
33+
+ {{ name }}{{# properties_description }} ({{ properties_description }}){{/ properties_description }}
34+
{{# description }}
35+
36+
{{ description }}
37+
{{/ description }}
3038
{{/ parameters }}
3139
{{/ has_parameters? }}
32-
{{# has_attributes? }}
33-
34-
+ Attributes (object)
35-
{{# attributes }}
36-
+ {{ name }}{{# example }}: {{ example }}{{/ example }}{{# properties_description }} ({{ properties_description }}){{/ properties_description }}{{# description }} - {{ description }}{{/ description }}
37-
{{/ attributes }}
38-
{{/ has_attributes? }}
3940
{{# http_methods }}
4041

4142
### {{ description }} [{{ http_method }}]
43+
{{# explanation }}
44+
45+
{{{ explanation }}}
46+
{{/ explanation }}
47+
4248
{{# examples }}
4349
{{# requests }}
50+
{{# has_attributes? }}
51+
52+
+ Parameters
53+
54+
{{# attributes }}
55+
+ {{ name }}{{# value }}: {{ value }}{{/ value }}{{# properties_description }} ({{ properties_description }}){{/ properties_description }}
56+
{{# description }}
57+
58+
{{ description }}
59+
{{/ description }}
60+
{{# default }}
61+
62+
+ Default: {{ default }}
63+
{{/ default }}
64+
{{/ attributes }}
65+
{{/ has_attributes? }}
4466
{{# has_request? }}
4567

4668
+ Request {{ description }}{{# request_content_type }} ({{ request_content_type }}){{/ request_content_type }}
69+
70+
{{# explanation }}
71+
{{{ explanation }}}
72+
{{/ explanation }}
4773
{{/ has_request? }}
4874
{{# request_headers_text }}
4975

0 commit comments

Comments
 (0)