rspec-api-blueprint-formatter 0.1.3 → 0.2.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.
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: