From e1dd3d554eb746cf070a9adc534591d4199dddfd Mon Sep 17 00:00:00 2001 From: Mth0158 Date: Fri, 24 Nov 2023 16:17:03 +0100 Subject: [PATCH] [Validator] Refacto the size_validator tests --- .../aspect_ratio/validator/with_message.rb | 15 + .../models/attached/validator/with_message.rb | 15 + .../content_type/validator/with_message.rb | 15 + .../dimension/validator/with_message.rb | 15 + .../models/limit/validator/with_message.rb | 15 + .../validator/with_message.rb | 15 + test/dummy/app/models/size/portfolio.rb | 43 -- .../app/models/size/several_validator.rb | 19 - .../app/models/size/several_validator_proc.rb | 19 - test/dummy/app/models/size/validator/check.rb | 37 ++ .../app/models/size/validator/with_message.rb | 15 + test/dummy/app/models/size/zero_validator.rb | 19 - .../app/models/size/zero_validator_proc.rb | 19 - test/dummy/db/schema.rb | 37 +- ...ith_all_rails_common_validation_options.rb | 3 +- .../works_with_message_option.rb | 46 ++ test/validators/size_validator_test.rb | 459 +++++++++--------- test/validators/support/validator_helpers.rb | 17 + 18 files changed, 438 insertions(+), 385 deletions(-) create mode 100644 test/dummy/app/models/aspect_ratio/validator/with_message.rb create mode 100644 test/dummy/app/models/attached/validator/with_message.rb create mode 100644 test/dummy/app/models/content_type/validator/with_message.rb create mode 100644 test/dummy/app/models/dimension/validator/with_message.rb create mode 100644 test/dummy/app/models/limit/validator/with_message.rb create mode 100644 test/dummy/app/models/processable_image/validator/with_message.rb delete mode 100644 test/dummy/app/models/size/portfolio.rb delete mode 100644 test/dummy/app/models/size/several_validator.rb delete mode 100644 test/dummy/app/models/size/several_validator_proc.rb create mode 100644 test/dummy/app/models/size/validator/check.rb create mode 100644 test/dummy/app/models/size/validator/with_message.rb delete mode 100644 test/dummy/app/models/size/zero_validator.rb delete mode 100644 test/dummy/app/models/size/zero_validator_proc.rb create mode 100644 test/validators/shared_examples/works_with_message_option.rb diff --git a/test/dummy/app/models/aspect_ratio/validator/with_message.rb b/test/dummy/app/models/aspect_ratio/validator/with_message.rb new file mode 100644 index 00000000..c7a8b861 --- /dev/null +++ b/test/dummy/app/models/aspect_ratio/validator/with_message.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: aspect_ratio_validator_with_messages +# +# id :integer not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# + +class AspectRatio::Validator::WithMessage < ApplicationRecord + has_one_attached :with_message + validates :with_message, aspect_ratio: { with: :square , message: 'Custom message' } +end diff --git a/test/dummy/app/models/attached/validator/with_message.rb b/test/dummy/app/models/attached/validator/with_message.rb new file mode 100644 index 00000000..25c05aad --- /dev/null +++ b/test/dummy/app/models/attached/validator/with_message.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: attached_validator_with_messages +# +# id :integer not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# + +class Attached::Validator::WithMessage < ApplicationRecord + has_one_attached :with_message + validates :with_message, attached: { message: 'Custom message' } +end diff --git a/test/dummy/app/models/content_type/validator/with_message.rb b/test/dummy/app/models/content_type/validator/with_message.rb new file mode 100644 index 00000000..fb5a0680 --- /dev/null +++ b/test/dummy/app/models/content_type/validator/with_message.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: content_type_validator_with_messages +# +# id :integer not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# + +class ContentType::Validator::WithMessage < ApplicationRecord + has_one_attached :with_message + validates :with_message, content_type: { with: :webp, message: 'Custom message' } +end diff --git a/test/dummy/app/models/dimension/validator/with_message.rb b/test/dummy/app/models/dimension/validator/with_message.rb new file mode 100644 index 00000000..b7d58709 --- /dev/null +++ b/test/dummy/app/models/dimension/validator/with_message.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: dimension_validator_with_messages +# +# id :integer not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# + +class Dimension::Validator::WithMessage < ApplicationRecord + has_one_attached :with_message + validates :with_message, dimension: { width: 150, height: 150, message: 'Custom message' } +end diff --git a/test/dummy/app/models/limit/validator/with_message.rb b/test/dummy/app/models/limit/validator/with_message.rb new file mode 100644 index 00000000..2591fa17 --- /dev/null +++ b/test/dummy/app/models/limit/validator/with_message.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: limit_validator_with_messages +# +# id :integer not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# + +class Limit::Validator::WithMessage < ApplicationRecord + has_one_attached :with_message + validates :with_message, limit: { max: 0, message: 'Custom message' } +end diff --git a/test/dummy/app/models/processable_image/validator/with_message.rb b/test/dummy/app/models/processable_image/validator/with_message.rb new file mode 100644 index 00000000..4f00d93f --- /dev/null +++ b/test/dummy/app/models/processable_image/validator/with_message.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: processable_image_validator_with_messages +# +# id :integer not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# + +class ProcessableImage::Validator::WithMessage < ApplicationRecord + has_one_attached :with_message + validates :with_message, processable_image: { message: 'Custom message' } +end diff --git a/test/dummy/app/models/size/portfolio.rb b/test/dummy/app/models/size/portfolio.rb deleted file mode 100644 index e8bee33b..00000000 --- a/test/dummy/app/models/size/portfolio.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -# == Schema Information -# -# Table name: size_portfolios -# -# id :integer not null, primary key -# title :string -# created_at :datetime not null -# updated_at :datetime not null -# - -class Size::Portfolio < ApplicationRecord - has_one_attached :size_less_than - has_one_attached :size_less_than_or_equal_to - has_one_attached :size_greater_than - has_one_attached :size_greater_than_or_equal_to - has_one_attached :size_between - has_one_attached :size_with_message - - has_one_attached :proc_size_less_than - has_one_attached :proc_size_less_than_or_equal_to - has_one_attached :proc_size_greater_than - has_one_attached :proc_size_greater_than_or_equal_to - has_one_attached :proc_size_between - has_one_attached :proc_size_with_message - - validates :title, presence: true - - validates :size_less_than, size: { less_than: 2.kilobytes } - validates :size_less_than_or_equal_to, size: { less_than_or_equal_to: 2.kilobytes } - validates :size_greater_than, size: { greater_than: 7.kilobytes } - validates :size_greater_than_or_equal_to, size: { greater_than_or_equal_to: 7.kilobytes } - validates :size_between, size: { between: 2.kilobytes..7.kilobytes } - validates :size_with_message, size: { between: 2.kilobytes..7.kilobytes, message: 'is not in required file size range' } - - validates :proc_size_less_than, size: { less_than: -> (record) { 2.kilobytes } } - validates :proc_size_less_than_or_equal_to, size: { less_than_or_equal_to: -> (record) { 2.kilobytes } } - validates :proc_size_greater_than, size: { greater_than: -> (record) { 7.kilobytes } } - validates :proc_size_greater_than_or_equal_to, size: { greater_than_or_equal_to: -> (record) { 7.kilobytes } } - validates :proc_size_between, size: { between: -> (record) { 2.kilobytes..7.kilobytes } } - validates :proc_size_with_message, size: { between: -> (record) { 2.kilobytes..7.kilobytes } } -end diff --git a/test/dummy/app/models/size/several_validator.rb b/test/dummy/app/models/size/several_validator.rb deleted file mode 100644 index 2aa23552..00000000 --- a/test/dummy/app/models/size/several_validator.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -# == Schema Information -# -# Table name: size_several_validators -# -# id :integer not null, primary key -# title :string -# created_at :datetime not null -# updated_at :datetime not null -# - -class Size::SeveralValidator < ApplicationRecord - has_one_attached :several_size_validators - - validates :title, presence: true - - validates :several_size_validators, size: { less_than: 2.kilobytes, greater_than_or_equal_to: 7.kilobytes } -end diff --git a/test/dummy/app/models/size/several_validator_proc.rb b/test/dummy/app/models/size/several_validator_proc.rb deleted file mode 100644 index 81eda4c7..00000000 --- a/test/dummy/app/models/size/several_validator_proc.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -# == Schema Information -# -# Table name: size_several_validator_procs -# -# id :integer not null, primary key -# title :string -# created_at :datetime not null -# updated_at :datetime not null -# - -class Size::SeveralValidatorProc < ApplicationRecord - has_one_attached :proc_several_size_validators - - validates :title, presence: true - - validates :proc_several_size_validators, size: { less_than: -> (record) { 2.kilobytes }, greater_than_or_equal_to: -> (record) { 7.kilobytes } } -end diff --git a/test/dummy/app/models/size/validator/check.rb b/test/dummy/app/models/size/validator/check.rb new file mode 100644 index 00000000..30ea3325 --- /dev/null +++ b/test/dummy/app/models/size/validator/check.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: size_validator_checks +# +# id :integer not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# + +class Size::Validator::Check < ApplicationRecord + has_one_attached :less_than + has_one_attached :less_than_or_equal_to + has_one_attached :greater_than + has_one_attached :greater_than_or_equal_to + has_one_attached :between + validates :less_than, size: { less_than: 2.kilobytes } + validates :less_than_or_equal_to, size: { less_than_or_equal_to: 2.kilobytes } + validates :greater_than, size: { greater_than: 7.kilobytes } + validates :greater_than_or_equal_to, size: { greater_than_or_equal_to: 7.kilobytes } + validates :between, size: { between: 2.kilobytes..7.kilobytes } + + has_one_attached :less_than_proc + has_one_attached :less_than_or_equal_to_proc + has_one_attached :greater_than_proc + has_one_attached :greater_than_or_equal_to_proc + has_one_attached :between_proc + validates :less_than_proc, size: { less_than: -> (record) { 2.kilobytes } } + validates :less_than_or_equal_to_proc, size: { less_than_or_equal_to: -> (record) { 2.kilobytes } } + validates :greater_than_proc, size: { greater_than: -> (record) { 7.kilobytes } } + validates :greater_than_or_equal_to_proc, size: { greater_than_or_equal_to: -> (record) { 7.kilobytes } } + validates :between_proc, size: { between: -> { 2.kilobytes..7.kilobytes } } + + has_one_attached :with_message + validates :with_message, size: { less_than_or_equal_to: 5.megabytes, message: 'Custom message' } +end diff --git a/test/dummy/app/models/size/validator/with_message.rb b/test/dummy/app/models/size/validator/with_message.rb new file mode 100644 index 00000000..ae4916b0 --- /dev/null +++ b/test/dummy/app/models/size/validator/with_message.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: size_validator_with_messages +# +# id :integer not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# + +class Size::Validator::WithMessage < ApplicationRecord + has_one_attached :with_message + validates :with_message, size: { less_than: 2.kilobytes , message: 'Custom message' } +end diff --git a/test/dummy/app/models/size/zero_validator.rb b/test/dummy/app/models/size/zero_validator.rb deleted file mode 100644 index 3a64c56c..00000000 --- a/test/dummy/app/models/size/zero_validator.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -# == Schema Information -# -# Table name: size_zero_validators -# -# id :integer not null, primary key -# title :string -# created_at :datetime not null -# updated_at :datetime not null -# - -class Size::ZeroValidator < ApplicationRecord - has_one_attached :zero_size_validator - - validates :title, presence: true - - validates :zero_size_validator, size: {} -end diff --git a/test/dummy/app/models/size/zero_validator_proc.rb b/test/dummy/app/models/size/zero_validator_proc.rb deleted file mode 100644 index 29830376..00000000 --- a/test/dummy/app/models/size/zero_validator_proc.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -# == Schema Information -# -# Table name: size_zero_validator_procs -# -# id :integer not null, primary key -# title :string -# created_at :datetime not null -# updated_at :datetime not null -# - -class Size::ZeroValidatorProc < ApplicationRecord - has_one_attached :proc_zero_size_validator - - validates :title, presence: true - - validates :proc_zero_size_validator, size: {} -end diff --git a/test/dummy/db/schema.rb b/test/dummy/db/schema.rb index 461d0d34..8160e074 100644 --- a/test/dummy/db/schema.rb +++ b/test/dummy/db/schema.rb @@ -63,7 +63,12 @@ end end - %i(allow_nil allow_blank if on strict unless).each do |option| + create_table :"#{validator}_validator_checks", force: :cascade do |t| + t.datetime :created_at, null: false + t.datetime :updated_at, null: false + end + + %i(allow_nil allow_blank if on strict unless message).each do |option| create_table :"#{validator}_validator_with_#{option.to_s.pluralize}", force: :cascade do |t| t.string :title if option == :if t.integer :rating if option == :unless @@ -104,36 +109,6 @@ t.datetime :updated_at, precision: 6, null: false end - create_table :size_portfolios, force: :cascade do |t| - t.string :title - t.datetime :created_at, null: false - t.datetime :updated_at, null: false - end - - create_table :size_several_validator_procs, force: :cascade do |t| - t.string :title - t.datetime :created_at, null: false - t.datetime :updated_at, null: false - end - - create_table :size_several_validators, force: :cascade do |t| - t.string :title - t.datetime :created_at, null: false - t.datetime :updated_at, null: false - end - - create_table :size_zero_validator_procs, force: :cascade do |t| - t.string :title - t.datetime :created_at, null: false - t.datetime :updated_at, null: false - end - - create_table :size_zero_validators, force: :cascade do |t| - t.string :title - t.datetime :created_at, null: false - t.datetime :updated_at, null: false - end - create_table :users, force: :cascade do |t| t.string :name t.datetime :created_at, null: false diff --git a/test/validators/shared_examples/works_with_all_rails_common_validation_options.rb b/test/validators/shared_examples/works_with_all_rails_common_validation_options.rb index 3921d04e..7c2867ab 100644 --- a/test/validators/shared_examples/works_with_all_rails_common_validation_options.rb +++ b/test/validators/shared_examples/works_with_all_rails_common_validation_options.rb @@ -1,6 +1,7 @@ require 'validators/shared_examples/works_with_allow_blank_option' require 'validators/shared_examples/works_with_allow_nil_option' require 'validators/shared_examples/works_with_if_option' +require 'validators/shared_examples/works_with_message_option' require 'validators/shared_examples/works_with_on_option' require 'validators/shared_examples/works_with_unless_option' require 'validators/shared_examples/works_with_strict_option' @@ -12,7 +13,7 @@ module WorksWithAllRailsCommonValidationOptions # https://guides.rubyonrails.org/active_record_validations.html#common-validation-options included do - %i(allow_nil allow_blank if on strict unless).each do |validation_option| + %i(allow_nil allow_blank if on strict unless message).each do |validation_option| describe ":#{validation_option}" do include "WorksWith#{validation_option.to_s.camelize}Option".constantize end diff --git a/test/validators/shared_examples/works_with_message_option.rb b/test/validators/shared_examples/works_with_message_option.rb new file mode 100644 index 00000000..95c02326 --- /dev/null +++ b/test/validators/shared_examples/works_with_message_option.rb @@ -0,0 +1,46 @@ +module WorksWithMessageOption + extend ActiveSupport::Concern + + included do + subject { validator_test_class::WithMessage.new(params) } + + let(:file_matching_requirements) do + case validator_sym + when :aspect_ratio then image_150x150_file + when :attached then image_150x150_file + when :content_type then webp_file + when :dimension then image_150x150_file + when :limit then nil + when :processable_image then image_150x150_file + when :size then file_1ko + end + end + let(:file_not_matching_requirements) do + case validator_sym + when :aspect_ratio then image_700x500_file + when :attached then nil + when :content_type then html_file + when :dimension then image_700x500_file + when :limit then file_5ko + when :processable_image then tar_file_with_image_content_type + when :size then file_5ko + end + end + + describe 'when passed a file matching the requirements' do + before { subject.with_message.attach(file_matching_requirements) } + + it { is_expected_to_be_valid } + end + + describe 'when passed a file not matching the requirements' do + let(:error_options) { { custom_message: 'Custom message' } } + + before { subject.with_message.attach(file_not_matching_requirements) } + + it { is_expected_not_to_be_valid } + it { is_expected_to_have_error_message("Custom message", error_options:) } + it { is_expected_to_have_error_options(error_options) } + end + end +end diff --git a/test/validators/size_validator_test.rb b/test/validators/size_validator_test.rb index 08dcf2b5..eb8b6543 100644 --- a/test/validators/size_validator_test.rb +++ b/test/validators/size_validator_test.rb @@ -14,242 +14,233 @@ include ChecksValidatorValidity end - describe 'Rails options' do - include WorksWithAllRailsCommonValidationOptions - end -end - -class ActiveStorageValidations::SizeValidator::Test < ActiveSupport::TestCase - - class LessThanValidator < ActiveStorageValidations::SizeValidator::Test - # validates :size_less_than, size: { less_than: 2.kilobytes } - - test 'validates attached file when size is stricly less than the model validation value' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_less_than.attach(file_1ko) - pt.proc_size_less_than.attach(file_1ko) - - assert pt.valid? - end - - test 'does not validate attached file when size is equal to the model validation value' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_less_than.attach(file_2ko) - pt.proc_size_less_than.attach(file_2ko) - - refute pt.valid? - assert_equal pt.errors.full_messages, [ - 'Size less than file size must be less than 2 KB (current size is 2 KB)', - 'Proc size less than file size must be less than 2 KB (current size is 2 KB)' - ] - end - - test 'does not validate attached file when size is stricly higher than the model validation value' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_less_than.attach(file_10ko) - pt.proc_size_less_than.attach(file_10ko) - - refute pt.valid? - assert_equal pt.errors.full_messages, [ - 'Size less than file size must be less than 2 KB (current size is 10 KB)', - 'Proc size less than file size must be less than 2 KB (current size is 10 KB)' - ] - end - end - - - class LessThanOrEqualToValidator < ActiveStorageValidations::SizeValidator::Test - # validates :size_less_than_or_equal_to, size: { less_than_or_equal_to: 2.kilobytes } - - test 'validates attached file when size is stricly less than the model validation value' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_less_than_or_equal_to.attach(file_1ko) - pt.proc_size_less_than_or_equal_to.attach(file_1ko) - - assert pt.valid? - end - - test 'validates attached file when size is equal to the model validation value' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_less_than_or_equal_to.attach(file_2ko) - pt.proc_size_less_than_or_equal_to.attach(file_2ko) - - assert pt.valid? - end - - test 'does not validate attached file when size is stricly higher than the model validation value' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_less_than_or_equal_to.attach(file_10ko) - pt.proc_size_less_than_or_equal_to.attach(file_10ko) - - refute pt.valid? - assert_equal pt.errors.full_messages, [ - 'Size less than or equal to file size must be less than or equal to 2 KB (current size is 10 KB)', - 'Proc size less than or equal to file size must be less than or equal to 2 KB (current size is 10 KB)' - ] - end - end - - - class GreaterThanValidator < ActiveStorageValidations::SizeValidator::Test - # validates :size_greater_than, size: { greater_than: 7.kilobytes } - - test 'validates attached file when size is stricly greater than the model validation value' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_greater_than.attach(file_10ko) - pt.proc_size_greater_than.attach(file_10ko) - - assert pt.valid? - end - - test 'does not validate attached file when size is equal to the model validation value' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_greater_than.attach(file_7ko) - pt.proc_size_greater_than.attach(file_7ko) - - refute pt.valid? - assert_equal pt.errors.full_messages, [ - 'Size greater than file size must be greater than 7 KB (current size is 7 KB)', - 'Proc size greater than file size must be greater than 7 KB (current size is 7 KB)' - ] - end - - test 'does not validate attached file when size is stricly less than the model validation value' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_greater_than.attach(file_2ko) - pt.proc_size_greater_than.attach(file_2ko) - - refute pt.valid? - assert_equal pt.errors.full_messages, [ - 'Size greater than file size must be greater than 7 KB (current size is 2 KB)', - 'Proc size greater than file size must be greater than 7 KB (current size is 2 KB)' - ] - end - end - - - class GreaterThanOrEqualToValidator < ActiveStorageValidations::SizeValidator::Test - # validates :size_greater_than_or_equal_to, size: { greater_than_or_equal_to: 7.kilobytes } - - test 'validates attached file when size is stricly greater than the model validation value' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_greater_than_or_equal_to.attach(file_10ko) - pt.proc_size_greater_than_or_equal_to.attach(file_10ko) - - assert pt.valid? - end - - test 'validates attached file when size is equal to the model validation value' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_greater_than_or_equal_to.attach(file_7ko) - pt.proc_size_greater_than_or_equal_to.attach(file_7ko) - - assert pt.valid? - end - - test 'does not validate attached file when size is stricly less than the model validation value' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_greater_than_or_equal_to.attach(file_2ko) - pt.proc_size_greater_than_or_equal_to.attach(file_2ko) - - refute pt.valid? - assert_equal pt.errors.full_messages, [ - 'Size greater than or equal to file size must be greater than or equal to 7 KB (current size is 2 KB)', - 'Proc size greater than or equal to file size must be greater than or equal to 7 KB (current size is 2 KB)' - ] + describe 'Validator checks' do + let(:model) { validator_test_class::Check.new(params) } + + describe ':less_than' do + # validates :less_than, size: { less_than: 2.kilobytes } + # validates :less_than_proc, size: { less_than: -> (record) { 2.kilobytes } } + %w(value proc).each do |value_type| + describe "#{value_type} validator" do + describe 'when provided with a lower size than the size specified in the model validations' do + subject { model.less_than.attach(file_1ko) and model } + + it { is_expected_to_be_valid } + end + + describe 'when provided with the exact size specified in the model validations' do + subject { model.less_than.attach(file_2ko) and model } + + let(:error_options) do + { + file_size: '2 KB', + min_size: nil, + max_size: '2 KB' + } + end + + it { is_expected_not_to_be_valid } + it { is_expected_to_have_error_message("file_size_not_less_than", error_options:) } + it { is_expected_to_have_error_options(error_options) } + end + + describe 'when provided with a higher size than the size specified in the model validations' do + subject { model.less_than.attach(file_5ko) and model } + + let(:error_options) do + { + file_size: '5 KB', + min_size: nil, + max_size: '2 KB' + } + end + + it { is_expected_not_to_be_valid } + it { is_expected_to_have_error_message("file_size_not_less_than", error_options:) } + it { is_expected_to_have_error_options(error_options) } + end + end + end + end + + describe ':less_than_or_equal_to' do + # validates :less_than_or_equal_to, size: { less_than_or_equal_to: 2.kilobytes } + # validates :less_than_or_equal_to_proc, size: { less_than_or_equal_to: -> (record) { 2.kilobytes } } + %w(value proc).each do |value_type| + describe "#{value_type} validator" do + describe 'when provided with a lower size than the size specified in the model validations' do + subject { model.less_than_or_equal_to.attach(file_1ko) and model } + + it { is_expected_to_be_valid } + end + + describe 'when provided with the exact size specified in the model validations' do + subject { model.less_than_or_equal_to.attach(file_2ko) and model } + + it { is_expected_to_be_valid } + end + + describe 'when provided with a higher size than the size specified in the model validations' do + subject { model.less_than_or_equal_to.attach(file_5ko) and model } + + let(:error_options) do + { + file_size: '5 KB', + min_size: nil, + max_size: '2 KB' + } + end + + it { is_expected_not_to_be_valid } + it { is_expected_to_have_error_message("file_size_not_less_than_or_equal_to", error_options:) } + it { is_expected_to_have_error_options(error_options) } + end + end + end + end + + describe ':greater_than' do + # validates :greater_than, size: { greater_than: 7.kilobytes } + # validates :greater_than_proc, size: { greater_than: -> (record) { 7.kilobytes } } + %w(value proc).each do |value_type| + describe "#{value_type} validator" do + describe 'when provided with a lower size than the size specified in the model validations' do + subject { model.greater_than.attach(file_1ko) and model } + + let(:error_options) do + { + file_size: '1 KB', + min_size: '7 KB', + max_size: nil + } + end + + it { is_expected_not_to_be_valid } + it { is_expected_to_have_error_message("file_size_not_greater_than", error_options:) } + it { is_expected_to_have_error_options(error_options) } + end + + describe 'when provided with the exact size specified in the model validations' do + subject { model.greater_than.attach(file_7ko) and model } + + let(:error_options) do + { + file_size: '7 KB', + min_size: '7 KB', + max_size: nil + } + end + + it { is_expected_not_to_be_valid } + it { is_expected_to_have_error_message("file_size_not_greater_than", error_options:) } + it { is_expected_to_have_error_options(error_options) } + end + + describe 'when provided with a higher size than the size specified in the model validations' do + subject { model.greater_than.attach(file_10ko) and model } + + it { is_expected_to_be_valid } + end + end + end + end + + describe ':greater_than_or_equal_to' do + # validates :greater_than_or_equal_to, size: { greater_than_or_equal_to: 7.kilobytes } + # validates :greater_than_or_equal_to_proc, size: { greater_than_or_equal_to: -> (record) { 7.kilobytes } } + %w(value proc).each do |value_type| + describe "#{value_type} validator" do + describe 'when provided with a lower size than the size specified in the model validations' do + subject { model.greater_than_or_equal_to.attach(file_1ko) and model } + + let(:error_options) do + { + file_size: '1 KB', + min_size: '7 KB', + max_size: nil + } + end + + it { is_expected_not_to_be_valid } + it { is_expected_to_have_error_message("file_size_not_greater_than_or_equal_to", error_options:) } + it { is_expected_to_have_error_options(error_options) } + end + + describe 'when provided with the exact size specified in the model validations' do + subject { model.greater_than_or_equal_to.attach(file_7ko) and model } + + it { is_expected_to_be_valid } + end + + describe 'when provided with a higher size than the size specified in the model validations' do + subject { model.greater_than_or_equal_to.attach(file_10ko) and model } + + it { is_expected_to_be_valid } + end + end + end + end + + describe ':between' do + # validates :between, size: { between: 2.kilobytes..7.kilobytes } + # validates :between_proc, size: { between: -> (record) { 2.kilobytes..7.kilobytes } } + %w(value proc).each do |value_type| + describe "#{value_type} validator" do + describe 'when provided with a lower size than the size specified in the model validations' do + subject { model.between.attach(file_1ko) and model } + + let(:error_options) do + { + file_size: '1 KB', + min_size: '2 KB', + max_size: '7 KB' + } + end + + it { is_expected_not_to_be_valid } + it { is_expected_to_have_error_message("file_size_not_between", error_options:) } + it { is_expected_to_have_error_options(error_options) } + end + + describe 'when provided with the exact lower size specified in the model validations' do + subject { model.between.attach(file_2ko) and model } + + it { is_expected_to_be_valid } + end + + describe 'when provided with a size between the sizes specified in the model validations' do + subject { model.between.attach(file_5ko) and model } + + it { is_expected_to_be_valid } + end + + describe 'when provided with the exact higher size specified in the model validations' do + subject { model.between.attach(file_7ko) and model } + + it { is_expected_to_be_valid } + end + + describe 'when provided with a higher size than the size specified in the model validations' do + subject { model.between.attach(file_10ko) and model } + + let(:error_options) do + { + file_size: '10 KB', + min_size: '2 KB', + max_size: '7 KB' + } + end + + it { is_expected_not_to_be_valid } + it { is_expected_to_have_error_message("file_size_not_between", error_options:) } + it { is_expected_to_have_error_options(error_options) } + end + end + end end end - - class BetweenValidator < ActiveStorageValidations::SizeValidator::Test - # validates :size_between, size: { between: 2..7.kilobytes } - - test 'validates attached file when size is in the model validation value range' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_between.attach(file_5ko) - pt.proc_size_between.attach(file_5ko) - - assert pt.valid? - end - - test 'validates attached file when size is equal to the lowest possible value of the model validation value range' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_between.attach(file_2ko) - pt.proc_size_between.attach(file_2ko) - - assert pt.valid? - end - - test 'validates attached file when size is equal to the highest possible value of the model validation value range' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_between.attach(file_7ko) - pt.proc_size_between.attach(file_7ko) - - assert pt.valid? - end - - test 'does not validate attached file when size is stricly less than the model validation value range' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_between.attach(file_1ko) - pt.proc_size_between.attach(file_1ko) - - refute pt.valid? - assert_equal pt.errors.full_messages, [ - 'Size between file size must be between 2 KB and 7 KB (current size is 1 KB)', - 'Proc size between file size must be between 2 KB and 7 KB (current size is 1 KB)' - ] - end - - test 'does not validate attached file when size is stricly higher than the model validation value range' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_between.attach(file_10ko) - pt.proc_size_between.attach(file_10ko) - - refute pt.valid? - assert_equal pt.errors.full_messages, [ - 'Size between file size must be between 2 KB and 7 KB (current size is 10 KB)', - 'Proc size between file size must be between 2 KB and 7 KB (current size is 10 KB)' - ] - end - end - - - class WithMessage < ActiveStorageValidations::SizeValidator::Test - # validates :size_with_message, size: { between: 2.kilobytes..7.kilobytes, message: 'is not in required file size range' } - - test 'generates the custom error message when the attached file is not valid' do - pt = Size::Portfolio.new(title: 'Matisse') - pt.size_with_message.attach(file_10ko) - pt.proc_size_with_message.attach(file_10ko) - - refute pt.valid? - assert_equal pt.errors.full_messages, [ - 'Size with message is not in required file size range', - 'Proc size with message file size must be between 2 KB and 7 KB (current size is 10 KB)' - ] - end - end - - class ValidatorValidity < ActiveStorageValidations::SizeValidator::Test - def error_message - 'You must pass either :less_than(_or_equal_to), :greater_than(_or_equal_to), or :between to the validator' - end - - test 'ensures that at least 1 size validator has been used' do - assert_raises(ArgumentError, error_message) { Size::ZeroValidator.new(title: 'Raises error') } - end - - test 'ensures that at least 1 size validator has been used when using a Proc' do - assert_raises(ArgumentError, error_message) { Size::ZeroValidatorProc.new(title: 'Raises error') } - end - - test 'ensures that no more than 1 size validator has been used' do - assert_raises(ArgumentError, error_message) { Size::SeveralValidator.new(title: 'Raises error') } - end - - test 'ensures that no more than 1 size validator has been used when using a Proc' do - assert_raises(ArgumentError, error_message) { Size::SeveralValidatorProc.new(title: 'Raises error') } - end + describe 'Rails options' do + include WorksWithAllRailsCommonValidationOptions end - end diff --git a/test/validators/support/validator_helpers.rb b/test/validators/support/validator_helpers.rb index 585a7da3..8769cd68 100644 --- a/test/validators/support/validator_helpers.rb +++ b/test/validators/support/validator_helpers.rb @@ -27,6 +27,23 @@ def is_expected_to_have_error_options(error_options, **kwargs) ) end + def is_expected_to_have_error_message(message_key, **kwargs) + subject.valid?(kwargs[:context]) + + # Rails 6.1.0 changes the form of ActiveModel’s errors collection + # https://github.com/rails/rails/blob/6-1-stable/activemodel/CHANGELOG.md#rails-610-december-09-2020 + validator_error_message = if Rails.gem_version >= Gem::Version.new('6.1.0') + subject.errors.find { |error| error.options[:validator_type] == validator_sym }.message + else + # For errors before Rails 6.1.0 we do not have error options + return true + end + + message = kwargs[:error_options][:custom_message] || I18n.t("errors.messages.#{message_key}", **kwargs[:error_options]) + + assert_equal(message, validator_error_message) + end + def is_expected_to_raise_error(error_class, message) begin subject.valid? rescue => e