Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Ensure DefineEnumForMatcher#validating handles Hash enum values correctly #1646

Conversation

mi-wada
Copy link
Contributor

@mi-wada mi-wada commented Aug 13, 2024

Why

DefineEnumForMatcher#validating is added at #1630

At 6.3.0, DefineEnumForMatcher#validating only worked with Array enum values. This PR ensures it now also correctly handles Hash enum values.

How it works

class Issue < ActiveRecord::Base
  enum :status, {
    open: 0,
    closed: 1
  }, validate: true
end

RSpec.describe Issue, type: :model do
  before do
    ActiveRecord::Base.connection.create_table('issues', temporary: true) do |t|
      t.integer :status
    end
  end

  it do
    should define_enum_for(:status)
      .with_values(open: 0, closed: 1)
      .validating
  end
end

At 6.3.0

assertion fails. This is because the existing code only assumes that enum values is an Array.

       Expected Issue to define :status as an enum backed by an integer,
       mapping ‹"open"› to ‹0›、‹"closed"› to ‹1›, and being validated not
       allowing nil values. However, :status is not being validated.

By this patch

assertion succeed.

  is expected to define :status as an enum backed by an integer with values ‹{open: 0, closed: 1}›

…correctly

Previously, DefineEnumForMatcher#validating only worked with Array enum values. This fix ensures it now also correctly handles Hash enum values.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I simply applied the test code for the existing Array to Hash as well.
If there is another better way to do this, please let me know.

describe 'qualified with #validating' do
context 'if enum is being validated' do
context 'but validating qualifier is not used' do
it 'matches' do
record = build_record_with_array_values(attribute_name: :attr, default: 'published', validate: true)
matcher = lambda do
define_enum_for(:attr).with_values(['published', 'unpublished', 'draft'])
end
message = format_message(<<-MESSAGE)
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
expect(&matcher).to match_against(record).or_fail_with(message)
end
end
context 'and validating qualifier is used as false' do
it 'rejects with an appropriate failure message' do
record = build_record_with_array_values(attribute_name: :attr, default: 'published', validate: true)
assertion = lambda do
expect(record).
to define_enum_for(:attr).
with_values(['published', 'unpublished', 'draft']).
validating(false)
end
message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum backed by an integer,
mapping ‹"published"› to ‹0›, ‹"unpublished"› to ‹1›, and ‹"draft"›
to ‹2›. However, :attr is being validated.
MESSAGE
expect(&assertion).to fail_with_message(message)
end
end
context 'and validating qualifier is used' do
it 'matches' do
record = build_record_with_array_values(attribute_name: :attr, validate: true)
matcher = lambda do
define_enum_for(:attr).
with_values(['published', 'unpublished', 'draft']).
validating
end
message = format_message(<<-MESSAGE)
Expected Example not to define :attr as an enum backed by an integer,
mapping ‹"published"› to ‹0›, ‹"unpublished"› to ‹1›, and ‹"draft"›
to ‹2›, and being validated not allowing nil values, but it did.
MESSAGE
expect(&matcher).to match_against(record).or_fail_with(message)
end
end
context 'using allow_nil' do
context 'when allowing nil on qualifier' do
it 'matches' do
record = build_record_with_array_values(attribute_name: :attr, validate: { allow_nil: true })
matcher = lambda do
define_enum_for(:attr).
with_values(['published', 'unpublished', 'draft']).
validating(allowing_nil: true)
end
message = format_message(<<-MESSAGE)
Expected Example not to define :attr as an enum backed by an integer,
mapping ‹"published"› to ‹0›, ‹"unpublished"› to ‹1›, and ‹"draft"›
to ‹2›, and being validated allowing nil values, but it did.
MESSAGE
expect(&matcher).to match_against(record).or_fail_with(message)
end
end
context 'when not allowing nil on qualifier' do
it 'rejects with an appropriate failure message' do
record = build_record_with_array_values(attribute_name: :attr, validate: { allow_nil: true })
assertion = lambda do
expect(record).
to define_enum_for(:attr).
with_values(['published', 'unpublished', 'draft']).
validating
end
message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum backed by an integer,
mapping ‹"published"› to ‹0›, ‹"unpublished"› to ‹1›, and ‹"draft"›
to ‹2›, and being validated not allowing nil values. However, :attr is
allowing nil values.
MESSAGE
expect(&assertion).to fail_with_message(message)
end
end
end
end
context 'when not allowing nil values' do
it 'matches if qualifier does not allow' do
record = build_record_with_array_values(attribute_name: :attr, validate: { allow_nil: false })
matcher = lambda do
define_enum_for(:attr).
with_values(['published', 'unpublished', 'draft']).
validating(allowing_nil: false)
end
message = format_message(<<-MESSAGE)
Expected Example not to define :attr as an enum backed by an integer,
mapping ‹"published"› to ‹0›, ‹"unpublished"› to ‹1›, and ‹"draft"›
to ‹2›, and being validated not allowing nil values, but it did.
MESSAGE
expect(&matcher).to match_against(record).or_fail_with(message)
end
it 'rejects with an appropriate failure message if qualifier allows' do
record = build_record_with_array_values(attribute_name: :attr, validate: { allow_nil: false })
assertion = lambda do
expect(record).
to define_enum_for(:attr).
with_values(['published', 'unpublished', 'draft']).
validating(allowing_nil: true)
end
message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum backed by an integer,
mapping ‹"published"› to ‹0›, ‹"unpublished"› to ‹1›, and ‹"draft"›
to ‹2›, and being validated allowing nil values. However, :attr is allowing
nil values.
MESSAGE
expect(&assertion).to fail_with_message(message)
end
end
context 'if enum is not being validated' do
context 'but validating qualifier is used' do
it 'rejects with an appropriate failure message' do
record = build_record_with_array_values(attribute_name: :attr, default: 'published')
assertion = lambda do
expect(record).
to define_enum_for(:attr).
with_values(['published', 'unpublished', 'draft']).
validating
end
message = format_message(<<-MESSAGE)
Expected Example to define :attr as an enum backed by an integer,
mapping ‹"published"› to ‹0›, ‹"unpublished"› to ‹1›, and ‹"draft"›
to ‹2›, and being validated not allowing nil values. However, :attr
is not being validated.
MESSAGE
expect(&assertion).to fail_with_message(message)
end
end
context 'and validating qualifier is used as false' do
it 'matches' do
record = build_record_with_array_values(attribute_name: :attr, default: 'published')
matcher = lambda do
define_enum_for(:attr).
with_values(['published', 'unpublished', 'draft']).
validating(false)
end
message = format_message(<<-MESSAGE)
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
expect(&matcher).to match_against(record).or_fail_with(message)
end
end
context 'and validating qualifier is not used' do
it 'matches' do
record = build_record_with_array_values(attribute_name: :attr, default: 'published')
matcher = lambda do
define_enum_for(:attr).with_values(['published', 'unpublished', 'draft'])
end
message = format_message(<<-MESSAGE)
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
expect(&matcher).to match_against(record).or_fail_with(message)
end
end
end

Copy link
Member

@matsales28 matsales28 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for fixing that!

@matsales28 matsales28 merged commit 2e93c6d into thoughtbot:main Aug 13, 2024
15 checks passed
@mi-wada mi-wada deleted the fix-validating-behavior-when-enum_values-defined-as-hash branch August 13, 2024 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants