skooma 0.2.1 → 0.2.2

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: eef2c83a80d1526de1a465acbb29b70fc053b6b5e54ed1e6b6ed131f56a8fe0a
4
- data.tar.gz: 0c4cdec06703bdeb6fd3cf6922401552afaa13aa20b9189e472e703288ba60aa
3
+ metadata.gz: d780ea317b116a8bdafac72f240b68366cf6f2892ea671f29ed51dd48a198093
4
+ data.tar.gz: '078593785c8fc17c73c171616131880dbeaf1b85923e593a3612eb9b2309ff0d'
5
5
  SHA512:
6
- metadata.gz: b5089b0a710836b072b723014cfaaf88b4504853f09a42ddf6a6f9e36ed50271b082dfcc184e047f2bf4481e6a343b4bebbd3bced7dfcec2c5a4f85697fbf113
7
- data.tar.gz: aacb7329ef950a1fc9ff87513a85803e5530cacaec97f0dad1330bf20fb45e9bc339fe9004af11e1b90cfa6cbb725a2cd339a69c6a23721b667e8d10959b37fb
6
+ metadata.gz: f16cb70ad584c45615c4c376ebbab69e48caca0daa32c687d55c9c96453b3a608096afeedc45a7286e0e4ace4c2dc500c2d36ed013d0b951d915b60bbba42a63
7
+ data.tar.gz: c301176ff04134e0e6d18c57e4e0ced55f1dca82d8ff807eefa820cc02f8227101275ccf43b4e3b60c6716b19d7da94f714da37435f417995e97faf44f2b20d3
data/CHANGELOG.md CHANGED
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning].
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.2] - 2024-01-04
11
+
12
+ ### Added
13
+
14
+ - Add support for APIs mounted under a path prefix. ([@skryukov])
15
+
16
+ ```ruby
17
+ # spec/rails_helper.rb
18
+
19
+ RSpec.configure do |config|
20
+ # ...
21
+ path_to_openapi = Rails.root.join("docs", "openapi.yml")
22
+ # pass path_prefix option if your API is mounted under a prefix:
23
+ config.include Skooma::RSpec[path_to_openapi, path_prefix: "/internal/api"], type: :request
24
+ end
25
+ ```
26
+
27
+ ### Changed
28
+
29
+ - Bump `json_skooma` version to `~> 0.2.0`. ([@skryukov])
30
+
31
+ ### Fixed
32
+
33
+ - Better checks to automatic request/response detection to prevent methods overrides via RSpec helpers (i.e. `subject(:response)`). ([@skryukov])
34
+ - Fail response validation when expected response code or `responses` keyword aren't listed. ([@skryukov])
35
+
10
36
  ## [0.2.1] - 2023-10-23
11
37
 
12
38
  ### Fixed
@@ -33,7 +59,8 @@ and this project adheres to [Semantic Versioning].
33
59
 
34
60
  [@skryukov]: https://github.com/skryukov
35
61
 
36
- [Unreleased]: https://github.com/skryukov/skooma/compare/v0.2.1...HEAD
62
+ [Unreleased]: https://github.com/skryukov/skooma/compare/v0.2.2...HEAD
63
+ [0.2.2]: https://github.com/skryukov/skooma/compare/v0.2.1...v0.2.2
37
64
  [0.2.1]: https://github.com/skryukov/skooma/compare/v0.2.0...v0.2.1
38
65
  [0.2.0]: https://github.com/skryukov/skooma/compare/v0.1.0...v0.2.0
39
66
  [0.1.0]: https://github.com/skryukov/skooma/commits/v0.1.0
data/README.md CHANGED
@@ -14,6 +14,10 @@ Skooma is a Ruby library for validating API implementations against OpenAPI docu
14
14
  - Supports request/response validations against OpenAPI document
15
15
  - Includes RSpec and Minitest helpers
16
16
 
