rspec-openapi 0.1.4 → 0.3.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 +4 -4
- data/.github/workflows/test.yml +27 -0
- data/.rspec +2 -1
- data/CHANGELOG.md +23 -0
- data/Gemfile +5 -1
- data/README.md +12 -11
- data/Rakefile +4 -2
- data/lib/rspec/openapi.rb +3 -1
- data/lib/rspec/openapi/hooks.rb +3 -2
- data/lib/rspec/openapi/record.rb +1 -2
- data/lib/rspec/openapi/record_builder.rb +36 -10
- data/lib/rspec/openapi/schema_builder.rb +15 -5
- data/lib/rspec/openapi/version.rb +1 -1
- data/rspec-openapi.gemspec +4 -3
- metadata +21 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bf20b571bfadeda67cae266f85c87530c32067d5b1d9934a16ea423652a17be
|
4
|
+
data.tar.gz: ae4222d06d8d4aaee18ddcabc26808fe84cdfcf1ea6674527af7ffd7aa5e0d38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ef3047477727572e3c8bdab0680b5fe82264aa6653c33e5ea19c7680739db5b55bde2c51d11a3cce6c422d487f445705d549eca82068f474fcb750b6d21fdc59
|
7
|
+
data.tar.gz: b3e03fedec66b64f24e83fe1023abaea2fb4accdb2e1da7dab78eb4870c0cc1338e9453e6c9cd345fe01e77258cbe39f01223b0ff4e708fd568c98dc5315b8d4
|
@@ -0,0 +1,27 @@
|
|
1
|
+
name: test
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
- master
|
6
|
+
pull_request:
|
7
|
+
types:
|
8
|
+
- opened
|
9
|
+
- synchronize
|
10
|
+
- reopened
|
11
|
+
jobs:
|
12
|
+
test:
|
13
|
+
runs-on: ubuntu-latest
|
14
|
+
container: ${{ matrix.ruby }}
|
15
|
+
strategy:
|
16
|
+
fail-fast: false
|
17
|
+
matrix:
|
18
|
+
ruby:
|
19
|
+
- ruby:2.5
|
20
|
+
- ruby:2.6
|
21
|
+
- ruby:2.7
|
22
|
+
steps:
|
23
|
+
- uses: actions/checkout@v2
|
24
|
+
- name: bundle install
|
25
|
+
run: bundle install -j$(nproc) --retry 3
|
26
|
+
- run: bundle exec rspec
|
27
|
+
timeout-minutes: 1
|
data/.rspec
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
## v0.3.0
|
2
|
+
|
3
|
+
* Initial support of rack-test and non-Rails apps
|
4
|
+
|
5
|
+
## v0.2.2
|
6
|
+
|
7
|
+
* Allow disabling `example` by `RSpec::OpenAPI.enable_example = false`
|
8
|
+
|
9
|
+
## v0.2.1
|
10
|
+
|
11
|
+
* Generate `example` of request body and path / query params
|
12
|
+
[#4](https://github.com/k0kubun/rspec-openapi/issues/4)
|
13
|
+
* Remove a wrapper param created by Rails in request body
|
14
|
+
[#4](https://github.com/k0kubun/rspec-openapi/issues/4)
|
15
|
+
|
16
|
+
## v0.2.0
|
17
|
+
|
18
|
+
* Generate `example` of response body [#3](https://github.com/k0kubun/rspec-openapi/issues/3)
|
19
|
+
|
20
|
+
## v0.1.5
|
21
|
+
|
22
|
+
* Support detecting `float` type [#2](https://github.com/k0kubun/rspec-openapi/issues/2)
|
23
|
+
|
1
24
|
## v0.1.4
|
2
25
|
|
3
26
|
* Avoid NoMethodError on nil Content-Type
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# rspec-openapi
|
1
|
+
# rspec-openapi 
|
2
2
|
|
3
|
-
Generate OpenAPI
|
3
|
+
Generate OpenAPI schema from RSpec request specs.
|
4
4
|
|
5
5
|
## What's this?
|
6
6
|
|
@@ -29,7 +29,7 @@ $ OPENAPI=1 rspec
|
|
29
29
|
|
30
30
|
### Example
|
31
31
|
|
32
|
-
Let's say you have [a request spec](./spec/requests/tables_spec.rb) like this:
|
32
|
+
Let's say you have [a request spec](./spec/requests/rails/tables_spec.rb) like this:
|
33
33
|
|
34
34
|
```rb
|
35
35
|
RSpec.describe 'Tables', type: :request do
|
@@ -55,7 +55,7 @@ If you run the spec with `OPENAPI=1`,
|
|
55
55
|
OPENAPI=1 rspec spec/requests/tables_spec.rb
|
56
56
|
```
|
57
57
|
|
58
|
-
It will generate [`doc/openapi.yaml` file](./spec/
|
58
|
+
It will generate [`doc/openapi.yaml` file](./spec/rails/doc/openapi.yaml) like:
|
59
59
|
|
60
60
|
```yml
|
61
61
|
openapi: 3.0.3
|
@@ -93,17 +93,20 @@ paths:
|
|
93
93
|
|
94
94
|
and the schema file can be used as an input of [Swagger UI](https://github.com/swagger-api/swagger-ui) or [Redoc](https://github.com/Redocly/redoc).
|
95
95
|
|
96
|
-

|
97
97
|
|
98
98
|
|
99
99
|
### Configuration
|
100
100
|
|
101
|
-
|
101
|
+
The following configurations are optional.
|
102
102
|
|
103
103
|
```rb
|
104
104
|
# Change the path to generate schema from `doc/openapi.yaml`
|
105
105
|
RSpec::OpenAPI.path = 'doc/schema.yaml'
|
106
106
|
|
107
|
+
# Disable generating `example`
|
108
|
+
RSpec::OpenAPI.enable_example = false
|
109
|
+
|
107
110
|
# Generate a comment on top of a schema file
|
108
111
|
RSpec::OpenAPI.comment = <<~EOS
|
109
112
|
This file is auto-generated by rspec-openapi https://github.com/k0kubun/rspec-openapi
|
@@ -138,15 +141,13 @@ end
|
|
138
141
|
|
139
142
|
## Project status
|
140
143
|
|
141
|
-
|
144
|
+
Beta
|
142
145
|
|
143
|
-
|
146
|
+
Basic features are there, and some people are already using this.
|
144
147
|
|
145
|
-
### Current
|
148
|
+
### Current limitation
|
146
149
|
|
147
150
|
* Generating a JSON file is not supported yet
|
148
|
-
* This only works for RSpec request specs
|
149
|
-
* Only Rails is supported for looking up a request route
|
150
151
|
|
151
152
|
### Other missing features with notes
|
152
153
|
|
data/Rakefile
CHANGED
data/lib/rspec/openapi.rb
CHANGED
data/lib/rspec/openapi/hooks.rb
CHANGED
@@ -8,8 +8,9 @@ require 'rspec/openapi/schema_merger'
|
|
8
8
|
records = []
|
9
9
|
|
10
10
|
RSpec.configuration.after(:each) do |example|
|
11
|
-
if example.metadata[:type] == :request && example.metadata[:openapi] != false
|
12
|
-
|
11
|
+
if example.metadata[:type] == :request && example.metadata[:openapi] != false
|
12
|
+
record = RSpec::OpenAPI::RecordBuilder.build(self, example: example)
|
13
|
+
records << record if record
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
data/lib/rspec/openapi/record.rb
CHANGED
@@ -5,8 +5,7 @@ RSpec::OpenAPI::Record = Struct.new(
|
|
5
5
|
:query_params, # @param [Hash] - {:query=>"string"}
|
6
6
|
:request_params, # @param [Hash] - {:request=>"body"}
|
7
7
|
:request_content_type, # @param [String] - "application/json"
|
8
|
-
:
|
9
|
-
:action, # @param [String] - "show"
|
8
|
+
:summary, # @param [String] - "v1/statuses #show"
|
10
9
|
:description, # @param [String] - "returns a status"
|
11
10
|
:status, # @param [Integer] - 200
|
12
11
|
:response_body, # @param [Object] - {"status" => "ok"}
|
@@ -1,24 +1,37 @@
|
|
1
|
+
require 'action_dispatch'
|
1
2
|
require 'rspec/openapi/record'
|
2
3
|
|
3
4
|
class << RSpec::OpenAPI::RecordBuilder = Object.new
|
4
5
|
# @param [RSpec::ExampleGroups::*] context
|
5
6
|
# @param [RSpec::Core::Example] example
|
6
|
-
# @return [RSpec::OpenAPI::Record]
|
7
|
+
# @return [RSpec::OpenAPI::Record,nil]
|
7
8
|
def build(context, example:)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
if rack_test?(context)
|
10
|
+
request = ActionDispatch::Request.new(context.last_request.env)
|
11
|
+
response = ActionDispatch::TestResponse.new(*context.last_response.to_a)
|
12
|
+
else
|
13
|
+
request = context.request
|
14
|
+
response = context.response
|
15
|
+
end
|
16
|
+
|
17
|
+
# Generate `path` and `summary` in a framework-friendly manner when possible
|
18
|
+
if defined?(Rails) && Rails.application
|
19
|
+
route = find_rails_route(request)
|
20
|
+
path = route.path.spec.to_s.delete_suffix('(.:format)')
|
21
|
+
summary = "#{route.requirements[:controller]} ##{route.requirements[:action]}"
|
22
|
+
else
|
23
|
+
path = request.path
|
24
|
+
summary = "#{request.method} #{request.path}"
|
25
|
+
end
|
12
26
|
|
13
27
|
RSpec::OpenAPI::Record.new(
|
14
28
|
method: request.request_method,
|
15
|
-
path:
|
29
|
+
path: path,
|
16
30
|
path_params: request.path_parameters,
|
17
31
|
query_params: request.query_parameters,
|
18
|
-
request_params: request
|
32
|
+
request_params: raw_request_params(request),
|
19
33
|
request_content_type: request.content_type,
|
20
|
-
|
21
|
-
action: route.requirements[:action],
|
34
|
+
summary: summary,
|
22
35
|
description: example.description,
|
23
36
|
status: response.status,
|
24
37
|
response_body: response.parsed_body,
|
@@ -28,11 +41,24 @@ class << RSpec::OpenAPI::RecordBuilder = Object.new
|
|
28
41
|
|
29
42
|
private
|
30
43
|
|
44
|
+
def rack_test?(context)
|
45
|
+
defined?(Rack::Test::Methods) && context.class < Rack::Test::Methods
|
46
|
+
end
|
47
|
+
|
31
48
|
# @param [ActionDispatch::Request] request
|
32
|
-
def
|
49
|
+
def find_rails_route(request)
|
33
50
|
Rails.application.routes.router.recognize(request) do |route|
|
34
51
|
return route
|
35
52
|
end
|
36
53
|
raise "No route matched for #{request.request_method} #{request.path_info}"
|
37
54
|
end
|
55
|
+
|
56
|
+
# workaround to get real request parameters
|
57
|
+
# because ActionController::ParamsWrapper overwrites request_parameters
|
58
|
+
def raw_request_params(request)
|
59
|
+
original = request.delete_header('action_dispatch.request.request_parameters')
|
60
|
+
request.request_parameters
|
61
|
+
ensure
|
62
|
+
request.set_header('action_dispatch.request.request_parameters', original)
|
63
|
+
end
|
38
64
|
end
|
@@ -6,7 +6,7 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
|
|
6
6
|
paths: {
|
7
7
|
normalize_path(record.path) => {
|
8
8
|
record.method.downcase => {
|
9
|
-
summary:
|
9
|
+
summary: record.summary,
|
10
10
|
parameters: build_parameters(record),
|
11
11
|
requestBody: build_request_body(record),
|
12
12
|
responses: {
|
@@ -15,7 +15,8 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
|
|
15
15
|
content: {
|
16
16
|
normalize_content_type(record.response_content_type) => {
|
17
17
|
schema: build_property(record.response_body),
|
18
|
-
|
18
|
+
example: (record.response_body if example_enabled?),
|
19
|
+
}.compact,
|
19
20
|
},
|
20
21
|
},
|
21
22
|
},
|
@@ -27,6 +28,10 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
|
|
27
28
|
|
28
29
|
private
|
29
30
|
|
31
|
+
def example_enabled?
|
32
|
+
RSpec::OpenAPI.enable_example
|
33
|
+
end
|
34
|
+
|
30
35
|
def build_parameters(record)
|
31
36
|
parameters = []
|
32
37
|
|
@@ -37,7 +42,8 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
|
|
37
42
|
in: 'path',
|
38
43
|
required: true,
|
39
44
|
schema: build_property(try_cast(value)),
|
40
|
-
|
45
|
+
example: (try_cast(value) if example_enabled?),
|
46
|
+
}.compact
|
41
47
|
end
|
42
48
|
|
43
49
|
record.query_params.each do |key, value|
|
@@ -45,7 +51,8 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
|
|
45
51
|
name: key.to_s,
|
46
52
|
in: 'query',
|
47
53
|
schema: build_property(try_cast(value)),
|
48
|
-
|
54
|
+
example: (try_cast(value) if example_enabled?),
|
55
|
+
}.compact
|
49
56
|
end
|
50
57
|
|
51
58
|
return nil if parameters.empty?
|
@@ -60,7 +67,8 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
|
|
60
67
|
content: {
|
61
68
|
normalize_content_type(record.request_content_type) => {
|
62
69
|
schema: build_property(record.request_params),
|
63
|
-
|
70
|
+
example: (record.request_params if example_enabled?),
|
71
|
+
}.compact
|
64
72
|
}
|
65
73
|
}
|
66
74
|
end
|
@@ -84,6 +92,8 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
|
|
84
92
|
case value
|
85
93
|
when String
|
86
94
|
'string'
|
95
|
+
when Float
|
96
|
+
'float'
|
87
97
|
when Integer
|
88
98
|
'integer'
|
89
99
|
when TrueClass, FalseClass
|
data/rspec-openapi.gemspec
CHANGED
@@ -6,15 +6,15 @@ Gem::Specification.new do |spec|
|
|
6
6
|
spec.authors = ['Takashi Kokubun']
|
7
7
|
spec.email = ['takashikkbn@gmail.com']
|
8
8
|
|
9
|
-
spec.summary = %q{Generate OpenAPI
|
10
|
-
spec.description = %q{Generate OpenAPI
|
9
|
+
spec.summary = %q{Generate OpenAPI schema from RSpec request specs}
|
10
|
+
spec.description = %q{Generate OpenAPI from RSpec request specs}
|
11
11
|
spec.homepage = 'https://github.com/k0kubun/rspec-openapi'
|
12
12
|
spec.license = 'MIT'
|
13
13
|
spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
|
14
14
|
|
15
15
|
spec.metadata['homepage_uri'] = spec.homepage
|
16
16
|
spec.metadata['source_code_uri'] = spec.homepage
|
17
|
-
|
17
|
+
spec.metadata['changelog_uri'] = File.join(spec.homepage, 'blob/master/CHANGELOG.md')
|
18
18
|
|
19
19
|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
20
20
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
@@ -23,5 +23,6 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
24
|
spec.require_paths = ['lib']
|
25
25
|
|
26
|
+
spec.add_dependency 'actionpack'
|
26
27
|
spec.add_dependency 'rspec'
|
27
28
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-openapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takashi Kokubun
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: actionpack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rspec
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,13 +38,14 @@ dependencies:
|
|
24
38
|
- - ">="
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '0'
|
27
|
-
description: Generate OpenAPI
|
41
|
+
description: Generate OpenAPI from RSpec request specs
|
28
42
|
email:
|
29
43
|
- takashikkbn@gmail.com
|
30
44
|
executables: []
|
31
45
|
extensions: []
|
32
46
|
extra_rdoc_files: []
|
33
47
|
files:
|
48
|
+
- ".github/workflows/test.yml"
|
34
49
|
- ".gitignore"
|
35
50
|
- ".rspec"
|
36
51
|
- ".travis.yml"
|
@@ -57,6 +72,7 @@ licenses:
|
|
57
72
|
metadata:
|
58
73
|
homepage_uri: https://github.com/k0kubun/rspec-openapi
|
59
74
|
source_code_uri: https://github.com/k0kubun/rspec-openapi
|
75
|
+
changelog_uri: https://github.com/k0kubun/rspec-openapi/blob/master/CHANGELOG.md
|
60
76
|
post_install_message:
|
61
77
|
rdoc_options: []
|
62
78
|
require_paths:
|
@@ -72,8 +88,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
88
|
- !ruby/object:Gem::Version
|
73
89
|
version: '0'
|
74
90
|
requirements: []
|
75
|
-
rubygems_version: 3.
|
91
|
+
rubygems_version: 3.2.0.pre1
|
76
92
|
signing_key:
|
77
93
|
specification_version: 4
|
78
|
-
summary: Generate OpenAPI
|
94
|
+
summary: Generate OpenAPI schema from RSpec request specs
|
79
95
|
test_files: []
|