rspec-api-blueprint-formatter 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: caa97c97bdc0ff1c45846a5d0941f76ff950e483
4
- data.tar.gz: 333ffb493e1e9289ae840e13f22b63e1cdb7860e
3
+ metadata.gz: e639084209b7c2eb7969f4bf4472bde50b48b7ca
4
+ data.tar.gz: d3498d9b1ee41bcbaf92b0345b1700bc8749db04
5
5
  SHA512:
6
- metadata.gz: df31b52419a0594e5e3868648fb626267206e6788aaa8bf280f3781b4254e1d49c2dff1ce760f06e19fd6a32bec1d68ed8ce186a5250bf38982951330515ed15
7
- data.tar.gz: 5fce90486bb6df004c785313aaea5cab8081a8383e5a1017c3e572611078d302ac6075a4f43b003b7bacfd969368478d0ef0a6bcdafd1def6aa26b85d099fe23
6
+ metadata.gz: 7e79fc9af3465c1bc7fc329d440fa8635b56445a83c0a9e3f8cc9f0c19fdefffba87f006dbfa4e4ff0972ab9cbe477ebfa660ab929cebe7dfce61e5f5d4ee0ea
7
+ data.tar.gz: 871449a2bc0e3d2f8a22e47dc260e4a4b720bb4261dc53dfeed9e1b90db9ea98f8ad0a1f4f0fcf82bf4c71001f2d500a9c15470c6789d4245a166dca0b8791ba
data/lib/api_blueprint.rb CHANGED
@@ -1,8 +1,12 @@
1
1
  require 'rspec'
2
2
  require 'rspec/core/formatters/base_formatter'
3
3
 
4
+ require 'api_blueprint/version'
5
+ require 'api_blueprint/base_formatter'
6
+ require 'api_blueprint/example_formatter'
7
+ require 'api_blueprint/action_formatter'
8
+
4
9
  class ApiBlueprint < RSpec::Core::Formatters::BaseFormatter
5
- VERSION = "0.1.3"
6
10
  RSpec::Core::Formatters.register self, :example_passed, :example_started, :stop
7
11
 
8
12
  def initialize(output)
