Skip to content
Snippets Groups Projects
Commit 1c8fa70f authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 736d36d8
No related branches found
No related tags found
No related merge requests found
Showing
with 434 additions and 83 deletions
import { mount } from '@vue/test-utils';
import { GlTable, GlPagination, GlLoadingIcon } from '@gitlab/ui';
import { GlTable, GlPagination, GlSkeletonLoader } from '@gitlab/ui';
import Tracking from '~/tracking';
import stubChildren from 'helpers/stub_children';
import component from '~/registry/explorer/pages/details.vue';
Loading
Loading
@@ -14,8 +14,7 @@ describe('Details Page', () => {
 
const findDeleteModal = () => wrapper.find(GlModal);
const findPagination = () => wrapper.find(GlPagination);
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findTagsTable = () => wrapper.find(GlTable);
const findSkeletonLoader = () => wrapper.find(GlSkeletonLoader);
const findMainCheckbox = () => wrapper.find({ ref: 'mainCheckbox' });
const findFirstRowItem = ref => wrapper.find({ ref });
const findBulkDeleteButton = () => wrapper.find({ ref: 'bulkDeleteButton' });
Loading
Loading
@@ -33,7 +32,7 @@ describe('Details Page', () => {
...stubChildren(component),
GlModal,
GlSprintf: false,
GlTable: false,
GlTable,
},
mocks: {
$route: {
Loading
Loading
@@ -53,18 +52,19 @@ describe('Details Page', () => {
});
 
describe('when isLoading is true', () => {
beforeAll(() => store.commit(SET_MAIN_LOADING, true));
beforeEach(() => {
store.dispatch('receiveTagsListSuccess', { ...tagsListResponse, data: [] });
store.commit(SET_MAIN_LOADING, true);
});
 
afterAll(() => store.commit(SET_MAIN_LOADING, false));
 
it('has a loading icon', () => {
expect(findLoadingIcon().exists()).toBe(true);
it('has a skeleton loader', () => {
expect(findSkeletonLoader().exists()).toBe(true);
});
 
it('does not have a main content', () => {
expect(findTagsTable().exists()).toBe(false);
expect(findPagination().exists()).toBe(false);
expect(findDeleteModal().exists()).toBe(false);
it('does not have list items', () => {
expect(findFirstRowItem('rowCheckbox').exists()).toBe(false);
});
});
 
Loading
Loading
import VueRouter from 'vue-router';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlPagination, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { GlPagination, GlSkeletonLoader, GlSprintf } from '@gitlab/ui';
import Tracking from '~/tracking';
import component from '~/registry/explorer/pages/list.vue';
import store from '~/registry/explorer/stores/';
Loading
Loading
@@ -17,7 +17,7 @@ describe('List Page', () => {
 
const findDeleteBtn = () => wrapper.find({ ref: 'deleteImageButton' });
const findDeleteModal = () => wrapper.find(GlModal);
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findSkeletonLoader = () => wrapper.find(GlSkeletonLoader);
const findImagesList = () => wrapper.find({ ref: 'imagesList' });
const findRowItems = () => wrapper.findAll({ ref: 'rowItem' });
const findEmptyState = () => wrapper.find(GlEmptyState);
Loading
Loading
@@ -71,7 +71,7 @@ describe('List Page', () => {
});
 
it('should not show the loading or default state', () => {
expect(findLoadingIcon().exists()).toBe(false);
expect(findSkeletonLoader().exists()).toBe(false);
expect(findImagesList().exists()).toBe(false);
});
});
Loading
Loading
@@ -81,8 +81,8 @@ describe('List Page', () => {
 
afterAll(() => store.commit(SET_MAIN_LOADING, false));
 
it('shows the loading icon', () => {
expect(findLoadingIcon().exists()).toBe(true);
it('shows the skeleton loader', () => {
expect(findSkeletonLoader().exists()).toBe(true);
});
 
it('imagesList is not visible', () => {
Loading
Loading
Loading
Loading
@@ -180,10 +180,7 @@ describe('Actions RegistryExplorer Store', () => {
{
tagsPagination: {},
},
[
{ type: types.SET_MAIN_LOADING, payload: true },
{ type: types.SET_MAIN_LOADING, payload: false },
],
[{ type: types.SET_MAIN_LOADING, payload: true }],
[
{
type: 'requestTagsList',
Loading
Loading
@@ -220,13 +217,11 @@ describe('Actions RegistryExplorer Store', () => {
});
 
describe('request delete multiple tags', () => {
const id = 1;
const params = window.btoa(JSON.stringify({ id }));
const projectPath = 'project-path';
const url = `${projectPath}/registry/repository/${id}/tags/bulk_destroy`;
const url = `project-path/registry/repository/foo/tags`;
const params = window.btoa(JSON.stringify({ tags_path: `${url}?format=json` }));
 
it('successfully performs the delete request', done => {
mock.onDelete(url).replyOnce(200);
mock.onDelete(`${url}/bulk_destroy`).replyOnce(200);
 
testAction(
actions.requestDeleteTags,
Loading
Loading
@@ -235,15 +230,9 @@ describe('Actions RegistryExplorer Store', () => {
params,
},
{
config: {
projectPath,
},
tagsPagination: {},
},
[
{ type: types.SET_MAIN_LOADING, payload: true },
{ type: types.SET_MAIN_LOADING, payload: false },
],
[{ type: types.SET_MAIN_LOADING, payload: true }],
[
{
type: 'requestTagsList',
Loading
Loading
@@ -267,9 +256,6 @@ describe('Actions RegistryExplorer Store', () => {
params,
},
{
config: {
projectPath,
},
tagsPagination: {},
},
[
Loading
Loading
import * as getters from '~/registry/explorer/stores/getters';
describe('Getters RegistryExplorer store', () => {
let state;
const tags = ['foo', 'bar'];
describe('tags', () => {
describe('when isLoading is false', () => {
beforeEach(() => {
state = {
tags,
isLoading: false,
};
});
it('returns tags', () => {
expect(getters.tags(state)).toEqual(state.tags);
});
});
describe('when isLoading is true', () => {
beforeEach(() => {
state = {
tags,
isLoading: true,
};
});
it('returns empty array', () => {
expect(getters.tags(state)).toEqual([]);
});
});
});
});
Loading
Loading
@@ -15,26 +15,10 @@ describe Gitlab::ConfigChecker::PumaRuggedChecker do
end
 
context 'application is puma' do
let(:notice_running_puma) do
{
type: 'info',
message: 'You are running Puma, which is currently experimental. '\
'More information is available in our '\
'<a href="https://docs.gitlab.com/ee/administration/operations/puma.html">documentation</a>.'
}
end
let(:notice_multi_threaded_puma) do
{
type: 'info',
message: 'Puma is running with a thread count above 1. '\
'Information on deprecated GitLab features in this configuration is available in the '\
'<a href="https://docs.gitlab.com/ee/administration/operations/puma.html">documentation</a>.'\
}
end
let(:notice_multi_threaded_puma_with_rugged) do
{
type: 'warning',
message: 'Puma is running with a thread count above 1 and the rugged '\
message: 'Puma is running with a thread count above 1 and the Rugged '\
'service is enabled. This may decrease performance in some environments. '\
'See our <a href="https://docs.gitlab.com/ee/administration/operations/puma.html#performance-caveat-when-using-puma-with-rugged">documentation</a> '\
'for details of this issue.'
Loading
Loading
@@ -51,35 +35,29 @@ describe Gitlab::ConfigChecker::PumaRuggedChecker do
let(:multithreaded_puma) { false }
let(:rugged_enabled) { true }
 
it 'report running puma notice' do
is_expected.to contain_exactly(notice_running_puma)
end
it { is_expected.to be_empty }
end
 
context 'not multithreaded_puma and rugged API is not enabled' do
let(:multithreaded_puma) { false }
let(:rugged_enabled) { false }
 
it 'report running puma notice' do
is_expected.to contain_exactly(notice_running_puma)
end
it { is_expected.to be_empty }
end
 
context 'multithreaded_puma and rugged API is not enabled' do
let(:multithreaded_puma) { true }
let(:rugged_enabled) { false }
 
it 'report running puma notice and multi-thread puma notice' do
is_expected.to contain_exactly(notice_running_puma, notice_multi_threaded_puma)
end
it { is_expected.to be_empty }
end
 
context 'multithreaded_puma and rugged API is enabled' do
let(:multithreaded_puma) { true }
let(:rugged_enabled) { true }
 
it 'report puma/multi_threaded_puma/multi_threaded_puma_with_rugged notices' do
is_expected.to contain_exactly(notice_running_puma, notice_multi_threaded_puma, notice_multi_threaded_puma_with_rugged)
it 'report multi_threaded_puma_with_rugged notices' do
is_expected.to contain_exactly(notice_multi_threaded_puma_with_rugged)
end
end
end
Loading
Loading
Loading
Loading
@@ -3,6 +3,11 @@
require 'spec_helper'
 
describe SnippetRepository do
let_it_be(:user) { create(:user) }
let(:snippet) { create(:personal_snippet, :repository, author: user) }
let(:snippet_repository) { snippet.snippet_repository }
let(:commit_opts) { { branch_name: 'master', message: 'whatever' } }
describe 'associations' do
it { is_expected.to belong_to(:shard) }
it { is_expected.to belong_to(:snippet) }
Loading
Loading
@@ -10,7 +15,7 @@ describe SnippetRepository do
 
describe '.find_snippet' do
it 'finds snippet by disk path' do
snippet = create(:snippet)
snippet = create(:snippet, author: user)
snippet.track_snippet_repository
 
expect(described_class.find_snippet(snippet.disk_path)).to eq(snippet)
Loading
Loading
@@ -20,4 +25,147 @@ describe SnippetRepository do
expect(described_class.find_snippet('@@unexisting/path/to/snippet')).to be_nil
end
end
describe '#multi_files_action' do
let(:new_file) { { file_path: 'new_file_test', content: 'bar' } }
let(:move_file) { { previous_path: 'CHANGELOG', file_path: 'CHANGELOG_new', content: 'bar' } }
let(:update_file) { { previous_path: 'README', file_path: 'README', content: 'bar' } }
let(:data) { [new_file, move_file, update_file] }
it 'returns nil when files argument is empty' do
expect(snippet.repository).not_to receive(:multi_action)
operation = snippet_repository.multi_files_action(user, [], commit_opts)
expect(operation).to be_nil
end
it 'returns nil when files argument is nil' do
expect(snippet.repository).not_to receive(:multi_action)
operation = snippet_repository.multi_files_action(user, nil, commit_opts)
expect(operation).to be_nil
end
it 'performs the operation accordingly to the files data' do
new_file_blob = blob_at(snippet, new_file[:file_path])
move_file_blob = blob_at(snippet, move_file[:previous_path])
update_file_blob = blob_at(snippet, update_file[:previous_path])
aggregate_failures do
expect(new_file_blob).to be_nil
expect(move_file_blob).not_to be_nil
expect(update_file_blob).not_to be_nil
end
expect do
snippet_repository.multi_files_action(user, data, commit_opts)
end.not_to raise_error
aggregate_failures do
data.each do |entry|
blob = blob_at(snippet, entry[:file_path])
expect(blob).not_to be_nil
expect(blob.path).to eq entry[:file_path]
expect(blob.data).to eq entry[:content]
end
end
end
it 'tries to obtain an exclusive lease' do
expect(Gitlab::ExclusiveLease).to receive(:new).with("multi_files_action:#{snippet.id}", anything).and_call_original
snippet_repository.multi_files_action(user, data, commit_opts)
end
it 'cancels the lease when the method has finished' do
expect(Gitlab::ExclusiveLease).to receive(:cancel).with("multi_files_action:#{snippet.id}", anything).and_call_original
snippet_repository.multi_files_action(user, data, commit_opts)
end
it 'raises an error if the lease cannot be obtained' do
allow_next_instance_of(Gitlab::ExclusiveLease) do |instance|
allow(instance).to receive(:try_obtain).and_return false
end
expect do
snippet_repository.multi_files_action(user, data, commit_opts)
end.to raise_error(described_class::CommitError)
end
context 'with commit actions' do
let(:result) do
[{ action: :create }.merge(new_file),
{ action: :move }.merge(move_file),
{ action: :update }.merge(update_file)]
end
let(:repo) { double }
before do
allow(snippet).to receive(:repository).and_return(repo)
allow(repo).to receive(:ls_files).and_return([])
end
it 'infers the commit action based on the parameters if not present' do
expect(repo).to receive(:multi_action).with(user, hash_including(actions: result))
snippet_repository.multi_files_action(user, data, commit_opts)
end
context 'when commit actions are present' do
let(:file_action) { { file_path: 'foo.txt', content: 'foo', action: :foobar } }
let(:data) { [file_action] }
it 'does not change commit action' do
expect(repo).to(
receive(:multi_action).with(
user,
hash_including(actions: array_including(hash_including(action: :foobar)))))
snippet_repository.multi_files_action(user, data, commit_opts)
end
end
end
context 'when files are not named' do
let(:data) do
[
{
file_path: '',
content: 'foo',
action: :create
},
{
file_path: '',
content: 'bar',
action: :create
},
{
file_path: 'foo.txt',
content: 'bar',
action: :create
}
]
end
it 'sets a name for non named files' do
expect do
snippet_repository.multi_files_action(user, data, commit_opts)
end.not_to raise_error
expect(snippet.repository.ls_files(nil)).to include('snippetfile1.txt', 'snippetfile2.txt', 'foo.txt')
end
end
end
def blob_at(snippet, path)
snippet.repository.blob_at('master', path)
end
def first_blob(snippet)
snippet.repository.blob_at('master', snippet.repository.ls_files(nil).first)
end
end
Loading
Loading
@@ -98,6 +98,36 @@ describe API::ProjectSnippets do
}
end
 
shared_examples 'project snippet repository actions' do
let(:snippet) { ProjectSnippet.find(json_response['id']) }
it 'creates repository' do
subject
expect(snippet.repository.exists?).to be_truthy
end
it 'commit the files to the repository' do
subject
blob = snippet.repository.blob_at('master', params[:file_name])
expect(blob.data).to eq params[:code]
end
context 'when feature flag :version_snippets is disabled' do
it 'does not create snippet repository' do
stub_feature_flags(version_snippets: false)
expect do
subject
end.to change { ProjectSnippet.count }.by(1)
expect(snippet.repository_exists?).to be_falsey
end
end
end
context 'with a regular user' do
let(:user) { create(:user) }
 
Loading
Loading
@@ -118,6 +148,10 @@ describe API::ProjectSnippets do
expect(snippet.file_name).to eq(params[:file_name])
expect(snippet.visibility_level).to eq(Snippet::INTERNAL)
end
it_behaves_like 'project snippet repository actions' do
subject { post api("/projects/#{project.id}/snippets/", user), params: params }
end
end
 
it 'creates a new snippet' do
Loading
Loading
@@ -132,6 +166,10 @@ describe API::ProjectSnippets do
expect(snippet.visibility_level).to eq(Snippet::PUBLIC)
end
 
it_behaves_like 'project snippet repository actions' do
subject { post api("/projects/#{project.id}/snippets/", admin), params: params }
end
it 'creates a new snippet with content parameter' do
params[:content] = params.delete(:code)
 
Loading
Loading
Loading
Loading
@@ -199,9 +199,13 @@ describe API::Snippets do
end
 
shared_examples 'snippet creation' do
let(:snippet) { Snippet.find(json_response["id"]) }
subject { post api("/snippets/", user), params: params }
it 'creates a new snippet' do
expect do
post api("/snippets/", user), params: params
subject
end.to change { PersonalSnippet.count }.by(1)
 
expect(response).to have_gitlab_http_status(201)
Loading
Loading
@@ -210,6 +214,32 @@ describe API::Snippets do
expect(json_response['file_name']).to eq(params[:file_name])
expect(json_response['visibility']).to eq(params[:visibility])
end
it 'creates repository' do
subject
expect(snippet.repository.exists?).to be_truthy
end
it 'commit the files to the repository' do
subject
blob = snippet.repository.blob_at('master', params[:file_name])
expect(blob.data).to eq params[:content]
end
context 'when feature flag :version_snippets is disabled' do
it 'does not create snippet repository' do
stub_feature_flags(version_snippets: false)
expect do
subject
end.to change { PersonalSnippet.count }.by(1)
expect(snippet.repository_exists?).to be_falsey
end
end
end
 
context 'with restricted visibility settings' do
Loading
Loading
Loading
Loading
@@ -798,6 +798,11 @@ describe 'project routing' do
end
 
it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/settings/repository", "/gitlab/gitlabhq/-/settings/repository"
# TODO: remove this test as part of https://gitlab.com/gitlab-org/gitlab/issues/207079 (12.9)
it 'to ci_cd#create_deploy_token' do
expect(post('gitlab/gitlabhq/-/settings/repository/deploy_token/create')).to route_to('projects/settings/ci_cd#create_deploy_token', namespace_id: 'gitlab', project_id: 'gitlabhq')
end
end
 
describe Projects::TemplatesController, 'routing' do
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe Groups::DeployTokens::CreateService do
it_behaves_like 'a deploy token creation service' do
let(:entity) { create(:group) }
let(:deploy_token_class) { GroupDeployToken }
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Projects::DeployTokens::CreateService do
it_behaves_like 'a deploy token creation service' do
let(:entity) { create(:project) }
let(:deploy_token_class) { ProjectDeployToken }
end
end
Loading
Loading
@@ -143,37 +143,102 @@ describe Snippets::CreateService do
end
end
 
shared_examples 'creates repository' do
it do
shared_examples 'creates repository and files' do
it 'creates repository' do
subject
 
expect(snippet.repository_exists?).to be_truthy
expect(snippet.repository.exists?).to be_truthy
end
it 'commit the files to the repository' do
subject
blob = snippet.repository.blob_at('master', base_opts[:file_name])
expect(blob.data).to eq base_opts[:content]
end
context 'when repository creation action fails' do
before do
allow_next_instance_of(Snippet) do |instance|
allow(instance).to receive(:create_repository).and_return(nil)
end
end
it 'does not create the snippet' do
expect { subject }.not_to change { Snippet.count }
end
it 'returns the error' do
expect(snippet.errors.full_messages).to include('Repository could not be created')
end
end
context 'when the commit action fails' do
before do
allow_next_instance_of(SnippetRepository) do |instance|
allow(instance).to receive(:multi_files_action).and_raise(SnippetRepository::CommitError.new('foobar'))
end
end
it 'does not create the snippet' do
expect { subject }.not_to change { Snippet.count }
end
it 'does not create the repository' do
expect(snippet.repository_exists?).to be_falsey
end
it 'destroys the existing repository' do
expect(Repositories::DestroyService).to receive(:new).and_call_original
subject
end
it 'returns the error' do
response = subject
expect(response).to be_error
expect(response.payload[:snippet].errors.full_messages).to eq ['foobar']
end
end
 
context 'when snippet creation fails' do
let(:extra_opts) { { content: nil } }
 
it 'does not create repository' do
subject
expect do
subject
end.not_to change(Snippet, :count)
 
expect(snippet.repository_exists?).to be_falsey
end
end
 
context 'when feature flag :version_snippets is disabled' do
it 'does not create snippet repository' do
before do
stub_feature_flags(version_snippets: false)
end
 
it 'does not create snippet repository' do
expect do
subject
end.to change(Snippet, :count).by(1)
 
expect(snippet.repository_exists?).to be_falsey
end
it 'does not try to commit files' do
expect_next_instance_of(described_class) do |instance|
expect(instance).not_to receive(:create_commit)
end
subject
end
end
end
 
context 'when Project Snippet' do
context 'when ProjectSnippet' do
let_it_be(:project) { create(:project) }
 
before do
Loading
Loading
@@ -185,7 +250,7 @@ describe Snippets::CreateService do
it_behaves_like 'spam check is performed'
it_behaves_like 'snippet create data is tracked'
it_behaves_like 'an error service response when save fails'
it_behaves_like 'creates repository'
it_behaves_like 'creates repository and files'
end
 
context 'when PersonalSnippet' do
Loading
Loading
@@ -196,7 +261,7 @@ describe Snippets::CreateService do
it_behaves_like 'spam check is performed'
it_behaves_like 'snippet create data is tracked'
it_behaves_like 'an error service response when save fails'
it_behaves_like 'creates repository'
it_behaves_like 'creates repository and files'
end
end
end
# frozen_string_literal: true
 
require 'spec_helper'
describe DeployTokens::CreateService do
let(:project) { create(:project) }
RSpec.shared_examples 'a deploy token creation service' do
let(:user) { create(:user) }
let(:deploy_token_params) { attributes_for(:deploy_token) }
 
describe '#execute' do
subject { described_class.new(project, user, deploy_token_params).execute }
subject { described_class.new(entity, user, deploy_token_params).execute }
 
context 'when the deploy token is valid' do
it 'creates a new DeployToken' do
Loading
Loading
@@ -16,7 +13,7 @@ describe DeployTokens::CreateService do
end
 
it 'creates a new ProjectDeployToken' do
expect { subject }.to change { ProjectDeployToken.count }.by(1)
expect { subject }.to change { deploy_token_class.count }.by(1)
end
 
it 'returns a DeployToken' do
Loading
Loading
@@ -56,7 +53,7 @@ describe DeployTokens::CreateService do
end
 
it 'does not create a new ProjectDeployToken' do
expect { subject }.not_to change { ProjectDeployToken.count }
expect { subject }.not_to change { deploy_token_class.count }
end
end
end
Loading
Loading
# frozen_string_literal: true
RSpec.shared_examples 'a created deploy token' do
let(:deploy_token_params) do
{
name: 'deployer_token',
expires_at: 1.month.from_now.to_date.to_s,
username: 'deployer',
read_repository: '1',
deploy_token_type: deploy_token_type
}
end
subject(:create_deploy_token) { post :create_deploy_token, params: create_entity_params.merge({ deploy_token: deploy_token_params }) }
it 'creates deploy token' do
expect { create_deploy_token }.to change { DeployToken.active.count }.by(1)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:show)
end
end
# frozen_string_literal: true
RSpec.shared_examples 'a deploy token in ci/cd settings' do
it 'view deploy tokens' do
within('.deploy-tokens') do
expect(page).to have_content(deploy_token.name)
expect(page).to have_content('read_repository')
expect(page).to have_content('read_registry')
end
end
it 'add a new deploy token' do
fill_in 'deploy_token_name', with: 'new_deploy_key'
fill_in 'deploy_token_expires_at', with: (Date.today + 1.month).to_s
fill_in 'deploy_token_username', with: 'deployer'
check 'deploy_token_read_repository'
check 'deploy_token_read_registry'
click_button 'Create deploy token'
expect(page).to have_content("Your new #{entity_type} deploy token has been created")
within('.created-deploy-token-container') do
expect(page).to have_selector("input[name='deploy-token-user'][value='deployer']")
expect(page).to have_selector("input[name='deploy-token'][readonly='readonly']")
end
end
end
Loading
Loading
@@ -5,17 +5,18 @@ require 'spec_helper'
describe 'import/gitlab_projects/new.html.haml' do
include Devise::Test::ControllerHelpers
 
let(:user) { build_stubbed(:user, namespace: build_stubbed(:namespace)) }
let(:namespace) { build_stubbed(:namespace) }
let(:user) { build_stubbed(:user, namespace: namespace) }
 
before do
allow(view).to receive(:current_user).and_return(user)
end
 
context 'when the user has no other namespaces' do
it 'shows a namespace_id hidden field tag' do
it 'adds a namespace_id hidden field tag with the namespace id as value' do
render
 
expect(rendered).to have_css('input[name="namespace_id"]', count: 1, visible: false)
expect(rendered).to have_css("input[name='namespace_id'][value='#{namespace.id}']", count: 1, visible: false)
end
end
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment