rspec-openapi 0.1.4 → 0.3.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
  SHA256:
3
- metadata.gz: 6592834cfaeab157827636bb38312e11e49bbb109da57290585ebd8d06f0a027
4
- data.tar.gz: 717567dede6a8966d42cd6bdbd8ec0d68c59f92015bfe08285b22bbf15743614
3
+ metadata.gz: 4bf20b571bfadeda67cae266f85c87530c32067d5b1d9934a16ea423652a17be
4
+ data.tar.gz: ae4222d06d8d4aaee18ddcabc26808fe84cdfcf1ea6674527af7ffd7aa5e0d38
5
5
  SHA512:
6
- metadata.gz: 1fc45e3e2fe27cf6dc049fe079435e14459e0af479971cf6da7ad074673ab371b37bb831bbacbffc6a244fa3dca63c33c8ebc51608706da351c35f4734ce629e
7
- data.tar.gz: 5466deae08cd7b298386fbcd7e9d399840e10144483d7a6bb93c296791666f33450e7d3628eebe41a4400f28ce7c810c57c640c9f4794374f5401ad640c9b16a
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
@@ -1,3 +1,4 @@
1
+ --exclude-pattern spec/requests/**/*_spec.rb
1
2
  --format documentation
3
+ --require rspec/openapi
2
4
  --color
3
- --require spec_helper
@@ -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
@@ -4,5 +4,9 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  gem 'rails', '6.0.3.2'
7
+ gem 'roda'
7
8
  gem 'rspec-rails'
8
- gem 'pry'
9
+
10
+ group :development do
11
+ gem 'pry'
12
+ end
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # rspec-openapi
1
+ # rspec-openapi ![test](https://github.com/k0kubun/rspec-openapi/workflows/test/badge.svg)
2
2
 
3
- Generate OpenAPI specs from RSpec request specs.
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/railsapp/doc/openapi.yaml) like:
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
- ![Redoc example](./spec/railsapp/doc/screenshot.png)
96
+ ![Redoc example](./spec/rails/doc/screenshot.png)
97
97
 
98
98
 
99
99
  ### Configuration
100
100
 
101
- If you want to change the path to generate a spec from `doc/openapi.yaml`, use:
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
- PoC / Experimental
144
+ Beta
142
145
 
143
- This worked for some of my Rails apps, but this may raise a basic error for your app.
146
+ Basic features are there, and some people are already using this.
144
147
 
145
- ### Current limitations
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
@@ -1,6 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
3
 
4
- RSpec::Core::RakeTask.new(:spec)
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.pattern = 'spec/rspec/openapi/**/*_spec.rb'
6
+ end
5
7
 
6
- task :default => :spec
8
+ task default: :spec
@@ -3,8 +3,10 @@ require 'rspec/openapi/hooks' if ENV['OPENAPI']
3
3
 
4
4
  module RSpec::OpenAPI
5
5
  @path = 'doc/openapi.yaml'
6
+ @comment = nil
7
+ @enable_example = true
6
8
 
7
9
  class << self
8
- attr_accessor :path, :comment
10
+ attr_accessor :path, :comment, :enable_example
9
11
  end
10
12
  end
@@ -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 && request && response
12
- records << RSpec::OpenAPI::RecordBuilder.build(self, example: example)
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
 
@@ -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
- :controller, # @param [String] - "v1/statuses"
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
- # TODO: Support Non-Rails frameworks
9
- request = context.request
10
- response = context.response
11
- route = find_route(request)
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: route.path.spec.to_s.delete_suffix('(.:format)'),
29
+ path: path,
16
30
  path_params: request.path_parameters,
17
31
  query_params: request.query_parameters,
18
- request_params: request.request_parameters,
32
+ request_params: raw_request_params(request),
19
33
  request_content_type: request.content_type,
20
- controller: route.requirements[:controller],
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 find_route(request)
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: "#{record.controller} ##{record.action}",
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
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module OpenAPI
3
- VERSION = '0.1.4'
3
+ VERSION = '0.3.0'
4
4
  end
5
5
  end
@@ -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 specs from RSpec request specs}
10
- spec.description = %q{Generate OpenAPI specs from RSpec request specs}
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
- # spec.metadata['changelog_uri'] = 'TODO'
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.1.4
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-06-19 00:00:00.000000000 Z
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 specs from RSpec request specs
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.1.2
91
+ rubygems_version: 3.2.0.pre1
76
92
  signing_key:
77
93
  specification_version: 4
78
- summary: Generate OpenAPI specs from RSpec request specs
94
+ summary: Generate OpenAPI schema from RSpec request specs
79
95
  test_files: []