2020-09-01 05:10:28 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module NextFoundInstanceOf
|
|
|
|
ERROR_MESSAGE = 'NextFoundInstanceOf mock helpers can only be used with ActiveRecord targets'
|
|
|
|
|
|
|
|
def expect_next_found_instance_of(klass)
|
|
|
|
check_if_active_record!(klass)
|
|
|
|
|
2021-02-03 04:09:07 -05:00
|
|
|
stub_allocate(expect(klass), klass) do |expectation|
|
2020-09-01 05:10:28 -04:00
|
|
|
yield(expectation)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def allow_next_found_instance_of(klass)
|
|
|
|
check_if_active_record!(klass)
|
|
|
|
|
2021-02-03 04:09:07 -05:00
|
|
|
stub_allocate(allow(klass), klass) do |allowance|
|
2020-09-01 05:10:28 -04:00
|
|
|
yield(allowance)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def check_if_active_record!(klass)
|
2021-05-04 11:10:36 -04:00
|
|
|
raise ArgumentError, ERROR_MESSAGE unless klass < ActiveRecord::Base
|
2020-09-01 05:10:28 -04:00
|
|
|
end
|
|
|
|
|
2021-02-03 04:09:07 -05:00
|
|
|
def stub_allocate(target, klass)
|
2020-09-01 05:10:28 -04:00
|
|
|
target.to receive(:allocate).and_wrap_original do |method|
|
2021-02-03 04:09:07 -05:00
|
|
|
method.call.tap do |allocation|
|
|
|
|
# ActiveRecord::Core.allocate returns a frozen object:
|
|
|
|
# https://github.com/rails/rails/blob/291a3d2ef29a3842d1156ada7526f4ee60dd2b59/activerecord/lib/active_record/core.rb#L620
|
|
|
|
# It's unexpected behavior and probably a bug in Rails
|
|
|
|
# Let's work it around by setting the attributes to default to unfreeze the object for now
|
|
|
|
allocation.instance_variable_set(:@attributes, klass._default_attributes)
|
|
|
|
|
|
|
|
yield(allocation)
|
|
|
|
end
|
2020-09-01 05:10:28 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|