17
+ ### Learn more
18
+
19
+ - [Let there be docs! A documentation-first approach to Rails API development](https://evilmartians.com/events/let-there-be-docs-a-documentation-first-approach-to-rails-api-development) – Talk and slides from Friendly.rb 2023
20
+
17
21
  <a href="https://evilmartians.com/?utm_source=skooma&utm_campaign=project_page">
18
22
  <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54">
19
23
  </a>
@@ -44,6 +48,9 @@ RSpec.configure do |config|
44
48
  # ...
45
49
  path_to_openapi = Rails.root.join("docs", "openapi.yml")
46
50
  config.include Skooma::RSpec[path_to_openapi], type: :request
51
+
52
+ # OR pass path_prefix option if your API is mounted under a prefix:
53
+ config.include Skooma::RSpec[path_to_openapi, path_prefix: "/internal/api"], type: :request
47
54
  end
48
55
  ```
49
56
 
@@ -19,7 +19,7 @@ module Skooma
19
19
  end
20
20
 
21
21
  def failure_message
22
- return "Expected #{@expected} status code" unless status_matches?
22
+ return "Expected #{@expected} status code, but got #{@mapped_response["response"]["status"]}" unless status_matches?
23
23
 
24
24
  super
25
25
  end
@@ -23,24 +23,24 @@ module Skooma
23
23
 
24
24
  def request_object
25
25
  # `rails` integration
26
- return request if defined?(::ActionDispatch)
26
+ return @request if defined?(::ActionDispatch) && @request.is_a?(::ActionDispatch::Request)
27
27
  # `rack-test` integration
28
- return last_request if defined?(::Rack::Test)
28
+ return last_request if defined?(::Rack::Test) && defined?(:last_request)
29
29
 
30
30
  raise "Request object not found"
31
31
  end
32
32
 
33
33
  def response_object
34
34
  # `rails` integration
35
- return response if defined?(::ActionDispatch)
35
+ return @response if defined?(::ActionDispatch) && @response.is_a?(::ActionDispatch::Response)
36
36
  # `rack-test` integration
37
- return last_response if defined?(::Rack::Test)
37
+ return last_response if defined?(::Rack::Test) && defined?(:last_response)
38
38
 
39
39
  raise "Response object not found"
40
40
  end
41
41
  end
42
42
 
43
- def initialize(helper_methods_module, openapi_path, base_uri: "https://skoomarb.dev/")
43
+ def initialize(helper_methods_module, openapi_path, base_uri: "https://skoomarb.dev/", path_prefix: "")
44
44
  super()
45
45
 
46
46
  registry = create_test_registry
@@ -50,6 +50,7 @@ module Skooma
50
50
  JSONSkooma::Sources::Local.new(pathname.dirname.to_s)
51
51
  )
52
52
  schema = registry.schema(URI.parse("#{base_uri}#{pathname.basename}"), schema_class: Skooma::Objects::OpenAPI)
53
+ schema.path_prefix = path_prefix
53
54
 
54
55
  include DefaultHelperMethods
55
56
  include helper_methods_module
@@ -32,7 +32,7 @@ module Skooma
32
32
  subresult.annotate({"path_attributes" => attributes})
33
33
  path_schema.evaluate(instance, subresult)
34
34
 
35
- if subresult.passed?
35
+ if subresult.passed? && subresult.children.any?
36
36
  result.success
37
37
  else
38
38
  result.failure("Path #{instance["path"]} is invalid")
@@ -43,6 +43,7 @@ module Skooma
43
43
  private
44
44
 
45
45
  def find_route(instance_path)
46
+ instance_path = instance_path.delete_prefix(json.root.path_prefix)
46
47
  return [instance_path, {}, json[instance_path]] if json.key?(instance_path)
47
48
 
48
49
  @regexp_map.reduce(nil) do |result, (path, path_regex, subschema)|
@@ -31,6 +31,18 @@ module Skooma
31
31
  super(Instance.new(instance), result)
32
32
  end
33
33
 
34
+ def path_prefix=(value)
35
+ raise ArgumentError, "Path prefix must be a string" unless value.is_a?(String)
36
+
37
+ @path_prefix = value
38
+ @path_prefix = "/#{@path_prefix}" unless @path_prefix.start_with?("/")
39
+ @path_prefix = @path_prefix.delete_suffix("/") if @path_prefix.end_with?("/")
40
+ end
41
+
42
+ def path_prefix
43
+ @path_prefix || ""
44
+ end
45
+
34
46
  def json_schema_dialect_uri
35
47
  @json_schema_dialect_uri || parent_schema&.json_schema_dialect_uri
36
48
  end
@@ -12,7 +12,7 @@ module Skooma
12
12
  def initialize(parent_schema, value)
13
13
  super
14
14
  keys = json.filter_map { |v| v["in"] && [v["in"].value, v["name"].value] }
15
- parent_params = (parent_schema.parent["parameters"] || [])
15
+ parent_params = parent_schema.parent["parameters"] || []
16
16
  parent_params.reject! do |v|
17
17
  v["in"] && keys.include?([v["in"].value, v["name"].value])
18
18
  end
@@ -8,6 +8,10 @@ module Skooma
8
8
  def evaluate(instance, result)
9
9
  return result.discard unless instance["method"] == key
10
10
 
11
+ if json["responses"].nil? && instance["response"]
12
+ return result.failure("Responses are not listed for #{key.upcase} #{instance["path"]}")
13
+ end
14
+
11
15
  json.evaluate(instance, result)
12
16
  return result.success if result.passed?
13
17
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Skooma
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.2"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skooma
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Svyatoslav Kryukov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-23 00:00:00.000000000 Z
11
+ date: 2024-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zeitwerk
@@ -30,15 +30,15 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.2'
33
+ version: 0.2.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.2'
41
- description: I bring some sugar for your APIs.
40
+ version: 0.2.0
41
+ description: Apply a documentation-first approach to API development.
42
42
  email:
43
43
  - me@skryukov.dev
44
44
  executables: []
@@ -166,5 +166,5 @@ requirements: []
166
166
  rubygems_version: 3.3.7
167
167
  signing_key:
168
168
  specification_version: 4
169
- summary: I bring some sugar for your APIs.
169
+ summary: Validate API implementations against OpenAPI documents.
170
170
  test_files: []