-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Bring back assert_serializer for controller testing #1390
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
Changes from all commits
c0b99c9
37a6d2b
ef09c90
f594314
a43cff4
28f314a
e60937b
9779185
f5e2b99
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# 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" | ||
end | ||
end | ||
``` | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Outside the scope of this PR, but something link #1011 (comment) should probably be included here as well for unit testing serializers themselves There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
See [ActiveModelSerializers::Test::Serializer](../../lib/active_model_serializers/test/serializer.rb) | ||
for more examples and documentation. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module ActiveModelSerializers | ||
module Test | ||
extend ActiveSupport::Autoload | ||
autoload :Serializer | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
require 'set' | ||
module ActiveModelSerializers | ||
module Test | ||
module Serializer | ||
extend ActiveSupport::Concern | ||
|
||
included do | ||
setup :setup_serialization_subscriptions | ||
teardown :teardown_serialization_subscriptions | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We really need this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it needs a test. It just unsubscribes the subscriber created in the test... See more in the commit d9eefdb I can try to show what may break without it, but given that the teardown is copied from rails, and I understand the behavior with and without... B mobile phone
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ref original comment 11fda59#commitcomment-15145827 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I am good with that. |
||
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 = Set.new | ||
@_subscribers = [] | ||
end | ||
|
||
def message=(message) | ||
@message = message || "expecting <#{expectation.inspect}> but rendering with <#{serializers.to_a}>" | ||
end | ||
|
||
def matches? | ||
# Force body to be read in case the template is being streamed. | ||
response.body | ||
|
||
case expectation | ||
when a_serializer? then matches_class? | ||
when Symbol then matches_symbol? | ||
when String then matches_string? | ||
when Regexp then matches_regexp? | ||
when NilClass then matches_nil? | ||
else fail ArgumentError, 'assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil' | ||
end | ||
end | ||
|
||
def subscribe | ||
@_subscribers << ActiveSupport::Notifications.subscribe(event_name) do |_name, _start, _finish, _id, payload| | ||
serializer = payload[:serializer].name | ||
serializers << serializer | ||
end | ||
end | ||
|
||
def unsubscribe | ||
@_subscribers.each do |subscriber| | ||
ActiveSupport::Notifications.unsubscribe(subscriber) | ||
end | ||
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.empty? | ||
end | ||
|
||
def a_serializer? | ||
->(exp) { exp.is_a?(Class) && exp < ActiveModel::Serializer } | ||
end | ||
|
||
def event_name | ||
::ActiveModelSerializers::Logging::RENDER_EVENT | ||
end | ||
end | ||
|
||
private | ||
|
||
def setup_serialization_subscriptions | ||
@assert_serializer = AssertSerializer.new | ||
@assert_serializer.subscribe | ||
end | ||
|
||
def teardown_serialization_subscriptions | ||
@assert_serializer.unsubscribe | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
require 'test_helper' | ||
|
||
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 | ||
|
||
# For Rails4.0 | ||
def render_some_text | ||
Rails.version > '4.1' ? render(plain: 'ok') : render(text: 'ok') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. womp womp (Really for Rails 5, but it works on 4.1+) |
||
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_some_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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😍