diff options
Diffstat (limited to 'spec')
26 files changed, 403 insertions, 73 deletions
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index 5d9403c23ac..b4a22a46b51 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -900,5 +900,37 @@ describe Projects::IssuesController do expect(JSON.parse(response.body).first.keys).to match_array(%w[id reply_id expanded notes individual_note]) end + + context 'with cross-reference system note', :request_store do + let(:new_issue) { create(:issue) } + let(:cross_reference) { "mentioned in #{new_issue.to_reference(issue.project)}" } + + before do + create(:discussion_note_on_issue, :system, noteable: issue, project: issue.project, note: cross_reference) + end + + it 'filters notes that the user should not see' do + get :discussions, namespace_id: project.namespace, project_id: project, id: issue.iid + + expect(JSON.parse(response.body).count).to eq(1) + end + + it 'does not result in N+1 queries' do + # Instantiate the controller variables to ensure QueryRecorder has an accurate base count + get :discussions, namespace_id: project.namespace, project_id: project, id: issue.iid + + RequestStore.clear! + + control_count = ActiveRecord::QueryRecorder.new do + get :discussions, namespace_id: project.namespace, project_id: project, id: issue.iid + end.count + + RequestStore.clear! + + create_list(:discussion_note_on_issue, 2, :system, noteable: issue, project: issue.project, note: cross_reference) + + expect { get :discussions, namespace_id: project.namespace, project_id: project, id: issue.iid }.not_to exceed_query_limit(control_count) + end + end end end diff --git a/spec/controllers/projects/pipelines_settings_controller_spec.rb b/spec/controllers/projects/pipelines_settings_controller_spec.rb new file mode 100644 index 00000000000..ee46ad00947 --- /dev/null +++ b/spec/controllers/projects/pipelines_settings_controller_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' + +describe Projects::PipelinesSettingsController do + set(:user) { create(:user) } + set(:project_auto_devops) { create(:project_auto_devops) } + let(:project) { project_auto_devops.project } + + before do + project.add_master(user) + + sign_in(user) + end + + describe 'PATCH update' do + before do + patch :update, + namespace_id: project.namespace.to_param, + project_id: project, + project: { + auto_devops_attributes: params + } + end + + context 'when updating the auto_devops settings' do + let(:params) { { enabled: '', domain: 'mepmep.md' } } + + it 'redirects to the settings page' do + expect(response).to have_http_status(302) + expect(flash[:notice]).to eq("Pipelines settings for '#{project.name}' were successfully updated.") + end + + context 'following the instance default' do + let(:params) { { enabled: '' } } + + it 'allows enabled to be set to nil' do + project_auto_devops.reload + + expect(project_auto_devops.enabled).to be_nil + end + end + end + end +end diff --git a/spec/features/issues/user_uses_slash_commands_spec.rb b/spec/features/issues/user_uses_slash_commands_spec.rb index 9261acda9dc..7437c469a72 100644 --- a/spec/features/issues/user_uses_slash_commands_spec.rb +++ b/spec/features/issues/user_uses_slash_commands_spec.rb @@ -159,7 +159,7 @@ feature 'Issues > User uses quick actions', js: true do describe 'move the issue to another project' do let(:issue) { create(:issue, project: project) } - context 'when the project is valid', js: true do + context 'when the project is valid' do let(:target_project) { create(:project, :public) } before do @@ -180,7 +180,7 @@ feature 'Issues > User uses quick actions', js: true do end end - context 'when the project is valid but the user not authorized', js: true do + context 'when the project is valid but the user not authorized' do let(:project_unauthorized) {create(:project, :public)} before do @@ -196,7 +196,7 @@ feature 'Issues > User uses quick actions', js: true do end end - context 'when the project is invalid', js: true do + context 'when the project is invalid' do before do sign_in(user) visit project_issue_path(project, issue) @@ -210,7 +210,7 @@ feature 'Issues > User uses quick actions', js: true do end end - context 'when the user issues multiple commands', js: true do + context 'when the user issues multiple commands' do let(:target_project) { create(:project, :public) } let(:milestone) { create(:milestone, title: '1.0', project: project) } let(:target_milestone) { create(:milestone, title: '1.0', project: target_project) } diff --git a/spec/features/merge_requests/widget_spec.rb b/spec/features/merge_requests/widget_spec.rb index fd991293ee9..443b596b3c6 100644 --- a/spec/features/merge_requests/widget_spec.rb +++ b/spec/features/merge_requests/widget_spec.rb @@ -142,6 +142,24 @@ describe 'Merge request', :js do end end + context 'view merge request where project has CI setup but no CI status' do + before do + pipeline = create(:ci_pipeline, project: project, + sha: merge_request.diff_head_sha, + ref: merge_request.source_branch) + create(:ci_build, pipeline: pipeline) + + visit project_merge_request_path(project, merge_request) + end + + it 'has pipeline error text' do + # Wait for the `ci_status` and `merge_check` requests + wait_for_requests + + expect(page).to have_text('Could not connect to the CI server. Please check your settings and try again') + end + end + context 'view merge request with MWPS enabled but automatically merge fails' do before do merge_request.update( diff --git a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb new file mode 100644 index 00000000000..1bd2098af6d --- /dev/null +++ b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe 'User comments on a snippet', :js do + let(:project) { create(:project) } + let!(:snippet) { create(:project_snippet, project: project, author: user) } + let(:user) { create(:user) } + + before do + project.add_master(user) + sign_in(user) + + visit(project_snippet_path(project, snippet)) + end + + it 'leaves a comment on a snippet' do + page.within('.js-main-target-form') do + fill_in('note_note', with: 'Good snippet!') + click_button('Comment') + end + + wait_for_requests + + expect(page).to have_content('Good snippet!') + end +end diff --git a/spec/features/projects/snippets/user_deletes_snippet_spec.rb b/spec/features/projects/snippets/user_deletes_snippet_spec.rb new file mode 100644 index 00000000000..ca5f7981c33 --- /dev/null +++ b/spec/features/projects/snippets/user_deletes_snippet_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe 'User deletes a snippet' do + let(:project) { create(:project) } + let!(:snippet) { create(:project_snippet, project: project, author: user) } + let(:user) { create(:user) } + + before do + project.add_master(user) + sign_in(user) + + visit(project_snippet_path(project, snippet)) + end + + it 'deletes a snippet' do + first(:link, 'Delete').click + + expect(page).not_to have_content(snippet.title) + end +end diff --git a/spec/features/projects/snippets/user_updates_snippet_spec.rb b/spec/features/projects/snippets/user_updates_snippet_spec.rb new file mode 100644 index 00000000000..09a390443cf --- /dev/null +++ b/spec/features/projects/snippets/user_updates_snippet_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe 'User updates a snippet' do + let(:project) { create(:project) } + let!(:snippet) { create(:project_snippet, project: project, author: user) } + let(:user) { create(:user) } + + before do + project.add_master(user) + sign_in(user) + + visit(project_snippet_path(project, snippet)) + end + + it 'updates a snippet' do + page.within('.detail-page-header') do + first(:link, 'Edit').click + end + + fill_in('project_snippet_title', with: 'Snippet new title') + click_button('Save') + + expect(page).to have_content('Snippet new title') + end +end diff --git a/spec/features/projects/snippets/user_views_snippets_spec.rb b/spec/features/projects/snippets/user_views_snippets_spec.rb new file mode 100644 index 00000000000..e9992e00ca8 --- /dev/null +++ b/spec/features/projects/snippets/user_views_snippets_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe 'User views snippets' do + let(:project) { create(:project) } + let!(:project_snippet) { create(:project_snippet, project: project, author: user) } + let!(:snippet) { create(:snippet, author: user) } + let(:user) { create(:user) } + + before do + project.add_master(user) + sign_in(user) + + visit(project_snippets_path(project)) + end + + it 'shows snippets' do + expect(page).to have_content(project_snippet.title) + expect(page).not_to have_content(snippet.title) + end +end diff --git a/spec/fixtures/api/schemas/public_api/v4/issues.json b/spec/fixtures/api/schemas/public_api/v4/issues.json index 8acd9488215..03c422ab023 100644 --- a/spec/fixtures/api/schemas/public_api/v4/issues.json +++ b/spec/fixtures/api/schemas/public_api/v4/issues.json @@ -9,6 +9,7 @@ "title": { "type": "string" }, "description": { "type": ["string", "null"] }, "state": { "type": "string" }, + "closed_at": { "type": "date" }, "created_at": { "type": "date" }, "updated_at": { "type": "date" }, "labels": { diff --git a/spec/helpers/submodule_helper_spec.rb b/spec/helpers/submodule_helper_spec.rb index c4f4e0d21dc..5a2e4b34069 100644 --- a/spec/helpers/submodule_helper_spec.rb +++ b/spec/helpers/submodule_helper_spec.rb @@ -147,6 +147,12 @@ describe SubmoduleHelper do expect(helper.submodule_links(submodule_item)).to eq([nil, nil]) end + it 'sanitizes invalid URL with extended ASCII' do + stub_url('é') + + expect(helper.submodule_links(submodule_item)).to eq([nil, nil]) + end + it 'returns original' do stub_url('http://mygitserver.com/gitlab-org/gitlab-ce') expect(submodule_links(submodule_item)).to eq([repo.submodule_url_for, nil]) diff --git a/spec/initializers/doorkeeper_spec.rb b/spec/initializers/doorkeeper_spec.rb index 37cc08b3038..1a78196e33d 100644 --- a/spec/initializers/doorkeeper_spec.rb +++ b/spec/initializers/doorkeeper_spec.rb @@ -9,8 +9,8 @@ describe Doorkeeper.configuration do end describe '#optional_scopes' do - it 'matches Gitlab::Auth::OPTIONAL_SCOPES' do - expect(subject.optional_scopes).to eq Gitlab::Auth::OPTIONAL_SCOPES - Gitlab::Auth::REGISTRY_SCOPES + it 'matches Gitlab::Auth.optional_scopes' do + expect(subject.optional_scopes).to eq Gitlab::Auth.optional_scopes - Gitlab::Auth::REGISTRY_SCOPES end end diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js index c763487d12f..690665ae12c 100644 --- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js +++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js @@ -37,6 +37,26 @@ describe('MRWidgetPipeline', () => { }); }); + describe('hasPipeline', () => { + it('should return true when there is a pipeline', () => { + expect(Object.keys(mockData.pipeline).length).toBeGreaterThan(0); + + const vm = createComponent({ + pipeline: mockData.pipeline, + }); + + expect(vm.hasPipeline).toBeTruthy(); + }); + + it('should return false when there is no pipeline', () => { + const vm = createComponent({ + pipeline: null, + }); + + expect(vm.hasPipeline).toBeFalsy(); + }); + }); + describe('hasCIError', () => { it('should return false when there is no CI error', () => { const vm = createComponent({ diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js index c607c9746a4..03a52f1f91c 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js @@ -11,6 +11,7 @@ const createComponent = (customConfig = {}) => { isPipelineActive: false, pipeline: null, isPipelineFailed: false, + isPipelinePassing: false, onlyAllowMergeIfPipelineSucceeds: false, hasCI: false, ciStatus: null, @@ -68,6 +69,18 @@ describe('MRWidgetReadyToMerge', () => { }); describe('computed', () => { + describe('shouldShowMergeWhenPipelineSucceedsText', () => { + it('should return true with active pipeline', () => { + vm.mr.isPipelineActive = true; + expect(vm.shouldShowMergeWhenPipelineSucceedsText).toBeTruthy(); + }); + + it('should return false with inactive pipeline', () => { + vm.mr.isPipelineActive = false; + expect(vm.shouldShowMergeWhenPipelineSucceedsText).toBeFalsy(); + }); + }); + describe('commitMessageLinkTitle', () => { const withDesc = 'Include description in commit message'; const withoutDesc = "Don't include description in commit message"; @@ -83,7 +96,7 @@ describe('MRWidgetReadyToMerge', () => { }); describe('mergeButtonClass', () => { - const defaultClass = 'btn btn-small btn-success accept-merge-request'; + const defaultClass = 'btn btn-sm btn-success accept-merge-request'; const failedClass = `${defaultClass} btn-danger`; const inActionClass = `${defaultClass} btn-info`; @@ -203,20 +216,55 @@ describe('MRWidgetReadyToMerge', () => { describe('methods', () => { describe('isMergeAllowed', () => { - it('should return false with initial data', () => { + it('should return true when no pipeline and not required to succeed', () => { + vm.mr.onlyAllowMergeIfPipelineSucceeds = false; + vm.mr.isPipelinePassing = false; expect(vm.isMergeAllowed()).toBeTruthy(); }); - it('should return false when MR is set only merge when pipeline succeeds', () => { - vm.mr.onlyAllowMergeIfPipelineSucceeds = true; + it('should return true when pipeline failed and not required to succeed', () => { + vm.mr.onlyAllowMergeIfPipelineSucceeds = false; + vm.mr.isPipelinePassing = false; expect(vm.isMergeAllowed()).toBeTruthy(); }); - it('should return true true', () => { + it('should return false when pipeline failed and required to succeed', () => { vm.mr.onlyAllowMergeIfPipelineSucceeds = true; - vm.mr.isPipelineFailed = true; + vm.mr.isPipelinePassing = false; expect(vm.isMergeAllowed()).toBeFalsy(); }); + + it('should return true when pipeline succeeded and required to succeed', () => { + vm.mr.onlyAllowMergeIfPipelineSucceeds = true; + vm.mr.isPipelinePassing = true; + expect(vm.isMergeAllowed()).toBeTruthy(); + }); + }); + + describe('shouldShowMergeControls', () => { + it('should return false when an external pipeline is running and required to succeed', () => { + spyOn(vm, 'isMergeAllowed').and.returnValue(false); + vm.mr.isPipelineActive = false; + expect(vm.shouldShowMergeControls()).toBeFalsy(); + }); + + it('should return true when the build succeeded or build not required to succeed', () => { + spyOn(vm, 'isMergeAllowed').and.returnValue(true); + vm.mr.isPipelineActive = false; + expect(vm.shouldShowMergeControls()).toBeTruthy(); + }); + + it('should return true when showing the MWPS button and a pipeline is running that needs to be successful', () => { + spyOn(vm, 'isMergeAllowed').and.returnValue(false); + vm.mr.isPipelineActive = true; + expect(vm.shouldShowMergeControls()).toBeTruthy(); + }); + + it('should return true when showing the MWPS button but not required for the pipeline to succeed', () => { + spyOn(vm, 'isMergeAllowed').and.returnValue(true); + vm.mr.isPipelineActive = true; + expect(vm.shouldShowMergeControls()).toBeTruthy(); + }); }); describe('updateCommitMessage', () => { diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js index 669ee248bf1..da66c7504cb 100644 --- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js +++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js @@ -59,23 +59,15 @@ describe('mrWidgetOptions', () => { }); describe('shouldRenderPipelines', () => { - it('should return true for the initial data', () => { - expect(vm.shouldRenderPipelines).toBeTruthy(); - }); + it('should return true when hasCI is true', () => { + vm.mr.hasCI = true; - it('should return true when pipeline is empty but MR.hasCI is set to true', () => { - vm.mr.pipeline = {}; expect(vm.shouldRenderPipelines).toBeTruthy(); }); - it('should return true when pipeline available', () => { + it('should return false when hasCI is false', () => { vm.mr.hasCI = false; - expect(vm.shouldRenderPipelines).toBeTruthy(); - }); - it('should return false when there is no pipeline', () => { - vm.mr.pipeline = {}; - vm.mr.hasCI = false; expect(vm.shouldRenderPipelines).toBeFalsy(); }); }); diff --git a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js index 56dd0198ae2..8e5614b20f0 100644 --- a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js +++ b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js @@ -18,5 +18,39 @@ describe('MergeRequestStore', () => { store.setData({ ...mockData, work_in_progress: !mockData.work_in_progress }); expect(store.hasSHAChanged).toBe(false); }); + + describe('isPipelinePassing', () => { + it('is true when the CI status is `success`', () => { + store.setData({ ...mockData, ci_status: 'success' }); + expect(store.isPipelinePassing).toBe(true); + }); + + it('is true when the CI status is `success_with_warnings`', () => { + store.setData({ ...mockData, ci_status: 'success_with_warnings' }); + expect(store.isPipelinePassing).toBe(true); + }); + + it('is false when the CI status is `failed`', () => { + store.setData({ ...mockData, ci_status: 'failed' }); + expect(store.isPipelinePassing).toBe(false); + }); + + it('is false when the CI status is anything except `success`', () => { + store.setData({ ...mockData, ci_status: 'foobarbaz' }); + expect(store.isPipelinePassing).toBe(false); + }); + }); + + describe('isPipelineSkipped', () => { + it('should set isPipelineSkipped=true when the CI status is `skipped`', () => { + store.setData({ ...mockData, ci_status: 'skipped' }); + expect(store.isPipelineSkipped).toBe(true); + }); + + it('should set isPipelineSkipped=false when the CI status is anything except `skipped`', () => { + store.setData({ ...mockData, ci_status: 'foobarbaz' }); + expect(store.isPipelineSkipped).toBe(false); + }); + }); }); }); diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 4f4a27e4c41..af1db2c3455 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -16,20 +16,20 @@ describe Gitlab::Auth do expect(subject::DEFAULT_SCOPES).to eq [:api] end - it 'OPTIONAL_SCOPES contains all non-default scopes' do + it 'optional_scopes contains all non-default scopes' do stub_container_registry_config(enabled: true) - expect(subject::OPTIONAL_SCOPES).to eq %i[read_user read_registry openid] + expect(subject.optional_scopes).to eq %i[read_user read_registry openid] end - context 'REGISTRY_SCOPES' do + context 'registry_scopes' do context 'when registry is disabled' do before do stub_container_registry_config(enabled: false) end it 'is empty' do - expect(subject::REGISTRY_SCOPES).to eq [] + expect(subject.registry_scopes).to eq [] end end @@ -39,7 +39,7 @@ describe Gitlab::Auth do end it 'contains all registry related scopes' do - expect(subject::REGISTRY_SCOPES).to eq %i[read_registry] + expect(subject.registry_scopes).to eq %i[read_registry] end end end diff --git a/spec/lib/gitlab/diff/position_tracer_spec.rb b/spec/lib/gitlab/diff/position_tracer_spec.rb index 8beebc10040..4fa30d8df8b 100644 --- a/spec/lib/gitlab/diff/position_tracer_spec.rb +++ b/spec/lib/gitlab/diff/position_tracer_spec.rb @@ -1761,17 +1761,9 @@ describe Gitlab::Diff::PositionTracer do let(:merge_commit) do update_file_again_commit - committer = repository.user_to_committer(current_user) - - options = { - message: "Merge branches", - author: committer, - committer: committer - } - merge_request = create(:merge_request, source_branch: second_create_file_commit.sha, target_branch: branch_name, source_project: project) - repository.merge(current_user, merge_request.diff_head_sha, merge_request, options) + repository.merge(current_user, merge_request.diff_head_sha, merge_request, "Merge branches") project.commit(branch_name) end diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 11e64a0f877..e3cfa149e3a 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -207,11 +207,6 @@ eos context 'of a merge commit' do let(:repository) { project.repository } - let(:commit_options) do - author = repository.user_to_committer(user) - { message: 'Test message', committer: author, author: author } - end - let(:merge_request) do create(:merge_request, source_branch: 'video', @@ -224,7 +219,7 @@ eos merge_commit_id = repository.merge(user, merge_request.diff_head_sha, merge_request, - commit_options) + 'Test message') repository.commit(merge_commit_id) end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 53280f2c1cf..60cd7e70055 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -10,10 +10,7 @@ describe Repository, models: true do let(:user) { create(:user) } let(:git_user) { Gitlab::Git::User.from_gitlab(user) } - let(:commit_options) do - author = repository.user_to_committer(user) - { message: 'Test message', committer: author, author: author } - end + let(:message) { 'Test message' } let(:merge_commit) do merge_request = create(:merge_request, source_branch: 'feature', target_branch: 'master', source_project: project) @@ -21,7 +18,7 @@ describe Repository, models: true do merge_commit_id = repository.merge(user, merge_request.diff_head_sha, merge_request, - commit_options) + message) repository.commit(merge_commit_id) end @@ -1287,10 +1284,7 @@ describe Repository, models: true do describe '#merge' do let(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'master', source_project: project) } - let(:commit_options) do - author = repository.user_to_committer(user) - { message: 'Test \r\n\r\n message', committer: author, author: author } - end + let(:message) { 'Test \r\n\r\n message' } it 'merges the code and returns the commit id' do expect(merge_commit).to be_present @@ -1298,19 +1292,19 @@ describe Repository, models: true do end it 'sets the `in_progress_merge_commit_sha` flag for the given merge request' do - merge_commit_id = merge(repository, user, merge_request, commit_options) + merge_commit_id = merge(repository, user, merge_request, message) expect(merge_request.in_progress_merge_commit_sha).to eq(merge_commit_id) end it 'removes carriage returns from commit message' do - merge_commit_id = merge(repository, user, merge_request, commit_options) + merge_commit_id = merge(repository, user, merge_request, message) - expect(repository.commit(merge_commit_id).message).to eq(commit_options[:message].delete("\r")) + expect(repository.commit(merge_commit_id).message).to eq(message.delete("\r")) end - def merge(repository, user, merge_request, options = {}) - repository.merge(user, merge_request.diff_head_sha, merge_request, options) + def merge(repository, user, merge_request, message) + repository.merge(user, merge_request.diff_head_sha, merge_request, message) end end diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb index b186a78e44a..17dc3bb4f48 100644 --- a/spec/policies/group_policy_spec.rb +++ b/spec/policies/group_policy_spec.rb @@ -11,10 +11,11 @@ describe GroupPolicy do let(:reporter_permissions) { [:admin_label] } + let(:developer_permissions) { [:admin_milestones] } + let(:master_permissions) do [ - :create_projects, - :admin_milestones + :create_projects ] end @@ -52,6 +53,7 @@ describe GroupPolicy do it do expect_allowed(:read_group) expect_disallowed(*reporter_permissions) + expect_disallowed(*developer_permissions) expect_disallowed(*master_permissions) expect_disallowed(*owner_permissions) end @@ -63,6 +65,7 @@ describe GroupPolicy do it do expect_allowed(:read_group) expect_disallowed(*reporter_permissions) + expect_disallowed(*developer_permissions) expect_disallowed(*master_permissions) expect_disallowed(*owner_permissions) end @@ -74,6 +77,7 @@ describe GroupPolicy do it do expect_allowed(:read_group) expect_allowed(*reporter_permissions) + expect_disallowed(*developer_permissions) expect_disallowed(*master_permissions) expect_disallowed(*owner_permissions) end @@ -85,6 +89,7 @@ describe GroupPolicy do it do expect_allowed(:read_group) expect_allowed(*reporter_permissions) + expect_allowed(*developer_permissions) expect_disallowed(*master_permissions) expect_disallowed(*owner_permissions) end @@ -96,6 +101,7 @@ describe GroupPolicy do it do expect_allowed(:read_group) expect_allowed(*reporter_permissions) + expect_allowed(*developer_permissions) expect_allowed(*master_permissions) expect_disallowed(*owner_permissions) end @@ -109,6 +115,7 @@ describe GroupPolicy do expect_allowed(:read_group) expect_allowed(*reporter_permissions) + expect_allowed(*developer_permissions) expect_allowed(*master_permissions) expect_allowed(*owner_permissions) end @@ -122,6 +129,7 @@ describe GroupPolicy do expect_allowed(:read_group) expect_allowed(*reporter_permissions) + expect_allowed(*developer_permissions) expect_allowed(*master_permissions) expect_allowed(*owner_permissions) end @@ -180,6 +188,7 @@ describe GroupPolicy do it do expect_disallowed(:read_group) expect_disallowed(*reporter_permissions) + expect_disallowed(*developer_permissions) expect_disallowed(*master_permissions) expect_disallowed(*owner_permissions) end @@ -191,6 +200,7 @@ describe GroupPolicy do it do expect_allowed(:read_group) expect_disallowed(*reporter_permissions) + expect_disallowed(*developer_permissions) expect_disallowed(*master_permissions) expect_disallowed(*owner_permissions) end @@ -202,6 +212,7 @@ describe GroupPolicy do it do expect_allowed(:read_group) expect_allowed(*reporter_permissions) + expect_disallowed(*developer_permissions) expect_disallowed(*master_permissions) expect_disallowed(*owner_permissions) end @@ -213,6 +224,7 @@ describe GroupPolicy do it do expect_allowed(:read_group) expect_allowed(*reporter_permissions) + expect_allowed(*developer_permissions) expect_disallowed(*master_permissions) expect_disallowed(*owner_permissions) end @@ -224,6 +236,7 @@ describe GroupPolicy do it do expect_allowed(:read_group) expect_allowed(*reporter_permissions) + expect_allowed(*developer_permissions) expect_allowed(*master_permissions) expect_disallowed(*owner_permissions) end @@ -237,6 +250,7 @@ describe GroupPolicy do expect_allowed(:read_group) expect_allowed(*reporter_permissions) + expect_allowed(*developer_permissions) expect_allowed(*master_permissions) expect_allowed(*owner_permissions) end diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index 4dbaf7fb025..c0cbdeed03d 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -33,7 +33,7 @@ describe ProjectPolicy do let(:developer_permissions) do %i[ - admin_merge_request update_merge_request create_commit_status + admin_milestone admin_merge_request update_merge_request create_commit_status update_commit_status create_build update_build create_pipeline update_pipeline create_merge_request create_wiki push_code resolve_note create_container_image update_container_image @@ -44,7 +44,7 @@ describe ProjectPolicy do let(:master_permissions) do %i[ delete_protected_branch update_project_snippet update_environment - update_deployment admin_milestone admin_project_snippet + update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project admin_commit_status admin_build admin_container_image admin_pipeline admin_environment admin_deployment diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 1583d1c2435..972e57bc373 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -22,7 +22,8 @@ describe API::Issues, :mailer do state: :closed, milestone: milestone, created_at: generate(:past_time), - updated_at: 3.hours.ago + updated_at: 3.hours.ago, + closed_at: 1.hour.ago end let!(:confidential_issue) do create :issue, @@ -738,6 +739,7 @@ describe API::Issues, :mailer do expect(json_response['title']).to eq(issue.title) expect(json_response['description']).to eq(issue.description) expect(json_response['state']).to eq(issue.state) + expect(json_response['closed_at']).to be_falsy expect(json_response['created_at']).to be_present expect(json_response['updated_at']).to be_present expect(json_response['labels']).to eq(issue.label_names) @@ -748,6 +750,13 @@ describe API::Issues, :mailer do expect(json_response['confidential']).to be_falsy end + it "exposes the 'closed_at' attribute" do + get api("/projects/#{project.id}/issues/#{closed_issue.iid}", user) + + expect(response).to have_http_status(200) + expect(json_response['closed_at']).to be_present + end + context 'links exposure' do it 'exposes related resources full URIs' do get api("/projects/#{project.id}/issues/#{issue.iid}", user) diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 21d2c9644fb..c4f6e97b915 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -28,10 +28,29 @@ describe API::MergeRequests do describe 'GET /merge_requests' do context 'when unauthenticated' do - it 'returns authentication error' do - get api('/merge_requests') + it 'returns an array of all merge requests' do + get api('/merge_requests', user), scope: 'all' + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + end + + it "returns authentication error without any scope" do + get api("/merge_requests") + + expect(response).to have_http_status(401) + end + + it "returns authentication error when scope is assigned-to-me" do + get api("/merge_requests"), scope: 'assigned-to-me' - expect(response).to have_gitlab_http_status(401) + expect(response).to have_http_status(401) + end + + it "returns authentication error when scope is created-by-me" do + get api("/merge_requests"), scope: 'created-by-me' + + expect(response).to have_http_status(401) end end @@ -134,10 +153,18 @@ describe API::MergeRequests do describe "GET /projects/:id/merge_requests" do context "when unauthenticated" do - it "returns authentication error" do + it 'returns merge requests for public projects' do + get api("/projects/#{project.id}/merge_requests") + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + end + + it "returns 404 for non public projects" do + project = create(:project, :private) get api("/projects/#{project.id}/merge_requests") - expect(response).to have_gitlab_http_status(401) + expect(response).to have_http_status(404) end end diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 2af2485eeed..64e676f22a0 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -150,9 +150,7 @@ describe MergeRequests::RefreshService do context 'manual merge of source branch' do before do # Merge master -> feature branch - author = { email: 'test@gitlab.com', time: Time.now, name: "Me" } - commit_options = { message: 'Test message', committer: author, author: author } - @project.repository.merge(@user, @merge_request.diff_head_sha, @merge_request, commit_options) + @project.repository.merge(@user, @merge_request.diff_head_sha, @merge_request, 'Test message') commit = @project.repository.commit('feature') service.new(@project, @user).execute(@oldrev, commit.id, 'refs/heads/feature') reload_mrs diff --git a/spec/support/stub_gitlab_calls.rb b/spec/support/stub_gitlab_calls.rb index 9695f35bd25..78a2ff73746 100644 --- a/spec/support/stub_gitlab_calls.rb +++ b/spec/support/stub_gitlab_calls.rb @@ -26,11 +26,9 @@ module StubGitlabCalls end def stub_container_registry_config(registry_settings) + allow(Gitlab.config.registry).to receive_messages(registry_settings) allow(Auth::ContainerRegistryAuthenticationService) .to receive(:full_access_token).and_return('token') - - allow(Gitlab.config.registry).to receive_messages(registry_settings) - load 'lib/gitlab/auth.rb' end def stub_container_registry_tags(repository: :any, tags:) diff --git a/spec/views/shared/milestones/_issuable.html.haml.rb b/spec/views/shared/milestones/_issuable.html.haml.rb new file mode 100644 index 00000000000..0a3f877cae0 --- /dev/null +++ b/spec/views/shared/milestones/_issuable.html.haml.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe 'shared/milestones/_issuable.html.haml' do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:milestone) { create(:milestone, project: project) } + let(:issuable) { create(:issue, project: project, assignees: [user]) } + + before do + assign(:project, project) + assign(:milestone, milestone) + end + + it 'avatar links to issues page' do + render 'shared/milestones/issuable', issuable: issuable, show_project_name: true + + expect(rendered).to have_css("a[href='#{project_issues_path(project, milestone_title: milestone.title, assignee_id: user.id, state: 'all')}']") + end +end |