Add with_prefix and with_suffix to define_enum_for
In Rails 5, the `enum` macro received two new options: `_prefix` and `_suffix`. These options change the names of the methods that are generated from the given enum values. This commit adds qualifiers to the `define_enum_for` matcher so that they can be tested.
This commit is contained in:
parent
d8681fa721
commit
147ac482e8
|
@ -80,6 +80,55 @@ module Shoulda
|
|||
# backed_by_column_of_type(:string)
|
||||
# end
|
||||
#
|
||||
## ##### with_prefix
|
||||
#
|
||||
# Use `with_prefix` to test that the enum is defined with a `_prefix`
|
||||
# option (Rails 5 only). Can take either a boolean or a symbol:
|
||||
#
|
||||
# class Issue < ActiveRecord::Base
|
||||
# enum status: [:open, :closed], _prefix: :old
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# RSpec.describe Issue, type: :model do
|
||||
# it do
|
||||
# should define_enum_for(:status).
|
||||
# with_values([:open, :closed]).
|
||||
# with_prefix(:old)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Minitest (Shoulda)
|
||||
# class ProcessTest < ActiveSupport::TestCase
|
||||
# should define_enum_for(:status).
|
||||
# with_values([:open, :closed]).
|
||||
# with_prefix(:old)
|
||||
# end
|
||||
#
|
||||
# ##### with_suffix
|
||||
#
|
||||
# Use `with_suffix` to test that the enum is defined with a `_suffix`
|
||||
# option (Rails 5 only). Can take either a boolean or a symbol:
|
||||
#
|
||||
# class Issue < ActiveRecord::Base
|
||||
# enum status: [:open, :closed], _suffix: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# RSpec.describe Issue, type: :model do
|
||||
# it do
|
||||
# should define_enum_for(:status).
|
||||
# with_values([:open, :closed]).
|
||||
# with_suffix
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Minitest (Shoulda)
|
||||
# class ProcessTest < ActiveSupport::TestCase
|
||||
# should define_enum_for(:status).
|
||||
# with_values([:open, :closed]).
|
||||
# with_suffix
|
||||
# end
|
||||
#
|
||||
# @return [DefineEnumForMatcher]
|
||||
#
|
||||
|
@ -98,6 +147,23 @@ module Shoulda
|
|||
description = "define :#{attribute_name} as an enum, backed by "
|
||||
description << Shoulda::Matchers::Util.a_or_an(expected_column_type)
|
||||
|
||||
if options[:expected_prefix]
|
||||
description << ', using a prefix of '
|
||||
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(
|
||||
|
@ -121,6 +187,16 @@ module Shoulda
|
|||
with_values(expected_enum_values)
|
||||
end
|
||||
|
||||
def with_prefix(expected_prefix = attribute_name)
|
||||
options[:expected_prefix] = expected_prefix
|
||||
self
|
||||
end
|
||||
|
||||
def with_suffix(expected_suffix = attribute_name)
|
||||
options[:expected_suffix] = expected_suffix
|
||||
self
|
||||
end
|
||||
|
||||
def backed_by_column_of_type(expected_column_type)
|
||||
options[:expected_column_type] = expected_column_type
|
||||
self
|
||||
|
@ -128,7 +204,11 @@ module Shoulda
|
|||
|
||||
def matches?(subject)
|
||||
@record = subject
|
||||
enum_defined? && enum_values_match? && column_type_matches?
|
||||
|
||||
enum_defined? &&
|
||||
enum_values_match? &&
|
||||
column_type_matches? &&
|
||||
enum_value_methods_exist?
|
||||
end
|
||||
|
||||
def failure_message
|
||||
|
@ -168,6 +248,10 @@ module Shoulda
|
|||
to_hash(expected_enum_values)
|
||||
end
|
||||
|
||||
def expected_enum_value_names
|
||||
to_array(expected_enum_values)
|
||||
end
|
||||
|
||||
def expected_enum_values
|
||||
options[:expected_enum_values]
|
||||
end
|
||||
|
@ -238,6 +322,38 @@ module Shoulda
|
|||
record.class
|
||||
end
|
||||
|
||||
def enum_value_methods_exist?
|
||||
passed = expected_singleton_methods.all? do |method|
|
||||
model.singleton_methods.include?(method)
|
||||
end
|
||||
|
||||
if passed
|
||||
true
|
||||
else
|
||||
@failure_reason =
|
||||
if options[:expected_prefix]
|
||||
if options[:expected_suffix]
|
||||
'it was defined with either a different prefix, a ' +
|
||||
'different suffix, or neither one at all'
|
||||
else
|
||||
'it was defined with either a different prefix or none at all'
|
||||
end
|
||||
elsif options[:expected_suffix]
|
||||
'it was defined with either a different suffix or none at all'
|
||||
end
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def expected_singleton_methods
|
||||
expected_enum_value_names.map do |name|
|
||||
[options[:expected_prefix], name, options[:expected_suffix]].
|
||||
select(&:present?).
|
||||
join('_').
|
||||
to_sym
|
||||
end
|
||||
end
|
||||
|
||||
def to_hash(value)
|
||||
if value.is_a?(Array)
|
||||
value.each_with_index.inject({}) do |hash, (item, index)|
|
||||
|
|
|
@ -9,6 +9,10 @@ module UnitTests
|
|||
Tests::Version.new(::ActiveRecord::VERSION::STRING)
|
||||
end
|
||||
|
||||
def active_record_enum_supports_prefix_and_suffix?
|
||||
active_record_version >= 5
|
||||
end
|
||||
|
||||
def active_record_supports_has_secure_password?
|
||||
active_record_version >= 3.1
|
||||
end
|
||||
|
|
|
@ -304,30 +304,361 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
|
|||
end
|
||||
end
|
||||
|
||||
if active_record_enum_supports_prefix_and_suffix?
|
||||
context 'qualified with #with_prefix' do
|
||||
context 'when the prefix is explicit' do
|
||||
context 'if the attribute was not defined with a prefix' do
|
||||
it 'rejects with an appropriate failure message' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
column_type: :integer,
|
||||
values: [:active, :archived],
|
||||
)
|
||||
|
||||
assertion = lambda do
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_prefix(:foo)
|
||||
end
|
||||
|
||||
message = format_message(<<-MESSAGE)
|
||||
Expected Example to define :attr as an enum, backed by an integer,
|
||||
using a prefix of :foo, with possible values ‹[:active,
|
||||
:archived]›. However, it was defined with either a different
|
||||
prefix or none at all.
|
||||
MESSAGE
|
||||
|
||||
expect(&assertion).to fail_with_message(message)
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the attribute was defined with a different prefix' do
|
||||
it 'rejects with an appropriate failure message' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
column_type: :integer,
|
||||
values: [:active, :archived],
|
||||
prefix: :foo,
|
||||
)
|
||||
|
||||
assertion = lambda do
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_prefix(:bar)
|
||||
end
|
||||
|
||||
message = format_message(<<-MESSAGE)
|
||||
Expected Example to define :attr as an enum, backed by an integer,
|
||||
using a prefix of :bar, with possible values ‹[:active,
|
||||
:archived]›. However, it was defined with either a different
|
||||
prefix or none at all.
|
||||
MESSAGE
|
||||
|
||||
expect(&assertion).to fail_with_message(message)
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the attribute was defined with the same prefix' do
|
||||
it 'accepts' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
values: [:active, :archived],
|
||||
prefix: :foo,
|
||||
)
|
||||
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_prefix(:foo)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the prefix is implicit' do
|
||||
context 'if the attribute was not defined with a prefix' do
|
||||
it 'rejects with an appropriate failure message' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
column_type: :integer,
|
||||
values: [:active, :archived],
|
||||
)
|
||||
|
||||
assertion = lambda do
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_prefix
|
||||
end
|
||||
|
||||
message = format_message(<<-MESSAGE)
|
||||
Expected Example to define :attr as an enum, backed by an integer,
|
||||
using a prefix of :attr, with possible values ‹[:active,
|
||||
:archived]›. However, it was defined with either a different
|
||||
prefix or none at all.
|
||||
MESSAGE
|
||||
|
||||
expect(&assertion).to fail_with_message(message)
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the attribute was defined with a prefix' do
|
||||
it 'accepts' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
values: [:active, :archived],
|
||||
prefix: true,
|
||||
)
|
||||
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_prefix
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'qualified with #with_suffix' do
|
||||
context 'when the suffix is explicit' do
|
||||
context 'if the attribute was not defined with a suffix' do
|
||||
it 'rejects with an appropriate failure message' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
column_type: :integer,
|
||||
values: [:active, :archived],
|
||||
)
|
||||
|
||||
assertion = lambda do
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_suffix(:foo)
|
||||
end
|
||||
|
||||
message = format_message(<<-MESSAGE)
|
||||
Expected Example to define :attr as an enum, backed by an integer,
|
||||
using a suffix of :foo, with possible values ‹[:active,
|
||||
:archived]›. However, it was defined with either a different
|
||||
suffix or none at all.
|
||||
MESSAGE
|
||||
|
||||
expect(&assertion).to fail_with_message(message)
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the attribute was defined with a different suffix' do
|
||||
it 'rejects with an appropriate failure message' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
column_type: :integer,
|
||||
values: [:active, :archived],
|
||||
suffix: :foo,
|
||||
)
|
||||
|
||||
assertion = lambda do
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_suffix(:bar)
|
||||
end
|
||||
|
||||
message = format_message(<<-MESSAGE)
|
||||
Expected Example to define :attr as an enum, backed by an integer,
|
||||
using a suffix of :bar, with possible values ‹[:active,
|
||||
:archived]›. However, it was defined with either a different
|
||||
suffix or none at all.
|
||||
MESSAGE
|
||||
|
||||
expect(&assertion).to fail_with_message(message)
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the attribute was defined with the same suffix' do
|
||||
it 'accepts' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
values: [:active, :archived],
|
||||
suffix: :foo,
|
||||
)
|
||||
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_suffix(:foo)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the suffix is implicit' do
|
||||
context 'if the attribute was not defined with a suffix' do
|
||||
it 'rejects with an appropriate failure message' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
column_type: :integer,
|
||||
values: [:active, :archived],
|
||||
)
|
||||
|
||||
assertion = lambda do
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_suffix
|
||||
end
|
||||
|
||||
message = format_message(<<-MESSAGE)
|
||||
Expected Example to define :attr as an enum, backed by an integer,
|
||||
using a suffix of :attr, with possible values ‹[:active,
|
||||
:archived]›. However, it was defined with either a different
|
||||
suffix or none at all.
|
||||
MESSAGE
|
||||
|
||||
expect(&assertion).to fail_with_message(message)
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the attribute was defined with a suffix' do
|
||||
it 'accepts' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
values: [:active, :archived],
|
||||
suffix: true,
|
||||
)
|
||||
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_suffix
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'qualified with both #with_prefix and #with_suffix' do
|
||||
context 'if the attribute was not defined with a different prefix' do
|
||||
it 'rejects with an appropriate failure message' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
column_type: :integer,
|
||||
values: [:active, :archived],
|
||||
prefix: :foo,
|
||||
suffix: :bar,
|
||||
)
|
||||
|
||||
assertion = lambda do
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_prefix(:whatever).
|
||||
with_suffix(:bar)
|
||||
end
|
||||
|
||||
message = format_message(<<-MESSAGE)
|
||||
Expected Example to define :attr as an enum, backed by an integer,
|
||||
using a prefix of :whatever and a suffix of :bar, with possible
|
||||
values ‹[:active, :archived]›. However, it was defined with either
|
||||
a different prefix, a different suffix, or neither one at all.
|
||||
MESSAGE
|
||||
|
||||
expect(&assertion).to fail_with_message(message)
|
||||
end
|
||||
|
||||
context 'if the attribute was defined with a different suffix' do
|
||||
it 'rejects with an appropriate failure message' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
column_type: :integer,
|
||||
values: [:active, :archived],
|
||||
prefix: :foo,
|
||||
suffix: :bar,
|
||||
)
|
||||
|
||||
assertion = lambda do
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_prefix(:foo).
|
||||
with_suffix(:whatever)
|
||||
end
|
||||
|
||||
message = format_message(<<-MESSAGE)
|
||||
Expected Example to define :attr as an enum, backed by an integer,
|
||||
using a prefix of :foo and a suffix of :whatever, with possible
|
||||
values ‹[:active, :archived]›. However, it was defined with
|
||||
either a different prefix, a different suffix, or neither one at
|
||||
all.
|
||||
MESSAGE
|
||||
|
||||
expect(&assertion).to fail_with_message(message)
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the attribute was defined with the same prefix and suffix' do
|
||||
it 'accepts' do
|
||||
record = build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
values: [:active, :archived],
|
||||
prefix: :foo,
|
||||
suffix: :bar,
|
||||
)
|
||||
|
||||
expect(record).
|
||||
to define_enum_for(:attr).
|
||||
with_values([:active, :archived]).
|
||||
with_prefix(:foo).
|
||||
with_suffix(:bar)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def build_record_with_array_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
column_type: :integer,
|
||||
values: ['published', 'unpublished', 'draft']
|
||||
values: ['published', 'unpublished', 'draft'],
|
||||
prefix: false,
|
||||
suffix: false
|
||||
)
|
||||
build_record_with_enum_attribute(
|
||||
model_name: model_name,
|
||||
attribute_name: attribute_name,
|
||||
column_type: column_type,
|
||||
values: values,
|
||||
prefix: prefix,
|
||||
suffix: suffix,
|
||||
)
|
||||
end
|
||||
|
||||
def build_record_with_hash_values(
|
||||
model_name: 'Example',
|
||||
attribute_name: :attr,
|
||||
values: { active: 0, archived: 1 }
|
||||
values: { active: 0, archived: 1 },
|
||||
prefix: false,
|
||||
suffix: false
|
||||
)
|
||||
build_record_with_enum_attribute(
|
||||
model_name: model_name,
|
||||
attribute_name: attribute_name,
|
||||
column_type: :integer,
|
||||
values: values,
|
||||
prefix: prefix,
|
||||
suffix: suffix,
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -335,13 +666,21 @@ describe Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher, type: :model do
|
|||
model_name:,
|
||||
attribute_name:,
|
||||
column_type:,
|
||||
values:
|
||||
values:,
|
||||
prefix: false,
|
||||
suffix: false
|
||||
)
|
||||
model = define_model(
|
||||
model_name,
|
||||
attribute_name => column_type,
|
||||
attribute_name => { type: column_type },
|
||||
)
|
||||
model.enum(attribute_name => values)
|
||||
|
||||
if active_record_enum_supports_prefix_and_suffix?
|
||||
model.enum(attribute_name => values, _prefix: prefix, _suffix: suffix)
|
||||
else
|
||||
model.enum(attribute_name => values)
|
||||
end
|
||||
|
||||
model.new
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue