Commit 6f468830 authored by Gabriel Mazetto's avatar Gabriel Mazetto

Fix existing Uploader specs

Our current specs base are in many cases, not testing uploads correctly.

There are many variations on how uploads behave, depending on which
Uploader and which model it is related to, but because our test cases
have mocked important pieces, it was never testing them.

This fixes that by removing mocks and making the required adjustments.
parent 4e2fd07e
...@@ -19,7 +19,7 @@ class AvatarUploader < GitlabUploader ...@@ -19,7 +19,7 @@ class AvatarUploader < GitlabUploader
end end
def absolute_path def absolute_path
self.class.absolute_path(model.avatar.upload) self.class.absolute_path(upload)
end end
private private
......
...@@ -9,10 +9,6 @@ describe Gitlab::Geo::Replication::FileRetriever, :geo do ...@@ -9,10 +9,6 @@ describe Gitlab::Geo::Replication::FileRetriever, :geo do
context 'when the upload exists' do context 'when the upload exists' do
let(:retriever) { described_class.new(upload.id, message) } let(:retriever) { described_class.new(upload.id, message) }
before do
expect(Upload).to receive(:find_by).with(id: upload.id).and_return(upload)
end
context 'when the upload has a file' do context 'when the upload has a file' do
before do before do
FileUtils.mkdir_p(File.dirname(upload.absolute_path)) FileUtils.mkdir_p(File.dirname(upload.absolute_path))
...@@ -24,7 +20,7 @@ describe Gitlab::Geo::Replication::FileRetriever, :geo do ...@@ -24,7 +20,7 @@ describe Gitlab::Geo::Replication::FileRetriever, :geo do
it 'returns the file in a success hash' do it 'returns the file in a success hash' do
expect(subject).to include(code: :ok, message: 'Success') expect(subject).to include(code: :ok, message: 'Success')
expect(subject[:file].file).to eq(upload.absolute_path) expect(subject[:file].file.path).to eq(upload.absolute_path)
end end
end end
...@@ -74,19 +70,19 @@ describe Gitlab::Geo::Replication::FileRetriever, :geo do ...@@ -74,19 +70,19 @@ describe Gitlab::Geo::Replication::FileRetriever, :geo do
describe '#execute' do describe '#execute' do
context 'user avatar' do context 'user avatar' do
it_behaves_like "returns necessary params for sending a file from an API endpoint" do it_behaves_like "returns necessary params for sending a file from an API endpoint" do
let(:upload) { create(:upload, model: build(:user)) } let(:upload) { create(:upload, model: create(:user)) }
end end
end end
context 'group avatar' do context 'group avatar' do
it_behaves_like "returns necessary params for sending a file from an API endpoint" do it_behaves_like "returns necessary params for sending a file from an API endpoint" do
let(:upload) { create(:upload, model: build(:group)) } let(:upload) { create(:upload, model: create(:group)) }
end end
end end
context 'project avatar' do context 'project avatar' do
it_behaves_like "returns necessary params for sending a file from an API endpoint" do it_behaves_like "returns necessary params for sending a file from an API endpoint" do
let(:upload) { create(:upload, model: build(:project)) } let(:upload) { create(:upload, model: create(:project)) }
end end
end end
......
...@@ -39,9 +39,10 @@ describe Geo::UploadRegistry, :geo, :geo_fdw do ...@@ -39,9 +39,10 @@ describe Geo::UploadRegistry, :geo, :geo_fdw do
describe '#file' do describe '#file' do
it 'returns the path of the upload of a registry' do it 'returns the path of the upload of a registry' do
registry = create(:geo_upload_registry, :file, :with_file) upload = create(:upload, :with_file)
registry = create(:geo_upload_registry, :file, file_id: upload.id)
expect(registry.file).to eq('uploads/-/system/project/avatar/avatar.jpg') expect(registry.file).to eq("uploads/-/system/project/avatar/#{upload.id}/avatar.jpg")
end end
it 'return "removed" message when the upload no longer exists' do it 'return "removed" message when the upload no longer exists' do
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
FactoryBot.define do FactoryBot.define do
factory :upload do factory :upload do
model { build(:project) } model { create(:project) }
size { 100.kilobytes } size { 100.kilobytes }
uploader { "AvatarUploader" } uploader { "AvatarUploader" }
mount_point { :avatar } mount_point { :avatar }
...@@ -11,23 +11,27 @@ FactoryBot.define do ...@@ -11,23 +11,27 @@ FactoryBot.define do
# we should build a mount agnostic upload by default # we should build a mount agnostic upload by default
transient do transient do
filename { 'myfile.jpg' } filename { 'avatar.jpg' }
end end
# this needs to comply with RecordsUpload::Concern#upload_path path do
path { File.join("uploads/-/system", model.class.underscore, mount_point.to_s, 'avatar.jpg') } uploader_instance = Object.const_get(uploader.to_s).new(model, mount_point)
File.join(uploader_instance.store_dir, filename)
end
trait :personal_snippet_upload do trait :personal_snippet_upload do
uploader { "PersonalFileUploader" } model { create(:personal_snippet) }
path { File.join(secret, filename) } path { File.join(secret, filename) }
model { build(:personal_snippet) } uploader { "PersonalFileUploader" }
secret { SecureRandom.hex } secret { SecureRandom.hex }
mount_point { nil }
end end
trait :issuable_upload do trait :issuable_upload do
uploader { "FileUploader" } uploader { "FileUploader" }
path { File.join(secret, filename) } path { File.join(secret, filename) }
secret { SecureRandom.hex } secret { SecureRandom.hex }
mount_point { nil }
end end
trait :with_file do trait :with_file do
...@@ -42,22 +46,23 @@ FactoryBot.define do ...@@ -42,22 +46,23 @@ FactoryBot.define do
end end
trait :namespace_upload do trait :namespace_upload do
model { build(:group) } model { create(:group) }
path { File.join(secret, filename) } path { File.join(secret, filename) }
uploader { "NamespaceFileUploader" } uploader { "NamespaceFileUploader" }
secret { SecureRandom.hex } secret { SecureRandom.hex }
mount_point { nil }
end end
trait :favicon_upload do trait :favicon_upload do
model { build(:appearance) } model { create(:appearance) }
path { File.join(secret, filename) }
uploader { "FaviconUploader" } uploader { "FaviconUploader" }
secret { SecureRandom.hex } secret { SecureRandom.hex }
mount_point { :favicon }
end end
trait :attachment_upload do trait :attachment_upload do
mount_point { :attachment } mount_point { :attachment }
model { build(:note) } model { create(:note) }
uploader { "AttachmentUploader" } uploader { "AttachmentUploader" }
end end
end end
......
...@@ -41,7 +41,8 @@ shared_examples_for 'model with uploads' do |supports_fileuploads| ...@@ -41,7 +41,8 @@ shared_examples_for 'model with uploads' do |supports_fileuploads|
end end
it 'deletes remote files' do it 'deletes remote files' do
expect_any_instance_of(Uploads::Fog).to receive(:delete_keys).with(uploads.map(&:path)) expected_array = array_including(*uploads.map(&:path))
expect_any_instance_of(Uploads::Fog).to receive(:delete_keys).with(expected_array)
model_object.destroy model_object.destroy
end end
......
...@@ -42,33 +42,23 @@ describe ObjectStorage::MigrateUploadsWorker, :sidekiq do ...@@ -42,33 +42,23 @@ describe ObjectStorage::MigrateUploadsWorker, :sidekiq do
end end
describe '.sanity_check!' do describe '.sanity_check!' do
shared_examples 'raises a SanityCheckError' do shared_examples 'raises a SanityCheckError' do |expected_message|
let(:mount_point) { nil } let(:mount_point) { nil }
it do it do
expect { described_class.sanity_check!(uploads, model_class, mount_point) } expect { described_class.sanity_check!(uploads, model_class, mount_point) }
.to raise_error(described_class::SanityCheckError) .to raise_error(described_class::SanityCheckError).with_message(expected_message)
end end
end end
before do
stub_const("WrongModel", Class.new)
end
context 'uploader types mismatch' do context 'uploader types mismatch' do
let!(:outlier) { create(:upload, uploader: 'GitlabUploader') } let!(:outlier) { create(:upload, uploader: 'GitlabUploader') }
include_examples 'raises a SanityCheckError' include_examples 'raises a SanityCheckError', /Multiple uploaders found/
end
context 'model types mismatch' do
let!(:outlier) { create(:upload, model_type: 'WrongModel') }
include_examples 'raises a SanityCheckError'
end end
context 'mount point not found' do context 'mount point not found' do
include_examples 'raises a SanityCheckError' do include_examples 'raises a SanityCheckError', /Mount point [a-z:]+ not found in/ do
let(:mount_point) { :potato } let(:mount_point) { :potato }
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment