Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

259 processable image validator matcher #262

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ Very simple example of validation with file attached, content type check and cus
[![Sample](https://raw.githubusercontent.com/igorkasyanchuk/active_storage_validations/master/docs/preview.png)](https://raw.githubusercontent.com/igorkasyanchuk/active_storage_validations/master/docs/preview.png)

## Test matchers
Provides RSpec-compatible and Minitest-compatible matchers for testing the validators. Only `aspect_ratio`, `attached`, `content_type`, `dimension` and `size` validators currently have their matcher developed.
Provides RSpec-compatible and Minitest-compatible matchers for testing the validators. Only `aspect_ratio`, `attached`, `processable_image`, `content_type`, `dimension` and `size` validators currently have their matcher developed.

### RSpec

Expand Down Expand Up @@ -310,6 +310,9 @@ describe User do
# attached
it { is_expected.to validate_attached_of(:avatar) }

# processable_image
it { is_expected.to validate_processable_image_of(:avatar) }

# content_type:
# #allowing, #rejecting
it { is_expected.to validate_content_type_of(:avatar).allowing('image/png', 'image/gif') }
Expand Down
1 change: 1 addition & 0 deletions lib/active_storage_validations/matchers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require 'active_storage_validations/matchers/aspect_ratio_validator_matcher'
require 'active_storage_validations/matchers/attached_validator_matcher'
require 'active_storage_validations/matchers/processable_image_validator_matcher'
require 'active_storage_validations/matchers/content_type_validator_matcher'
require 'active_storage_validations/matchers/dimension_validator_matcher'
require 'active_storage_validations/matchers/size_validator_matcher'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ def io
def detach_file
@subject.attachment_changes.delete(@attribute_name.to_s)
end

def file_attached?
@subject.public_send(@attribute_name).attached?
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# frozen_string_literal: true

require_relative 'concerns/active_storageable.rb'
require_relative 'concerns/allow_blankable.rb'
require_relative 'concerns/attachable.rb'
require_relative 'concerns/contextable.rb'
require_relative 'concerns/messageable.rb'
require_relative 'concerns/rspecable.rb'
require_relative 'concerns/validatable.rb'

module ActiveStorageValidations
module Matchers
def validate_processable_image_of(name)
ProcessableImageValidatorMatcher.new(name)
end

class ProcessableImageValidatorMatcher
include ActiveStorageable
include AllowBlankable
include Attachable
include Contextable
include Messageable
include Rspecable
include Validatable

def initialize(attribute_name)
initialize_allow_blankable
initialize_contextable
initialize_messageable
initialize_rspecable
@attribute_name = attribute_name
end

def description
"validate that :#{@attribute_name} is a processable image"
end

def failure_message
"is expected to validate the processable image of :#{@attribute_name}"
end

def matches?(subject)
@subject = subject.is_a?(Class) ? subject.new : subject

is_a_valid_active_storage_attribute? &&
is_context_valid? &&
is_custom_message_valid? &&
is_valid_when_image_processable? &&
is_invalid_when_image_not_processable?
end

private

def is_valid_when_image_processable?
attach_processable_image
validate
detach_file
is_valid?
end

def is_invalid_when_image_not_processable?
attach_not_processable_image
validate
detach_file
!is_valid?
end

def is_custom_message_valid?
return true unless @custom_message

attach_not_processable_image
validate
detach_file
has_an_error_message_which_is_custom_message?
end

def attach_processable_image
processable_image = {
io: File.open(Rails.root.join('public', 'image_1920x1080.png')),
filename: 'image_1920x1080_file.png',
content_type: 'image/png'
}

@subject.public_send(@attribute_name).attach(processable_image)
Mth0158 marked this conversation as resolved.
Show resolved Hide resolved
end

def attach_not_processable_image
not_processable_image = {
io: Tempfile.new('.'),
filename: 'processable.txt',
content_type: 'text/plain'
}

@subject.public_send(@attribute_name).attach(not_processable_image)
Mth0158 marked this conversation as resolved.
Show resolved Hide resolved
end

end
end
end
46 changes: 46 additions & 0 deletions test/dummy/app/models/processable_image/matcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: processable_image_matchers
#
# title :string
# id :integer not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
#

class ProcessableImage::Matcher < ApplicationRecord
include Validatable

has_one_attached :custom_matcher
validates :custom_matcher, processable_image: true

has_one_attached :processable
validates :processable, processable_image: true

has_one_attached :with_message
validates :with_message, processable_image: { message: 'Custom message' }

has_one_attached :with_context_symbol
validates :with_context_symbol, processable_image: true, on: :update
has_one_attached :with_context_array
validates :with_context_array, processable_image: true, on: %i[update custom]
has_one_attached :with_several_validators_and_contexts
validates :with_several_validators_and_contexts, processable_image: true, on: :update
validates :with_several_validators_and_contexts, processable_image: true, on: :custom

has_one_attached :as_instance
validates :as_instance, processable_image: true

has_one_attached :validatable_different_error_messages
validates :validatable_different_error_messages, processable_image: { message: 'Custom message 1' }, if: :title_is_quo_vadis?
validates :validatable_different_error_messages, processable_image: { message: 'Custom message 2' }, if: :title_is_american_psycho?

has_one_attached :failure_message
validates :failure_message, processable_image: true
has_one_attached :failure_message_when_negated
validates :failure_message_when_negated, processable_image: true

has_one_attached :not_processable
end
43 changes: 43 additions & 0 deletions test/matchers/processable_image_validator_matcher_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

require 'test_helper'
require 'matchers/shared_examples/checks_if_is_a_valid_active_storage_attribute'
require 'matchers/shared_examples/checks_if_is_valid'
require 'matchers/shared_examples/has_custom_matcher'
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'

describe ActiveStorageValidations::Matchers::ProcessableImageValidatorMatcher do
include MatcherHelpers

include ChecksIfIsAValidActiveStorageAttribute
include ChecksIfIsValid
include HasCustomMatcher
include HasValidRspecMessageMethods
include WorksWithBothInstanceAndClass

let(:matcher) { ActiveStorageValidations::Matchers::ProcessableImageValidatorMatcher.new(model_attribute) }
let(:klass) { ProcessableImage::Matcher }

describe "#validate_processable_image_of" do
include HasCustomMatcher
end

describe 'when the passed model attribute does not have a `processable: true` constraint' do
subject { matcher }

let(:model_attribute) { :not_required }

it { is_expected_not_to_match_for(klass) }
end

describe '#with_message' do
include WorksWithCustomMessage
end

describe "#on" do
include WorksWithContext
end
end
1 change: 1 addition & 0 deletions test/matchers/shared_examples/checks_if_is_valid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module ChecksIfIsValid
case validator_sym
when :aspect_ratio then matcher.allowing(:square)
when :attached then matcher
when :processable_image then matcher
when :content_type then matcher.rejecting('image/jpg')
when :dimension then matcher.width(150)
when :size then matcher.less_than(10.megabytes)
Expand Down
1 change: 1 addition & 0 deletions test/matchers/shared_examples/has_custom_matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class ActiveSupport::TestCase
case validator_sym
when :aspect_ratio then custom_matcher_builder.validate_aspect_ratio_of(model_attribute).allowing(:square)
when :attached then custom_matcher_builder.validate_attached_of(model_attribute)
when :processable_image then custom_matcher_builder.validate_processable_image_of(model_attribute)
when :content_type then custom_matcher_builder.validate_content_type_of(model_attribute).allowing('image/png')
when :dimension then custom_matcher_builder.validate_dimensions_of(model_attribute).width(150).height(150)
when :size then custom_matcher_builder.validate_size_of(model_attribute).less_than_or_equal_to(5.megabytes)
Expand Down
10 changes: 10 additions & 0 deletions test/matchers/shared_examples/has_valid_rspec_message_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module HasValidRspecMessageMethods
case validator_sym
when :aspect_ratio then matcher.rejecting(:square)
when :attached then matcher
when :processable_image 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)
Expand All @@ -26,6 +27,10 @@ module HasValidRspecMessageMethods
<<~FAILURE_MESSAGE
is expected to validate attachment of :#{model_attribute}
FAILURE_MESSAGE
when :processable_image
<<~FAILURE_MESSAGE
is expected to validate the processable image of :#{model_attribute}
FAILURE_MESSAGE
when :content_type
<<~FAILURE_MESSAGE
is expected to validate the content types of :#{model_attribute}
Expand Down Expand Up @@ -59,6 +64,7 @@ module HasValidRspecMessageMethods
case validator_sym
when :aspect_ratio then matcher.allowing(:square)
when :attached then matcher
when :processable_image 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)
Expand All @@ -78,6 +84,10 @@ module HasValidRspecMessageMethods
<<~FAILURE_MESSAGE
is expected not to validate attachment of :#{model_attribute}
FAILURE_MESSAGE
when :processable_image
<<~FAILURE_MESSAGE
is expected not to validate the processable image of :#{model_attribute}
FAILURE_MESSAGE
when :content_type
<<~FAILURE_MESSAGE
is expected not to validate the content types of :#{model_attribute}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module WorksWithBothInstanceAndClass
case validator_sym
when :aspect_ratio then matcher.allowing(:square)
when :attached then nil
when :processable_image then nil
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)
Expand Down
1 change: 1 addition & 0 deletions test/matchers/shared_examples/works_with_custom_message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module WorksWithCustomMessage
case validator_sym
when :aspect_ratio then matcher.allowing(:square)
when :attached then nil
when :processable_image then nil
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)
Expand Down
Loading