Skip to content

Commit

Permalink
WIP: Use json_schema instead of json-schema
Browse files Browse the repository at this point in the history
* `json_matchers` cannot easily be used concurrently with Heroku's
  JSON API tools, i.e. `prmd` and `committee`, because `json_matchers`
  makes different assumptions about the structure of the user's
  schemata. An example of an incompatibility can be found in
  #25: `json_matchers`
  breaks when the `id` property is present within a schema, but the Heroku
  tools require the presence of the `id` property
  ([reference](https://github.com/interagent/prmd/blob/master/docs/schemata.md#meta-data)).

  This is happening because the libraries used to dereference JSON
  pointers behave differently. `json-schema`, the library we're
  currently using, appears to conform less strictly to the JSON Schema
  specification than the library the Heroku tools use, `json_schema`.

  One solution to this problem is to update `json_matchers` to use the
  same approach to validating schemata as the Heroku tools.

  1. Use `json_schema` instead of `json-schema` to validate schemata
  2. Update documentation to instruct readers to follow Heroku's
  guidelines for structuring schemata:
https://github.com/interagent/prmd/blob/master/docs/schemata.md

* In this commit I've replaced `json-schema` with `json_schema` and
  made an attempt at updating the specs.
  • Loading branch information
Laila Winner committed Nov 24, 2015
1 parent 9dabf15 commit c537fa2
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 24 deletions.
2 changes: 1 addition & 1 deletion json_matchers.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]

spec.add_dependency("json-schema", "~> 2.2.5")
spec.add_dependency("json_schema")
spec.add_dependency("activesupport", '>= 3.0.0')

spec.add_development_dependency "bundler", "~> 1.7"
Expand Down
26 changes: 15 additions & 11 deletions lib/json_matchers/matcher.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require "json-schema"
require "json_schema"

module JsonMatchers
class Matcher
Expand All @@ -10,16 +10,20 @@ def initialize(schema_path, **options)
def matches?(response)
@response = response

JSON::Validator.validate!(
schema_path.to_s,
response.body,
options,
)
rescue JSON::Schema::ValidationError => ex
@validation_failure_message = ex.message
false
rescue JSON::ParserError
raise InvalidSchemaError
begin
schema_data = JSON.parse(File.read(@schema_path.to_s))
response_body = JSON.parse(@response.body)
json_schema = JsonSchema.parse!(schema_data)
json_schema.expand_references
json_schema.validate!(response_body)
rescue RuntimeError => ex
@validation_failure_message = ex.message
return false
rescue JsonSchema::SchemaError, JSON::ParserError => ex
raise InvalidSchemaError
end

true
end

def validation_failure_message
Expand Down
63 changes: 51 additions & 12 deletions spec/json_matchers/match_response_schema_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,22 +95,61 @@
end

it "supports $ref" do
create_schema("single", {
create_schema("user", {
"id" => "user",
"type" => "object",
"required" => ["foo"],
"properties" => {
"foo" => { "type" => "string" },
}
"definitions" => {
"id" => {
"description" => "A unique identifier",
"example" => "1",
"type" => "integer"
}
},
"required" => ["id"],
"properties" => { "id" => { "$ref" => "#/definitions/id" } }
})
create_schema("collection", {
"type" => "array",
"items" => { "$ref" => "single.json" },
create_schema("users", {
"id" => "users",
"type" => "object",
"definitions" => {
"users" => {
"description" => "A collection of users",
"example" => [{ "id" => "1" }],
"type" => "array",
"items" => { "$ref" => "/schemas/user.json#" }
}
},
"required" => ["users"],
"properties" => { "users" => { "$ref" => "#/definitions/users" } }
})

valid_response = response_for([{ "foo" => "is a string" }])
invalid_response = response_for([{ "foo" => 0 }])
valid_response = response_for([{ "id" => "1" }])
invalid_response = response_for([{ "id" => "invalid" }])

expect(valid_response).to match_response_schema("collection")
expect(invalid_response).not_to match_response_schema("collection")
expect(valid_response).to match_response_schema("users")
expect(invalid_response).not_to match_response_schema("users")
end

it "supports the 'id' keyword" do
top_level_schema = {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"a": { "$ref": "#/nested.json" }
}
}
nested_schema = {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": ["b"],
"properties": { "b": { "type": "string" } },
"id": "nested"
}
response_json = { a: { b: "foo" } }
create_schema("schema-with-id", top_level_schema)
create_schema("nested", nested_schema)

expect(response_for(response_json)).
to match_response_schema("schema-with-id")
end
end

0 comments on commit c537fa2

Please sign in to comment.