diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-22 18:11:12 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-22 18:11:12 +0000 |
commit | 1862f4a83ebb0a08a0da8269c568e1b93f75d55a (patch) | |
tree | bfec3ba41bedd2c138b60fdb5c2cc308932f16ee /spec | |
parent | b6abc9850e69e4e2ab60fa6ababe25da97505edc (diff) | |
download | gitlab-ce-1862f4a83ebb0a08a0da8269c568e1b93f75d55a.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
28 files changed, 296 insertions, 97 deletions
diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb index 70e58124d21..e9b39d44e46 100644 --- a/spec/controllers/autocomplete_controller_spec.rb +++ b/spec/controllers/autocomplete_controller_spec.rb @@ -96,7 +96,7 @@ RSpec.describe AutocompleteController do end context 'user order' do - it 'shows exact matches first' do + it 'shows exact matches first', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/375028' do reported_user = create(:user, username: 'reported_user', name: 'Doug') user = create(:user, username: 'user', name: 'User') user1 = create(:user, username: 'user1', name: 'Ian') diff --git a/spec/controllers/boards/issues_controller_spec.rb b/spec/controllers/boards/issues_controller_spec.rb index 1fd249eba69..6bf2f088ab9 100644 --- a/spec/controllers/boards/issues_controller_spec.rb +++ b/spec/controllers/boards/issues_controller_spec.rb @@ -481,6 +481,23 @@ RSpec.describe Boards::IssuesController do end end + context 'when create service returns an unrecoverable error' do + before do + allow_next_instance_of(Issues::CreateService) do |create_service| + allow(create_service).to receive(:execute).and_return( + ServiceResponse.error(message: 'unrecoverable error', http_status: 404) + ) + end + end + + it 'returns an array with errors an service http_status' do + create_issue user: user, board: board, list: list1, title: 'New issue' + + expect(response).to have_gitlab_http_status(:not_found) + expect(json_response).to contain_exactly('unrecoverable error') + end + end + context 'with guest user' do context 'in open list' do it 'returns a successful 200 response' do diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index c48be8efb1b..64d4b276519 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -1107,6 +1107,46 @@ RSpec.describe Projects::IssuesController do end end + context 'when create service return an unrecoverable error with http_status' do + let(:http_status) { 403 } + + before do + allow_next_instance_of(::Issues::CreateService) do |create_service| + allow(create_service).to receive(:execute).and_return( + ServiceResponse.error(message: 'unrecoverable error', http_status: http_status) + ) + end + end + + it 'renders 403 and logs the error' do + expect(Gitlab::AppLogger).to receive(:warn).with( + message: 'Cannot create issue', + errors: ['unrecoverable error'], + http_status: http_status + ) + + post_new_issue + + expect(response).to have_gitlab_http_status :forbidden + end + + context 'when no render method is found for the returned http_status' do + let(:http_status) { nil } + + it 'renders 404 and logs the error' do + expect(Gitlab::AppLogger).to receive(:warn).with( + message: 'Cannot create issue', + errors: ['unrecoverable error'], + http_status: http_status + ) + + post_new_issue + + expect(response).to have_gitlab_http_status :not_found + end + end + end + it 'creates the issue successfully', :aggregate_failures do issue = post_new_issue diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index b30610d98d7..1f7c124a601 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -299,14 +299,16 @@ RSpec.describe ProjectsController do end it "renders files even with invalid license" do + invalid_license = ::Gitlab::Git::DeclaredLicense.new(key: 'woozle', name: 'woozle wuzzle') + controller.instance_variable_set(:@project, public_project) - expect(public_project.repository).to receive(:license_key).and_return('woozle wuzzle').at_least(:once) + expect(public_project.repository).to receive(:license).and_return(invalid_license).at_least(:once) get_show expect(response).to have_gitlab_http_status(:ok) expect(response).to render_template('_files') - expect(response.body).to have_content('LICENSE') # would be 'MIT license' if stub not works + expect(response.body).to have_content('woozle wuzzle') end describe 'tracking events', :snowplow do diff --git a/spec/factories/ci/reports/sbom/components.rb b/spec/factories/ci/reports/sbom/components.rb index 317e1c863cf..fd9b4386130 100644 --- a/spec/factories/ci/reports/sbom/components.rb +++ b/spec/factories/ci/reports/sbom/components.rb @@ -2,7 +2,7 @@ FactoryBot.define do factory :ci_reports_sbom_component, class: '::Gitlab::Ci::Reports::Sbom::Component' do - type { :library } + type { "library" } sequence(:name) { |n| "component-#{n}" } sequence(:version) { |n| "v0.0.#{n}" } diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb index 1eebb6c2e28..47a25533809 100644 --- a/spec/features/merge_request/user_posts_diff_notes_spec.rb +++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb @@ -219,7 +219,7 @@ RSpec.describe 'Merge request > User posts diff notes', :js do end context 'with a match line' do - it 'does not allow commenting' do + it 'does not allow commenting', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/375024' do match_should_not_allow_commenting(find_by_scrolling('.match', match: :first)) end end diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb index 13a4c1b5912..93e5be18229 100644 --- a/spec/features/projects/blobs/blob_show_spec.rb +++ b/spec/features/projects/blobs/blob_show_spec.rb @@ -675,7 +675,7 @@ RSpec.describe 'File blob', :js do expect(page).to have_content('This project is licensed under the MIT License.') # shows a learn more link - expect(page).to have_link('Learn more', href: 'http://choosealicense.com/licenses/mit/') + expect(page).to have_link('Learn more', href: 'https://opensource.org/licenses/MIT') end end end diff --git a/spec/features/unsubscribe_links_spec.rb b/spec/features/unsubscribe_links_spec.rb index 5317f586390..f90b2060418 100644 --- a/spec/features/unsubscribe_links_spec.rb +++ b/spec/features/unsubscribe_links_spec.rb @@ -9,7 +9,7 @@ RSpec.describe 'Unsubscribe links', :sidekiq_might_not_need_inline do let(:author) { create(:user) } let(:project) { create(:project, :public) } let(:params) { { title: 'A bug!', description: 'Fix it!', assignees: [recipient] } } - let(:issue) { Issues::CreateService.new(project: project, current_user: author, params: params, spam_params: nil).execute } + let(:issue) { Issues::CreateService.new(project: project, current_user: author, params: params, spam_params: nil).execute[:issue] } let(:mail) { ActionMailer::Base.deliveries.last } let(:body) { Capybara::Node::Simple.new(mail.default_part_body.to_s) } diff --git a/spec/frontend/__helpers__/stub_component.js b/spec/frontend/__helpers__/stub_component.js index 4f9d1ee6f5d..3e9af994ee3 100644 --- a/spec/frontend/__helpers__/stub_component.js +++ b/spec/frontend/__helpers__/stub_component.js @@ -38,7 +38,7 @@ export function stubComponent(Component, options = {}) { // Do not render any slots/scoped slots except default // This differs from VTU behavior which renders all slots template: '<div><slot></slot></div>', - // allows wrapper.find(Component) to work for stub + // allows wrapper.findComponent(Component) to work for stub $_vueTestUtils_original: Component, ...options, }; diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js index cc2ff90de57..bdde2874535 100644 --- a/spec/frontend/pipelines/pipelines_spec.js +++ b/spec/frontend/pipelines/pipelines_spec.js @@ -261,9 +261,14 @@ describe('Pipelines', () => { ); }); - it('tracks tab change click', () => { + it.each(['all', 'finished', 'branches', 'tags'])('tracks %p tab click', async (scope) => { + goToTab(scope); + + await waitForPromises(); + expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_filter_tabs', { label: TRACKING_CATEGORIES.tabs, + property: scope, }); }); }); diff --git a/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js index 12ee100bb9c..f310f7669a9 100644 --- a/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js +++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js @@ -137,9 +137,11 @@ describe('Deployment component', () => { if (actionButtons.includes(DeploymentViewButton)) { it('renders the View button with expected text', () => { if (status === SUCCESS) { - expect(wrapper.find(DeploymentViewButton).text()).toContain('View app'); + expect(wrapper.findComponent(DeploymentViewButton).text()).toContain('View app'); } else { - expect(wrapper.find(DeploymentViewButton).text()).toContain('View latest app'); + expect(wrapper.findComponent(DeploymentViewButton).text()).toContain( + 'View latest app', + ); } }); } diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index a9db2a1c008..a3826ec8eb8 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -825,7 +825,7 @@ RSpec.describe ProjectsHelper do end context 'gitaly is working appropriately' do - let(:license) { Licensee::License.new('mit') } + let(:license) { ::Gitlab::Git::DeclaredLicense.new(key: 'mit', name: 'MIT License') } before do expect(repository).to receive(:license).and_return(license) diff --git a/spec/helpers/sessions_helper_spec.rb b/spec/helpers/sessions_helper_spec.rb index 15424425060..c7b8225b866 100644 --- a/spec/helpers/sessions_helper_spec.rb +++ b/spec/helpers/sessions_helper_spec.rb @@ -92,6 +92,12 @@ RSpec.describe SessionsHelper do end context 'when an email address is very short' do + let(:email) { 'a@b.c' } + + it { is_expected.to eq('a@b.c') } + end + + context 'when an email address is even shorter' do let(:email) { 'a@b' } it { is_expected.to eq('a@b') } diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 9a87911b6e8..52c6557b93b 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -1784,22 +1784,32 @@ RSpec.describe Gitlab::Git::Repository do end end - describe '#license_short_name' do - subject { repository.license_short_name } + describe '#license' do + where(from_gitaly: [true, false]) + with_them do + subject(:license) { repository.license(from_gitaly) } - context 'when no license file can be found' do - let(:project) { create(:project, :repository) } - let(:repository) { project.repository.raw_repository } + context 'when no license file can be found' do + let(:project) { create(:project, :repository) } + let(:repository) { project.repository.raw_repository } - before do - project.repository.delete_file(project.owner, 'LICENSE', message: 'remove license', branch_name: 'master') + before do + project.repository.delete_file(project.owner, 'LICENSE', message: 'remove license', branch_name: 'master') + end + + it { is_expected.to be_nil } end - it { is_expected.to be_nil } + context 'when an mit license is found' do + it { is_expected.to have_attributes(key: 'mit') } + end end - context 'when an mit license is found' do - it { is_expected.to eq('mit') } + it 'does not crash when license is not recognized' do + expect(Licensee::License).to receive(:new) + .and_raise(Licensee::InvalidLicense) + + expect(repository.license(false)).to be_nil end end diff --git a/spec/lib/gitlab/slash_commands/issue_new_spec.rb b/spec/lib/gitlab/slash_commands/issue_new_spec.rb index c17cee887ee..29a941f3691 100644 --- a/spec/lib/gitlab/slash_commands/issue_new_spec.rb +++ b/spec/lib/gitlab/slash_commands/issue_new_spec.rb @@ -53,6 +53,21 @@ RSpec.describe Gitlab::SlashCommands::IssueNew do expect(subject[:response_type]).to be(:ephemeral) expect(subject[:text]).to match("- Title is too long") end + + context 'when create issue service return an unrecoverable error' do + let(:regex_match) { described_class.match("issue create title}") } + + before do + allow_next_instance_of(Issues::CreateService) do |create_service| + allow(create_service).to receive(:execute).and_return(ServiceResponse.error(message: 'unauthorized')) + end + end + + it 'displays the errors' do + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to eq('unauthorized') + end + end end end diff --git a/spec/models/integrations/microsoft_teams_spec.rb b/spec/models/integrations/microsoft_teams_spec.rb index b1b3e42b5e9..89ccc9eaf35 100644 --- a/spec/models/integrations/microsoft_teams_spec.rb +++ b/spec/models/integrations/microsoft_teams_spec.rb @@ -81,7 +81,7 @@ RSpec.describe Integrations::MicrosoftTeams do let(:opts) { { title: 'Awesome issue', description: 'please fix' } } let(:issues_sample_data) do service = Issues::CreateService.new(project: project, current_user: user, params: opts, spam_params: nil) - issue = service.execute + issue = service.execute[:issue] service.hook_data(issue, 'open') end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index d77a8f50cd1..bd46fb9b1a6 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1331,7 +1331,7 @@ RSpec.describe Repository do end end - describe '#license_key', :use_clean_rails_memory_store_caching do + describe '#license_key', :clean_gitlab_redis_cache do let(:project) { create(:project, :repository) } before do @@ -1377,48 +1377,46 @@ RSpec.describe Repository do end end - describe '#license' do - let(:project) { create(:project, :repository) } - - before do - repository.delete_file(user, 'LICENSE', - message: 'Remove LICENSE', branch_name: 'master') - end + [true, false].each do |ff| + context "with feature flag license_from_gitaly=#{ff}" do + before do + stub_feature_flags(license_from_gitaly: ff) + end - it 'returns nil when no license is detected' do - expect(repository.license).to be_nil - end + describe '#license', :use_clean_rails_memory_store_caching, :clean_gitlab_redis_cache do + let(:project) { create(:project, :repository) } - it 'returns nil when the repository does not exist' do - expect(repository).to receive(:exists?).and_return(false) + before do + repository.delete_file(user, 'LICENSE', + message: 'Remove LICENSE', branch_name: 'master') + end - expect(repository.license).to be_nil - end + it 'returns nil when no license is detected' do + expect(repository.license).to be_nil + end - it 'returns nil when license_key is not recognized' do - expect(repository).to receive(:license_key).twice.and_return('not-recognized') - expect(Gitlab::ErrorTracking).to receive(:track_exception) do |ex| - expect(ex).to be_a(Licensee::InvalidLicense) - end + it 'returns nil when the repository does not exist' do + expect(repository).to receive(:exists?).and_return(false) - expect(repository.license).to be_nil - end + expect(repository.license).to be_nil + end - it 'returns other when the content is not recognizable' do - license = Licensee::License.new('other') - repository.create_file(user, 'LICENSE', 'Gitlab B.V.', - message: 'Add LICENSE', branch_name: 'master') + it 'returns other when the content is not recognizable' do + repository.create_file(user, 'LICENSE', 'Gitlab B.V.', + message: 'Add LICENSE', branch_name: 'master') - expect(repository.license).to eq(license) - end + expect(repository.license_key).to eq('other') + end - it 'returns the license' do - license = Licensee::License.new('mit') - repository.create_file(user, 'LICENSE', - license.content, - message: 'Add LICENSE', branch_name: 'master') + it 'returns the license' do + license = Licensee::License.new('mit') + repository.create_file(user, 'LICENSE', + license.content, + message: 'Add LICENSE', branch_name: 'master') - expect(repository.license).to eq(license) + expect(repository.license_key).to eq(license.key) + end + end end end @@ -2207,7 +2205,8 @@ RSpec.describe Repository do :contribution_guide, :changelog, :license_blob, - :license_key, + :license_licensee, + :license_gitaly, :gitignore, :gitlab_ci_yml, :branch_names, @@ -2695,7 +2694,7 @@ RSpec.describe Repository do match[1].to_sym if match end.compact - expect(Repository::CACHED_METHODS + Repository::MEMOIZED_CACHED_METHODS).to include(*methods) + expect(Repository::CACHED_METHODS).to include(*methods) end end @@ -2860,12 +2859,12 @@ RSpec.describe Repository do describe '#refresh_method_caches' do it 'refreshes the caches of the given types' do expect(repository).to receive(:expire_method_caches) - .with(%i(readme_path license_blob license_key license)) + .with(%i(readme_path license_blob license_licensee license_gitaly)) expect(repository).to receive(:readme_path) expect(repository).to receive(:license_blob) - expect(repository).to receive(:license_key) - expect(repository).to receive(:license) + expect(repository).to receive(:license_licensee) + expect(repository).to receive(:license_gitaly) repository.refresh_method_caches(%i(readme license)) end diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb index 7ff19b1b770..832deee6186 100644 --- a/spec/presenters/project_presenter_spec.rb +++ b/spec/presenters/project_presenter_spec.rb @@ -10,13 +10,15 @@ RSpec.describe ProjectPresenter do describe '#license_short_name' do context 'when project.repository has a license_key' do it 'returns the nickname of the license if present' do - allow(project.repository).to receive(:license_key).and_return('agpl-3.0') + allow(project.repository).to receive(:license).and_return( + ::Gitlab::Git::DeclaredLicense.new(name: 'foo', nickname: 'GNU AGPLv3')) expect(presenter.license_short_name).to eq('GNU AGPLv3') end it 'returns the name of the license if nickname is not present' do - allow(project.repository).to receive(:license_key).and_return('mit') + allow(project.repository).to receive(:license).and_return( + ::Gitlab::Git::DeclaredLicense.new(name: 'MIT License')) expect(presenter.license_short_name).to eq('MIT License') end @@ -24,7 +26,7 @@ RSpec.describe ProjectPresenter do context 'when project.repository has no license_key but a license_blob' do it 'returns LICENSE' do - allow(project.repository).to receive(:license_key).and_return(nil) + allow(project.repository).to receive(:license).and_return(nil) expect(presenter.license_short_name).to eq('LICENSE') end diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb index dd7d32f3565..f5c73846173 100644 --- a/spec/requests/api/issues/issues_spec.rb +++ b/spec/requests/api/issues/issues_spec.rb @@ -1164,6 +1164,21 @@ RSpec.describe API::Issues do expect(json_response['title']).to eq('new issue') expect(json_response['issue_type']).to eq('issue') end + + context 'when issue create service returns an unrecoverable error' do + before do + allow_next_instance_of(Issues::CreateService) do |create_service| + allow(create_service).to receive(:execute).and_return(ServiceResponse.error(message: 'some error', http_status: 403)) + end + end + + it 'returns and error message and status code from the service' do + post api("/projects/#{project.id}/issues", user), params: { title: 'new issue' } + + expect(response).to have_gitlab_http_status(:forbidden) + expect(json_response['message']).to eq('some error') + end + end end describe 'PUT /projects/:id/issues/:issue_iid' do diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 7ad1ce0ede9..4ffc6055a23 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -2516,7 +2516,7 @@ RSpec.describe API::Projects do 'name' => project.repository.license.name, 'nickname' => project.repository.license.nickname, 'html_url' => project.repository.license.url, - 'source_url' => project.repository.license.meta['source'] + 'source_url' => nil }) end diff --git a/spec/services/alert_management/create_alert_issue_service_spec.rb b/spec/services/alert_management/create_alert_issue_service_spec.rb index 083e5b8c6f1..fc2bd9e90a6 100644 --- a/spec/services/alert_management/create_alert_issue_service_spec.rb +++ b/spec/services/alert_management/create_alert_issue_service_spec.rb @@ -161,7 +161,7 @@ RSpec.describe AlertManagement::CreateAlertIssueService do it 'has an unsuccessful status' do expect(execute).to be_error - expect(execute.message).to eq("Title can't be blank") + expect(execute.errors).to contain_exactly("Title can't be blank") end end @@ -170,7 +170,7 @@ RSpec.describe AlertManagement::CreateAlertIssueService do it 'responds with error' do expect(execute).to be_error - expect(execute.message).to eq('Hosts hosts array is over 255 chars') + expect(execute.errors).to contain_exactly('Hosts hosts array is over 255 chars') end end diff --git a/spec/services/boards/issues/create_service_spec.rb b/spec/services/boards/issues/create_service_spec.rb index 9a6b48c13bf..c4f1eb093dc 100644 --- a/spec/services/boards/issues/create_service_spec.rb +++ b/spec/services/boards/issues/create_service_spec.rb @@ -29,9 +29,10 @@ RSpec.describe Boards::Issues::CreateService do end it 'adds the label of the list to the issue' do - issue = service.execute + result = service.execute - expect(issue.labels).to eq [label] + expect(result).to be_success + expect(result[:issue].labels).to contain_exactly(label) end end end diff --git a/spec/services/incident_management/incidents/create_service_spec.rb b/spec/services/incident_management/incidents/create_service_spec.rb index ac44bc4608c..851b21e1227 100644 --- a/spec/services/incident_management/incidents/create_service_spec.rb +++ b/spec/services/incident_management/incidents/create_service_spec.rb @@ -77,7 +77,7 @@ RSpec.describe IncidentManagement::Incidents::CreateService do it 'responds with errors' do expect(create_incident).to be_error - expect(create_incident.message).to eq("Title can't be blank") + expect(create_incident.errors).to contain_exactly("Title can't be blank") end it 'result payload contains an Issue object' do @@ -98,7 +98,7 @@ RSpec.describe IncidentManagement::Incidents::CreateService do it 'responds with errors' do expect(create_incident).to be_error - expect(create_incident.message).to eq('Hosts hosts array is over 255 chars') + expect(create_incident.errors).to contain_exactly('Hosts hosts array is over 255 chars') end end end diff --git a/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb b/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb index fb536df5d17..572b1a20166 100644 --- a/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb +++ b/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb @@ -63,7 +63,7 @@ RSpec.describe IncidentManagement::PagerDuty::CreateIncidentIssueService do it 'responds with error' do expect(execute).to be_error - expect(execute.message).to eq("Title can't be blank") + expect(execute.errors).to contain_exactly("Title can't be blank") end end end diff --git a/spec/services/issues/clone_service_spec.rb b/spec/services/issues/clone_service_spec.rb index 435488b7f66..67f32b85350 100644 --- a/spec/services/issues/clone_service_spec.rb +++ b/spec/services/issues/clone_service_spec.rb @@ -36,6 +36,21 @@ RSpec.describe Issues::CloneService do context 'issue movable' do include_context 'user can clone issue' + context 'when issue creation fails' do + before do + allow_next_instance_of(Issues::CreateService) do |create_service| + allow(create_service).to receive(:execute).and_return(ServiceResponse.error(message: 'some error')) + end + end + + it 'raises a clone error' do + expect { clone_service.execute(old_issue, new_project) }.to raise_error( + Issues::CloneService::CloneError, + 'some error' + ) + end + end + context 'generic issue' do let!(:new_issue) { clone_service.execute(old_issue, new_project, with_notes: with_notes) } diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb index 4a84862b9d5..b2b7de338da 100644 --- a/spec/services/issues/create_service_spec.rb +++ b/spec/services/issues/create_service_spec.rb @@ -23,12 +23,28 @@ RSpec.describe Issues::CreateService do let_it_be(:assignee) { create(:user) } let_it_be(:milestone) { create(:milestone, project: project) } - let(:issue) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute } + let(:result) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute } + let(:issue) { result[:issue] } before do stub_spam_services end + context 'when params are invalid' do + let(:opts) { { title: '' } } + + before_all do + project.add_guest(user) + project.add_guest(assignee) + end + + it 'returns an error service response' do + expect(result).to be_error + expect(result.errors).to include("Title can't be blank") + expect(issue).not_to be_persisted + end + end + context 'when params are valid' do let_it_be(:labels) { create_pair(:label, project: project) } @@ -58,6 +74,7 @@ RSpec.describe Issues::CreateService do it 'creates the issue with the given params' do expect(Issuable::CommonSystemNotesService).to receive_message_chain(:new, :execute) + expect(result).to be_success expect(issue).to be_persisted expect(issue).to be_a(::Issue) expect(issue.title).to eq('Awesome issue') @@ -76,12 +93,13 @@ RSpec.describe Issues::CreateService do end context 'when a build_service is provided' do - let(:issue) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params, build_service: build_service).execute } + let(:result) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params, build_service: build_service).execute } let(:issue_from_builder) { WorkItem.new(project: project, title: 'Issue from builder') } let(:build_service) { double(:build_service, execute: issue_from_builder) } it 'uses the provided service to build the issue' do + expect(result).to be_success expect(issue).to be_persisted expect(issue).to be_a(WorkItem) end @@ -106,6 +124,7 @@ RSpec.describe Issues::CreateService do end it 'sets the correct relative position' do + expect(result).to be_success expect(issue).to be_persisted expect(issue.relative_position).to be_present expect(issue.relative_position).to be_between(issue_before.relative_position, issue_after.relative_position) @@ -183,8 +202,10 @@ RSpec.describe Issues::CreateService do let_it_be(:non_member) { create(:user) } it 'filters out params that cannot be set without the :set_issue_metadata permission' do - issue = described_class.new(project: project, current_user: non_member, params: opts, spam_params: spam_params).execute + result = described_class.new(project: project, current_user: non_member, params: opts, spam_params: spam_params).execute + issue = result[:issue] + expect(result).to be_success expect(issue).to be_persisted expect(issue.title).to eq('Awesome issue') expect(issue.description).to eq('please fix') @@ -195,8 +216,10 @@ RSpec.describe Issues::CreateService do end it 'can create confidential issues' do - issue = described_class.new(project: project, current_user: non_member, params: { confidential: true }, spam_params: spam_params).execute + result = described_class.new(project: project, current_user: non_member, params: opts.merge(confidential: true), spam_params: spam_params).execute + issue = result[:issue] + expect(result).to be_success expect(issue.confidential).to be_truthy end end @@ -391,16 +414,20 @@ RSpec.describe Issues::CreateService do it 'removes assignee when user id is invalid' do opts = { title: 'Title', description: 'Description', assignee_ids: [-1] } - issue = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute + result = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute + issue = result[:issue] + expect(result).to be_success expect(issue.assignees).to be_empty end it 'removes assignee when user id is 0' do opts = { title: 'Title', description: 'Description', assignee_ids: [0] } - issue = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute + result = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute + issue = result[:issue] + expect(result).to be_success expect(issue.assignees).to be_empty end @@ -408,8 +435,10 @@ RSpec.describe Issues::CreateService do project.add_maintainer(assignee) opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] } - issue = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute + result = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute + issue = result[:issue] + expect(result).to be_success expect(issue.assignees).to eq([assignee]) end @@ -426,8 +455,10 @@ RSpec.describe Issues::CreateService do project.update!(visibility_level: level) opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] } - issue = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute + result = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute + issue = result[:issue] + expect(result).to be_success expect(issue.assignees).to be_empty end end @@ -436,7 +467,7 @@ RSpec.describe Issues::CreateService do end it_behaves_like 'issuable record that supports quick actions' do - let(:issuable) { described_class.new(project: project, current_user: user, params: params, spam_params: spam_params).execute } + let(:issuable) { described_class.new(project: project, current_user: user, params: params, spam_params: spam_params).execute[:issue] } end context 'Quick actions' do @@ -459,6 +490,7 @@ RSpec.describe Issues::CreateService do end it 'assigns, sets milestone, and sets contact to issuable from command' do + expect(result).to be_success expect(issue).to be_persisted expect(issue.assignees).to eq([assignee]) expect(issue.milestone).to eq(milestone) @@ -480,6 +512,8 @@ RSpec.describe Issues::CreateService do context 'with permission' do it 'assigns contact to issue' do group.add_reporter(user) + + expect(result).to be_success expect(issue).to be_persisted expect(issue.issue_customer_relations_contacts.last.contact).to eq(contact) end @@ -488,6 +522,8 @@ RSpec.describe Issues::CreateService do context 'without permission' do it 'does not assign contact to issue' do group.add_guest(user) + + expect(result).to be_success expect(issue).to be_persisted expect(issue.issue_customer_relations_contacts).to be_empty end @@ -522,6 +558,7 @@ RSpec.describe Issues::CreateService do end it 'can apply labels' do + expect(result).to be_success expect(issue).to be_persisted expect(issue.labels).to eq([label]) end @@ -556,25 +593,32 @@ RSpec.describe Issues::CreateService do end it 'sets default title and description values if not provided' do - issue = described_class.new( + result = described_class.new( project: project, current_user: user, params: opts, spam_params: spam_params ).execute + issue = result[:issue] + expect(result).to be_success expect(issue).to be_persisted expect(issue.title).to eq("Follow-up from \"#{merge_request.title}\"") expect(issue.description).to include("The following discussion from #{merge_request.to_reference} should be addressed") end it 'takes params from the request over the default values' do - issue = described_class.new(project: project, current_user: user, - params: opts.merge( - description: 'Custom issue description', - title: 'My new issue' - ), - spam_params: spam_params).execute + result = described_class.new( + project: project, + current_user: user, + params: opts.merge( + description: 'Custom issue description', + title: 'My new issue' + ), + spam_params: spam_params + ).execute + issue = result[:issue] + expect(result).to be_success expect(issue).to be_persisted expect(issue.description).to eq('Custom issue description') expect(issue.title).to eq('My new issue') @@ -600,25 +644,32 @@ RSpec.describe Issues::CreateService do end it 'sets default title and description values if not provided' do - issue = described_class.new( + result = described_class.new( project: project, current_user: user, params: opts, spam_params: spam_params ).execute + issue = result[:issue] + expect(result).to be_success expect(issue).to be_persisted expect(issue.title).to eq("Follow-up from \"#{merge_request.title}\"") expect(issue.description).to include("The following discussion from #{merge_request.to_reference} should be addressed") end it 'takes params from the request over the default values' do - issue = described_class.new(project: project, current_user: user, - params: opts.merge( - description: 'Custom issue description', - title: 'My new issue' - ), - spam_params: spam_params).execute + result = described_class.new( + project: project, + current_user: user, + params: opts.merge( + description: 'Custom issue description', + title: 'My new issue' + ), + spam_params: spam_params + ).execute + issue = result[:issue] + expect(result).to be_success expect(issue).to be_persisted expect(issue.description).to eq('Custom issue description') expect(issue.title).to eq('My new issue') @@ -635,6 +686,7 @@ RSpec.describe Issues::CreateService do it 'ignores related issue if not accessible' do expect { issue }.not_to change { IssueLink.count } + expect(result).to be_success expect(issue).to be_persisted end @@ -645,6 +697,7 @@ RSpec.describe Issues::CreateService do it 'adds a link to the issue' do expect { issue }.to change { IssueLink.count }.by(1) + expect(result).to be_success expect(issue).to be_persisted expect(issue.related_issues(user)).to eq([related_issue]) end diff --git a/spec/services/issues/move_service_spec.rb b/spec/services/issues/move_service_spec.rb index 863df810d01..23180f75eb3 100644 --- a/spec/services/issues/move_service_spec.rb +++ b/spec/services/issues/move_service_spec.rb @@ -35,6 +35,23 @@ RSpec.describe Issues::MoveService do let!(:new_issue) { move_service.execute(old_issue, new_project) } end + context 'when issue creation fails' do + include_context 'user can move issue' + + before do + allow_next_instance_of(Issues::CreateService) do |create_service| + allow(create_service).to receive(:execute).and_return(ServiceResponse.error(message: 'some error')) + end + end + + it 'raises a move error' do + expect { move_service.execute(old_issue, new_project) }.to raise_error( + Issues::MoveService::MoveError, + 'some error' + ) + end + end + context 'issue movable' do include_context 'user can move issue' diff --git a/spec/support/shared_examples/models/chat_integration_shared_examples.rb b/spec/support/shared_examples/models/chat_integration_shared_examples.rb index 6cfeeabc952..769011c1675 100644 --- a/spec/support/shared_examples/models/chat_integration_shared_examples.rb +++ b/spec/support/shared_examples/models/chat_integration_shared_examples.rb @@ -166,7 +166,7 @@ RSpec.shared_examples "chat integration" do |integration_name| let(:opts) { { title: "Awesome issue", description: "please fix" } } let(:sample_data) do service = Issues::CreateService.new(project: project, current_user: user, params: opts, spam_params: nil) - issue = service.execute + issue = service.execute[:issue] service.hook_data(issue, "open") end |