openapi_first 2.9.1 → 2.9.3
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/CHANGELOG.md +9 -0
- data/README.md +10 -5
- data/lib/openapi_first/file_loader.rb +1 -1
- data/lib/openapi_first/router/find_response.rb +13 -9
- data/lib/openapi_first/test/coverage/terminal_formatter.rb +5 -2
- data/lib/openapi_first/version.rb +1 -1
- data/lib/openapi_first.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef8ea95833884daf36e8a33742ce4a6eddfb9343b67de0b5e787ebc377c0691d
|
4
|
+
data.tar.gz: b63916918c1d1116d99c2e071c3e8e752b1cce66cd431dceb5076a3e70688c10
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3cbf77e0a4a51b213a90458c1181bd29474f378195210cf76466c24ef832195b32e4cbd8aec7ba97ece0bd7d9a97b6022e02b5288600d8879b82401c398d1ddc
|
7
|
+
data.tar.gz: 8789c3dadcff66b6cbb831dfae948da5adcbcd2788ff40765f39d4a1a0ba238cef1d7df609b4dd57e8ba71653103e21f9fb6a7e1f0a212e45c02d4f8c5e41e39
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## 2.9.3
|
6
|
+
|
7
|
+
- Fix OpenapiFirst.load when MultiJson is configured to return symbol keys
|
8
|
+
|
9
|
+
## 2.9.2
|
10
|
+
|
11
|
+
- OpenapiFirst::Test reports all non-covered requests now
|
12
|
+
- Response validation: Improve content type mismatch exception message
|
13
|
+
|
5
14
|
## 2.9.1
|
6
15
|
|
7
16
|
- Fix OpenapiFirst::Test's request validation to not always raise an error, but only for unknown requests
|
data/README.md
CHANGED
@@ -56,11 +56,7 @@ Here is how to set it up:
|
|
56
56
|
end
|
57
57
|
```
|
58
58
|
2. Observe your application. You can do this in one of two ways:
|
59
|
-
-
|
60
|
-
```ruby
|
61
|
-
OpenapiFirst::Test.observe(MyApplication)
|
62
|
-
```
|
63
|
-
- Or add an `app` method to your tests, which wraps your application with silent request / response validation. (✷1)
|
59
|
+
- Add an `app` method to your tests, which wraps your application with silent request / response validation. (✷1)
|
64
60
|
```ruby
|
65
61
|
RSpec.configure do |config|
|
66
62
|
config.include OpenapiFirst::Test::Methods[MyApp], type: :request
|
@@ -73,6 +69,13 @@ Here is how to set it up:
|
|
73
69
|
OpenapiFirst::Test.app(MyApp)
|
74
70
|
end
|
75
71
|
```
|
72
|
+
- Or inject a Module to wrap (prepend) the `call` method of your Rack app Class.
|
73
|
+
|
74
|
+
NOTE: This is still work in progress. It works with basic Sinatra apps, but does not work with Hanami or Rails out of the box, yet. PRs welcome 🤗
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
OpenapiFirst::Test.observe(MyApplication)
|
78
|
+
```
|
76
79
|
3. Run your tests. The Coverage feature will tell you about missing or invalid requests/responses.
|
77
80
|
|
78
81
|
(✷1): It does not matter what method of openapi_first you use to validate requests/responses. Instead of using `OpenapiFirstTest.app` to wrap your application, you could also use the [middlewares](#rack-middlewares) or [test assertion method](#test-assertions), but you would have to do that for all requests/responses defined in your API description to make coverage work.
|
@@ -368,6 +371,8 @@ use OpenapiFirst::Middlewares::RequestValidation, oad
|
|
368
371
|
|
369
372
|
## Development
|
370
373
|
|
374
|
+
Run `git submodule update --init` to initialize the git submodules.
|
375
|
+
|
371
376
|
Run `bin/setup` to install dependencies.
|
372
377
|
|
373
378
|
See `bundle exec rake` to run the linter and the tests.
|
@@ -13,7 +13,7 @@ module OpenapiFirst
|
|
13
13
|
|
14
14
|
body = File.read(file_path)
|
15
15
|
extname = File.extname(file_path)
|
16
|
-
return JSON.parse(body) if extname == '.json'
|
16
|
+
return ::JSON.parse(body) if extname == '.json'
|
17
17
|
return YAML.unsafe_load(body) if ['.yaml', '.yml'].include?(extname)
|
18
18
|
|
19
19
|
body
|
@@ -16,20 +16,24 @@ module OpenapiFirst
|
|
16
16
|
return Match.new(error: Failure.new(:response_not_found, message:), response: nil)
|
17
17
|
end
|
18
18
|
response = FindContent.call(contents, content_type)
|
19
|
-
|
20
|
-
message = "#{content_error(content_type, request_method:,
|
21
|
-
path:)} Content-Type should be #{contents.keys.join(' or ')}."
|
22
|
-
return Match.new(error: Failure.new(:response_not_found, message:), response: nil)
|
23
|
-
end
|
19
|
+
return response_not_found(content_type:, contents:, request_method:, path:) unless response
|
24
20
|
|
25
21
|
Match.new(response:, error: nil)
|
26
22
|
end
|
27
23
|
|
28
|
-
def self.
|
29
|
-
|
30
|
-
|
31
|
-
|
24
|
+
def self.response_not_found(content_type:, contents:, request_method:, path:)
|
25
|
+
empty_content = content_type.nil? || content_type.empty?
|
26
|
+
message =
|
27
|
+
"Content-Type should be #{contents.keys.join(' or ')}, " \
|
28
|
+
"but was #{empty_content ? 'empty' : content_type} for " \
|
29
|
+
"#{request_method.upcase} #{path}"
|
30
|
+
|
31
|
+
Match.new(
|
32
|
+
error: Failure.new(:response_not_found, message:),
|
33
|
+
response: nil
|
34
|
+
)
|
32
35
|
end
|
36
|
+
private_class_method :response_not_found
|
33
37
|
|
34
38
|
def self.find_status(responses, status)
|
35
39
|
# According to OAS status has to be a string,
|
@@ -33,14 +33,17 @@ module OpenapiFirst
|
|
33
33
|
@out.print(string)
|
34
34
|
end
|
35
35
|
|
36
|
-
def format_plan(plan)
|
36
|
+
def format_plan(plan) # rubocop:disable Metrics/PerceivedComplexity
|
37
37
|
puts ['', "API validation coverage for #{plan.api_identifier}: #{plan.coverage}%"]
|
38
38
|
return if plan.done? && !verbose
|
39
39
|
|
40
|
+
requested_routes_count = plan.routes.count { |route| route.requests.any?(&:requested?) }
|
41
|
+
focused_route = requested_routes_count <= 1 && focused
|
42
|
+
|
40
43
|
plan.routes.each do |route|
|
41
44
|
next if route.finished? && !verbose
|
42
45
|
|
43
|
-
next if route.requests.none?(&:requested?) &&
|
46
|
+
next if route.requests.none?(&:requested?) && focused_route
|
44
47
|
|
45
48
|
format_requests(route.requests)
|
46
49
|
|
data/lib/openapi_first.rb
CHANGED
@@ -66,7 +66,7 @@ module OpenapiFirst
|
|
66
66
|
# @return [Definition]
|
67
67
|
# TODO: This needs to work with unresolved contents as well
|
68
68
|
def self.parse(contents, only: nil, filepath: nil, &)
|
69
|
-
contents = JSON.parse(JSON.generate(contents)) # Deeply stringify keys, because of YAML. See https://github.com/ahx/openapi_first/issues/367
|
69
|
+
contents = ::JSON.parse(::JSON.generate(contents)) # Deeply stringify keys, because of YAML. See https://github.com/ahx/openapi_first/issues/367
|
70
70
|
contents['paths'].filter!(&->(key, _) { only.call(key) }) if only
|
71
71
|
Definition.new(contents, filepath, &)
|
72
72
|
end
|