diff --git a/lib/active_storage_validations/matchers/aspect_ratio_validator_matcher.rb b/lib/active_storage_validations/matchers/aspect_ratio_validator_matcher.rb index 3c4f78bf..90ae0ed7 100644 --- a/lib/active_storage_validations/matchers/aspect_ratio_validator_matcher.rb +++ b/lib/active_storage_validations/matchers/aspect_ratio_validator_matcher.rb @@ -4,6 +4,7 @@ require_relative 'concerns/allow_blankable.rb' require_relative 'concerns/contextable.rb' require_relative 'concerns/messageable.rb' +require_relative 'concerns/rspecable.rb' require_relative 'concerns/validatable.rb' module ActiveStorageValidations @@ -17,6 +18,7 @@ class AspectRatioValidatorMatcher include AllowBlankable include Contextable include Messageable + include Rspecable include Validatable def initialize(attribute_name) @@ -25,7 +27,11 @@ def initialize(attribute_name) end def description - "validate the aspect ratios allowed on attachment #{@attribute_name}." + "validate the aspect ratios allowed on :#{@attribute_name}." + end + + def failure_message + "is expected to validate aspect ratio of :#{@attribute_name}" end def allowing(*aspect_ratios) @@ -49,10 +55,6 @@ def matches?(subject) all_rejected_aspect_ratios_rejected? end - def failure_message - "is expected to validate aspect ratio of #{@attribute_name}" - end - protected def all_allowed_aspect_ratios_allowed? diff --git a/lib/active_storage_validations/matchers/attached_validator_matcher.rb b/lib/active_storage_validations/matchers/attached_validator_matcher.rb index 50cbed79..ea6c029a 100644 --- a/lib/active_storage_validations/matchers/attached_validator_matcher.rb +++ b/lib/active_storage_validations/matchers/attached_validator_matcher.rb @@ -3,6 +3,7 @@ require_relative 'concerns/active_storageable.rb' require_relative 'concerns/contextable.rb' require_relative 'concerns/messageable.rb' +require_relative 'concerns/rspecable.rb' require_relative 'concerns/validatable.rb' module ActiveStorageValidations @@ -15,6 +16,7 @@ class AttachedValidatorMatcher include ActiveStorageable include Contextable include Messageable + include Rspecable include Validatable def initialize(attribute_name) @@ -22,7 +24,11 @@ def initialize(attribute_name) end def description - "validate #{@attribute_name} must be attached" + "validate that :#{@attribute_name} must be attached" + end + + def failure_message + "is expected to validate attachment of :#{@attribute_name}" end def matches?(subject) @@ -35,14 +41,6 @@ def matches?(subject) is_invalid_when_file_not_attached? end - def failure_message - "is expected to validate attached of #{@attribute_name}" - end - - def failure_message_when_negated - "is expected to not validate attached of #{@attribute_name}" - end - private def is_valid_when_file_attached? diff --git a/lib/active_storage_validations/matchers/concerns/rspecable.rb b/lib/active_storage_validations/matchers/concerns/rspecable.rb new file mode 100644 index 00000000..fd4ce5f9 --- /dev/null +++ b/lib/active_storage_validations/matchers/concerns/rspecable.rb @@ -0,0 +1,26 @@ +require "active_support/concern" + +module ActiveStorageValidations + module Matchers + module Rspecable + extend ActiveSupport::Concern + + def initialize(attribute_name) + super + @failure_message_artefacts = [] + end + + def description + raise NotImplementedError, "#{self.class} did not define #{__method__}" + end + + def failure_message + raise NotImplementedError, "#{self.class} did not define #{__method__}" + end + + def failure_message_when_negated + failure_message.sub(/is expected to validate/, 'is expected not to validate') + end + end + end +end diff --git a/lib/active_storage_validations/matchers/content_type_validator_matcher.rb b/lib/active_storage_validations/matchers/content_type_validator_matcher.rb index abcb2578..fdbf15e4 100644 --- a/lib/active_storage_validations/matchers/content_type_validator_matcher.rb +++ b/lib/active_storage_validations/matchers/content_type_validator_matcher.rb @@ -7,6 +7,7 @@ require_relative 'concerns/allow_blankable.rb' require_relative 'concerns/contextable.rb' require_relative 'concerns/messageable.rb' +require_relative 'concerns/rspecable.rb' require_relative 'concerns/validatable.rb' module ActiveStorageValidations @@ -20,6 +21,7 @@ class ContentTypeValidatorMatcher include AllowBlankable include Contextable include Messageable + include Rspecable include Validatable def initialize(attribute_name) @@ -28,7 +30,33 @@ def initialize(attribute_name) end def description - "validate the content types allowed on attachment #{@attribute_name}" + "validate the content types allowed on :#{@attribute_name}" + end + + def failure_message + message = ["is expected to validate the content types of :#{@attribute_name}"] + build_failure_message(message) + message.join("\n") + end + + def build_failure_message(message) + if @allowed_types_not_allowed.present? + message << " the following content type#{'s' if @allowed_types.count > 1} should be allowed: :#{@allowed_types.join(", :")}" + message << " but #{pluralize(@allowed_types_not_allowed)} rejected" + end + + if @rejected_types_not_rejected.present? + message << " the following content type#{'s' if @rejected_types.count > 1} should be rejected: :#{@rejected_types.join(", :")}" + message << " but #{pluralize(@rejected_types_not_rejected)} accepted" + end + end + + def pluralize(types) + if types.count == 1 + ":#{types[0]} was" + else + ":#{types.join(", :")} were" + end end def allowing(*types) @@ -52,22 +80,6 @@ def matches?(subject) all_rejected_types_rejected? end - def failure_message - message = ["Expected #{@attribute_name}"] - - if @allowed_types_not_allowed.present? - message << "Accept content types: #{@allowed_types.join(", ")}" - message << "#{@allowed_types_not_allowed.join(", ")} were rejected" - end - - if @rejected_types_not_rejected.present? - message << "Reject content types: #{@rejected_types.join(", ")}" - message << "#{@rejected_types_not_rejected.join(", ")} were accepted" - end - - message.join("\n") - end - protected def all_allowed_types_allowed? diff --git a/lib/active_storage_validations/matchers/dimension_validator_matcher.rb b/lib/active_storage_validations/matchers/dimension_validator_matcher.rb index 77c06cfd..fa2cc068 100644 --- a/lib/active_storage_validations/matchers/dimension_validator_matcher.rb +++ b/lib/active_storage_validations/matchers/dimension_validator_matcher.rb @@ -4,6 +4,7 @@ require_relative 'concerns/allow_blankable.rb' require_relative 'concerns/contextable.rb' require_relative 'concerns/messageable.rb' +require_relative 'concerns/rspecable.rb' require_relative 'concerns/validatable.rb' module ActiveStorageValidations @@ -17,15 +18,38 @@ class DimensionValidatorMatcher include AllowBlankable include Contextable include Messageable + include Rspecable include Validatable def initialize(attribute_name) @attribute_name = attribute_name @width_min = @width_max = @height_min = @height_max = nil + @failure_message_artefacts = [] end def description - "validate image dimensions of #{@attribute_name}" + "validate the image dimensions of :#{@attribute_name}" + end + + def failure_message + message = ["is expected to validate dimensions of :#{@attribute_name}"] + build_failure_message(message) + message.join("\n") + end + + def build_failure_message(message) + return unless @failure_message_artefacts.present? + + message << " but there seem to have issues with the matcher methods you used, since:" + @failure_message_artefacts.each do |error_case| + message << " validation failed when provided with a #{error_case[:width]}x#{error_case[:height]}px test image" + end + message << " whereas it should have passed" + end + + def width(width) + @width_min = @width_max = width + self end def width_min(width) @@ -38,8 +62,13 @@ def width_max(width) self end - def width(width) - @width_min = @width_max = width + def width_between(range) + @width_min, @width_max = range.first, range.last + self + end + + def height(height) + @height_min = @height_max = height self end @@ -53,21 +82,11 @@ def height_max(height) self end - def width_between(range) - @width_min, @width_max = range.first, range.last - self - end - def height_between(range) @height_min, @height_max = range.first, range.last self end - def height(height) - @height_min = @height_max = height - self - end - def matches?(subject) @subject = subject.is_a?(Class) ? subject.new : subject @@ -87,14 +106,6 @@ def matches?(subject) height_equals? end - def failure_message - <<~MESSAGE - is expected to validate dimensions of #{@attribute_name} - width between #{@width_min} and #{@width_max} - height between #{@height_min} and #{@height_max} - MESSAGE - end - protected def valid_width @@ -106,52 +117,57 @@ def valid_height end def width_not_smaller_than_min? - @width_min.nil? || !passes_validation_with_dimensions(@width_min - 1, valid_height, 'width') + @width_min.nil? || !passes_validation_with_dimensions(@width_min - 1, valid_height) end def width_larger_than_min? - @width_min.nil? || @width_min == @width_max || passes_validation_with_dimensions(@width_min + 1, valid_height, 'width') + @width_min.nil? || @width_min == @width_max || passes_validation_with_dimensions(@width_min + 1, valid_height) end def width_smaller_than_max? - @width_max.nil? || @width_min == @width_max || passes_validation_with_dimensions(@width_max - 1, valid_height, 'width') + @width_max.nil? || @width_min == @width_max || passes_validation_with_dimensions(@width_max - 1, valid_height) end def width_not_larger_than_max? - @width_max.nil? || !passes_validation_with_dimensions(@width_max + 1, valid_height, 'width') + @width_max.nil? || !passes_validation_with_dimensions(@width_max + 1, valid_height) end def width_equals? - @width_min.nil? || @width_min != @width_max || passes_validation_with_dimensions(@width_min, valid_height, 'width') + @width_min.nil? || @width_min != @width_max || passes_validation_with_dimensions(@width_min, valid_height) end def height_not_smaller_than_min? - @height_min.nil? || !passes_validation_with_dimensions(valid_width, @height_min - 1, 'height') + @height_min.nil? || !passes_validation_with_dimensions(valid_width, @height_min - 1) end def height_larger_than_min? - @height_min.nil? || @height_min == @height_max || passes_validation_with_dimensions(valid_width, @height_min + 1, 'height') + @height_min.nil? || @height_min == @height_max || passes_validation_with_dimensions(valid_width, @height_min + 1) end def height_smaller_than_max? - @height_max.nil? || @height_min == @height_max || passes_validation_with_dimensions(valid_width, @height_max - 1, 'height') + @height_max.nil? || @height_min == @height_max || passes_validation_with_dimensions(valid_width, @height_max - 1) end def height_not_larger_than_max? - @height_max.nil? || !passes_validation_with_dimensions(valid_width, @height_max + 1, 'height') + @height_max.nil? || !passes_validation_with_dimensions(valid_width, @height_max + 1) end def height_equals? - @height_min.nil? || @height_min != @height_max || passes_validation_with_dimensions(valid_width, @height_min, 'height') + @height_min.nil? || @height_min != @height_max || passes_validation_with_dimensions(valid_width, @height_min) end - def passes_validation_with_dimensions(width, height, check) + def passes_validation_with_dimensions(width, height) mock_dimensions_for(attach_file, width, height) do validate - is_valid? + is_valid? || add_failure_message_artefact(width, height) end end + def add_failure_message_artefact(width, height) + @failure_message_artefacts << { width: width, height: height } + false + end + def is_custom_message_valid? return true unless @custom_message diff --git a/lib/active_storage_validations/matchers/size_validator_matcher.rb b/lib/active_storage_validations/matchers/size_validator_matcher.rb index c70e1bea..e0f45a9a 100644 --- a/lib/active_storage_validations/matchers/size_validator_matcher.rb +++ b/lib/active_storage_validations/matchers/size_validator_matcher.rb @@ -7,6 +7,7 @@ require_relative 'concerns/allow_blankable.rb' require_relative 'concerns/contextable.rb' require_relative 'concerns/messageable.rb' +require_relative 'concerns/rspecable.rb' require_relative 'concerns/validatable.rb' module ActiveStorageValidations @@ -20,15 +21,33 @@ class SizeValidatorMatcher include AllowBlankable include Contextable include Messageable + include Rspecable include Validatable def initialize(attribute_name) @attribute_name = attribute_name @min = @max = nil + @failure_message_artefacts = [] end def description - "validate file size of #{@attribute_name}" + "validate file size of :#{@attribute_name}" + end + + def failure_message + message = ["is expected to validate file size of :#{@attribute_name}"] + build_failure_message(message) + message.join("\n") + end + + def build_failure_message(message) + return unless @failure_message_artefacts.present? + + message << " but there seem to have issues with the matcher methods you used, since:" + @failure_message_artefacts.each do |error_case| + message << " validation failed when provided with a #{error_case[:size]} bytes test file" + end + message << " whereas it should have passed" end def less_than(size) @@ -69,14 +88,6 @@ def matches?(subject) not_higher_than_max? end - def failure_message - "is expected to validate file size of #{@attribute_name} to be between #{@min} and #{@max} bytes" - end - - def failure_message_when_negated - "is expected to not validate file size of #{@attribute_name} to be between #{@min} and #{@max} bytes" - end - protected def not_lower_than_min? @@ -99,10 +110,15 @@ def passes_validation_with_size(size) mock_size_for(io, size) do attach_file validate - is_valid? + is_valid? || add_failure_message_artefact(size) end end + def add_failure_message_artefact(size) + @failure_message_artefacts << { size: size } + false + end + def is_custom_message_valid? return true unless @custom_message diff --git a/test/dummy/app/models/aspect_ratio/matcher.rb b/test/dummy/app/models/aspect_ratio/matcher.rb index 0832d0b8..1cb98dc3 100644 --- a/test/dummy/app/models/aspect_ratio/matcher.rb +++ b/test/dummy/app/models/aspect_ratio/matcher.rb @@ -32,6 +32,11 @@ class AspectRatio::Matcher < ApplicationRecord has_one_attached :as_instance validates :as_instance, aspect_ratio: :square + has_one_attached :failure_message + validates :failure_message, aspect_ratio: :square + has_one_attached :failure_message_when_negated + validates :failure_message_when_negated, aspect_ratio: :square + # Combinations has_one_attached :allowing_one_with_message validates :allowing_one_with_message, aspect_ratio: { with: :portrait, message: 'Not authorized aspect ratio.' } diff --git a/test/dummy/app/models/attached/matcher.rb b/test/dummy/app/models/attached/matcher.rb index 25657ec5..77be774e 100644 --- a/test/dummy/app/models/attached/matcher.rb +++ b/test/dummy/app/models/attached/matcher.rb @@ -25,5 +25,10 @@ class Attached::Matcher < ApplicationRecord has_one_attached :as_instance validates :as_instance, attached: true + has_one_attached :failure_message + validates :failure_message, attached: true + has_one_attached :failure_message_when_negated + validates :failure_message_when_negated, attached: true + has_one_attached :not_required end diff --git a/test/dummy/app/models/content_type/matcher.rb b/test/dummy/app/models/content_type/matcher.rb index 94eab6d7..413e545a 100644 --- a/test/dummy/app/models/content_type/matcher.rb +++ b/test/dummy/app/models/content_type/matcher.rb @@ -32,6 +32,11 @@ class ContentType::Matcher < ApplicationRecord has_one_attached :as_instance validates :as_instance, content_type: :png + has_one_attached :failure_message + validates :failure_message, content_type: :png + has_one_attached :failure_message_when_negated + validates :failure_message_when_negated, content_type: :png + # Combinations has_one_attached :allowing_one_with_message validates :allowing_one_with_message, content_type: { in: ['file/pdf'], message: 'Not authorized file type.' } diff --git a/test/dummy/app/models/dimension/matcher.rb b/test/dummy/app/models/dimension/matcher.rb index bcf9e4af..268ae444 100644 --- a/test/dummy/app/models/dimension/matcher.rb +++ b/test/dummy/app/models/dimension/matcher.rb @@ -57,6 +57,11 @@ class Dimension::Matcher < ApplicationRecord has_one_attached :as_instance validates :as_instance, dimension: { width: 150, height: 150 } + has_one_attached :failure_message + validates :failure_message, dimension: { width: 150, height: 150 } + has_one_attached :failure_message_when_negated + validates :failure_message_when_negated, dimension: { width: 150, height: 150 } + # Combinations has_one_attached :width_and_height_exact has_one_attached :width_and_height_exact_with_message diff --git a/test/dummy/app/models/size/matcher.rb b/test/dummy/app/models/size/matcher.rb index 9b0387a0..376490ef 100644 --- a/test/dummy/app/models/size/matcher.rb +++ b/test/dummy/app/models/size/matcher.rb @@ -47,6 +47,11 @@ class Size::Matcher < ApplicationRecord has_one_attached :as_instance validates :as_instance, size: { less_than_or_equal_to: 5.megabytes } + has_one_attached :failure_message + validates :failure_message, size: { less_than_or_equal_to: 5.megabytes } + has_one_attached :failure_message_when_negated + validates :failure_message_when_negated, size: { less_than_or_equal_to: 5.megabytes } + # Combinations has_one_attached :less_than_with_message has_one_attached :less_than_or_equal_to_with_message diff --git a/test/matchers/aspect_ratio_validator_matcher_test.rb b/test/matchers/aspect_ratio_validator_matcher_test.rb index 99c2c23d..9128b67b 100644 --- a/test/matchers/aspect_ratio_validator_matcher_test.rb +++ b/test/matchers/aspect_ratio_validator_matcher_test.rb @@ -2,6 +2,7 @@ require 'test_helper' require 'matchers/shared_examples/checks_if_is_a_valid_active_storage_attribute' +require 'matchers/shared_examples/has_valid_rspec_message_methods' require 'matchers/shared_examples/works_with_allow_blank' require 'matchers/shared_examples/works_with_both_instance_and_class' require 'matchers/shared_examples/works_with_context' @@ -10,6 +11,7 @@ describe ActiveStorageValidations::Matchers::AspectRatioValidatorMatcher do include MatcherHelpers + include HasValidRspecMessageMethods include ChecksIfIsAValidActiveStorageAttribute include WorksWithBothInstanceAndClass diff --git a/test/matchers/attached_validator_matcher_test.rb b/test/matchers/attached_validator_matcher_test.rb index d5c29494..39e1b718 100644 --- a/test/matchers/attached_validator_matcher_test.rb +++ b/test/matchers/attached_validator_matcher_test.rb @@ -2,6 +2,7 @@ require 'test_helper' require 'matchers/shared_examples/checks_if_is_a_valid_active_storage_attribute' +require 'matchers/shared_examples/has_valid_rspec_message_methods' require 'matchers/shared_examples/works_with_both_instance_and_class' require 'matchers/shared_examples/works_with_context' require 'matchers/shared_examples/works_with_custom_message' @@ -9,6 +10,7 @@ describe ActiveStorageValidations::Matchers::AttachedValidatorMatcher do include MatcherHelpers + include HasValidRspecMessageMethods include ChecksIfIsAValidActiveStorageAttribute include WorksWithBothInstanceAndClass diff --git a/test/matchers/content_type_validator_matcher_test.rb b/test/matchers/content_type_validator_matcher_test.rb index 19c90793..1c4e8445 100644 --- a/test/matchers/content_type_validator_matcher_test.rb +++ b/test/matchers/content_type_validator_matcher_test.rb @@ -2,6 +2,7 @@ require 'test_helper' require 'matchers/shared_examples/checks_if_is_a_valid_active_storage_attribute' +require 'matchers/shared_examples/has_valid_rspec_message_methods' require 'matchers/shared_examples/works_with_allow_blank' require 'matchers/shared_examples/works_with_both_instance_and_class' require 'matchers/shared_examples/works_with_context' @@ -10,6 +11,7 @@ describe ActiveStorageValidations::Matchers::ContentTypeValidatorMatcher do include MatcherHelpers + include HasValidRspecMessageMethods include ChecksIfIsAValidActiveStorageAttribute include WorksWithBothInstanceAndClass diff --git a/test/matchers/dimension_validator_matcher_test.rb b/test/matchers/dimension_validator_matcher_test.rb index 1c8ebf36..f2d28e57 100644 --- a/test/matchers/dimension_validator_matcher_test.rb +++ b/test/matchers/dimension_validator_matcher_test.rb @@ -2,6 +2,7 @@ require 'test_helper' require 'matchers/shared_examples/checks_if_is_a_valid_active_storage_attribute' +require 'matchers/shared_examples/has_valid_rspec_message_methods' require 'matchers/shared_examples/works_with_allow_blank' require 'matchers/shared_examples/works_with_both_instance_and_class' require 'matchers/shared_examples/works_with_context' @@ -140,6 +141,7 @@ module OnlyMatchWhenExactValues describe ActiveStorageValidations::Matchers::DimensionValidatorMatcher do include MatcherHelpers + include HasValidRspecMessageMethods include ChecksIfIsAValidActiveStorageAttribute include WorksWithBothInstanceAndClass diff --git a/test/matchers/shared_examples/has_valid_rspec_message_methods.rb b/test/matchers/shared_examples/has_valid_rspec_message_methods.rb new file mode 100644 index 00000000..f6dfb9b1 --- /dev/null +++ b/test/matchers/shared_examples/has_valid_rspec_message_methods.rb @@ -0,0 +1,118 @@ +module HasValidRspecMessageMethods + extend ActiveSupport::Concern + + included do + describe 'when the matcher returns a failure message to the dev' do + before do + case validator_sym + when :aspect_ratio then matcher.rejecting(:square) + when :attached then matcher + when :content_type then matcher.rejecting('image/png') + when :dimension then matcher.width(75).height(75) + when :size then matcher.less_than_or_equal_to(7.megabytes) + end + end + + subject { matcher } + + let(:model_attribute) { :failure_message } + let(:expected_failure_message) do + case validator_sym + when :aspect_ratio + <<~FAILURE_MESSAGE + is expected to validate aspect ratio of :#{model_attribute} + FAILURE_MESSAGE + when :attached + <<~FAILURE_MESSAGE + is expected to validate attachment of :#{model_attribute} + FAILURE_MESSAGE + when :content_type + <<~FAILURE_MESSAGE + is expected to validate the content types of :#{model_attribute} + the following content type should be rejected: :image/png + but :image/png was accepted + FAILURE_MESSAGE + when :dimension + <<~FAILURE_MESSAGE + is expected to validate dimensions of :#{model_attribute} + but there seem to have issues with the matcher methods you used, since: + validation failed when provided with a 74x75px test image + validation failed when provided with a 76x75px test image + validation failed when provided with a 75x75px test image + whereas it should have passed + FAILURE_MESSAGE + when :size + <<~FAILURE_MESSAGE + is expected to validate file size of :#{model_attribute} + but there seem to have issues with the matcher methods you used, since: + validation failed when provided with a 7340031 bytes test file + whereas it should have passed + FAILURE_MESSAGE + end[0..-2] # to remove last \n generated by the <<~ format + end + + it { is_expected_to_have_failure_message(expected_failure_message) } + end + + describe 'when the matcher returns a negated failure message to the dev' do + before do + case validator_sym + when :aspect_ratio then matcher.allowing(:square) + when :attached then matcher + when :content_type then matcher.allowing('image/png') + when :dimension then matcher.width(150).height(150) + when :size then matcher.less_than_or_equal_to(5.megabytes) + end + end + + subject { matcher } + + let(:model_attribute) { :failure_message_when_negated } + let(:expected_failure_message) do + case validator_sym + when :aspect_ratio + <<~FAILURE_MESSAGE + is expected not to validate aspect ratio of :#{model_attribute} + FAILURE_MESSAGE + when :attached + <<~FAILURE_MESSAGE + is expected not to validate attachment of :#{model_attribute} + FAILURE_MESSAGE + when :content_type + <<~FAILURE_MESSAGE + is expected not to validate the content types of :#{model_attribute} + FAILURE_MESSAGE + when :dimension + <<~MESSAGE + is expected not to validate dimensions of :#{model_attribute} + but there seem to have issues with the matcher methods you used, since: + validation failed when provided with a 149x150px test image + validation failed when provided with a 151x150px test image + validation failed when provided with a 150x149px test image + validation failed when provided with a 150x151px test image + whereas it should have passed + MESSAGE + when :size + <<~FAILURE_MESSAGE + is expected not to validate file size of :#{model_attribute} + but there seem to have issues with the matcher methods you used, since: + validation failed when provided with a 5242881 bytes test file + whereas it should have passed + FAILURE_MESSAGE + end[0..-2] # to remove last \n generated by the <<~ format + end + + it { is_expected_to_have_failure_message_when_negated(expected_failure_message) } + end + + describe 'when the dev asks for a description of the matcher' do + subject { matcher.description } + + let(:model_attribute) { :failure_message_when_negated } + + it "returns a string containing the attribute name" do + assert(subject.match(/#{model_attribute}/)) + end + end + end +end diff --git a/test/matchers/size_validator_matcher_test.rb b/test/matchers/size_validator_matcher_test.rb index fe85aad7..8d694d90 100644 --- a/test/matchers/size_validator_matcher_test.rb +++ b/test/matchers/size_validator_matcher_test.rb @@ -2,6 +2,7 @@ require 'test_helper' require 'matchers/shared_examples/checks_if_is_a_valid_active_storage_attribute' +require 'matchers/shared_examples/has_valid_rspec_message_methods' require 'matchers/shared_examples/works_with_allow_blank' require 'matchers/shared_examples/works_with_both_instance_and_class' require 'matchers/shared_examples/works_with_context' @@ -60,6 +61,7 @@ module OnlyMatchWhenExactValue describe ActiveStorageValidations::Matchers::SizeValidatorMatcher do include MatcherHelpers + include HasValidRspecMessageMethods include ChecksIfIsAValidActiveStorageAttribute include WorksWithBothInstanceAndClass diff --git a/test/matchers/support/matcher_helpers.rb b/test/matchers/support/matcher_helpers.rb index dff6d578..c476484a 100644 --- a/test/matchers/support/matcher_helpers.rb +++ b/test/matchers/support/matcher_helpers.rb @@ -17,6 +17,16 @@ def is_expected_to_raise_error(error_class, message) end end + def is_expected_to_have_failure_message(expected_failure_message) + subject.matches?(klass) + assert_equal(subject.failure_message, expected_failure_message) + end + + def is_expected_to_have_failure_message_when_negated(expected_failure_message) + subject.matches?(klass) + assert_equal(subject.failure_message_when_negated, expected_failure_message) + end + def validator_class subject.class.name.sub(/::Matchers/, '').sub(/Matcher/, '').constantize end