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 :processable_file then matcher
        when :limit then matcher.min(0).max(6)
        when :content_type then matcher.rejecting("image/png")
        when :dimension then matcher.width(75).height(75)
        when :duration then matcher.less_than_or_equal_to(7.minutes)
        when :size then matcher.less_than_or_equal_to(7.megabytes)
        when :total_size then matcher.less_than_or_equal_to(7.megabytes)
        when :pages then matcher.less_than_or_equal_to(7)
        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 :processable_file
          <<~FAILURE_MESSAGE
            is expected to validate the processable image of :#{model_attribute}
          FAILURE_MESSAGE
        when :limit
          <<~FAILURE_MESSAGE
            is expected to validate limit file of :#{model_attribute}
              but there seem to have issues with the matcher methods you used, since:
              validation failed when provided with 6 file(s)
              whereas it should have passed
          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 :duration
          <<~FAILURE_MESSAGE
            is expected to validate file duration of :#{model_attribute}
              but there seem to have issues with the matcher methods you used, since:
              validation failed when provided with a 419 seconds test file
              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
        when :total_size
          <<~FAILURE_MESSAGE
            is expected to validate total 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
        when :pages
          <<~FAILURE_MESSAGE
            is expected to validate file number of pages of :#{model_attribute}
              but there seem to have issues with the matcher methods you used, since:
              validation failed when provided with a 6 pages 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 :processable_file then matcher
        when :limit then matcher.min(1).max(5)
        when :content_type then matcher.allowing("image/png")
        when :dimension then matcher.width(150).height(150)
        when :duration then matcher.less_than_or_equal_to(5.minutes)
        when :size then matcher.less_than_or_equal_to(5.megabytes)
        when :total_size then matcher.less_than_or_equal_to(5.megabytes)
        when :pages then matcher.less_than_or_equal_to(5)
        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 :processable_file
          <<~FAILURE_MESSAGE
            is expected not to validate the processable image of :#{model_attribute}
          FAILURE_MESSAGE
        when :limit
          <<~FAILURE_MESSAGE
            is expected not to validate limit file of :#{model_attribute}
              but there seem to have issues with the matcher methods you used, since:
              validation failed when provided with 0 file(s)
              validation failed when provided with 6 file(s)
              whereas it should have passed
          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 :duration
          <<~FAILURE_MESSAGE
            is expected not to validate file duration of :#{model_attribute}
              but there seem to have issues with the matcher methods you used, since:
              validation failed when provided with a 301 seconds test file
              whereas it should have passed
          FAILURE_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
        when :total_size
          <<~FAILURE_MESSAGE
            is expected not to validate total 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
        when :pages
          <<~FAILURE_MESSAGE
            is expected not to validate file number of pages of :#{model_attribute}
              but there seem to have issues with the matcher methods you used, since:
              validation failed when provided with a 6 pages 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
