Bring back assert_serializer for controller testing

The `assert_serializer` test helper was added in 0.9.0.apha1[1],
and was not included in 0.10.

This patch brings back the `assert_serializer` test helper. This is the last
revision[2] that has the helper. The original helper was used as base.

[1]: https://github.com/rails-api/active_model_serializers/pull/596
[2]: 610aeb2e92

- Create the AssertSerializer

- Use the Test namespace

- Make the tests pass on the Rails master
  - Rails 5 does not include `assert_template` but we need this on the tests of
the helper.
  - This add the `rails-controller-testing` to keep support on `assert_template`.

- Only load test helpers in the test environment
This commit is contained in:
Mauro George 2015-08-29 12:37:24 -03:00 committed by Benjamin Fleischer
parent d448481b6b
commit c0b99c980c
10 changed files with 238 additions and 0 deletions

View File

@ -45,6 +45,7 @@ Features:
CollectionSerializer for clarity, add ActiveModelSerializers.config.collection_serializer (@bf4)
- [#1295](https://github.com/rails-api/active_model_serializers/pull/1295) Add config `serializer_lookup_enabled` that,
when disabled, requires serializers to explicitly specified. (@trek)
- [#1099](https://github.com/rails-api/active_model_serializers/pull/1099) Adds `assert_serializer` test helper (@maurogeorge)
Fixes:
- [#1239](https://github.com/rails-api/active_model_serializers/pull/1239) Fix duplicates in JSON API compound documents (@beauby)

View File

@ -12,6 +12,7 @@ version = ENV['RAILS_VERSION'] || '4.2'
if version == 'master'
gem 'rack', github: 'rack/rack'
gem 'arel', github: 'rails/arel'
gem 'rails-controller-testing', github: 'rails/rails-controller-testing'
git 'https://github.com/rails/rails.git' do
gem 'railties'
gem 'activesupport'

View File

@ -22,6 +22,7 @@ This is the documentation of ActiveModelSerializers, it's focused on the **0.10.
- [How to add root key](howto/add_root_key.md)
- [How to add pagination links](howto/add_pagination_links.md)
- [Using ActiveModelSerializers Outside Of Controllers](howto/outside_controller_use.md)
- [Testing ActiveModelSerializers](howto/test.md)
## Integrations

29
docs/howto/test.md Normal file
View File

@ -0,0 +1,29 @@
# How to test
## Test helpers
ActiveModelSerializers provides a `assert_serializer` method to be used on your controller tests to
assert that a specific serializer was used.
```ruby
class PostsControllerTest < ActionController::TestCase
test "should render post serializer" do
get :index
assert_serializer "PostSerializer"
# # return a custom error message
# assert_serializer "PostSerializer", "PostSerializer not rendered"
#
# # assert that the instance of PostSerializer was rendered
# assert_serializer PostSerializer
#
# # assert that the "PostSerializer" serializer was rendered
# assert_serializer :post_serializer
#
# # assert that the rendered serializer starts with "Post"
# assert_serializer %r{\APost.+\Z}
#
# # assert that no serializer was rendered
# assert_serializer nil
end
end
```

View File

@ -19,5 +19,9 @@ module ActiveModel
app.load_generators
require 'generators/serializer/resource_override'
end
if Rails.env.test?
ActionController::TestCase.send(:include, ActiveModelSerializers::Test::Serializer)
end
end
end

View File

@ -14,6 +14,7 @@ module ActiveModelSerializers
autoload :Callbacks
autoload :Deserialization
autoload :Logging
autoload :Test
end
require 'active_model/serializer'

View File

@ -0,0 +1,5 @@
module ActiveModelSerializers
module Test
autoload :Serializer, 'active_model_serializers/test/serializer'
end
end

View File

@ -0,0 +1,122 @@
module ActiveModelSerializers
module Test
module Serializer
extend ActiveSupport::Concern
included do
setup :setup_serialization_subscriptions
end
# Asserts that the request was rendered with the appropriate serializers.
#
# # assert that the "PostSerializer" serializer was rendered
# assert_serializer "PostSerializer"
#
# # return a custom error message
# assert_serializer "PostSerializer", "PostSerializer not rendered"
#
# # assert that the instance of PostSerializer was rendered
# assert_serializer PostSerializer
#
# # assert that the "PostSerializer" serializer was rendered
# assert_serializer :post_serializer
#
# # assert that the rendered serializer starts with "Post"
# assert_serializer %r{\APost.+\Z}
#
# # assert that no serializer was rendered
# assert_serializer nil
#
def assert_serializer(expectation, message = nil)
@assert_serializer.expectation = expectation
@assert_serializer.message = message
@assert_serializer.response = response
assert(@assert_serializer.matches?, @assert_serializer.message)
end
class AssertSerializer
attr_reader :serializers, :message
attr_accessor :response, :expectation
def initialize
@serializers = []
end
def message=(message)
@message = message || "expecting <#{expectation.inspect}> but rendering with <#{serializers}>"
end
def matches?
# Force body to be read in case the template is being streamed.
response.body
case expectation
when a_serializer?
matches_class?
when Symbol
matches_symbol?
when String
matches_string?
when Regexp
matches_regexp?
when NilClass
matches_nil?
else
fail ArgumentError, 'assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil'
end
end
def subscribe
ActiveSupport::Notifications.subscribe(event_name) do |_name, _start, _finish, _id, payload|
serializer = payload[:serializer].name
serializers << serializer
end
end
def unsubscribe
ActiveSupport::Notifications.unsubscribe(event_name)
end
private
def matches_class?
serializers.include?(expectation.name)
end
def matches_symbol?
camelize_expectation = expectation.to_s.camelize
serializers.include?(camelize_expectation)
end
def matches_string?
!expectation.empty? && serializers.include?(expectation)
end
def matches_regexp?
serializers.any? do |serializer|
serializer.match(expectation)
end
end
def matches_nil?
serializers.blank?
end
def a_serializer?
->(exp) { exp.is_a?(Class) && exp < ActiveModel::Serializer }
end
def event_name
'render.active_model_serializers'
end
end
private
def setup_serialization_subscriptions
@assert_serializer = AssertSerializer.new
@assert_serializer.subscribe
end
end
end
end

View File

@ -0,0 +1,73 @@
require 'test_helper'
require 'rails-controller-testing' if Rails::VERSION::MAJOR >= 5
module ActiveModelSerializers
module Test
class SerializerTest < ActionController::TestCase
include ActiveModelSerializers::Test::Serializer
class MyController < ActionController::Base
def render_using_serializer
render json: Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
end
def render_text
render text: 'ok'
end
def render_template
prepend_view_path './test/fixtures'
render template: 'template'
end
end
tests MyController
def test_supports_specifying_serializers_with_a_serializer_class
get :render_using_serializer
assert_serializer ProfileSerializer
end
def test_supports_specifying_serializers_with_a_regexp
get :render_using_serializer
assert_serializer(/\AProfile.+\Z/)
end
def test_supports_specifying_serializers_with_a_string
get :render_using_serializer
assert_serializer 'ProfileSerializer'
end
def test_supports_specifying_serializers_with_a_symbol
get :render_using_serializer
assert_serializer :profile_serializer
end
def test_supports_specifying_serializers_with_a_nil
get :render_text
assert_serializer nil
end
def test_raises_descriptive_error_message_when_serializer_was_not_rendered
get :render_using_serializer
e = assert_raise ActiveSupport::TestCase::Assertion do
assert_serializer 'PostSerializer'
end
assert_match 'expecting <"PostSerializer"> but rendering with <["ProfileSerializer"]>', e.message
end
def test_raises_argument_error_when_asserting_with_invalid_object
get :render_using_serializer
e = assert_raise ArgumentError do
assert_serializer Hash
end
assert_match 'assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil', e.message
end
def test_does_not_overwrite_notification_subscriptions
get :render_template
assert_template 'template'
end
end
end
end

1
test/fixtures/template.html.erb vendored Normal file
View File

@ -0,0 +1 @@
<p>Hello.</p>