diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-09-27 21:06:20 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-09-27 21:06:20 +0300 |
commit | 2abb1b54c0305b359b178d6660810e865f619c22 (patch) | |
tree | e388953a0566ef9844b0b98cdb34236049721a14 /spec | |
parent | 8320f7956d72986f5a7c850874fce4f8b5a8e015 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/boards/lists_controller_spec.rb | 25 | ||||
-rw-r--r-- | spec/features/issues/issues_tabs_spec.rb | 56 | ||||
-rw-r--r-- | spec/frontend/lib/utils/suppress_ajax_errors_during_navigation_spec.js | 37 | ||||
-rw-r--r-- | spec/javascripts/frequent_items/components/app_spec.js | 7 | ||||
-rw-r--r-- | spec/javascripts/lib/utils/common_utils_spec.js | 10 | ||||
-rw-r--r-- | spec/models/ci/build_spec.rb | 6 | ||||
-rw-r--r-- | spec/models/ci/persistent_ref_spec.rb | 108 | ||||
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 10 | ||||
-rw-r--r-- | spec/models/list_spec.rb | 12 | ||||
-rw-r--r-- | spec/presenters/ci/build_runner_presenter_spec.rb | 17 | ||||
-rw-r--r-- | spec/requests/boards/lists_controller_spec.rb | 25 | ||||
-rw-r--r-- | spec/services/ci/process_pipeline_service_spec.rb | 16 | ||||
-rw-r--r-- | spec/services/ci/register_job_service_spec.rb | 16 |
13 files changed, 320 insertions, 25 deletions
diff --git a/spec/controllers/boards/lists_controller_spec.rb b/spec/controllers/boards/lists_controller_spec.rb index 77b5872fcb3..bc46d02556b 100644 --- a/spec/controllers/boards/lists_controller_spec.rb +++ b/spec/controllers/boards/lists_controller_spec.rb @@ -14,6 +14,10 @@ describe Boards::ListsController do end describe 'GET index' do + before do + create(:list, board: board) + end + it 'returns a successful 200 response' do read_board_list user: user, board: board @@ -22,27 +26,22 @@ describe Boards::ListsController do end it 'returns a list of board lists' do - create(:list, board: board) - read_board_list user: user, board: board expect(response).to match_response_schema('lists') expect(json_response.length).to eq 3 end - it 'avoids n+1 queries when serializing lists' do - list_1 = create(:list, board: board) - list_1.update_preferences_for(user, { collapsed: true }) - - control_count = ActiveRecord::QueryRecorder.new { read_board_list user: user, board: board }.count - - list_2 = create(:list, board: board) - list_2.update_preferences_for(user, { collapsed: true }) + context 'when another user has list preferences' do + before do + board.lists.first.update_preferences_for(guest, collapsed: true) + end - list_3 = create(:list, board: board) - list_3.update_preferences_for(user, { collapsed: true }) + it 'returns the complete list of board lists' do + read_board_list user: user, board: board - expect { read_board_list user: user, board: board }.not_to exceed_query_limit(control_count) + expect(json_response.length).to eq 3 + end end context 'with unauthorized user' do diff --git a/spec/features/issues/issues_tabs_spec.rb b/spec/features/issues/issues_tabs_spec.rb new file mode 100644 index 00000000000..66d55dd9021 --- /dev/null +++ b/spec/features/issues/issues_tabs_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Issue page tabs', :js do + let(:user) { create(:user) } + let(:project) { create(:project, :public) } + let(:issue) { create(:issue, author: user, assignees: [user], project: project) } + + describe 'discussions tab counter' do + before do + stub_licensed_features(design_management: true) + stub_feature_flags(design_management_flag: true) + allow(Ability).to receive(:allowed?) { true } + end + + subject do + sign_in(user) + + visit project_issue_path(project, issue) + + wait_for_requests + + find('#discussion') + end + + context 'new issue' do + it 'displays count of 0' do + is_expected.to have_content('Discussion 0') + end + end + + context 'issue with 2 system notes and 1 discussion' do + let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: project, note: "This is good") } + + before do + create(:system_note, noteable: issue, project: project, author: user, note: 'description updated') + create(:system_note, noteable: issue, project: project, author: user, note: 'description updated') + end + + it 'displays count of 1' do + is_expected.to have_content('Discussion 1') + end + + context 'with 1 reply' do + before do + create(:note, noteable: issue, in_reply_to: discussion, discussion_id: discussion.discussion_id, note: 'I also think this is good') + end + + it 'displays count of 2' do + is_expected.to have_content('Discussion 2') + end + end + end + end +end diff --git a/spec/frontend/lib/utils/suppress_ajax_errors_during_navigation_spec.js b/spec/frontend/lib/utils/suppress_ajax_errors_during_navigation_spec.js new file mode 100644 index 00000000000..89e8459d594 --- /dev/null +++ b/spec/frontend/lib/utils/suppress_ajax_errors_during_navigation_spec.js @@ -0,0 +1,37 @@ +import suppressAjaxErrorsDuringNavigation from '~/lib/utils/suppress_ajax_errors_during_navigation'; +import waitForPromises from 'helpers/wait_for_promises'; + +describe('suppressAjaxErrorsDuringNavigation', () => { + const OTHER_ERR_CODE = 'foo'; + const NAV_ERR_CODE = 'ECONNABORTED'; + + it.each` + isFeatureFlagEnabled | isUserNavigating | code + ${false} | ${false} | ${OTHER_ERR_CODE} + ${false} | ${false} | ${NAV_ERR_CODE} + ${false} | ${true} | ${OTHER_ERR_CODE} + ${false} | ${true} | ${NAV_ERR_CODE} + ${true} | ${false} | ${OTHER_ERR_CODE} + ${true} | ${false} | ${NAV_ERR_CODE} + ${true} | ${true} | ${OTHER_ERR_CODE} + `('should return a rejected Promise', ({ isFeatureFlagEnabled, isUserNavigating, code }) => { + const err = { code }; + const actual = suppressAjaxErrorsDuringNavigation(err, isUserNavigating, isFeatureFlagEnabled); + + return expect(actual).rejects.toBe(err); + }); + + it('should return a Promise that never resolves', () => { + const err = { code: NAV_ERR_CODE }; + const actual = suppressAjaxErrorsDuringNavigation(err, true, true); + + const thenCallback = jest.fn(); + const catchCallback = jest.fn(); + actual.then(thenCallback).catch(catchCallback); + + return waitForPromises().then(() => { + expect(thenCallback).not.toHaveBeenCalled(); + expect(catchCallback).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/spec/javascripts/frequent_items/components/app_spec.js b/spec/javascripts/frequent_items/components/app_spec.js index 6814f656f5d..36dd8604d08 100644 --- a/spec/javascripts/frequent_items/components/app_spec.js +++ b/spec/javascripts/frequent_items/components/app_spec.js @@ -236,8 +236,15 @@ describe('Frequent Items App Component', () => { .then(() => { expect(vm.$el.querySelector('.loading-animation')).toBeDefined(); }) + + // This test waits for multiple ticks in order to allow the responses to + // propagate through each interceptor installed on the Axios instance. + // This shouldn't be necessary; this test should be refactored to avoid this. + // https://gitlab.com/gitlab-org/gitlab/issues/32479 + .then(vm.$nextTick) .then(vm.$nextTick) .then(vm.$nextTick) + .then(() => { expect(vm.$el.querySelectorAll('.frequent-items-list-container li').length).toBe( mockSearchedProjects.length, diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js index 85949f2ae86..8956bc92e6b 100644 --- a/spec/javascripts/lib/utils/common_utils_spec.js +++ b/spec/javascripts/lib/utils/common_utils_spec.js @@ -943,4 +943,14 @@ describe('common_utils', () => { expect(commonUtils.isScopedLabel({ title: 'foobar' })).toBe(false); }); }); + + describe('getDashPath', () => { + it('returns the path following /-/', () => { + expect(commonUtils.getDashPath('/some/-/url-with-dashes-/')).toEqual('url-with-dashes-/'); + }); + + it('returns null when no path follows /-/', () => { + expect(commonUtils.getDashPath('/some/url')).toEqual(null); + }); + }); }); diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 5c0f8bd392a..8ae56ae2d4b 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -3079,6 +3079,12 @@ describe Ci::Build do rescue StateMachines::InvalidTransition end + it 'ensures pipeline ref existence' do + expect(job.pipeline.persistent_ref).to receive(:create).once + + run_job_without_exception + end + shared_examples 'saves data on transition' do it 'saves timeout' do expect { job.run! }.to change { job.reload.ensure_metadata.timeout }.from(nil).to(expected_timeout) diff --git a/spec/models/ci/persistent_ref_spec.rb b/spec/models/ci/persistent_ref_spec.rb new file mode 100644 index 00000000000..71e0b03dff9 --- /dev/null +++ b/spec/models/ci/persistent_ref_spec.rb @@ -0,0 +1,108 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Ci::PersistentRef do + it 'cleans up persistent refs after pipeline finished' do + pipeline = create(:ci_pipeline, :running) + + expect(pipeline.persistent_ref).to receive(:delete).once + + pipeline.succeed! + end + + context '#exist?' do + subject { pipeline.persistent_ref.exist? } + + let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) } + let(:project) { create(:project, :repository) } + let(:sha) { project.repository.commit.sha } + + context 'when a persistent ref does not exist' do + it { is_expected.to eq(false) } + end + + context 'when a persistent ref exists' do + before do + pipeline.persistent_ref.create + end + + it { is_expected.to eq(true) } + end + end + + context '#create' do + subject { pipeline.persistent_ref.create } + + let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) } + let(:project) { create(:project, :repository) } + let(:sha) { project.repository.commit.sha } + + context 'when a persistent ref does not exist' do + it 'creates a persistent ref' do + subject + + expect(pipeline.persistent_ref).to be_exist + end + + context 'when depend_on_persistent_pipeline_ref feature flag is disabled' do + before do + stub_feature_flags(depend_on_persistent_pipeline_ref: false) + end + + it 'does not create a persistent ref' do + expect(project.repository).not_to receive(:create_ref) + + subject + end + end + + context 'when sha does not exist in the repository' do + let(:sha) { 'not-exist' } + + it 'fails to create a persistent ref' do + subject + + expect(pipeline.persistent_ref).not_to be_exist + end + end + end + + context 'when a persistent ref already exists' do + before do + pipeline.persistent_ref.create + end + + it 'does not create a persistent ref' do + expect(project.repository).not_to receive(:create_ref) + + subject + end + end + end + + context '#delete' do + subject { pipeline.persistent_ref.delete } + + let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) } + let(:project) { create(:project, :repository) } + let(:sha) { project.repository.commit.sha } + + context 'when a persistent ref exists' do + before do + pipeline.persistent_ref.create + end + + it 'deletes the ref' do + expect { subject }.to change { pipeline.persistent_ref.exist? } + .from(true).to(false) + end + end + + context 'when a persistent ref does not exist' do + it 'does not raise an error' do + expect { subject }.not_to raise_error + end + end + end +end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index fdd0cd8a3b7..a00d93ac4ba 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -1318,6 +1318,16 @@ describe Ci::Pipeline, :mailer do let(:build_b) { create_build('build2', queued_at: 0) } let(:build_c) { create_build('build3', queued_at: 0) } + %w[succeed! drop! cancel! skip!].each do |action| + context "when the pipeline recieved #{action} event" do + it 'deletes a persistent ref' do + expect(pipeline.persistent_ref).to receive(:delete).once + + pipeline.public_send(action) + end + end + end + describe '#duration' do context 'when multiple builds are finished' do before do diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb index dc28204d7aa..bc9124e73af 100644 --- a/spec/models/list_spec.rb +++ b/spec/models/list_spec.rb @@ -136,18 +136,6 @@ describe List do expect(preferences).to be_persisted expect(preferences.collapsed).to eq(true) end - - context 'when preferences are already loaded for user' do - it 'gets preloaded user preferences' do - fetched_list = described_class.where(id: list.id).with_preferences_for(user).first - - expect(fetched_list).to receive(:preloaded_preferences_for).with(user).and_call_original - - preferences = fetched_list.preferences_for(user) - - expect(preferences.collapsed).to eq(true) - end - end end context 'when preferences for user does not exist' do diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb index a4234d14255..fa8791f2257 100644 --- a/spec/presenters/ci/build_runner_presenter_spec.rb +++ b/spec/presenters/ci/build_runner_presenter_spec.rb @@ -207,5 +207,22 @@ describe Ci::BuildRunnerPresenter do end end end + + context 'when persistent pipeline ref exists' do + let(:project) { create(:project, :repository) } + let(:sha) { project.repository.commit.sha } + let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) } + let(:build) { create(:ci_build, pipeline: pipeline) } + + before do + pipeline.persistent_ref.create + end + + it 'exposes the persistent pipeline ref' do + is_expected + .to contain_exactly("+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}", + "+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}") + end + end end end diff --git a/spec/requests/boards/lists_controller_spec.rb b/spec/requests/boards/lists_controller_spec.rb new file mode 100644 index 00000000000..7451ad93efd --- /dev/null +++ b/spec/requests/boards/lists_controller_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Boards::ListsController do + describe '#index' do + let(:board) { create(:board) } + let(:user) { board.project.owner } + + it 'does not have N+1 queries' do + login_as(user) + + # First request has more queries because we create the default `backlog` list + get board_lists_path(board) + + create(:list, board: board) + + control_count = ActiveRecord::QueryRecorder.new { get board_lists_path(board) }.count + + create_list(:list, 5, board: board) + + expect { get board_lists_path(board) }.not_to exceed_query_limit(control_count) + end + end +end diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb index 1b28d2d4d02..05adec8b745 100644 --- a/spec/services/ci/process_pipeline_service_spec.rb +++ b/spec/services/ci/process_pipeline_service_spec.rb @@ -422,6 +422,18 @@ describe Ci::ProcessPipelineService, '#execute' do end end + context 'when an exception is raised during a persistent ref creation' do + before do + successful_build('test', stage_idx: 0) + + allow_any_instance_of(Ci::PersistentRef).to receive(:delete_refs) { raise ArgumentError } + end + + it 'process the pipeline' do + expect { process_pipeline }.not_to raise_error + end + end + context 'when there are manual action in earlier stages' do context 'when first stage has only optional manual actions' do before do @@ -907,6 +919,10 @@ describe Ci::ProcessPipelineService, '#execute' do create(:ci_build, :created, pipeline: pipeline, name: name, **opts) end + def successful_build(name, **opts) + create(:ci_build, :success, pipeline: pipeline, name: name, **opts) + end + def delayed_options { when: 'delayed', options: { script: %w(echo), start_in: '1 minute' } } end diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb index 874945c8585..2f2c525ccc4 100644 --- a/spec/services/ci/register_job_service_spec.rb +++ b/spec/services/ci/register_job_service_spec.rb @@ -501,6 +501,22 @@ module Ci expect(pending_job).to be_archived_failure end end + + context 'when an exception is raised during a persistent ref creation' do + before do + allow_any_instance_of(Ci::PersistentRef).to receive(:exist?) { false } + allow_any_instance_of(Ci::PersistentRef).to receive(:create_ref) { raise ArgumentError } + end + + subject { execute(specific_runner, {}) } + + it 'picks the build' do + expect(subject).to eq(pending_job) + + pending_job.reload + expect(pending_job).to be_running + end + end end describe '#register_success' do |