Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-10-16 00:09:12 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-10-16 00:09:12 +0300
commitc083f926c5714ee4dcbb3ae497b14d4cb31aa794 (patch)
tree2bc13107c4396e3263afe3c13b7e9e32f06a843b /spec
parent316fbf9f95dcdd16775f0339415572c3195eea92 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/file_uploads/maven_package_spec.rb26
-rw-r--r--spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/members/table/role_dropdown_spec.js69
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb32
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb34
-rw-r--r--spec/models/group_spec.rb20
-rw-r--r--spec/requests/api/maven_packages_spec.rb56
-rw-r--r--spec/requests/api/members_spec.rb1
-rw-r--r--spec/services/groups/create_service_spec.rb9
-rw-r--r--spec/services/repository_archive_clean_up_service_spec.rb22
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb2
11 files changed, 244 insertions, 33 deletions
diff --git a/spec/features/file_uploads/maven_package_spec.rb b/spec/features/file_uploads/maven_package_spec.rb
index c873a0e9a36..e87eec58618 100644
--- a/spec/features/file_uploads/maven_package_spec.rb
+++ b/spec/features/file_uploads/maven_package_spec.rb
@@ -25,5 +25,31 @@ RSpec.describe 'Upload a maven package', :api, :js do
it { expect(subject.code).to eq(200) }
end
+ RSpec.shared_examples 'for a maven sha1' do
+ let(:dummy_package) { double(Packages::Package) }
+ let(:api_path) { "/projects/#{project.id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar.sha1" }
+
+ before do
+ # The sha verification done by the maven api is between:
+ # - the sha256 set by workhorse
+ # - the sha256 of the sha1 of the uploaded package file
+ # We're going to send `file` for the sha1 and stub the sha1 of the package file so that
+ # both sha256 being the same
+ expect(::Packages::PackageFileFinder).to receive(:new).and_return(double(execute!: dummy_package))
+ expect(dummy_package).to receive(:file_sha1).and_return(File.read(file.path))
+ end
+
+ it { expect(subject.code).to eq(204) }
+ end
+
+ RSpec.shared_examples 'for a maven md5' do
+ let(:api_path) { "/projects/#{project.id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar.md5" }
+ let(:file) { StringIO.new('dummy_package') }
+
+ it { expect(subject.code).to eq(200) }
+ end
+
it_behaves_like 'handling file uploads', 'for a maven package'
+ it_behaves_like 'handling file uploads', 'for a maven sha1'
+ it_behaves_like 'handling file uploads', 'for a maven md5'
end
diff --git a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
index 99cb864ce34..7c1a4ff1085 100644
--- a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
+++ b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
@@ -1,6 +1,6 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlDeprecatedDropdownItem, GlDropdown } from '@gitlab/ui';
+import { GlDropdownItem, GlDropdown } from '@gitlab/ui';
import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
import createStore from '~/deploy_freeze/store';
@@ -29,8 +29,8 @@ describe('Deploy freeze timezone dropdown', () => {
wrapper.setData({ searchTerm });
};
- const findAllDropdownItems = () => wrapper.findAll(GlDeprecatedDropdownItem);
- const findDropdownItemByIndex = index => wrapper.findAll(GlDeprecatedDropdownItem).at(index);
+ const findAllDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findDropdownItemByIndex = index => wrapper.findAll(GlDropdownItem).at(index);
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/vue_shared/components/members/table/role_dropdown_spec.js b/spec/frontend/vue_shared/components/members/table/role_dropdown_spec.js
index 5e5a013018b..1e47953a510 100644
--- a/spec/frontend/vue_shared/components/members/table/role_dropdown_spec.js
+++ b/spec/frontend/vue_shared/components/members/table/role_dropdown_spec.js
@@ -1,13 +1,30 @@
-import { mount, createWrapper } from '@vue/test-utils';
+import { mount, createWrapper, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { nextTick } from 'vue';
import { within } from '@testing-library/dom';
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
+import waitForPromises from 'helpers/wait_for_promises';
import RoleDropdown from '~/vue_shared/components/members/table/role_dropdown.vue';
import { member } from '../mock_data';
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
describe('RoleDropdown', () => {
let wrapper;
+ let actions;
+ const $toast = {
+ show: jest.fn(),
+ };
+
+ const createStore = () => {
+ actions = {
+ updateMemberRole: jest.fn(() => Promise.resolve()),
+ };
+
+ return new Vuex.Store({ actions });
+ };
const createComponent = (propsData = {}) => {
wrapper = mount(RoleDropdown, {
@@ -15,6 +32,11 @@ describe('RoleDropdown', () => {
member,
...propsData,
},
+ localVue,
+ store: createStore(),
+ mocks: {
+ $toast,
+ },
});
};
@@ -22,7 +44,11 @@ describe('RoleDropdown', () => {
const getByTextInDropdownMenu = (text, options = {}) =>
createWrapper(within(getDropdownMenu()).getByText(text, options));
const getDropdownItemByText = text =>
- getByTextInDropdownMenu(text, { selector: '[role="menuitem"] p' });
+ createWrapper(
+ within(getDropdownMenu())
+ .getByText(text, { selector: '[role="menuitem"] p' })
+ .closest('[role="menuitem"]'),
+ );
const getCheckedDropdownItem = () =>
wrapper
.findAll(GlDropdownItem)
@@ -55,10 +81,47 @@ describe('RoleDropdown', () => {
expect(getByTextInDropdownMenu('Change permissions').exists()).toBe(true);
});
- it('sets dropdown toggle and checks selected role', async () => {
+ it('sets dropdown toggle and checks selected role', () => {
expect(findDropdownToggle().text()).toBe('Owner');
expect(getCheckedDropdownItem().text()).toBe('Owner');
});
+
+ describe('when dropdown item is selected', () => {
+ it('does nothing if the item selected was already selected', () => {
+ getDropdownItemByText('Owner').trigger('click');
+
+ expect(actions.updateMemberRole).not.toHaveBeenCalled();
+ });
+
+ it('calls `updateMemberRole` Vuex action', () => {
+ getDropdownItemByText('Developer').trigger('click');
+
+ expect(actions.updateMemberRole).toHaveBeenCalledWith(expect.any(Object), {
+ memberId: member.id,
+ accessLevel: { integerValue: 30, stringValue: 'Developer' },
+ });
+ });
+
+ it('displays toast when successful', async () => {
+ getDropdownItemByText('Developer').trigger('click');
+
+ await waitForPromises();
+
+ expect($toast.show).toHaveBeenCalledWith('Role updated successfully.');
+ });
+
+ it('disables dropdown while waiting for `updateMemberRole` to resolve', async () => {
+ getDropdownItemByText('Developer').trigger('click');
+
+ await nextTick();
+
+ expect(findDropdown().attributes('disabled')).toBe('disabled');
+
+ await waitForPromises();
+
+ expect(findDropdown().attributes('disabled')).toBeUndefined();
+ });
+ });
});
it("sets initial dropdown toggle value to member's role", () => {
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 3dc0db1bc3c..1c818bd4a88 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -120,7 +120,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
let(:expected_extension) { 'tar.gz' }
let(:expected_filename) { "#{expected_prefix}.#{expected_extension}" }
- let(:expected_path) { File.join(storage_path, cache_key, expected_filename) }
+ let(:expected_path) { File.join(storage_path, cache_key, "@v2", expected_filename) }
let(:expected_prefix) { "gitlab-git-test-#{ref}-#{SeedRepo::LastCommit::ID}" }
subject(:metadata) { repository.archive_metadata(ref, storage_path, 'gitlab-git-test', format, append_sha: append_sha, path: path) }
@@ -133,12 +133,32 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
expect(metadata['ArchivePrefix']).to eq(expected_prefix)
end
- it 'sets ArchivePath to the expected globally-unique path' do
- # This is really important from a security perspective. Think carefully
- # before changing it: https://gitlab.com/gitlab-org/gitlab-foss/issues/45689
- expect(expected_path).to include(File.join(repository.gl_repository, SeedRepo::LastCommit::ID))
+ context 'when :include_lfs_blobs_in_archive feature flag is disabled' do
+ let(:expected_path) { File.join(storage_path, cache_key, expected_filename) }
- expect(metadata['ArchivePath']).to eq(expected_path)
+ before do
+ stub_feature_flags(include_lfs_blobs_in_archive: false)
+ end
+
+ it 'sets ArchivePath to the expected globally-unique path' do
+ # This is really important from a security perspective. Think carefully
+ # before changing it: https://gitlab.com/gitlab-org/gitlab-foss/issues/45689
+ expect(expected_path).to include(File.join(repository.gl_repository, SeedRepo::LastCommit::ID))
+
+ expect(metadata['ArchivePath']).to eq(expected_path)
+ end
+ end
+
+ context 'when :include_lfs_blobs_in_archive feature flag is enabled' do
+ before do
+ stub_feature_flags(include_lfs_blobs_in_archive: true)
+ end
+
+ it 'sets ArchivePath to the expected globally-unique path' do
+ expect(expected_path).to include(File.join(repository.gl_repository, SeedRepo::LastCommit::ID))
+
+ expect(metadata['ArchivePath']).to eq(expected_path)
+ end
end
context 'path is set' do
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index e9733851590..9662ad13631 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -54,12 +54,44 @@ RSpec.describe Gitlab::Workhorse do
commit_id: metadata['CommitId'],
prefix: metadata['ArchivePrefix'],
format: Gitaly::GetArchiveRequest::Format::ZIP,
- path: path
+ path: path,
+ include_lfs_blobs: true
).to_proto
)
}.deep_stringify_keys)
end
+ context 'when include_lfs_blobs_in_archive is disabled' do
+ before do
+ stub_feature_flags(include_lfs_blobs_in_archive: false)
+ end
+
+ it 'sets include_lfs_blobs to false' do
+ key, command, params = decode_workhorse_header(subject)
+
+ expect(key).to eq('Gitlab-Workhorse-Send-Data')
+ expect(command).to eq('git-archive')
+ expect(params).to eq({
+ 'GitalyServer' => {
+ features: { 'gitaly-feature-foobar' => 'true' },
+ address: Gitlab::GitalyClient.address(project.repository_storage),
+ token: Gitlab::GitalyClient.token(project.repository_storage)
+ },
+ 'ArchivePath' => metadata['ArchivePath'],
+ 'GetArchiveRequest' => Base64.encode64(
+ Gitaly::GetArchiveRequest.new(
+ repository: repository.gitaly_repository,
+ commit_id: metadata['CommitId'],
+ prefix: metadata['ArchivePrefix'],
+ format: Gitaly::GetArchiveRequest::Format::ZIP,
+ path: path,
+ include_lfs_blobs: false
+ ).to_proto
+ )
+ }.deep_stringify_keys)
+ end
+ end
+
context 'when archive caching is disabled' do
let(:cache_disabled) { true }
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index a5262fabb08..cc29e20710a 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -1571,4 +1571,24 @@ RSpec.describe Group do
end
end
end
+
+ describe '#parent_allows_two_factor_authentication?' do
+ it 'returns true for top-level group' do
+ expect(group.parent_allows_two_factor_authentication?).to eq(true)
+ end
+
+ context 'for subgroup' do
+ let(:subgroup) { create(:group, parent: group) }
+
+ it 'returns true if parent group allows two factor authentication for its descendants' do
+ expect(subgroup.parent_allows_two_factor_authentication?).to eq(true)
+ end
+
+ it 'returns true if parent group allows two factor authentication for its descendants' do
+ group.namespace_settings.update!(allow_mfa_for_subgroups: false)
+
+ expect(subgroup.parent_allows_two_factor_authentication?).to eq(false)
+ end
+ end
+ end
end
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index 8580c0ab4d4..37748fe5ea7 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -562,7 +562,7 @@ RSpec.describe API::MavenPackages do
allow(uploaded_file).to receive(:size).and_return(project.actual_limits.maven_max_file_size + 1)
end
- upload_file_with_token(params)
+ upload_file_with_token(params: params)
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -577,19 +577,19 @@ RSpec.describe API::MavenPackages do
context 'without workhorse header' do
let(:workhorse_header) { {} }
- subject { upload_file_with_token(params) }
+ subject { upload_file_with_token(params: params) }
it_behaves_like 'package workhorse uploads'
end
context 'event tracking' do
- subject { upload_file_with_token(params) }
+ subject { upload_file_with_token(params: params) }
it_behaves_like 'a package tracking event', described_class.name, 'push_package'
end
it 'creates package and stores package file' do
- expect { upload_file_with_token(params) }.to change { project.packages.count }.by(1)
+ expect { upload_file_with_token(params: params) }.to change { project.packages.count }.by(1)
.and change { Packages::Maven::Metadatum.count }.by(1)
.and change { Packages::PackageFile.count }.by(1)
@@ -598,7 +598,7 @@ RSpec.describe API::MavenPackages do
end
it 'allows upload with running job token' do
- upload_file(params.merge(job_token: job.token))
+ upload_file(params: params.merge(job_token: job.token))
expect(response).to have_gitlab_http_status(:ok)
expect(project.reload.packages.last.build_info.pipeline).to eq job.pipeline
@@ -606,13 +606,13 @@ RSpec.describe API::MavenPackages do
it 'rejects upload without running job token' do
job.update!(status: :failed)
- upload_file(params.merge(job_token: job.token))
+ upload_file(params: params.merge(job_token: job.token))
expect(response).to have_gitlab_http_status(:unauthorized)
end
it 'allows upload with deploy token' do
- upload_file(params, headers_with_deploy_token)
+ upload_file(params: params, request_headers: headers_with_deploy_token)
expect(response).to have_gitlab_http_status(:ok)
end
@@ -626,7 +626,10 @@ RSpec.describe API::MavenPackages do
# We force the id of the deploy token and the user to be the same
unauthorized_deploy_token.update!(id: another_user.id)
- upload_file(params, headers.merge(Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => unauthorized_deploy_token.token))
+ upload_file(
+ params: params,
+ request_headers: headers.merge(Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => unauthorized_deploy_token.token)
+ )
expect(response).to have_gitlab_http_status(:forbidden)
end
@@ -635,16 +638,43 @@ RSpec.describe API::MavenPackages do
let(:version) { '$%123' }
it 'rejects request' do
- expect { upload_file_with_token(params) }.not_to change { project.packages.count }
+ expect { upload_file_with_token(params: params) }.not_to change { project.packages.count }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']).to include('Validation failed')
end
end
+
+ context 'for sha1 file' do
+ let(:dummy_package) { double(Packages::Package) }
+
+ it 'checks the sha1' do
+ # The sha verification done by the maven api is between:
+ # - the sha256 set by workhorse helpers
+ # - the sha256 of the sha1 of the uploaded package file
+ # We're going to send `file_upload` for the sha1 and stub the sha1 of the package file so that
+ # both sha256 being the same
+ expect(::Packages::PackageFileFinder).to receive(:new).and_return(double(execute!: dummy_package))
+ expect(dummy_package).to receive(:file_sha1).and_return(File.read(file_upload.path))
+
+ upload_file_with_token(params: params, file_extension: 'jar.sha1')
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
+
+ context 'for md5 file' do
+ it 'returns an empty body' do
+ upload_file_with_token(params: params, file_extension: 'jar.md5')
+
+ expect(response.body).to eq('')
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
end
- def upload_file(params = {}, request_headers = headers)
- url = "/projects/#{project.id}/packages/maven/com/example/my-app/#{version}/my-app-1.0-20180724.124855-1.jar"
+ def upload_file(params: {}, request_headers: headers, file_extension: 'jar')
+ url = "/projects/#{project.id}/packages/maven/com/example/my-app/#{version}/my-app-1.0-20180724.124855-1.#{file_extension}"
workhorse_finalize(
api(url),
method: :put,
@@ -655,8 +685,8 @@ RSpec.describe API::MavenPackages do
)
end
- def upload_file_with_token(params = {}, request_headers = headers_with_token)
- upload_file(params, request_headers)
+ def upload_file_with_token(params: {}, request_headers: headers_with_token, file_extension: 'jar')
+ upload_file(params: params, request_headers: request_headers, file_extension: file_extension)
end
end
end
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index 6a2419fbbf3..047b9423906 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -196,6 +196,7 @@ RSpec.describe API::Members do
# Member attributes
expect(json_response['access_level']).to eq(Member::DEVELOPER)
+ expect(json_response['created_at'].to_time).to be_like_time(developer.created_at)
end
end
end
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
index d5479fa2a06..4f5bc3a3d5a 100644
--- a/spec/services/groups/create_service_spec.rb
+++ b/spec/services/groups/create_service_spec.rb
@@ -45,6 +45,15 @@ RSpec.describe Groups::CreateService, '#execute' do
end
end
+ context 'creating a group with `allow_mfa_for_subgroups` attribute' do
+ let(:params) { group_params.merge(allow_mfa_for_subgroups: false) }
+ let(:service) { described_class.new(user, params) }
+
+ it 'creates group without error' do
+ expect(service.execute).to be_persisted
+ end
+ end
+
describe 'creating a top level group' do
let(:service) { described_class.new(user, group_params) }
diff --git a/spec/services/repository_archive_clean_up_service_spec.rb b/spec/services/repository_archive_clean_up_service_spec.rb
index c6d673fb1b5..8db1a6858fa 100644
--- a/spec/services/repository_archive_clean_up_service_spec.rb
+++ b/spec/services/repository_archive_clean_up_service_spec.rb
@@ -18,6 +18,16 @@ RSpec.describe RepositoryArchiveCleanUpService do
end
end
+ it 'removes outdated archives and directories in a versioned path' do
+ in_directory_with_files("project-#{non_existing_record_id}/#{sha}/@v2", %w[tar tar.bz2 tar.gz zip], 3.hours) do |dirname, files|
+ service.execute
+
+ files.each { |filename| expect(File.exist?(filename)).to be_falsy }
+ expect(File.directory?(dirname)).to be_falsy
+ expect(File.directory?(File.dirname(dirname))).to be_falsy
+ end
+ end
+
it 'does not remove directories when they contain outdated non-archives' do
in_directory_with_files("project-#{non_existing_record_id}/#{sha}", %w[tar conf rb], 2.hours) do |dirname, files|
service.execute
@@ -64,7 +74,9 @@ RSpec.describe RepositoryArchiveCleanUpService do
end
it 'removes files older than 2 hours that matches valid archive extensions' do
- in_directory_with_files('sample.git', %w[tar tar.bz2 tar.gz zip], 2.hours) do |dir, files|
+ # In macOS, the the `mmin` parameter for `find` rounds up, so add a full
+ # minute to ensure these files are deemed old.
+ in_directory_with_files('sample.git', %w[tar tar.bz2 tar.gz zip], 121.minutes) do |dir, files|
service.execute
files.each { |file| expect(File.exist?(file)).to eq false }
@@ -73,11 +85,11 @@ RSpec.describe RepositoryArchiveCleanUpService do
end
context 'with files older than 2 hours that does not matches valid archive extensions' do
- it_behaves_like 'invalid archive files', 'sample.git', %w[conf rb], 2.hours
+ it_behaves_like 'invalid archive files', 'sample.git', %w[conf rb], 121.minutes
end
context 'with files older than 2 hours inside invalid directories' do
- it_behaves_like 'invalid archive files', 'john/doe/sample.git', %w[conf rb tar tar.gz], 2.hours
+ it_behaves_like 'invalid archive files', 'john/t/doe/sample.git', %w[conf rb tar tar.gz], 121.minutes
end
context 'with files newer than 2 hours that matches valid archive extensions' do
@@ -110,8 +122,6 @@ RSpec.describe RepositoryArchiveCleanUpService do
def create_temporary_files(dir, extensions, mtime)
FileUtils.mkdir_p(dir)
- # rubocop: disable Rails/TimeZone
- FileUtils.touch(extensions.map { |ext| File.join(dir, "sample.#{ext}") }, mtime: Time.now - mtime)
- # rubocop: enable Rails/TimeZone
+ FileUtils.touch(extensions.map { |ext| File.join(dir, "sample.#{ext}") }, mtime: Time.now.utc - mtime)
end
end
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index 55bf981e0fb..9ebfdcb9522 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -45,7 +45,7 @@ RSpec.shared_context 'project navbar structure' do
_('Labels'),
_('Service Desk'),
_('Milestones'),
- _('Iterations')
+ (_('Iterations') if Gitlab.ee?)
]
},
{