Improve failure message for enum matcher

When the enum matcher fails, the message it generates is not as clear as
it could be, particularly around showing the expected enum values versus
the actual ones. This commit expands the failure message to be more
helpful (and ensures that the description of the matcher is kept
compact).
This commit is contained in:
Elliot Winkler 2019-06-09 01:57:09 -06:00
parent 47e21951b6
commit 47f47d0d7a
2 changed files with 390 additions and 165 deletions

View File

@ -144,33 +144,24 @@ module Shoulda
end end
def description def description
description = "define :#{attribute_name} as an enum, backed by " description = "#{simple_description} backed by "
description << Shoulda::Matchers::Util.a_or_an(expected_column_type) description << Shoulda::Matchers::Util.a_or_an(expected_column_type)
if options[:expected_prefix] if expected_enum_values.any?
description << ', using a prefix of ' description << ' with values '
description << "#{options[:expected_prefix].inspect}"
end
if options[:expected_suffix]
if options[:expected_prefix]
description << ' and'
else
description << ', using'
end
description << ' a suffix of '
description << "#{options[:expected_suffix].inspect}"
end
if presented_expected_enum_values.any?
description << ', with possible values '
description << Shoulda::Matchers::Util.inspect_value( description << Shoulda::Matchers::Util.inspect_value(
presented_expected_enum_values, expected_enum_values,
) )
end end
if options[:prefix]
description << ", prefix: #{options[:prefix].inspect}"
end
if options[:suffix]
description << ", suffix: #{options[:suffix].inspect}"
end
description description
end end
@ -187,13 +178,13 @@ module Shoulda
with_values(expected_enum_values) with_values(expected_enum_values)
end end
def with_prefix(expected_prefix = attribute_name) def with_prefix(expected_prefix = true)
options[:expected_prefix] = expected_prefix options[:prefix] = expected_prefix
self self
end end
def with_suffix(expected_suffix = attribute_name) def with_suffix(expected_suffix = true)
options[:expected_suffix] = expected_suffix options[:suffix] = expected_suffix
self self
end end
@ -212,13 +203,14 @@ module Shoulda
end end
def failure_message def failure_message
message = "Expected #{model} to #{expectation}" message =
if enum_defined?
"Expected #{model} to #{expectation}. "
else
"Expected #{model} to #{expectation}, but "
end
if failure_reason message << failure_message_continuation + '.'
message << ". However, #{failure_reason}"
end
message << '.'
Shoulda::Matchers.word_wrap(message) Shoulda::Matchers.word_wrap(message)
end end
@ -230,18 +222,63 @@ module Shoulda
private private
attr_reader :attribute_name, :options, :record, :failure_reason attr_reader :attribute_name, :options, :record,
:failure_message_continuation
def expectation def expectation
description if enum_defined?
expectation = "#{simple_description} backed by "
expectation << Shoulda::Matchers::Util.a_or_an(expected_column_type)
if expected_enum_values.any?
expectation << ', mapping '
expectation << presented_enum_mapping(
normalized_expected_enum_values,
)
end
if expected_prefix
expectation <<
if expected_suffix
', '
else
' and '
end
expectation << 'prefixing accessor methods with '
expectation << "#{expected_prefix}_".inspect
end
if expected_suffix
expectation <<
if expected_prefix
', and '
else
' and '
end
expectation << 'suffixing accessor methods with '
expectation << "_#{expected_suffix}".inspect
end
expectation
else
simple_description
end
end end
def presented_expected_enum_values def simple_description
if expected_enum_values.is_a?(Hash) "define :#{attribute_name} as an enum"
expected_enum_values.symbolize_keys end
else
expected_enum_values def presented_enum_mapping(enum_values)
end enum_values.
map { |output_to_input|
output_to_input.
map(&Shoulda::Matchers::Util.method(:inspect_value)).
join(' to ')
}.
to_sentence
end end
def normalized_expected_enum_values def normalized_expected_enum_values
@ -256,14 +293,6 @@ module Shoulda
options[:expected_enum_values] options[:expected_enum_values]
end end
def presented_actual_enum_values
if expected_enum_values.is_a?(Array)
to_array(actual_enum_values)
else
to_hash(actual_enum_values).symbolize_keys
end
end
def normalized_actual_enum_values def normalized_actual_enum_values
to_hash(actual_enum_values) to_hash(actual_enum_values)
end end
@ -276,7 +305,8 @@ module Shoulda
if model.defined_enums.include?(attribute_name.to_s) if model.defined_enums.include?(attribute_name.to_s)
true true
else else
@failure_reason = "no such enum exists in #{model}" @failure_message_continuation =
"no such enum exists on #{model}"
false false
end end
end end
@ -289,11 +319,9 @@ module Shoulda
if passed if passed
true true
else else
@failure_reason = @failure_message_continuation =
"the actual enum values for #{attribute_name.inspect} are " + "However, #{attribute_name.inspect} actually maps " +
Shoulda::Matchers::Util.inspect_value( presented_enum_mapping(normalized_actual_enum_values)
presented_actual_enum_values,
)
false false
end end
end end
@ -302,8 +330,8 @@ module Shoulda
if column.type == expected_column_type.to_sym if column.type == expected_column_type.to_sym
true true
else else
@failure_reason = @failure_message_continuation =
"#{attribute_name.inspect} is " + "However, #{attribute_name.inspect} is " +
Shoulda::Matchers::Util.a_or_an(column.type) + Shoulda::Matchers::Util.a_or_an(column.type) +
' column' ' column'
false false
@ -330,30 +358,59 @@ module Shoulda
if passed if passed
true true
else else
@failure_reason = message = "#{attribute_name.inspect} does map to these "
if options[:expected_prefix] message << 'values, but the enum is '
if options[:expected_suffix]
'it was defined with either a different prefix, a ' + if expected_prefix
'different suffix, or neither one at all' if expected_suffix
else message << 'configured with either a different prefix or '
'it was defined with either a different prefix or none at all' message << 'suffix, or no prefix or suffix at all'
end else
elsif options[:expected_suffix] message << 'configured with either a different prefix or no '
'it was defined with either a different suffix or none at all' message << 'prefix at all'
end end
elsif expected_suffix
message << 'configured with either a different suffix or no '
message << 'suffix at all'
end
message << " (we can't tell which)"
@failure_message_continuation = message
false false
end end
end end
def expected_singleton_methods def expected_singleton_methods
expected_enum_value_names.map do |name| expected_enum_value_names.map do |name|
[options[:expected_prefix], name, options[:expected_suffix]]. [expected_prefix, name, expected_suffix].
select(&:present?). select(&:present?).
join('_'). join('_').
to_sym to_sym
end end
end end
def expected_prefix
if options.include?(:prefix)
if options[:prefix] == true
attribute_name#.to_sym
else
options[:prefix]#.to_sym
end
end
end
def expected_suffix
if options.include?(:suffix)
if options[:suffix] == true
attribute_name#.to_sym
else
options[:suffix]#.to_sym
end
end
end
def to_hash(value) def to_hash(value)
if value.is_a?(Array) if value.is_a?(Array)
value.each_with_index.inject({}) do |hash, (item, index)| value.each_with_index.inject({}) do |hash, (item, index)|

