rspec-document_requests 1.1.0 → 1.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: 231e877c797beff56b6713d86e7247cf7e31ea72
4
- data.tar.gz: 06f5cbf0269fa7c3d5f772425081619327ef7ab7
3
+ metadata.gz: 7c1fd117650183a8e2b17f41acfeb19bcd011251
4
+ data.tar.gz: 582ddbaa7fd602d131b676747a10b084172fb479
5
5
  SHA512:
6
- metadata.gz: efc0c7d69098f85741a3cbc27e395e6addb62510226ac4398a4c27e624d3c910e8eeb4dbb488c5d27e0e1219c1852eda4b14749569ec7239392789cc9f7cf116
7
- data.tar.gz: 3cff5a55338cf639810fc696855c0aa9089f78e5629969447c7f5ddfa6eb157a7cf07c32fa419b9c1ffb17e65698c4ba4ec4a22f3e7b6683bed850fe8442f0d1
6
+ metadata.gz: e31e5dcc0518b3c6305ad60a8ac1f34dd2047ccd4a5759aaf4ffebc7a4b79764cce964edc29ca069338314e21a31e9bab892a269d2d8feeb63c50217f97bdd8b
7
+ data.tar.gz: 8952825398234193dc0dad866685978a5fd4e5e601bbd9a3258e91dc53ed6ed8835b6612df2acaa2993100972656849640e8b8e2c34f7e3f67e7f9eff829a103
data/README.md CHANGED
@@ -44,6 +44,8 @@ require 'rspec/document_requests/dsl' # <- this line
44
44
 
45
45
  ### Marking code to document
46
46
 
47
+ **NOTE:** The `nodoc` DSL is not available in example groups (`describe`/`context`) without `doc: true`.
48
+
47
49
  In your example group (`describe`/`context`), simply add the `doc: true` metadata:
48
50
 
49
51
  ```ruby
@@ -85,7 +87,7 @@ also exclude any specs without `doc: true` metadata to make this run faster.
85
87
 
86
88
  ### Explaining the request
87
89
 
88
- **NOTE:** This DSL is not available in `doc: false` example groups (`describe`/`context`).
90
+ **NOTE:** The `explain` DSL is not available in example groups (`describe`/`context`) without `doc: true`.
89
91
 
90
92
  Just before your request, it's a good idea to explain (everything is optional):
91
93
 
@@ -93,20 +95,20 @@ Just before your request, it's a good idea to explain (everything is optional):
93
95
  # spec/requests/session_spec.rb
94
96
 
95
97
  RSpec.describe "Session resource", type: :request, doc: true do
96
- describe "Create session" do
98
+ describe "Create session", explanation: "This is how you create a session." do
97
99
  before do
98
- explain "Creating the user"
100
+ explain { request "Creating a user" }
99
101
  post "/users", user: { username: "myuser", password: "123123" }
100
102
  end
101
103
 
102
104
  before do
103
- explain do # No request explanation
104
- request do
105
+ explain do
106
+ request do # No request explanation
105
107
  parameter 'session[username]', "The username", required: true, type: 'string'
106
108
  parameter 'session[password]', required: true, type: 'string' # No explanation
107
109
  header 'Content-Type', ... # you get the point
108
110
  end
109
- response do
111
+ response do # No response explanation
110
112
  parameter 'message', "Message from the server", required: true # No type
111
113
  parameter 'session_id', "The session ID" # Not required and no type
112
114
  header 'Set-Cookie', ...
@@ -30,8 +30,9 @@ module RSpec
30
30
  @writer = config.writer.new(file)
31
31
  write_breadcrumb
32
32
  write_title
33
- @current.ungrouped_children.each { |child| write_child(child) }
33
+ @current.ungrouped_children.each { |child| write_child(child, last: child == @current.ungrouped_children.last) }
34
34
  write_recursive_requests(@current)
35
+ @writer.close
35
36
  end
36
37
 
37
38
  @current.ungrouped_children.each do |child|
@@ -44,12 +45,18 @@ module RSpec
44
45
  missing_levels = []
45
46
  if not child == @current
46
47
  missing = child
47
- missing_levels.unshift(missing.description) while (missing = missing.parent) and missing != @current
48
+ missing_levels.unshift(missing) while (missing = missing.parent) and missing != @current
49
+ end
50
+ missing_levels = missing_levels.map do |organized_entry|
51
+ {
52
+ description: organized_entry.metadata[:description],
53
+ explanation: metadata_explanation(organized_entry.metadata),
54
+ }
48
55
  end
49
56
 
50
57
  child.example_requests.to_a.uniq { |e,| e.example_group }.each do |example, requests|
51
58
  write_example_title(example, missing_levels: missing_levels) unless child == @current
52
- requests.each { |request| write_request(request, missing_levels: missing_levels) }
59
+ requests.each { |request| write_request(request) }
53
60
  end
54
61
 
55
62
  child.grouped_children.each_with_index do |grandchild, i|
@@ -57,6 +64,10 @@ module RSpec
57
64
  end
58
65
  end
59
66
 
67
+ def metadata_explanation(metadata)
68
+ metadata[:explanation] if metadata[:parent_example_group].nil? or metadata[:explanation] != metadata[:parent_example_group][:explanation]
69
+ end
70
+
60
71
  def write_breadcrumb
61
72
  current = @current
62
73
  parent_tree = []
@@ -67,7 +78,7 @@ module RSpec
67
78
  parent_path = Pathname.new('.').join(*parent_tree.length.times.map { '..' })
68
79
  parent_tree.each do |parent|
69
80
  @writer.breadcrumb(
70
- description: parent.description,
81
+ description: parent.metadata[:description],
71
82
  filename: parent_path.join(parent.filename).sub_ext(config.writer::EXTENSION),
72
83
  last: parent == @current.parent,
73
84
  )
@@ -76,22 +87,37 @@ module RSpec
76
87
  end
77
88
 
78
89
  def write_title
79
- @writer.title(@current.description)
90
+ metadata = @current.metadata
91
+ @writer.title(description: metadata[:description], explanation: metadata_explanation(metadata))
80
92
  end
81
93
 
82
- def write_child(child)
94
+ def write_child(child, last:)
83
95
  @writer.child(
84
- description: child.description,
96
+ description: child.metadata[:description],
85
97
  filename: @current.filename.join(child.filename).sub_ext(config.writer::EXTENSION),
98
+ last: last,
86
99
  )
87
100
  end
88
101
 
89
102
  def write_example_title(example, missing_levels:)
90
- @writer.example_title(example.example_group.metadata[:description], missing_levels: missing_levels)
103
+ metadata = example.example_group.metadata
104
+ @writer.example_title(description: metadata[:description], explanation: metadata_explanation(metadata), missing_levels: missing_levels)
91
105
  end
92
106
 
93
- def write_request(request, missing_levels:)
94
- @writer.request(request, missing_levels: missing_levels)
107
+ def write_request(request)
108
+ # request
109
+ @writer.request.title(request.explanation.request.message)
110
+ @writer.request.path(request.method, request.path)
111
+ @writer.request.parameters(request.request_parameters) if request.request_parameters.present?
112
+ @writer.request.body(request.request_body) if request.request_body.present?
113
+ @writer.request.headers(request.request_headers) if request.request_headers.present?
114
+ # response
115
+ @writer.response.title(request.explanation.response.message)
116
+ @writer.response.status(request.response.status, request.response.status_message)
117
+ @writer.response.content_type(request.response.content_type)
118
+ @writer.response.parameters(request.response_parameters) if request.response_parameters.present?
119
+ @writer.response.body(request.response.body) if request.response.body.present?
120
+ @writer.response.headers(request.response_headers) if request.response_headers.present?
95
121
  end
96
122
  end
97
123
  end
@@ -28,9 +28,8 @@ module RSpec
28
28
  end
29
29
  end
30
30
 
31
- def explain(message = nil, &block)
32
- document_request_explanation.message = message if message
33
- document_request_explanation.instance_eval(&block) if block_given?
31
+ def explain(&block)
32
+ document_request_explanation.instance_eval(&block)
34
33
  end
35
34
 
36
35
  def document_request_explanation
@@ -2,7 +2,7 @@ module RSpec
2
2
  module DocumentRequests
3
3
  class Explanation
4
4
  class Side
5
- attr_accessor :parameters, :headers
5
+ attr_accessor :message, :parameters, :headers
6
6
 
7
7
  def initialize
8
8
  @parameters = {}
@@ -18,22 +18,22 @@ module RSpec
18
18
  end
19
19
  end
20
20
 
21
- attr_accessor :message
22
-
23
21
  def initialize
24
22
  @request = Side.new
25
23
  @response = Side.new
26
24
  end
27
25
 
28
- def request(&block)
29
- @request.instance_eval(&block) if block_given?
30
- @request
26
+ def self.build_side(side)
27
+ define_method(side) do |message = nil, &block|
28
+ instance = instance_variable_get(:"@#{side}")
29
+ instance.message = message if message
30
+ instance.instance_eval(&block) if block_given?
31
+ instance
32
+ end
31
33
  end
32
34
 
33
- def response(&block)
34
- @response.instance_eval(&block) if block_given?
35
- @response
36
- end
35
+ build_side :request
36
+ build_side :response
37
37
  end
38
38
  end
39
39
  end
@@ -1,19 +1,22 @@
1
1
  module RSpec
2
2
  module DocumentRequests
3
3
  class OrganizedRequest
4
- attr_reader :parent, :filename, :description, :example_requests, :children, :levels
5
- def initialize(description:, parent: nil)
6
- @description = description
4
+ attr_reader :parent, :metadata, :example_requests, :children, :levels
5
+ def initialize(metadata, parent: nil)
6
+ @metadata = metadata
7
7
  @parent = parent
8
- @filename = Pathname.new(DocumentRequests.configuration.filename_generator.call(description))
9
8
  @example_requests = Hash.new { |h, k| h[k] = [] }
10
9
  @children = {}
11
10
  @levels = Hash.new { |h, k| h[k] = 0 }
12
11
  @parent.increase_level(self) if @parent
13
12
  end
14
13
 
15
- def child(description)
16
- @children[DocumentRequests.configuration.filename_generator.call(description)] ||= OrganizedRequest.new(description: description, parent: self)
14
+ def filename
15
+ @filename ||= Pathname.new(DocumentRequests.configuration.filename_generator.call(@metadata[:description]))
16
+ end
17
+
18
+ def child(metadata)
19
+ @children[DocumentRequests.configuration.filename_generator.call(metadata[:description])] ||= OrganizedRequest.new(metadata, parent: self)
17
20
  end
18
21
 
19
22
  def increase_level(child)
@@ -44,7 +47,7 @@ module RSpec
44
47
 
45
48
  organized_request = root
46
49
  metadata_tree.each do |metadata|
47
- organized_request = organized_request.child(metadata[:description])
50
+ organized_request = organized_request.child(metadata)
48
51
  end
49
52
  organized_request.example_requests[request.example] << request
50
53
  end
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module DocumentRequests
3
- VERSION = "1.1.0"
3
+ VERSION = "1.2.0"
4
4
  end
5
5
  end
@@ -4,28 +4,96 @@ module RSpec
4
4
  class Base
5
5
  #EXTENSION = ".something"
6
6
 
7
+ attr_reader :request, :response
8
+
7
9
  def initialize(file)
8
10
  @file = file
11
+ @request = self.class::Request.new(file)
12
+ @response = self.class::Response.new(file)
9
13
  end
10
14
 
11
15
  def breadcrumb(description:, filename:, last:)
12
16
  raise NotImplementedError
13
17
  end
14
18
 
15
- def title(description)
19
+ def title(description:, explanation:)
16
20
  raise NotImplementedError
17
21
  end
18
22
 
19
- def child(description:, filename:)
23
+ def child(description:, filename:, last:)
20
24
  raise NotImplementedError
21
25
  end
22
26
 
23
- def request_title(description, missing_levels:)
27
+ # missing_levels: [{ description: "", explanation: "" || nil }, ...]
28
+ def example_title(description:, explanation:, missing_levels:)
24
29
  raise NotImplementedError
25
30
  end
26
31
 
27
- def request(request, missing_levels:)
28
- raise NotImplementedError
32
+ def close
33
+ @request.close
34
+ @response.close
35
+ end
36
+
37
+ class Request
38
+ def initialize(file)
39
+ @file = file
40
+ end
41
+
42
+ def title(message)
43
+ raise NotImplementedError
44
+ end
45
+
46
+ def path(method, path)
47
+ raise NotImplementedError
48
+ end
49
+
50
+ def parameters(parameters)
51
+ raise NotImplementedError
52
+ end
53
+
54
+ def body(body)
55
+ raise NotImplementedError
56
+ end
57
+
58
+ def headers(headers)
59
+ raise NotImplementedError
60
+ end
61
+
62
+ def close
63
+ end
64
+ end
65
+
66
+ class Response
67
+ def initialize(file)
68
+ @file = file
69
+ end
70
+
71
+ def title(message)
72
+ raise NotImplementedError
73
+ end
74
+
75
+ def status(status, message)
76
+ raise NotImplementedError
77
+ end
78
+
79
+ def content_type(content_type)
80
+ raise NotImplementedError
81
+ end
82
+
83
+ def parameters(parameters)
84
+ raise NotImplementedError
85
+ end
86
+
87
+ def body(body)
88
+ raise NotImplementedError
89
+ end
90
+
91
+ def headers(headers)
92
+ raise NotImplementedError
93
+ end
94
+
95
+ def close
96
+ end
29
97
  end
30
98
  end
31
99
  end
@@ -14,100 +14,115 @@ module RSpec
14
14
  end
15
15
  end
16
16
 
17
- def title(description)
17
+ def title(description:, explanation:)
18
18
  @file.puts "# #{description}"
19
19
  @file.puts
20
+ if explanation
21
+ @file.puts explanation
22
+ @file.puts
23
+ end
20
24
  end
21
25
 
22
- def child(description:, filename:)
26
+ def child(description:, filename:, last:)
23
27
  @file.puts "* [#{description}](#{filename})"
28
+ @file.puts if last
24
29
  end
25
30
 
26
- def example_title(description, missing_levels:)
27
- @file.puts "## #{missing_levels.map { |l| "#{l} > " }.join} #{description}"
31
+ def example_title(description:, explanation:, missing_levels:)
32
+ @file.puts "## #{missing_levels.map { |l| "#{l[:description]} > " }.join}#{description}"
28
33
  @file.puts
34
+ if explanation
35
+ @file.puts explanation
36
+ @file.puts
37
+ end
29
38
  end
30
39
 
31
- def request(request, missing_levels:)
32
- @file.write <<FILE
33
- ### Request#{" (#{request.explanation.message})" if request.explanation.message}
34
-
35
- #{request.method} #{request.path}
36
-
37
- FILE
40
+ module ParametersTable
41
+ private
38
42
 
39
- if request.request_parameters and request.request_parameters.any?
40
- @file.write <<FILE
41
- #### Parameters
42
-
43
- FILE
44
- parameters_table(request.request_parameters)
45
- elsif request.request_body
46
- @file.write <<FILE
47
- #### Body
48
-
49
- #{request.request_body}
50
-
51
- FILE
43
+ def parameters_table(parameters)
44
+ @file.puts "| Name | Type | Required? | Value | |"
45
+ @file.puts "|------|------|-----------|-------|---|"
46
+ parameters.each do |name, parameter|
47
+ @file.puts "| #{name} | #{parameter.type} | #{"Required" if parameter.required} | #{parameter.value} | #{parameter.message} |"
48
+ end
49
+ @file.puts
52
50
  end
51
+ end
53
52
 
54
- if request.request_headers.any?
55
- @file.write <<FILE
56
- #### Headers
53
+ class Request < Base::Request
54
+ include ParametersTable
57
55
 
58
- FILE
59
- parameters_table(request.request_headers)
56
+ def title(message)
57
+ @file.puts "### Request#{" (#{message})" if message}"
58
+ @file.puts
60
59
  end
61
60
 
62
- @file.write <<FILE
63
- ### Response
64
-
65
- #### Status
66
-
67
- #{request.response.status} #{request.response.status_message}
68
-
69
- #### Content-Type
70
-
71
- #{request.response.content_type}
72
-
73
- FILE
61
+ def path(method, path)
62
+ @file.puts " #{method} #{path}"
63
+ @file.puts
64
+ end
74
65
 
75
- if request.response_parameters and request.response_parameters.any?
76
- @file.write <<FILE
77
- #### Parameters
66
+ def parameters(parameters)
67
+ @file.puts "#### Parameters"
68
+ @file.puts
69
+ parameters_table(parameters)
70
+ end
78
71
 
79
- FILE
80
- parameters_table(request.response_parameters)
72
+ def body(body)
73
+ @file.puts "#### Body"
74
+ @file.puts
75
+ @file.puts " #{body}"
76
+ @file.puts
81
77
  end
82
78
 
83
- @file.write <<FILE
84
- #### Body
79
+ def headers(headers)
80
+ @file.puts "#### Headers"
81
+ @file.puts
82
+ parameters_table(headers)
83
+ end
84
+ end
85
85
 
86
- #{request.response.body}
86
+ class Response < Base::Response
87
+ include ParametersTable
87
88
 
88
- FILE
89
+ def title(message)
90
+ @file.puts "### Response#{" (#{message})" if message}"
91
+ @file.puts
92
+ end
89
93
 
90
- if request.response_headers.any?
91
- @file.write <<FILE
92
- #### Headers
94
+ def status(status, message)
95
+ @file.puts "#### Status"
96
+ @file.puts
97
+ @file.puts " #{status} #{message}"
98
+ @file.puts
99
+ end
93
100
 
94
- FILE
95
- parameters_table(request.response_headers)
101
+ def content_type(content_type)
102
+ @file.puts "#### Content-Type"
103
+ @file.puts
104
+ @file.puts " #{content_type}"
105
+ @file.puts
96
106
  end
97
- end
98
107
 
99
- private
108
+ def parameters(parameters)
109
+ @file.puts "#### Parameters"
110
+ @file.puts
111
+ parameters_table(parameters)
112
+ end
100
113
 
101
- def parameters_table(parameters)
102
- @file.write <<FILE
103
- | Name | Type | Required? | Value | |
104
- |------|------|-----------|-------|---|
105
- FILE
114
+ def body(body)
115
+ @file.puts "#### Body"
116
+ @file.puts
117
+ @file.puts " #{body}"
118
+ @file.puts
119
+ end
106
120
 
107
- parameters.each do |name, parameter|
108
- @file.puts "| #{name} | #{parameter.type} | #{"Required" if parameter.required} | #{parameter.value} | #{parameter.message} |"
121
+ def headers(headers)
122
+ @file.puts "#### Headers"
123
+ @file.puts
124
+ parameters_table(headers)
109
125
  end
110
- @file.puts
111
126
  end
112
127
  end
113
128
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-document_requests
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oded Niv
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-06-23 00:00:00.000000000 Z
11
+ date: 2015-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec-rails