summaryrefslogtreecommitdiff
path: root/spec/controllers/projects/alerting/notifications_controller_spec.rb
blob: fe0c4ce00bf21053bce4f8b2bab3a8ebd43ad30c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Projects::Alerting::NotificationsController do
  let_it_be(:project) { create(:project) }
  let_it_be(:environment) { create(:environment, project: project) }

  let(:params) { project_params }

  describe 'POST #create' do
    around do |example|
      ForgeryProtection.with_forgery_protection { example.run }
    end

    shared_examples 'process alert payload' do |notify_service_class|
      let(:service_response) { ServiceResponse.success }
      let(:notify_service) { instance_double(notify_service_class, execute: service_response) }

      before do
        allow(notify_service_class).to receive(:new).and_return(notify_service)
      end

      def make_request
        post :create, params: params, body: payload.to_json, as: :json
      end

      context 'when notification service succeeds' do
        let(:permitted_params) { ActionController::Parameters.new(payload).permit! }

        it 'responds with ok' do
          make_request

          expect(response).to have_gitlab_http_status(:ok)
        end

        it 'does not pass excluded parameters to the notify service' do
          make_request

          expect(notify_service_class)
            .to have_received(:new)
            .with(project, permitted_params)
        end
      end

      context 'when notification service fails' do
        let(:service_response) { ServiceResponse.error(message: 'Unauthorized', http_status: :unauthorized) }

        it 'responds with the service response' do
          make_request

          expect(response).to have_gitlab_http_status(:unauthorized)
        end
      end

      context 'bearer token' do
        context 'when set' do
          context 'when extractable' do
            before do
              request.headers['HTTP_AUTHORIZATION'] = 'Bearer some token'
            end

            it 'extracts bearer token' do
              expect(notify_service).to receive(:execute).with('some token', nil)

              make_request
            end

            context 'with a corresponding integration' do
              context 'with integration parameters specified' do
                let_it_be_with_reload(:integration) { create(:alert_management_http_integration, project: project) }

                let(:params) { project_params(endpoint_identifier: integration.endpoint_identifier, name: integration.name) }

                context 'the integration is active' do
                  it 'extracts and finds the integration' do
                    expect(notify_service).to receive(:execute).with('some token', integration)

                    make_request
                  end
                end

                context 'when the integration is inactive' do
                  before do
                    integration.update!(active: false)
                  end

                  it 'does not find an integration' do
                    expect(notify_service).to receive(:execute).with('some token', nil)

                    make_request
                  end
                end
              end

              context 'without integration parameters specified' do
                let_it_be(:integration) { create(:alert_management_http_integration, :legacy, project: project) }

                it 'extracts and finds the legacy integration' do
                  expect(notify_service).to receive(:execute).with('some token', integration)

                  make_request
                end
              end
            end
          end

          context 'when inextractable' do
            it 'passes nil for a non-bearer token' do
              request.headers['HTTP_AUTHORIZATION'] = 'some token'

              expect(notify_service).to receive(:execute).with(nil, nil)

              make_request
            end
          end
        end

        context 'when missing' do
          it 'passes nil' do
            expect(notify_service).to receive(:execute).with(nil, nil)

            make_request
          end
        end
      end
    end

    context 'generic alert payload' do
      it_behaves_like 'process alert payload', Projects::Alerting::NotifyService do
        let(:payload) { { title: 'Alert title' } }
      end
    end

    context 'Prometheus alert payload' do
      include PrometheusHelpers

      it_behaves_like 'process alert payload', Projects::Prometheus::Alerts::NotifyService do
        let(:payload) { prometheus_alert_payload }
      end
    end
  end

  private

  def project_params(opts = {})
    opts.reverse_merge(namespace_id: project.namespace, project_id: project)
  end
end