From 58cf46a22d5eb723a2f01c7aac24c418c539e823 Mon Sep 17 00:00:00 2001 From: Mauro George Date: Sat, 29 Aug 2015 12:37:24 -0300 Subject: [PATCH] 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 --- active_model_serializers.gemspec | 2 + lib/active_model/serializer/assertions.rb | 16 +++++++ lib/active_model/serializer/configuration.rb | 1 + lib/active_model_serializers.rb | 2 + test/assertions_test.rb | 46 +++++++++++++++++++ .../serializer/assertions_test/my/index.json | 6 +++ .../serializer/assertions_test/my/index.json | 6 +++ .../serializer/assertions_test/my/show.json | 5 ++ test/support/schemas/custom/show.json | 6 +++ 9 files changed, 90 insertions(+) create mode 100644 lib/active_model/serializer/assertions.rb create mode 100644 test/assertions_test.rb create mode 100644 test/support/custom_schemas/active_model/serializer/assertions_test/my/index.json create mode 100644 test/support/schemas/active_model/serializer/assertions_test/my/index.json create mode 100644 test/support/schemas/active_model/serializer/assertions_test/my/show.json create mode 100644 test/support/schemas/custom/show.json diff --git a/active_model_serializers.gemspec b/active_model_serializers.gemspec index 1e438e2cb..10703f80c 100644 --- a/active_model_serializers.gemspec +++ b/active_model_serializers.gemspec @@ -41,6 +41,8 @@ Gem::Specification.new do |spec| # 'minitest' # 'thread_safe' + spec.add_runtime_dependency 'json-schema' + # Soft dependency for pagination spec.add_development_dependency 'kaminari', ' ~> 0.16.3' spec.add_development_dependency 'will_paginate', '~> 3.0', '>= 3.0.7' diff --git a/lib/active_model/serializer/assertions.rb b/lib/active_model/serializer/assertions.rb new file mode 100644 index 000000000..773f0c914 --- /dev/null +++ b/lib/active_model/serializer/assertions.rb @@ -0,0 +1,16 @@ +require 'json-schema' + +module ActiveModel + class Serializer + module Assertions + def assert_response_schema(schema_path = nil) + controller_path = response.request.filtered_parameters[:controller] + action = response.request.filtered_parameters[:action] + schema_directory = ActiveModel::Serializer.config.schema_path + schema_path ||= "#{controller_path}/#{action}.json" + schema_full_path = "#{schema_directory}/#{schema_path}" + JSON::Validator.validate!(schema_full_path, response.body, strict: true) + end + end + end +end diff --git a/lib/active_model/serializer/configuration.rb b/lib/active_model/serializer/configuration.rb index 564277801..4b1099ec0 100644 --- a/lib/active_model/serializer/configuration.rb +++ b/lib/active_model/serializer/configuration.rb @@ -10,6 +10,7 @@ module Configuration base.config.array_serializer = ActiveModel::Serializer::ArraySerializer base.config.adapter = :attributes base.config.jsonapi_resource_type = :plural + base.config.schema_path = 'test/support/schemas' end end end diff --git a/lib/active_model_serializers.rb b/lib/active_model_serializers.rb index 355393e55..08d557be7 100644 --- a/lib/active_model_serializers.rb +++ b/lib/active_model_serializers.rb @@ -44,6 +44,7 @@ def silence_warnings require 'active_model/serializer' require 'active_model/serializable_resource' require 'active_model/serializer/version' +require 'active_model/serializer/assertions' require 'action_controller/serialization' ActiveSupport.on_load(:action_controller) do @@ -51,6 +52,7 @@ def silence_warnings ActionDispatch::Reloader.to_prepare do ActiveModel::Serializer.serializers_cache.clear end + ActionController::TestCase.send(:include, ActiveModel::Serializer::Assertions) end require 'active_model/serializer/railtie' diff --git a/test/assertions_test.rb b/test/assertions_test.rb new file mode 100644 index 000000000..fb856282a --- /dev/null +++ b/test/assertions_test.rb @@ -0,0 +1,46 @@ +require 'test_helper' + +module ActiveModel + class Serializer + class AssertionsTest < ActionController::TestCase + class MyController < ActionController::Base + def index + render json: Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1') + end + + def show + index + end + end + + tests MyController + + def test_that_assert_with_a_valid_schema + get :index + assert_response_schema + end + + def test_that_raises_a_json_schema_with_a_invalid_schema + get :show + assert_raises JSON::Schema::ValidationError do + assert_response_schema + end + end + + def test_that_assert_with_a_custom_schema + get :show + assert_response_schema('custom/show.json') + end + + def test_that_assert_with_a_custom_schema_directory + original_schema_path = ActiveModel::Serializer.config.schema_path + ActiveModel::Serializer.config.schema_path = 'test/support/custom_schemas' + + get :index + assert_response_schema + + ActiveModel::Serializer.config.schema_path = original_schema_path + end + end + end +end diff --git a/test/support/custom_schemas/active_model/serializer/assertions_test/my/index.json b/test/support/custom_schemas/active_model/serializer/assertions_test/my/index.json new file mode 100644 index 000000000..9474c509b --- /dev/null +++ b/test/support/custom_schemas/active_model/serializer/assertions_test/my/index.json @@ -0,0 +1,6 @@ +{ + "properties": { + "name" : { "type" : "string" }, + "description" : { "type" : "string" } + } +} diff --git a/test/support/schemas/active_model/serializer/assertions_test/my/index.json b/test/support/schemas/active_model/serializer/assertions_test/my/index.json new file mode 100644 index 000000000..9474c509b --- /dev/null +++ b/test/support/schemas/active_model/serializer/assertions_test/my/index.json @@ -0,0 +1,6 @@ +{ + "properties": { + "name" : { "type" : "string" }, + "description" : { "type" : "string" } + } +} diff --git a/test/support/schemas/active_model/serializer/assertions_test/my/show.json b/test/support/schemas/active_model/serializer/assertions_test/my/show.json new file mode 100644 index 000000000..269fcda8a --- /dev/null +++ b/test/support/schemas/active_model/serializer/assertions_test/my/show.json @@ -0,0 +1,5 @@ +{ + "properties": { + "name" : { "type" : "string" } + } +} diff --git a/test/support/schemas/custom/show.json b/test/support/schemas/custom/show.json new file mode 100644 index 000000000..9474c509b --- /dev/null +++ b/test/support/schemas/custom/show.json @@ -0,0 +1,6 @@ +{ + "properties": { + "name" : { "type" : "string" }, + "description" : { "type" : "string" } + } +}