Skip to content

Test::Unit assert_serializer implemented #596

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 22, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions lib/action_controller/serialization_test_case.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
module ActionController
module SerializationAssertions
extend ActiveSupport::Concern

included do
setup :setup_subscriptions
teardown :teardown_subscriptions
end

def setup_subscriptions
@serializers = Hash.new(0)

ActiveSupport::Notifications.subscribe("!serialize.active_model_serializers") do |name, start, finish, id, payload|
serializer = payload[:serializer]
@serializers[serializer] += 1
end
end

def teardown_subscriptions
ActiveSupport::Notifications.unsubscribe("!serialize.active_model_serializers")
end

def process(*args)
@serializers = Hash.new(0)
super
end

# Asserts that the request was rendered with the appropriate serializers.
#
# # assert that the "PostSerializer" serializer was rendered
# assert_serializer "PostSerializer"
#
# # 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(options = {}, message = nil)
# Force body to be read in case the template is being streamed.
response.body

rendered = @serializers
msg = message || "expecting <#{options.inspect}> but rendering with <#{rendered.keys}>"

matches_serializer = case options
when lambda { |options| options.kind_of?(Class) && options < ActiveModel::Serializer }
rendered.any? do |serializer, count|
options.name == serializer
end
when Symbol
options = options.to_s.camelize
rendered.any? do |serializer, count|
serializer == options
end
when String
!options.empty? && rendered.any? do |serializer, count|
serializer == options
end
when Regexp
rendered.any? do |serializer, count|
serializer.match(options)
end
when NilClass
rendered.blank?
else
raise ArgumentError, "assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil"
end
assert matches_serializer, msg
end
end
end
5 changes: 5 additions & 0 deletions lib/active_model/array_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,10 @@ def embedded_in_root_associations
end
end
end

private
def instrumentation_keys
[:object, :scope, :root, :meta_key, :meta, :each_serializer, :resource_name, :key_format]
end
end
end
13 changes: 10 additions & 3 deletions lib/active_model/default_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,18 @@ def initialize(object, options={})
end

def as_json(options={})
return [] if @object.nil? && @wrap_in_array
hash = @object.as_json
@wrap_in_array ? [hash] : hash
instrument('!serialize') do
return [] if @object.nil? && @wrap_in_array
hash = @object.as_json
@wrap_in_array ? [hash] : hash
end
end
alias serializable_hash as_json
alias serializable_object as_json

private
def instrumentation_keys
[:object, :wrap_in_array]
end
end
end
27 changes: 21 additions & 6 deletions lib/active_model/serializable.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
module ActiveModel
module Serializable
def as_json(options={})
if root = options.fetch(:root, json_key)
hash = { root => serializable_object }
hash.merge!(serializable_data)
hash
else
serializable_object
instrument('!serialize') do
if root = options.fetch(:root, json_key)
hash = { root => serializable_object }
hash.merge!(serializable_data)
hash
else
serializable_object
end
end
end

Expand All @@ -21,5 +23,18 @@ def serializable_data
def embedded_in_root_associations
{}
end

private
def instrument(action, &block)
payload = instrumentation_keys.inject({ serializer: self.class.name }) do |payload, key|
payload[:payload] = self.instance_variable_get(:"@#{key}")
payload
end
ActiveSupport::Notifications.instrument("#{action}.active_model_serializers", payload, &block)
end

def instrumentation_keys
[:object, :scope, :root, :meta_key, :meta, :wrap_in_array, :only, :except, :key_format]
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 @@ -7,10 +7,12 @@
begin
require 'action_controller'
require 'action_controller/serialization'
require 'action_controller/serialization_test_case'

ActiveSupport.on_load(:after_initialize) do
if ::ActionController::Serialization.enabled
ActionController::Base.send(:include, ::ActionController::Serialization)
ActionController::TestCase.send(:include, ::ActionController::SerializationAssertions)
end
end
rescue LoadError
Expand Down
61 changes: 61 additions & 0 deletions test/integration/action_controller/serialization_test_case_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
require 'test_helper'

module ActionController
module SerializationsAssertions
class RenderSerializerTest < 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
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 %r{\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
end
end
end