Create assert_response_schema test helper

It is a common pattern to use JSON Schema to validate a API response[1], [2]
and [3].

This patch creates the `assert_response_schema` test helper that helps people do
this kind of validation easily on the controller tests.

[1]: https://robots.thoughtbot.com/validating-json-schemas-with-an-rspec-matcher
[2]: https://github.com/sharethrough/json-schema-rspec
[3]: https://github.com/rails-api/active_model_serializers/issues/1011#issuecomment-127608121
This commit is contained in:
Mauro George
2015-08-29 12:37:24 -03:00
committed by Benjamin Fleischer
parent 9aed6ac634
commit 5058694f4a
15 changed files with 543 additions and 2 deletions

View File

@@ -0,0 +1,128 @@
require 'test_helper'
module ActiveModelSerializers
module Test
class SchemaTest < ActionController::TestCase
include ActiveModelSerializers::Test::Schema
class MyController < ActionController::Base
def index
render json: profile
end
def show
index
end
def name_as_a_integer
profile.name = 1
index
end
def render_using_json_api
render json: profile, adapter: :json_api
end
def invalid_json_body
render json: ''
end
private
def profile
@profile ||= Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
end
end
tests MyController
def test_that_assert_with_a_valid_schema
get :index
assert_response_schema
end
def test_that_raises_a_minitest_error_with_a_invalid_schema
message = "#/name: failed schema #/properties/name: For 'properties/name', \"Name 1\" is not an integer. and #/description: failed schema #/properties/description: For 'properties/description', \"Description 1\" is not a boolean."
get :show
error = assert_raises Minitest::Assertion do
assert_response_schema
end
assert_equal(message, error.message)
end
def test_that_raises_error_with_a_custom_message_with_a_invalid_schema
message = 'oh boy the show is broken'
get :show
error = assert_raises Minitest::Assertion do
assert_response_schema(nil, message)
end
assert_equal(message, error.message)
end
def test_that_assert_with_a_custom_schema
get :show
assert_response_schema('custom/show.json')
end
def test_that_assert_with_a_hyper_schema
get :show
assert_response_schema('hyper_schema.json')
end
def test_simple_json_pointers
get :show
assert_response_schema('simple_json_pointers.json')
end
def test_simple_json_pointers_that_doesnt_match
get :name_as_a_integer
assert_raises Minitest::Assertion do
assert_response_schema('simple_json_pointers.json')
end
end
def test_json_api_schema
get :render_using_json_api
assert_response_schema('render_using_json_api.json')
end
def test_that_assert_with_a_custom_schema_directory
original_schema_path = ActiveModelSerializers.config.schema_path
ActiveModelSerializers.config.schema_path = 'test/support/custom_schemas'
get :index
assert_response_schema
ActiveModelSerializers.config.schema_path = original_schema_path
end
def test_with_a_non_existent_file
message = %r{.* - No Schema file at test/support/schemas/non-existent.json}
get :show
error = assert_raises ActiveModelSerializers::Test::Schema::MissingSchema do
assert_response_schema('non-existent.json')
end
assert_match(message, error.message)
end
def test_that_raises_with_a_invalid_json_body
message = 'A JSON text must at least contain two octets!'
get :invalid_json_body
error = assert_raises ActiveModelSerializers::Test::Schema::InvalidSchemaError do
assert_response_schema('custom/show.json')
end
assert_equal(message, error.message)
end
end
end
end

View File

@@ -0,0 +1,6 @@
{
"properties": {
"name" : { "type" : "string" },
"description" : { "type" : "string" }
}
}

View File

@@ -0,0 +1,6 @@
{
"properties": {
"name" : { "type" : "string" },
"description" : { "type" : "string" }
}
}

View File

@@ -0,0 +1,6 @@
{
"properties": {
"name" : { "type" : "integer" },
"description" : { "type" : "boolean" }
}
}

View File

@@ -0,0 +1,7 @@
{
"id": "file://custom/show.json#",
"properties": {
"name" : { "type" : "string" },
"description" : { "type" : "string" }
}
}

View File

@@ -0,0 +1,93 @@
{
"$schema": "http://json-schema.org/draft-04/hyper-schema",
"title": "Profile",
"description": "Profile schema",
"stability": "prototype",
"strictProperties": true,
"type": [
"object"
],
"definitions": {
"name": {
"description": "unique name of profile",
"readOnly": true,
"type": [
"string"
]
},
"description": {
"description": "description of profile",
"readOnly": true,
"type": [
"string"
]
},
"identity": {
"anyOf": [
{
"$ref": "/schemata/profile#/definitions/name"
}
]
}
},
"links": [
{
"description": "Create a new profile.",
"href": "/profiles",
"method": "POST",
"rel": "create",
"schema": {
"properties": {
},
"type": [
"object"
]
},
"title": "Create"
},
{
"description": "Delete an existing profile.",
"href": "/profiles/{(%2Fschemata%2Fprofile%23%2Fdefinitions%2Fidentity)}",
"method": "DELETE",
"rel": "destroy",
"title": "Delete"
},
{
"description": "Info for existing profile.",
"href": "/profiles/{(%2Fschemata%2Fprofile%23%2Fdefinitions%2Fidentity)}",
"method": "GET",
"rel": "self",
"title": "Info"
},
{
"description": "List existing profiles.",
"href": "/profiles",
"method": "GET",
"rel": "instances",
"title": "List"
},
{
"description": "Update an existing profile.",
"href": "/profiles/{(%2Fschemata%2Fprofile%23%2Fdefinitions%2Fidentity)}",
"method": "PATCH",
"rel": "update",
"schema": {
"properties": {
},
"type": [
"object"
]
},
"title": "Update"
}
],
"properties": {
"name": {
"$ref": "/schemata/profile#/definitions/name"
},
"description": {
"$ref": "/schemata/profile#/definitions/description"
}
},
"id": "/schemata/profile"
}

View File

@@ -0,0 +1,43 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "",
"type": "object",
"properties": {
"data": {
"id": "/data",
"type": "object",
"properties": {
"id": {
"id": "/data/id",
"type": "string"
},
"type": {
"id": "/data/type",
"type": "string"
},
"attributes": {
"id": "/data/attributes",
"type": "object",
"properties": {
"name": {
"id": "/data/attributes/name",
"type": "string"
},
"description": {
"id": "/data/attributes/description",
"type": "string"
}
}
}
},
"required": [
"id",
"type",
"attributes"
]
}
},
"required": [
"data"
]
}

View File

@@ -0,0 +1,10 @@
{
"properties": {
"name": {
"$ref": "file://custom/show.json#/properties/name"
},
"description": {
"$ref": "file://custom/show.json#/properties/description"
}
}
}