diff options
Diffstat (limited to 'spec/lib/gitlab/email/handler')
5 files changed, 381 insertions, 4 deletions
diff --git a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb index 7833b9f387d..ee2173a9c8d 100644 --- a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Gitlab::Email::Handler::CreateIssueHandler do +RSpec.describe Gitlab::Email::Handler::CreateIssueHandler do include_context :email_shared_context it_behaves_like :reply_processing_shared_examples diff --git a/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb b/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb index 9f5413f9607..75d5fc040cb 100644 --- a/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Gitlab::Email::Handler::CreateMergeRequestHandler do +RSpec.describe Gitlab::Email::Handler::CreateMergeRequestHandler do include_context :email_shared_context it_behaves_like :reply_processing_shared_examples diff --git a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb index af963e1b695..e5598bbd10f 100644 --- a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Gitlab::Email::Handler::CreateNoteHandler do +RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do include_context :email_shared_context it_behaves_like :reply_processing_shared_examples @@ -242,4 +242,70 @@ describe Gitlab::Email::Handler::CreateNoteHandler do it_behaves_like 'a reply to existing comment' end + + context 'when the service desk' do + let(:project) { create(:project, :public, service_desk_enabled: true) } + let(:support_bot) { User.support_bot } + let(:noteable) { create(:issue, project: project, author: support_bot, title: 'service desk issue') } + let(:note) { create(:note, project: project, noteable: noteable) } + let(:email_raw) { fixture_file('emails/valid_reply_with_quick_actions.eml') } + + let!(:sent_notification) do + SentNotification.record_note(note, support_bot.id, mail_key) + end + + context 'is enabled' do + before do + allow(Gitlab::ServiceDesk).to receive(:enabled?).with(project: project).and_return(true) + project.project_feature.update!(issues_access_level: issues_access_level) + end + + context 'when issues are enabled for everyone' do + let(:issues_access_level) { ProjectFeature::ENABLED } + + it 'creates a comment' do + expect { receiver.execute }.to change { noteable.notes.count }.by(1) + end + + context 'when quick actions are present' do + it 'encloses quick actions with code span markdown' do + receiver.execute + noteable.reload + + note = Note.last + expect(note.note).to include("Jake out\n\n`/close`\n`/title test`") + expect(noteable.title).to eq('service desk issue') + expect(noteable).to be_opened + end + end + end + + context 'when issues are protected members only' do + let(:issues_access_level) { ProjectFeature::PRIVATE } + + it 'creates a comment' do + expect { receiver.execute }.to change { noteable.notes.count }.by(1) + end + end + + context 'when issues are disabled' do + let(:issues_access_level) { ProjectFeature::DISABLED } + + it 'does not create a comment' do + expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotAuthorizedError) + end + end + end + + context 'is disabled' do + before do + allow(Gitlab::ServiceDesk).to receive(:enabled?).and_return(false) + allow(Gitlab::ServiceDesk).to receive(:enabled?).with(project: project).and_return(false) + end + + it 'does not create a comment' do + expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound) + end + end + end end diff --git a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb new file mode 100644 index 00000000000..a38fe2c51ca --- /dev/null +++ b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb @@ -0,0 +1,311 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do + include_context :email_shared_context + + before do + stub_incoming_email_setting(enabled: true, address: "incoming+%{key}@appmail.adventuretime.ooo") + stub_config_setting(host: 'localhost') + end + + let(:email_raw) { email_fixture('emails/service_desk.eml') } + let_it_be(:namespace) { create(:namespace, name: "email") } + let(:expected_description) do + "Service desk stuff!\n\n```\na = b\n```\n\n`/label ~label1`\n`/assign @user1`\n`/close`\n![image](uploads/image.png)" + end + + context 'service desk is enabled for the project' do + let_it_be(:project) { create(:project, :repository, :public, namespace: namespace, path: 'test', service_desk_enabled: true) } + + before do + allow(Gitlab::ServiceDesk).to receive(:supported?).and_return(true) + end + + shared_examples 'a new issue request' do + before do + setup_attachment + end + + it 'creates a new issue' do + expect { receiver.execute }.to change { Issue.count }.by(1) + + new_issue = Issue.last + + expect(new_issue.author).to eql(User.support_bot) + expect(new_issue.confidential?).to be true + expect(new_issue.all_references.all).to be_empty + expect(new_issue.title).to eq("Service Desk (from jake@adventuretime.ooo): The message subject! @all") + expect(new_issue.description).to eq(expected_description.strip) + end + + it 'sends thank you email' do + expect { receiver.execute }.to have_enqueued_job.on_queue('mailers') + end + end + + context 'when everything is fine' do + it_behaves_like 'a new issue request' + + context 'with legacy incoming email address' do + let(:email_raw) { fixture_file('emails/service_desk_legacy.eml') } + + it_behaves_like 'a new issue request' + end + + context 'when using issue templates' do + let_it_be(:user) { create(:user) } + + before do + setup_attachment + end + + context 'and template is present' do + let_it_be(:settings) { create(:service_desk_setting, project: project) } + + def set_template_file(file_name, content) + file_path = ".gitlab/issue_templates/#{file_name}.md" + project.repository.create_file(user, file_path, content, message: 'message', branch_name: 'master') + settings.update!(issue_template_key: file_name) + end + + it 'appends template text to issue description' do + set_template_file('service_desk', 'text from template') + + receiver.execute + + issue_description = Issue.last.description + expect(issue_description).to include(expected_description) + expect(issue_description.lines.last).to eq('text from template') + end + + context 'when quick actions are present' do + let(:label) { create(:label, project: project, title: 'label1') } + let(:milestone) { create(:milestone, project: project) } + let!(:user) { create(:user, username: 'user1') } + + before do + project.add_developer(user) + end + + it 'applies quick action commands present on templates' do + file_content = %(Text from template \n/label ~#{label.title} \n/milestone %"#{milestone.name}"") + set_template_file('with_slash_commands', file_content) + + receiver.execute + + issue = Issue.last + expect(issue.description).to include('Text from template') + expect(issue.label_ids).to include(label.id) + expect(issue.milestone).to eq(milestone) + end + + it 'redacts quick actions present on user email body' do + set_template_file('service_desk1', 'text from template') + + receiver.execute + + issue = Issue.last + expect(issue).to be_opened + expect(issue.description).to include('`/label ~label1`') + expect(issue.description).to include('`/assign @user1`') + expect(issue.description).to include('`/close`') + expect(issue.assignees).to be_empty + expect(issue.milestone).to be_nil + end + end + end + + context 'and template cannot be found' do + before do + service = ServiceDeskSetting.new(project_id: project.id, issue_template_key: 'unknown') + service.save!(validate: false) + end + + it 'does not append template text to issue description' do + receiver.execute + + new_issue = Issue.last + + expect(new_issue.description).to eq(expected_description.strip) + end + + it 'creates support bot note on issue' do + receiver.execute + + note = Note.last + + expect(note.note).to include("WARNING: The template file unknown.md used for service desk issues is empty or could not be found.") + expect(note.author).to eq(User.support_bot) + end + + it 'does not send warning note email' do + ActionMailer::Base.deliveries = [] + + perform_enqueued_jobs do + expect { receiver.execute }.to change { ActionMailer::Base.deliveries.size }.by(1) + end + + # Only sends created issue email + expect(ActionMailer::Base.deliveries.last.text_part.body).to include("Thank you for your support request!") + end + end + end + + context 'when using service desk key' do + let_it_be(:service_desk_settings) { create(:service_desk_setting, project: project, project_key: 'mykey') } + let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml') } + let(:receiver) { Gitlab::Email::ServiceDeskReceiver.new(email_raw) } + + before do + stub_service_desk_email_setting(enabled: true, address: 'support+%{key}@example.com') + end + + it_behaves_like 'a new issue request' + + context 'when there is no project with the key' do + let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml', key: 'some_key') } + + it 'bounces the email' do + expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound) + end + end + + context 'when the project slug does not match' do + let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml', slug: 'some-slug') } + + it 'bounces the email' do + expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound) + end + end + + context 'when service_desk_custom_address feature is disabled' do + before do + stub_feature_flags(service_desk_custom_address: false) + end + + it 'bounces the email' do + expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound) + end + end + end + end + + describe '#can_handle?' do + let(:mail) { Mail::Message.new(email_raw) } + + it 'handles the new email key format' do + handler = described_class.new(mail, "h5bp-html5-boilerplate-#{project.project_id}-issue-") + + expect(handler.instance_variable_get(:@project_id).to_i).to eq project.project_id + expect(handler.can_handle?).to be_truthy + end + + it 'handles the legacy email key format' do + handler = described_class.new(mail, "h5bp/html5-boilerplate") + + expect(handler.instance_variable_get(:@project_path)).to eq 'h5bp/html5-boilerplate' + expect(handler.can_handle?).to be_truthy + end + + it "doesn't handle invalid email key" do + handler = described_class.new(mail, "h5bp-html5-boilerplate-invalid") + + expect(handler.can_handle?).to be_falsey + end + end + + context 'when there is no from address' do + before do + allow_next_instance_of(described_class) do |instance| + allow(instance).to receive(:from_address).and_return(nil) + end + end + + it "creates a new issue" do + expect { receiver.execute }.to change { Issue.count }.by(1) + end + + it 'does not send thank you email' do + expect { receiver.execute }.not_to have_enqueued_job.on_queue('mailers') + end + end + + context 'when there is a sender address and a from address' do + let(:email_raw) { email_fixture('emails/service_desk_sender_and_from.eml') } + + it 'prefers the from address' do + setup_attachment + + expect { receiver.execute }.to change { Issue.count }.by(1) + + new_issue = Issue.last + + expect(new_issue.service_desk_reply_to).to eq('finn@adventuretime.ooo') + end + end + + context 'when service desk is not enabled for project' do + before do + allow(Gitlab::ServiceDesk).to receive(:enabled?).and_return(false) + end + + it 'does not create an issue' do + expect { receiver.execute rescue nil }.not_to change { Issue.count } + end + + it 'does not send thank you email' do + expect { receiver.execute rescue nil }.not_to have_enqueued_job.on_queue('mailers') + end + end + + context 'when the email is forwarded through an alias' do + let(:email_raw) { email_fixture('emails/service_desk_forwarded.eml') } + + it_behaves_like 'a new issue request' + end + + context 'when the email is forwarded' do + let(:email_raw) { email_fixture('emails/service_desk_forwarded_new_issue.eml') } + + it_behaves_like 'a new issue request' do + let(:expected_description) do + <<~EOF + Service desk stuff! + + ---------- Forwarded message --------- + From: Jake the Dog <jake@adventuretime.ooo> + To: <jake@adventuretime.ooo> + + + forwarded content + + ![image](uploads/image.png) + EOF + end + end + end + end + + context 'service desk is disabled for the project' do + let(:project) { create(:project, :public, namespace: namespace, path: 'test', service_desk_enabled: false) } + + it 'bounces the email' do + expect { receiver.execute }.to raise_error(Gitlab::Email::ProcessingError) + end + + it "doesn't create an issue" do + expect { receiver.execute rescue nil }.not_to change { Issue.count } + end + end + + def email_fixture(path) + fixture_file(path).gsub('project_id', project.project_id.to_s) + end + + def service_desk_fixture(path, slug: nil, key: 'mykey') + slug ||= project.full_path_slug.to_s + fixture_file(path).gsub('project_slug', slug).gsub('project_key', key) + end +end diff --git a/spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb b/spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb index dcddd00df59..13ad9ddd8ef 100644 --- a/spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Gitlab::Email::Handler::UnsubscribeHandler do +RSpec.describe Gitlab::Email::Handler::UnsubscribeHandler do include_context :email_shared_context before do |