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

Configure matcher to record_errors #52

Merged
merged 1 commit into from
Feb 24, 2017
Merged
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
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
master
======

* Default `record_errors: true` [#52]
* Add support for configuring `record_errors` [#51]

[#52]: https://github.com/thoughtbot/json_matchers/pull/52
[#51]: https://github.com/thoughtbot/json_matchers/pull/51

0.6.3
=====

Expand Down
4 changes: 3 additions & 1 deletion lib/json_matchers/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ class Configuration
attr_reader :options

def initialize
@options = {}
@options = {
record_errors: true,
}
end
end
end
46 changes: 18 additions & 28 deletions lib/json_matchers/matcher.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require "json-schema"
require "json_matchers/payload"
require "json_matchers/validator"

module JsonMatchers
class Matcher
Expand All @@ -9,47 +9,37 @@ def initialize(schema_path, options = {})
end

def matches?(response)
# validate! will not raise and will always return true if you configure
# the validator to record errors, so we must instead inspect
# fully_validate's errors response
if options[:record_errors]
errors = JSON::Validator.fully_validate(
schema_path.to_s,
Payload.new(response).to_s,
options,
)

# errors is an array, but it will always only return a single item
if errors.any?
@validation_failure_message = errors.first
false
else
true
end
else
JSON::Validator.validate!(
schema_path.to_s,
Payload.new(response).to_s,
options,
)
end
rescue JSON::Schema::ValidationError => ex
@validation_failure_message = ex.message
validator = build_validator(response)

self.errors = validator.validate!

errors.empty?
rescue JSON::Schema::ValidationError => error
self.errors = [error.message]
false
rescue JSON::Schema::JsonParseError
raise InvalidSchemaError
end

def validation_failure_message
@validation_failure_message.to_s
errors.first.to_s
end

private

attr_reader :schema_path, :options
attr_accessor :errors

def default_options
JsonMatchers.configuration.options || {}
end

def build_validator(response)
Validator.new(
options: options,
response: response,
schema_path: schema_path,
)
end
end
end
38 changes: 38 additions & 0 deletions lib/json_matchers/validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require "json-schema"
require "json_matchers/payload"

module JsonMatchers
class Validator
def initialize(options:, response:, schema_path:)
@options = options.dup
@payload = Payload.new(response).to_s
@schema_path = schema_path.to_s
end

def validate!
if recording_errors?
validate_recording_errors
else
validate
end
end

private

attr_reader :options, :payload, :schema_path

def recording_errors?
options.fetch(:record_errors, false)
end

def validate_recording_errors
JSON::Validator.fully_validate(schema_path, payload, options)
end

def validate
JSON::Validator.validate!(schema_path, payload, options)

[]
end
end
end
23 changes: 17 additions & 6 deletions spec/json_matchers/match_response_schema_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,24 @@
end

context "when configured to record errors" do
it "fails when the body is missing a required property" do
it "includes the reasons for failure in the exception's message" do
with_options(record_errors: true) do
create_schema("foo_schema",
"type" => "object",
"required" => ["foo"])

expect(response_for({})).not_to match_response_schema("foo_schema")
create_schema("foo_schema", {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant curly braces around a hash parameter.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant curly braces around a hash parameter.

"type" => "object",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use 2 spaces for indentation in a hash, relative to the first position after the preceding left parenthesis.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use 2 spaces for indentation in a hash, relative to the first position after the preceding left parenthesis.

"properties" => {
"username" => {
"allOf": [
{ "type": "string" },
{ "minLength": 5 }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a comma after the last item of a multiline array.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a comma after the last item of a multiline array.

]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a comma after the last item of a multiline hash.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a comma after the last item of a multiline hash.

}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a comma after the last item of a multiline hash.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a comma after the last item of a multiline hash.

}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a comma after the last item of a multiline hash.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a comma after the last item of a multiline hash.

})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent the right brace the same as the first position after the preceding left parenthesis.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent the right brace the same as the first position after the preceding left parenthesis.

invalid_payload = response_for({ "username" => "foo" })

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant curly braces around a hash parameter.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant curly braces around a hash parameter.


expect {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using {...} for multi-line blocks.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using {...} for multi-line blocks.

expect(invalid_payload).to match_response_schema("foo_schema")
}.to raise_error(/minimum/)
end
end
end
Expand Down