Skip to content

Commit e175f14

Browse files
maurogeorgebf4
authored andcommitted
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]: rails-api#596 [2]: https://github.com/rails-api/active_model_serializers/tree/610aeb2e9297fa31b8d561f0be9a4597f0258f8c - 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
1 parent d8b2b94 commit e175f14

File tree

10 files changed

+238
-0
lines changed

10 files changed

+238
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Features:
2828
CollectionSerializer for clarity, add ActiveModelSerializers.config.collection_serializer (@bf4)
2929
- [#1295](https://github.com/rails-api/active_model_serializers/pull/1295) Add config `serializer_lookup_enabled` that,
3030
when disabled, requires serializers to explicitly specified. (@trek)
31+
- [#1099](https://github.com/rails-api/active_model_serializers/pull/1099) Adds `assert_serializer` test helper (@maurogeorge)
3132

3233
Fixes:
3334
- [#1239](https://github.com/rails-api/active_model_serializers/pull/1239) Fix duplicates in JSON API compound documents (@beauby)

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ version = ENV['RAILS_VERSION'] || '4.2'
1212
if version == 'master'
1313
gem 'rack', github: 'rack/rack'
1414
gem 'arel', github: 'rails/arel'
15+
gem 'rails-controller-testing', github: 'rails/rails-controller-testing'
1516
git 'https://github.com/rails/rails.git' do
1617
gem 'railties'
1718
gem 'activesupport'

docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ This is the documentation of ActiveModelSerializers, it's focused on the **0.10.
2222
- [How to add root key](howto/add_root_key.md)
2323
- [How to add pagination links](howto/add_pagination_links.md)
2424
- [Using ActiveModelSerializers Outside Of Controllers](howto/outside_controller_use.md)
25+
- [Testing ActiveModelSerializers](howto/test.md)
2526

2627
## Integrations
2728

docs/howto/test.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# How to test
2+
3+
## Test helpers
4+
5+
ActiveModelSerializers provides a `assert_serializer` method to be used on your controller tests to
6+
assert that a specific serializer was used.
7+
8+
```ruby
9+
class PostsControllerTest < ActionController::TestCase
10+
test "should render post serializer" do
11+
get :index
12+
assert_serializer "PostSerializer"
13+
# # return a custom error message
14+
# assert_serializer "PostSerializer", "PostSerializer not rendered"
15+
#
16+
# # assert that the instance of PostSerializer was rendered
17+
# assert_serializer PostSerializer
18+
#
19+
# # assert that the "PostSerializer" serializer was rendered
20+
# assert_serializer :post_serializer
21+
#
22+
# # assert that the rendered serializer starts with "Post"
23+
# assert_serializer %r{\APost.+\Z}
24+
#
25+
# # assert that no serializer was rendered
26+
# assert_serializer nil
27+
end
28+
end
29+
```

lib/active_model/serializer/railtie.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,9 @@ class Railtie < Rails::Railtie
1919
app.load_generators
2020
require 'generators/serializer/resource_override'
2121
end
22+
23+
if Rails.env.test?
24+
ActionController::TestCase.send(:include, ActiveModelSerializers::Test::Serializer)
25+
end
2226
end
2327
end

lib/active_model_serializers.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ def self.config
1313
autoload :Model
1414
autoload :Callbacks
1515
autoload :Logging
16+
autoload :Test
1617

1718
module_function
1819

lib/active_model_serializers/test.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module ActiveModelSerializers
2+
module Test
3+
autoload :Serializer, 'active_model_serializers/test/serializer'
4+
end
5+
end
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
module ActiveModelSerializers
2+
module Test
3+
module Serializer
4+
extend ActiveSupport::Concern
5+
6+
included do
7+
setup :setup_serialization_subscriptions
8+
end
9+
10+
# Asserts that the request was rendered with the appropriate serializers.
11+
#
12+
# # assert that the "PostSerializer" serializer was rendered
13+
# assert_serializer "PostSerializer"
14+
#
15+
# # return a custom error message
16+
# assert_serializer "PostSerializer", "PostSerializer not rendered"
17+
#
18+
# # assert that the instance of PostSerializer was rendered
19+
# assert_serializer PostSerializer
20+
#
21+
# # assert that the "PostSerializer" serializer was rendered
22+
# assert_serializer :post_serializer
23+
#
24+
# # assert that the rendered serializer starts with "Post"
25+
# assert_serializer %r{\APost.+\Z}
26+
#
27+
# # assert that no serializer was rendered
28+
# assert_serializer nil
29+
#
30+
def assert_serializer(expectation, message = nil)
31+
@assert_serializer.expectation = expectation
32+
@assert_serializer.message = message
33+
@assert_serializer.response = response
34+
assert(@assert_serializer.matches?, @assert_serializer.message)
35+
end
36+
37+
class AssertSerializer
38+
attr_reader :serializers, :message
39+
attr_accessor :response, :expectation
40+
41+
def initialize
42+
@serializers = []
43+
end
44+
45+
def message=(message)
46+
@message = message || "expecting <#{expectation.inspect}> but rendering with <#{serializers}>"
47+
end
48+
49+
def matches?
50+
# Force body to be read in case the template is being streamed.
51+
response.body
52+
53+
case expectation
54+
when a_serializer?
55+
matches_class?
56+
when Symbol
57+
matches_symbol?
58+
when String
59+
matches_string?
60+
when Regexp
61+
matches_regexp?
62+
when NilClass
63+
matches_nil?
64+
else
65+
fail ArgumentError, 'assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil'
66+
end
67+
end
68+
69+
def subscribe
70+
ActiveSupport::Notifications.subscribe(event_name) do |_name, _start, _finish, _id, payload|
71+
serializer = payload[:serializer].name
72+
serializers << serializer
73+
end
74+
end
75+
76+
def unsubscribe
77+
ActiveSupport::Notifications.unsubscribe(event_name)
78+
end
79+
80+
private
81+
82+
def matches_class?
83+
serializers.include?(expectation.name)
84+
end
85+
86+
def matches_symbol?
87+
camelize_expectation = expectation.to_s.camelize
88+
serializers.include?(camelize_expectation)
89+
end
90+
91+
def matches_string?
92+
!expectation.empty? && serializers.include?(expectation)
93+
end
94+
95+
def matches_regexp?
96+
serializers.any? do |serializer|
97+
serializer.match(expectation)
98+
end
99+
end
100+
101+
def matches_nil?
102+
serializers.blank?
103+
end
104+
105+
def a_serializer?
106+
->(exp) { exp.is_a?(Class) && exp < ActiveModel::Serializer }
107+
end
108+
109+
def event_name
110+
'render.active_model_serializers'
111+
end
112+
end
113+
114+
private
115+
116+
def setup_serialization_subscriptions
117+
@assert_serializer = AssertSerializer.new
118+
@assert_serializer.subscribe
119+
end
120+
end
121+
end
122+
end
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
require 'test_helper'
2+
require 'rails-controller-testing' if Rails::VERSION::MAJOR >= 5
3+
4+
module ActiveModelSerializers
5+
module Test
6+
class SerializerTest < ActionController::TestCase
7+
include ActiveModelSerializers::Test::Serializer
8+
9+
class MyController < ActionController::Base
10+
def render_using_serializer
11+
render json: Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
12+
end
13+
14+
def render_text
15+
render text: 'ok'
16+
end
17+
18+
def render_template
19+
prepend_view_path './test/fixtures'
20+
render template: 'template'
21+
end
22+
end
23+
24+
tests MyController
25+
26+
def test_supports_specifying_serializers_with_a_serializer_class
27+
get :render_using_serializer
28+
assert_serializer ProfileSerializer
29+
end
30+
31+
def test_supports_specifying_serializers_with_a_regexp
32+
get :render_using_serializer
33+
assert_serializer(/\AProfile.+\Z/)
34+
end
35+
36+
def test_supports_specifying_serializers_with_a_string
37+
get :render_using_serializer
38+
assert_serializer 'ProfileSerializer'
39+
end
40+
41+
def test_supports_specifying_serializers_with_a_symbol
42+
get :render_using_serializer
43+
assert_serializer :profile_serializer
44+
end
45+
46+
def test_supports_specifying_serializers_with_a_nil
47+
get :render_text
48+
assert_serializer nil
49+
end
50+
51+
def test_raises_descriptive_error_message_when_serializer_was_not_rendered
52+
get :render_using_serializer
53+
e = assert_raise ActiveSupport::TestCase::Assertion do
54+
assert_serializer 'PostSerializer'
55+
end
56+
assert_match 'expecting <"PostSerializer"> but rendering with <["ProfileSerializer"]>', e.message
57+
end
58+
59+
def test_raises_argument_error_when_asserting_with_invalid_object
60+
get :render_using_serializer
61+
e = assert_raise ArgumentError do
62+
assert_serializer Hash
63+
end
64+
assert_match 'assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil', e.message
65+
end
66+
67+
def test_does_not_overwrite_notification_subscriptions
68+
get :render_template
69+
assert_template 'template'
70+
end
71+
end
72+
end
73+
end

test/fixtures/template.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<p>Hello.</p>

0 commit comments

Comments
 (0)