@@ -34,6 +38,7 @@ class ApiBlueprint < RSpec::Core::Formatters::BaseFormatter
34
38
  metadata[:resource] => {
35
39
  metadata[:action] => {
36
40
  description: metadata[:action_description],
41
+ parameters: metadata[:action_parameters],
37
42
  examples: {
38
43
  description => {
39
44
  request: {
@@ -84,30 +89,14 @@ class ApiBlueprint < RSpec::Core::Formatters::BaseFormatter
84
89
  actions.each &method(:print_action)
85
90
  end
86
91
 
87
- def print_action(action_name, action_meta_data)
88
- output.puts "## #{action_name}\n" \
89
- "\n" \
90
- "#{action_meta_data[:description]}\n" \
91
- "\n" \
92
+ def print_action(action_name, action_metadata)
93
+ output.puts ApiBlueprintFormatter::ActionFormatter.new(action_name, action_metadata).format
92
94
 
93
- action_meta_data[:examples].each &method(:print_example)
95
+ action_metadata[:examples].each &method(:print_example)
94
96
  end
95
97
 
96
98
  def print_example(example_description, example_metadata)
97
- output.puts "+ Request #{example_description}\n" \
98
- "\n" \
99
- " #{example_metadata[:request][:parameters]}\n" \
100
- " \n" \
101
- " Location: #{example_metadata[:location]}\n" \
102
- " Source code:\n" \
103
- " \n" \
104
- "#{indent_lines(8, example_metadata[:source])}\n" \
105
- "\n"
106
-
107
- output.puts "+ Response #{example_metadata[:response][:status]} (#{example_metadata[:request][:format]})\n" \
108
- "\n" \
109
- " #{example_metadata[:response][:body]}\n" \
110
- "\n"
99
+ output.puts ApiBlueprintFormatter::ExampleFormatter.new(example_description, example_metadata).format
111
100
  end
112
101
 
113
102
  # To include the descriptions of all the contexts that are below the action
@@ -121,11 +110,4 @@ class ApiBlueprint < RSpec::Core::Formatters::BaseFormatter
121
110
  [example_metadata[:description]] + description_array_from(parent)
122
111
  end
123
112
  end
124
-
125
- def indent_lines(number_of_spaces, string)
126
- string
127
- .split("\n")
128
- .map { |a| a.prepend(' ' * number_of_spaces) }
129
- .join("\n")
130
- end
131
113
  end
@@ -0,0 +1,93 @@
1
+ module ApiBlueprintFormatter
2
+ # Parses example metadata for Actions and outputs markdown in
3
+ # accordance with the API Blueprint spec.
4
+ #
5
+ # Spec: https://github.com/apiaryio/api-blueprint/blob/master/API%20Blueprint%20Specification.md#def-action-section
6
+ class ActionFormatter < BaseFormatter
7
+ attr_reader :action_metadata, :action_name
8
+
9
+ def initialize(action_name, action_metadata)
10
+ @action_name = action_name
11
+ @action_metadata = action_metadata
12
+ @parameters = action_metadata[:parameters] || []
13
+ end
14
+
15
+ def format
16
+ output = []
17
+ output << "## #{action_name}"
18
+ output << ''
19
+ output << action_metadata[:description].to_s
20
+ output << ''
21
+ output += format_parameters
22
+ output << ''
23
+
24
+ output.join("\n")
25
+ end
26
+
27
+ private
28
+
29
+ def format_parameters
30
+ return [] if @parameters.empty?
31
+
32
+ output = ['']
33
+ output << '+ Parameters'
34
+ @parameters.each_pair do |param, data|
35
+ output += format_param(param, data)
36
+ end
37
+ output << ''
38
+
39
+ output
40
+ end
41
+
42
+ def format_param(param, data)
43
+ out = []
44
+ out << indent_lines(4, action_header(param, data))
45
+
46
+ if multiline_description(param)
47
+ out << ''
48
+ out << indent_lines(8, data[:description])
49
+ out << ''
50
+ end
51
+
52
+ out << indent_lines(8, "+ Default: #{data[:default]}") if data[:default]
53
+ out += format_members(param)
54
+
55
+ out
56
+ end
57
+
58
+ def multiline_description(param)
59
+ members(param).size > 0
60
+ end
61
+
62
+ def action_header(param, data)
63
+ param_signature = "#{param}#{param_attributes_string(data)}"
64
+ multiline_description = !members(param).empty?
65
+
66
+ header = "+ #{param_signature}"
67
+ header += " - #{data[:description]}" unless multiline_description
68
+ header
69
+ end
70
+
71
+ def param_attributes_string(data)
72
+ optional = data[:optional] ? 'optional' : nil
73
+ param_attributes = [data[:type], optional].compact
74
+
75
+ " (#{param_attributes.join(', ')})" unless param_attributes.empty?
76
+ end
77
+
78
+ def members(param)
79
+ @action_metadata[:parameters][param].fetch(:members, [])
80
+ end
81
+
82
+ def format_members(param)
83
+ out = []
84
+ unless members(param).empty?
85
+ out << indent_lines(8, '+ Members')
86
+ members(param).each do |member|
87
+ out << indent_lines(12, "+ `#{member}`")
88
+ end
89
+ end
90
+ out
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,20 @@
1
+ module ApiBlueprintFormatter
2
+ # Base for other formatters, providing utility methods
3
+ class BaseFormatter
4
+ protected
5
+
6
+ def indent_lines(number_of_spaces, string)
7
+ string
8
+ .split("\n")
9
+ .map { |a| a.prepend(' ' * number_of_spaces) }
10
+ .join("\n")
11
+ end
12
+
13
+ # Change certain characters that might come up in example names
14
+ # but do not play well with the API specs.
15
+ # Example: 'Test for [value]' -> 'Test for {value}'
16
+ def sanitize_api_identifier(name)
17
+ name.gsub(/[\[\]]/, '[' => '{', ']' => '}')
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,47 @@
1
+ module ApiBlueprintFormatter
2
+ # Parses example metadata for Examples (Request+Response) and outputs
3
+ # markdown in accordance with the API Blueprint spec.
4
+ #
5
+ # Specs:
6
+ # - https://github.com/apiaryio/api-blueprint/blob/master/API%20Blueprint%20Specification.md#def-request-section
7
+ # - https://github.com/apiaryio/api-blueprint/blob/master/API%20Blueprint%20Specification.md#response-section
8
+ class ExampleFormatter < BaseFormatter
9
+ attr_reader :example_metadata
10
+
11
+ def initialize(example_description, example_metadata)
12
+ @example_description = example_description
13
+ @example_metadata = example_metadata
14
+ end
15
+
16
+ def format
17
+ out = ''
18
+ out << format_request
19
+ out << format_response
20
+ end
21
+
22
+ def example_description
23
+ sanitize_api_identifier(@example_description)
24
+ end
25
+
26
+ private
27
+
28
+ def format_request
29
+ "+ Request #{example_description}\n" \
30
+ "\n" \
31
+ " #{example_metadata[:request][:parameters]}\n" \
32
+ "\n" \
33
+ " Location: #{example_metadata[:location]}\n" \
34
+ " Source code:\n" \
35
+ "\n" \
36
+ "#{indent_lines(8, example_metadata[:source])}\n" \
37
+ "\n"
38
+ end
39
+
40
+ def format_response
41
+ "+ Response #{example_metadata[:response][:status]} (#{example_metadata[:request][:format]})\n" \
42
+ "\n" \
43
+ " #{example_metadata[:response][:body]}\n" \
44
+ "\n"
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module ApiBlueprintFormatter
2
+ VERSION = '0.2.0'
3
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ require 'json'
4
+
5
+ RSpec.describe ApiBlueprintFormatter::ActionFormatter do
6
+ subject { described_class.new(action_name, action_metadata).format }
7
+
8
+ let(:action_name) { 'Standard Action [GET /api/v0/resource]' }
9
+ let(:action_metadata) { { description: action_description, parameters: action_parameters } }
10
+
11
+ let(:action_description) { 'Lorem ipsum et dolor' }
12
+ let(:action_parameters) { {} }
13
+
14
+ describe '#format' do
15
+ context 'with standard meta-data' do
16
+ it 'formats properly' do
17
+ is_expected.to eq "## Standard Action [GET /api/v0/resource]\n\nLorem ipsum et dolor\n\n"
18
+ end
19
+ end
20
+
21
+ context 'with parameters' do
22
+ let(:action_header) { "## #{action_name}\n\n#{action_description}\n" }
23
+
24
+ context 'only descriptive params' do
25
+ let(:action_parameters) do
26
+ {
27
+ id: { description: 'Id of a post' }
28
+ }
29
+ end
30
+
31
+ it do
32
+ is_expected.to eq <<-EOF
33
+ #{action_header}
34
+
35
+ + Parameters
36
+ + id - Id of a post
37
+
38
+ EOF
39
+ end
40
+ end
41
+
42
+ context 'descriptive param with type' do
43
+ let(:action_parameters) do
44
+ {
45
+ id: { description: 'Id of a post', type: :number }
46
+ }
47
+ end
48
+
49
+ it do
50
+ is_expected.to eq <<-EOF
51
+ #{action_header}
52
+
53
+ + Parameters
54
+ + id (number) - Id of a post
55
+
56
+ EOF
57
+ end
58
+ end
59
+
60
+ context 'descriptive param with type and optionality' do
61
+ let(:action_parameters) do
62
+ {
63
+ amount: { description: 'Id of a post', type: :number, optional: true }
64
+ }
65
+ end
66
+
67
+ it do
68
+ is_expected.to eq <<-EOF
69
+ #{action_header}
70
+
71
+ + Parameters
72
+ + amount (number, optional) - Id of a post
73
+
74
+ EOF
75
+ end
76
+ end
77
+
78
+ context 'descriptive param with: type, optionality, default value' do
79
+ let(:action_parameters) do
80
+ {
81
+ amount: { description: 'Id of a post', type: :number, optional: true, default: 0 }
82
+ }
83
+ end
84
+
85
+ it do
86
+ is_expected.to eq <<-EOF
87
+ #{action_header}
88
+
89
+ + Parameters
90
+ + amount (number, optional) - Id of a post
91
+ + Default: 0
92
+
93
+ EOF
94
+ end
95
+ end
96
+
97
+ context 'descriptive param with: enum and members' do
98
+ let(:action_parameters) do
99
+ {
100
+ id: { description: 'Id of a post', type: 'enum[string]', members: %w(A B C) }
101
+ }
102
+ end
103
+
104
+ it do
105
+ is_expected.to eq <<-EOF
106
+ #{action_header}
107
+
108
+ + Parameters
109
+ + id (enum[string])
110
+
111
+ Id of a post
112
+
113
+ + Members
114
+ + `A`
115
+ + `B`
116
+ + `C`
117
+
118
+ EOF
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ require 'json'
4
+
5
+ RSpec.describe ApiBlueprintFormatter::ExampleFormatter do
6
+ subject { described_class.new(example_description, example_metadata).format }
7
+
8
+ let(:example_description) { "Standard Request" }
9
+ let(:example_metadata) do
10
+ {
11
+ request: request_metadata,
12
+ response: response_metadata,
13
+ location: location,
14
+ source: source
15
+ }
16
+ end
17
+
18
+ let(:request_metadata) { { parameters: {}, format: 'application/json' } }
19
+ let(:response_metadata) { { status: 200, body: JSON.generate({a:1, b:2, c:3}) } }
20
+ let(:location) { "spec/api_blueprint/example_formatter_spec.rb" }
21
+ let(:source) { "it 'returns standard APi Blueprint format' do\n ;\nend" }
22
+
23
+
24
+ describe '#format' do
25
+ context 'with standard meta-data' do
26
+ it 'formats properly' do
27
+ is_expected.to eq <<EOF
28
+ + Request Standard Request
29
+
30
+ {}
31
+
32
+ Location: spec/api_blueprint/example_formatter_spec.rb
33
+ Source code:
34
+
35
+ it 'returns standard APi Blueprint format' do
36
+ ;
37
+ end
38
+
39
+ + Response 200 (application/json)
40
+
41
+ {"a":1,"b":2,"c":3}
42
+
43
+ EOF
44
+ end
45
+
46
+ context 'and with parameters' do
47
+ context 'from request data' do
48
+ let(:request_metadata) { { parameters: {'p1': 'v1', 'p2': 'v2'}, format: 'application/json' } }
49
+
50
+ it 'formats properly' do
51
+ is_expected.to eq <<EOF
52
+ + Request Standard Request
53
+
54
+ {:p1=>"v1", :p2=>"v2"}
55
+
56
+ Location: spec/api_blueprint/example_formatter_spec.rb
57
+ Source code:
58
+
59
+ it 'returns standard APi Blueprint format' do
60
+ ;
61
+ end
62
+
63
+ + Response 200 (application/json)
64
+
65
+ {"a":1,"b":2,"c":3}
66
+
67
+ EOF
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ describe '#example_description' do
76
+ subject { described_class.new(example_description, example_metadata).example_description }
77
+
78
+ context 'when description has non-compliant characters' do
79
+ let(:example_description) { 'Standard Request for [company]' }
80
+
81
+ it 'changes [] to {}' do
82
+ expect(subject).to eq 'Standard Request for {company}'
83
+ end
84
+ end
85
+ end
86
+
87
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe ApiBlueprint do
3
+ describe ApiBlueprintFormatter do
4
4
  it 'has a version number' do
5
- expect(ApiBlueprint::VERSION).not_to be nil
5
+ expect(ApiBlueprintFormatter::VERSION).not_to be nil
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-api-blueprint-formatter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nam Chu Hoai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-01 00:00:00.000000000 Z
11
+ date: 2016-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -64,6 +64,12 @@ files:
64
64
  - bin/console
65
65
  - bin/setup
66
66
  - lib/api_blueprint.rb
67
+ - lib/api_blueprint/action_formatter.rb
68
+ - lib/api_blueprint/base_formatter.rb
69
+ - lib/api_blueprint/example_formatter.rb
70
+ - lib/api_blueprint/version.rb
71
+ - spec/api_blueprint/action_formatter_spec.rb
72
+ - spec/api_blueprint/example_formatter_spec.rb
67
73
  - spec/rspec/api/blueprint/formatter_spec.rb
68
74
  - spec/spec_helper.rb
69
75
  homepage: https://github.com/nambrot/rspec-api-blueprint-formatter
@@ -92,6 +98,8 @@ signing_key:
92
98
  specification_version: 4
93
99
  summary: Use your Rspec tests to build your API documentation
94
100
  test_files:
101
+ - spec/api_blueprint/action_formatter_spec.rb
102
+ - spec/api_blueprint/example_formatter_spec.rb
95
103
  - spec/rspec/api/blueprint/formatter_spec.rb
96
104
  - spec/spec_helper.rb
97
105
  has_rdoc: