diff options
Diffstat (limited to 'spec/models/upload_spec.rb')
-rw-r--r-- | spec/models/upload_spec.rb | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/spec/models/upload_spec.rb b/spec/models/upload_spec.rb new file mode 100644 index 00000000000..4c832c87d6a --- /dev/null +++ b/spec/models/upload_spec.rb @@ -0,0 +1,151 @@ +require 'rails_helper' + +describe Upload, type: :model do + describe 'assocations' do + it { is_expected.to belong_to(:model) } + end + + describe 'validations' do + it { is_expected.to validate_presence_of(:size) } + it { is_expected.to validate_presence_of(:path) } + it { is_expected.to validate_presence_of(:model) } + it { is_expected.to validate_presence_of(:uploader) } + end + + describe 'callbacks' do + context 'for a file above the checksum threshold' do + it 'schedules checksum calculation' do + stub_const('UploadChecksumWorker', spy) + + upload = described_class.create( + path: __FILE__, + size: described_class::CHECKSUM_THRESHOLD + 1.kilobyte, + model: build_stubbed(:user), + uploader: double('ExampleUploader') + ) + + expect(UploadChecksumWorker) + .to have_received(:perform_async).with(upload.id) + end + end + + context 'for a file at or below the checksum threshold' do + it 'calculates checksum immediately before save' do + upload = described_class.new( + path: __FILE__, + size: described_class::CHECKSUM_THRESHOLD, + model: build_stubbed(:user), + uploader: double('ExampleUploader') + ) + + expect { upload.save } + .to change { upload.checksum }.from(nil) + .to(a_string_matching(/\A\h{64}\z/)) + end + end + end + + describe '.remove_path' do + it 'removes all records at the given path' do + described_class.create!( + size: File.size(__FILE__), + path: __FILE__, + model: build_stubbed(:user), + uploader: 'AvatarUploader' + ) + + expect { described_class.remove_path(__FILE__) }. + to change { described_class.count }.from(1).to(0) + end + end + + describe '.record' do + let(:fake_uploader) do + double( + file: double(size: 12_345), + relative_path: 'foo/bar.jpg', + model: build_stubbed(:user), + class: 'AvatarUploader' + ) + end + + it 'removes existing paths before creation' do + expect(described_class).to receive(:remove_path) + .with(fake_uploader.relative_path) + + described_class.record(fake_uploader) + end + + it 'creates a new record and assigns size, path, model, and uploader' do + upload = described_class.record(fake_uploader) + + aggregate_failures do + expect(upload).to be_persisted + expect(upload.size).to eq fake_uploader.file.size + expect(upload.path).to eq fake_uploader.relative_path + expect(upload.model_id).to eq fake_uploader.model.id + expect(upload.model_type).to eq fake_uploader.model.class.to_s + expect(upload.uploader).to eq fake_uploader.class + end + end + end + + describe '#absolute_path' do + it 'returns the path directly when already absolute' do + path = '/path/to/namespace/project/secret/file.jpg' + upload = described_class.new(path: path) + + expect(upload).not_to receive(:uploader_class) + + expect(upload.absolute_path).to eq path + end + + it "delegates to the uploader's absolute_path method" do + uploader = spy('FakeUploader') + upload = described_class.new(path: 'secret/file.jpg') + expect(upload).to receive(:uploader_class).and_return(uploader) + + upload.absolute_path + + expect(uploader).to have_received(:absolute_path).with(upload) + end + end + + describe '#calculate_checksum' do + it 'calculates the SHA256 sum' do + upload = described_class.new( + path: __FILE__, + size: described_class::CHECKSUM_THRESHOLD - 1.megabyte + ) + expected = Digest::SHA256.file(__FILE__).hexdigest + + expect { upload.calculate_checksum } + .to change { upload.checksum }.from(nil).to(expected) + end + + it 'returns nil for a non-existant file' do + upload = described_class.new( + path: __FILE__, + size: described_class::CHECKSUM_THRESHOLD - 1.megabyte + ) + + expect(upload).to receive(:exist?).and_return(false) + + expect(upload.calculate_checksum).to be_nil + end + end + + describe '#exist?' do + it 'returns true when the file exists' do + upload = described_class.new(path: __FILE__) + + expect(upload).to exist + end + + it 'returns false when the file does not exist' do + upload = described_class.new(path: "#{__FILE__}-nope") + + expect(upload).not_to exist + end + end +end |