diff --git a/lib/shoulda/matchers/active_record/have_implicit_order_column.rb b/lib/shoulda/matchers/active_record/have_implicit_order_column.rb index 984f575c5..66f12413d 100644 --- a/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +++ b/lib/shoulda/matchers/active_record/have_implicit_order_column.rb @@ -2,7 +2,7 @@ module Shoulda module Matchers module ActiveRecord # The `have_implicit_order_column` matcher tests that the model has `implicit_order_column` - # assigned to one of the table columns. (Rails 6+ only) + # assigned to one of the table columns. # # class Product < ApplicationRecord # self.implicit_order_column = :created_at @@ -20,10 +20,8 @@ module ActiveRecord # # @return [HaveImplicitOrderColumnMatcher] # - if RailsShim.active_record_gte_6? - def have_implicit_order_column(column_name) - HaveImplicitOrderColumnMatcher.new(column_name) - end + def have_implicit_order_column(column_name) + HaveImplicitOrderColumnMatcher.new(column_name) end # @private diff --git a/lib/shoulda/matchers/rails_shim.rb b/lib/shoulda/matchers/rails_shim.rb index 63e08eb10..06c3fd80d 100644 --- a/lib/shoulda/matchers/rails_shim.rb +++ b/lib/shoulda/matchers/rails_shim.rb @@ -9,10 +9,6 @@ def action_pack_version Gem::Version.new('0') end - def active_record_gte_6? - Gem::Requirement.new('>= 6').satisfied_by?(active_record_version) - end - def active_record_version Gem::Version.new(::ActiveRecord::VERSION::STRING) rescue NameError diff --git a/spec/support/acceptance/helpers/rails_version_helpers.rb b/spec/support/acceptance/helpers/rails_version_helpers.rb index dcc2ff514..a65d70b78 100644 --- a/spec/support/acceptance/helpers/rails_version_helpers.rb +++ b/spec/support/acceptance/helpers/rails_version_helpers.rb @@ -8,10 +8,6 @@ def rails_version bundle_version_of('rails') end - def rails_gt_6_0? - rails_version > 6.0 - end - def rails_6_x? rails_version =~ '~> 6.0' end diff --git a/spec/support/acceptance/helpers/step_helpers.rb b/spec/support/acceptance/helpers/step_helpers.rb index cce623659..555afd297 100644 --- a/spec/support/acceptance/helpers/step_helpers.rb +++ b/spec/support/acceptance/helpers/step_helpers.rb @@ -90,11 +90,7 @@ def create_rails_application end def rails_new_command - if rails_version >= 6.0 - "bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --skip-javascript --no-rc --skip-bootsnap" - else - "bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --no-rc --skip-bootsnap" - end + "bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --skip-javascript --no-rc --skip-bootsnap" end def configure_routes @@ -116,7 +112,7 @@ def add_rspec_to_project def add_rspec_rails_to_project! add_gem 'rspec-rails', rspec_rails_version - run_command_within_bundle!('bundle install --local --binstubs') if rails_gt_6_0? + run_command_within_bundle!('bundle install --local --binstubs') run_command_within_bundle!('rails g rspec:install') remove_from_file '.rspec', '--warnings' end diff --git a/spec/support/unit/helpers/action_pack_versions.rb b/spec/support/unit/helpers/action_pack_versions.rb deleted file mode 100644 index ef7d1dd25..000000000 --- a/spec/support/unit/helpers/action_pack_versions.rb +++ /dev/null @@ -1,18 +0,0 @@ -module UnitTests - module ActionPackVersions - extend self - - def self.configure_example_group(example_group) - example_group.include(self) - example_group.extend(self) - end - - def action_pack_gte_5? - action_pack_version >= 5 - end - - def action_pack_version - Tests::Version.new(ActionPack::VERSION::STRING) - end - end -end diff --git a/spec/support/unit/helpers/active_model_versions.rb b/spec/support/unit/helpers/active_model_versions.rb index b07633f6a..efdf7992e 100644 --- a/spec/support/unit/helpers/active_model_versions.rb +++ b/spec/support/unit/helpers/active_model_versions.rb @@ -8,33 +8,5 @@ def self.configure_example_group(example_group) def active_model_version Tests::Version.new(::ActiveModel::VERSION::STRING) end - - def active_model_3_1? - (::ActiveModel::VERSION::MAJOR == 3 && ::ActiveModel::VERSION::MINOR >= 1) || active_model_4_0? - end - - def active_model_3_2? - (::ActiveModel::VERSION::MAJOR == 3 && ::ActiveModel::VERSION::MINOR >= 2) || active_model_4_0? - end - - def active_model_4_0? - ::ActiveModel::VERSION::MAJOR == 4 - end - - def active_model_supports_absence_validation? - active_model_version >= 4 - end - - def active_model_supports_strict? - active_model_version >= 3.2 - end - - def active_model_supports_full_attributes_api? - active_model_version >= '5.2' - end - - def active_model_supports_custom_has_secure_password_attribute? - active_model_version >= '6.0' - end end end diff --git a/spec/support/unit/helpers/active_record_versions.rb b/spec/support/unit/helpers/active_record_versions.rb index 2350e49fc..c018b30fc 100644 --- a/spec/support/unit/helpers/active_record_versions.rb +++ b/spec/support/unit/helpers/active_record_versions.rb @@ -10,13 +10,5 @@ def self.configure_example_group(example_group) def active_record_version Tests::Version.new(::ActiveRecord::VERSION::STRING) end - - def active_record_supports_validate_presence_on_active_storage? - active_record_version >= '6.0.0.beta1' - end - - def active_record_supports_implicit_order_column? - active_record_version >= '6.0.0.beta1' - end end end diff --git a/spec/support/unit/helpers/model_builder.rb b/spec/support/unit/helpers/model_builder.rb index dffb637aa..e33c8c241 100644 --- a/spec/support/unit/helpers/model_builder.rb +++ b/spec/support/unit/helpers/model_builder.rb @@ -83,15 +83,8 @@ def define_model(name, columns = {}, options = {}, &block) private def clear_column_caches - # Rails 4.x - if ::ActiveRecord::Base.connection.respond_to?(:schema_cache) - DevelopmentRecord.connection.schema_cache.clear! - ProductionRecord.connection.schema_cache.clear! - # Rails 3.1 - 4.0 - elsif ::ActiveRecord::Base.connection_pool.respond_to?(:clear_cache!) - DevelopmentRecord.connection_pool.clear_cache! - ProductionRecord.connection_pool.clear_cache! - end + DevelopmentRecord.connection.schema_cache.clear! + ProductionRecord.connection.schema_cache.clear! end def drop_created_tables diff --git a/spec/support/unit/helpers/rails_versions.rb b/spec/support/unit/helpers/rails_versions.rb index 44ac3f59b..386daf14b 100644 --- a/spec/support/unit/helpers/rails_versions.rb +++ b/spec/support/unit/helpers/rails_versions.rb @@ -12,7 +12,7 @@ def rails_version end def rails_oldest_version_supported - 5.2 + 6.1 end end end diff --git a/spec/support/unit/rails_application.rb b/spec/support/unit/rails_application.rb index b370b87d9..22a65a4a8 100644 --- a/spec/support/unit/rails_application.rb +++ b/spec/support/unit/rails_application.rb @@ -27,7 +27,7 @@ def load load_environment add_active_storage_migration - add_action_text_migration if rails_version >= 6.0 + add_action_text_migration run_migrations end @@ -90,11 +90,7 @@ def rails_new end def rails_new_command - if rails_version >= 6.0 - "bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --skip-javascript --no-rc --skip-bootsnap" - else - "bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --no-rc --skip-bootsnap" - end + "bundle exec rails new #{fs.project_directory} --database=#{database.adapter_name} --skip-bundle --skip-javascript --no-rc --skip-bootsnap" end def fix_available_locales_warning diff --git a/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb b/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb index d711f1b0b..b62add043 100644 --- a/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb @@ -603,10 +603,6 @@ def build_context end def expect_to_have_made_controller_request(context:, verb:, action:, params:) - if action_pack_gte_5? - expect(context).to have_received(verb).with(action, params: params) - else - expect(context).to have_received(verb).with(action, params) - end + expect(context).to have_received(verb).with(action, params: params) end end diff --git a/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb b/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb index 929a9ce2f..d7c6556fb 100644 --- a/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb @@ -32,16 +32,6 @@ expect(matcher.description).to eq 'allow :baz to be ‹"foo"›' end - if active_model_3_2? - it 'describes itself with a strict validation' do - strict_matcher = allow_value('xyz').for(:attr).strict - - expect(strict_matcher.description).to eq( - 'allow :attr to be ‹"xyz"›, raising a validation exception on failure', - ) - end - end - it 'truncates the description when long' do matcher = allow_value('A' * 10000).for(:baz) @@ -559,45 +549,6 @@ end end - if active_model_3_2? - context 'an attribute with a strict format validation' do - context 'when qualified with strict' do - it 'rejects a bad value, providing the correct failure message' do - message = <<-MESSAGE.strip_heredoc -After setting :attr to ‹"xyz"›, the matcher expected the Example to be -valid, but it was invalid instead, raising a validation exception with -the message "Attr is invalid". - MESSAGE - - assertion = lambda do - expect(validating_format(with: /abc/, strict: true)). - to allow_value('xyz').for(:attr).strict - end - - expect(&assertion).to fail_with_message(message) - end - - context 'qualified with a custom message' do - it 'rejects a bad value when the failure messages do not match' do - message = <<-MESSAGE.strip_heredoc -After setting :attr to ‹"xyz"›, the matcher expected the Example to be -invalid and to raise a validation exception with message matching -‹/abc/›. The record was indeed invalid, but the exception message was -"Attr is invalid" instead. - MESSAGE - - assertion = lambda do - expect(validating_format(with: /abc/, strict: true)). - not_to allow_value('xyz').for(:attr).with_message(/abc/).strict - end - - expect(&assertion).to fail_with_message(message) - end - end - end - end - end - context 'when the attribute interferes with attempts to be set' do context 'when the attribute cannot be changed from nil to non-nil' do context 'and the record remains valid' do diff --git a/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb b/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb index 32ae832f1..b9dd4a319 100644 --- a/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb @@ -18,22 +18,20 @@ end end - if active_model_supports_custom_has_secure_password_attribute? - context 'when custom attribute is given to has_secure_password' do - it 'matches when the subject configures has_secure_password with correct options' do - working_model = define_model(:example, reset_password_digest: :string) { has_secure_password :reset_password } - expect(working_model.new).to have_secure_password :reset_password - end + context 'when custom attribute is given to has_secure_password' do + it 'matches when the subject configures has_secure_password with correct options' do + working_model = define_model(:example, reset_password_digest: :string) { has_secure_password :reset_password } + expect(working_model.new).to have_secure_password :reset_password + end - it 'does not match when the subject does not authenticate a password' do - no_secure_password = define_model(:example) - expect(no_secure_password.new).not_to have_secure_password :reset_password - end + it 'does not match when the subject does not authenticate a password' do + no_secure_password = define_model(:example) + expect(no_secure_password.new).not_to have_secure_password :reset_password + end - it 'does not match when the subject is missing the custom digest attribute' do - no_digest_column = define_model(:example) { has_secure_password :reset_password } - expect(no_digest_column.new).not_to have_secure_password :reset_password - end + it 'does not match when the subject is missing the custom digest attribute' do + no_digest_column = define_model(:example) { has_secure_password :reset_password } + expect(no_digest_column.new).not_to have_secure_password :reset_password end end end diff --git a/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb b/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb index aa6d259aa..b92aac012 100644 --- a/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb @@ -1,114 +1,113 @@ require 'unit_spec_helper' describe Shoulda::Matchers::ActiveModel::ValidateAbsenceOfMatcher, type: :model do - if active_model_supports_absence_validation? - def self.available_column_types - [ - :string, - :text, - :integer, - :float, - :decimal, - :datetime, - :timestamp, - :time, - :date, - :binary, - :uuid, - ] - end + def self.available_column_types + [ + :string, + :text, + :integer, + :float, + :decimal, + :datetime, + :timestamp, + :time, + :date, + :binary, + :uuid, + ] + end - context 'a model with an absence validation' do - it 'accepts' do - expect(validating_absence_of(:attr)).to validate_absence_of(:attr) - end + context 'a model with an absence validation' do + it 'accepts' do + expect(validating_absence_of(:attr)).to validate_absence_of(:attr) + end - it 'does not override the default message with a present' do - expect(validating_absence_of(:attr)).to validate_absence_of(:attr).with_message(nil) - end + it 'does not override the default message with a present' do + expect(validating_absence_of(:attr)).to validate_absence_of(:attr).with_message(nil) + end - available_column_types.each do |type| - context "when column is of type #{type}" do - it 'accepts' do - expect(validating_absence_of(:attr, {}, type: type)). - to validate_absence_of(:attr) - end + available_column_types.each do |type| + context "when column is of type #{type}" do + it 'accepts' do + expect(validating_absence_of(:attr, {}, type: type)). + to validate_absence_of(:attr) + end - it_supports( - 'ignoring_interference_by_writer', - tests: { - accept_if_qualified_but_changing_value_does_not_interfere: { - changing_values_with: :next_value, - }, + it_supports( + 'ignoring_interference_by_writer', + tests: { + accept_if_qualified_but_changing_value_does_not_interfere: { + changing_values_with: :next_value, }, - ) + }, + ) - define_method(:validation_matcher_scenario_args) do |*args| - super(*args).deep_merge(column_type: type) - end + define_method(:validation_matcher_scenario_args) do |*args| + super(*args).deep_merge(column_type: type) end end + end - if database_supports_array_columns? - context 'when the column backing the attribute is an array' do - context 'of varchar' do - it 'still works' do - record = validating_absence_of( - :attr, - {}, - type: :varchar, - options: { array: true, default: [], null: false }, - ) - - expect(record).to validate_absence_of(:attr) - end + if database_supports_array_columns? + context 'when the column backing the attribute is an array' do + context 'of varchar' do + it 'still works' do + record = validating_absence_of( + :attr, + {}, + type: :varchar, + options: { array: true, default: [], null: false }, + ) + + expect(record).to validate_absence_of(:attr) end + end - context 'of string' do - it 'still works' do - record = validating_absence_of( - :attr, - {}, - type: :string, - options: { array: true, default: [], null: false }, - ) - - expect(record).to validate_absence_of(:attr) - end + context 'of string' do + it 'still works' do + record = validating_absence_of( + :attr, + {}, + type: :string, + options: { array: true, default: [], null: false }, + ) + + expect(record).to validate_absence_of(:attr) end + end - context 'of a type other than string' do - it 'still works' do - record = validating_absence_of( - :possible_meeting_dates, - {}, - type: :date, - options: { array: true, default: [], null: false }, - ) - - expect(record).to validate_absence_of(:possible_meeting_dates) - end + context 'of a type other than string' do + it 'still works' do + record = validating_absence_of( + :possible_meeting_dates, + {}, + type: :date, + options: { array: true, default: [], null: false }, + ) + + expect(record).to validate_absence_of(:possible_meeting_dates) end end end + end - context 'when the column backing the attribute is an enum' do - it 'still works' do - model = define_model_validating_absence_of(:attr) - model.enum attr: %w[one two three] + context 'when the column backing the attribute is an enum' do + it 'still works' do + model = define_model_validating_absence_of(:attr) + model.enum attr: %w[one two three] - expect(model.new).to validate_absence_of(:attr) - end + expect(model.new).to validate_absence_of(:attr) end + end - context 'when used in the negative' do - it 'fails' do - assertion = lambda do - expect(validating_absence_of(:attr)). - not_to validate_absence_of(:attr) - end + context 'when used in the negative' do + it 'fails' do + assertion = lambda do + expect(validating_absence_of(:attr)). + not_to validate_absence_of(:attr) + end - message = <<-MESSAGE + message = <<-MESSAGE Expected Example not to validate that :attr is empty/falsy, but this could not be proved. After setting :attr to ‹"an arbitrary value"›, the matcher expected @@ -116,228 +115,227 @@ def self.available_column_types validation errors: * attr: ["must be blank"] - MESSAGE + MESSAGE - expect(&assertion).to fail_with_message(message) - end + expect(&assertion).to fail_with_message(message) end + end - def validation_matcher_scenario_args - super.deep_merge(model_creator: :active_record) - end + def validation_matcher_scenario_args + super.deep_merge(model_creator: :active_record) end + end - context 'a model without an absence validation' do - it 'rejects with the correct failure message' do - record = define_model(:example, attr: :string).new + context 'a model without an absence validation' do + it 'rejects with the correct failure message' do + record = define_model(:example, attr: :string).new - message = <<-MESSAGE + message = <<-MESSAGE Expected Example to validate that :attr is empty/falsy, but this could not be proved. After setting :attr to ‹"an arbitrary value"›, the matcher expected the Example to be invalid, but it was valid instead. - MESSAGE + MESSAGE - assertion = lambda do - expect(record).to validate_absence_of(:attr) - end - - expect(&assertion).to fail_with_message(message) + assertion = lambda do + expect(record).to validate_absence_of(:attr) end + + expect(&assertion).to fail_with_message(message) end + end - context 'an ActiveModel class with an absence validation' do - it 'accepts' do - expect(active_model_validating_absence_of(:attr)).to validate_absence_of(:attr) - end + context 'an ActiveModel class with an absence validation' do + it 'accepts' do + expect(active_model_validating_absence_of(:attr)).to validate_absence_of(:attr) + end - it 'does not override the default message with a blank' do - expect(active_model_validating_absence_of(:attr)).to validate_absence_of(:attr).with_message(nil) - end + it 'does not override the default message with a blank' do + expect(active_model_validating_absence_of(:attr)).to validate_absence_of(:attr).with_message(nil) + end - it_supports( - 'ignoring_interference_by_writer', - tests: { - accept_if_qualified_but_changing_value_does_not_interfere: { - changing_values_with: :upcase, - }, + it_supports( + 'ignoring_interference_by_writer', + tests: { + accept_if_qualified_but_changing_value_does_not_interfere: { + changing_values_with: :upcase, }, - ) + }, + ) - def validation_matcher_scenario_args - super.deep_merge(model_creator: :active_model) - end + def validation_matcher_scenario_args + super.deep_merge(model_creator: :active_model) end + end - context 'an ActiveModel class without an absence validation' do - it 'rejects with the correct failure message' do - message = <<-MESSAGE + context 'an ActiveModel class without an absence validation' do + it 'rejects with the correct failure message' do + message = <<-MESSAGE Expected Example to validate that :attr is empty/falsy, but this could not be proved. After setting :attr to ‹"an arbitrary value"›, the matcher expected the Example to be invalid, but it was valid instead. - MESSAGE - - assertion = lambda do - expect(active_model_with(:attr)).to validate_absence_of(:attr) - end + MESSAGE - expect(&assertion).to fail_with_message(message) + assertion = lambda do + expect(active_model_with(:attr)).to validate_absence_of(:attr) end + + expect(&assertion).to fail_with_message(message) end + end - context 'a has_many association with an absence validation' do - it 'requires the attribute to not be set' do - expect(having_many(:children, absence: true)).to validate_absence_of(:children) - end + context 'a has_many association with an absence validation' do + it 'requires the attribute to not be set' do + expect(having_many(:children, absence: true)).to validate_absence_of(:children) + end - it_supports( - 'ignoring_interference_by_writer', - tests: { - accept_if_qualified_but_changing_value_does_not_interfere: { - changing_values_with: :next_value, - }, + it_supports( + 'ignoring_interference_by_writer', + tests: { + accept_if_qualified_but_changing_value_does_not_interfere: { + changing_values_with: :next_value, }, - ) + }, + ) - def validation_matcher_scenario_args - super.deep_merge(model_creator: :"active_record/has_many") - end + def validation_matcher_scenario_args + super.deep_merge(model_creator: :"active_record/has_many") end + end - context 'a has_many association without an absence validation' do - it 'does not require the attribute to not be set' do - expect(having_many(:children, absence: false)). - not_to validate_absence_of(:children) - end + context 'a has_many association without an absence validation' do + it 'does not require the attribute to not be set' do + expect(having_many(:children, absence: false)). + not_to validate_absence_of(:children) end + end - context 'an absent has_and_belongs_to_many association' do - it 'accepts' do - model = having_and_belonging_to_many(:children, absence: true) - expect(model).to validate_absence_of(:children) - end + context 'an absent has_and_belongs_to_many association' do + it 'accepts' do + model = having_and_belonging_to_many(:children, absence: true) + expect(model).to validate_absence_of(:children) + end - it_supports( - 'ignoring_interference_by_writer', - tests: { - accept_if_qualified_but_changing_value_does_not_interfere: { - changing_values_with: :next_value, - }, + it_supports( + 'ignoring_interference_by_writer', + tests: { + accept_if_qualified_but_changing_value_does_not_interfere: { + changing_values_with: :next_value, }, - ) + }, + ) - def validation_matcher_scenario_args - super.deep_merge(model_creator: :"active_record/habtm") - end + def validation_matcher_scenario_args + super.deep_merge(model_creator: :"active_record/habtm") end + end - context 'a non-absent has_and_belongs_to_many association' do - it 'rejects with the correct failure message' do - model = having_and_belonging_to_many(:children, absence: false) + context 'a non-absent has_and_belongs_to_many association' do + it 'rejects with the correct failure message' do + model = having_and_belonging_to_many(:children, absence: false) - message = <<-MESSAGE + message = <<-MESSAGE Expected Parent to validate that :children is empty/falsy, but this could not be proved. After setting :children to ‹[#]›, the matcher expected the Parent to be invalid, but it was valid instead. - MESSAGE - - assertion = lambda do - expect(model).to validate_absence_of(:children) - end + MESSAGE - expect(&assertion).to fail_with_message(message) + assertion = lambda do + expect(model).to validate_absence_of(:children) end + + expect(&assertion).to fail_with_message(message) end + end - context 'an i18n translation containing %{attribute} and %{model}' do - after { I18n.backend.reload! } + context 'an i18n translation containing %{attribute} and %{model}' do + after { I18n.backend.reload! } - it 'does not raise an exception' do - stub_translation('activerecord.errors.messages.present', - '%{attribute} must be blank in a %{model}',) + it 'does not raise an exception' do + stub_translation('activerecord.errors.messages.present', + '%{attribute} must be blank in a %{model}',) - expect { - expect(validating_absence_of(:attr)).to validate_absence_of(:attr) - }.to_not raise_exception - end + expect { + expect(validating_absence_of(:attr)).to validate_absence_of(:attr) + }.to_not raise_exception end + end - context 'an attribute with a context-dependent validation' do - context 'without the validation context' do - it 'does not match' do - expect(validating_absence_of(:attr, on: :customisable)).not_to validate_absence_of(:attr) - end + context 'an attribute with a context-dependent validation' do + context 'without the validation context' do + it 'does not match' do + expect(validating_absence_of(:attr, on: :customisable)).not_to validate_absence_of(:attr) end + end - context 'with the validation context' do - it 'matches' do - expect(validating_absence_of(:attr, on: :customisable)).to validate_absence_of(:attr).on(:customisable) - end + context 'with the validation context' do + it 'matches' do + expect(validating_absence_of(:attr, on: :customisable)).to validate_absence_of(:attr).on(:customisable) end end + end - def define_model_validating_absence_of(attr, validation_options = {}, given_column_options = {}) - default_column_options = { type: :string, options: {} } - column_options = default_column_options.merge(given_column_options) + def define_model_validating_absence_of(attr, validation_options = {}, given_column_options = {}) + default_column_options = { type: :string, options: {} } + column_options = default_column_options.merge(given_column_options) - define_model :example, attr => column_options do |model| - model.validates_absence_of(attr, validation_options) + define_model :example, attr => column_options do |model| + model.validates_absence_of(attr, validation_options) - if block_given? - yield model - end + if block_given? + yield model end end + end - def validating_absence_of(attr, validation_options = {}, given_column_options = {}) - model = define_model_validating_absence_of( - attr, - validation_options, - given_column_options, - ) - model.new - end - alias_method :build_record_validating_absence_of, :validating_absence_of + def validating_absence_of(attr, validation_options = {}, given_column_options = {}) + model = define_model_validating_absence_of( + attr, + validation_options, + given_column_options, + ) + model.new + end + alias_method :build_record_validating_absence_of, :validating_absence_of - def active_model_with(attr, &block) - define_active_model_class('Example', accessors: [attr], &block).new + def active_model_with(attr, &block) + define_active_model_class('Example', accessors: [attr], &block).new + end + + def active_model_validating_absence_of(attr) + active_model_with(attr) do + validates_absence_of attr end + end - def active_model_validating_absence_of(attr) - active_model_with(attr) do - validates_absence_of attr + def having_many(plural_name, options = {}) + define_model plural_name.to_s.singularize + define_model :parent do + has_many plural_name + if options[:absence] + validates_absence_of plural_name end - end + end.new + end - def having_many(plural_name, options = {}) - define_model plural_name.to_s.singularize - define_model :parent do - has_many plural_name - if options[:absence] - validates_absence_of plural_name - end - end.new + def having_and_belonging_to_many(plural_name, options = {}) + create_table 'children_parents', id: false do |t| + t.integer "#{plural_name.to_s.singularize}_id" + t.integer :parent_id end - def having_and_belonging_to_many(plural_name, options = {}) - create_table 'children_parents', id: false do |t| - t.integer "#{plural_name.to_s.singularize}_id" - t.integer :parent_id + define_model plural_name.to_s.singularize + define_model :parent do + has_and_belongs_to_many plural_name + if options[:absence] + validates_absence_of plural_name end + end.new + end - define_model plural_name.to_s.singularize - define_model :parent do - has_and_belongs_to_many plural_name - if options[:absence] - validates_absence_of plural_name - end - end.new - end - - def validation_matcher_scenario_args - super.deep_merge(matcher_name: :validate_absence_of) - end + def validation_matcher_scenario_args + super.deep_merge(matcher_name: :validate_absence_of) end end diff --git a/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb b/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb index e237a412b..512a610fa 100644 --- a/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb @@ -519,51 +519,6 @@ def configure_validation_matcher(matcher) it_behaves_like 'it supports with_message', valid_values: possible_values - if active_model_3_2? - context '+ strict' do - context 'when the validation specifies strict' do - it 'matches when the given values match the valid values' do - builder = build_object_allowing( - possible_values, - validation_options: { strict: true }, - ) - - # rubocop:disable Style/SymbolProc - expect_to_match_on_values(builder, possible_values) do |matcher| - matcher.strict - end - # rubocop:enable Style/SymbolProc - end - - it 'does not match when the given values do not match the valid values' do - builder = build_object_allowing( - possible_values, - validation_options: { strict: true }, - ) - - values = add_outside_value_to(possible_values) - # rubocop:disable Style/SymbolProc - expect_not_to_match_on_values(builder, values) do |matcher| - matcher.strict - end - # rubocop:enable Style/SymbolProc - end - end - - context 'when the validation does not specify strict' do - it 'does not match' do - builder = build_object_allowing(possible_values) - - # rubocop:disable Style/SymbolProc - expect_not_to_match_on_values(builder, possible_values) do |matcher| - matcher.strict - end - # rubocop:enable Style/SymbolProc - end - end - end - end - def expect_to_match_on_values(builder, values, &block) expect_to_match_in_array(builder, values, &block) end @@ -675,51 +630,6 @@ def configure_validation_matcher(matcher) it_behaves_like 'it supports with_message', valid_values: possible_values - if active_model_3_2? - context '+ strict' do - context 'when the validation specifies strict' do - it 'matches when the given range matches the range in the validation' do - builder = build_object_allowing( - possible_values, - validation_options: { strict: true }, - ) - - # rubocop:disable Style/SymbolProc - expect_to_match_on_values(builder, possible_values) do |matcher| - matcher.strict - end - # rubocop:enable Style/SymbolProc - end - - it 'matches when the given range does not match the range in the validation' do - builder = build_object_allowing( - possible_values, - validation_options: { strict: true }, - ) - - range = Range.new(possible_values.first, possible_values.last + 1) - # rubocop:disable Style/SymbolProc - expect_not_to_match_on_values(builder, range) do |matcher| - matcher.strict - end - # rubocop:enable Style/SymbolProc - end - end - - context 'when the validation does not specify strict' do - it 'does not match' do - builder = build_object_allowing(possible_values) - - # rubocop:disable Style/SymbolProc - expect_not_to_match_on_values(builder, possible_values) do |matcher| - matcher.strict - end - # rubocop:enable Style/SymbolProc - end - end - end - end - def expect_to_match_on_values(builder, range, &block) expect_to_match_in_range(builder, range, &block) end diff --git a/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb b/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb index a54c029b2..a416b60d9 100644 --- a/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb @@ -222,17 +222,10 @@ expect(record).to matcher end - blank_value = - if active_model_supports_full_attributes_api? - '' - else - nil - end - message = <<-MESSAGE Expected Example to validate that :attr cannot be empty/falsy, but this could not be proved. - After setting :attr to ‹#{blank_value.inspect}›, the matcher expected the Example to be + After setting :attr to ‹""›, the matcher expected the Example to be invalid, but it was valid instead. MESSAGE @@ -276,48 +269,46 @@ }, ) - if active_model_supports_full_attributes_api? - context 'when the attribute has been configured with a type' do - context 'and it is a string' do - it 'works' do - record = active_model_object_validating_presence_of(:age) do - attribute :age, :string - end - - expect(record).to validate_presence_of(:age) + context 'when the attribute has been configured with a type' do + context 'and it is a string' do + it 'works' do + record = active_model_object_validating_presence_of(:age) do + attribute :age, :string end - end - context 'and it is not a string' do - it 'still works' do - record = active_model_object_validating_presence_of(:age) do - attribute :age, :time - end + expect(record).to validate_presence_of(:age) + end + end - expect(record).to validate_presence_of(:age) + context 'and it is not a string' do + it 'still works' do + record = active_model_object_validating_presence_of(:age) do + attribute :age, :time end + + expect(record).to validate_presence_of(:age) end end + end - context 'when the attribute has not been configured with a type' do - context 'and it is assumed to be something other than a string' do - it 'still works' do - record = active_model_object_validating_presence_of(:user) do - attribute :user + context 'when the attribute has not been configured with a type' do + context 'and it is assumed to be something other than a string' do + it 'still works' do + record = active_model_object_validating_presence_of(:user) do + attribute :user - validate :validate_user_has_email, if: :user + validate :validate_user_has_email, if: :user - private + private - def validate_user_has_email - if !user.email - errors.add(:base, 'user does not have an email') - end + def validate_user_has_email + if !user.email + errors.add(:base, 'user does not have an email') end end - - expect(record).to validate_presence_of(:user) end + + expect(record).to validate_presence_of(:user) end end end @@ -346,23 +337,22 @@ def model_creator end end - if active_record_supports_validate_presence_on_active_storage? - context 'a has_one_attached association with a presence validation' do - it 'requires the attribute to be set' do - expect(has_one_attached_child(presence: true)).to validate_presence_of(:child) - end + context 'a has_one_attached association with a presence validation' do + it 'requires the attribute to be set' do + expect(has_one_attached_child(presence: true)).to validate_presence_of(:child) + end - it_supports( - 'ignoring_interference_by_writer', - tests: { - accept_if_qualified_but_changing_value_does_not_interfere: { - changing_values_with: :nil_to_blank, - }, - reject_if_qualified_but_changing_value_interferes: { - model_name: 'Example', - attribute_name: :attr, - changing_values_with: :never_falsy, - expected_message: <<-MESSAGE, + it_supports( + 'ignoring_interference_by_writer', + tests: { + accept_if_qualified_but_changing_value_does_not_interfere: { + changing_values_with: :nil_to_blank, + }, + reject_if_qualified_but_changing_value_interferes: { + model_name: 'Example', + attribute_name: :attr, + changing_values_with: :never_falsy, + expected_message: <<-MESSAGE, Expected Example to validate that :attr cannot be empty/falsy, but this could not be proved. After setting :attr to ‹nil› -- which was read back as ‹"dummy value"› @@ -374,35 +364,35 @@ def model_creator this test is failing. If you've overridden the writer method for this attribute, then you may need to change it to make this test pass, or do something else entirely. - MESSAGE - }, + MESSAGE }, - ) - end + }, + ) + end - context 'a has_one_attached association without a presence validation' do - it 'requires the attribute to be set' do - expect(has_one_attached_child(presence: false)). - not_to validate_presence_of(:child) - end + context 'a has_one_attached association without a presence validation' do + it 'requires the attribute to be set' do + expect(has_one_attached_child(presence: false)). + not_to validate_presence_of(:child) end + end - context 'a has_many_attached association with a presence validation' do - it 'requires the attribute to be set' do - expect(has_many_attached_children(presence: true)).to validate_presence_of(:children) - end + context 'a has_many_attached association with a presence validation' do + it 'requires the attribute to be set' do + expect(has_many_attached_children(presence: true)).to validate_presence_of(:children) + end - it_supports( - 'ignoring_interference_by_writer', - tests: { - accept_if_qualified_but_changing_value_does_not_interfere: { - changing_values_with: :nil_to_blank, - }, - reject_if_qualified_but_changing_value_interferes: { - model_name: 'Example', - attribute_name: :attr, - changing_values_with: :never_falsy, - expected_message: <<-MESSAGE, + it_supports( + 'ignoring_interference_by_writer', + tests: { + accept_if_qualified_but_changing_value_does_not_interfere: { + changing_values_with: :nil_to_blank, + }, + reject_if_qualified_but_changing_value_interferes: { + model_name: 'Example', + attribute_name: :attr, + changing_values_with: :never_falsy, + expected_message: <<-MESSAGE, Expected Example to validate that :attr cannot be empty/falsy, but this could not be proved. After setting :attr to ‹nil› -- which was read back as ‹"dummy value"› @@ -414,17 +404,16 @@ def model_creator this test is failing. If you've overridden the writer method for this attribute, then you may need to change it to make this test pass, or do something else entirely. - MESSAGE - }, + MESSAGE }, - ) - end + }, + ) + end - context 'a has_many_attached association without a presence validation' do - it 'does not require the attribute to be set' do - expect(has_many_attached_children(presence: false)). - not_to validate_presence_of(:children) - end + context 'a has_many_attached association without a presence validation' do + it 'does not require the attribute to be set' do + expect(has_many_attached_children(presence: false)). + not_to validate_presence_of(:children) end end @@ -872,17 +861,10 @@ def record_belonging_to( expect(validating_presence(strict: false)).to matcher.strict end - blank_value = - if active_model_supports_full_attributes_api? - '' - else - nil - end - message = <<-MESSAGE Expected Example to validate that :attr cannot be empty/falsy, raising a validation exception on failure, but this could not be proved. - After setting :attr to ‹#{blank_value.inspect}›, the matcher expected the Example to be + After setting :attr to ‹""›, the matcher expected the Example to be invalid and to raise a validation exception, but the record produced validation errors instead. MESSAGE @@ -959,23 +941,14 @@ def foo=(_value) assertion = -> { expect(record).not_to matcher.allow_nil } - if active_model_supports_full_attributes_api? - expect(&assertion).to fail_with_message(<<-MESSAGE) + expect(&assertion).to fail_with_message(<<-MESSAGE) Expected Example not to validate that :attr cannot be empty/falsy, but this could not be proved. After setting :attr to ‹""›, the matcher expected the Example to be valid, but it was invalid instead, producing these validation errors: * attr: ["can't be blank"] - MESSAGE - else - expect(&assertion).to fail_with_message(<<-MESSAGE) -Expected Example not to validate that :attr cannot be empty/falsy, but -this could not be proved. - After setting :attr to ‹nil›, the matcher expected the Example to be - invalid, but it was valid instead. - MESSAGE - end + MESSAGE end end @@ -1008,52 +981,27 @@ def foo=(_value) end context 'when validating a model without a presence validator' do - if active_model_supports_full_attributes_api? - it 'does not match in the positive' do - record = without_validating_presence + it 'does not match in the positive' do + record = without_validating_presence - assertion = lambda do - expect(record).to matcher.allow_nil - end + assertion = lambda do + expect(record).to matcher.allow_nil + end - message = <<-MESSAGE + message = <<-MESSAGE Expected Example to validate that :attr cannot be empty/falsy, but this could not be proved. After setting :attr to ‹""›, the matcher expected the Example to be invalid, but it was valid instead. - MESSAGE - - expect(&assertion).to fail_with_message(message) - end - - it 'matches in the negative' do - record = without_validating_presence - - expect(record).not_to matcher.allow_nil - end - else - it 'matches in the positive' do - record = without_validating_presence - - expect(record).to matcher.allow_nil - end - - it 'does not match in the negative' do - record = without_validating_presence + MESSAGE - assertion = lambda do - expect(record).not_to matcher.allow_nil - end + expect(&assertion).to fail_with_message(message) + end - message = <<-MESSAGE -Expected Example not to validate that :attr cannot be empty/falsy, but -this could not be proved. - After setting :attr to ‹nil›, the matcher expected the Example to be - invalid, but it was valid instead. - MESSAGE + it 'matches in the negative' do + record = without_validating_presence - expect(&assertion).to fail_with_message(message) - end + expect(record).not_to matcher.allow_nil end end end diff --git a/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb b/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb index 8e4190aeb..e027e8d51 100644 --- a/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb @@ -948,10 +948,7 @@ def build_record_with_enum_attribute( if rails_version >= 7.0 model.enum(enum_name, values, prefix: prefix, suffix: suffix) else - if rails_version =~ '~> 6.0' - params.merge!(_scopes: scopes) - end - + params.merge!(_scopes: scopes) model.enum(params) end diff --git a/spec/unit/shoulda/matchers/active_record/have_implicit_order_column_spec.rb b/spec/unit/shoulda/matchers/active_record/have_implicit_order_column_spec.rb index 51c88c00d..8408b14f1 100644 --- a/spec/unit/shoulda/matchers/active_record/have_implicit_order_column_spec.rb +++ b/spec/unit/shoulda/matchers/active_record/have_implicit_order_column_spec.rb @@ -1,173 +1,171 @@ require 'unit_spec_helper' describe Shoulda::Matchers::ActiveRecord::HaveImplicitOrderColumnMatcher, type: :model do - if active_record_supports_implicit_order_column? - context 'when the given column exists' do - context 'when an implicit_order_column is set on the model' do - context 'and it matches the given column name' do - context 'and the column name is a symbol' do - it 'matches' do - record = record_with_implicit_order_column_on( - :created_at, - class_name: 'Employee', - columns: [:created_at], - ) - - expect { have_implicit_order_column(:created_at) }. - to match_against(record). - or_fail_with(<<~MESSAGE, wrap: true) - Expected Employee not to have an implicit_order_column of - :created_at, but it did. - MESSAGE - end - end + context 'when the given column exists' do + context 'when an implicit_order_column is set on the model' do + context 'and it matches the given column name' do + context 'and the column name is a symbol' do + it 'matches' do + record = record_with_implicit_order_column_on( + :created_at, + class_name: 'Employee', + columns: [:created_at], + ) - context 'and the column name is a string' do - it 'matches' do - record = record_with_implicit_order_column_on( - :created_at, - class_name: 'Employee', - columns: [:created_at], - ) - - expect { have_implicit_order_column('created_at') }. - to match_against(record). - or_fail_with(<<~MESSAGE, wrap: true) - Expected Employee not to have an implicit_order_column of - :created_at, but it did. - MESSAGE - end + expect { have_implicit_order_column(:created_at) }. + to match_against(record). + or_fail_with(<<~MESSAGE, wrap: true) + Expected Employee not to have an implicit_order_column of + :created_at, but it did. + MESSAGE end end - context 'and it does not match the given column name' do - context 'and the column name is a symbol' do - it 'does not match, producing an appropriate message' do - record = record_with_implicit_order_column_on( - :created_at, - class_name: 'Employee', - columns: [:created_at, :email], - ) - - expect { have_implicit_order_column(:email) }. - not_to match_against(record). - and_fail_with(<<-MESSAGE, wrap: true) - Expected Employee to have an implicit_order_column of :email, - but it is :created_at. - MESSAGE - end - end + context 'and the column name is a string' do + it 'matches' do + record = record_with_implicit_order_column_on( + :created_at, + class_name: 'Employee', + columns: [:created_at], + ) - context 'and the column name is a string' do - it 'does not match, producing an appropriate message' do - record = record_with_implicit_order_column_on( - :created_at, - class_name: 'Employee', - columns: [:created_at, :email], - ) - - expect { have_implicit_order_column('email') }. - not_to match_against(record). - and_fail_with(<<-MESSAGE, wrap: true) - Expected Employee to have an implicit_order_column of :email, - but it is :created_at. - MESSAGE - end + expect { have_implicit_order_column('created_at') }. + to match_against(record). + or_fail_with(<<~MESSAGE, wrap: true) + Expected Employee not to have an implicit_order_column of + :created_at, but it did. + MESSAGE end end end - context 'when no implicit_order_column is set on the model' do - context 'and the given column name is a symbol' do + context 'and it does not match the given column name' do + context 'and the column name is a symbol' do it 'does not match, producing an appropriate message' do - record = record_without_implicit_order_column( + record = record_with_implicit_order_column_on( + :created_at, class_name: 'Employee', - columns: [:created_at], + columns: [:created_at, :email], ) - expect { have_implicit_order_column(:created_at) }. + expect { have_implicit_order_column(:email) }. not_to match_against(record). and_fail_with(<<-MESSAGE, wrap: true) - Expected Employee to have an implicit_order_column of - :created_at, but implicit_order_column is not set. + Expected Employee to have an implicit_order_column of :email, + but it is :created_at. MESSAGE end end - context 'and the given column name is a string' do + context 'and the column name is a string' do it 'does not match, producing an appropriate message' do - record = record_without_implicit_order_column( + record = record_with_implicit_order_column_on( + :created_at, class_name: 'Employee', - columns: [:created_at], + columns: [:created_at, :email], ) - expect { have_implicit_order_column('created_at') }. + expect { have_implicit_order_column('email') }. not_to match_against(record). and_fail_with(<<-MESSAGE, wrap: true) - Expected Employee to have an implicit_order_column of - :created_at, but implicit_order_column is not set. + Expected Employee to have an implicit_order_column of :email, + but it is :created_at. MESSAGE end end end end - context 'when the given column does not exist' do - context 'and it is a symbol' do + context 'when no implicit_order_column is set on the model' do + context 'and the given column name is a symbol' do it 'does not match, producing an appropriate message' do - record = record_without_any_columns(class_name: 'Employee') + record = record_without_implicit_order_column( + class_name: 'Employee', + columns: [:created_at], + ) - expect { have_implicit_order_column(:whatever) }. + expect { have_implicit_order_column(:created_at) }. not_to match_against(record). and_fail_with(<<-MESSAGE, wrap: true) - Expected Employee to have an implicit_order_column of :whatever, - but that could not be proved: The :employees table does not have a - :whatever column. + Expected Employee to have an implicit_order_column of + :created_at, but implicit_order_column is not set. MESSAGE end end - context 'and it is a string' do + context 'and the given column name is a string' do it 'does not match, producing an appropriate message' do - record = record_without_any_columns(class_name: 'Employee') + record = record_without_implicit_order_column( + class_name: 'Employee', + columns: [:created_at], + ) - expect { have_implicit_order_column('whatever') }. + expect { have_implicit_order_column('created_at') }. not_to match_against(record). and_fail_with(<<-MESSAGE, wrap: true) - Expected Employee to have an implicit_order_column of :whatever, - but that could not be proved: The :employees table does not have a - :whatever column. + Expected Employee to have an implicit_order_column of + :created_at, but implicit_order_column is not set. MESSAGE end end end + end - describe '#description' do - it 'returns the correct description' do - matcher = have_implicit_order_column(:created_at) - - expect(matcher.description).to eq( - 'have an implicit_order_column of :created_at', - ) + context 'when the given column does not exist' do + context 'and it is a symbol' do + it 'does not match, producing an appropriate message' do + record = record_without_any_columns(class_name: 'Employee') + + expect { have_implicit_order_column(:whatever) }. + not_to match_against(record). + and_fail_with(<<-MESSAGE, wrap: true) + Expected Employee to have an implicit_order_column of :whatever, + but that could not be proved: The :employees table does not have a + :whatever column. + MESSAGE end end - def record_with_implicit_order_column_on( - column_name, - class_name:, - columns: { column_name => :string } - ) - define_model_instance(class_name, columns) do |model| - model.implicit_order_column = column_name + context 'and it is a string' do + it 'does not match, producing an appropriate message' do + record = record_without_any_columns(class_name: 'Employee') + + expect { have_implicit_order_column('whatever') }. + not_to match_against(record). + and_fail_with(<<-MESSAGE, wrap: true) + Expected Employee to have an implicit_order_column of :whatever, + but that could not be proved: The :employees table does not have a + :whatever column. + MESSAGE end end + end - def record_without_implicit_order_column(class_name:, columns:) - define_model_instance(class_name, columns) + describe '#description' do + it 'returns the correct description' do + matcher = have_implicit_order_column(:created_at) + + expect(matcher.description).to eq( + 'have an implicit_order_column of :created_at', + ) end + end - def record_without_any_columns(class_name:) - define_model_instance(class_name) + def record_with_implicit_order_column_on( + column_name, + class_name:, + columns: { column_name => :string } + ) + define_model_instance(class_name, columns) do |model| + model.implicit_order_column = column_name end end + + def record_without_implicit_order_column(class_name:, columns:) + define_model_instance(class_name, columns) + end + + def record_without_any_columns(class_name:) + define_model_instance(class_name) + end end diff --git a/spec/unit_spec_helper.rb b/spec/unit_spec_helper.rb index 18a01c23f..968f8c497 100644 --- a/spec/unit_spec_helper.rb +++ b/spec/unit_spec_helper.rb @@ -15,7 +15,6 @@ RSpec.configure do |config| config.include RSpec::Matchers::FailMatchers - UnitTests::ActionPackVersions.configure_example_group(config) UnitTests::ActiveModelHelpers.configure_example_group(config) UnitTests::ActiveModelVersions.configure_example_group(config) UnitTests::ClassBuilder.configure_example_group(config)