rspec-document_requests 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -6
- data/lib/rspec/document_requests/builder.rb +36 -10
- data/lib/rspec/document_requests/dsl.rb +2 -3
- data/lib/rspec/document_requests/explanation.rb +10 -10
- data/lib/rspec/document_requests/organized_request.rb +10 -7
- data/lib/rspec/document_requests/version.rb +1 -1
- data/lib/rspec/document_requests/writers/base.rb +73 -5
- data/lib/rspec/document_requests/writers/markdown.rb +80 -65
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c1fd117650183a8e2b17f41acfeb19bcd011251
|
4
|
+
data.tar.gz: 582ddbaa7fd602d131b676747a10b084172fb479
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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:**
|
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
|
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
|
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
|
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
|
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
|
-
@
|
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
|
-
|
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
|
94
|
-
|
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(
|
32
|
-
document_request_explanation.
|
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
|
29
|
-
|
30
|
-
|
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
|
-
|
34
|
-
|
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, :
|
5
|
-
def initialize(
|
6
|
-
@
|
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
|
16
|
-
@
|
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
|
50
|
+
organized_request = organized_request.child(metadata)
|
48
51
|
end
|
49
52
|
organized_request.example_requests[request.example] << request
|
50
53
|
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
|
-
|
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
|
28
|
-
|
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
|
27
|
-
@file.puts "## #{missing_levels.map { |l| "#{l} > " }.join}
|
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
|
-
|
32
|
-
|
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
|
-
|
40
|
-
@file.
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
55
|
-
|
56
|
-
#### Headers
|
53
|
+
class Request < Base::Request
|
54
|
+
include ParametersTable
|
57
55
|
|
58
|
-
|
59
|
-
|
56
|
+
def title(message)
|
57
|
+
@file.puts "### Request#{" (#{message})" if message}"
|
58
|
+
@file.puts
|
60
59
|
end
|
61
60
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
76
|
-
@file.
|
77
|
-
|
66
|
+
def parameters(parameters)
|
67
|
+
@file.puts "#### Parameters"
|
68
|
+
@file.puts
|
69
|
+
parameters_table(parameters)
|
70
|
+
end
|
78
71
|
|
79
|
-
|
80
|
-
|
72
|
+
def body(body)
|
73
|
+
@file.puts "#### Body"
|
74
|
+
@file.puts
|
75
|
+
@file.puts " #{body}"
|
76
|
+
@file.puts
|
81
77
|
end
|
82
78
|
|
83
|
-
|
84
|
-
####
|
79
|
+
def headers(headers)
|
80
|
+
@file.puts "#### Headers"
|
81
|
+
@file.puts
|
82
|
+
parameters_table(headers)
|
83
|
+
end
|
84
|
+
end
|
85
85
|
|
86
|
-
|
86
|
+
class Response < Base::Response
|
87
|
+
include ParametersTable
|
87
88
|
|
88
|
-
|
89
|
+
def title(message)
|
90
|
+
@file.puts "### Response#{" (#{message})" if message}"
|
91
|
+
@file.puts
|
92
|
+
end
|
89
93
|
|
90
|
-
|
91
|
-
@file.
|
92
|
-
|
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
|
-
|
95
|
-
|
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
|
-
|
108
|
+
def parameters(parameters)
|
109
|
+
@file.puts "#### Parameters"
|
110
|
+
@file.puts
|
111
|
+
parameters_table(parameters)
|
112
|
+
end
|
100
113
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
114
|
+
def body(body)
|
115
|
+
@file.puts "#### Body"
|
116
|
+
@file.puts
|
117
|
+
@file.puts " #{body}"
|
118
|
+
@file.puts
|
119
|
+
end
|
106
120
|
|
107
|
-
|
108
|
-
@file.puts "
|
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.
|
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-
|
11
|
+
date: 2015-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-rails
|