require "spec_helper" describe Paperclip::Thumbnail do context "An image" do before do @file = File.new(fixture_file("5k.png"), "rb") end after { @file.close } [["600x600>", "434x66"], ["400x400>", "400x61"], ["32x32<", "434x66"], [nil, "434x66"]].each do |args| context "being thumbnailed with a geometry of #{args[0]}" do before do @thumb = Paperclip::Thumbnail.new(@file, geometry: args[0]) end it "starts with dimensions of 434x66" do cmd = %[identify -format "%wx%h" "#{@file.path}"] assert_equal "434x66", `#{cmd}`.chomp end it "reports the correct target geometry" do assert_equal args[0].to_s, @thumb.target_geometry.to_s end context "when made" do before do @thumb_result = @thumb.make end it "is the size we expect it to be" do cmd = %[identify -format "%wx%h" "#{@thumb_result.path}"] assert_equal args[1], `#{cmd}`.chomp end end end end context "being thumbnailed at 100x50 with cropping" do before do @thumb = Paperclip::Thumbnail.new(@file, geometry: "100x50#") end it "lets us know when a command isn't found versus a processing error" do old_path = ENV["PATH"] begin Terrapin::CommandLine.path = "" Paperclip.options[:command_path] = "" ENV["PATH"] = "" assert_raises(Paperclip::Errors::CommandNotFoundError) do silence_stream(STDERR) do @thumb.make end end ensure ENV["PATH"] = old_path end end it "reports its correct current and target geometries" do assert_equal "100x50#", @thumb.target_geometry.to_s assert_equal "434x66", @thumb.current_geometry.to_s end it "reports its correct format" do assert_nil @thumb.format end it "has whiny turned on by default" do assert @thumb.whiny end it "has convert_options set to nil by default" do assert_equal nil, @thumb.convert_options end it "has source_file_options set to nil by default" do assert_equal nil, @thumb.source_file_options end it "sends the right command to convert when sent #make" do expect(@thumb).to receive(:convert) do |*arg| arg[0] == ':source -auto-orient -resize "x50" -crop "100x50+114+0" +repage :dest' && arg[1][:source] == "#{File.expand_path(@thumb.file.path)}[0]" end @thumb.make end it "creates the thumbnail when sent #make" do dst = @thumb.make assert_match /100x50/, `identify "#{dst.path}"` end end it "crops a EXIF-rotated image properly" do file = File.new(fixture_file("rotated.jpg")) thumb = Paperclip::Thumbnail.new(file, geometry: "50x50#") output_file = thumb.make command = Terrapin::CommandLine.new("identify", "-format %wx%h :file") assert_equal "50x50", command.run(file: output_file.path).strip end context "being thumbnailed with source file options set" do before do @thumb = Paperclip::Thumbnail.new(@file, geometry: "100x50#", source_file_options: "-strip") end it "has source_file_options value set" do assert_equal ["-strip"], @thumb.source_file_options end it "sends the right command to convert when sent #make" do expect(@thumb).to receive(:convert) do |*arg| arg[0] == '-strip :source -auto-orient -resize "x50" -crop "100x50+114+0" +repage :dest' && arg[1][:source] == "#{File.expand_path(@thumb.file.path)}[0]" end @thumb.make end it "creates the thumbnail when sent #make" do dst = @thumb.make assert_match /100x50/, `identify "#{dst.path}"` end context "redefined to have bad source_file_options setting" do before do @thumb = Paperclip::Thumbnail.new(@file, geometry: "100x50#", source_file_options: "-this-aint-no-option") end it "errors when trying to create the thumbnail" do assert_raises(Paperclip::Error) do silence_stream(STDERR) do @thumb.make end end end end end context "being thumbnailed with convert options set" do before do @thumb = Paperclip::Thumbnail.new(@file, geometry: "100x50#", convert_options: "-strip -depth 8") end it "has convert_options value set" do assert_equal %w"-strip -depth 8", @thumb.convert_options end it "sends the right command to convert when sent #make" do expect(@thumb).to receive(:convert) do |*arg| arg[0] == ':source -auto-orient -resize "x50" -crop "100x50+114+0" +repage -strip -depth 8 :dest' && arg[1][:source] == "#{File.expand_path(@thumb.file.path)}[0]" end @thumb.make end it "creates the thumbnail when sent #make" do dst = @thumb.make assert_match /100x50/, `identify "#{dst.path}"` end context "redefined to have bad convert_options setting" do before do @thumb = Paperclip::Thumbnail.new(@file, geometry: "100x50#", convert_options: "-this-aint-no-option") end it "errors when trying to create the thumbnail" do silence_stream(STDERR) do expect do @thumb.make end.to raise_error( Paperclip::Error, /unrecognized option `-this-aint-no-option'/ ) end end it "lets us know when a command isn't found versus a processing error" do old_path = ENV["PATH"] begin Terrapin::CommandLine.path = "" Paperclip.options[:command_path] = "" ENV["PATH"] = "" assert_raises(Paperclip::Errors::CommandNotFoundError) do silence_stream(STDERR) do @thumb.make end end ensure ENV["PATH"] = old_path end end end end context "being thumbnailed with a blank geometry string" do before do @thumb = Paperclip::Thumbnail.new(@file, geometry: "", convert_options: "-gravity center -crop \"300x300+0-0\"") end it "does not get resized by default" do assert !@thumb.transformation_command.include?("-resize") end end context "being thumbnailed with default animated option (true)" do it "calls identify to check for animated images when sent #make" do thumb = Paperclip::Thumbnail.new(@file, geometry: "100x50#") expect(thumb).to receive(:identify).at_least(1).times do |*arg| arg[0] == "-format %m :file" && arg[1][:file] == "#{File.expand_path(thumb.file.path)}[0]" end thumb.make end end context "passing a custom file geometry parser" do after do Object.send(:remove_const, :GeoParser) if Object.const_defined?(:GeoParser) end it "produces the appropriate transformation_command" do GeoParser = Class.new do def self.from_file(_file) new end def transformation_to(_target, _should_crop) ["SCALE", "CROP"] end end thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", file_geometry_parser: ::GeoParser) transformation_command = thumb.transformation_command assert transformation_command.include?("-crop"), %{expected #{transformation_command.inspect} to include '-crop'} assert transformation_command.include?('"CROP"'), %{expected #{transformation_command.inspect} to include '"CROP"'} assert transformation_command.include?("-resize"), %{expected #{transformation_command.inspect} to include '-resize'} assert transformation_command.include?('"SCALE"'), %{expected #{transformation_command.inspect} to include '"SCALE"'} end end context "passing a custom geometry string parser" do after do Object.send(:remove_const, :GeoParser) if Object.const_defined?(:GeoParser) end it "produces the appropriate transformation_command" do GeoParser = Class.new do def self.parse(_s) new end def to_s "151x167" end end thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", string_geometry_parser: ::GeoParser) transformation_command = thumb.transformation_command assert transformation_command.include?('"151x167"'), %{expected #{transformation_command.inspect} to include '151x167'} end end end context "A multipage PDF" do before do @file = File.new(fixture_file("twopage.pdf"), "rb") end after { @file.close } it "starts with two pages with dimensions 612x792" do cmd = %[identify -format "%wx%h" "#{@file.path}"] assert_equal "612x792" * 2, `#{cmd}`.chomp end context "being thumbnailed at 100x100 with cropping" do before do @thumb = Paperclip::Thumbnail.new(@file, geometry: "100x100#", format: :png) end it "reports its correct current and target geometries" do assert_equal "100x100#", @thumb.target_geometry.to_s assert_equal "612x792", @thumb.current_geometry.to_s end it "reports its correct format" do assert_equal :png, @thumb.format end it "creates the thumbnail when sent #make" do dst = @thumb.make assert_match /100x100/, `identify "#{dst.path}"` end end end context "An animated gif" do before do @file = File.new(fixture_file("animated.gif"), "rb") end after { @file.close } it "starts with 12 frames with size 100x100" do cmd = %[identify -format "%wx%h" "#{@file.path}"] assert_equal "100x100" * 12, `#{cmd}`.chomp end context "with static output" do before do @thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", format: :jpg) end it "creates the single frame thumbnail when sent #make" do dst = @thumb.make cmd = %[identify -format "%wx%h" "#{dst.path}"] assert_equal "50x50", `#{cmd}`.chomp end end context "with animated output format" do before do @thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", format: :gif) end it "creates the 12 frames thumbnail when sent #make" do dst = @thumb.make cmd = %[identify -format "%wx%h," "#{dst.path}"] frames = `#{cmd}`.chomp.split(",") assert_equal 12, frames.size assert_frame_dimensions (45..50), frames end it "uses the -coalesce option" do assert_equal @thumb.transformation_command.first, "-coalesce" end it "uses the -layers 'optimize' option" do assert_equal @thumb.transformation_command.last, '-layers "optimize"' end end context "with omitted output format" do before do @thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50") end it "creates the 12 frames thumbnail when sent #make" do dst = @thumb.make cmd = %[identify -format "%wx%h," "#{dst.path}"] frames = `#{cmd}`.chomp.split(",") assert_equal 12, frames.size assert_frame_dimensions (45..50), frames end it "uses the -coalesce option" do assert_equal @thumb.transformation_command.first, "-coalesce" end it "uses the -layers 'optimize' option" do assert_equal @thumb.transformation_command.last, '-layers "optimize"' end end context "with unidentified source format" do before do @unidentified_file = File.new(fixture_file("animated.unknown"), "rb") @thumb = Paperclip::Thumbnail.new(@file, geometry: "60x60") end it "creates the 12 frames thumbnail when sent #make" do dst = @thumb.make cmd = %[identify -format "%wx%h," "#{dst.path}"] frames = `#{cmd}`.chomp.split(",") assert_equal 12, frames.size assert_frame_dimensions (55..60), frames end it "uses the -coalesce option" do assert_equal @thumb.transformation_command.first, "-coalesce" end it "uses the -layers 'optimize' option" do assert_equal @thumb.transformation_command.last, '-layers "optimize"' end end context "with no source format" do before do @unidentified_file = File.new(fixture_file("animated"), "rb") @thumb = Paperclip::Thumbnail.new(@file, geometry: "70x70") end it "creates the 12 frames thumbnail when sent #make" do dst = @thumb.make cmd = %[identify -format "%wx%h," "#{dst.path}"] frames = `#{cmd}`.chomp.split(",") assert_equal 12, frames.size assert_frame_dimensions (60..70), frames end it "uses the -coalesce option" do assert_equal @thumb.transformation_command.first, "-coalesce" end it "uses the -layers 'optimize' option" do assert_equal @thumb.transformation_command.last, '-layers "optimize"' end end context "with animated option set to false" do before do @thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", animated: false) end it "outputs the gif format" do dst = @thumb.make cmd = %[identify "#{dst.path}"] assert_match /GIF/, `#{cmd}`.chomp end it "creates the single frame thumbnail when sent #make" do dst = @thumb.make cmd = %[identify -format "%wx%h" "#{dst.path}"] assert_equal "50x50", `#{cmd}`.chomp end end context "with a specified frame_index" do before do @thumb = Paperclip::Thumbnail.new( @file, geometry: "50x50", frame_index: 5, format: :jpg ) end it "creates the thumbnail from the frame index when sent #make" do @thumb.make assert_equal 5, @thumb.frame_index end end context "with a specified frame_index out of bounds" do before do @thumb = Paperclip::Thumbnail.new( @file, geometry: "50x50", frame_index: 20, format: :jpg ) end it "errors when trying to create the thumbnail" do assert_raises(Paperclip::Error) do silence_stream(STDERR) do @thumb.make end end end end end context "with a really long file name" do before do tempfile = Tempfile.new("f") tempfile_additional_chars = tempfile.path.split("/")[-1].length + 15 image_file = File.new(fixture_file("5k.png"), "rb") @file = Tempfile.new("f" * (255 - tempfile_additional_chars)) @file.write(image_file.read) @file.rewind end it "does not throw Errno::ENAMETOOLONG" do thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", format: :gif) expect { thumb.make }.to_not raise_error end end end