1
0
Fork 0
mirror of https://github.com/thoughtbot/shoulda-matchers.git synced 2022-11-09 12:01:38 -05:00
thoughtbot--shoulda-matchers/spec/support/unit/change_value.rb

112 lines
2 KiB
Ruby
Raw Permalink Normal View History

Extract classes for defining models in tests The main driver behind this commit is to provide a programmatic way to define models in tests. We already have ways of doing this, of course, with `define_model` and `define_active_model_class`, but these methods are very low-level, and in writing tests we have historically made our own methods inside of test files to define full and complete models. So we have this common pattern of defining a model with a validation, and that's repeated across many different files. What we would like to do, right now, is extract some commonly used assertions to a shared example group. These assertions need to define models inside of the tests, but the issue is that sometimes the models are ActiveRecord models, and sometimes they are ActiveModel models, and when the shared example group is used within a test file, we need a way to choose the strategy we'd like to use at runtime. Since the way we currently define models is via methods, we can't really provide a strategy very easily. Also, if we need to customize how those models are defined (say, the attribute needs to be a has-many association instead of a normal attribute) then the methods only go so far in providing us that level of customization before things get really complicated. So, to help us with this, this commit takes the pattern of model-plus-validation previously mentioned and places it in multiple classes. Note that this is also a precursor to a later commit in which we introduce `ignoring_interference_by_writer` across the board. The way we will do this is by adding a shared example group that then uses these model creation classes internally to build objects instead of relying upon methods that the outer example group -- to which the shared example group is being mixed into -- provides.
2015-12-23 18:10:40 -05:00
module UnitTests
class ChangeValue
def self.call(column_type, value, value_changer)
new(column_type, value, value_changer).call
end
def initialize(column_type, value, value_changer)
@column_type = column_type
@value = value
@value_changer = value_changer
end
def call
if value_changer.is_a?(Proc)
value_changer.call(value)
elsif respond_to?(value_changer, true)
send(value_changer)
else
value.public_send(value_changer)
end
end
protected
attr_reader :column_type, :value, :value_changer
private
def previous_value
if value.is_a?(String)
value[0..-2] + (value[-1].ord - 1).chr
else
value - 1
end
end
def next_value
if value.is_a?(Array)
value + [value.first.class.new]
elsif value.respond_to?(:next)
value.next
else
value + 1
end
end
def next_next_value
change_value(change_value(value, :next_value), :next_value)
end
def next_value_or_numeric_value
if value
change_value(value, :next_value)
else
change_value(value, :numeric_value)
end
end
def next_value_or_non_numeric_value
if value
change_value(value, :next_value)
else
change_value(value, :non_numeric_value)
end
end
def never_falsy
value || dummy_value_for_column
end
def truthy_or_numeric
value || 1
end
def never_blank
value.presence || dummy_value_for_column
end
def nil_to_blank
value || ''
end
def always_nil
nil
end
def add_character
"#{value}a"
Extract classes for defining models in tests The main driver behind this commit is to provide a programmatic way to define models in tests. We already have ways of doing this, of course, with `define_model` and `define_active_model_class`, but these methods are very low-level, and in writing tests we have historically made our own methods inside of test files to define full and complete models. So we have this common pattern of defining a model with a validation, and that's repeated across many different files. What we would like to do, right now, is extract some commonly used assertions to a shared example group. These assertions need to define models inside of the tests, but the issue is that sometimes the models are ActiveRecord models, and sometimes they are ActiveModel models, and when the shared example group is used within a test file, we need a way to choose the strategy we'd like to use at runtime. Since the way we currently define models is via methods, we can't really provide a strategy very easily. Also, if we need to customize how those models are defined (say, the attribute needs to be a has-many association instead of a normal attribute) then the methods only go so far in providing us that level of customization before things get really complicated. So, to help us with this, this commit takes the pattern of model-plus-validation previously mentioned and places it in multiple classes. Note that this is also a precursor to a later commit in which we introduce `ignoring_interference_by_writer` across the board. The way we will do this is by adding a shared example group that then uses these model creation classes internally to build objects instead of relying upon methods that the outer example group -- to which the shared example group is being mixed into -- provides.
2015-12-23 18:10:40 -05:00
end
def remove_character
value.chop
end
def numeric_value
'1'
end
def non_numeric_value
'a'
end
def change_value(value, value_changer)
self.class.call(column_type, value, value_changer)
end
def dummy_value_for_column
Shoulda::Matchers::Util.dummy_value_for(column_type)
end
end
end