forked from rails-api/active_model_serializers
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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]: rails-api#1011 (comment)
- Loading branch information
1 parent
9aed6ac
commit 5058694
Showing
15 changed files
with
543 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
module ActiveModelSerializers | ||
module Test | ||
module Schema | ||
# A Minitest Assertion that test the response is valid against a schema. | ||
# @params schema_path [String] a custom schema path | ||
# @params message [String] a custom error message | ||
# @return [Boolean] true when the response is valid | ||
# @return [Minitest::Assertion] when the response is invalid | ||
# @example | ||
# get :index | ||
# assert_response_schema | ||
def assert_response_schema(schema_path = nil, message = nil) | ||
matcher = AssertResponseSchema.new(schema_path, response, message) | ||
assert(matcher.call, matcher.message) | ||
end | ||
|
||
MissingSchema = Class.new(Errno::ENOENT) | ||
InvalidSchemaError = Class.new(StandardError) | ||
|
||
class AssertResponseSchema | ||
attr_reader :schema_path, :response, :message | ||
|
||
def initialize(schema_path, response, message) | ||
require_json_schema! | ||
@response = response | ||
@schema_path = schema_path || schema_path_default | ||
@message = message | ||
@document_store = JsonSchema::DocumentStore.new | ||
add_schema_to_document_store | ||
end | ||
|
||
def call | ||
json_schema.expand_references!(store: document_store) | ||
status, errors = json_schema.validate(response_body) | ||
@message ||= errors.map(&:to_s).to_sentence | ||
status | ||
end | ||
|
||
protected | ||
|
||
attr_reader :document_store | ||
|
||
def controller_path | ||
response.request.filtered_parameters[:controller] | ||
end | ||
|
||
def action | ||
response.request.filtered_parameters[:action] | ||
end | ||
|
||
def schema_directory | ||
ActiveModelSerializers.config.schema_path | ||
end | ||
|
||
def schema_full_path | ||
"#{schema_directory}/#{schema_path}" | ||
end | ||
|
||
def schema_path_default | ||
"#{controller_path}/#{action}.json" | ||
end | ||
|
||
def schema_data | ||
load_json_file(schema_full_path) | ||
end | ||
|
||
def response_body | ||
load_json(response.body) | ||
end | ||
|
||
def json_schema | ||
@json_schema ||= JsonSchema.parse!(schema_data) | ||
end | ||
|
||
def add_schema_to_document_store | ||
Dir.glob("#{schema_directory}/**/*.json").each do |path| | ||
schema_data = load_json_file(path) | ||
extra_schema = JsonSchema.parse!(schema_data) | ||
document_store.add_schema(extra_schema) | ||
end | ||
end | ||
|
||
def load_json(json) | ||
JSON.parse(json) | ||
rescue JSON::ParserError => ex | ||
raise InvalidSchemaError, ex.message | ||
end | ||
|
||
def load_json_file(path) | ||
load_json(File.read(path)) | ||
rescue Errno::ENOENT | ||
raise MissingSchema, "No Schema file at #{schema_full_path}" | ||
end | ||
|
||
def require_json_schema! | ||
require 'json_schema' | ||
rescue LoadError | ||
raise LoadError, "You don't have json_schema installed in your application. Please add it to your Gemfile and run bundle install" | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.