Permalink
Browse files

Size validation matcher conversion

  • Loading branch information...
1 parent 9e73929 commit f78528a76e5f787555a2eee64b2bab3fd2a846fe @jyurek jyurek committed Feb 8, 2009
@@ -1,3 +1,4 @@
require 'shoulda_macros/matchers/have_attached_file_matcher'
require 'shoulda_macros/matchers/validate_attachment_presence_matcher'
require 'shoulda_macros/matchers/validate_attachment_content_type_matcher'
+require 'shoulda_macros/matchers/validate_attachment_size_matcher'
@@ -0,0 +1,83 @@
+module Paperclip
+ module Shoulda
+ module Matchers
+ def validate_attachment_size name
+ ValidateAttachmentSizeMatcher.new(name)
+ end
+
+ class ValidateAttachmentSizeMatcher
+ def initialize attachment_name
+ @attachment_name = attachment_name
+ @low, @high = 0, (1.0/0)
+ end
+
+ def less_than size
+ @high = size
+ self
+ end
+
+ def greater_than size
+ @low = size
+ self
+ end
+
+ def in range
+ @low, @high = range.first, range.last
+ self
+ end
+
+ def matches? subject
+ @subject = subject
+ lower_than_low? && higher_than_low? && lower_than_high? && higher_than_high?
+ end
+
+ def failure_message
+ "Attachment #{@attachment_name} must be between #{@low} and #{@high} bytes"
+ end
+
+ def negative_failure_message
+ "Attachment #{@attachment_name} cannot be between #{@low} and #{@high} bytes"
+ end
+
+ def description
+ "validate the size of attachment #{@attachment_name}"
+ end
+
+ protected
+
+ def override_method object, method, &replacement
+ (class << object; self; end).class_eval do
+ define_method(method, &replacement)
+ end
+ end
+
+ def passes_validation_with_size(new_size)
+ file = StringIO.new(".")
+ override_method(file, :size){ new_size }
+ attachment = @subject.new.attachment_for(@attachment_name)
+ attachment.assign(file)
+ attachment.errors[:size].nil?
+ end
+
+ def lower_than_low?
+ not passes_validation_with_size(@low - 1)
+ end
+
+ def higher_than_low?
+ passes_validation_with_size(@low + 1)
+ end
+
+ def lower_than_high?
+ return true if @high == (1.0/0)
+ passes_validation_with_size(@high - 1)
+ end
+
+ def higher_than_high?
+ return true if @high == (1.0/0)
+ not passes_validation_with_size(@high + 1)
+ end
+ end
+ end
+ end
+end
+
@@ -54,54 +54,9 @@ def should_validate_attachment_size name, options = {}
min = options[:greater_than] || (options[:in] && options[:in].first) || 0
max = options[:less_than] || (options[:in] && options[:in].last) || (1.0/0)
range = (min..max)
- context "Class #{klass.name} validating file size on #{name}" do
- context "with an attachment that is #{max+1} bytes" do
- setup do
- @file = StringIO.new("." * (max+1))
- @attachment = klass.new.send(name)
- @attachment.assign(@file)
- end
-
- should "have a :size validation error" do
- assert @attachment.errors[:size]
- end
- end
- context "with an attachment that us #{max-1} bytes" do
- setup do
- @file = StringIO.new("." * (max-1))
- @attachment = klass.new.send(name)
- @attachment.assign(@file)
- end
-
- should "not have a :size validation error" do
- assert ! @attachment.errors[:size]
- end
- end
-
- if min > 0
- context "with an attachment that is #{min-1} bytes" do
- setup do
- @file = StringIO.new("." * (min-1))
- @attachment = klass.new.send(name)
- @attachment.assign(@file)
- end
-
- should "have a :size validation error" do
- assert @attachment.errors[:size]
- end
- end
- context "with an attachment that us #{min+1} bytes" do
- setup do
- @file = StringIO.new("." * (min+1))
- @attachment = klass.new.send(name)
- @attachment.assign(@file)
- end
-
- should "not have a :size validation error" do
- assert ! @attachment.errors[:size]
- end
- end
- end
+ matcher = validate_attachment_size(name).in(range)
+ should matcher.description do
+ assert_accepts(matcher, klass)
end
end
end
@@ -0,0 +1,50 @@
+require 'test/helper'
+
+class ValidateAttachmentSizeMatcherTest < Test::Unit::TestCase
+ context "validate_attachment_size" do
+ setup do
+ reset_table("dummies") do |d|
+ d.string :avatar_file_name
+ end
+ @dummy_class = reset_class "Dummy"
+ @dummy_class.has_attached_file :avatar
+ end
+
+ context "of limited size" do
+ setup{ @matcher = validate_attachment_size(:avatar).in(256..1024) }
+
+ should "reject a class with no validation" do
+ assert_rejects @matcher, @dummy_class
+ end
+
+ should "reject a class with a validation that's too high" do
+ @dummy_class.validates_attachment_size :avatar, :in => 256..2048
+ assert_rejects @matcher, @dummy_class
+ end
+
+ should "reject a class with a validation that's too low" do
+ @dummy_class.validates_attachment_size :avatar, :in => 0..1024
+ assert_rejects @matcher, @dummy_class
+ end
+
+ should "accept a class with a validation that matches" do
+ @dummy_class.validates_attachment_size :avatar, :in => 256..1024
+ assert_accepts @matcher, @dummy_class
+ end
+ end
+
+ context "validates_attachment_size with infinite range" do
+ setup{ @matcher = validate_attachment_size(:avatar) }
+
+ should "accept a class with an upper limit" do
+ @dummy_class.validates_attachment_size :avatar, :less_than => 1
+ assert_accepts @matcher, @dummy_class
+ end
+
+ should "accept a class with no upper limit" do
+ @dummy_class.validates_attachment_size :avatar, :greater_than => 1
+ assert_accepts @matcher, @dummy_class
+ end
+ end
+ end
+end

0 comments on commit f78528a

Please sign in to comment.