View File

@ -9,8 +9,8 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
column_type: :integer, column_type: :integer,
) )
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attrs as an enum, backed by an integer. Expected Example to define :attrs as an enum, but no such enum exists on
However, no such enum exists in Example. Example.
MESSAGE MESSAGE
assertion = lambda do assertion = lambda do
@ -28,8 +28,8 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer. Expected Example to define :attr as an enum, but no such enum exists on
However, no such enum exists in Example. Example.
MESSAGE MESSAGE
assertion = lambda do assertion = lambda do
@ -48,8 +48,8 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
attribute_name: :attr, attribute_name: :attr,
) )
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer. Expected Example to define :attr as an enum, but no such enum exists
However, no such enum exists in Example. on Example.
MESSAGE MESSAGE
assertion = lambda do assertion = lambda do
@ -68,7 +68,7 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
column_type: :string, column_type: :string,
) )
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer. Expected Example to define :attr as an enum backed by an integer.
However, :attr is a string column. However, :attr is a string column.
MESSAGE MESSAGE
@ -81,30 +81,23 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
context 'if the attribute is defined as an enum' do context 'if the attribute is defined as an enum' do
it 'accepts' do it 'matches' do
record = build_record_with_array_values(attribute_name: :attr) record = build_record_with_array_values(attribute_name: :attr)
expect(record).to define_enum_for(:attr) expect { define_enum_for(:attr) }.
to match_against(record).
or_fail_with(<<-MESSAGE, wrap: true)
Expected Example not to define :attr as an enum backed by an
integer, but it did.
MESSAGE
end end
context 'and the matcher is negated' do it 'has the right description' do
it 'rejects with an appropriate failure message' do matcher = define_enum_for(:attr)
record = build_record_with_array_values(
model_name: 'Example',
attribute_name: :attr,
column_type: :integer,
)
message = format_message(<<-MESSAGE)
Expected Example not to define :attr as an enum, backed by an integer,
but it did.
MESSAGE
assertion = lambda do expect(matcher.description).to eq(<<~MESSAGE.strip)
expect(record).not_to define_enum_for(:attr) define :attr as an enum backed by an integer
end MESSAGE
expect(&assertion).to fail_with_message(message)
end
end end
end end
end end
@ -118,9 +111,8 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
attribute_name: :attr, attribute_name: :attr,
) )
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer, Expected Example to define :attr as an enum, but no such enum
with possible values ["open", "close"]. However, no such enum exists on Example.
exists in Example.
MESSAGE MESSAGE
assertion = lambda do assertion = lambda do
@ -142,9 +134,10 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
values: ['published', 'unpublished', 'draft'], values: ['published', 'unpublished', 'draft'],
) )
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer, Expected Example to define :attr as an enum backed by an integer,
with possible values ["open", "close"]. However, the actual mapping "open" to 0 and "close" to 1. However, :attr
enum values for :attr are ["published", "unpublished", "draft"]. actually maps "published" to 0, "unpublished" to 1, and
"draft" to 2.
MESSAGE MESSAGE
assertion = lambda do assertion = lambda do
@ -158,14 +151,33 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
context 'and the enum values match' do context 'and the enum values match' do
it 'accepts' do it 'matches' do
record = build_record_with_array_values( record = build_record_with_array_values(
attribute_name: :attr, attribute_name: :attr,
values: ['published', 'unpublished', 'draft'], values: ['published', 'unpublished', 'draft'],
) )
expect(record).to define_enum_for(:attr). matcher = lambda do
define_enum_for(:attr).
with_values(['published', 'unpublished', 'draft'])
end
expect(&matcher).
to match_against(record).
or_fail_with(<<-MESSAGE, wrap: true)
Expected Example not to define :attr as an enum backed by an
integer, mapping "published" to 0, "unpublished" to 1,
and "draft" to 2, but it did.
MESSAGE
end
it 'has the right description' do
matcher = define_enum_for(:attr).
with_values(['published', 'unpublished', 'draft']) with_values(['published', 'unpublished', 'draft'])
expect(matcher.description).to eq(<<~MESSAGE.strip)
define :attr as an enum backed by an integer with values ["published", "unpublished", "draft"]
MESSAGE
end end
end end
end end
@ -179,9 +191,8 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
attribute_name: :attr, attribute_name: :attr,
) )
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer, Expected Example to define :attr as an enum, but no such enum exists
with possible values {active: 5, archived: 10}. However, no such on Example.
enum exists in Example.
MESSAGE MESSAGE
assertion = lambda do assertion = lambda do
@ -203,9 +214,9 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
values: { active: 0, archived: 1 }, values: { active: 0, archived: 1 },
) )
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer, Expected Example to define :attr as an enum backed by an integer,
with possible values {active: 5, archived: 10}. However, the mapping "active" to 5 and "archived" to 10. However, :attr
actual enum values for :attr are {active: 0, archived: 1}. actually maps "active" to 0 and "archived" to 1.
MESSAGE MESSAGE
assertion = lambda do assertion = lambda do
@ -220,28 +231,64 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
context 'and the enum values match' do context 'and the enum values match' do
context 'when expected enum values are a hash' do context 'when expected enum values are a hash' do
it 'accepts' do it 'matches' do
record = build_record_with_hash_values( record = build_record_with_hash_values(
attribute_name: :attr, attribute_name: :attr,
values: { active: 0, archived: 1 }, values: { active: 0, archived: 1 },
) )
expect(record). matcher = lambda do
to define_enum_for(:attr). define_enum_for(:attr).
with_values(active: 0, archived: 1)
end
expect(&matcher).
to match_against(record).
or_fail_with(<<-MESSAGE, wrap: true)
Expected Example not to define :attr as an enum backed by an
integer, mapping "active" to 0 and "archived" to 1,
but it did.
MESSAGE
end
it 'has the right description' do
matcher = define_enum_for(:attr).
with_values(active: 0, archived: 1) with_values(active: 0, archived: 1)
expect(matcher.description).to eq(<<~MESSAGE.strip)
define :attr as an enum backed by an integer with values {active: 0, archived: 1}
MESSAGE
end end
end end
context 'when expected enum values are an array' do context 'when expected enum values are an array' do
it 'accepts' do it 'matches' do
record = build_record_with_hash_values( record = build_record_with_hash_values(
attribute_name: :attr, attribute_name: :attr,
values: { active: 0, archived: 1 }, values: { active: 0, archived: 1 },
) )
expect(record). matcher = lambda do
to define_enum_for(:attr). define_enum_for(:attr).
with_values(['active', 'archived'])
end
expect(&matcher).
to match_against(record).
or_fail_with(<<-MESSAGE, wrap: true)
Expected Example not to define :attr as an enum backed by an
integer, mapping "active" to 0 and "archived" to 1,
but it did.
MESSAGE
end
it 'has the right description' do
matcher = define_enum_for(:attr).
with_values(['active', 'archived']) with_values(['active', 'archived'])
expect(matcher.description).to eq(<<~MESSAGE.strip)
define :attr as an enum backed by an integer with values ["active", "archived"]
MESSAGE
end end
end end
end end
@ -276,7 +323,7 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
column_type: :integer, column_type: :integer,
) )
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by a string. Expected Example to define :attr as an enum backed by a string.
However, :attr is an integer column. However, :attr is an integer column.
MESSAGE MESSAGE
@ -291,15 +338,30 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
context 'if the column storing the attribute is of the same type' do context 'if the column storing the attribute is of the same type' do
it 'accepts' do it 'matches' do
record = build_record_with_array_values( record = build_record_with_array_values(
attribute_name: :attr, attribute_name: :attr,
column_type: :string, column_type: :string,
) )
expect(record). matcher = lambda do
to define_enum_for(:attr). define_enum_for(:attr).backed_by_column_of_type(:string)
backed_by_column_of_type(:string) end
expect(&matcher).
to match_against(record).
or_fail_with(<<-MESSAGE, wrap: true)
Expected Example not to define :attr as an enum backed by a string,
but it did.
MESSAGE
end
it 'has the right description' do
matcher = define_enum_for(:attr).backed_by_column_of_type(:string)
expect(matcher.description).to eq(<<~MESSAGE.strip)
define :attr as an enum backed by a string
MESSAGE
end end
end end
end end
@ -324,10 +386,11 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer, Expected Example to define :attr as an enum backed by an integer,
using a prefix of :foo, with possible values [:active, mapping "active" to 0 and "archived" to 1 and prefixing
:archived]. However, it was defined with either a different accessor methods with "foo_". :attr does map to these values, but
prefix or none at all. the enum is configured with either a different prefix or no prefix
at all (we can't tell which).
MESSAGE MESSAGE
expect(&assertion).to fail_with_message(message) expect(&assertion).to fail_with_message(message)
@ -352,10 +415,11 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer, Expected Example to define :attr as an enum backed by an integer,
using a prefix of :bar, with possible values [:active, mapping "active" to 0 and "archived" to 1 and prefixing
:archived]. However, it was defined with either a different accessor methods with "bar_". :attr does map to these values, but
prefix or none at all. the enum is configured with either a different prefix or no prefix
at all (we can't tell which).
MESSAGE MESSAGE
expect(&assertion).to fail_with_message(message) expect(&assertion).to fail_with_message(message)
@ -363,7 +427,7 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
context 'if the attribute was defined with the same prefix' do context 'if the attribute was defined with the same prefix' do
it 'accepts' do it 'matches' do
record = build_record_with_array_values( record = build_record_with_array_values(
model_name: 'Example', model_name: 'Example',
attribute_name: :attr, attribute_name: :attr,
@ -371,10 +435,29 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
prefix: :foo, prefix: :foo,
) )
expect(record). matcher = lambda do
to define_enum_for(:attr). define_enum_for(:attr).
with_values([:active, :archived]).
with_prefix(:foo)
end
expect(&matcher).
to match_against(record).
or_fail_with(<<-MESSAGE, wrap: true)
Expected Example not to define :attr as an enum backed by an
integer, mapping "active" to 0 and "archived" to 1 and
prefixing accessor methods with "foo_", but it did.
MESSAGE
end
it 'has the right description' do
matcher = define_enum_for(:attr).
with_values([:active, :archived]). with_values([:active, :archived]).
with_prefix(:foo) with_prefix(:foo)
expect(matcher.description).to eq(<<~MESSAGE.strip)
define :attr as an enum backed by an integer with values [:active, :archived], prefix: :foo
MESSAGE
end end
end end
end end
@ -397,10 +480,11 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer, Expected Example to define :attr as an enum backed by an integer,
using a prefix of :attr, with possible values [:active, mapping "active" to 0 and "archived" to 1 and prefixing
:archived]. However, it was defined with either a different accessor methods with "attr_". :attr does map to these values, but
prefix or none at all. the enum is configured with either a different prefix or no prefix
at all (we can't tell which).
MESSAGE MESSAGE
expect(&assertion).to fail_with_message(message) expect(&assertion).to fail_with_message(message)
@ -408,7 +492,7 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
context 'if the attribute was defined with a prefix' do context 'if the attribute was defined with a prefix' do
it 'accepts' do it 'matches' do
record = build_record_with_array_values( record = build_record_with_array_values(
model_name: 'Example', model_name: 'Example',
attribute_name: :attr, attribute_name: :attr,
@ -416,10 +500,29 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
prefix: true, prefix: true,
) )
expect(record). matcher = lambda do
to define_enum_for(:attr). define_enum_for(:attr).
with_values([:active, :archived]).
with_prefix
end
expect(&matcher).
to match_against(record).
or_fail_with(<<-MESSAGE, wrap: true)
Expected Example not to define :attr as an enum backed by an
integer, mapping "active" to 0 and "archived" to 1 and
prefixing accessor methods with "attr_", but it did.
MESSAGE
end
it 'has the right description' do
matcher = define_enum_for(:attr).
with_values([:active, :archived]). with_values([:active, :archived]).
with_prefix with_prefix
expect(matcher.description).to eq(<<~MESSAGE.strip)
define :attr as an enum backed by an integer with values [:active, :archived], prefix: true
MESSAGE
end end
end end
end end
@ -444,10 +547,11 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer, Expected Example to define :attr as an enum backed by an integer,
using a suffix of :foo, with possible values [:active, mapping "active" to 0 and "archived" to 1 and suffixing
:archived]. However, it was defined with either a different accessor methods with "_foo". :attr does map to these values, but
suffix or none at all. the enum is configured with either a different suffix or no suffix
at all (we can't tell which).
MESSAGE MESSAGE
expect(&assertion).to fail_with_message(message) expect(&assertion).to fail_with_message(message)
@ -472,10 +576,11 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer, Expected Example to define :attr as an enum backed by an integer,
using a suffix of :bar, with possible values [:active, mapping "active" to 0 and "archived" to 1 and suffixing
:archived]. However, it was defined with either a different accessor methods with "_bar". :attr does map to these values, but
suffix or none at all. the enum is configured with either a different suffix or no suffix
at all (we can't tell which).
MESSAGE MESSAGE
expect(&assertion).to fail_with_message(message) expect(&assertion).to fail_with_message(message)
@ -483,7 +588,7 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
context 'if the attribute was defined with the same suffix' do context 'if the attribute was defined with the same suffix' do
it 'accepts' do it 'matches' do
record = build_record_with_array_values( record = build_record_with_array_values(
model_name: 'Example', model_name: 'Example',
attribute_name: :attr, attribute_name: :attr,
@ -491,10 +596,29 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
suffix: :foo, suffix: :foo,
) )
expect(record). matcher = lambda do
to define_enum_for(:attr). define_enum_for(:attr).
with_values([:active, :archived]).
with_suffix(:foo)
end
expect(&matcher).
to match_against(record).
or_fail_with(<<-MESSAGE, wrap: true)
Expected Example not to define :attr as an enum backed by an
integer, mapping "active" to 0 and "archived" to 1 and
suffixing accessor methods with "_foo", but it did.
MESSAGE
end
it 'has the right description' do
matcher = define_enum_for(:attr).
with_values([:active, :archived]). with_values([:active, :archived]).
with_suffix(:foo) with_suffix(:foo)
expect(matcher.description).to eq(<<~MESSAGE.strip)
define :attr as an enum backed by an integer with values [:active, :archived], suffix: :foo
MESSAGE
end end
end end
end end
@ -517,10 +641,11 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer, Expected Example to define :attr as an enum backed by an integer,
using a suffix of :attr, with possible values [:active, mapping "active" to 0 and "archived" to 1 and suffixing
:archived]. However, it was defined with either a different accessor methods with "_attr". :attr does map to these values, but
suffix or none at all. the enum is configured with either a different suffix or no suffix
at all (we can't tell which).
MESSAGE MESSAGE
expect(&assertion).to fail_with_message(message) expect(&assertion).to fail_with_message(message)
@ -528,7 +653,7 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
context 'if the attribute was defined with a suffix' do context 'if the attribute was defined with a suffix' do
it 'accepts' do it 'matches' do
record = build_record_with_array_values( record = build_record_with_array_values(
model_name: 'Example', model_name: 'Example',
attribute_name: :attr, attribute_name: :attr,
@ -536,10 +661,29 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
suffix: true, suffix: true,
) )
expect(record). matcher = lambda do
to define_enum_for(:attr). define_enum_for(:attr).
with_values([:active, :archived]).
with_suffix
end
expect(&matcher).
to match_against(record).
or_fail_with(<<-MESSAGE, wrap: true)
Expected Example not to define :attr as an enum backed by an
integer, mapping "active" to 0 and "archived" to 1 and
suffixing accessor methods with "_attr", but it did.
MESSAGE
end
it 'has the right description' do
matcher = define_enum_for(:attr).
with_values([:active, :archived]). with_values([:active, :archived]).
with_suffix with_suffix
expect(matcher.description).to eq(<<~MESSAGE.strip)
define :attr as an enum backed by an integer with values [:active, :archived], suffix: true
MESSAGE
end end
end end
end end
@ -566,10 +710,12 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer, Expected Example to define :attr as an enum backed by an integer,
using a prefix of :whatever and a suffix of :bar, with possible mapping "active" to 0 and "archived" to 1, prefixing
values [:active, :archived]. However, it was defined with either accessor methods with "whatever_", and suffixing accessor methods
a different prefix, a different suffix, or neither one at all. with "_bar". :attr does map to these values, but the enum is
configured with either a different prefix or suffix, or no prefix or
suffix at all (we can't tell which).
MESSAGE MESSAGE
expect(&assertion).to fail_with_message(message) expect(&assertion).to fail_with_message(message)
@ -595,11 +741,12 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
message = format_message(<<-MESSAGE) message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum, backed by an integer, Expected Example to define :attr as an enum backed by an integer,
using a prefix of :foo and a suffix of :whatever, with possible mapping "active" to 0 and "archived" to 1, prefixing
values [:active, :archived]. However, it was defined with accessor methods with "foo_", and suffixing accessor methods with
either a different prefix, a different suffix, or neither one at "_whatever". :attr does map to these values, but the enum is
all. configured with either a different prefix or suffix, or no prefix
or suffix at all (we can't tell which).
MESSAGE MESSAGE
expect(&assertion).to fail_with_message(message) expect(&assertion).to fail_with_message(message)
@ -607,7 +754,7 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
end end
context 'if the attribute was defined with the same prefix and suffix' do context 'if the attribute was defined with the same prefix and suffix' do
it 'accepts' do it 'matches' do
record = build_record_with_array_values( record = build_record_with_array_values(
model_name: 'Example', model_name: 'Example',
attribute_name: :attr, attribute_name: :attr,
@ -616,11 +763,32 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
suffix: :bar, suffix: :bar,
) )
expect(record). matcher = lambda do
to define_enum_for(:attr). define_enum_for(:attr).
with_values([:active, :archived]).
with_prefix(:foo).
with_suffix(:bar)
end
expect(&matcher).
to match_against(record).
or_fail_with(<<-MESSAGE, wrap: true)
Expected Example not to define :attr as an enum backed by an
integer, mapping "active" to 0 and "archived" to 1,
prefixing accessor methods with "foo_", and suffixing accessor
methods with "_bar", but it did.
MESSAGE
end
it 'has the right description' do
matcher = define_enum_for(:attr).
with_values([:active, :archived]). with_values([:active, :archived]).
with_prefix(:foo). with_prefix(:foo).
with_suffix(:bar) with_suffix(:bar)
expect(matcher.description).to eq(<<~MESSAGE.strip)
define :attr as an enum backed by an integer with values [:active, :archived], prefix: :foo, suffix: :bar
MESSAGE
end end
end end
end end