Skip to content

Commit

Permalink
Bring back assert_serializer
Browse files Browse the repository at this point in the history
The `assert_serializer` test helper was removed at some point.

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

[1]: https://github.com/rails-api/active_model_serializers/tree/610aeb2e9297fa31b8d561f0be9a4597f0258f8c
  • Loading branch information
maurogeorge committed Sep 30, 2015
1 parent 1f08865 commit fde7f5d
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Features:
- [#1158](https://github.com/rails-api/active_model_serializers/pull/1158) Add support for wildcards in `include` option (@beauby)
- [#1127](https://github.com/rails-api/active_model_serializers/pull/1127) Add support for nested
associations for JSON and Attributes adapters via the `include` option (@NullVoxPopuli, @beauby).
- [#1099](https://github.com/rails-api/active_model_serializers/pull/1099) Adds `assert_serializer` test helper (@maurogeorge)

Fixes:

Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This is the documentation of AMS, it's focused on the **0.10.x version.**
- [How to add root key](howto/add_root_key.md)
- [How to add pagination links](howto/add_pagination_links.md)
- [Using AMS Outside Of Controllers](howto/outside_controller_use.md)
- [Testing AMS](howto/test.md)

## Getting Help

Expand Down
29 changes: 29 additions & 0 deletions docs/howto/test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# How to test

## Test helpers

AMS 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
```
8 changes: 8 additions & 0 deletions lib/active_model/serializable_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ def initialize(resource, options = {})
@resource = resource
@adapter_opts, @serializer_opts =
options.partition { |k, _| ADAPTER_OPTION_KEYS.include? k }.map { |h| Hash[h] }
notify_active_support
end

delegate :serializable_hash, :as_json, :to_json, to: :adapter
Expand Down Expand Up @@ -61,6 +62,13 @@ def serializer?
use_adapter? && !!(serializer)
end

def notify_active_support
return unless serializer?
event_name = 'serialize.active_model_serializers'
payload = { serializer: serializer.name }
ActiveSupport::Notifications.instrument(event_name, payload)
end

private

ActiveModelSerializers.silence_warnings do
Expand Down
104 changes: 104 additions & 0 deletions lib/active_model/serializer/assertions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
module ActiveModel
class Serializer
module Assertions
extend ActiveSupport::Concern

included do
setup :setup_serialization_subscriptions
teardown :teardown_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)
# Force body to be read in case the template is being streamed.
response.body

msg = message || "expecting <#{expectation.inspect}> but rendering with <#{serializers}>"

matches_serializer = case expectation
when a_serializer?
matches_class?(expectation)
when Symbol
matches_symbol?(expectation)
when String
matches_string?(expectation)
when Regexp
matches_regexp?(expectation)
when NilClass
matches_nil?
else
fail ArgumentError, 'assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil'
end
assert(matches_serializer, msg)
end

private

ActiveModelSerializers.silence_warnings do
attr_reader :serializers, :expectation
end

def setup_serialization_subscriptions
@serializers = []
ActiveSupport::Notifications.subscribe(event_name) do |_name, _start, _finish, _id, payload|
serializer = payload[:serializer]
serializers << serializer
end
end

def teardown_serialization_subscriptions
ActiveSupport::Notifications.unsubscribe(event_name)
end

def event_name
'serialize.active_model_serializers'
end

def matches_class?(expectation)
serializers.include?(expectation.name)
end

def matches_symbol?(expectation)
expectation = expectation.to_s.camelize
serializers.include?(expectation)
end

def matches_string?(expectation)
!expectation.empty? && serializers.include?(expectation)
end

def matches_regexp?(expectation)
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
end
end
end
2 changes: 2 additions & 0 deletions lib/active_model_serializers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ 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
include ::ActionController::Serialization
ActionDispatch::Reloader.to_prepare do
ActiveModel::Serializer.serializers_cache.clear
end
ActionController::TestCase.send(:include, ActiveModel::Serializer::Assertions)
end

require 'active_model/serializer/railtie'
70 changes: 70 additions & 0 deletions test/assertions_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
require 'test_helper'

module ActiveModel
class Serializer
class AssertionsTest < ActionController::TestCase
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 change: 1 addition & 0 deletions test/fixtures/template.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>Hello.</p>

0 comments on commit fde7f5d

Please sign in to comment.