Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support not keyword #136

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/openapi_parser/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,17 @@ def message
end
end

class NotNot < OpenAPIError
def initialize(value, reference)
super(reference)
@value = value
end

def message
"#{@value.inspect} isn't 'not' of #{@reference}"
end
end

class NotEnumInclude < OpenAPIError
def initialize(value, reference)
super(reference)
Expand Down
6 changes: 6 additions & 0 deletions lib/openapi_parser/schema_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
require_relative 'schema_validators/any_of_validator'
require_relative 'schema_validators/all_of_validator'
require_relative 'schema_validators/one_of_validator'
require_relative 'schema_validators/not_validator'
require_relative 'schema_validators/nil_validator'
require_relative 'schema_validators/unspecified_type_validator'

Expand Down Expand Up @@ -98,6 +99,7 @@ def validator(value, schema)
return any_of_validator if schema.any_of
return all_of_validator if schema.all_of
return one_of_validator if schema.one_of
return not_validator if schema.not
return nil_validator if value.nil?

case schema.type
Expand Down Expand Up @@ -154,6 +156,10 @@ def one_of_validator
@one_of_validator ||= OpenAPIParser::SchemaValidator::OneOfValidator.new(self, @coerce_value)
end

def not_validator
@not_validator ||= OpenAPIParser::SchemaValidator::NotValidator.new(self, @coerce_value)
end

def nil_validator
@nil_validator ||= OpenAPIParser::SchemaValidator::NilValidator.new(self, @coerce_value)
end
Expand Down
15 changes: 15 additions & 0 deletions lib/openapi_parser/schema_validators/not_validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class OpenAPIParser::SchemaValidator
class NotValidator < Base
# @param [Object] value
# @param [OpenAPIParser::Schemas::Schema] schema
def coerce_and_validate(value, schema, **_keyword_args)
coerced, err = validatable.validate_schema(value, schema.not)

if err
[coerced, nil]
else
[nil, OpenAPIParser::NotNot.new(value, schema.object_reference)]
end
end
end
end
4 changes: 4 additions & 0 deletions lib/openapi_parser/schemas/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ class Schema < Base
# @return [Array<Schema, Reference>, nil]
openapi_attr_list_object :any_of, Schema, reference: true, schema_key: :anyOf

# @!attribute [r] not
# @return [Schema, nil]
openapi_attr_object :not, Schema, reference: true

# @!attribute [r] items
# @return [Schema, nil]
openapi_attr_object :items, Schema, reference: true
Expand Down
16 changes: 16 additions & 0 deletions spec/data/normal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,22 @@ paths:
type: boolean
enum:
- true
not_integer:
not:
type: integer
# The idea of null value comes from
# https://github.com/OAI/OpenAPI-Specification/issues/1368#issuecomment-487314681
null_value:
not:
anyOf:
- type: string
- type: number
- type: boolean
- type: object
- type: array
# Array schema must specify items, so we'll use an
# empty object to mean arrays of any type are included.
items: {}

responses:
'200':
Expand Down
53 changes: 53 additions & 0 deletions spec/openapi_parser/schema_validator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,59 @@
end
end

describe 'not' do
context 'not_integer' do
it do
expect(request_operation.validate_request_body(content_type, { 'not_integer' => "This is string" })).
to eq({ 'not_integer' => "This is string" })
end

it 'invalid' do
expect { request_operation.validate_request_body(content_type, { 'not_integer' => 1 }) }.to raise_error do |e|
expect(e.kind_of?(OpenAPIParser::NotNot)).to eq true
expect(e.message.start_with?("1 isn't 'not' of")).to eq true
end
end
end

context 'null_value' do
it 'invalid' do
expect { request_operation.validate_request_body(content_type, { 'null_value' => 'abc' }) }.to raise_error do |e|
expect(e.kind_of?(OpenAPIParser::NotNot)).to eq true
expect(e.message.start_with?("\"abc\" isn't 'not' of")).to eq true
end
end

it 'invalid' do
expect { request_operation.validate_request_body(content_type, { 'null_value' => 1 }) }.to raise_error do |e|
expect(e.kind_of?(OpenAPIParser::NotNot)).to eq true
expect(e.message.start_with?("1 isn't 'not' of")).to eq true
end
end

it 'invalid' do
expect { request_operation.validate_request_body(content_type, { 'null_value' => true }) }.to raise_error do |e|
expect(e.kind_of?(OpenAPIParser::NotNot)).to eq true
expect(e.message.start_with?("true isn't 'not' of")).to eq true
end
end

it 'invalid' do
expect { request_operation.validate_request_body(content_type, { 'null_value' => {} }) }.to raise_error do |e|
expect(e.kind_of?(OpenAPIParser::NotNot)).to eq true
expect(e.message.start_with?("{} isn't 'not' of")).to eq true
end
end

it 'invalid' do
expect { request_operation.validate_request_body(content_type, { 'null_value' => [1] }) }.to raise_error do |e|
expect(e.kind_of?(OpenAPIParser::NotNot)).to eq true
expect(e.message.start_with?("[1] isn't 'not' of")).to eq true
end
end
end
end

it 'unknown param' do
expect { request_operation.validate_request_body(content_type, { 'unknown' => 1 }) }.to raise_error do |e|
expect(e).to be_kind_of(OpenAPIParser::NotExistPropertyDefinition)
Expand Down