summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-28 18:09:07 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-28 18:09:07 +0000
commit1c8fa70f9d0818e2a82089c8643a6e455bca47fd (patch)
treef339f97de0425270bdd909e2f4d378927b6e0a18 /spec
parent736d36d8597d0d1ec1b47644e6d091c3f4a78f45 (diff)
downloadgitlab-ce-1c8fa70f9d0818e2a82089c8643a6e455bca47fd.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/groups/settings/ci_cd_controller_spec.rb12
-rw-r--r--spec/controllers/projects/settings/ci_cd_controller_spec.rb8
-rw-r--r--spec/controllers/projects/settings/repository_controller_spec.rb20
-rw-r--r--spec/features/groups/settings/ci_cd_spec.rb13
-rw-r--r--spec/features/projects/settings/ci_cd_settings_spec.rb24
-rw-r--r--spec/features/projects/settings/repository_settings_spec.rb33
-rw-r--r--spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb2
-rw-r--r--spec/frontend/behaviors/quick_submit_spec.js (renamed from spec/javascripts/behaviors/quick_submit_spec.js)84
-rw-r--r--spec/frontend/registry/explorer/pages/details_spec.js22
-rw-r--r--spec/frontend/registry/explorer/pages/list_spec.js10
-rw-r--r--spec/frontend/registry/explorer/stores/actions_spec.js24
-rw-r--r--spec/frontend/registry/explorer/stores/getters_spec.js34
-rw-r--r--spec/lib/gitlab/config_checker/puma_rugged_checker_spec.rb34
-rw-r--r--spec/models/snippet_repository_spec.rb150
-rw-r--r--spec/requests/api/project_snippets_spec.rb38
-rw-r--r--spec/requests/api/snippets_spec.rb32
-rw-r--r--spec/routing/project_routing_spec.rb5
-rw-r--r--spec/services/groups/deploy_tokens/create_service_spec.rb10
-rw-r--r--spec/services/projects/deploy_tokens/create_service_spec.rb10
-rw-r--r--spec/services/snippets/create_service_spec.rb81
-rw-r--r--spec/support/services/deploy_token_shared_examples.rb (renamed from spec/services/deploy_tokens/create_service_spec.rb)11
-rw-r--r--spec/support/shared_examples/controllers/deploy_token_shared_examples.rb22
-rw-r--r--spec/support/shared_examples/features/deploy_token_shared_examples.rb27
-rw-r--r--spec/views/import/gitlab_projects/new.html.haml_spec.rb7
24 files changed, 539 insertions, 174 deletions
diff --git a/spec/controllers/groups/settings/ci_cd_controller_spec.rb b/spec/controllers/groups/settings/ci_cd_controller_spec.rb
index 4e8cb3f94fb..fbf88a01eb3 100644
--- a/spec/controllers/groups/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/groups/settings/ci_cd_controller_spec.rb
@@ -210,4 +210,16 @@ describe Groups::Settings::CiCdController do
end
end
end
+
+ describe 'POST create_deploy_token' do
+ it_behaves_like 'a created deploy token' do
+ let(:entity) { group }
+ let(:create_entity_params) { { group_id: group } }
+ let(:deploy_token_type) { DeployToken.deploy_token_types[:group_type] }
+
+ before do
+ entity.add_owner(user)
+ end
+ end
+ end
end
diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
index 68260e4e101..a8631389e17 100644
--- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
@@ -247,4 +247,12 @@ describe Projects::Settings::CiCdController do
end
end
end
+
+ describe 'POST create_deploy_token' do
+ it_behaves_like 'a created deploy token' do
+ let(:entity) { project }
+ let(:create_entity_params) { { namespace_id: project.namespace, project_id: project } }
+ let(:deploy_token_type) { DeployToken.deploy_token_types[:project_type] }
+ end
+ end
end
diff --git a/spec/controllers/projects/settings/repository_controller_spec.rb b/spec/controllers/projects/settings/repository_controller_spec.rb
index 64f5b8e34ae..67ae9ebda38 100644
--- a/spec/controllers/projects/settings/repository_controller_spec.rb
+++ b/spec/controllers/projects/settings/repository_controller_spec.rb
@@ -32,24 +32,4 @@ describe Projects::Settings::RepositoryController do
expect(RepositoryCleanupWorker).to have_received(:perform_async).once
end
end
-
- describe 'POST create_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'
- }
- end
-
- subject(:create_deploy_token) { post :create_deploy_token, params: { namespace_id: project.namespace, project_id: project, 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
end
diff --git a/spec/features/groups/settings/ci_cd_spec.rb b/spec/features/groups/settings/ci_cd_spec.rb
index 5b1a9512c55..3fbc7c7a695 100644
--- a/spec/features/groups/settings/ci_cd_spec.rb
+++ b/spec/features/groups/settings/ci_cd_spec.rb
@@ -37,6 +37,19 @@ describe 'Group CI/CD settings' do
end
end
+ context 'Deploy tokens' do
+ let!(:deploy_token) { create(:deploy_token, :group, groups: [group]) }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ visit group_settings_ci_cd_path(group)
+ end
+
+ it_behaves_like 'a deploy token in ci/cd settings' do
+ let(:entity_type) { 'group' }
+ end
+ end
+
describe 'Auto DevOps form' do
before do
stub_application_setting(auto_devops_enabled: true)
diff --git a/spec/features/projects/settings/ci_cd_settings_spec.rb b/spec/features/projects/settings/ci_cd_settings_spec.rb
new file mode 100644
index 00000000000..e69ee31e582
--- /dev/null
+++ b/spec/features/projects/settings/ci_cd_settings_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Projects > Settings > CI/CD settings' do
+ let(:project) { create(:project_empty_repo) }
+ let(:user) { create(:user) }
+ let(:role) { :maintainer }
+
+ context 'Deploy tokens' do
+ let!(:deploy_token) { create(:deploy_token, projects: [project]) }
+
+ before do
+ project.add_role(user, role)
+ sign_in(user)
+ stub_container_registry_config(enabled: true)
+ visit project_settings_ci_cd_path(project)
+ end
+
+ it_behaves_like 'a deploy token in ci/cd settings' do
+ let(:entity_type) { 'project' }
+ end
+ end
+end
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 18031a40f15..d750234d9ad 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -108,39 +108,6 @@ describe 'Projects > Settings > Repository settings' do
end
end
- context 'Deploy tokens' do
- let!(:deploy_token) { create(:deploy_token, projects: [project]) }
-
- before do
- stub_container_registry_config(enabled: true)
- visit project_settings_repository_path(project)
- end
-
- 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 project 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
-
context 'remote mirror settings' do
let(:user2) { create(:user) }
diff --git a/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb b/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb
index 3e9bfed1e47..a9253c20896 100644
--- a/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb
+++ b/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb
@@ -11,7 +11,7 @@ describe 'Repository Settings > User sees revoke deploy token modal', :js do
before do
project.add_role(user, role)
sign_in(user)
- visit(project_settings_repository_path(project))
+ visit(project_settings_ci_cd_path(project))
click_link('Revoke')
end
diff --git a/spec/javascripts/behaviors/quick_submit_spec.js b/spec/frontend/behaviors/quick_submit_spec.js
index 7af8c984841..2dc2bb198e8 100644
--- a/spec/javascripts/behaviors/quick_submit_spec.js
+++ b/spec/frontend/behaviors/quick_submit_spec.js
@@ -1,70 +1,72 @@
import $ from 'jquery';
import '~/behaviors/quick_submit';
-describe('Quick Submit behavior', function() {
+describe('Quick Submit behavior', () => {
+ let testContext;
+
const keydownEvent = (options = { keyCode: 13, metaKey: true }) => $.Event('keydown', options);
preloadFixtures('snippets/show.html');
beforeEach(() => {
loadFixtures('snippets/show.html');
+
+ testContext = {};
+
+ testContext.spies = {
+ submit: jest.fn(),
+ };
+
$('form').submit(e => {
// Prevent a form submit from moving us off the testing page
e.preventDefault();
+ // Explicitly call the spie to know this function get's not called
+ testContext.spies.submit();
});
- this.spies = {
- submit: spyOnEvent('form', 'submit'),
- };
-
- this.textarea = $('.js-quick-submit textarea').first();
- });
-
- afterEach(() => {
- // Undo what we did to the shared <body>
- $('body').removeAttr('data-page');
+ testContext.textarea = $('.js-quick-submit textarea').first();
});
it('does not respond to other keyCodes', () => {
- this.textarea.trigger(
+ testContext.textarea.trigger(
keydownEvent({
keyCode: 32,
}),
);
- expect(this.spies.submit).not.toHaveBeenTriggered();
+ expect(testContext.spies.submit).not.toHaveBeenCalled();
});
it('does not respond to Enter alone', () => {
- this.textarea.trigger(
+ testContext.textarea.trigger(
keydownEvent({
ctrlKey: false,
metaKey: false,
}),
);
- expect(this.spies.submit).not.toHaveBeenTriggered();
+ expect(testContext.spies.submit).not.toHaveBeenCalled();
});
it('does not respond to repeated events', () => {
- this.textarea.trigger(
+ testContext.textarea.trigger(
keydownEvent({
repeat: true,
}),
);
- expect(this.spies.submit).not.toHaveBeenTriggered();
+ expect(testContext.spies.submit).not.toHaveBeenCalled();
});
it('disables input of type submit', () => {
const submitButton = $('.js-quick-submit input[type=submit]');
- this.textarea.trigger(keydownEvent());
+ testContext.textarea.trigger(keydownEvent());
expect(submitButton).toBeDisabled();
});
it('disables button of type submit', () => {
const submitButton = $('.js-quick-submit input[type=submit]');
- this.textarea.trigger(keydownEvent());
+ testContext.textarea.trigger(keydownEvent());
expect(submitButton).toBeDisabled();
});
@@ -73,71 +75,79 @@ describe('Quick Submit behavior', function() {
const existingSubmit = $('.js-quick-submit input[type=submit]');
// Add an extra submit button
const newSubmit = $('<button type="submit">Submit it</button>');
- newSubmit.insertAfter(this.textarea);
+ newSubmit.insertAfter(testContext.textarea);
- const oldClick = spyOnEvent(existingSubmit, 'click');
- const newClick = spyOnEvent(newSubmit, 'click');
+ const spies = {
+ oldClickSpy: jest.fn(),
+ newClickSpy: jest.fn(),
+ };
+ existingSubmit.on('click', () => {
+ spies.oldClickSpy();
+ });
+ newSubmit.on('click', () => {
+ spies.newClickSpy();
+ });
- this.textarea.trigger(keydownEvent());
+ testContext.textarea.trigger(keydownEvent());
- expect(oldClick).not.toHaveBeenTriggered();
- expect(newClick).toHaveBeenTriggered();
+ expect(spies.oldClickSpy).not.toHaveBeenCalled();
+ expect(spies.newClickSpy).toHaveBeenCalled();
});
// We cannot stub `navigator.userAgent` for CI's `rake karma` task, so we'll
// only run the tests that apply to the current platform
if (navigator.userAgent.match(/Macintosh/)) {
describe('In Macintosh', () => {
it('responds to Meta+Enter', () => {
- this.textarea.trigger(keydownEvent());
+ testContext.textarea.trigger(keydownEvent());
- expect(this.spies.submit).toHaveBeenTriggered();
+ expect(testContext.spies.submit).toHaveBeenCalled();
});
it('excludes other modifier keys', () => {
- this.textarea.trigger(
+ testContext.textarea.trigger(
keydownEvent({
altKey: true,
}),
);
- this.textarea.trigger(
+ testContext.textarea.trigger(
keydownEvent({
ctrlKey: true,
}),
);
- this.textarea.trigger(
+ testContext.textarea.trigger(
keydownEvent({
shiftKey: true,
}),
);
- expect(this.spies.submit).not.toHaveBeenTriggered();
+ expect(testContext.spies.submit).not.toHaveBeenCalled();
});
});
} else {
it('responds to Ctrl+Enter', () => {
- this.textarea.trigger(keydownEvent());
+ testContext.textarea.trigger(keydownEvent());
- expect(this.spies.submit).toHaveBeenTriggered();
+ expect(testContext.spies.submit).toHaveBeenCalled();
});
it('excludes other modifier keys', () => {
- this.textarea.trigger(
+ testContext.textarea.trigger(
keydownEvent({
altKey: true,
}),
);
- this.textarea.trigger(
+ testContext.textarea.trigger(
keydownEvent({
metaKey: true,
}),
);
- this.textarea.trigger(
+ testContext.textarea.trigger(
keydownEvent({
shiftKey: true,
}),
);
- expect(this.spies.submit).not.toHaveBeenTriggered();
+ expect(testContext.spies.submit).not.toHaveBeenCalled();
});
}
});
diff --git a/spec/frontend/registry/explorer/pages/details_spec.js b/spec/frontend/registry/explorer/pages/details_spec.js
index 48f3b0f9b65..2b83f7e7351 100644
--- a/spec/frontend/registry/explorer/pages/details_spec.js
+++ b/spec/frontend/registry/explorer/pages/details_spec.js
@@ -1,5 +1,5 @@
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';
@@ -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' });
@@ -33,7 +32,7 @@ describe('Details Page', () => {
...stubChildren(component),
GlModal,
GlSprintf: false,
- GlTable: false,
+ GlTable,
},
mocks: {
$route: {
@@ -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);
});
});
diff --git a/spec/frontend/registry/explorer/pages/list_spec.js b/spec/frontend/registry/explorer/pages/list_spec.js
index f463dc49035..91c3c242ed4 100644
--- a/spec/frontend/registry/explorer/pages/list_spec.js
+++ b/spec/frontend/registry/explorer/pages/list_spec.js
@@ -1,6 +1,6 @@
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/';
@@ -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);
@@ -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);
});
});
@@ -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', () => {
diff --git a/spec/frontend/registry/explorer/stores/actions_spec.js b/spec/frontend/registry/explorer/stores/actions_spec.js
index a3fb29c0eb9..3e22621058e 100644
--- a/spec/frontend/registry/explorer/stores/actions_spec.js
+++ b/spec/frontend/registry/explorer/stores/actions_spec.js
@@ -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',
@@ -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,
@@ -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',
@@ -267,9 +256,6 @@ describe('Actions RegistryExplorer Store', () => {
params,
},
{
- config: {
- projectPath,
- },
tagsPagination: {},
},
[
diff --git a/spec/frontend/registry/explorer/stores/getters_spec.js b/spec/frontend/registry/explorer/stores/getters_spec.js
new file mode 100644
index 00000000000..c224f076d30
--- /dev/null
+++ b/spec/frontend/registry/explorer/stores/getters_spec.js
@@ -0,0 +1,34 @@
+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([]);
+ });
+ });
+ });
+});
diff --git a/spec/lib/gitlab/config_checker/puma_rugged_checker_spec.rb b/spec/lib/gitlab/config_checker/puma_rugged_checker_spec.rb
index 070887c83c3..badfd56d571 100644
--- a/spec/lib/gitlab/config_checker/puma_rugged_checker_spec.rb
+++ b/spec/lib/gitlab/config_checker/puma_rugged_checker_spec.rb
@@ -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.'
@@ -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
diff --git a/spec/models/snippet_repository_spec.rb b/spec/models/snippet_repository_spec.rb
index 9befbb02b17..5b16b945efe 100644
--- a/spec/models/snippet_repository_spec.rb
+++ b/spec/models/snippet_repository_spec.rb
@@ -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) }
@@ -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)
@@ -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
diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb
index 7efc426c81d..16903d9d6d0 100644
--- a/spec/requests/api/project_snippets_spec.rb
+++ b/spec/requests/api/project_snippets_spec.rb
@@ -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) }
@@ -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
@@ -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)
diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb
index 21565265b99..cb2a0adc092 100644
--- a/spec/requests/api/snippets_spec.rb
+++ b/spec/requests/api/snippets_spec.rb
@@ -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)
@@ -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
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index e503f1a4231..449c4c07b08 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -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
diff --git a/spec/services/groups/deploy_tokens/create_service_spec.rb b/spec/services/groups/deploy_tokens/create_service_spec.rb
new file mode 100644
index 00000000000..20c609bc828
--- /dev/null
+++ b/spec/services/groups/deploy_tokens/create_service_spec.rb
@@ -0,0 +1,10 @@
+# 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
diff --git a/spec/services/projects/deploy_tokens/create_service_spec.rb b/spec/services/projects/deploy_tokens/create_service_spec.rb
new file mode 100644
index 00000000000..5c3ada8af4e
--- /dev/null
+++ b/spec/services/projects/deploy_tokens/create_service_spec.rb
@@ -0,0 +1,10 @@
+# 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
diff --git a/spec/services/snippets/create_service_spec.rb b/spec/services/snippets/create_service_spec.rb
index 37b203c2341..5c853f8b7d7 100644
--- a/spec/services/snippets/create_service_spec.rb
+++ b/spec/services/snippets/create_service_spec.rb
@@ -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
@@ -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
@@ -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
diff --git a/spec/services/deploy_tokens/create_service_spec.rb b/spec/support/services/deploy_token_shared_examples.rb
index fbb66fe4cb7..b49f4743f7d 100644
--- a/spec/services/deploy_tokens/create_service_spec.rb
+++ b/spec/support/services/deploy_token_shared_examples.rb
@@ -1,14 +1,11 @@
# 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
@@ -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
@@ -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
diff --git a/spec/support/shared_examples/controllers/deploy_token_shared_examples.rb b/spec/support/shared_examples/controllers/deploy_token_shared_examples.rb
new file mode 100644
index 00000000000..791eb0b68e0
--- /dev/null
+++ b/spec/support/shared_examples/controllers/deploy_token_shared_examples.rb
@@ -0,0 +1,22 @@
+# 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
diff --git a/spec/support/shared_examples/features/deploy_token_shared_examples.rb b/spec/support/shared_examples/features/deploy_token_shared_examples.rb
new file mode 100644
index 00000000000..f358615ee9e
--- /dev/null
+++ b/spec/support/shared_examples/features/deploy_token_shared_examples.rb
@@ -0,0 +1,27 @@
+# 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
diff --git a/spec/views/import/gitlab_projects/new.html.haml_spec.rb b/spec/views/import/gitlab_projects/new.html.haml_spec.rb
index 953fcc6dc51..17636c99cbc 100644
--- a/spec/views/import/gitlab_projects/new.html.haml_spec.rb
+++ b/spec/views/import/gitlab_projects/new.html.haml_spec.rb
@@ -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