diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-12-17 09:07:48 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-12-17 09:07:48 +0000 |
commit | 5bd24a54ef4ce3a38a860eb53b66d062c2382971 (patch) | |
tree | 5f5e65571dfcb2c62c27600ee7655dec4b44c923 /spec | |
parent | 74673d04d25ffed35cbcf17cd42969bed0a4e705 (diff) | |
download | gitlab-ce-5bd24a54ef4ce3a38a860eb53b66d062c2382971.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
30 files changed, 432 insertions, 115 deletions
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb index 42248dc1165..2344ffffa65 100644 --- a/spec/factories/merge_requests.rb +++ b/spec/factories/merge_requests.rb @@ -188,6 +188,10 @@ FactoryBot.define do end end + trait :sequence_source_branch do + sequence(:source_branch) { |n| "feature#{n}" } + end + after(:build) do |merge_request| target_project = merge_request.target_project source_project = merge_request.source_project diff --git a/spec/features/groups/clusters/user_spec.rb b/spec/features/groups/clusters/user_spec.rb index e06f2efe183..ceec50e4f58 100644 --- a/spec/features/groups/clusters/user_spec.rb +++ b/spec/features/groups/clusters/user_spec.rb @@ -115,11 +115,11 @@ describe 'User Cluster', :js do end end - context 'when user destroy the cluster' do + context 'when user destroys the cluster' do before do - page.accept_confirm do - click_link 'Remove integration' - end + click_button 'Remove integration and resources' + fill_in 'confirm_cluster_name_input', with: cluster.name + click_button 'Remove integration' end it 'user sees creation form with the successful message' do diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb index 741f46cef45..7c8b2640e89 100644 --- a/spec/features/projects/clusters/gcp_spec.rb +++ b/spec/features/projects/clusters/gcp_spec.rb @@ -131,11 +131,11 @@ describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do end end - context 'when user destroy the cluster' do + context 'when user destroys the cluster' do before do - page.accept_confirm do - click_link 'Remove integration' - end + click_button 'Remove integration and resources' + fill_in 'confirm_cluster_name_input', with: cluster.name + click_button 'Remove integration' end it 'user sees creation form with the successful message' do diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb index bdaeda83926..38efcf758e1 100644 --- a/spec/features/projects/clusters/user_spec.rb +++ b/spec/features/projects/clusters/user_spec.rb @@ -101,11 +101,11 @@ describe 'User Cluster', :js do end end - context 'when user destroy the cluster' do + context 'when user destroys the cluster' do before do - page.accept_confirm do - click_link 'Remove integration' - end + click_button 'Remove integration and resources' + fill_in 'confirm_cluster_name_input', with: cluster.name + click_button 'Remove integration' end it 'user sees creation form with the successful message' do diff --git a/spec/finders/keys_finder_spec.rb b/spec/finders/keys_finder_spec.rb index 147e6ee3d84..f80abdcdb38 100644 --- a/spec/finders/keys_finder_spec.rb +++ b/spec/finders/keys_finder_spec.rb @@ -3,74 +3,145 @@ require 'spec_helper' describe KeysFinder do - subject(:keys_finder) { described_class.new(user, params) } + subject { described_class.new(user, params).execute } let(:user) { create(:user) } - let(:fingerprint_type) { 'md5' } - let(:fingerprint) { 'ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1' } - - let(:params) do - { - type: fingerprint_type, - fingerprint: fingerprint - } - end + let(:params) { {} } - let!(:key) do - create(:key, user: user, + let!(:key_1) do + create(:personal_key, + last_used_at: 7.days.ago, + user: user, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt1016k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=', fingerprint: 'ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1', - fingerprint_sha256: 'nUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo/lCg' - ) + fingerprint_sha256: 'nUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo/lCg') end + let!(:key_2) { create(:personal_key, last_used_at: nil, user: user) } + let!(:key_3) { create(:personal_key, last_used_at: 2.days.ago) } + context 'with a regular user' do it 'raises GitLabAccessDeniedError' do - expect do - keys_finder.execute - end.to raise_error(KeysFinder::GitLabAccessDeniedError) + expect { subject }.to raise_error(KeysFinder::GitLabAccessDeniedError) end end context 'with an admin user' do let(:user) {create(:admin)} - context 'with invalid MD5 fingerprint' do - let(:fingerprint) { '11:11:11:11' } + context 'key_type' do + let!(:deploy_key) { create(:deploy_key) } - it 'raises InvalidFingerprint' do - expect { keys_finder.execute } - .to raise_error(KeysFinder::InvalidFingerprint) - end - end + context 'when `key_type` is `ssh`' do + before do + params[:key_type] = 'ssh' + end - context 'with invalid SHA fingerprint' do - let(:fingerprint_type) { 'sha256' } - let(:fingerprint) { 'nUhzNyftwAAKs7HufskYTte2g' } + it 'returns only SSH keys' do + expect(subject).to contain_exactly(key_1, key_2, key_3) + end + end - it 'raises InvalidFingerprint' do - expect { keys_finder.execute } - .to raise_error(KeysFinder::InvalidFingerprint) + context 'when `key_type` is not specified' do + it 'returns all types of keys' do + expect(subject).to contain_exactly(key_1, key_2, key_3, deploy_key) + end end end - context 'with valid MD5 params' do - it 'returns key if the fingerprint is found' do - result = keys_finder.execute + context 'fingerprint' do + context 'with invalid fingerprint' do + context 'with invalid MD5 fingerprint' do + before do + params[:fingerprint] = '11:11:11:11' + end + + it 'raises InvalidFingerprint' do + expect { subject }.to raise_error(KeysFinder::InvalidFingerprint) + end + end + + context 'with invalid SHA fingerprint' do + before do + params[:fingerprint] = 'nUhzNyftwAAKs7HufskYTte2g' + end + + it 'raises InvalidFingerprint' do + expect { subject }.to raise_error(KeysFinder::InvalidFingerprint) + end + end + end - expect(result).to eq(key) - expect(key.user).to eq(user) + context 'with valid fingerprints' do + context 'with valid MD5 params' do + context 'with an existent fingerprint' do + before do + params[:fingerprint] = 'ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1' + end + + it 'returns the key' do + expect(subject).to eq(key_1) + expect(subject.user).to eq(user) + end + end + + context 'with a non-existent fingerprint' do + before do + params[:fingerprint] = 'bb:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d2' + end + + it 'returns nil' do + expect(subject).to be_nil + end + end + end + + context 'with valid SHA256 params' do + context 'with an existent fingerprint' do + before do + params[:fingerprint] = 'SHA256:nUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo/lCg' + end + + it 'returns key' do + expect(subject).to eq(key_1) + expect(subject.user).to eq(user) + end + end + + context 'with a non-existent fingerprint' do + before do + params[:fingerprint] = 'SHA256:xTjuFqftwADy8AH3wFY31tAKs7HufskYTte2aXi/mNp' + end + + it 'returns nil' do + expect(subject).to be_nil + end + end + end end end - context 'with valid SHA256 params' do - let(:fingerprint) { 'ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1' } + context 'user' do + context 'without user' do + it 'contains ssh_keys of all users in the system' do + expect(subject).to contain_exactly(key_1, key_2, key_3) + end + end + + context 'with user' do + before do + params[:user] = user + end - it 'returns key if the fingerprint is found' do - result = keys_finder.execute + it 'contains ssh_keys of only the specified users' do + expect(subject).to contain_exactly(key_1, key_2) + end + end + end - expect(result).to eq(key) - expect(key.user).to eq(user) + context 'sort order' do + it 'sorts in last_used_at_desc order' do + expect(subject).to eq([key_3, key_1, key_2]) end end end diff --git a/spec/finders/merge_request_target_project_finder_spec.rb b/spec/finders/merge_request_target_project_finder_spec.rb index 1d78b7ba4e3..7fef16d1040 100644 --- a/spec/finders/merge_request_target_project_finder_spec.rb +++ b/spec/finders/merge_request_target_project_finder_spec.rb @@ -27,6 +27,22 @@ describe MergeRequestTargetProjectFinder do expect(finder.execute).to contain_exactly(other_fork, forked_project) end + + it 'does not include routes by default' do + row = finder.execute.first + + expect(row.association(:route).loaded?).to be_falsey + expect(row.association(:namespace).loaded?).to be_falsey + expect(row.namespace.association(:route).loaded?).to be_falsey + end + + it 'includes routes when requested' do + row = finder.execute(include_routes: true).first + + expect(row.association(:route).loaded?).to be_truthy + expect(row.association(:namespace).loaded?).to be_truthy + expect(row.namespace.association(:route).loaded?).to be_truthy + end end context 'public projects' do diff --git a/spec/finders/personal_access_tokens_finder_spec.rb b/spec/finders/personal_access_tokens_finder_spec.rb index a44daf585ba..ce8ef80bb99 100644 --- a/spec/finders/personal_access_tokens_finder_spec.rb +++ b/spec/finders/personal_access_tokens_finder_spec.rb @@ -26,6 +26,16 @@ describe PersonalAccessTokensFinder do revoked_impersonation_token, expired_impersonation_token) end + describe 'with sort order' do + before do + params[:sort] = 'id_asc' + end + + it 'sorts records as per the specified sort order' do + expect(subject).to match_array(PersonalAccessToken.all.order(id: :asc)) + end + end + describe 'without impersonation' do before do params[:impersonation] = false diff --git a/spec/frontend/boards/boards_store_spec.js b/spec/frontend/boards/boards_store_spec.js index 3588197ebdc..bf3d81d3117 100644 --- a/spec/frontend/boards/boards_store_spec.js +++ b/spec/frontend/boards/boards_store_spec.js @@ -41,7 +41,6 @@ describe('boardsStore', () => { afterEach(() => { axiosMock.restore(); - jest.clearAllMocks(); }); const setupDefaultResponses = () => { diff --git a/spec/frontend/clusters/clusters_bundle_spec.js b/spec/frontend/clusters/clusters_bundle_spec.js index 7b1d96c8da5..d7c648bcd20 100644 --- a/spec/frontend/clusters/clusters_bundle_spec.js +++ b/spec/frontend/clusters/clusters_bundle_spec.js @@ -46,7 +46,6 @@ describe('Clusters', () => { afterEach(() => { cluster.destroy(); mock.restore(); - jest.clearAllMocks(); }); describe('class constructor', () => { diff --git a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap new file mode 100644 index 00000000000..8f406c62824 --- /dev/null +++ b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap @@ -0,0 +1,80 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Remove cluster confirmation modal renders splitbutton with modal included 1`] = ` +<div> + <div + class="dropdown btn-group b-dropdown gl-dropdown" + > + <button + class="btn btn-danger" + type="button" + > + + Remove integration and resources + + <!----> + </button> + <button + aria-expanded="false" + aria-haspopup="true" + class="btn dropdown-toggle btn-danger dropdown-toggle-split" + type="button" + > + <span + class="sr-only" + > + Toggle Dropdown + </span> + </button> + <ul + class="dropdown-menu dropdown-menu-selectable dropdown-menu-large" + role="menu" + tabindex="-1" + > + <li> + <button + class="dropdown-item is-active" + role="menuitem" + type="button" + > + <strong> + Remove integration and resources + </strong> + + <div> + Deletes all GitLab resources attached to this cluster during removal + </div> + </button> + </li> + + <li> + <hr + aria-orientation="horizontal" + class="dropdown-divider" + role="separator" + /> + </li> + <li> + <button + class="dropdown-item" + role="menuitem" + type="button" + > + <strong> + Remove integration + </strong> + + <div> + Removes cluster from project but keeps associated resources + </div> + </button> + </li> + + <!----> + + </ul> + </div> + + <!----> +</div> +`; diff --git a/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js b/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js new file mode 100644 index 00000000000..b5aead238ad --- /dev/null +++ b/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js @@ -0,0 +1,57 @@ +import { mount } from '@vue/test-utils'; +import { GlModal } from '@gitlab/ui'; +import SplitButton from '~/vue_shared/components/split_button.vue'; +import RemoveClusterConfirmation from '~/clusters/components/remove_cluster_confirmation.vue'; + +describe('Remove cluster confirmation modal', () => { + let wrapper; + + const createComponent = (props = {}) => { + wrapper = mount(RemoveClusterConfirmation, { + propsData: { + clusterPath: 'clusterPath', + clusterName: 'clusterName', + ...props, + }, + sync: false, + }); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('renders splitbutton with modal included', () => { + createComponent(); + expect(wrapper.element).toMatchSnapshot(); + }); + + describe('split button dropdown', () => { + const findModal = () => wrapper.find(GlModal).vm; + const findSplitButton = () => wrapper.find(SplitButton).vm; + + beforeEach(() => { + createComponent({ clusterName: 'my-test-cluster' }); + jest.spyOn(findModal(), 'show').mockReturnValue(); + }); + + it('opens modal with "cleanup" option', () => { + findSplitButton().$emit('remove-cluster-and-cleanup'); + + return wrapper.vm.$nextTick().then(() => { + expect(findModal().show).toHaveBeenCalled(); + expect(wrapper.vm.confirmCleanup).toEqual(true); + }); + }); + + it('opens modal without "cleanup" option', () => { + findSplitButton().$emit('remove-cluster'); + + return wrapper.vm.$nextTick().then(() => { + expect(findModal().show).toHaveBeenCalled(); + expect(wrapper.vm.confirmCleanup).toEqual(false); + }); + }); + }); +}); diff --git a/spec/frontend/commit/commit_pipeline_status_component_spec.js b/spec/frontend/commit/commit_pipeline_status_component_spec.js index 36fc6ee52a8..a2a6d405eab 100644 --- a/spec/frontend/commit/commit_pipeline_status_component_spec.js +++ b/spec/frontend/commit/commit_pipeline_status_component_spec.js @@ -44,7 +44,6 @@ describe('Commit pipeline status component', () => { afterEach(() => { wrapper.destroy(); wrapper = null; - jest.clearAllMocks(); }); describe('Visibility management', () => { diff --git a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js index fda1f71b1f9..1139f094705 100644 --- a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js +++ b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js @@ -272,14 +272,11 @@ describe('EKS Cluster Store Actions', () => { payload = { name: ['Create cluster failed'] }; }); - it('commits createClusterError mutation', () => { + it('commits createClusterError mutation and displays flash message', () => testAction(actions.createClusterError, payload, state, [ { type: CREATE_CLUSTER_ERROR, payload }, - ]); - }); - - it('creates a flash that displays the create cluster error', () => { - expect(createFlash).toHaveBeenCalledWith(payload.name[0]); - }); + ]).then(() => { + expect(createFlash).toHaveBeenCalledWith(payload.name[0]); + })); }); }); diff --git a/spec/frontend/ide/components/preview/clientside_spec.js b/spec/frontend/ide/components/preview/clientside_spec.js index 6a33f4998c5..5cb9e598fc4 100644 --- a/spec/frontend/ide/components/preview/clientside_spec.js +++ b/spec/frontend/ide/components/preview/clientside_spec.js @@ -68,10 +68,6 @@ describe('IDE clientside preview', () => { jest.useRealTimers(); }); - beforeEach(() => { - jest.clearAllMocks(); - }); - afterEach(() => { wrapper.destroy(); }); diff --git a/spec/frontend/ide/stores/modules/pipelines/actions_spec.js b/spec/frontend/ide/stores/modules/pipelines/actions_spec.js index a58c7b8f819..b08d1cd01da 100644 --- a/spec/frontend/ide/stores/modules/pipelines/actions_spec.js +++ b/spec/frontend/ide/stores/modules/pipelines/actions_spec.js @@ -111,8 +111,6 @@ describe('IDE pipelines actions', () => { }); describe('fetchLatestPipeline', () => { - beforeEach(() => {}); - afterEach(() => { stopPipelinePolling(); clearEtagPoll(); diff --git a/spec/frontend/issuables_list/components/issuables_list_app_spec.js b/spec/frontend/issuables_list/components/issuables_list_app_spec.js index 666ccc07416..621e8b8aa54 100644 --- a/spec/frontend/issuables_list/components/issuables_list_app_spec.js +++ b/spec/frontend/issuables_list/components/issuables_list_app_spec.js @@ -72,7 +72,6 @@ describe('Issuables list component', () => { afterEach(() => { wrapper.destroy(); mockAxios.restore(); - jest.clearAllMocks(); window.location = oldLocation; }); diff --git a/spec/frontend/jest_self_check/mocks_spec.js b/spec/frontend/jest_self_check/mocks_spec.js new file mode 100644 index 00000000000..f1e9e12e633 --- /dev/null +++ b/spec/frontend/jest_self_check/mocks_spec.js @@ -0,0 +1,43 @@ +import * as textUtils from '~/lib/utils/text_utility'; + +jest.mock('~/lib/utils/text_utility'); + +describe('does restore mocks config work?', () => { + describe('shared spy', () => { + const spy = jest.fn(); + + beforeEach(() => { + spy(); + }); + + it('is only called once', () => { + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('is only called once B', () => { + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('is only called once C', () => { + expect(spy).toHaveBeenCalledTimes(1); + }); + }); + + describe('module mock', () => { + beforeEach(() => { + textUtils.humanize(''); + }); + + it('is only called once', () => { + expect(textUtils.humanize).toHaveBeenCalledTimes(1); + }); + + it('is only called once B', () => { + expect(textUtils.humanize).toHaveBeenCalledTimes(1); + }); + + it('is only called once C', () => { + expect(textUtils.humanize).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js index 10d92e9535c..7652f48474d 100644 --- a/spec/frontend/notes/components/comment_form_spec.js +++ b/spec/frontend/notes/components/comment_form_spec.js @@ -50,7 +50,6 @@ describe('issue_comment_form component', () => { afterEach(() => { axiosMock.restore(); wrapper.destroy(); - jest.clearAllMocks(); }); describe('user is logged in', () => { diff --git a/spec/frontend/pages/admin/users/components/user_modal_manager_spec.js b/spec/frontend/pages/admin/users/components/user_modal_manager_spec.js index 7653fffc502..c88a182660d 100644 --- a/spec/frontend/pages/admin/users/components/user_modal_manager_spec.js +++ b/spec/frontend/pages/admin/users/components/user_modal_manager_spec.js @@ -83,10 +83,6 @@ describe('Users admin page Modal Manager', () => { jest.spyOn(document, 'removeEventListener'); }); - afterEach(() => { - jest.clearAllMocks(); - }); - afterAll(() => { jest.restoreAllMocks(); }); diff --git a/spec/frontend/project_find_file_spec.js b/spec/frontend/project_find_file_spec.js index b697ca01046..b4c6d202e14 100644 --- a/spec/frontend/project_find_file_spec.js +++ b/spec/frontend/project_find_file_spec.js @@ -42,21 +42,23 @@ describe('ProjectFindFile', () => { })); const files = [ - 'fileA.txt', - 'fileB.txt', - 'fi#leC.txt', - 'folderA/fileD.txt', - 'folder#B/fileE.txt', - 'folde?rC/fil#F.txt', + { path: 'fileA.txt', escaped: 'fileA.txt' }, + { path: 'fileB.txt', escaped: 'fileB.txt' }, + { path: 'fi#leC.txt', escaped: 'fi%23leC.txt' }, + { path: 'folderA/fileD.txt', escaped: 'folderA/fileD.txt' }, + { path: 'folder#B/fileE.txt', escaped: 'folder%23B/fileE.txt' }, + { path: 'folde?rC/fil#F.txt', escaped: 'folde%3FrC/fil%23F.txt' }, ]; - beforeEach(() => { + beforeEach(done => { // Create a mock adapter for stubbing axios API requests mock = new MockAdapter(axios); element = $(TEMPLATE); - mock.onGet(FILE_FIND_URL).replyOnce(200, files); + mock.onGet(FILE_FIND_URL).replyOnce(200, files.map(x => x.path)); getProjectFindFileInstance(); // This triggers a load / axios call + subsequent render in the constructor + + setImmediate(done); }); afterEach(() => { @@ -65,26 +67,19 @@ describe('ProjectFindFile', () => { sanitize.mockClear(); }); - it('loads and renders elements from remote server', done => { - setImmediate(() => { - expect(findFiles()).toEqual( - files.map(text => ({ - text, - href: `${BLOB_URL_TEMPLATE}/${encodeURIComponent(text)}`, - })), - ); - - done(); - }); + it('loads and renders elements from remote server', () => { + expect(findFiles()).toEqual( + files.map(({ path, escaped }) => ({ + text: path, + href: `${BLOB_URL_TEMPLATE}/${escaped}`, + })), + ); }); - it('sanitizes search text', done => { + it('sanitizes search text', () => { const searchText = element.find('.file-finder-input').val(); - setImmediate(() => { - expect(sanitize).toHaveBeenCalledTimes(1); - expect(sanitize).toHaveBeenCalledWith(searchText); - done(); - }); + expect(sanitize).toHaveBeenCalledTimes(1); + expect(sanitize).toHaveBeenCalledWith(searchText); }); }); diff --git a/spec/frontend/registry/list/components/app_spec.js b/spec/frontend/registry/list/components/app_spec.js index f2733ac9fef..5072a285f83 100644 --- a/spec/frontend/registry/list/components/app_spec.js +++ b/spec/frontend/registry/list/components/app_spec.js @@ -52,7 +52,6 @@ describe('Registry List', () => { }); afterEach(() => { - jest.clearAllMocks(); Vue.config.silent = false; wrapper.destroy(); }); diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js index aa0b9385f1a..94fa8b1e363 100644 --- a/spec/frontend/repository/components/table/row_spec.js +++ b/spec/frontend/repository/components/table/row_spec.js @@ -35,7 +35,6 @@ function factory(propsData = {}) { describe('Repository table row component', () => { afterEach(() => { vm.destroy(); - jest.clearAllMocks(); }); it('renders table row', () => { diff --git a/spec/frontend/sentry/sentry_config_spec.js b/spec/frontend/sentry/sentry_config_spec.js index 62b8bbd50a2..bcc7f29b98d 100644 --- a/spec/frontend/sentry/sentry_config_spec.js +++ b/spec/frontend/sentry/sentry_config_spec.js @@ -54,8 +54,7 @@ describe('SentryConfig', () => { }); it('should not call setUser if there is no current user ID', () => { - jest.clearAllMocks(); - + SentryConfig.setUser.mockClear(); options.currentUserId = undefined; SentryConfig.init(options); @@ -167,8 +166,6 @@ describe('SentryConfig', () => { describe('if no err is provided', () => { beforeEach(() => { - jest.clearAllMocks(); - SentryConfig.handleSentryErrors(event, req, config); }); @@ -191,8 +188,6 @@ describe('SentryConfig', () => { beforeEach(() => { req.responseText = undefined; - jest.clearAllMocks(); - SentryConfig.handleSentryErrors(event, req, config, err); }); diff --git a/spec/frontend/sidebar/confidential_issue_sidebar_spec.js b/spec/frontend/sidebar/confidential_issue_sidebar_spec.js index 68dde14880a..432ec111e52 100644 --- a/spec/frontend/sidebar/confidential_issue_sidebar_spec.js +++ b/spec/frontend/sidebar/confidential_issue_sidebar_spec.js @@ -42,7 +42,6 @@ describe('Confidential Issue Sidebar Block', () => { }; beforeEach(() => { - jest.clearAllMocks(); jest.spyOn(window.location, 'reload').mockImplementation(); }); diff --git a/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap index 95296de5a5d..530428ef27c 100644 --- a/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap +++ b/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap @@ -5,6 +5,7 @@ exports[`SplitButton renders actionItems 1`] = ` menu-class="dropdown-menu-selectable " split="true" text="professor" + variant="secondary" > <gldropdownitem-stub active="true" diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index 559dc95768a..2dd9583087f 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -50,6 +50,32 @@ describe Key, :mailer do end end + describe 'scopes' do + describe '.for_user' do + let(:user_1) { create(:user) } + let(:key_of_user_1) { create(:personal_key, user: user_1) } + + before do + create_list(:personal_key, 2, user: create(:user)) + end + + it 'returns keys of the specified user only' do + expect(described_class.for_user(user_1)).to contain_exactly(key_of_user_1) + end + end + + describe '.order_last_used_at_desc' do + it 'sorts by last_used_at descending, with null values at last' do + key_1 = create(:personal_key, last_used_at: 7.days.ago) + key_2 = create(:personal_key, last_used_at: nil) + key_3 = create(:personal_key, last_used_at: 2.days.ago) + + expect(described_class.order_last_used_at_desc) + .to eq([key_3, key_1, key_2]) + end + end + end + context "validation of uniqueness (based on fingerprint uniqueness)" do let(:user) { create(:user) } diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb index aaf9ecb8089..b16d1f58be5 100644 --- a/spec/models/personal_access_token_spec.rb +++ b/spec/models/personal_access_token_spec.rb @@ -21,6 +21,18 @@ describe PersonalAccessToken do end end + describe 'scopes' do + describe '.for_user' do + it 'returns personal access tokens of specified user only' do + user_1 = create(:user) + token_of_user_1 = create(:personal_access_token, user: user_1) + create_list(:personal_access_token, 2) + + expect(described_class.for_user(user_1)).to contain_exactly(token_of_user_1) + end + end + end + describe ".active?" do let(:active_personal_access_token) { build(:personal_access_token) } let(:revoked_personal_access_token) { build(:personal_access_token, :revoked) } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index e5c30e4ca46..99d7e4d156f 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1786,11 +1786,11 @@ describe Project do end end - describe '.including_namespace_and_owner' do + describe '.eager_load_namespace_and_owner' do it 'eager loads the namespace and namespace owner' do create(:project) - row = described_class.eager_load_namespace_and_owner.to_a.first + row = described_class.eager_load_namespace_and_owner.first recorder = ActiveRecord::QueryRecorder.new { row.namespace.owner } expect(recorder.count).to be_zero diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index db26b872045..749d80ebfc2 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -2894,11 +2894,11 @@ describe User, :do_not_mock_admin_mode do end end - describe '#full_private_access?' do + describe '#can_read_all_resources?' do it 'returns false for regular user' do user = build(:user) - expect(user.full_private_access?).to be_falsy + expect(user.can_read_all_resources?).to be_falsy end context 'for admin user' do @@ -2908,7 +2908,7 @@ describe User, :do_not_mock_admin_mode do context 'when admin mode is disabled' do it 'returns false' do - expect(user.full_private_access?).to be_falsy + expect(user.can_read_all_resources?).to be_falsy end end @@ -2919,7 +2919,7 @@ describe User, :do_not_mock_admin_mode do end it 'returns true' do - expect(user.full_private_access?).to be_truthy + expect(user.can_read_all_resources?).to be_truthy end end end diff --git a/spec/requests/projects/merge_requests/creations_spec.rb b/spec/requests/projects/merge_requests/creations_spec.rb new file mode 100644 index 00000000000..d192e1bca7f --- /dev/null +++ b/spec/requests/projects/merge_requests/creations_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'merge requests creations' do + describe 'GET /:namespace/:project/merge_requests/new' do + include ProjectForksHelper + + let(:project) { create(:project, :repository) } + let(:user) { project.owner } + + before do + login_as(user) + end + + def get_new + get namespace_project_new_merge_request_path(namespace_id: project.namespace, project_id: project) + end + + it 'avoids N+1 DB queries even with forked projects' do + control = ActiveRecord::QueryRecorder.new(skip_cached: false) { get_new } + + 5.times { fork_project(project, user) } + + expect { get_new }.not_to exceed_query_limit(control) + end + end +end |