summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/com_spec_helper.rb3
-rw-r--r--spec/factories/uploads.rb25
-rw-r--r--spec/fast_spec_helper.rb2
-rw-r--r--spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb31
-rw-r--r--spec/frontend/commit/__snapshots__/commit_pipeline_status_component_spec.js.snap39
-rw-r--r--spec/frontend/commit/commit_pipeline_status_component_spec.js39
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js127
-rw-r--r--spec/frontend/create_cluster/eks_cluster/store/actions_spec.js27
-rw-r--r--spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js9
-rw-r--r--spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/uploads_manager_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/uploads_restorer_spec.rb4
-rw-r--r--spec/lib/gitlab/sanitizers/exif_spec.rb2
-rw-r--r--spec/lib/gitlab_spec.rb12
-rw-r--r--spec/models/commit_collection_spec.rb11
-rw-r--r--spec/models/upload_spec.rb48
-rw-r--r--spec/models/uploads/fog_spec.rb2
-rw-r--r--spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/with_uploads_shared_examples.rb3
-rw-r--r--spec/uploaders/file_uploader_spec.rb10
-rw-r--r--spec/uploaders/gitlab_uploader_spec.rb10
-rw-r--r--spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb18
23 files changed, 334 insertions, 96 deletions
diff --git a/spec/com_spec_helper.rb b/spec/com_spec_helper.rb
new file mode 100644
index 00000000000..f71ccde9509
--- /dev/null
+++ b/spec/com_spec_helper.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+Settings.gitlab[:url] = "https://test.gitlab.com"
diff --git a/spec/factories/uploads.rb b/spec/factories/uploads.rb
index bfe02c6010b..ef464d3d6e0 100644
--- a/spec/factories/uploads.rb
+++ b/spec/factories/uploads.rb
@@ -2,7 +2,7 @@
FactoryBot.define do
factory :upload do
- model { build(:project) }
+ model { create(:project) }
size { 100.kilobytes }
uploader { "AvatarUploader" }
mount_point { :avatar }
@@ -11,23 +11,27 @@ FactoryBot.define do
# we should build a mount agnostic upload by default
transient do
- filename { 'myfile.jpg' }
+ filename { 'avatar.jpg' }
end
- # this needs to comply with RecordsUpload::Concern#upload_path
- path { File.join("uploads/-/system", model.class.underscore, mount_point.to_s, 'avatar.jpg') }
+ path do
+ 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
- uploader { "PersonalFileUploader" }
+ model { create(:personal_snippet) }
path { File.join(secret, filename) }
- model { build(:personal_snippet) }
+ uploader { "PersonalFileUploader" }
secret { SecureRandom.hex }
+ mount_point { nil }
end
trait :issuable_upload do
uploader { "FileUploader" }
path { File.join(secret, filename) }
secret { SecureRandom.hex }
+ mount_point { nil }
end
trait :with_file do
@@ -42,22 +46,23 @@ FactoryBot.define do
end
trait :namespace_upload do
- model { build(:group) }
+ model { create(:group) }
path { File.join(secret, filename) }
uploader { "NamespaceFileUploader" }
secret { SecureRandom.hex }
+ mount_point { nil }
end
trait :favicon_upload do
- model { build(:appearance) }
- path { File.join(secret, filename) }
+ model { create(:appearance) }
uploader { "FaviconUploader" }
secret { SecureRandom.hex }
+ mount_point { :favicon }
end
trait :attachment_upload do
mount_point { :attachment }
- model { build(:note) }
+ model { create(:note) }
uploader { "AttachmentUploader" }
end
end
diff --git a/spec/fast_spec_helper.rb b/spec/fast_spec_helper.rb
index f5a487b4d57..a7810d72671 100644
--- a/spec/fast_spec_helper.rb
+++ b/spec/fast_spec_helper.rb
@@ -5,10 +5,12 @@ ENV['IN_MEMORY_APPLICATION_SETTINGS'] = 'true'
require 'active_support/dependencies'
require_relative '../config/initializers/0_inject_enterprise_edition_module'
+require_relative '../config/initializers/0_inject_com_module'
require_relative '../config/settings'
require_relative 'support/rspec'
require 'active_support/all'
ActiveSupport::Dependencies.autoload_paths << 'lib'
ActiveSupport::Dependencies.autoload_paths << 'ee/lib'
+ActiveSupport::Dependencies.autoload_paths << 'com/lib'
ActiveSupport::XmlMini.backend = 'Nokogiri'
diff --git a/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb b/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb
new file mode 100644
index 00000000000..26984a1fb5e
--- /dev/null
+++ b/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+# This is a feature spec because the problems arrise when rendering the view for
+# an actual project for which the repository is removed but the cached not
+# updated.
+# This can occur when the fork a merge request is created from is in the process
+# of being destroyed.
+describe 'User views merged merge request from deleted fork' do
+ include ProjectForksHelper
+
+ let(:project) { create(:project, :repository) }
+ let(:source_project) { fork_project(project, nil, repository: true) }
+ let(:user) { project.owner }
+ let!(:merge_request) { create(:merge_request, :merged, source_project: source_project, target_project: project) }
+
+ before do
+ sign_in user
+
+ fork_owner = source_project.namespace.owners.first
+ # Place the source_project in the weird in between state
+ source_project.update_attribute(:pending_delete, true)
+ Projects::DestroyService.new(source_project, fork_owner, {}).__send__(:trash_repositories!)
+ end
+
+ it 'correctly shows the merge request' do
+ visit(merge_request_path(merge_request))
+
+ expect(page).to have_content(merge_request.title)
+ end
+end
diff --git a/spec/frontend/commit/__snapshots__/commit_pipeline_status_component_spec.js.snap b/spec/frontend/commit/__snapshots__/commit_pipeline_status_component_spec.js.snap
deleted file mode 100644
index 9199db69fed..00000000000
--- a/spec/frontend/commit/__snapshots__/commit_pipeline_status_component_spec.js.snap
+++ /dev/null
@@ -1,39 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Commit pipeline status component when polling is not successful renders not found CI icon without loader 1`] = `
-<div
- class="ci-status-link"
->
- <a>
- <ciicon-stub
- aria-label="Pipeline: not found"
- cssclasses=""
- data-container="body"
- data-original-title="Pipeline: not found"
- size="24"
- status="[object Object]"
- title=""
- />
- </a>
-</div>
-`;
-
-exports[`Commit pipeline status component when polling is successful renders CI icon without loader 1`] = `
-<div
- class="ci-status-link"
->
- <a
- href="/frontend-fixtures/pipelines-project/pipelines/47"
- >
- <ciicon-stub
- aria-label="Pipeline: pending"
- cssclasses=""
- data-container="body"
- data-original-title="Pipeline: pending"
- size="24"
- status="[object Object]"
- title=""
- />
- </a>
-</div>
-`;
diff --git a/spec/frontend/commit/commit_pipeline_status_component_spec.js b/spec/frontend/commit/commit_pipeline_status_component_spec.js
index 1768fd745c9..1736d1d0df8 100644
--- a/spec/frontend/commit/commit_pipeline_status_component_spec.js
+++ b/spec/frontend/commit/commit_pipeline_status_component_spec.js
@@ -2,6 +2,7 @@ import Visibility from 'visibilityjs';
import { GlLoadingIcon } from '@gitlab/ui';
import Poll from '~/lib/utils/poll';
import flash from '~/flash';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
import { shallowMount } from '@vue/test-utils';
import { getJSONFixture } from '../helpers/fixtures';
@@ -36,6 +37,10 @@ describe('Commit pipeline status component', () => {
});
};
+ const findLoader = () => wrapper.find(GlLoadingIcon);
+ const findLink = () => wrapper.find('a');
+ const findCiIcon = () => findLink().find(CiIcon);
+
afterEach(() => {
wrapper.destroy();
wrapper = null;
@@ -111,14 +116,14 @@ describe('Commit pipeline status component', () => {
it('shows the loading icon at start', () => {
createComponent();
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(findLoader().exists()).toBe(true);
pollConfig.successCallback({
data: { pipelines: [] },
});
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(findLoader().exists()).toBe(false);
});
});
@@ -130,8 +135,17 @@ describe('Commit pipeline status component', () => {
return wrapper.vm.$nextTick();
});
- it('renders CI icon without loader', () => {
- expect(wrapper.element).toMatchSnapshot();
+ it('does not render loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('renders link with href', () => {
+ expect(findLink().attributes('href')).toEqual(mockCiStatus.details_path);
+ });
+
+ it('renders CI icon', () => {
+ expect(findCiIcon().attributes('data-original-title')).toEqual('Pipeline: pending');
+ expect(findCiIcon().props('status')).toEqual(mockCiStatus);
});
});
@@ -140,8 +154,21 @@ describe('Commit pipeline status component', () => {
pollConfig.errorCallback();
});
- it('renders not found CI icon without loader', () => {
- expect(wrapper.element).toMatchSnapshot();
+ it('does not render loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('renders link with href', () => {
+ expect(findLink().attributes('href')).toBeUndefined();
+ });
+
+ it('renders not found CI icon', () => {
+ expect(findCiIcon().attributes('data-original-title')).toEqual('Pipeline: not found');
+ expect(findCiIcon().props('status')).toEqual({
+ text: 'not found',
+ icon: 'status_notfound',
+ group: 'notfound',
+ });
});
it('displays flash error message', () => {
diff --git a/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js b/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js
index 1bd16d356b9..cc7c6735a80 100644
--- a/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js
@@ -4,6 +4,7 @@ import Vue from 'vue';
import EksClusterConfigurationForm from '~/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue';
import RegionDropdown from '~/create_cluster/eks_cluster/components/region_dropdown.vue';
+import eksClusterFormState from '~/create_cluster/eks_cluster/store/state';
import clusterDropdownStoreState from '~/create_cluster/eks_cluster/store/cluster_dropdown/state';
const localVue = createLocalVue();
@@ -12,29 +13,59 @@ localVue.use(Vuex);
describe('EksClusterConfigurationForm', () => {
let store;
let actions;
+ let state;
let regionsState;
+ let vpcsState;
+ let subnetsState;
+ let vpcsActions;
let regionsActions;
+ let subnetsActions;
let vm;
beforeEach(() => {
+ state = eksClusterFormState();
actions = {
setRegion: jest.fn(),
setVpc: jest.fn(),
+ setSubnet: jest.fn(),
};
regionsActions = {
fetchItems: jest.fn(),
};
+ vpcsActions = {
+ fetchItems: jest.fn(),
+ };
+ subnetsActions = {
+ fetchItems: jest.fn(),
+ };
regionsState = {
...clusterDropdownStoreState(),
};
+ vpcsState = {
+ ...clusterDropdownStoreState(),
+ };
+ subnetsState = {
+ ...clusterDropdownStoreState(),
+ };
store = new Vuex.Store({
+ state,
actions,
modules: {
+ vpcs: {
+ namespaced: true,
+ state: vpcsState,
+ actions: vpcsActions,
+ },
regions: {
namespaced: true,
state: regionsState,
actions: regionsActions,
},
+ subnets: {
+ namespaced: true,
+ state: subnetsState,
+ actions: subnetsActions,
+ },
},
});
});
@@ -51,6 +82,8 @@ describe('EksClusterConfigurationForm', () => {
});
const findRegionDropdown = () => vm.find(RegionDropdown);
+ const findVpcDropdown = () => vm.find('[field-id="eks-vpc"]');
+ const findSubnetDropdown = () => vm.find('[field-id="eks-subnet"]');
describe('when mounted', () => {
it('fetches available regions', () => {
@@ -62,16 +95,72 @@ describe('EksClusterConfigurationForm', () => {
regionsState.isLoadingItems = true;
return Vue.nextTick().then(() => {
- expect(findRegionDropdown().props('loading')).toEqual(regionsState.isLoadingItems);
+ expect(findRegionDropdown().props('loading')).toBe(regionsState.isLoadingItems);
});
});
it('sets regions to RegionDropdown regions property', () => {
- expect(findRegionDropdown().props('regions')).toEqual(regionsState.items);
+ expect(findRegionDropdown().props('regions')).toBe(regionsState.items);
});
it('sets loadingRegionsError to RegionDropdown error property', () => {
- expect(findRegionDropdown().props('error')).toEqual(regionsState.loadingItemsError);
+ expect(findRegionDropdown().props('error')).toBe(regionsState.loadingItemsError);
+ });
+
+ it('disables VpcDropdown when no region is selected', () => {
+ expect(findVpcDropdown().props('disabled')).toBe(true);
+ });
+
+ it('enables VpcDropdown when no region is selected', () => {
+ state.selectedRegion = { name: 'west-1 ' };
+
+ return Vue.nextTick().then(() => {
+ expect(findVpcDropdown().props('disabled')).toBe(false);
+ });
+ });
+
+ it('sets isLoadingVpcs to VpcDropdown loading property', () => {
+ vpcsState.isLoadingItems = true;
+
+ return Vue.nextTick().then(() => {
+ expect(findVpcDropdown().props('loading')).toBe(vpcsState.isLoadingItems);
+ });
+ });
+
+ it('sets vpcs to VpcDropdown items property', () => {
+ expect(findVpcDropdown().props('items')).toBe(vpcsState.items);
+ });
+
+ it('sets loadingVpcsError to VpcDropdown hasErrors property', () => {
+ expect(findVpcDropdown().props('hasErrors')).toBe(vpcsState.loadingItemsError);
+ });
+
+ it('disables SubnetDropdown when no vpc is selected', () => {
+ expect(findSubnetDropdown().props('disabled')).toBe(true);
+ });
+
+ it('enables SubnetDropdown when a vpc is selected', () => {
+ state.selectedVpc = { name: 'vpc-1 ' };
+
+ return Vue.nextTick().then(() => {
+ expect(findSubnetDropdown().props('disabled')).toBe(false);
+ });
+ });
+
+ it('sets isLoadingSubnets to SubnetDropdown loading property', () => {
+ subnetsState.isLoadingItems = true;
+
+ return Vue.nextTick().then(() => {
+ expect(findSubnetDropdown().props('loading')).toBe(subnetsState.isLoadingItems);
+ });
+ });
+
+ it('sets subnets to SubnetDropdown items property', () => {
+ expect(findSubnetDropdown().props('items')).toBe(subnetsState.items);
+ });
+
+ it('sets loadingSubnetsError to SubnetDropdown hasErrors property', () => {
+ expect(findSubnetDropdown().props('hasErrors')).toBe(subnetsState.loadingItemsError);
});
describe('when region is selected', () => {
@@ -84,5 +173,37 @@ describe('EksClusterConfigurationForm', () => {
it('dispatches setRegion action', () => {
expect(actions.setRegion).toHaveBeenCalledWith(expect.anything(), { region }, undefined);
});
+
+ it('fetches available vpcs', () => {
+ expect(vpcsActions.fetchItems).toHaveBeenCalledWith(expect.anything(), { region }, undefined);
+ });
+ });
+
+ describe('when vpc is selected', () => {
+ const vpc = { name: 'vpc-1' };
+
+ beforeEach(() => {
+ findVpcDropdown().vm.$emit('input', vpc);
+ });
+
+ it('dispatches setVpc action', () => {
+ expect(actions.setVpc).toHaveBeenCalledWith(expect.anything(), { vpc }, undefined);
+ });
+
+ it('dispatches fetchSubnets action', () => {
+ expect(subnetsActions.fetchItems).toHaveBeenCalledWith(expect.anything(), { vpc }, undefined);
+ });
+ });
+
+ describe('when a subnet is selected', () => {
+ const subnet = { name: 'subnet-1' };
+
+ beforeEach(() => {
+ findSubnetDropdown().vm.$emit('input', subnet);
+ });
+
+ it('dispatches setSubnet action', () => {
+ expect(actions.setSubnet).toHaveBeenCalledWith(expect.anything(), { subnet }, undefined);
+ });
});
});
diff --git a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
index 3744ddb3dc6..893c657e699 100644
--- a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
@@ -1,17 +1,28 @@
import testAction from 'helpers/vuex_action_helper';
import createState from '~/create_cluster/eks_cluster/store/state';
-import * as types from '~/create_cluster/eks_cluster/store/mutation_types';
import * as actions from '~/create_cluster/eks_cluster/store/actions';
+import { SET_REGION, SET_VPC, SET_SUBNET } from '~/create_cluster/eks_cluster/store/mutation_types';
describe('EKS Cluster Store Actions', () => {
- describe('setRegion', () => {
- it(`commits ${types.SET_REGION} mutation`, () => {
- const region = { name: 'west-1' };
+ let region;
+ let vpc;
+ let subnet;
- testAction(actions.setRegion, { region }, createState(), [
- { type: types.SET_REGION, payload: { region } },
- ]);
- });
+ beforeEach(() => {
+ region = { name: 'regions-1' };
+ vpc = { name: 'vpc-1' };
+ subnet = { name: 'subnet-1' };
+ });
+
+ it.each`
+ action | mutation | payload | payloadDescription
+ ${'setRegion'} | ${SET_REGION} | ${{ region }} | ${'region'}
+ ${'setVpc'} | ${SET_VPC} | ${{ vpc }} | ${'vpc'}
+ ${'setSubnet'} | ${SET_SUBNET} | ${{ subnet }} | ${'subnet'}
+ `(`$action commits $mutation with $payloadDescription payload`, data => {
+ const { action, mutation, payload } = data;
+
+ testAction(actions[action], payload, createState(), [{ type: mutation, payload }]);
});
});
diff --git a/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js b/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js
index 99f05b0f449..38199471f79 100644
--- a/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js
@@ -1,19 +1,26 @@
-import { SET_REGION } from '~/create_cluster/eks_cluster/store/mutation_types';
+import { SET_REGION, SET_VPC, SET_SUBNET } from '~/create_cluster/eks_cluster/store/mutation_types';
import createState from '~/create_cluster/eks_cluster/store/state';
import mutations from '~/create_cluster/eks_cluster/store/mutations';
describe('Create EKS cluster store mutations', () => {
let state;
let region;
+ let vpc;
+ let subnet;
beforeEach(() => {
region = { name: 'regions-1' };
+ vpc = { name: 'vpc-1' };
+ subnet = { name: 'subnet-1' };
+
state = createState();
});
it.each`
mutation | mutatedProperty | payload | expectedValue | expectedValueDescription
${SET_REGION} | ${'selectedRegion'} | ${{ region }} | ${region} | ${'selected region payload'}
+ ${SET_VPC} | ${'selectedVpc'} | ${{ vpc }} | ${vpc} | ${'selected vpc payload'}
+ ${SET_SUBNET} | ${'selectedSubnet'} | ${{ subnet }} | ${subnet} | ${'selected sybnet payload'}
`(`$mutation sets $mutatedProperty to $expectedValueDescription`, data => {
const { mutation, mutatedProperty, payload, expectedValue } = data;
diff --git a/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb b/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb
index 7d67dc0251d..c1eaf1d3433 100644
--- a/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb
+++ b/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb
@@ -32,7 +32,7 @@ describe Gitlab::BackgroundMigration::LegacyUploadMover do
if with_file
upload = create(:upload, :with_file, :attachment_upload, params)
- model.update(attachment: upload.build_uploader)
+ model.update(attachment: upload.retrieve_uploader)
model.attachment.upload
else
create(:upload, :attachment_upload, params)
diff --git a/spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb b/spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb
index ed8cbfeb11f..cabca3dbef9 100644
--- a/spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb
+++ b/spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb
@@ -24,7 +24,7 @@ describe Gitlab::BackgroundMigration::LegacyUploadsMigrator do
if with_file
upload = create(:upload, :with_file, :attachment_upload, params)
- model.update(attachment: upload.build_uploader)
+ model.update(attachment: upload.retrieve_uploader)
model.attachment.upload
else
create(:upload, :attachment_upload, params)
diff --git a/spec/lib/gitlab/import_export/uploads_manager_spec.rb b/spec/lib/gitlab/import_export/uploads_manager_spec.rb
index 792117e1df1..f13f639d6b7 100644
--- a/spec/lib/gitlab/import_export/uploads_manager_spec.rb
+++ b/spec/lib/gitlab/import_export/uploads_manager_spec.rb
@@ -83,7 +83,7 @@ describe Gitlab::ImportExport::UploadsManager do
it 'restores the file' do
manager.restore
- expect(project.uploads.map { |u| u.build_uploader.filename }).to include('dummy.txt')
+ expect(project.uploads.map { |u| u.retrieve_uploader.filename }).to include('dummy.txt')
end
end
end
diff --git a/spec/lib/gitlab/import_export/uploads_restorer_spec.rb b/spec/lib/gitlab/import_export/uploads_restorer_spec.rb
index 6072f18b8c7..e2e8204b2fa 100644
--- a/spec/lib/gitlab/import_export/uploads_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/uploads_restorer_spec.rb
@@ -27,7 +27,7 @@ describe Gitlab::ImportExport::UploadsRestorer do
it 'copies the uploads to the project path' do
subject.restore
- expect(project.uploads.map { |u| u.build_uploader.filename }).to include('dummy.txt')
+ expect(project.uploads.map { |u| u.retrieve_uploader.filename }).to include('dummy.txt')
end
end
@@ -43,7 +43,7 @@ describe Gitlab::ImportExport::UploadsRestorer do
it 'copies the uploads to the project path' do
subject.restore
- expect(project.uploads.map { |u| u.build_uploader.filename }).to include('dummy.txt')
+ expect(project.uploads.map { |u| u.retrieve_uploader.filename }).to include('dummy.txt')
end
end
end
diff --git a/spec/lib/gitlab/sanitizers/exif_spec.rb b/spec/lib/gitlab/sanitizers/exif_spec.rb
index f882dbbdb5c..11e430e0be4 100644
--- a/spec/lib/gitlab/sanitizers/exif_spec.rb
+++ b/spec/lib/gitlab/sanitizers/exif_spec.rb
@@ -58,7 +58,7 @@ describe Gitlab::Sanitizers::Exif do
end
describe '#clean' do
- let(:uploader) { create(:upload, :with_file, :issuable_upload).build_uploader }
+ let(:uploader) { create(:upload, :with_file, :issuable_upload).retrieve_uploader }
context "no dry run" do
it "removes exif from the image" do
diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb
index ccb5cb3aa43..7e318017a05 100644
--- a/spec/lib/gitlab_spec.rb
+++ b/spec/lib/gitlab_spec.rb
@@ -71,26 +71,30 @@ describe Gitlab do
end
describe '.com?' do
+ before do
+ Thread.current[:is_com] = nil
+ end
+
it 'is true when on GitLab.com' do
- stub_config_setting(url: 'https://gitlab.com')
+ allow(LightSettings).to receive(:host).and_return('gitlab.com')
expect(described_class.com?).to eq true
end
it 'is true when on staging' do
- stub_config_setting(url: 'https://staging.gitlab.com')
+ allow(LightSettings).to receive(:host).and_return('staging.gitlab.com')
expect(described_class.com?).to eq true
end
it 'is true when on other gitlab subdomain' do
- stub_config_setting(url: 'https://example.gitlab.com')
+ allow(LightSettings).to receive(:host).and_return('example.gitlab.com')
expect(described_class.com?).to eq true
end
it 'is false when not on GitLab.com' do
- stub_config_setting(url: 'http://example.com')
+ allow(LightSettings).to receive(:host).and_return('example.com')
expect(described_class.com?).to eq false
end
diff --git a/spec/models/commit_collection_spec.rb b/spec/models/commit_collection_spec.rb
index a8957bbfdd0..d49b71db5f8 100644
--- a/spec/models/commit_collection_spec.rb
+++ b/spec/models/commit_collection_spec.rb
@@ -149,6 +149,17 @@ describe CommitCollection do
collection.enrich!
end
+
+ it 'returns the original commit if the commit could not be lazy loaded' do
+ collection = described_class.new(project, [hash_commit])
+ unexisting_lazy_commit = Commit.lazy(project, Gitlab::Git::BLANK_SHA)
+
+ expect(Commit).to receive(:lazy).with(project, hash_commit.id).and_return(unexisting_lazy_commit)
+
+ collection.enrich!
+
+ expect(collection.commits).to contain_exactly(hash_commit)
+ end
end
end
diff --git a/spec/models/upload_spec.rb b/spec/models/upload_spec.rb
index d97bb8cfb90..03434c95218 100644
--- a/spec/models/upload_spec.rb
+++ b/spec/models/upload_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
describe Upload do
- describe 'assocations' do
+ describe 'associations' do
it { is_expected.to belong_to(:model) }
end
@@ -107,6 +107,52 @@ describe Upload do
end
end
+ describe '#build_uploader' do
+ it 'returns a uploader object with current upload associated with it' do
+ subject = build(:upload)
+ uploader = subject.build_uploader
+
+ expect(uploader.upload).to eq(subject)
+ expect(uploader.mounted_as).to eq(subject.send(:mount_point))
+ expect(uploader.file).to be_nil
+ end
+ end
+
+ describe '#retrieve_uploader' do
+ it 'returns a uploader object with current uploader associated with and cache retrieved' do
+ subject = build(:upload)
+ uploader = subject.retrieve_uploader
+
+ expect(uploader.upload).to eq(subject)
+ expect(uploader.mounted_as).to eq(subject.send(:mount_point))
+ expect(uploader.file).not_to be_nil
+ end
+ end
+
+ describe '#needs_checksum?' do
+ context 'with local storage' do
+ it 'returns true when no checksum exists' do
+ subject = create(:upload, :with_file, checksum: nil)
+
+ expect(subject.needs_checksum?).to be_truthy
+ end
+
+ it 'returns false when checksum is already present' do
+ subject = create(:upload, :with_file, checksum: 'something')
+
+ expect(subject.needs_checksum?).to be_falsey
+ end
+ end
+
+ context 'with remote storage' do
+ subject { build(:upload, :object_storage) }
+
+ it 'returns false' do
+ expect(subject.needs_checksum?).to be_falsey
+ end
+ end
+ end
+
describe '#exist?' do
it 'returns true when the file exists' do
upload = described_class.new(path: __FILE__, store: ObjectStorage::Store::LOCAL)
diff --git a/spec/models/uploads/fog_spec.rb b/spec/models/uploads/fog_spec.rb
index 4a44cf5ab0f..b93d9449da9 100644
--- a/spec/models/uploads/fog_spec.rb
+++ b/spec/models/uploads/fog_spec.rb
@@ -44,7 +44,7 @@ describe Uploads::Fog do
subject { data_store.delete_keys(keys) }
before do
- uploads.each { |upload| upload.build_uploader.migrate!(2) }
+ uploads.each { |upload| upload.retrieve_uploader.migrate!(2) }
end
it 'deletes multiple data' do
diff --git a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
index 4bc22861d58..0b4ab9941fc 100644
--- a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
@@ -104,7 +104,7 @@ shared_examples 'handle uploads' do
context "when neither the uploader nor the model exists" do
before do
- allow_any_instance_of(Upload).to receive(:build_uploader).and_return(nil)
+ allow_any_instance_of(Upload).to receive(:retrieve_uploader).and_return(nil)
allow(controller).to receive(:find_model).and_return(nil)
end
diff --git a/spec/support/shared_examples/models/with_uploads_shared_examples.rb b/spec/support/shared_examples/models/with_uploads_shared_examples.rb
index eb1ade03017..822836c771e 100644
--- a/spec/support/shared_examples/models/with_uploads_shared_examples.rb
+++ b/spec/support/shared_examples/models/with_uploads_shared_examples.rb
@@ -41,7 +41,8 @@ shared_examples_for 'model with uploads' do |supports_fileuploads|
end
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
end
diff --git a/spec/uploaders/file_uploader_spec.rb b/spec/uploaders/file_uploader_spec.rb
index 04206de3dc6..3c14edc7e0e 100644
--- a/spec/uploaders/file_uploader_spec.rb
+++ b/spec/uploaders/file_uploader_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe FileUploader do
let(:group) { create(:group, name: 'awesome') }
let(:project) { create(:project, :legacy_storage, namespace: group, name: 'project') }
- let(:uploader) { described_class.new(project) }
+ let(:uploader) { described_class.new(project, :avatar) }
let(:upload) { double(model: project, path: 'secret/foo.jpg') }
subject { uploader }
@@ -184,6 +184,14 @@ describe FileUploader do
end
end
+ describe '#replace_file_without_saving!' do
+ let(:replacement) { Tempfile.create('replacement.jpg') }
+
+ it 'replaces an existing file without changing its metadata' do
+ expect { subject.replace_file_without_saving! CarrierWave::SanitizedFile.new(replacement) }.not_to change { subject.upload }
+ end
+ end
+
context 'when remote file is used' do
let(:temp_file) { Tempfile.new("test") }
diff --git a/spec/uploaders/gitlab_uploader_spec.rb b/spec/uploaders/gitlab_uploader_spec.rb
index 3bee4875348..4425dd947c0 100644
--- a/spec/uploaders/gitlab_uploader_spec.rb
+++ b/spec/uploaders/gitlab_uploader_spec.rb
@@ -69,6 +69,16 @@ describe GitlabUploader do
end
end
+ describe '#replace_file_without_saving!' do
+ it 'allows file to be replaced without triggering any callbacks' do
+ new_file = CarrierWave::SanitizedFile.new(Tempfile.new)
+
+ expect(subject).not_to receive(:with_callbacks)
+
+ subject.replace_file_without_saving!(new_file)
+ end
+ end
+
describe '#open' do
context 'when trace is stored in File storage' do
context 'when file exists' do
diff --git a/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb b/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
index 6c2544d2efd..97e8a43f7fd 100644
--- a/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
+++ b/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
@@ -42,33 +42,23 @@ describe ObjectStorage::MigrateUploadsWorker, :sidekiq do
end
describe '.sanity_check!' do
- shared_examples 'raises a SanityCheckError' do
+ shared_examples 'raises a SanityCheckError' do |expected_message|
let(:mount_point) { nil }
it do
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
- before do
- stub_const("WrongModel", Class.new)
- end
-
context 'uploader types mismatch' do
let!(:outlier) { create(:upload, uploader: 'GitlabUploader') }
- include_examples 'raises a SanityCheckError'
- end
-
- context 'model types mismatch' do
- let!(:outlier) { create(:upload, model_type: 'WrongModel') }
-
- include_examples 'raises a SanityCheckError'
+ include_examples 'raises a SanityCheckError', /Multiple uploaders found/
end
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 }
end
end