diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-05 18:08:19 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-05 18:08:19 +0000 |
commit | a8de96bff51846e160b76506dc0ca0fe6f767f64 (patch) | |
tree | 1036f1ca75aba492eaaa3439c84a3109b4684896 /spec | |
parent | afe2b984524ae4b0c8a0636db7ec5b2c452f0734 (diff) | |
download | gitlab-ce-a8de96bff51846e160b76506dc0ca0fe6f767f64.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
30 files changed, 398 insertions, 243 deletions
diff --git a/spec/features/groups/group_page_with_external_authorization_service_spec.rb b/spec/features/groups/group_page_with_external_authorization_service_spec.rb index 823c8cc8fad..a71b930d35f 100644 --- a/spec/features/groups/group_page_with_external_authorization_service_spec.rb +++ b/spec/features/groups/group_page_with_external_authorization_service_spec.rb @@ -47,7 +47,7 @@ describe 'The group page' do expect(page).to have_link('Group overview') expect(page).to have_link('Details') expect(page).not_to have_link('Activity') - expect(page).not_to have_link('Contribution Analytics') + expect(page).not_to have_link('Contribution') expect(page).not_to have_link('Issues') expect(page).not_to have_link('Merge Requests') diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb index 4d45bcf639d..0c457c11fce 100644 --- a/spec/features/groups/navbar_spec.rb +++ b/spec/features/groups/navbar_spec.rb @@ -10,7 +10,7 @@ describe 'Group navbar' do { nav_item: _('Analytics'), nav_sub_items: [ - _('Contribution Analytics') + _('Contribution') ] } end @@ -63,7 +63,7 @@ describe 'Group navbar' do before do stub_licensed_features(productivity_analytics: true) - analytics_nav_item[:nav_sub_items] << _('Productivity Analytics') + analytics_nav_item[:nav_sub_items] << _('Productivity') group.add_maintainer(user) sign_in(user) @@ -78,7 +78,7 @@ describe 'Group navbar' do before do stub_licensed_features(cycle_analytics_for_groups: true) - analytics_nav_item[:nav_sub_items] << _('Value Stream Analytics') + analytics_nav_item[:nav_sub_items] << _('Value Stream') group.add_maintainer(user) sign_in(user) diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb index 9baba80bf06..e7c675bf6bf 100644 --- a/spec/features/issues/issue_sidebar_spec.rb +++ b/spec/features/issues/issue_sidebar_spec.rb @@ -225,6 +225,29 @@ describe 'Issue Sidebar' do it 'does not have a option to edit labels' do expect(page).not_to have_selector('.block.labels .edit-link') end + + context 'interacting with collapsed sidebar', :js do + collapsed_sidebar_selector = 'aside.right-sidebar.right-sidebar-collapsed' + expanded_sidebar_selector = 'aside.right-sidebar.right-sidebar-expanded' + lock_sidebar_block = '.block.lock' + lock_button = '.block.lock .btn-close' + collapsed_sidebar_block_icon = '.sidebar-collapsed-icon' + + before do + resize_screen_sm + end + + it 'expands then does not show the lock dialog form' do + expect(page).to have_css(collapsed_sidebar_selector) + + page.within(lock_sidebar_block) do + find(collapsed_sidebar_block_icon).click + end + + expect(page).to have_css(expanded_sidebar_selector) + expect(page).not_to have_selector(lock_button) + end + end end def visit_issue(project, issue) diff --git a/spec/features/projects/active_tabs_spec.rb b/spec/features/projects/active_tabs_spec.rb index d7060c63d6d..69681da6b2a 100644 --- a/spec/features/projects/active_tabs_spec.rb +++ b/spec/features/projects/active_tabs_spec.rb @@ -136,16 +136,16 @@ describe 'Project active tab' do context 'on project Analytics/Repository Analytics' do it_behaves_like 'page has active tab', _('Analytics') - it_behaves_like 'page has active sub tab', _('Repository Analytics') + it_behaves_like 'page has active sub tab', _('Repository') end context 'on project Analytics/Cycle Analytics' do before do - click_tab(_('CI / CD Analytics')) + click_tab(_('CI / CD')) end it_behaves_like 'page has active tab', _('Analytics') - it_behaves_like 'page has active sub tab', _('CI / CD Analytics') + it_behaves_like 'page has active sub tab', _('CI / CD') end end end diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb index 95a8f974261..dabb2b2dbf2 100644 --- a/spec/features/projects/navbar_spec.rb +++ b/spec/features/projects/navbar_spec.rb @@ -10,10 +10,10 @@ describe 'Project navbar' do { nav_item: _('Analytics'), nav_sub_items: [ - _('CI / CD Analytics'), + _('CI / CD'), (_('Code Review') if Gitlab.ee?), - _('Repository Analytics'), - _('Value Stream Analytics') + _('Repository'), + _('Value Stream') ] } end @@ -114,7 +114,7 @@ describe 'Project navbar' do before do stub_licensed_features(issues_analytics: true) - analytics_nav_item[:nav_sub_items] << _('Issues Analytics') + analytics_nav_item[:nav_sub_items] << _('Issues') analytics_nav_item[:nav_sub_items].sort! visit project_path(project) diff --git a/spec/features/projects/user_uses_shortcuts_spec.rb b/spec/features/projects/user_uses_shortcuts_spec.rb index beed1c07e51..33c2e65633e 100644 --- a/spec/features/projects/user_uses_shortcuts_spec.rb +++ b/spec/features/projects/user_uses_shortcuts_spec.rb @@ -222,7 +222,7 @@ describe 'User uses shortcuts', :js do find('body').native.send_key('d') expect(page).to have_active_navigation(_('Analytics')) - expect(page).to have_active_sub_navigation(_('Repository Analytics')) + expect(page).to have_active_sub_navigation(_('Repository')) end end end diff --git a/spec/fixtures/group_export_invalid_subrelations.tar.gz b/spec/fixtures/group_export_invalid_subrelations.tar.gz Binary files differnew file mode 100644 index 00000000000..6a8f1453517 --- /dev/null +++ b/spec/fixtures/group_export_invalid_subrelations.tar.gz diff --git a/spec/frontend/blob/components/__snapshots__/blob_edit_header_spec.js.snap b/spec/frontend/blob/components/__snapshots__/blob_edit_header_spec.js.snap new file mode 100644 index 00000000000..e47a7dcfa2a --- /dev/null +++ b/spec/frontend/blob/components/__snapshots__/blob_edit_header_spec.js.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Blob Header Editing rendering matches the snapshot 1`] = ` +<div + class="js-file-title file-title-flex-parent" +> + <gl-form-input-stub + class="form-control js-snippet-file-name qa-snippet-file-name" + id="snippet_file_name" + name="snippet_file_name" + placeholder="Give your file a name to add code highlighting, e.g. example.rb for Ruby" + type="text" + value="foo.md" + /> +</div> +`; diff --git a/spec/frontend/blob/components/blob_edit_header_spec.js b/spec/frontend/blob/components/blob_edit_header_spec.js new file mode 100644 index 00000000000..db7d7d7d48d --- /dev/null +++ b/spec/frontend/blob/components/blob_edit_header_spec.js @@ -0,0 +1,50 @@ +import { shallowMount } from '@vue/test-utils'; +import BlobEditHeader from '~/blob/components/blob_edit_header.vue'; +import { GlFormInput } from '@gitlab/ui'; + +describe('Blob Header Editing', () => { + let wrapper; + const value = 'foo.md'; + + function createComponent() { + wrapper = shallowMount(BlobEditHeader, { + propsData: { + value, + }, + }); + } + + beforeEach(() => { + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + describe('rendering', () => { + it('matches the snapshot', () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it('contains a form input field', () => { + expect(wrapper.contains(GlFormInput)).toBe(true); + }); + }); + + describe('functionality', () => { + it('emits input event when the blob name is changed', () => { + const inputComponent = wrapper.find(GlFormInput); + const newValue = 'bar.txt'; + + wrapper.setData({ + name: newValue, + }); + inputComponent.vm.$emit('change'); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.emitted().input[0]).toEqual([newValue]); + }); + }); + }); +}); diff --git a/spec/frontend/sidebar/mock_data.js b/spec/frontend/sidebar/mock_data.js index 3ee97b978fd..c7e52eae9bd 100644 --- a/spec/frontend/sidebar/mock_data.js +++ b/spec/frontend/sidebar/mock_data.js @@ -178,8 +178,17 @@ const RESPONSE_MAP = { }, }; +const graphQlResponseData = { + project: { + issue: { + healthStatus: 'onTrack', + }, + }, +}; + const mockData = { responseMap: RESPONSE_MAP, + graphQlResponseData, mediator: { endpoint: '/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar_extras', toggleSubscriptionEndpoint: '/gitlab-org/gitlab-shell/issues/5/toggle_subscription', @@ -195,6 +204,7 @@ const mockData = { }, rootPath: '/', fullPath: '/gitlab-org/gitlab-shell', + id: 1, }, time: { time_estimate: 3600, diff --git a/spec/frontend/snippet/snippet_bundle_spec.js b/spec/frontend/snippet/snippet_bundle_spec.js index af98e8d665d..12d20d5cd85 100644 --- a/spec/frontend/snippet/snippet_bundle_spec.js +++ b/spec/frontend/snippet/snippet_bundle_spec.js @@ -27,7 +27,7 @@ describe('Snippet editor', () => { setHTMLFixture(` <div class="snippet-form-holder"> <form> - <input class="snippet-file-name" type="text" value="${name}"> + <input class="js-snippet-file-name" type="text" value="${name}"> <input class="snippet-file-content" type="hidden" value="${content}"> <pre id="editor"></pre> </form> @@ -39,7 +39,7 @@ describe('Snippet editor', () => { setUpFixture(name, content); editorEl = document.getElementById('editor'); contentEl = document.querySelector('.snippet-file-content'); - fileNameEl = document.querySelector('.snippet-file-name'); + fileNameEl = document.querySelector('.js-snippet-file-name'); form = document.querySelector('.snippet-form-holder form'); initEditor(); diff --git a/spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js b/spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js index 0a3f0d6901f..5296908afe2 100644 --- a/spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js +++ b/spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js @@ -83,4 +83,17 @@ describe('LockIssueSidebar', () => { done(); }); }); + + it('does not display the edit form when opened from collapsed state if not editable', done => { + expect(vm2.isLockDialogOpen).toBe(false); + + vm2.$el.querySelector('.sidebar-collapsed-icon').click(); + + Vue.nextTick() + .then(() => { + expect(vm2.isLockDialogOpen).toBe(false); + }) + .then(done) + .catch(done.fail); + }); }); diff --git a/spec/javascripts/sidebar/sidebar_mediator_spec.js b/spec/javascripts/sidebar/sidebar_mediator_spec.js index b0412105e3f..2aa30fd1cc6 100644 --- a/spec/javascripts/sidebar/sidebar_mediator_spec.js +++ b/spec/javascripts/sidebar/sidebar_mediator_spec.js @@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; import SidebarMediator from '~/sidebar/sidebar_mediator'; import SidebarStore from '~/sidebar/stores/sidebar_store'; -import SidebarService from '~/sidebar/services/sidebar_service'; +import SidebarService, { gqClient } from '~/sidebar/services/sidebar_service'; import Mock from './mock_data'; const { mediator: mediatorMockData } = Mock; @@ -44,12 +44,18 @@ describe('Sidebar mediator', function() { it('fetches the data', done => { const mockData = Mock.responseMap.GET[mediatorMockData.endpoint]; mock.onGet(mediatorMockData.endpoint).reply(200, mockData); + + const mockGraphQlData = Mock.graphQlResponseData; + spyOn(gqClient, 'query').and.returnValue({ + data: mockGraphQlData, + }); + spyOn(this.mediator, 'processFetchedData').and.callThrough(); this.mediator .fetch() .then(() => { - expect(this.mediator.processFetchedData).toHaveBeenCalledWith(mockData); + expect(this.mediator.processFetchedData).toHaveBeenCalledWith(mockData, mockGraphQlData); }) .then(done) .catch(done.fail); diff --git a/spec/lib/gitlab/background_migration/link_lfs_objects_spec.rb b/spec/lib/gitlab/background_migration/link_lfs_objects_spec.rb deleted file mode 100644 index aba903e2f26..00000000000 --- a/spec/lib/gitlab/background_migration/link_lfs_objects_spec.rb +++ /dev/null @@ -1,76 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe Gitlab::BackgroundMigration::LinkLfsObjects, :migration, schema: 2020_02_10_062432 do - let(:namespaces) { table(:namespaces) } - let(:projects) { table(:projects) } - let(:fork_networks) { table(:fork_networks) } - let(:fork_network_members) { table(:fork_network_members) } - let(:lfs_objects) { table(:lfs_objects) } - let(:lfs_objects_projects) { table(:lfs_objects_projects) } - - let(:namespace) { namespaces.create(name: 'GitLab', path: 'gitlab') } - - let!(:source_project) { projects.create(namespace_id: namespace.id) } - let!(:another_source_project) { projects.create(namespace_id: namespace.id) } - let!(:project) { projects.create(namespace_id: namespace.id) } - let!(:another_project) { projects.create(namespace_id: namespace.id) } - let!(:other_project) { projects.create(namespace_id: namespace.id) } - let!(:linked_project) { projects.create(namespace_id: namespace.id) } - - let(:fork_network) { fork_networks.create(root_project_id: source_project.id) } - let(:another_fork_network) { fork_networks.create(root_project_id: another_source_project.id) } - - let(:lfs_object) { lfs_objects.create(oid: 'abc123', size: 100) } - let(:another_lfs_object) { lfs_objects.create(oid: 'def456', size: 200) } - - before do - stub_const("#{described_class}::BATCH_SIZE", 2) - - # Create links between projects - fork_network_members.create(fork_network_id: fork_network.id, project_id: source_project.id, forked_from_project_id: nil) - - [project, another_project, linked_project].each do |p| - fork_network_members.create( - fork_network_id: fork_network.id, - project_id: p.id, - forked_from_project_id: fork_network.root_project_id - ) - end - - fork_network_members.create(fork_network_id: another_fork_network.id, project_id: another_source_project.id, forked_from_project_id: nil) - fork_network_members.create(fork_network_id: another_fork_network.id, project_id: other_project.id, forked_from_project_id: another_fork_network.root_project_id) - - # Links LFS objects to some projects - [source_project, another_source_project, linked_project].each do |p| - lfs_objects_projects.create(lfs_object_id: lfs_object.id, project_id: p.id) - lfs_objects_projects.create(lfs_object_id: another_lfs_object.id, project_id: p.id) - end - end - - it 'creates LfsObjectsProject records for forks within the specified range of project IDs' do - expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |logger| - expect(logger).to receive(:info).twice - end - - expect { subject.perform(project.id, other_project.id) }.to change { lfs_objects_projects.count }.by(6) - - expect(lfs_object_ids_for(project)).to match_array(lfs_object_ids_for(source_project)) - expect(lfs_object_ids_for(another_project)).to match_array(lfs_object_ids_for(source_project)) - expect(lfs_object_ids_for(other_project)).to match_array(lfs_object_ids_for(another_source_project)) - - expect { subject.perform(project.id, other_project.id) }.not_to change { lfs_objects_projects.count } - end - - context 'when it is not necessary to create LfsObjectProject records' do - it 'does not create LfsObjectProject records' do - expect { subject.perform(linked_project.id, linked_project.id) } - .not_to change { lfs_objects_projects.count } - end - end - - def lfs_object_ids_for(project) - lfs_objects_projects.where(project_id: project.id).pluck(:lfs_object_id) - end -end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 78e80576aef..bbb61b4c356 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -467,6 +467,7 @@ project: - resource_groups - autoclose_referenced_issues - status_page_setting +- requirements award_emoji: - awardable - user diff --git a/spec/lib/gitlab/import_export/error_spec.rb b/spec/lib/gitlab/import_export/error_spec.rb new file mode 100644 index 00000000000..067f7049097 --- /dev/null +++ b/spec/lib/gitlab/import_export/error_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::ImportExport::Error do + describe '.permission_error' do + subject(:error) do + described_class.permission_error(user, importable) + end + + let(:user) { build(:user, id: 1) } + + context 'when supplied a project' do + let(:importable) { build(:project, id: 1, name: 'project1') } + + it 'returns an error with the correct message' do + expect(error.message) + .to eq 'User with ID: 1 does not have required permissions for Project: project1 with ID: 1' + end + end + + context 'when supplied a group' do + let(:importable) { build(:group, id: 1, name: 'group1') } + + it 'returns an error with the correct message' do + expect(error.message) + .to eq 'User with ID: 1 does not have required permissions for Group: group1 with ID: 1' + end + end + end +end diff --git a/spec/lib/gitlab/import_export/project/export_task_spec.rb b/spec/lib/gitlab/import_export/project/export_task_spec.rb new file mode 100644 index 00000000000..cf11a1df33c --- /dev/null +++ b/spec/lib/gitlab/import_export/project/export_task_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require 'rake_helper' + +describe Gitlab::ImportExport::Project::ExportTask do + let(:username) { 'root' } + let(:namespace_path) { username } + let!(:user) { create(:user, username: username) } + let(:measurement_enabled) { false } + let(:file_path) { 'spec/fixtures/gitlab/import_export/test_project_export.tar.gz' } + let(:project) { create(:project, creator: user, namespace: user.namespace) } + let(:project_name) { project.name } + + let(:task_params) do + { + username: username, + namespace_path: namespace_path, + project_path: project_name, + file_path: file_path, + measurement_enabled: measurement_enabled + } + end + + subject { described_class.new(task_params).export } + + context 'when project is found' do + let(:project) { create(:project, creator: user, namespace: user.namespace) } + + around do |example| + example.run + ensure + File.delete(file_path) + end + + it 'performs project export successfully' do + expect { subject }.to output(/Done!/).to_stdout + + expect(subject).to eq(true) + + expect(File).to exist(file_path) + end + + it_behaves_like 'measurable' + end + + context 'when project is not found' do + let(:project_name) { 'invalid project name' } + + it 'logs an error' do + expect { subject }.to output(/Project with path: #{project_name} was not found. Please provide correct project path/).to_stdout + end + + it 'returns false' do + expect(subject).to eq(false) + end + end + + context 'when file path is invalid' do + let(:file_path) { '/invalid_file_path/test_project_export.tar.gz' } + + it 'logs an error' do + expect { subject }.to output(/Invalid file path: #{file_path}. Please provide correct file path/ ).to_stdout + end + + it 'returns false' do + expect(subject).to eq(false) + end + end +end diff --git a/spec/tasks/gitlab/import_export/import_rake_spec.rb b/spec/lib/gitlab/import_export/project/import_task_spec.rb index 3e0bf2d0832..f7b9cbaa095 100644 --- a/spec/tasks/gitlab/import_export/import_rake_spec.rb +++ b/spec/lib/gitlab/import_export/project/import_task_spec.rb @@ -2,19 +2,25 @@ require 'rake_helper' -describe 'gitlab:import_export:import rake task' do +describe Gitlab::ImportExport::Project::ImportTask do let(:username) { 'root' } let(:namespace_path) { username } let!(:user) { create(:user, username: username) } let(:measurement_enabled) { false } - let(:task_params) { [username, namespace_path, project_name, archive_path, measurement_enabled] } let(:project) { Project.find_by_full_path("#{namespace_path}/#{project_name}") } + let(:import_task) { described_class.new(task_params) } + let(:task_params) do + { + username: username, + namespace_path: namespace_path, + project_path: project_name, + file_path: file_path, + measurement_enabled: measurement_enabled + } + end before do - Rake.application.rake_require('tasks/gitlab/import_export/import') allow(Settings.uploads.object_store).to receive(:[]=).and_call_original - allow_any_instance_of(GitlabProjectImport).to receive(:exit) - .and_raise(RuntimeError, 'exit not handled') end around do |example| @@ -30,15 +36,16 @@ describe 'gitlab:import_export:import rake task' do Settings.uploads.object_store['background_upload'] = old_background_upload_setting end - subject { run_rake_task('gitlab:import_export:import', task_params) } + subject { import_task.import } context 'when project import is valid' do let(:project_name) { 'import_rake_test_project' } - let(:archive_path) { 'spec/fixtures/gitlab/import_export/lightweight_project_export.tar.gz' } + let(:file_path) { 'spec/fixtures/gitlab/import_export/lightweight_project_export.tar.gz' } it 'performs project import successfully' do expect { subject }.to output(/Done!/).to_stdout expect { subject }.not_to raise_error + expect(subject).to eq(true) expect(project.merge_requests.count).to be > 0 expect(project.issues.count).to be > 0 @@ -56,15 +63,13 @@ describe 'gitlab:import_export:import rake task' do end end - expect_next_instance_of(GitlabProjectImport) do |importer| - expect(importer).to receive(:execute_sidekiq_job).and_wrap_original do |m| - expect(Settings.uploads.object_store['background_upload']).to eq(true) - expect(Settings.uploads.object_store['direct_upload']).to eq(true) - expect(Settings.uploads.object_store).not_to receive(:[]=).with('backgroud_upload', false) - expect(Settings.uploads.object_store).not_to receive(:[]=).with('direct_upload', false) + expect(import_task).to receive(:execute_sidekiq_job).and_wrap_original do |m| + expect(Settings.uploads.object_store['background_upload']).to eq(true) + expect(Settings.uploads.object_store['direct_upload']).to eq(true) + expect(Settings.uploads.object_store).not_to receive(:[]=).with('backgroud_upload', false) + expect(Settings.uploads.object_store).not_to receive(:[]=).with('direct_upload', false) - m.call - end + m.call end subject @@ -75,13 +80,13 @@ describe 'gitlab:import_export:import rake task' do context 'when project import is invalid' do let(:project_name) { 'import_rake_invalid_test_project' } - let(:archive_path) { 'spec/fixtures/gitlab/import_export/corrupted_project_export.tar.gz' } + let(:file_path) { 'spec/fixtures/gitlab/import_export/corrupted_project_export.tar.gz' } let(:not_imported_message) { /Total number of not imported relations: 1/ } - let(:error) { /Validation failed: Notes is invalid/ } it 'performs project import successfully' do expect { subject }.to output(not_imported_message).to_stdout expect { subject }.not_to raise_error + expect(subject).to eq(true) expect(project.merge_requests).to be_empty expect(project.import_state.last_error).to be_nil diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index b50481a85cd..7bc9e1a9a32 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -324,6 +324,24 @@ describe Gitlab::UsageData do end end + describe '#cycle_analytics_usage_data' do + subject { described_class.cycle_analytics_usage_data } + + it 'works when queries time out in new' do + allow(Gitlab::CycleAnalytics::UsageData) + .to receive(:new).and_raise(ActiveRecord::StatementInvalid.new('')) + + expect { subject }.not_to raise_error + end + + it 'works when queries time out in to_json' do + allow_any_instance_of(Gitlab::CycleAnalytics::UsageData) + .to receive(:to_json).and_raise(ActiveRecord::StatementInvalid.new('')) + + expect { subject }.not_to raise_error + end + end + describe '#ingress_modsecurity_usage' do subject { described_class.ingress_modsecurity_usage } diff --git a/spec/migrations/reschedule_link_lfs_objects_spec.rb b/spec/migrations/reschedule_link_lfs_objects_spec.rb deleted file mode 100644 index 6ce6e77f514..00000000000 --- a/spec/migrations/reschedule_link_lfs_objects_spec.rb +++ /dev/null @@ -1,86 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' -require Rails.root.join('db', 'post_migrate', '20200217091401_reschedule_link_lfs_objects.rb') - -describe RescheduleLinkLfsObjects, :migration, :sidekiq do - let(:namespaces) { table(:namespaces) } - let(:projects) { table(:projects) } - let(:fork_networks) { table(:fork_networks) } - let(:fork_network_members) { table(:fork_network_members) } - let(:lfs_objects) { table(:lfs_objects) } - let(:lfs_objects_projects) { table(:lfs_objects_projects) } - - let(:namespace) { namespaces.create(name: 'GitLab', path: 'gitlab') } - - let(:fork_network) { fork_networks.create(root_project_id: source_project.id) } - let(:another_fork_network) { fork_networks.create(root_project_id: another_source_project.id) } - - let!(:source_project) { projects.create(namespace_id: namespace.id) } - let!(:another_source_project) { projects.create(namespace_id: namespace.id) } - let!(:project) { projects.create(namespace_id: namespace.id) } - let!(:another_project) { projects.create(namespace_id: namespace.id) } - let!(:other_project) { projects.create(namespace_id: namespace.id) } - let!(:linked_project) { projects.create(namespace_id: namespace.id) } - - let(:lfs_object) { lfs_objects.create(oid: 'abc123', size: 100) } - let(:another_lfs_object) { lfs_objects.create(oid: 'def456', size: 200) } - - before do - # Create links between projects - fork_network_members.create(fork_network_id: fork_network.id, project_id: source_project.id, forked_from_project_id: nil) - - [project, another_project, linked_project].each do |p| - fork_network_members.create( - fork_network_id: fork_network.id, - project_id: p.id, - forked_from_project_id: fork_network.root_project_id - ) - end - - fork_network_members.create(fork_network_id: another_fork_network.id, project_id: another_source_project.id, forked_from_project_id: nil) - fork_network_members.create(fork_network_id: another_fork_network.id, project_id: other_project.id, forked_from_project_id: another_fork_network.root_project_id) - end - - context 'when there are forks to be backfilled' do - before do - stub_const("#{described_class.name}::BATCH_SIZE", 2) - - # Links LFS objects to some projects - [source_project, another_source_project, linked_project].each do |p| - lfs_objects_projects.create(lfs_object_id: lfs_object.id, project_id: p.id) - lfs_objects_projects.create(lfs_object_id: another_lfs_object.id, project_id: p.id) - end - end - - it 'schedules background migration to link LFS objects' do - Sidekiq::Testing.fake! do - migrate! - - expect(BackgroundMigrationWorker.jobs.size).to eq(2) - expect(described_class::MIGRATION) - .to be_scheduled_delayed_migration(2.minutes, project.id, another_project.id) - expect(described_class::MIGRATION) - .to be_scheduled_delayed_migration(4.minutes, other_project.id, other_project.id) - end - end - end - - context 'when there are no forks to be backfilled' do - before do - # Links LFS objects to all projects - projects.all.each do |p| - lfs_objects_projects.create(lfs_object_id: lfs_object.id, project_id: p.id) - lfs_objects_projects.create(lfs_object_id: another_lfs_object.id, project_id: p.id) - end - end - - it 'does not schedule any job' do - Sidekiq::Testing.fake! do - migrate! - - expect(BackgroundMigrationWorker.jobs.size).to eq(0) - end - end - end -end diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb index 67d8284bebe..6cef81d6e44 100644 --- a/spec/models/broadcast_message_spec.rb +++ b/spec/models/broadcast_message_spec.rb @@ -65,6 +65,17 @@ describe BroadcastMessage do end end + it 'expires the value if a broadcast message has ended', :request_store do + message = create(:broadcast_message, broadcast_type: broadcast_type, ends_at: Time.now.utc + 1.day) + + expect(subject.call).to match_array([message]) + expect(described_class.cache).to receive(:expire).and_call_original + + Timecop.travel(1.week) do + 2.times { expect(subject.call).to be_empty } + end + end + it 'does not create new records' do create(:broadcast_message, broadcast_type: broadcast_type) diff --git a/spec/services/groups/import_export/export_service_spec.rb b/spec/services/groups/import_export/export_service_spec.rb index 5eebf08892a..0d7fa98e16b 100644 --- a/spec/services/groups/import_export/export_service_spec.rb +++ b/spec/services/groups/import_export/export_service_spec.rb @@ -38,12 +38,31 @@ describe Groups::ImportExport::ExportService do let!(:another_user) { create(:user) } let(:service) { described_class.new(group: group, user: another_user, params: { shared: shared }) } + let(:expected_message) do + "User with ID: %s does not have required permissions for Group: %s with ID: %s" % + [another_user.id, group.name, group.id] + end + it 'fails' do - expected_message = - "User with ID: %s does not have permission to Group %s with ID: %s." % - [another_user.id, group.name, group.id] expect { service.execute }.to raise_error(Gitlab::ImportExport::Error).with_message(expected_message) end + + it 'logs the error' do + expect(shared.logger).to receive(:error).with( + group_id: group.id, + group_name: group.name, + error: expected_message, + message: 'Group Import/Export: Export failed' + ) + + expect { service.execute }.to raise_error(Gitlab::ImportExport::Error) + end + + it 'tracks the error' do + expect(shared).to receive(:error) { |param| expect(param.message).to eq expected_message } + + expect { service.execute }.to raise_error(Gitlab::ImportExport::Error) + end end context 'when export fails' do diff --git a/spec/services/groups/import_export/import_service_spec.rb b/spec/services/groups/import_export/import_service_spec.rb index bac266d08da..49c786ef67f 100644 --- a/spec/services/groups/import_export/import_service_spec.rb +++ b/spec/services/groups/import_export/import_service_spec.rb @@ -9,6 +9,8 @@ describe Groups::ImportExport::ImportService do let(:service) { described_class.new(group: group, user: user) } let(:import_file) { fixture_file_upload('spec/fixtures/group_export.tar.gz') } + let(:import_logger) { instance_double(Gitlab::Import::Logger) } + subject { service.execute } before do @@ -25,13 +27,82 @@ describe Groups::ImportExport::ImportService do expect(group.import_export_upload.import_file.file).to be_nil end + + it 'logs the import success' do + allow(Gitlab::Import::Logger).to receive(:build).and_return(import_logger) + + expect(import_logger).to receive(:info).with( + group_id: group.id, + group_name: group.name, + message: 'Group Import/Export: Import succeeded' + ) + + subject + end end context 'when user does not have correct permissions' do let(:user) { create(:user) } - it 'raises exception' do - expect { subject }.to raise_error(StandardError) + it 'logs the error and raises an exception' do + allow(Gitlab::Import::Logger).to receive(:build).and_return(import_logger) + + expect(import_logger).to receive(:error).with( + group_id: group.id, + group_name: group.name, + message: a_string_including('Errors occurred') + ) + + expect { subject }.to raise_error(Gitlab::ImportExport::Error) + end + + it 'tracks the error' do + shared = Gitlab::ImportExport::Shared.new(group) + allow(Gitlab::ImportExport::Shared).to receive(:new).and_return(shared) + + expect(shared).to receive(:error) do |param| + expect(param.message).to include 'does not have required permissions for' + end + + expect { subject }.to raise_error(Gitlab::ImportExport::Error) + end + end + + context 'when there are errors with the import file' do + let(:import_file) { fixture_file_upload('spec/fixtures/symlink_export.tar.gz') } + + before do + allow(Gitlab::Import::Logger).to receive(:build).and_return(import_logger) + end + + it 'logs the error and raises an exception' do + expect(import_logger).to receive(:error).with( + group_id: group.id, + group_name: group.name, + message: a_string_including('Errors occurred') + ) + + expect { subject }.to raise_error(Gitlab::ImportExport::Error) + end + end + + context 'when there are errors with the sub-relations' do + let(:import_file) { fixture_file_upload('spec/fixtures/group_export_invalid_subrelations.tar.gz') } + + it 'successfully imports the group' do + expect(subject).to be_truthy + end + + it 'logs the import success' do + allow(Gitlab::Import::Logger).to receive(:build).and_return(import_logger) + + expect(import_logger).to receive(:info).with( + group_id: group.id, + group_name: group.name, + message: 'Group Import/Export: Import succeeded' + ) + + subject end end end diff --git a/spec/services/merge_requests/merge_to_ref_service_spec.rb b/spec/services/merge_requests/merge_to_ref_service_spec.rb index 5c26e32bb22..596d46f3c43 100644 --- a/spec/services/merge_requests/merge_to_ref_service_spec.rb +++ b/spec/services/merge_requests/merge_to_ref_service_spec.rb @@ -91,6 +91,17 @@ describe MergeRequests::MergeToRefService do it_behaves_like 'successfully evaluates pre-condition checks' + it 'returns an error when Gitlab::Git::CommandError is raised during merge' do + allow(project.repository).to receive(:merge_to_ref) do + raise Gitlab::Git::CommandError.new('Failed to create merge commit') + end + + result = service.execute(merge_request) + + expect(result[:status]).to eq(:error) + expect(result[:message]).to eq('Failed to create merge commit') + end + context 'commit history comparison with regular MergeService' do before do # The merge service needs an authorized user while merge-to-ref diff --git a/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb b/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb index 5f7279ee550..431b0db392a 100644 --- a/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb +++ b/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb @@ -29,7 +29,7 @@ describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memory_stor end context 'user does not have push right to repository' do - it_behaves_like 'misconfigured dashboard service response', :forbidden, %q(You can't commit to this project) + it_behaves_like 'misconfigured dashboard service response', :forbidden, %q(You are not allowed to push into this branch. Create another branch or open a merge request.) end context 'with rights to push to the repository' do diff --git a/spec/services/metrics/dashboard/update_dashboard_service_spec.rb b/spec/services/metrics/dashboard/update_dashboard_service_spec.rb index 2bb08579fb9..66622524e9c 100644 --- a/spec/services/metrics/dashboard/update_dashboard_service_spec.rb +++ b/spec/services/metrics/dashboard/update_dashboard_service_spec.rb @@ -27,7 +27,7 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto end context 'user does not have push right to repository' do - it_behaves_like 'misconfigured dashboard service response', :forbidden, "You can't commit to this project" + it_behaves_like 'misconfigured dashboard service response', :forbidden, "You are not allowed to push into this branch. Create another branch or open a merge request." end context 'with rights to push to the repository' do diff --git a/spec/services/projects/import_export/export_service_spec.rb b/spec/services/projects/import_export/export_service_spec.rb index ec1771e64c2..4d51deaa404 100644 --- a/spec/services/projects/import_export/export_service_spec.rb +++ b/spec/services/projects/import_export/export_service_spec.rb @@ -164,7 +164,7 @@ describe Projects::ImportExport::ExportService do it 'fails' do expected_message = - "User with ID: %s does not have permission to Project %s with ID: %s." % + "User with ID: %s does not have required permissions for Project: %s with ID: %s" % [another_user.id, project.name, project.id] expect { service.execute }.to raise_error(Gitlab::ImportExport::Error).with_message(expected_message) end diff --git a/spec/support/shared_examples/tasks/gitlab/import_export/measurable_shared_examples.rb b/spec/support/shared_examples/tasks/gitlab/import_export/measurable_shared_examples.rb index 4df81478639..45b2c5eac3a 100644 --- a/spec/support/shared_examples/tasks/gitlab/import_export/measurable_shared_examples.rb +++ b/spec/support/shared_examples/tasks/gitlab/import_export/measurable_shared_examples.rb @@ -18,7 +18,7 @@ RSpec.shared_examples 'measurable' do end context 'when measurement is not provided' do - let(:task_params) { [username, namespace_path, project_name, archive_path] } + let(:measurement_enabled) { nil } it 'does not output measurement results' do expect { subject }.not_to output(/Measuring enabled.../).to_stdout diff --git a/spec/tasks/gitlab/import_export/export_rake_spec.rb b/spec/tasks/gitlab/import_export/export_rake_spec.rb deleted file mode 100644 index b665b46fe1c..00000000000 --- a/spec/tasks/gitlab/import_export/export_rake_spec.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -require 'rake_helper' - -describe 'gitlab:import_export:export rake task' do - let(:username) { 'root' } - let(:namespace_path) { username } - let!(:user) { create(:user, username: username) } - let(:measurement_enabled) { false } - let(:task_params) { [username, namespace_path, project_name, archive_path, measurement_enabled] } - - before do - Rake.application.rake_require('tasks/gitlab/import_export/export') - end - - subject { run_rake_task('gitlab:import_export:export', task_params) } - - context 'when project is found' do - let(:project) { create(:project, creator: user, namespace: user.namespace) } - let(:project_name) { project.name } - let(:archive_path) { 'spec/fixtures/gitlab/import_export/test_project_export.tar.gz' } - - around do |example| - example.run - ensure - File.delete(archive_path) - end - - it 'performs project export successfully' do - expect { subject }.to output(/Done!/).to_stdout - - expect(File).to exist(archive_path) - end - - it_behaves_like 'measurable' - end -end diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb index 6ca8fa2bc5c..3437839765d 100644 --- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb @@ -173,7 +173,7 @@ describe 'layouts/nav/sidebar/_project' do it 'shows the value stream analytics entry' do render - expect(rendered).to have_link('Value Stream Analytics', href: project_cycle_analytics_path(project)) + expect(rendered).to have_link('Value Stream', href: project_cycle_analytics_path(project)) end end @@ -183,7 +183,7 @@ describe 'layouts/nav/sidebar/_project' do it 'does not show the value stream analytics entry' do render - expect(rendered).not_to have_link('Value Stream Analytics', href: project_cycle_analytics_path(project)) + expect(rendered).not_to have_link('Value Stream', href: project_cycle_analytics_path(project)) end end end |