diaspora/spec/support/serializer_matchers.rb
cmrd Senya c6ed850a85
Memory usage optimization for archive export
- Removed posts and non contacts from other's data
- Collections are exported in batches to lower memory footprint
- In base exporters create User object instead of keeping instance because it caches all associations

closes #7627
2017-09-26 04:07:18 +02:00

87 lines
3.5 KiB
Ruby

# frozen_string_literal: true
# This file contains custom RSpec matchers for AMS.
# NOTE: It was developed for AMS v0.9 and the API might be changed in future, so that should be examined when moving
# between stable versions of AMS (e.g. 0.9 to 0.10, or 0.9 to a possible 1.0).
# This is a matcher that tests a ActiveModel Serializer derivatives to run a serializer for
# an association with expected properties and data.
#
# This matcher is expected to be used in unit testing of ActiveModel Serializer derivatives.
#
# It is mostly a wrapper around RSpec::Mocks::Matchers::Receive matcher with expectations based on
# ActiveModel::Serializer internal API knowledge.
# NOTE: this matcher uses knowledge of AMS internals
RSpec::Matchers.define :serialize_association do |association_name|
match do |root_serializer_class|
association = fetch_association(root_serializer_class, association_name)
@serializer_from_options = association.serializer_from_options
execute_receive_matcher_with(association)
end
# Sets expectation for a specific serializer class to be used for has_one association serialization
chain :with_serializer, :association_serializer_class
# Sets expectation for a specific serializer class to be user for has_many association serialization
chain :with_each_serializer, :each_serializer_class
# Sets expectation for actual data to be passed to the serializer of the association
chain :with_object, :association_object
alias_method :with_objects, :with_object
private
# subject is what comes from the expect method argument in usual notation.
# So this method is equivalent of calling `expect(subject).to receive(:build_serializer)` but valid within a custom
# RSpec matcher's match method.
def execute_receive_matcher_with(subject)
receive_matcher.matches?(subject)
end
def receive_matcher
receive(:build_serializer).and_wrap_original do |original, object, options, &block|
with_object_expectation(object)
original.call(object, options, &block).tap do |serializer|
expect(serializer).to be_an_instance_of(serializer_class) unless serializer_class.nil?
expect(serializer).to serialize_each_with(each_serializer_class) unless each_serializer_class.nil?
end
end
end
def with_object_expectation(object)
if association_object.is_a?(Array)
if serializer_class == FlatMapArraySerializer
expect(object.flat_map(&:to_a)).to match_array(association_object)
else
expect(object).to match_array(association_object)
end
elsif !association_object.nil?
expect(object).to eq(association_object)
end
end
def fetch_association(serializer_class, association_name)
serializer_class._associations[association_name]
end
def serializer_class
@serializer_class ||= pick_serializer_class
end
def pick_serializer_class
return association_serializer_class unless association_serializer_class.nil?
return @serializer_from_options unless @serializer_from_options.nil?
return ActiveModel::ArraySerializer unless each_serializer_class.nil?
end
end
# This serializer tests that ActiveModel::ArraySerializer uses specific serializer for each member object of the array.
# We could also set a mock expectation on each serializer, but it maybe overly complicated for our present
# requirements.
# NOTE: this matcher uses knowledge of AMS internals
RSpec::Matchers.define :serialize_each_with do |expected|
match do |actual|
actual.is_a?(ActiveModel::ArraySerializer) && actual.instance_variable_get("@each_serializer") == expected
end
end