skooma 0.1.0 → 0.2.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: 966ef8f92df0a6f38895c4aca4185b297256042173a3b42d32da01d5b826c24e
4
- data.tar.gz: c1a4661e7228815c3d1a031ffb646cefd067031e1b1138346f845af469a89135
3
+ metadata.gz: 784c4f022f60aced719808f543bcdc9a153df4a58dd44179888f73f9c7c8fa3f
4
+ data.tar.gz: c60b8a11cd1ccbefcc83207a0ad2734281d8e194b58fd2637dd25bd48e7577a3
5
5
  SHA512:
6
- metadata.gz: 047e598c99b797d98b7758a015ced5323c0dfe2889f64cca8e33b7a139713fa7515683da2e054c1597a1a1b79e62b9f77ab10e72d0b7276908e15b862cb54367
7
- data.tar.gz: 1b0dbfa91b60430bd1397d4145cc4d339c2144bfdda88d9c9085800a51a9fa0077087e09c3eb998136cf35c95b49d9449153113976fe6c72fbf6fa5258334841
6
+ metadata.gz: c17febaba56cd351329f42acd06a74fdbd02782ccaef3d855098cc41159ee31ef8862cba849a4591f15a6580ffe69705fc783a5ab026f52fa5eefbf55963cd8f
7
+ data.tar.gz: 35f93cdc5ace695d8e3bf7f315a573e9498e1799fb4bbd9f012d097b7b04ea0a3626b57239e67fbf49a5193d07947aa7c671543630353b10401a16bc66fb0625
data/CHANGELOG.md CHANGED
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning].
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.0] - 2023-10-23
11
+
12
+ ### Added
13
+
14
+ - Add `minitest` and `rake-test` support. ([@skryukov])
15
+ - Add `discriminator` keyword support. ([@skryukov])
16
+
17
+ ### Fixed
18
+
19
+ - Fix Zeitwerk eager loading. ([@skryukov])
20
+
10
21
  ## [0.1.0] - 2023-09-27
11
22
 
12
23
  ### Added
@@ -15,7 +26,8 @@ and this project adheres to [Semantic Versioning].
15
26
 
16
27
  [@skryukov]: https://github.com/skryukov
17
28
 
18
- [Unreleased]: https://github.com/skryukov/skooma/compare/v0.1.0...HEAD
29
+ [Unreleased]: https://github.com/skryukov/skooma/compare/v0.2.0...HEAD
30
+ [0.2.0]: https://github.com/skryukov/skooma/compare/v0.1.0...v0.2.0
19
31
  [0.1.0]: https://github.com/skryukov/skooma/commits/v0.1.0
20
32
 
