Search code examples
rubyruby-on-rails-3rspeccarrierwaverspec-rails

carrierwave be_identical_to helper not working in rspec


I am having some issues with an rspec test I am trying to run on Carrierwave uploads. Basically, I am trying to test processing to make sure if images are uploaded and processed. I have created a post-processed example file that should be identical to the post-uploaded-and-processed test file. However, I am getting the following warning:


ImageUploader the greyscale version should remove color from the image and make it greyscale
 Failure/Error: @uploader.should be_identical_to(@pregreyed_image)
 TypeError:
   can't convert ImageUploader into String
 # ./spec/uploaders/image_uploader_spec.rb:24:in `block (3 levels) in <top (required)>'

Here is my test file:

image_uploader_spec.rb

require File.dirname(__FILE__) + '/../spec_helper'
require 'carrierwave/test/matchers'

describe ImageUploader do
  include CarrierWave::Test::Matchers
  include ActionDispatch::TestProcess

  before do
    ImageUploader.enable_processing = true
    @uploader_attr = fixture_file_upload('/test_images/testimage.jpg',    'image/jpeg')
    @uploader = ImageUploader.new(@uploader_attr)
    @uploader.store!
    @pregreyed_image =             fixture_file_upload('/test_images/testimage_GREY.jpg', 'image/jpeg')
  end

  after do
    @uploader.remove!
    ImageUploader.enable_processing = false
  end

  context 'the greyscale version' do
    it "should remove color from the image and make it greyscale" do

      @uploader.should be_identical_to(@pregreyed_image)
    end
  end
  end

image_uploader.rb

class ImageUploader < CarrierWave::Uploader::Base

  # Include RMagick or MiniMagick support:
  include CarrierWave::RMagick
  # include CarrierWave::MiniMagick

  # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
  include Sprockets::Helpers::RailsHelper
  include Sprockets::Helpers::IsolatedHelper

  # Choose what kind of storage to use for this uploader:
  storage :file


  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end


  # Process files as they are uploaded:
   process :convert_to_grayscale

  def convert_to_grayscale
    manipulate! do |img|
      img.colorspace = Magick::GRAYColorspace
      img.quantize(256, Magick::GRAYColorspace)
      img = yield(img) if block_given?
      img
    end
  end

Solution

  • Underneath the covers be_identical_to uses FileUtils.identical? on the two arguments. So your expectation:

    @uploader.should be_identical_to(@pregreyed_image)
    

    is actually calling:

    FileUtils.identcal?(@uploader, @pregreyed_image)
    

    Since in my test environment I'm using a file storage system, I got around this by passing in the #current_path rather than the uploader itself like this:

    @uploader.current_path.should be_identical_to(@pregreyed_image)
    

    I actually ended up needing to compare uploaders directly and implemented == on my uploader:

    class MyUploader < CarrierWave::Uploader::Base
      ...
    
      def ==(other)
        return true if !present? && !other.present?
        FileUtils.identical?(current_path, other.current_path)
      end
    end