diff options
Diffstat (limited to 'spec')
20 files changed, 235 insertions, 173 deletions
diff --git a/spec/factories/users_statistics.rb b/spec/factories/users_statistics.rb index 5b0871f2262..07699dc38b2 100644 --- a/spec/factories/users_statistics.rb +++ b/spec/factories/users_statistics.rb @@ -2,5 +2,13 @@ FactoryBot.define do factory :users_statistics do + without_groups_and_projects { 23 } + with_highest_role_guest { 5 } + with_highest_role_reporter { 9 } + with_highest_role_developer { 21 } + with_highest_role_maintainer { 6 } + with_highest_role_owner { 5 } + bots { 2 } + blocked { 7 } end end diff --git a/spec/features/admin/dashboard_spec.rb b/spec/features/admin/dashboard_spec.rb index 6cb345c5066..018ef13cbb6 100644 --- a/spec/features/admin/dashboard_spec.rb +++ b/spec/features/admin/dashboard_spec.rb @@ -2,14 +2,14 @@ require 'spec_helper' -describe 'admin visits dashboard', :js do +describe 'admin visits dashboard' do include ProjectForksHelper before do sign_in(create(:admin)) end - context 'counting forks' do + context 'counting forks', :js do it 'correctly counts 2 forks of a project' do project = create(:project) project_fork = fork_project(project) @@ -25,4 +25,26 @@ describe 'admin visits dashboard', :js do expect(page).to have_content('Forks 2') end end + + describe 'Users statistic' do + let_it_be(:users_statistics) { create(:users_statistics) } + + it 'shows correct amounts of users', :aggregate_failures do + expected_active_users_text = Gitlab.ee? ? 'Active users (Billable users) 71' : 'Active users 71' + + sign_in(create(:admin)) + visit admin_dashboard_stats_path + + expect(page).to have_content('Users without a Group and Project 23') + expect(page).to have_content('Users with highest role Guest 5') + expect(page).to have_content('Users with highest role Reporter 9') + expect(page).to have_content('Users with highest role Developer 21') + expect(page).to have_content('Users with highest role Maintainer 6') + expect(page).to have_content('Users with highest role Owner 5') + expect(page).to have_content('Bots 2') + expect(page).to have_content(expected_active_users_text) + expect(page).to have_content('Blocked users 7') + expect(page).to have_content('Total users 78') + end + end end diff --git a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb index f8179979018..2eaa2d24c4b 100644 --- a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb +++ b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb @@ -174,7 +174,7 @@ describe 'Set up Mattermost slash commands', :js do describe 'stable logo url' do it 'shows a publicly available logo' do - expect(File.exist?(Rails.root.join('public/slash-command-logo.png'))) + expect(File.exist?(Rails.root.join('public/slash-command-logo.png'))).to be_truthy end end end diff --git a/spec/frontend/logs/components/environment_logs_spec.js b/spec/frontend/logs/components/environment_logs_spec.js index 4da987725a1..befcd462828 100644 --- a/spec/frontend/logs/components/environment_logs_spec.js +++ b/spec/frontend/logs/components/environment_logs_spec.js @@ -47,7 +47,7 @@ describe('EnvironmentLogs', () => { const findLogControlButtons = () => wrapper.find({ name: 'log-control-buttons-stub' }); const findInfiniteScroll = () => wrapper.find({ ref: 'infiniteScroll' }); - const findLogTrace = () => wrapper.find('.js-log-trace'); + const findLogTrace = () => wrapper.find({ ref: 'logTrace' }); const findLogFooter = () => wrapper.find({ ref: 'logFooter' }); const getInfiniteScrollAttr = attr => parseInt(findInfiniteScroll().attributes(attr), 10); @@ -169,16 +169,12 @@ describe('EnvironmentLogs', () => { expect(updateControlBtnsMock).not.toHaveBeenCalled(); }); - it('shows an infinite scroll with height and no content', () => { - expect(getInfiniteScrollAttr('max-list-height')).toBeGreaterThan(0); + it('shows an infinite scroll with no content', () => { expect(getInfiniteScrollAttr('fetched-items')).toBe(0); }); - it('shows an infinite scroll container with equal height and max-height ', () => { - const height = getInfiniteScrollAttr('max-list-height'); - - expect(height).toEqual(expect.any(Number)); - expect(findInfiniteScroll().attributes('style')).toMatch(`height: ${height}px;`); + it('shows an infinite scroll container with no set max-height ', () => { + expect(findInfiniteScroll().attributes('max-list-height')).toBeUndefined(); }); it('shows a logs trace', () => { @@ -270,8 +266,7 @@ describe('EnvironmentLogs', () => { expect(findAdvancedFilters().exists()).toBe(true); }); - it('shows infinite scroll with height and no content', () => { - expect(getInfiniteScrollAttr('max-list-height')).toBeGreaterThan(0); + it('shows infinite scroll with content', () => { expect(getInfiniteScrollAttr('fetched-items')).toBe(mockTrace.length); }); diff --git a/spec/frontend/logs/stores/actions_spec.js b/spec/frontend/logs/stores/actions_spec.js index 303737a11cd..882673af984 100644 --- a/spec/frontend/logs/stores/actions_spec.js +++ b/spec/frontend/logs/stores/actions_spec.js @@ -38,7 +38,7 @@ jest.mock('~/logs/utils'); const mockDefaultRange = { start: '2020-01-10T18:00:00.000Z', - end: '2020-01-10T10:00:00.000Z', + end: '2020-01-10T19:00:00.000Z', }; const mockFixedRange = { start: '2020-01-09T18:06:20.000Z', @@ -145,9 +145,6 @@ describe('Logs Store actions', () => { { type: types.RECEIVE_ENVIRONMENTS_DATA_ERROR }, ], [], - () => { - expect(flash).toHaveBeenCalledTimes(1); - }, ); }); }); @@ -186,6 +183,7 @@ describe('Logs Store actions', () => { it('should commit logs and pod data when there is pod name defined', () => { state.pods.current = mockPodName; + state.timeRange.current = mockFixedRange; return testAction(fetchLogs, null, state, expectedMutations, expectedActions, () => { expect(latestGetParams()).toMatchObject({ @@ -214,22 +212,26 @@ describe('Logs Store actions', () => { state.search = mockSearch; state.timeRange.current = 'INVALID_TIME_RANGE'; + expectedMutations.splice(1, 0, { + type: types.SHOW_TIME_RANGE_INVALID_WARNING, + }); + return testAction(fetchLogs, null, state, expectedMutations, expectedActions, () => { expect(latestGetParams()).toEqual({ pod_name: mockPodName, search: mockSearch, }); - // Warning about time ranges was issued - expect(flash).toHaveBeenCalledTimes(1); - expect(flash).toHaveBeenCalledWith(expect.any(String), 'warning'); }); }); it('should commit logs and pod data when no pod name defined', () => { - state.timeRange.current = mockDefaultRange; + state.timeRange.current = defaultTimeRange; return testAction(fetchLogs, null, state, expectedMutations, expectedActions, () => { - expect(latestGetParams()).toEqual({}); + expect(latestGetParams()).toEqual({ + start_time: expect.any(String), + end_time: expect.any(String), + }); }); }); }); @@ -249,6 +251,7 @@ describe('Logs Store actions', () => { it('should commit logs and pod data when there is pod name defined', () => { state.pods.current = mockPodName; + state.timeRange.current = mockFixedRange; expectedActions = []; @@ -293,6 +296,10 @@ describe('Logs Store actions', () => { state.search = mockSearch; state.timeRange.current = 'INVALID_TIME_RANGE'; + expectedMutations.splice(1, 0, { + type: types.SHOW_TIME_RANGE_INVALID_WARNING, + }); + return testAction( fetchMoreLogsPrepend, null, @@ -304,15 +311,12 @@ describe('Logs Store actions', () => { pod_name: mockPodName, search: mockSearch, }); - // Warning about time ranges was issued - expect(flash).toHaveBeenCalledTimes(1); - expect(flash).toHaveBeenCalledWith(expect.any(String), 'warning'); }, ); }); it('should commit logs and pod data when no pod name defined', () => { - state.timeRange.current = mockDefaultRange; + state.timeRange.current = defaultTimeRange; return testAction( fetchMoreLogsPrepend, @@ -321,7 +325,10 @@ describe('Logs Store actions', () => { expectedMutations, expectedActions, () => { - expect(latestGetParams()).toEqual({}); + expect(latestGetParams()).toEqual({ + start_time: expect.any(String), + end_time: expect.any(String), + }); }, ); }); @@ -357,6 +364,7 @@ describe('Logs Store actions', () => { it('fetchLogs should commit logs and pod errors', () => { state.environments.options = mockEnvironments; state.environments.current = mockEnvName; + state.timeRange.current = defaultTimeRange; return testAction( fetchLogs, @@ -377,6 +385,7 @@ describe('Logs Store actions', () => { it('fetchMoreLogsPrepend should commit logs and pod errors', () => { state.environments.options = mockEnvironments; state.environments.current = mockEnvName; + state.timeRange.current = defaultTimeRange; return testAction( fetchMoreLogsPrepend, diff --git a/spec/frontend/logs/stores/mutations_spec.js b/spec/frontend/logs/stores/mutations_spec.js index 37db355af09..46561055a4a 100644 --- a/spec/frontend/logs/stores/mutations_spec.js +++ b/spec/frontend/logs/stores/mutations_spec.js @@ -67,6 +67,7 @@ describe('Logs Store Mutations', () => { options: [], isLoading: false, current: null, + fetchError: true, }); }); }); @@ -83,6 +84,7 @@ describe('Logs Store Mutations', () => { expect(state.logs).toEqual({ lines: [], cursor: null, + fetchError: false, isLoading: true, isComplete: false, }); @@ -101,6 +103,7 @@ describe('Logs Store Mutations', () => { isLoading: false, cursor: mockCursor, isComplete: false, + fetchError: false, }); }); @@ -115,6 +118,7 @@ describe('Logs Store Mutations', () => { isLoading: false, cursor: null, isComplete: true, + fetchError: false, }); }); }); @@ -128,6 +132,7 @@ describe('Logs Store Mutations', () => { isLoading: false, cursor: null, isComplete: false, + fetchError: true, }); }); }); @@ -152,6 +157,7 @@ describe('Logs Store Mutations', () => { isLoading: false, cursor: mockCursor, isComplete: false, + fetchError: false, }); }); @@ -171,6 +177,7 @@ describe('Logs Store Mutations', () => { isLoading: false, cursor: mockNextCursor, isComplete: false, + fetchError: false, }); }); @@ -185,6 +192,7 @@ describe('Logs Store Mutations', () => { isLoading: false, cursor: null, isComplete: true, + fetchError: false, }); }); }); @@ -194,6 +202,7 @@ describe('Logs Store Mutations', () => { mutations[types.RECEIVE_LOGS_DATA_PREPEND_ERROR](state); expect(state.logs.isLoading).toBe(false); + expect(state.logs.fetchError).toBe(true); }); }); diff --git a/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap b/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap index 5b5c9fd714e..97597ed8063 100644 --- a/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap +++ b/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap @@ -7,17 +7,16 @@ exports[`Repository table row component renders table row 1`] = ` <td class="tree-item-file-name cursor-default position-relative" > - <!----> - <a class="tree-item-link str-truncated" data-qa-selector="file_name_link" href="https://test.com" > - <i - aria-label="file" - class="fa fa-fw mr-1 fa-file-text-o" - role="img" + <file-icon-stub + class="mr-1 position-relative text-secondary" + cssclasses="position-relative file-icon" + filename="test" + size="16" /> <span class="position-relative" @@ -60,17 +59,16 @@ exports[`Repository table row component renders table row for path with special <td class="tree-item-file-name cursor-default position-relative" > - <!----> - <a class="tree-item-link str-truncated" data-qa-selector="file_name_link" href="https://test.com" > - <i - aria-label="file" - class="fa fa-fw mr-1 fa-file-text-o" - role="img" + <file-icon-stub + class="mr-1 position-relative text-secondary" + cssclasses="position-relative file-icon" + filename="test" + size="16" /> <span class="position-relative" diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js index 7bb7ad6e5dd..cb2193e1d9a 100644 --- a/spec/frontend/repository/components/table/row_spec.js +++ b/spec/frontend/repository/components/table/row_spec.js @@ -1,7 +1,7 @@ import { shallowMount, RouterLinkStub } from '@vue/test-utils'; -import { GlBadge, GlLink, GlLoadingIcon } from '@gitlab/ui'; +import { GlBadge, GlLink, GlIcon } from '@gitlab/ui'; import TableRow from '~/repository/components/table/row.vue'; -import Icon from '~/vue_shared/components/icon.vue'; +import FileIcon from '~/vue_shared/components/file_icon.vue'; let vm; let $router; @@ -188,7 +188,8 @@ describe('Repository table row component', () => { vm.setData({ commit: { lockLabel: 'Locked by Root', committedDate: '2019-01-01' } }); return vm.vm.$nextTick().then(() => { - expect(vm.find(Icon).exists()).toBe(true); + expect(vm.find(GlIcon).exists()).toBe(true); + expect(vm.find(GlIcon).props('name')).toBe('lock'); }); }); @@ -202,6 +203,6 @@ describe('Repository table row component', () => { loadingPath: 'test', }); - expect(vm.find(GlLoadingIcon).exists()).toBe(true); + expect(vm.find(FileIcon).props('loading')).toBe(true); }); }); diff --git a/spec/frontend/vue_shared/components/file_icon_spec.js b/spec/frontend/vue_shared/components/file_icon_spec.js index 7b7633a06d6..5a385eee60c 100644 --- a/spec/frontend/vue_shared/components/file_icon_spec.js +++ b/spec/frontend/vue_shared/components/file_icon_spec.js @@ -1,7 +1,6 @@ import { shallowMount } from '@vue/test-utils'; -import { GlLoadingIcon } from '@gitlab/ui'; +import { GlLoadingIcon, GlIcon } from '@gitlab/ui'; import FileIcon from '~/vue_shared/components/file_icon.vue'; -import Icon from '~/vue_shared/components/icon.vue'; describe('File Icon component', () => { let wrapper; @@ -48,7 +47,7 @@ describe('File Icon component', () => { }); expect(findIcon().exists()).toBe(false); - expect(wrapper.find(Icon).classes()).toContain('folder-icon'); + expect(wrapper.find(GlIcon).classes()).toContain('folder-icon'); }); it('should render a loading icon', () => { diff --git a/spec/javascripts/ide/components/external_link_spec.js b/spec/javascripts/ide/components/external_link_spec.js deleted file mode 100644 index b3d94c041fa..00000000000 --- a/spec/javascripts/ide/components/external_link_spec.js +++ /dev/null @@ -1,35 +0,0 @@ -import Vue from 'vue'; -import externalLink from '~/ide/components/external_link.vue'; -import createVueComponent from '../../helpers/vue_mount_component_helper'; -import { file } from '../helpers'; - -describe('ExternalLink', () => { - const activeFile = file(); - let vm; - - function createComponent() { - const ExternalLink = Vue.extend(externalLink); - - activeFile.permalink = 'test'; - - return createVueComponent(ExternalLink, { - file: activeFile, - }); - } - - afterEach(() => { - vm.$destroy(); - }); - - it('renders the external link with the correct href', done => { - activeFile.binary = true; - vm = createComponent(); - - vm.$nextTick(() => { - const openLink = vm.$el.querySelector('a'); - - expect(openLink.href).toMatch(`/${activeFile.permalink}`); - done(); - }); - }); -}); diff --git a/spec/javascripts/pipelines/graph/graph_component_spec.js b/spec/javascripts/pipelines/graph/graph_component_spec.js index fa6a5f57410..d2c10362ba3 100644 --- a/spec/javascripts/pipelines/graph/graph_component_spec.js +++ b/spec/javascripts/pipelines/graph/graph_component_spec.js @@ -159,7 +159,6 @@ describe('graph component', () => { expect(component.$emit).toHaveBeenCalledWith( 'onClickTriggeredBy', - component.pipeline, component.pipeline.triggered_by[0], ); }); @@ -196,7 +195,6 @@ describe('graph component', () => { expect(component.$emit).toHaveBeenCalledWith( 'onClickTriggered', - component.pipeline, component.pipeline.triggered[0], ); }); diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 3ec6110d789..523e17f82c1 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -34,6 +34,10 @@ describe ApplicationSetting do it { is_expected.to allow_value("dev.gitlab.com").for(:commit_email_hostname) } it { is_expected.not_to allow_value("@dev.gitlab").for(:commit_email_hostname) } + it { is_expected.to allow_value(true).for(:container_expiration_policies_enable_historic_entries) } + it { is_expected.to allow_value(false).for(:container_expiration_policies_enable_historic_entries) } + it { is_expected.not_to allow_value(nil).for(:container_expiration_policies_enable_historic_entries) } + it { is_expected.to allow_value("myemail@gitlab.com").for(:lets_encrypt_notification_email) } it { is_expected.to allow_value(nil).for(:lets_encrypt_notification_email) } it { is_expected.not_to allow_value("notanemail").for(:lets_encrypt_notification_email) } diff --git a/spec/models/ci/group_spec.rb b/spec/models/ci/group_spec.rb index b3b158a111e..5516a1a9c61 100644 --- a/spec/models/ci/group_spec.rb +++ b/spec/models/ci/group_spec.rb @@ -53,7 +53,7 @@ describe Ci::Group do it 'calls the status from the object itself' do expect(jobs.first).to receive(:detailed_status) - expect(subject.detailed_status(double(:user))) + subject.detailed_status(double(:user)) end end diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index 55af292e8f3..b8034ba5bf2 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -526,14 +526,14 @@ describe Ci::Runner do it 'sets a new last_update value when it is called the first time' do last_update = runner.ensure_runner_queue_value - expect_value_in_queues.to eq(last_update) + expect(value_in_queues).to eq(last_update) end it 'does not change if it is not expired and called again' do last_update = runner.ensure_runner_queue_value expect(runner.ensure_runner_queue_value).to eq(last_update) - expect_value_in_queues.to eq(last_update) + expect(value_in_queues).to eq(last_update) end context 'updates runner queue after changing editable value' do @@ -544,7 +544,7 @@ describe Ci::Runner do end it 'sets a new last_update value' do - expect_value_in_queues.not_to eq(last_update) + expect(value_in_queues).not_to eq(last_update) end end @@ -556,14 +556,14 @@ describe Ci::Runner do end it 'has an old last_update value' do - expect_value_in_queues.to eq(last_update) + expect(value_in_queues).to eq(last_update) end end - def expect_value_in_queues + def value_in_queues Gitlab::Redis::SharedState.with do |redis| runner_queue_key = runner.send(:runner_queue_key) - expect(redis.get(runner_queue_key)) + redis.get(runner_queue_key) end end end diff --git a/spec/models/users_statistics_spec.rb b/spec/models/users_statistics_spec.rb index fc23bed711f..4437a5469c6 100644 --- a/spec/models/users_statistics_spec.rb +++ b/spec/models/users_statistics_spec.rb @@ -2,7 +2,36 @@ require 'spec_helper' -RSpec.describe UsersStatistics do +describe UsersStatistics do + let(:users_statistics) { build(:users_statistics) } + + describe 'scopes' do + describe '.order_created_at_desc' do + it 'returns the entries ordered by created at descending' do + users_statistics1 = create(:users_statistics, created_at: Time.current) + users_statistics2 = create(:users_statistics, created_at: Time.current - 2.days) + users_statistics3 = create(:users_statistics, created_at: Time.current - 5.hours) + + expect(described_class.order_created_at_desc).to eq( + [ + users_statistics1, + users_statistics3, + users_statistics2 + ] + ) + end + end + end + + describe '.latest' do + it 'returns the latest entry' do + create(:users_statistics, created_at: Time.current - 1.day) + users_statistics = create(:users_statistics, created_at: Time.current) + + expect(described_class.latest).to eq(users_statistics) + end + end + describe '.create_current_stats!' do before do create_list(:user_highest_role, 4) @@ -40,4 +69,16 @@ RSpec.describe UsersStatistics do end end end + + describe '#active' do + it 'sums users statistics values without the value for blocked' do + expect(users_statistics.active).to eq(71) + end + end + + describe '#total' do + it 'sums all users statistics values' do + expect(users_statistics.total).to eq(78) + end + end end diff --git a/spec/presenters/ci/pipeline_presenter_spec.rb b/spec/presenters/ci/pipeline_presenter_spec.rb index c9c4f567549..28eb6804703 100644 --- a/spec/presenters/ci/pipeline_presenter_spec.rb +++ b/spec/presenters/ci/pipeline_presenter_spec.rb @@ -7,7 +7,7 @@ describe Ci::PipelinePresenter do let(:user) { create(:user) } let(:current_user) { user } - let(:project) { create(:project) } + let(:project) { create(:project, :test_repo) } let(:pipeline) { create(:ci_pipeline, project: project) } subject(:presenter) do @@ -87,34 +87,32 @@ describe Ci::PipelinePresenter do end describe '#name' do + before do + allow(pipeline).to receive(:merge_request_event_type) { event_type } + end + subject { presenter.name } - context 'when pipeline is detached merge request pipeline' do - let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) } - let(:pipeline) { merge_request.all_pipelines.last } + context 'for a detached merge request pipeline' do + let(:event_type) { :detached } it { is_expected.to eq('Detached merge request pipeline') } end - context 'when pipeline is merge request pipeline' do - let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) } - let(:pipeline) { merge_request.all_pipelines.last } + context 'for a merged result pipeline' do + let(:event_type) { :merged_result } it { is_expected.to eq('Merged result pipeline') } end - context 'when pipeline is merge train pipeline' do - let(:pipeline) { create(:ci_pipeline, project: project) } - - before do - allow(pipeline).to receive(:merge_request_event_type) { :merge_train } - end + context 'for a merge train pipeline' do + let(:event_type) { :merge_train } it { is_expected.to eq('Merge train pipeline') } end context 'when pipeline is branch pipeline' do - let(:pipeline) { create(:ci_pipeline, project: project) } + let(:event_type) { nil } it { is_expected.to eq('Pipeline') } end @@ -145,8 +143,6 @@ describe Ci::PipelinePresenter do end context 'when pipeline is branch pipeline' do - let(:pipeline) { create(:ci_pipeline, project: project) } - context 'when ref exists in the repository' do before do allow(pipeline).to receive(:ref_exists?) { true } @@ -165,7 +161,7 @@ describe Ci::PipelinePresenter do end end - context 'when ref exists in the repository' do + context 'when ref does not exist in the repository' do before do allow(pipeline).to receive(:ref_exists?) { false } end @@ -188,12 +184,17 @@ describe Ci::PipelinePresenter do describe '#all_related_merge_request_text' do subject { presenter.all_related_merge_request_text } + let(:mr_1) { create(:merge_request) } + let(:mr_2) { create(:merge_request) } + context 'with zero related merge requests (branch pipeline)' do it { is_expected.to eq('No related merge requests found.') } end context 'with one related merge request' do - let!(:mr_1) { create(:merge_request, project: project, source_project: project) } + before do + allow(pipeline).to receive(:all_merge_requests).and_return(MergeRequest.where(id: mr_1.id)) + end it { is_expected.to eq("1 related merge request: " \ @@ -202,8 +203,9 @@ describe Ci::PipelinePresenter do end context 'with two related merge requests' do - let!(:mr_1) { create(:merge_request, project: project, source_project: project, target_branch: 'staging') } - let!(:mr_2) { create(:merge_request, project: project, source_project: project, target_branch: 'feature') } + before do + allow(pipeline).to receive(:all_merge_requests).and_return(MergeRequest.where(id: [mr_1.id, mr_2.id])) + end it { is_expected.to eq("2 related merge requests: " \ @@ -223,22 +225,25 @@ describe Ci::PipelinePresenter do end describe '#all_related_merge_requests' do + subject(:all_related_merge_requests) do + presenter.send(:all_related_merge_requests) + end + it 'memoizes the returned relation' do - query_count = ActiveRecord::QueryRecorder.new do - 3.times { presenter.send(:all_related_merge_requests).count } - end.count + expect(pipeline).to receive(:all_merge_requests_by_recency).exactly(1).time.and_call_original + 2.times { presenter.send(:all_related_merge_requests).count } + end + + context 'for a branch pipeline with two open MRs' do + let!(:one) { create(:merge_request, source_project: project, source_branch: pipeline.ref) } + let!(:two) { create(:merge_request, source_project: project, source_branch: pipeline.ref, target_branch: 'wip') } - expect(query_count).to eq(2) + it { is_expected.to contain_exactly(one, two) } end context 'permissions' do - let!(:merge_request) do - create(:merge_request, project: project, source_project: project) - end - - subject(:all_related_merge_requests) do - presenter.send(:all_related_merge_requests) - end + let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline, source_project: project) } + let(:pipeline) { merge_request.all_pipelines.take } shared_examples 'private merge requests' do context 'when not logged in' do @@ -315,61 +320,51 @@ describe Ci::PipelinePresenter do describe '#link_to_merge_request' do subject { presenter.link_to_merge_request } - let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) } - let(:pipeline) { merge_request.all_pipelines.last } + context 'with a related merge request' do + let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline, source_project: project) } + let(:pipeline) { merge_request.all_pipelines.take } - it 'returns a correct link' do - is_expected - .to include(project_merge_request_path(merge_request.project, merge_request)) + it 'returns a correct link' do + is_expected.to include(project_merge_request_path(project, merge_request)) + end end context 'when pipeline is branch pipeline' do - let(:pipeline) { create(:ci_pipeline, project: project) } - - it 'returns nothing' do - is_expected.to be_nil - end + it { is_expected.to be_nil } end end describe '#link_to_merge_request_source_branch' do subject { presenter.link_to_merge_request_source_branch } - let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) } - let(:pipeline) { merge_request.all_pipelines.last } + context 'with a related merge request' do + let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline, source_project: project) } + let(:pipeline) { merge_request.all_pipelines.take } - it 'returns a correct link' do - is_expected - .to include(project_commits_path(merge_request.source_project, - merge_request.source_branch)) + it 'returns a correct link' do + is_expected.to include(project_commits_path(project, merge_request.source_branch)) + end end context 'when pipeline is branch pipeline' do - let(:pipeline) { create(:ci_pipeline, project: project) } - - it 'returns nothing' do - is_expected.to be_nil - end + it { is_expected.to be_nil } end end describe '#link_to_merge_request_target_branch' do subject { presenter.link_to_merge_request_target_branch } - let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) } - let(:pipeline) { merge_request.all_pipelines.last } + context 'with a related merge request' do + let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline, source_project: project) } + let(:pipeline) { merge_request.all_pipelines.take } - it 'returns a correct link' do - is_expected - .to include(project_commits_path(merge_request.target_project, merge_request.target_branch)) + it 'returns a correct link' do + is_expected.to include(project_commits_path(project, merge_request.target_branch)) + end end context 'when pipeline is branch pipeline' do - let(:pipeline) { create(:ci_pipeline, project: project) } - - it 'returns nothing' do - is_expected.to be_nil - end + it { is_expected.to be_nil } end end end diff --git a/spec/requests/api/internal/pages_spec.rb b/spec/requests/api/internal/pages_spec.rb index 0c3c2fa22d6..fecf15c29c2 100644 --- a/spec/requests/api/internal/pages_spec.rb +++ b/spec/requests/api/internal/pages_spec.rb @@ -3,13 +3,36 @@ require 'spec_helper' describe API::Internal::Pages do - describe "GET /internal/pages" do - let(:pages_secret) { SecureRandom.random_bytes(Gitlab::Pages::SECRET_LENGTH) } + let(:auth_headers) do + jwt_token = JWT.encode({ 'iss' => 'gitlab-pages' }, Gitlab::Pages.secret, 'HS256') + { Gitlab::Pages::INTERNAL_API_REQUEST_HEADER => jwt_token } + end + let(:pages_secret) { SecureRandom.random_bytes(Gitlab::Pages::SECRET_LENGTH) } + + before do + allow(Gitlab::Pages).to receive(:secret).and_return(pages_secret) + end + + describe "GET /internal/pages/status" do + def query_enabled(headers = {}) + get api("/internal/pages/status"), headers: headers + end - before do - allow(Gitlab::Pages).to receive(:secret).and_return(pages_secret) + it 'responds with 401 Unauthorized' do + query_enabled + + expect(response).to have_gitlab_http_status(:unauthorized) + end + + it 'responds with 204 no content' do + query_enabled(auth_headers) + + expect(response).to have_gitlab_http_status(:no_content) + expect(response.body).to be_empty end + end + describe "GET /internal/pages" do def query_host(host, headers = {}) get api("/internal/pages"), headers: headers, params: { host: host } end diff --git a/spec/services/ci/expire_pipeline_cache_service_spec.rb b/spec/services/ci/expire_pipeline_cache_service_spec.rb index 7b9d6ed4f41..78e1ba0109a 100644 --- a/spec/services/ci/expire_pipeline_cache_service_spec.rb +++ b/spec/services/ci/expire_pipeline_cache_service_spec.rb @@ -22,19 +22,19 @@ describe Ci::ExpirePipelineCacheService do end it 'invalidates Etag caching for merge request pipelines if pipeline runs on any commit of that source branch' do - pipeline = create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master') - merge_request = create(:merge_request, source_project: project, source_branch: pipeline.ref) + merge_request = create(:merge_request, :with_detached_merge_request_pipeline) + project = merge_request.target_project + merge_request_pipelines_path = "/#{project.full_path}/-/merge_requests/#{merge_request.iid}/pipelines.json" allow_any_instance_of(Gitlab::EtagCaching::Store).to receive(:touch) expect_any_instance_of(Gitlab::EtagCaching::Store).to receive(:touch).with(merge_request_pipelines_path) - subject.execute(pipeline) + subject.execute(merge_request.all_pipelines.last) end it 'updates the cached status for a project' do - expect(Gitlab::Cache::Ci::ProjectPipelineStatus).to receive(:update_for_pipeline) - .with(pipeline) + expect(Gitlab::Cache::Ci::ProjectPipelineStatus).to receive(:update_for_pipeline).with(pipeline) subject.execute(pipeline) end diff --git a/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb b/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb index 4d87fa3e832..0cec1e7be22 100644 --- a/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb +++ b/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb @@ -8,10 +8,6 @@ describe MergeRequests::AddTodoWhenBuildFailsService do let(:sha) { '1234567890abcdef1234567890abcdef12345678' } let(:ref) { merge_request.source_branch } - let(:pipeline) do - create(:ci_pipeline, ref: ref, project: project, sha: sha) - end - let(:service) do described_class.new(project, user, commit_message: 'Awesome message') end @@ -19,12 +15,11 @@ describe MergeRequests::AddTodoWhenBuildFailsService do let(:todo_service) { spy('todo service') } let(:merge_request) do - create(:merge_request, merge_user: user, - source_branch: 'master', - target_branch: 'feature', - source_project: project, - target_project: project, - state: 'opened') + create(:merge_request, :with_detached_merge_request_pipeline, :opened, merge_user: user) + end + + let(:pipeline) do + merge_request.all_pipelines.take end before do diff --git a/spec/services/users/destroy_service_spec.rb b/spec/services/users/destroy_service_spec.rb index a664719783a..216d9170274 100644 --- a/spec/services/users/destroy_service_spec.rb +++ b/spec/services/users/destroy_service_spec.rb @@ -15,7 +15,7 @@ describe Users::DestroyService do it 'deletes the user' do user_data = service.execute(user) - expect { user_data['email'].to eq(user.email) } + expect(user_data['email']).to eq(user.email) expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) expect { Namespace.find(namespace.id) }.to raise_error(ActiveRecord::RecordNotFound) end |