21
33
  [Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
data/README.md CHANGED
@@ -3,12 +3,16 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/skooma.svg)](https://rubygems.org/gems/skooma)
4
4
  [![Ruby](https://github.com/skryukov/skooma/actions/workflows/main.yml/badge.svg)](https://github.com/skryukov/skooma/actions/workflows/main.yml)
5
5
 
6
+ <img align="right" height="150" width="150" title="Skooma logo" src="./assets/logo.svg">
7
+
6
8
  Skooma is a Ruby library for validating API implementations against OpenAPI documents.
7
9
 
8
- Features:
10
+ ### Features
11
+
9
12
  - Supports OpenAPI 3.1.0
10
13
  - Supports OpenAPI document validation
11
14
  - Supports request/response validations against OpenAPI document
15
+ - Includes RSpec and Minitest helpers
12
16
 
13
17
  <a href="https://evilmartians.com/?utm_source=skooma&utm_campaign=project_page">
14
18
  <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54">
@@ -26,20 +30,24 @@ If bundler is not being used to manage dependencies, install the gem by executin
26
30
 
27
31
  ## Usage
28
32
 
29
- ### Configuration
33
+ Skooma provides `rspec` and `minitest` helpers for validating OpenAPI documents and requests/responses against them.
34
+ Skooma helpers are designed to be used with `rails` request specs or `rack-test`.
35
+
36
+ ### RSpec
37
+
38
+ #### Configuration
30
39
 
31
40
  ```ruby
32
41
  # spec/rails_helper.rb
33
42
 
34
43
  RSpec.configure do |config|
35
44
  # ...
36
- Skooma.create_registry
37
45
  path_to_openapi = Rails.root.join("docs", "openapi.yml")
38
46
  config.include Skooma::RSpec[path_to_openapi], type: :request
39
47
  end
40
48
  ```
41
49
 
42
- ### Validate OpenAPI document
50
+ #### Validate OpenAPI document
43
51
 
44
52
  ```ruby
45
53
  # spec/openapi_spec.rb
@@ -53,7 +61,7 @@ describe "OpenAPI document", type: :request do
53
61
  end
54
62
  ```
55
63
 
56
- ### Validate request
64
+ #### Validate request
57
65
 
58
66
  ```ruby
59
67
  # spec/requests/feed_spec.rb
@@ -94,6 +102,55 @@ end
94
102
  # " [\"animalId\", \"food\", \"amount\"]"}]}
95
103
  ```
96
104
 
105
+ ### Minitest
106
+
107
+ #### Configuration
108
+
109
+ ```ruby
110
+ # test/test_helper.rb
111
+
112
+ ActionDispatch::IntegrationTest.include Skooma::Minitest[Rails.root.join("docs", "openapi.yml")]
113
+ ```
114
+
115
+ #### Validate OpenAPI document
116
+
117
+ ```ruby
118
+ # test/openapi_test.rb
119
+
120
+ require "test_helper"
121
+
122
+ class OpenapiTest < ActionDispatch::IntegrationTest
123
+ test "is valid OpenAPI document" do
124
+ assert_is_valid_document(skooma_openapi_schema)
125
+ end
126
+ end
127
+ ```
128
+
129
+ #### Validate request
130
+
131
+ ```ruby
132
+ # test/integration/items_test.rb
133
+
134
+ require "test_helper"
135
+
136
+ class ItemsTest < ActionDispatch::IntegrationTest
137
+ test "GET /" do
138
+ get "/"
139
+ assert_conform_schema(200)
140
+ end
141
+
142
+ test "POST / conforms to schema with 201 response code" do
143
+ post "/", params: {foo: "bar"}, as: :json
144
+ assert_conform_schema(201)
145
+ end
146
+
147
+ test "POST / conforms to schema with 400 response code" do
148
+ post "/", params: {foo: "baz"}, as: :json
149
+ assert_conform_response_schema(400)
150
+ end
151
+ end
152
+ ```
153
+
97
154
  ## Alternatives
98
155
 
99
156
  - [openapi_first](https://github.com/ahx/openapi_first)
@@ -103,7 +160,6 @@ end
103
160
 
104
161
  - Full support for external `$ref`s
105
162
  - Full OpenAPI 3.1.0 support:
106
- - `discriminator` keyword
107
163
  - respect `style` and `explode` keywords
108
164
  - xml
109
165
  - Callbacks and webhooks validations
@@ -12,6 +12,8 @@ module Skooma
12
12
 
13
13
  registry.add_vocabulary(
14
14
  "https://spec.openapis.org/oas/3.1/vocab/base",
15
+ Skooma::Keywords::OAS31::Dialect::AnyOf,
16
+ Skooma::Keywords::OAS31::Dialect::OneOf,
15
17
  Skooma::Keywords::OAS31::Dialect::Discriminator,
16
18
  Skooma::Keywords::OAS31::Dialect::Xml,
17
19
  Skooma::Keywords::OAS31::Dialect::ExternalDocs,
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module EnvMapper
5
+ class << self
6
+ PLAIN_HEADERS = %w[CONTENT_LENGTH CONTENT_TYPE].freeze
7
+ REGEXP_HTTP = /^HTTP_/.freeze
8
+
9
+ def call(env, response = nil, with_response: true, with_request: true)
10
+ result = {
11
+ "method" => env["REQUEST_METHOD"].downcase,
12
+ "path" => env["PATH_INFO"]
13
+ }
14
+ result["request"] = map_request(env) if with_request
15
+ result["response"] = map_response(response) if response && with_response
16
+
17
+ result
18
+ end
19
+
20
+ private
21
+
22
+ def map_request(env)
23
+ {
24
+ "query" => env["rack.request.query_string"] || env["QUERY_STRING"],
25
+ "headers" => env.select { |k, _| k.start_with?("HTTP_") || PLAIN_HEADERS.include?(k) }.transform_keys { |k| k.sub(REGEXP_HTTP, "").split("_").map(&:capitalize).join("-") },
26
+ "body" => env["RAW_POST_DATA"]
27
+ }
28
+ end
29
+
30
+ def map_response(response)
31
+ status, headers, body = response.to_a
32
+ full_body = +""
33
+ body.each { |chunk| full_body << chunk }
34
+ {
35
+ "status" => status,
36
+ "headers" => headers.to_h,
37
+ "body" => full_body
38
+ }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Skooma
4
- class Inflector < Zeitwerk::Inflector
4
+ class Inflector < Zeitwerk::GemInflector
5
5
  STATIC_MAPPING = {
6
6
  "oas_3_1" => "OAS31",
7
7
  "openapi" => "OpenAPI",
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Keywords
5
+ module OAS31
6
+ module Dialect
7
+ class AnyOf < JSONSkooma::Keywords::Applicator::AnyOf
8
+ self.key = "anyOf"
9
+ self.value_schema = :array_of_schemas
10
+ self.depends_on = %w[discriminator]
11
+
12
+ def evaluate(instance, result)
13
+ discriminator_schema = result.sibling(instance, "discriminator")&.annotation
14
+ reorder_json(discriminator_schema)
15
+
16
+ super
17
+ end
18
+
19
+ private
20
+
21
+ def reorder_json(discriminator_schema)
22
+ return unless discriminator_schema
23
+
24
+ first = @json.delete_at(@json.index { |schema| resolve_uri(schema["$ref"]) == discriminator_schema })
25
+ @json.unshift first if first
26
+ end
27
+
28
+ def resolve_uri(uri)
29
+ uri = URI.parse(uri)
30
+ return uri if uri.absolute?
31
+
32
+ parent_schema.base_uri + uri if parent_schema.base_uri
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -4,8 +4,39 @@ module Skooma
4
4
  module Keywords
5
5
  module OAS31
6
6
  module Dialect
7
- class Discriminator < JSONSkooma::Keywords::BaseAnnotation
7
+ # Discriminator keyword is an annotation keyword,
8
+ # it does not affect validation of allOf/anyOf/oneOf schemas.
9
+ # See https://github.com/OAI/OpenAPI-Specification/pull/2618
10
+ class Discriminator < JSONSkooma::Keywords::Base
8
11
  self.key = "discriminator"
12
+
13
+ def evaluate(instance, result)
14
+ value = instance[json["propertyName"]]
15
+ uri = mapped_uri(value)
16
+ return result.failure("Could not resolve discriminator for value `#{value.inspect}`") if uri.nil?
17
+
18
+ parent_schema.registry.schema(
19
+ uri,
20
+ metaschema_uri: parent_schema.metaschema_uri,
21
+ cache_id: parent_schema.cache_id
22
+ )
23
+ result.annotate(uri)
24
+ rescue JSONSkooma::RegistryError => e
25
+ result.failure("Could not resolve discriminator mapping: #{e.message}")
26
+ end
27
+
28
+ private
29
+
30
+ def mapped_uri(value)
31
+ uri = json["mapping"]&.fetch(value, value)
32
+ return if uri.nil?
33
+
34
+ uri = "#/components/schemas/#{uri}" unless uri.start_with?("#") || uri.include?("/")
35
+ uri = URI.parse(uri)
36
+ return uri if uri.absolute?
37
+
38
+ parent_schema.base_uri + uri if parent_schema.base_uri
39
+ end
9
40
  end
10
41
  end
11
42
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Keywords
5
+ module OAS31
6
+ module Dialect
7
+ class OneOf < JSONSkooma::Keywords::Applicator::OneOf
8
+ self.key = "oneOf"
9
+ self.value_schema = :array_of_schemas
10
+ self.depends_on = %w[discriminator]
11
+
12
+ def evaluate(instance, result)
13
+ discriminator_schema = result.sibling(instance, "discriminator")&.annotation
14
+ reorder_json(discriminator_schema)
15
+
16
+ super
17
+ end
18
+
19
+ private
20
+
21
+ def reorder_json(discriminator_schema)
22
+ return unless discriminator_schema
23
+
24
+ first = @json.delete_at(@json.index { |schema| resolve_uri(schema["$ref"]) == discriminator_schema })
25
+ @json.unshift first if first
26
+ end
27
+
28
+ def resolve_uri(uri)
29
+ uri = URI.parse(uri)
30
+ return uri if uri.absolute?
31
+
32
+ parent_schema.base_uri + uri if parent_schema.base_uri
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Matchers
5
+ class BeValidDocument
6
+ def matches?(actual)
7
+ @actual = actual
8
+ return false unless comparable?
9
+
10
+ @result = @actual.validate
11
+ @result.valid?
12
+ end
13
+
14
+ def description
15
+ "be a valid OpenAPI document"
16
+ end
17
+
18
+ def failure_message
19
+ return "expected value to be an OpenAPI object" unless comparable?
20
+
21
+ <<~MSG
22
+ must valid against OpenAPI specification:
23
+ #{pretty(@result.output(:detailed))}
24
+ MSG
25
+ end
26
+
27
+ private
28
+
29
+ def pretty(result)
30
+ PP.pp(result, +"")
31
+ end
32
+
33
+ def comparable?
34
+ @actual.is_a?(Skooma::Objects::OpenAPI)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Matchers
5
+ class ConformRequestSchema
6
+ def initialize(schema, mapped_response)
7
+ @schema = schema
8
+ @mapped_response = mapped_response
9
+ end
10
+
11
+ def matches?(*)
12
+ @result = @schema.evaluate(@mapped_response)
13
+ @result.valid?
14
+ end
15
+
16
+ def description
17
+ "conform request schema"
18
+ end
19
+
20
+ def failure_message
21
+ <<~MSG
22
+ ENV:
23
+ #{pretty(@mapped_response)}
24
+
25
+ Validation Result:
26
+ #{pretty(@result.output(:skooma))}
27
+ MSG
28
+ end
29
+
30
+ private
31
+
32
+ def pretty(result)
33
+ PP.pp(result, +"")
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Matchers
5
+ class ConformResponseSchema < ConformRequestSchema
6
+ def initialize(schema, mapped_response, expected)
7
+ super(schema, mapped_response)
8
+ @expected = expected
9
+ end
10
+
11
+ def description
12
+ "conform response schema with #{@expected} response code"
13
+ end
14
+
15
+ def matches?(*)
16
+ return false unless status_matches?
17
+
18
+ super
19
+ end
20
+
21
+ def failure_message
22
+ return "Expected #{@expected} status code" unless status_matches?
23
+
24
+ super
25
+ end
26
+
27
+ private
28
+
29
+ def status_matches?
30
+ @mapped_response["response"]["status"] == @expected
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Matchers
5
+ class ConformSchema < ConformResponseSchema
6
+ def description
7
+ "conform schema with #{@expected} response code"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+
5
+ module Skooma
6
+ module Matchers
7
+ class Wrapper < Module
8
+ TEST_REGISTRY_NAME = "skooma_test_registry"
9
+
10
+ class << self
11
+ alias_method :[], :new
12
+ end
13
+
14
+ module DefaultHelperMethods
15
+ def mapped_response(with_response: true, with_request: true)
16
+ Skooma::EnvMapper.call(
17
+ request_object.env,
18
+ response_object,
19
+ with_response: with_response,
20
+ with_request: with_request
21
+ )
22
+ end
23
+
24
+ def request_object
25
+ # `rails` integration
26
+ return request if defined?(::ActionDispatch)
27
+ # `rack-test` integration
28
+ return last_request if defined?(::Rack::Test)
29
+
30
+ raise "Request object not found"
31
+ end
32
+
33
+ def response_object
34
+ # `rails` integration
35
+ return response if defined?(::ActionDispatch)
36
+ # `rack-test` integration
37
+ return last_response if defined?(::Rack::Test)
38
+
39
+ raise "Response object not found"
40
+ end
41
+ end
42
+
43
+ def initialize(helper_methods_module, openapi_path, base_uri: "https://skoomarb.dev/")
44
+ super()
45
+
46
+ registry = create_test_registry
47
+ pathname = Pathname.new(openapi_path)
48
+ registry.add_source(
49
+ base_uri,
50
+ JSONSkooma::Sources::Local.new(pathname.dirname.to_s)
51
+ )
52
+ schema = registry.schema(URI.parse("#{base_uri}#{pathname.basename}"), schema_class: Skooma::Objects::OpenAPI)
53
+
54
+ include DefaultHelperMethods
55
+ include helper_methods_module
56
+
57
+ define_method :skooma_openapi_schema do
58
+ schema
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def create_test_registry
65
+ JSONSkooma::Registry[TEST_REGISTRY_NAME]
66
+ rescue JSONSkooma::RegistryError
67
+ Skooma.create_registry(name: TEST_REGISTRY_NAME)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ # Minitest helpers for OpenAPI schema validation
5
+ # @example
6
+ # describe TestApp do
7
+ # include Skooma::RSpec[Rails.root.join("docs", "openapi.yml")]
8
+ # # ...
9
+ # end
10
+ class Minitest < Matchers::Wrapper
11
+ module HelperMethods
12
+ def assert_conform_schema(expected_status)
13
+ matcher = Matchers::ConformSchema.new(skooma_openapi_schema, mapped_response, expected_status)
14
+
15
+ assert matcher.matches?, -> { matcher.failure_message }
16
+ end
17
+
18
+ def assert_conform_request_schema
19
+ matcher = Matchers::ConformRequestSchema.new(skooma_openapi_schema, mapped_response(with_response: false))
20
+
21
+ assert matcher.matches?, -> { matcher.failure_message }
22
+ end
23
+
24
+ def assert_conform_response_schema(expected_status)
25
+ matcher = Matchers::ConformResponseSchema.new(skooma_openapi_schema, mapped_response(with_request: false), expected_status)
26
+
27
+ assert matcher.matches?, -> { matcher.failure_message }
28
+ end
29
+
30
+ def assert_is_valid_document(document)
31
+ matcher = Matchers::BeValidDocument.new
32
+
33
+ assert matcher.matches?(document), -> { matcher.failure_message }
34
+ end
35
+ end
36
+
37
+ def initialize(openapi_path, **params)
38
+ super(HelperMethods, openapi_path, **params)
39
+ end
40
+ end
41
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skooma
2
4
  module OutputFormat
3
5
  class << self
data/lib/skooma/rspec.rb CHANGED
@@ -1,166 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "yaml"
4
-
5
3
  module Skooma
6
4
  # RSpec matchers for OpenAPI schema validation
7
5
  # @example
8
- # require "skooma/rspec"
9
- # # ...
10
6
  # RSpec.configure do |config|
11
7
  # # ...
12
8
  # config.include Skooma::RSpec[Rails.root.join("docs", "openapi.yml")], type: :request
13
9
  # end
14
- class RSpec < Module
15
- class << self
16
- alias_method :[], :new
17
- end
18
-
19
- module Mapper
20
- PLAIN_HEADERS = %w[CONTENT_LENGTH CONTENT_TYPE].freeze
21
- REGEXP_HTTP = /^HTTP_/.freeze
22
-
23
- def mapped_response(response: true, request: true)
24
- result = {
25
- "method" => env["REQUEST_METHOD"].downcase,
26
- "path" => env["PATH_INFO"]
27
- }
28
-
29
- if response
30
- result["response"] = {
31
- "status" => response_data[0],
32
- "headers" => response_data[1],
33
- "body" => response_data[2]
34
- }
35
- end
36
-
37
- if request
38
- result["request"] = {
39
- "query" => env["rack.request.query_string"] || env["QUERY_STRING"],
40
- "headers" => env.select { |k, _| k.start_with?("HTTP_") || PLAIN_HEADERS.include?(k) }.transform_keys { |k| k.sub(REGEXP_HTTP, "").split("_").map(&:capitalize).join("-") },
41
- "body" => env["RAW_POST_DATA"]
42
- }
43
- end
44
-
45
- result
10
+ class RSpec < Matchers::Wrapper
11
+ module HelperMethods
12
+ def conform_schema(expected_status)
13
+ Matchers::ConformSchema.new(skooma_openapi_schema, mapped_response, expected_status)
46
14
  end
47
15
 
48
- def env
49
- request.env
16
+ def conform_response_schema(expected_status)
17
+ Matchers::ConformResponseSchema.new(skooma_openapi_schema, mapped_response(with_request: false), expected_status)
50
18
  end
51
19
 
52
- def response_data
53
- [response.status, response.headers.to_h, response.body]
20
+ def conform_request_schema
21
+ Matchers::ConformRequestSchema.new(skooma_openapi_schema, mapped_response(with_response: false))
54
22
  end
55
- end
56
-
57
- def initialize(openapi_path, base_uri: "https://skoomarb.dev/")
58
- super()
59
-
60
- pathname = Pathname.new(openapi_path)
61
-
62
- registry = Skooma.create_registry
63
- registry.add_source(
64
- base_uri,
65
- JSONSkooma::Sources::Local.new(pathname.dirname.to_s)
66
- )
67
- schema = registry.schema(URI.parse("#{base_uri}#{pathname.basename}"), schema_class: Skooma::Objects::OpenAPI)
68
23
 
69
- include Mapper
70
-
71
- define_method :skooma_openapi_schema do
72
- schema
24
+ def be_valid_document
25
+ Matchers::BeValidDocument.new
73
26
  end
74
27
  end
75
- end
76
-
77
- ::RSpec::Matchers.define(:conform_schema) do |expected_status|
78
- match do
79
- next false unless response.status == expected_status
80
-
81
- @result = skooma_openapi_schema.evaluate(mapped_response)
82
- @result.valid?
83
- end
84
-
85
- description do
86
- "conform schema with #{expected_status} response code"
87
- end
88
-
89
- failure_message do
90
- <<~MSG
91
- ENV:
92
- #{PP.pp(mapped_response, +"")}
93
-
94
- Validation Result:
95
- #{@result ? PP.pp(@result.output(:skooma), +"") : "Expected #{expected_status} status code"}
96
- MSG
97
- end
98
- end
99
-
100
- ::RSpec::Matchers.define(:conform_request_schema) do
101
- match do
102
- @result = skooma_openapi_schema.evaluate(mapped_response(response: false))
103
- @result.valid?
104
- end
105
-
106
- description do
107
- "conform request schema"
108
- end
109
-
110
- failure_message do
111
- <<~MSG
112
- ENV:
113
- #{PP.pp(mapped_response, +"")}
114
-
115
- Validation Result:
116
- #{@result ? PP.pp(@result.output(:skooma), +"") : "Expected #{expected_status} status code"}
117
- MSG
118
- end
119
- end
120
-
121
- ::RSpec::Matchers.define(:conform_response_schema) do |expected_status|
122
- match do
123
- next false unless response.status == expected_status
124
-
125
- @result = skooma_openapi_schema.evaluate(mapped_response(request: false))
126
- @result.valid?
127
- end
128
-
129
- description do
130
- "conform response schema with #{expected_status} response code"
131
- end
132
-
133
- failure_message do
134
- <<~MSG
135
- ENV:
136
- #{PP.pp(mapped_response, +"")}
137
-
138
- Validation Result:
139
- #{@result ? PP.pp(@result.output(:skooma), +"") : "Expected #{expected_status} status code"}
140
- MSG
141
- end
142
- end
143
-
144
- ::RSpec::Matchers.define(:be_valid_document) do
145
- match do |actual|
146
- @actual = actual
147
- next false unless comparable?
148
-
149
- @result = actual.validate
150
- @result.valid?
151
- end
152
-
153
- description { "be a valid OpenAPI document" }
154
-
155
- failure_message do
156
- next "expected value to be an OpenAPI object" unless comparable?
157
-
158
- pretty_output = PP.pp(@result.output(:detailed), +"")
159
- "must valid against OpenAPI specification:\n#{pretty_output}"
160
- end
161
28
 
162
- def comparable?
163
- actual.is_a?(Skooma::Objects::OpenAPI)
29
+ def initialize(openapi_path, **params)
30
+ super(HelperMethods, openapi_path, **params)
164
31
  end
165
32
  end
166
33
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skooma
2
4
  module Validators
3
5
  class Double < JSONSkooma::Validators::Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skooma
2
4
  module Validators
3
5
  class Float < JSONSkooma::Validators::Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skooma
2
4
  module Validators
3
5
  class Int32 < JSONSkooma::Validators::Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skooma
2
4
  module Validators
3
5
  class Int64 < JSONSkooma::Validators::Base
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Skooma
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/skooma.rb CHANGED
@@ -6,7 +6,7 @@ require "zeitwerk"
6
6
  require_relative "skooma/inflector"
7
7
 
8
8
  loader = Zeitwerk::Loader.for_gem
9
- loader.inflector = Skooma::Inflector.new
9
+ loader.inflector = Skooma::Inflector.new(__FILE__)
10
10
  loader.setup
11
11
 
12
12
  module Skooma
@@ -19,8 +19,8 @@ module Skooma
19
19
  JSONSkooma::Formatters.register :skooma, OutputFormat
20
20
 
21
21
  class << self
22
- def create_registry
23
- JSONSkooma.create_registry("2020-12", "oas-3.1", name: REGISTRY_NAME, assert_formats: true)
22
+ def create_registry(name: REGISTRY_NAME)
23
+ JSONSkooma.create_registry("2020-12", "oas-3.1", name: name, assert_formats: true)
24
24
  end
25
25
  end
26
26
  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.1.0
4
+ version: 0.2.0
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-09-26 00:00:00.000000000 Z
11
+ date: 2023-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zeitwerk
@@ -30,17 +30,17 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.1'
33
+ version: '0.2'
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.1'
40
+ version: '0.2'
41
41
  description: I bring some sugar for your APIs.
42
42
  email:
43
- - s.g.kryukov@yandex.ru
43
+ - me@skryukov.dev
44
44
  executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
@@ -55,14 +55,23 @@ files:
55
55
  - lib/skooma.rb
56
56
  - lib/skooma/body_parsers.rb
57
57
  - lib/skooma/dialects/oas_3_1.rb
58
+ - lib/skooma/env_mapper.rb
58
59
  - lib/skooma/inflector.rb
59
60
  - lib/skooma/instance.rb
60
61
  - lib/skooma/keywords/oas_3_1.rb
62
+ - lib/skooma/keywords/oas_3_1/dialect/any_of.rb
61
63
  - lib/skooma/keywords/oas_3_1/dialect/discriminator.rb
62
64
  - lib/skooma/keywords/oas_3_1/dialect/example.rb
63
65
  - lib/skooma/keywords/oas_3_1/dialect/external_docs.rb
66
+ - lib/skooma/keywords/oas_3_1/dialect/one_of.rb
64
67
  - lib/skooma/keywords/oas_3_1/dialect/xml.rb
65
68
  - lib/skooma/keywords/oas_3_1/schema.rb
69
+ - lib/skooma/matchers/be_valid_document.rb
70
+ - lib/skooma/matchers/conform_request_schema.rb
71
+ - lib/skooma/matchers/conform_response_schema.rb
72
+ - lib/skooma/matchers/conform_schema.rb
73
+ - lib/skooma/matchers/wrapper.rb
74
+ - lib/skooma/minitest.rb
66
75
  - lib/skooma/objects/base.rb
67
76
  - lib/skooma/objects/base/keywords/deprecated.rb
68
77
  - lib/skooma/objects/base/keywords/description.rb