Otherwise this leaves it enabled if the processing failed, which then makes other specs fail where they expect the image not being processed (for example still have the initial set dimensions, instead of the one read from image after processing).
287 lines
8.4 KiB
Ruby
287 lines
8.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
|
# licensed under the Affero General Public License version 3 or later. See
|
|
# the COPYRIGHT file.
|
|
|
|
def with_carrierwave_processing(&block)
|
|
UnprocessedImage.enable_processing = true
|
|
yield
|
|
ensure
|
|
UnprocessedImage.enable_processing = false
|
|
end
|
|
|
|
describe Photo, :type => :model do
|
|
before do
|
|
@user = alice
|
|
@aspect = @user.aspects.first
|
|
|
|
@fixture_filename = 'button.png'
|
|
|
|
@fixture_name = File.join(File.dirname(__FILE__), '..', 'fixtures', @fixture_filename)
|
|
@fail_fixture_name = File.join(File.dirname(__FILE__), '..', 'fixtures', 'msg.xml')
|
|
|
|
@photo = @user.build_post(:photo, user_file: File.open(@fixture_name), to: @aspect.id)
|
|
@photo2 = @user.build_post(:photo, user_file: File.open(@fixture_name), to: @aspect.id)
|
|
@saved_photo = @user.build_post(:photo, user_file: File.open(@fixture_name), to: @aspect.id)
|
|
@saved_photo.save
|
|
end
|
|
|
|
describe 'after_create' do
|
|
it 'calls #queue_processing_job' do
|
|
expect(@photo).to receive(:queue_processing_job)
|
|
|
|
@photo.save!
|
|
end
|
|
end
|
|
|
|
it 'has a random string key' do
|
|
expect(@photo2.random_string).not_to be nil
|
|
end
|
|
|
|
describe '#diaspora_initialize' do
|
|
before do
|
|
@image = File.open(@fixture_name)
|
|
@photo = Photo.diaspora_initialize(author: @user.person, user_file: @image)
|
|
end
|
|
|
|
it 'sets the persons diaspora handle' do
|
|
expect(@photo.diaspora_handle).to eq(@user.person.diaspora_handle)
|
|
end
|
|
|
|
it 'sets the random prefix' do
|
|
photo_double = double.as_null_object
|
|
expect(photo_double).to receive(:random_string=)
|
|
allow(Photo).to receive(:new).and_return(photo_double)
|
|
|
|
Photo.diaspora_initialize(
|
|
:author => @user.person, :user_file => @image)
|
|
end
|
|
|
|
context "with user file" do
|
|
it 'builds the photo without saving' do
|
|
expect(@photo.created_at.nil?).to be true
|
|
expect(@photo.unprocessed_image.read.nil?).to be false
|
|
end
|
|
end
|
|
|
|
context "with a url" do
|
|
it 'saves the photo' do
|
|
url = "https://service.com/user/profile_image"
|
|
|
|
photo_double = double.as_null_object
|
|
expect(photo_double).to receive(:remote_unprocessed_image_url=).with(url)
|
|
allow(Photo).to receive(:new).and_return(photo_double)
|
|
|
|
Photo.diaspora_initialize(
|
|
:author => @user.person, :image_url => url)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe '#update_remote_path' do
|
|
before do
|
|
image = File.open(@fixture_name)
|
|
@photo = Photo.diaspora_initialize(
|
|
:author => @user.person, :user_file => image)
|
|
@photo.processed_image.store!(@photo.unprocessed_image)
|
|
@photo.save!
|
|
end
|
|
it 'sets a remote url' do
|
|
@photo.update_remote_path
|
|
|
|
expect(@photo.remote_photo_path).to include("http")
|
|
expect(@photo.remote_photo_name).to include(".webp")
|
|
end
|
|
end
|
|
|
|
it 'should save a photo' do
|
|
@photo.unprocessed_image.store! File.open(@fixture_name)
|
|
expect(@photo.save).to eq(true)
|
|
|
|
binary = @photo.unprocessed_image.read.force_encoding('BINARY')
|
|
fixture_binary = File.read(@fixture_name).force_encoding('BINARY')
|
|
|
|
expect(binary).to eq(fixture_binary)
|
|
end
|
|
|
|
context 'with a saved photo' do
|
|
before do
|
|
with_carrierwave_processing do
|
|
@photo.unprocessed_image.store! File.open(@fixture_name)
|
|
end
|
|
end
|
|
|
|
it 'should have text' do
|
|
@photo.text= "cool story, bro"
|
|
expect(@photo.save).to be true
|
|
end
|
|
|
|
it 'should remove its reference in user profile if it is referred' do
|
|
@photo.save
|
|
|
|
@user.profile.image_url = @photo.url(:thumb_large)
|
|
@user.person.save
|
|
@photo.destroy
|
|
expect(Person.find(@user.person.id).profile[:image_url]).to be_nil
|
|
end
|
|
|
|
it 'should not use the imported filename as the url' do
|
|
expect(@photo.url).not_to include @fixture_filename
|
|
expect(@photo.url(:thumb_medium)).not_to include ("/" + @fixture_filename)
|
|
end
|
|
|
|
it 'should save the image dimensions' do
|
|
expect(@photo.width).to eq(40)
|
|
expect(@photo.height).to eq(40)
|
|
end
|
|
end
|
|
|
|
context 'with a saved photo containing EXIF data' do
|
|
|
|
let(:base_path) { File.dirname(__FILE__) }
|
|
let(:public_path) { File.join(base_path, "../../public/") }
|
|
let(:photo_with_exif) { File.open(File.join(base_path, "..", "fixtures", "exif.jpg")) }
|
|
|
|
after do
|
|
FileUtils.rm_r Dir.glob(File.join(public_path, "uploads/images/*"))
|
|
end
|
|
|
|
it "should strip EXIF data" do
|
|
image = image_from a_photo_sent_by(bob)
|
|
|
|
expect(image.exif.length).to eq(0)
|
|
end
|
|
|
|
def a_photo_sent_by(user)
|
|
photo = user.build_post(:photo, user_file: photo_with_exif, to: @aspect.id)
|
|
|
|
with_carrierwave_processing do
|
|
photo.unprocessed_image.store! photo_with_exif
|
|
photo.save
|
|
end
|
|
|
|
photo
|
|
end
|
|
|
|
def image_from(photo)
|
|
photo_path = File.join(public_path, photo.unprocessed_image.store_dir, photo.unprocessed_image.filename)
|
|
MiniMagick::Image.new(photo_path)
|
|
end
|
|
end
|
|
|
|
describe 'non-image files' do
|
|
it 'should not store' do
|
|
file = File.open(@fail_fixture_name)
|
|
expect {
|
|
@photo.unprocessed_image.store! file
|
|
}.to raise_error CarrierWave::IntegrityError
|
|
end
|
|
end
|
|
|
|
describe "converting files" do
|
|
it "convert to webp" do
|
|
with_carrierwave_processing do
|
|
@photo.unprocessed_image.store! File.open(@fixture_name)
|
|
end
|
|
expect(@photo.remote_photo_name).to include(".webp")
|
|
end
|
|
end
|
|
|
|
describe "remote photos" do
|
|
it "should set the remote_photo on marshalling" do
|
|
url = @saved_photo.url
|
|
thumb_url = @saved_photo.url :thumb_medium
|
|
|
|
@saved_photo.height = 42
|
|
@saved_photo.width = 23
|
|
|
|
federation_photo = Diaspora::Federation::Entities.photo(@saved_photo)
|
|
|
|
@saved_photo.destroy
|
|
|
|
Diaspora::Federation::Receive.perform(federation_photo)
|
|
|
|
new_photo = Photo.find_by(guid: @saved_photo.guid)
|
|
expect(new_photo.url).to eq(url)
|
|
expect(new_photo.url(:thumb_medium)).to eq(thumb_url)
|
|
end
|
|
end
|
|
|
|
describe '#queue_processing_job' do
|
|
it 'should queue a job to process the images' do
|
|
expect(Workers::ProcessPhoto).to receive(:perform_async).with(@photo.id)
|
|
@photo.queue_processing_job
|
|
end
|
|
end
|
|
|
|
context "deletion" do
|
|
before do
|
|
@status_message = @user.build_post(:status_message, :text => "", :to => @aspect.id)
|
|
@status_message.photos << @photo2
|
|
@status_message.save
|
|
@status_message.reload
|
|
end
|
|
|
|
it 'is deleted with parent status message' do
|
|
expect {
|
|
@status_message.destroy
|
|
}.to change(Photo, :count).by(-1)
|
|
end
|
|
|
|
it 'will delete parent status message if message is otherwise empty' do
|
|
expect {
|
|
@photo2.destroy
|
|
}.to change(StatusMessage, :count).by(-1)
|
|
end
|
|
|
|
it 'will not delete parent status message if message had other content' do
|
|
@status_message.text = "Some text"
|
|
@status_message.save
|
|
@status_message.reload
|
|
|
|
expect {
|
|
@photo2.status_message.reload
|
|
@photo2.destroy
|
|
}.to_not change(StatusMessage, :count)
|
|
end
|
|
end
|
|
|
|
describe "#visible" do
|
|
context "with a current user" do
|
|
it "calls photos_from" do
|
|
expect(@user).to receive(:photos_from).with(@user.person, limit: :all, max_time: nil).and_call_original
|
|
Photo.visible(@user, @user.person)
|
|
end
|
|
|
|
it "does not contain pending photos" do
|
|
pending_photo = @user.post(:photo, pending: true, user_file: File.open(photo_fixture_name), to: @aspect)
|
|
expect(Photo.visible(@user, @user.person).ids).not_to include(pending_photo.id)
|
|
end
|
|
end
|
|
|
|
context "without a current user" do
|
|
it "returns all public photos" do
|
|
expect(Photo).to receive(:where).with(author_id: @user.person.id, public: true).and_call_original
|
|
Photo.visible(nil, @user.person)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "with a maliciously crafted image" do
|
|
let(:base_path) { File.dirname(__FILE__) }
|
|
let(:public_path) { File.join(base_path, "../../public/") }
|
|
let(:evil_image) { File.open(File.join(base_path, "..", "fixtures", "evil-image.ps.png")) }
|
|
|
|
it "fails to process a PostScript file camouflaged as a PNG" do
|
|
photo = bob.build_post(:photo, user_file: evil_image, to: @aspect.id)
|
|
|
|
expect {
|
|
with_carrierwave_processing do
|
|
photo.unprocessed_image.store! evil_image
|
|
photo.save
|
|
end
|
|
}.to raise_error(CarrierWave::ProcessingError)
|
|
end
|
|
end
|
|
end
|