-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Bring back assert_serializer #1099
Changes from all commits
7b8c76f
70d726a
d08fac1
e9daf89
3a96cc1
d40b30e
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,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 | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module ActiveModelSerializers | ||
module Test | ||
autoload :Serializer, 'active_model_serializers/test/serializer' | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -0,0 +1,73 @@ | ||||
require 'test_helper' | ||||
require 'rails-controller-testing' if Rails::VERSION::MAJOR >= 5 | ||||
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. What's in here that needed 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. This test uses, this test was based on the original codebase of the test helper. 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. @maurogeorge that's kind of hilarious because it was removed from rails due to it being too intimate a test rails/rails#18950 Do you have a link to the file you're basing this on? Would be nice to see. 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. @bf4 Yeah I know about the Rails decision removing this test helpers. This is the last version of the file active_model_serializers/test/integration/action_controller/serialization_test_case_test.rb Line 67 in 610aeb2
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, but we could subscribe to our own notifications here, right? 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 can look at that in a followup PR if you'd prefer. I think that'd be nicer at this point :) 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. |
||||
|
||||
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<p>Hello.</p> |
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.
So, people using RSpec would need to define
assert(expected, actual)
and any library not usingActionController::TestCase
would also need to includeActiveModelSerializers::Test::Serializer
(I forget if RSpec-Rails uses this)something like:
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.
Thanks for the review.
I don't think we need to care with RSpec and other libs at the moment, Action Mailer uses Minitest methods and Active Job too.
I think we can follow the same rationale, we are providing Minitest test helpers.
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.
Yeah, I know. :)