Permalink
Browse files

has_attached_file and validate_attachment_presence matchers

  • Loading branch information...
1 parent ba91710 commit b3770534960cf7a946116cfcdf2471631043208e @jyurek jyurek committed Feb 7, 2009
@@ -0,0 +1,2 @@
+require 'shoulda_macros/matchers/have_attached_file_matcher'
+require 'shoulda_macros/matchers/validate_attachment_presence_matcher'
@@ -0,0 +1,49 @@
+module Paperclip
+ module Shoulda
+ module Matchers
+ def have_attached_file name
+ HaveAttachedFileMatcher.new(name)
+ end
+
+ class HaveAttachedFileMatcher
+ def initialize attachment_name
+ @attachment_name = attachment_name
+ end
+
+ def matches? subject
+ @subject = subject
+ responds? && has_column? && included?
+ end
+
+ def failure_message
+ "Should have an attachment named #{@attachment_name}"
+ end
+
+ def negative_failure_message
+ "Should not have an attachment named #{@attachment_name}"
+ end
+
+ def description
+ "have an attachment named #{@attachment_name}"
+ end
+
+ protected
+
+ def responds?
+ methods = @subject.instance_methods
+ methods.include?("#{@attachment_name}") &&
+ methods.include?("#{@attachment_name}=") &&
+ methods.include?("#{@attachment_name}?")
+ end
+
+ def has_column?
+ @subject.column_names.include?("#{@attachment_name}_file_name")
+ end
+
+ def included?
+ @subject.ancestors.include?(Paperclip::InstanceMethods)
+ end
+ end
+ end
+ end
+end
@@ -0,0 +1,48 @@
+module Paperclip
+ module Shoulda
+ module Matchers
+ def validate_attachment_presence name
+ ValidateAttachmentPresenceMatcher.new(name)
+ end
+
+ class ValidateAttachmentPresenceMatcher
+ def initialize attachment_name
+ @attachment_name = attachment_name
+ end
+
+ def matches? subject
+ @subject = subject
+ error_when_not_valid? && no_error_when_valid?
+ end
+
+ def failure_message
+ "Attachment #{@attachment_name} should be required"
+ end
+
+ def negative_failure_message
+ "Attachment #{@attachment_name} should not be required"
+ end
+
+ def description
+ "require presence of attachment #{@attachment_name}"
+ end
+
+ protected
+
+ def error_when_not_valid?
+ @attachment = @subject.new.send(@attachment_name)
+ @attachment.assign(nil)
+ not @attachment.errors[:presence].nil?
+ end
+
+ def no_error_when_valid?
+ @file = StringIO.new(".")
+ @attachment = @subject.new.send(@attachment_name)
+ @attachment.assign(@file)
+ @attachment.errors[:presence].nil?
+ end
+ end
+ end
+ end
+end
+
@@ -1,3 +1,5 @@
+require 'shoulda_macros/matchers'
+
module Paperclip
# =Paperclip Shoulda Macros
#
@@ -10,40 +12,20 @@ module Shoulda
# This will test whether you have defined your attachment correctly by
# checking for all the required fields exist after the definition of the
# attachment.
- def should_have_attached_file name, options = {}
- klass = self.name.gsub(/Test$/, '').constantize
- context "Class #{klass.name} with attachment #{name}" do
- should "respond to all the right methods" do
- ["#{name}", "#{name}=", "#{name}?"].each do |meth|
- assert klass.instance_methods.include?(meth), "#{klass.name} does not respond to #{name}."
- end
- end
+ def should_have_attached_file name
+ klass = self.name.gsub(/Test$/, '').constantize
+ matcher = have_attached_file name
+ should matcher.description do
+ assert_accepts(matcher, klass)
end
end
# Tests for validations on the presence of the attachment.
def should_validate_attachment_presence name
klass = self.name.gsub(/Test$/, '').constantize
- context "Class #{klass.name} validating presence on #{name}" do
- context "when the assignment is nil" do
- setup do
- @attachment = klass.new.send(name)
- @attachment.assign(nil)
- end
- should "have a :presence validation error" do
- assert @attachment.errors[:presence]
- end
- end
- context "when the assignment is valid" do
- setup do
- @file = StringIO.new(".")
- @attachment = klass.new.send(name)
- @attachment.assign(@file)
- end
- should "have a :presence validation error" do
- assert ! @attachment.errors[:presence]
- end
- end
+ matcher = validate_attachment_presence name
+ should matcher.description do
+ assert_accepts(matcher, klass)
end
end
@@ -151,4 +133,7 @@ def should_validate_attachment_size name, options = {}
end
end
-Test::Unit::TestCase.extend(Paperclip::Shoulda)
+class Test::Unit::TestCase #:nodoc:
+ extend Paperclip::Shoulda
+ include Paperclip::Shoulda::Matchers
+end
View
@@ -23,13 +23,32 @@
require File.join(ROOT, 'lib', 'paperclip.rb')
+require 'shoulda_macros/paperclip'
+
ENV['RAILS_ENV'] ||= 'test'
FIXTURES_DIR = File.join(File.dirname(__FILE__), "fixtures")
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
ActiveRecord::Base.establish_connection(config['test'])
+def reset_class class_name
+ ActiveRecord::Base.send(:include, Paperclip)
+ Object.send(:remove_const, class_name) rescue nil
+ klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
+ klass.class_eval{ include Paperclip }
+ klass
+end
+
+def reset_table table_name, &block
+ block ||= lambda{ true }
+ ActiveRecord::Base.connection.create_table :dummies, {:force => true}, &block
+end
+
+def modify_table table_name, &block
+ ActiveRecord::Base.connection.change_table :dummies, &block
+end
+
def rebuild_model options = {}
ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
table.column :other, :string
@@ -0,0 +1,21 @@
+require 'test/helper'
+
+class HaveAttachedFileMatcherTest < Test::Unit::TestCase
+ context "have_attached_file" do
+ setup do
+ @dummy_class = reset_class "Dummy"
+ reset_table "dummies"
+ @matcher = have_attached_file(:avatar)
+ end
+
+ should "reject a class with no attachment" do
+ assert_rejects @matcher, @dummy_class
+ end
+
+ should "accept a class with an attachment" do
+ modify_table("dummies"){|d| d.string :avatar_file_name }
+ @dummy_class.has_attached_file :avatar
+ assert_accepts @matcher, @dummy_class
+ end
+ end
+end
@@ -0,0 +1,21 @@
+require 'test/helper'
+
+class ValidateAttachmentPresenceMatcherTest < Test::Unit::TestCase
+ context "validate_attachment_presence" do
+ setup do
+ reset_table("dummies"){|d| d.string :avatar_file_name }
+ @dummy_class = reset_class "Dummy"
+ @dummy_class.has_attached_file :avatar
+ @matcher = validate_attachment_presence(:avatar)
+ end
+
+ should "reject a class with no validation" do
+ assert_rejects @matcher, @dummy_class
+ end
+
+ should "accept a class with a validation" do
+ @dummy_class.validates_attachment_presence :avatar
+ assert_accepts @matcher, @dummy_class
+ end
+ end
+end

0 comments on commit b377053

Please sign in to comment.