summaryrefslogtreecommitdiff
path: root/spec/services/integrations/slack_interactions/incident_management/incident_modal_submit_service_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/services/integrations/slack_interactions/incident_management/incident_modal_submit_service_spec.rb')
-rw-r--r--spec/services/integrations/slack_interactions/incident_management/incident_modal_submit_service_spec.rb296
1 files changed, 296 insertions, 0 deletions
diff --git a/spec/services/integrations/slack_interactions/incident_management/incident_modal_submit_service_spec.rb b/spec/services/integrations/slack_interactions/incident_management/incident_modal_submit_service_spec.rb
new file mode 100644
index 00000000000..adaeadaa997
--- /dev/null
+++ b/spec/services/integrations/slack_interactions/incident_management/incident_modal_submit_service_spec.rb
@@ -0,0 +1,296 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::SlackInteractions::IncidentManagement::IncidentModalSubmitService,
+ feature_category: :incident_management do
+ include Gitlab::Routing
+
+ describe '#execute' do
+ let_it_be(:slack_installation) { create(:slack_integration) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:api_url) { 'https://api.slack.com/id/1234' }
+
+ let_it_be(:chat_name) do
+ create(:chat_name,
+ user: user,
+ team_id: slack_installation.team_id,
+ chat_id: slack_installation.user_id
+ )
+ end
+
+ # Setting below params as they are optional, have added values wherever required in specs
+ let(:zoom_link) { '' }
+ let(:severity) { {} }
+ let(:status) { '' }
+ let(:assignee_id) { nil }
+ let(:selected_label_ids) { [] }
+ let(:label_ids) { { selected_options: selected_label_ids } }
+ let(:confidential_selected_options) { [] }
+ let(:confidential) { { selected_options: confidential_selected_options } }
+ let(:title) { 'Incident title' }
+
+ let(:zoom) do
+ {
+ link: {
+ value: zoom_link
+ }
+ }
+ end
+
+ let(:params) do
+ {
+ team: {
+ id: slack_installation.team_id
+ },
+ user: {
+ id: slack_installation.user_id
+ },
+ view: {
+ private_metadata: api_url,
+ state: {
+ values: {
+ title_input: {
+ title: {
+ value: title
+ }
+ },
+ incident_description: {
+ description: {
+ value: 'Incident description'
+ }
+ },
+ project_and_severity_selector: {
+ incident_management_project: {
+ selected_option: {
+ value: project.id.to_s
+ }
+ },
+ severity: severity
+ },
+ confidentiality: {
+ confidential: confidential
+ },
+ zoom: zoom,
+ status_and_assignee_selector: {
+ status: {
+ selected_option: {
+ value: status
+ }
+ },
+ assignee: {
+ selected_option: {
+ value: assignee_id
+ }
+ }
+ },
+ label_selector: {
+ labels: label_ids
+ }
+ }
+ }
+ }
+ }
+ end
+
+ subject(:execute_service) { described_class.new(params).execute }
+
+ shared_examples 'error in creation' do |error_message|
+ it 'returns error and raises exception' do
+ expect(::Gitlab::ErrorTracking).to receive(:track_exception)
+ .with(
+ described_class::IssueCreateError.new(error_message),
+ {
+ slack_workspace_id: slack_installation.team_id,
+ slack_user_id: slack_installation.user_id
+ }
+ )
+
+ expect(Gitlab::HTTP).to receive(:post)
+ .with(
+ api_url,
+ body: Gitlab::Json.dump(
+ {
+ replace_original: 'true',
+ text: 'There was a problem creating the incident. Please try again.'
+ }
+ ),
+ headers: { 'Content-Type' => 'application/json' }
+ )
+
+ response = execute_service
+
+ expect(response).to be_error
+ expect(response.message).to eq(error_message)
+ end
+ end
+
+ context 'when user has permissions to create incidents' do
+ let(:api_response) { '{"ok":true}' }
+
+ before do
+ project.add_developer(user)
+ stub_request(:post, api_url)
+ .to_return(body: api_response, headers: { 'Content-Type' => 'application/json' })
+ end
+
+ context 'with markup string in title' do
+ let(:title) { '<a href="url">incident title</a>' }
+ let(:incident) { create(:incident, title: title, project: project) }
+
+ before do
+ allow_next_instance_of(Issues::CreateService) do |service|
+ allow(service).to receive(:execute).and_return(
+ ServiceResponse.success(payload: { issue: incident, error: [] })
+ )
+ end
+ end
+
+ it 'strips the markup and saves sends the title' do
+ expect(Gitlab::HTTP).to receive(:post)
+ .with(
+ api_url,
+ body: Gitlab::Json.dump(
+ {
+ replace_original: 'true',
+ text: "New incident has been created: " \
+ "<#{issue_url(incident)}|#{incident.to_reference} - a href=\"url\"incident title/a>. "
+ }
+ ),
+ headers: { 'Content-Type' => 'application/json' }
+ ).and_return(api_response)
+
+ execute_service
+ end
+ end
+
+ context 'with non-optional params' do
+ it 'creates incident' do
+ response = execute_service
+ incident = response[:incident]
+
+ expect(response).to be_success
+ expect(incident).not_to be_nil
+ expect(incident.description).to eq('Incident description')
+ expect(incident.author).to eq(user)
+ expect(incident.severity).to eq('unknown')
+ expect(incident.confidential).to be_falsey
+ expect(incident.escalation_status).to be_triggered
+ end
+
+ it 'sends incident link to slack' do
+ execute_service
+
+ expect(WebMock).to have_requested(:post, api_url)
+ end
+ end
+
+ context 'with zoom_link' do
+ let(:zoom_link) { 'https://gitlab.zoom.us/j/1234' }
+
+ it 'sets zoom link as quick action' do
+ incident = execute_service[:incident]
+ zoom_meeting = ZoomMeeting.find_by_issue_id(incident.id)
+
+ expect(incident.description).to eq("Incident description")
+ expect(zoom_meeting.url).to eq(zoom_link)
+ end
+ end
+
+ context 'with confidential and severity' do
+ let(:confidential_selected_options) { ['confidential'] }
+ let(:severity) do
+ {
+ selected_option: {
+ value: 'high'
+ }
+ }
+ end
+
+ it 'sets confidential and severity' do
+ incident = execute_service[:incident]
+
+ expect(incident.confidential).to be_truthy
+ expect(incident.severity).to eq('high')
+ end
+ end
+
+ context 'with incident status' do
+ let(:status) { 'resolved' }
+
+ it 'sets the incident status' do
+ incident = execute_service[:incident]
+
+ expect(incident.escalation_status).to be_resolved
+ end
+ end
+
+ context 'with assignee id' do
+ let(:assignee_id) { user.id.to_s }
+
+ it 'assigns the incident to user' do
+ incident = execute_service[:incident]
+
+ expect(incident.assignees).to contain_exactly(user)
+ end
+
+ context 'when user is not a member of the project' do
+ let(:assignee_id) { create(:user).id.to_s }
+
+ it 'does not assign the user' do
+ incident = execute_service[:incident]
+
+ expect(incident.assignees).to be_empty
+ end
+ end
+ end
+
+ context 'with label ids' do
+ let_it_be(:project_label1) { create(:label, project: project, title: 'Label 1') }
+ let_it_be(:project_label2) { create(:label, project: project, title: 'Label 2') }
+
+ let(:selected_label_ids) do
+ [
+ { value: project_label1.id.to_s },
+ { value: project_label2.id.to_s }
+ ]
+ end
+
+ it 'assigns the label to the incident' do
+ incident = execute_service[:incident]
+
+ expect(incident.labels).to contain_exactly(project_label1, project_label2)
+ end
+ end
+
+ context 'when response is not ok' do
+ let(:api_response) { '{"ok":false}' }
+
+ it 'returns error response and tracks the exception' do
+ expect(::Gitlab::ErrorTracking).to receive(:track_exception)
+ .with(
+ StandardError.new('Something went wrong when sending the incident link to Slack.'),
+ {
+ response: { 'ok' => false },
+ slack_workspace_id: slack_installation.team_id,
+ slack_user_id: slack_installation.user_id
+ }
+ )
+
+ execute_service
+ end
+ end
+
+ context 'when incident creation fails' do
+ let(:title) { '' }
+
+ it_behaves_like 'error in creation', "Title can't be blank"
+ end
+ end
+
+ context 'when user does not have permission to create incidents' do
+ it_behaves_like 'error in creation', 'Operation not allowed'
+ end
+ end
+end